Search Unity

Alpha area on round GUI button return click event

Discussion in 'Immediate Mode GUI (IMGUI)' started by besuser, Sep 25, 2008.

  1. besuser

    besuser

    Joined:
    Oct 9, 2007
    Posts:
    292
    I currently have a texture of a circle assigned to a GUI button. The button works fine, but I'm getting the mouse click when the user clicks on the transparent area of the button. I'd like to only get the mouse click event when the mouse is on the opaque area of the button. Is this possible?
     
  2. jeremyace

    jeremyace

    Joined:
    Oct 12, 2005
    Posts:
    1,661
    Not without a completely custom control. Click handling is based on the "bounding" rect of the control, so everything in the GUI system is actually rectangular as far as layout and input handling goes.

    -Jeremy
     
  3. Dougxing

    Dougxing

    Joined:
    Mar 13, 2008
    Posts:
    90
    You could get the screen coordinates of the mouse click, calculate where in your image the user clicked (if they clicked in your image), sample that pixel of the image, and then do whatever you need to do if it's not transparent.
    You can only sample pixels from images that are imported with a particular kind of compression. I'm afraid I can't remember which off the top of my head, though.
     
  4. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Non-compressed, actually (RGBA32, also works with other non-compressed formats like RGB24 and Alpha8), which is what you'd want to use for GUI graphics anyway. Nifty solution, though converting from "screen coords" to "where in my image is this" seems, offhand, like it would be somewhat tricky.

    --Eric
     
  5. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    I'd do something like this (WARNING: Untested code):
    Code (csharp):
    1. public Texture2D myCustomIcon, myCustomIconClicked;
    2.  
    3.  
    4.  
    5. /*
    6.     ...
    7.  */
    8.  
    9.  
    10.  
    11. public void OnGUI()
    12. {
    13.     if( AlphaButton( new Vector2( 100, 100 ), myCustomIcon, myCustomIconClicked ) )
    14.     {
    15.         Debug.Log( "Yarrr! Clicked!" );
    16.     }
    17. }
    18.  
    19.  
    20.  
    21. public static bool AlphaButton( Vector2 pos, Texture2D icon, Texture2D iconClicked )
    22. {
    23.     return AlphaButton( pos, icon, iconClicked, 0.5f );
    24. }
    25.  
    26.  
    27.  
    28. public static bool AlphaButton( Vector2 pos, Texture2D icon, Texture2D iconClicked, float alphaThreshold )
    29. {
    30.     Rect iconRect;
    31.     Vector2 relativeClick;
    32.    
    33.     iconRect = new Rect( pos.x, pos.y, icon.width, icon.height );
    34.    
    35.     if( Event.current.type == EventType.MouseDown  CheckRect( Event.current.mousePosition, iconRect ) )
    36.     {
    37.         relativeClick = new Vector2( Event.current.mousePosition.x - pos.x, Event.current.mousePosition.y - pos.y );
    38.        
    39.         if( icon.GetPixel( relativeClick.x, relativeClick.y ).a > alphaThreshold )
    40.         {
    41.             GUI.DrawTexture( iconRect, iconClicked );
    42.             return true;
    43.         }
    44.     }
    45.    
    46.     GUI.DrawTexture( iconRect, icon );
    47.     return false;
    48. }
    49.  
    50.  
    51.  
    52. public static bool CheckRect( Vector2 point, Rect rect )
    53. {
    54.     return  point.x >= rect.x  point.x <= rect.x + rect.width
    55.             point.y >= rect.y  point.y <= rect.y + rect.height;
    56. }
    Ok I got a bit carried away on that one. Hope it helps :wink:
     
  6. besuser

    besuser

    Joined:
    Oct 9, 2007
    Posts:
    292
    Thanks for the code Angry Ant. I thought the GUI in Unity would be smart enough to take the alpha channel into account. Apps like Flash, Dreamweaver, and Torque seemd to do this, so I thought it was the same in Unity. I'll try testing for the alpha myself and see if that'll work for me. Thanks all.
     
  7. hungrytom

    hungrytom

    Joined:
    Sep 23, 2009
    Posts:
    34
    AngryAnt - you're a legend. Took 5 mins to modify the example you gave and now I have a generic custom cursor CS script :D Happy days.

    Anyone who's looking for a custom cursor (particularly NooBees like myself.. just attach this as a script to an object in your scene and add two different textures for your normal onclick custom cursor.

    [DISCLAIMER: Modified from AngryAnt's code - I don't really know what I doing so this may not work...]

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class CustomCursor: MonoBehaviour {
    6.  
    7.     public delegate void OnCursorGUI();
    8.     private OnCursorGUI cursor;
    9.  
    10.     public Texture2D custom_cursor_on_click;
    11.     public Texture2D custom_cursor;
    12.  
    13.     public void Awake()
    14.     {
    15.        cursor = NormalCursor;
    16.     }
    17.  
    18.     public void OnGUI()
    19.     {
    20.        if(custom_cursor!=null)
    21.           cursor = MakeCustomCursor;
    22.        else
    23.            cursor = NormalCursor;
    24.        cursor();
    25.     }
    26.  
    27.     private void MakeCustomCursor()
    28.     {
    29.         float w,h;
    30.         Texture2D cursor_texture;
    31.         if( Input.GetMouseButton( 0 ) )
    32.         {
    33.             w = custom_cursor_on_click.width;
    34.             h = custom_cursor_on_click.height;
    35.             cursor_texture = custom_cursor_on_click;
    36.         }
    37.         else
    38.         {
    39.             w = custom_cursor.width;
    40.             h = custom_cursor.height;
    41.             cursor_texture = custom_cursor;
    42.         }
    43.         GUI.DrawTexture( new Rect( Event.current.mousePosition.x-(w/2), Event.current.mousePosition.y-(h/2), w, h), cursor_texture );
    44.         Screen.showCursor = false;
    45.     }
    46.  
    47.     private void NormalCursor()
    48.     {
    49.         Screen.showCursor = true;
    50.     }
    51.  
    52. }
    53.  
     
  8. wallfired

    wallfired

    Joined:
    Dec 26, 2009
    Posts:
    21
    Hello,

    Code (csharp):
    1.  
    2. public Texture2D myCustomIcon;
    3.     public Texture2D myCustomIconClicked;
    4.  
    5.  
    6. /*
    7.    ...
    8.  */
    9.  
    10.  
    11.  
    12. public void OnGUI()
    13. {
    14.    if( AlphaButton( new Vector2( 50 , 50), myCustomIcon, myCustomIconClicked ) )
    15.    {
    16.       Debug.Log( " Click Marica!" );
    17.    }
    18. }
    19.  
    20.  
    21.  
    22. public static bool AlphaButton( Vector2 pos, Texture2D icon, Texture2D iconClicked )
    23. {
    24.    return AlphaButton( pos, icon, iconClicked, 0.5f );
    25. }
    26.  
    27.  
    28.  
    29. public static bool AlphaButton( Vector2 pos, Texture2D icon, Texture2D iconClicked, float alphaThreshold )
    30. {
    31.    Rect iconRect;
    32.    Vector2 relativeClick;
    33.    
    34.    iconRect = new Rect( pos.x, pos.y, icon.width, icon.height );
    35.    
    36.    if( Event.current.type == EventType.MouseDown  CheckRect( Event.current.mousePosition, iconRect ) )
    37.    {
    38.       relativeClick = new Vector2( Event.current.mousePosition.x - pos.x, Event.current.mousePosition.y - pos.y );
    39.  
    40.       if (icon.GetPixel((int)relativeClick.x, (int)relativeClick.y).a > alphaThreshold)
    41.       {
    42.          GUI.DrawTexture( iconRect, iconClicked );
    43.          return true;
    44.       }
    45.    }
    46.    
    47.    GUI.DrawTexture( iconRect, icon );
    48.    return false;
    49. }
    50.  
    51.  
    52.  
    53. public static bool CheckRect( Vector2 point, Rect rect )
    54. {
    55.    return    point.x >= rect.x  point.x <= rect.x + rect.width
    56.          point.y >= rect.y  point.y <= rect.y + rect.height;
    57. }
    58. }
    59.  



     

    Attached Files:

  9. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    Can you explain in some more detail? I'm not sure what you mean by that.
     
  10. wallfired

    wallfired

    Joined:
    Dec 26, 2009
    Posts:
    21
    In my unity 3D editor show the alpha button, but when click it, doesn't show the click texture.

    Should I modified some propierties of the texture???
     

    Attached Files:

  11. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    When the image imports, the texture will have an alpha channel if one was created for the file (say if you use a transparent background with Photoshop). If not, you can use the Generate Alpha From Grayscale option. This will set white areas to full opacity, black areas to full transparency and other pixels' alpha to the equivalent brightness level.
     
  12. anxine

    anxine

    Joined:
    Aug 24, 2012
    Posts:
    1

    Sorry for answering on a two year old thread but maybe for somebody else searching around for round buttons this reply could be useful. The above code does not show the clicked Icon texture long enough (it's just drawn during the frame when the mouse click happens) or that was at least the case for me.

    Replace
    Code (csharp):
    1. Event.current.type == EventType.MouseDown
    with
    Code (csharp):
    1. Input.GetMouseButton(0)
    and everything works like a charm (meaning as long as you hold down the left mouse button).

    Not fully related to the original question but you can also add a hover on icon extending the AlphaButton function like this:

    Code (csharp):
    1. public static bool AlphaButton( Vector2 pos, Texture2D icon, Texture2D iconClicked, Texture2D iconHover, float alphaThreshold )
    2.     {
    3.         Rect iconRect;
    4.         Vector2 relativeClick;
    5.        
    6.         iconRect = new Rect( pos.x, pos.y, icon.width, icon.height );
    7.        
    8.         if(CheckRect( Event.current.mousePosition, iconRect ) )
    9.         {
    10.             relativeClick = new Vector2( Event.current.mousePosition.x - pos.x, Event.current.mousePosition.y - pos.y );
    11.            
    12.             if( icon.GetPixel( (int)relativeClick.x, (int)relativeClick.y ).a > alphaThreshold )
    13.             {
    14.                 GUI.DrawTexture( iconRect, iconHover );
    15.                 if(Input.GetMouseButton(0)) {
    16.                     GUI.DrawTexture( iconRect, iconClicked );
    17.                 }
    18.                 return true;
    19.             }
    20.         }
    21.        
    22.         GUI.DrawTexture( iconRect, icon, ScaleMode.ScaleToFit, true, 0 );
    23.         return false;
    24.     }