Currently selected Handle in editor script

Discussion in 'Scripting' started by keely, May 1, 2011.

  1. keely

    keely

    Unity Technologies

    Joined:
    Sep 9, 2010
    Messages:
    884
    Is there a way of knowing if one of your Handles is currently selected or gets selected in CustomEditor?

    I'm currently using Handles.FreeMoveHandle for every control point in my spline-tool. I try to keep track of the selected point via hacky code, where I'm making an intelligent guess during a mouseUp-event, that tries to determine which of the points is the closest of the click. This works "ok", but I'm getting reports that it's not 100%.
    Last edited: May 6, 2011
  2. keely

    keely

    Unity Technologies

    Joined:
    Sep 9, 2010
    Messages:
    884
    There's so much noise that I'm going to bump this once.
  3. Brady

    Brady

    Member

    Joined:
    Sep 25, 2008
    Messages:
    2,255
    If I understand your issue correctly, have you tried checking GUI.changed after drawing each handle? In theory, this should tell you which one was the last one with which the user interacted. Does that help?
  4. keely

    keely

    Unity Technologies

    Joined:
    Sep 9, 2010
    Messages:
    884
    I don't know yet, but seems like potential winner. I'm going to test it later when I get home. Thanks!
  5. mas

    mas

    New Member

    Joined:
    Nov 14, 2010
    Messages:
    694
    Any more info on this issue? I am wrestling with the same problem for my Orthello OTPath spline.

    The GUI.changed technique is only set when a handle has been moved.changed, not when you just select a handle ( and it gets outlined with a yellow line )

    Will go and check if I can cast a ray against the handle.

    Update

    I have managed to find the selected handle by doing this :

    - Code goes into the OnSceneGUI() of the editor class

    - Check if the GUIUtility.hotControl has changed ( value of 0 = no control selected )

    - If it hotControl changed, find the current handle by ray casting into the world using HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); and checking if that
    ray intersects with any of the created handles.

    This worlks because I know where I create my handles and within what radius the specific ray should fall to intersect with the handle.

    After I have found the right control, I can cache the controlID for future and quicker lookup. I have not managed to find a way to get a handle's ControlID right after I have created it. ( anyone??)
    Last edited: Aug 8, 2011
  6. BertMcD

    BertMcD

    New Member

    Joined:
    Oct 27, 2011
    Messages:
    1
    Cheers for the info, it pointed me in the right direction.

    The easiest way I found to do this is to name the Control using GUI.SetNextControlName ( ".." ).

    Unfortunately as some of the Handles ( PositionHandle ) create multiple controls only
    the first one will be named, but it easy enough to build your own from the components
    provided.

    Take the PositionHandle as an example we can add the following function to recreate
    it from the other handles provided. As you can see we set the name of each of the
    controls, this will let us use the function GUI.GetNameOfFocusedControl () to get the
    name of the control and use that to lookup an array or dictionary to find the related
    item.

    Vector3 PositionHandle ( Vector3 position, Quaternion rotation, string name )
    {
    // right Axis
    GUI.SetNextControlName ( name );
    Handles.color = new Color ( 1.0f, 0.0f, 0.0f, 0.75f );
    Vector3 newPos = Handles.Slider ( position, rotation*Vector3.right );

    // Up Axis
    GUI.SetNextControlName ( name );
    Handles.color = new Color ( 0.0f, 1.0f, 0.0f, 0.75f );
    newPos += Handles.Slider ( position, rotation*Vector3.up ) - position;

    // Forward Axis
    GUI.SetNextControlName ( name );
    Handles.color = new Color ( 0.0f, 0.0f, 1.0f, 0.75f );
    newPos += Handles.Slider ( position, rotation*Vector3.forward ) - position;

    float sizeMultiplier = 0.0f;

    if ( Camera.current.orthographic )
    {
    sizeMultiplier = Camera.current.orthographicSize * 2.5f;
    }
    else
    {
    Plane screen = new Plane ( Camera.current.transform.forward, Camera.current.transform.position );
    screen.Raycast ( new Ray ( position, Camera.current.transform.forward ), out sizeMultiplier );
    }

    GUI.SetNextControlName ( name );
    Handles.color = new Color ( 1.0f, 1.0f, 1.0f, 0.75f );
    newPos += Handles.FreeMoveHandle ( position, rotation, 0.02f * sizeMultiplier, Vector3.zero, Handles.RectangleCap ) - position;
    }
  7. tgraupmann

    tgraupmann

    Member

    Joined:
    Sep 14, 2007
    Messages:
    792
    Thanks for this post. I wasn't looking for the handle name, but I did want to check if a handle was pressed before raycasting.

    Thanks.
  8. littlemy

    littlemy

    New Member

    Joined:
    Feb 19, 2013
    Messages:
    1
    Just a little addition to this thread, in Unity 4.2 (at least) you can set the ID of some of the handles EG:

    static Vector3 Slider2D(
    int id,
    Vector3 handlePos,
    Vector3 offset,
    Vector3 handleDir,
    Vector3 slideDir1,
    Vector3 slideDir2,
    float handleSize,
    DrawCapFunction drawFunc,
    Vector2 snap,
    bool drawHelper);

    This can be used with GUIUtility.hotControl to identify which handle the user is currently interacting with