CustomHandles.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. namespace Shapes2D {
  2. using UnityEngine;
  3. using UnityEditor;
  4. // http://answers.unity3d.com/questions/463207/how-do-you-make-a-custom-handle-respond-to-the-mou.html
  5. public class CustomHandles
  6. {
  7. // internal state for DragHandle()
  8. static int s_DragHandleHash = "DragHandleHash".GetHashCode();
  9. static Vector2 s_DragHandleMouseStart;
  10. static Vector2 s_DragHandleMouseCurrent;
  11. static Vector3 s_DragHandleWorldStart;
  12. static float s_DragHandleClickTime = 0;
  13. static int s_DragHandleClickID;
  14. static float s_DragHandleDoubleClickInterval = 0.5f;
  15. static bool s_DragHandleHasMoved;
  16. // externally accessible to get the ID of the most resently processed DragHandle
  17. public static int lastDragHandleID;
  18. public enum DragHandleResult
  19. {
  20. none = 0,
  21. LMBPress,
  22. LMBClick,
  23. LMBDoubleClick,
  24. LMBDrag,
  25. LMBRelease,
  26. RMBPress,
  27. RMBClick,
  28. RMBDoubleClick,
  29. RMBDrag,
  30. RMBRelease,
  31. };
  32. #if UNITY_5_6_OR_NEWER
  33. public static Vector3 DragHandle(Vector3 position, float handleSize, Handles.CapFunction capFunc, Color colorSelected, out DragHandleResult result)
  34. #else
  35. public static Vector3 DragHandle(Vector3 position, float handleSize, Handles.DrawCapFunction capFunc, Color colorSelected, out DragHandleResult result)
  36. #endif
  37. {
  38. int id = GUIUtility.GetControlID(s_DragHandleHash, FocusType.Passive);
  39. lastDragHandleID = id;
  40. Vector3 screenPosition = Handles.matrix.MultiplyPoint(position);
  41. Matrix4x4 cachedMatrix = Handles.matrix;
  42. result = DragHandleResult.none;
  43. switch (Event.current.GetTypeForControl(id))
  44. {
  45. case EventType.MouseDown:
  46. if (HandleUtility.nearestControl == id && (Event.current.button == 0 || Event.current.button == 1))
  47. {
  48. GUIUtility.hotControl = id;
  49. s_DragHandleMouseCurrent = s_DragHandleMouseStart = Event.current.mousePosition;
  50. s_DragHandleWorldStart = position;
  51. s_DragHandleHasMoved = false;
  52. Event.current.Use();
  53. EditorGUIUtility.SetWantsMouseJumping(1);
  54. if (Event.current.button == 0)
  55. result = DragHandleResult.LMBPress;
  56. else if (Event.current.button == 1)
  57. result = DragHandleResult.RMBPress;
  58. }
  59. break;
  60. case EventType.MouseUp:
  61. if (GUIUtility.hotControl == id && (Event.current.button == 0 || Event.current.button == 1))
  62. {
  63. GUIUtility.hotControl = 0;
  64. Event.current.Use();
  65. EditorGUIUtility.SetWantsMouseJumping(0);
  66. if (Event.current.button == 0)
  67. result = DragHandleResult.LMBRelease;
  68. else if (Event.current.button == 1)
  69. result = DragHandleResult.RMBRelease;
  70. if (Event.current.mousePosition == s_DragHandleMouseStart)
  71. {
  72. bool doubleClick = (s_DragHandleClickID == id) &&
  73. (Time.realtimeSinceStartup - s_DragHandleClickTime < s_DragHandleDoubleClickInterval);
  74. s_DragHandleClickID = id;
  75. s_DragHandleClickTime = Time.realtimeSinceStartup;
  76. if (Event.current.button == 0)
  77. result = doubleClick ? DragHandleResult.LMBDoubleClick : DragHandleResult.LMBClick;
  78. else if (Event.current.button == 1)
  79. result = doubleClick ? DragHandleResult.RMBDoubleClick : DragHandleResult.RMBClick;
  80. }
  81. }
  82. break;
  83. case EventType.MouseDrag:
  84. if (GUIUtility.hotControl == id)
  85. {
  86. s_DragHandleMouseCurrent = Event.current.mousePosition;
  87. Vector3 worldPos = HandleUtility.GUIPointToWorldRay(s_DragHandleMouseCurrent).origin;
  88. position = Handles.matrix.inverse.MultiplyPoint(worldPos);
  89. if (Camera.current.transform.forward == Vector3.forward || Camera.current.transform.forward == -Vector3.forward)
  90. position.z = s_DragHandleWorldStart.z;
  91. if (Camera.current.transform.forward == Vector3.up || Camera.current.transform.forward == -Vector3.up)
  92. position.y = s_DragHandleWorldStart.y;
  93. if (Camera.current.transform.forward == Vector3.right || Camera.current.transform.forward == -Vector3.right)
  94. position.x = s_DragHandleWorldStart.x;
  95. if (Event.current.button == 0)
  96. result = DragHandleResult.LMBDrag;
  97. else if (Event.current.button == 1)
  98. result = DragHandleResult.RMBDrag;
  99. s_DragHandleHasMoved = true;
  100. GUI.changed = true;
  101. Event.current.Use();
  102. }
  103. break;
  104. case EventType.Repaint:
  105. Color currentColour = Handles.color;
  106. if (id == GUIUtility.hotControl && s_DragHandleHasMoved)
  107. Handles.color = colorSelected;
  108. Handles.matrix = Matrix4x4.identity;
  109. #if UNITY_5_6_OR_NEWER
  110. capFunc(id, screenPosition, Quaternion.identity, handleSize, EventType.Repaint);
  111. #else
  112. capFunc(id, screenPosition, Quaternion.identity, handleSize);
  113. #endif
  114. Handles.matrix = cachedMatrix;
  115. Handles.color = currentColour;
  116. break;
  117. case EventType.Layout:
  118. Handles.matrix = Matrix4x4.identity;
  119. HandleUtility.AddControl(id, HandleUtility.DistanceToCircle(screenPosition, handleSize));
  120. Handles.matrix = cachedMatrix;
  121. break;
  122. }
  123. return position;
  124. }
  125. }
  126. }