namespace Shapes2D { using UnityEngine; using UnityEditor; // http://answers.unity3d.com/questions/463207/how-do-you-make-a-custom-handle-respond-to-the-mou.html public class CustomHandles { // internal state for DragHandle() static int s_DragHandleHash = "DragHandleHash".GetHashCode(); static Vector2 s_DragHandleMouseStart; static Vector2 s_DragHandleMouseCurrent; static Vector3 s_DragHandleWorldStart; static float s_DragHandleClickTime = 0; static int s_DragHandleClickID; static float s_DragHandleDoubleClickInterval = 0.5f; static bool s_DragHandleHasMoved; // externally accessible to get the ID of the most resently processed DragHandle public static int lastDragHandleID; public enum DragHandleResult { none = 0, LMBPress, LMBClick, LMBDoubleClick, LMBDrag, LMBRelease, RMBPress, RMBClick, RMBDoubleClick, RMBDrag, RMBRelease, }; #if UNITY_5_6_OR_NEWER public static Vector3 DragHandle(Vector3 position, float handleSize, Handles.CapFunction capFunc, Color colorSelected, out DragHandleResult result) #else public static Vector3 DragHandle(Vector3 position, float handleSize, Handles.DrawCapFunction capFunc, Color colorSelected, out DragHandleResult result) #endif { int id = GUIUtility.GetControlID(s_DragHandleHash, FocusType.Passive); lastDragHandleID = id; Vector3 screenPosition = Handles.matrix.MultiplyPoint(position); Matrix4x4 cachedMatrix = Handles.matrix; result = DragHandleResult.none; switch (Event.current.GetTypeForControl(id)) { case EventType.MouseDown: if (HandleUtility.nearestControl == id && (Event.current.button == 0 || Event.current.button == 1)) { GUIUtility.hotControl = id; s_DragHandleMouseCurrent = s_DragHandleMouseStart = Event.current.mousePosition; s_DragHandleWorldStart = position; s_DragHandleHasMoved = false; Event.current.Use(); EditorGUIUtility.SetWantsMouseJumping(1); if (Event.current.button == 0) result = DragHandleResult.LMBPress; else if (Event.current.button == 1) result = DragHandleResult.RMBPress; } break; case EventType.MouseUp: if (GUIUtility.hotControl == id && (Event.current.button == 0 || Event.current.button == 1)) { GUIUtility.hotControl = 0; Event.current.Use(); EditorGUIUtility.SetWantsMouseJumping(0); if (Event.current.button == 0) result = DragHandleResult.LMBRelease; else if (Event.current.button == 1) result = DragHandleResult.RMBRelease; if (Event.current.mousePosition == s_DragHandleMouseStart) { bool doubleClick = (s_DragHandleClickID == id) && (Time.realtimeSinceStartup - s_DragHandleClickTime < s_DragHandleDoubleClickInterval); s_DragHandleClickID = id; s_DragHandleClickTime = Time.realtimeSinceStartup; if (Event.current.button == 0) result = doubleClick ? DragHandleResult.LMBDoubleClick : DragHandleResult.LMBClick; else if (Event.current.button == 1) result = doubleClick ? DragHandleResult.RMBDoubleClick : DragHandleResult.RMBClick; } } break; case EventType.MouseDrag: if (GUIUtility.hotControl == id) { s_DragHandleMouseCurrent = Event.current.mousePosition; Vector3 worldPos = HandleUtility.GUIPointToWorldRay(s_DragHandleMouseCurrent).origin; position = Handles.matrix.inverse.MultiplyPoint(worldPos); if (Camera.current.transform.forward == Vector3.forward || Camera.current.transform.forward == -Vector3.forward) position.z = s_DragHandleWorldStart.z; if (Camera.current.transform.forward == Vector3.up || Camera.current.transform.forward == -Vector3.up) position.y = s_DragHandleWorldStart.y; if (Camera.current.transform.forward == Vector3.right || Camera.current.transform.forward == -Vector3.right) position.x = s_DragHandleWorldStart.x; if (Event.current.button == 0) result = DragHandleResult.LMBDrag; else if (Event.current.button == 1) result = DragHandleResult.RMBDrag; s_DragHandleHasMoved = true; GUI.changed = true; Event.current.Use(); } break; case EventType.Repaint: Color currentColour = Handles.color; if (id == GUIUtility.hotControl && s_DragHandleHasMoved) Handles.color = colorSelected; Handles.matrix = Matrix4x4.identity; #if UNITY_5_6_OR_NEWER capFunc(id, screenPosition, Quaternion.identity, handleSize, EventType.Repaint); #else capFunc(id, screenPosition, Quaternion.identity, handleSize); #endif Handles.matrix = cachedMatrix; Handles.color = currentColour; break; case EventType.Layout: Handles.matrix = Matrix4x4.identity; HandleUtility.AddControl(id, HandleUtility.DistanceToCircle(screenPosition, handleSize)); Handles.matrix = cachedMatrix; break; } return position; } } }