Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Feedback Expose Handles.Button overload with controlID argument to support Handle Tooltips

Discussion in 'Immediate Mode GUI (IMGUI)' started by Xarbrough, Dec 6, 2019.

  1. Xarbrough

    Xarbrough

    Joined:
    Dec 11, 2014
    Posts:
    1,188
    I like to use Handles.Button for various tools, but from time to time I'd like to pass my own controlID to the function. This function already exists, but is currently internal. Please simply make this overload public!

    For example, one of my use cases: I have a series of buttons in the scene which can be clicked to select and connect different nodes in a graph. But before clicking, I would like to show a status text with the name of the target currently hovered and some detail information. For this, I would use
    HandleUtility.nearestControl == controlID
    to implement a simple Tooltip.

    What I'm currently doing looks like the following:

    Code (CSharp):
    1. public class MyCoolTool
    2. {
    3.     private delegate bool ButtonDelegate(
    4.         int controlID, Vector3 position, Quaternion rotation, float size, float pickSize, Handles.CapFunction capFunction);
    5.  
    6.     private readonly ButtonDelegate buttonMethod;
    7.  
    8.     public MyCoolTool()
    9.     {
    10.         var type = typeof(Handles);
    11.  
    12.         var method = type.GetMethod(
    13.             "Button",
    14.             BindingFlags.Static | BindingFlags.NonPublic,
    15.             null,
    16.             new[] { typeof(int), typeof(Vector3), typeof(Quaternion), typeof(float), typeof(float), typeof(Handles.CapFunction) },
    17.             null);
    18.  
    19.         buttonMethod = (ButtonDelegate)System.Delegate.CreateDelegate(typeof(ButtonDelegate), method);
    20.     }
    21.  
    22.     public void OnGUI()
    23.     {
    24.         int controlID = GUIUtility.GetControlID(FocusType.Passive);
    25.         if (buttonMethod.Invoke(controlID, Vector3.zero, Quaternion.identity, 1f, 1f, Handles.SphereHandleCap))
    26.         {
    27.             Debug.Log("Click!");
    28.         }
    29.  
    30.         if (HandleUtility.nearestControl == controlID)
    31.             Handles.Label(new Vector3(0.4f, 0.6f, 0f), "Hover Tooltip");
    32.     }
    33. }
     
  2. CameronND

    CameronND

    Joined:
    Oct 2, 2018
    Posts:
    88
    Hi, I am doing something similar and my solution was to add a custom cap function which just calls Handles.SphereHandleCap, but also displays a label if the button is the nearest control.

    Code (CSharp):
    1. void CustomSphereCapHandle(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType)
    2. {
    3.     Handles.SphereHandleCap(controlID, position, rotation, size, eventType);
    4.     if(eventType == EventType.Repaint && HandleUtility.nearestControl == controlID)
    5.     {
    6.         Handles.Label(position, "Hover Tooltip");
    7.     }                              
    8. }