public static Quaternion Do(int id, Quaternion rotation, Vector3 position, Vector3 axis, float size, bool cutoffPlane, float snap, bool enableRayDrag, bool showHotArc, Color fillColor) { var cam = Handles.inverseMatrix.MultiplyVector(Camera.current != null ? Camera.current.transform.forward : Vector3.forward); if (Mathf.Abs(Vector3.Dot(cam, axis)) > .999f) { cutoffPlane = false; } Event evt = Event.current; switch (evt.GetTypeForControl(id)) { case EventType.Layout: case EventType.MouseMove: { float d; if (cutoffPlane) { Vector3 from = Vector3.Cross(axis, cam).normalized; d = HandleUtility.DistanceToArc(position, axis, from, 180, size) * k_GrabZoneScale; } else { d = HandleUtility.DistanceToDisc(position, axis, size) * k_GrabZoneScale; } HandleUtility.AddControl(id, d); break; } case EventType.MouseDown: // am I closest to the thingy? if (HandleUtility.nearestControl == id && evt.button == 0 && !evt.alt) { GUIUtility.hotControl = id; // Grab mouse focus Tools.LockHandlePosition(); if (cutoffPlane) { Vector3 from = Vector3.Cross(axis, cam).normalized; s_StartPosition = HandleUtility.ClosestPointToArc(position, axis, from, 180, size); } else { s_StartPosition = HandleUtility.ClosestPointToDisc(position, axis, size); } s_RotationDist = 0; s_StartRotation = rotation; s_StartAxis = axis; s_CurrentMousePosition = s_StartMousePosition = Event.current.mousePosition; evt.Use(); EditorGUIUtility.SetWantsMouseJumping(1); } break; case EventType.MouseDrag: if (GUIUtility.hotControl == id) { // handle look to point rotation bool rayDrag = EditorGUI.actionKey && evt.shift && enableRayDrag; if (rayDrag) { if (HandleUtility.ignoreRaySnapObjects == null) { Handles.SetupIgnoreRaySnapObjects(); } object hit = HandleUtility.RaySnap(HandleUtility.GUIPointToWorldRay(evt.mousePosition)); if (hit != null && Vector3.Dot(axis.normalized, rotation * Vector3.forward) < 0.999) { RaycastHit rh = (RaycastHit)hit; Vector3 lookPoint = rh.point - position; Vector3 lookPointProjected = lookPoint - Vector3.Dot(lookPoint, axis.normalized) * axis.normalized; rotation = Quaternion.LookRotation(lookPointProjected, rotation * Vector3.up); } } else { Vector3 direction = Vector3.Cross(axis, position - s_StartPosition).normalized; s_CurrentMousePosition += evt.delta; s_RotationDist = HandleUtility.CalcLineTranslation(s_StartMousePosition, s_CurrentMousePosition, s_StartPosition, direction) / size * 30; s_RotationDist = Handles.SnapValue(s_RotationDist, snap); rotation = Quaternion.AngleAxis(s_RotationDist * -1, s_StartAxis) * s_StartRotation; } GUI.changed = true; evt.Use(); } break; case EventType.MouseUp: if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) { Tools.UnlockHandlePosition(); GUIUtility.hotControl = 0; evt.Use(); EditorGUIUtility.SetWantsMouseJumping(0); } break; case EventType.KeyDown: if (evt.keyCode == KeyCode.Escape && GUIUtility.hotControl == id) { // We do not use the event nor clear hotcontrol to ensure auto revert value kicks in from native side Tools.UnlockHandlePosition(); EditorGUIUtility.SetWantsMouseJumping(0); } break; case EventType.Repaint: Color temp = Color.white; if (id == GUIUtility.hotControl) { temp = Handles.color; Handles.color = Handles.selectedColor; } else if (id == HandleUtility.nearestControl && GUIUtility.hotControl == 0 && !evt.alt) { temp = Handles.color; Handles.color = Handles.preselectionColor; } // If we're dragging it, we'll go a bit further and draw a selection pie if (GUIUtility.hotControl == id) { Color t = Handles.color; Vector3 from = (s_StartPosition - position).normalized; Handles.color = fillColor; Handles.DrawLine(position, position + from * size); var d = -Mathf.Sign(s_RotationDist) * Mathf.Repeat(Mathf.Abs(s_RotationDist), 360); Vector3 to = Quaternion.AngleAxis(d, axis) * from; Handles.DrawLine(position, position + to * size); Handles.color = fillColor * new Color(1, 1, 1, .2f); for (int i = 0, revolutions = (int)Mathf.Abs(s_RotationDist * 0.002777777778f); i < revolutions; ++i) { Handles.DrawSolidDisc(position, axis, size); } Handles.DrawSolidArc(position, axis, from, d, size); // Draw snap markers if (EditorSnapSettings.incrementalSnapActive && snap > 0) { DrawRotationUnitSnapMarkers(position, axis, size, k_RotationUnitSnapMarkerSize, snap, @from); DrawRotationUnitSnapMarkers(position, axis, size, k_RotationUnitSnapMajorMarkerSize, k_RotationUnitSnapMajorMarkerStep, @from); } Handles.color = t; } if (showHotArc && GUIUtility.hotControl == id || GUIUtility.hotControl != id && !cutoffPlane) { Handles.DrawWireDisc(position, axis, size); } else if (GUIUtility.hotControl != id && cutoffPlane) { Vector3 from = Vector3.Cross(axis, cam).normalized; Handles.DrawWireArc(position, axis, from, 180, size); } if (id == GUIUtility.hotControl || id == HandleUtility.nearestControl && GUIUtility.hotControl == 0) { Handles.color = temp; } break; } return(rotation); }
public static float Do(int id, float value, Quaternion rotation, Vector3 position, Vector3 axis, float size, bool cutoffPlane, float snap, bool enableRayDrag, bool showHotArc, Color fillColor) { if (Mathf.Abs(Vector3.Dot(Camera.current.transform.forward, axis)) > 0.999f) { cutoffPlane = false; } Event current = Event.current; switch (current.GetTypeForControl(id)) { case EventType.MouseDown: if (HandleUtility.nearestControl == id && current.button == 0) { GUIUtility.hotControl = id; ToolsEx.LockHandlePosition(); if (cutoffPlane) { Vector3 normalized = Vector3.Cross(axis, Camera.current.transform.forward).normalized; s_StartPosition = HandleUtility.ClosestPointToArc(position, axis, normalized, 180f, size); } else { s_StartPosition = HandleUtility.ClosestPointToDisc(position, axis, size); } s_RotationDist = value; s_StartRotation = rotation; s_StartAxis = axis; s_CurrentMousePosition = s_StartMousePosition = Event.current.mousePosition; current.Use(); EditorGUIUtility.SetWantsMouseJumping(1); break; } break; case EventType.MouseUp: if (GUIUtility.hotControl == id && (current.button == 0 || current.button == 2)) { ToolsEx.UnlockHandlePosition(); GUIUtility.hotControl = 0; current.Use(); EditorGUIUtility.SetWantsMouseJumping(0); break; } break; case EventType.MouseMove: if (id == HandleUtility.nearestControl) { HandleUtility.Repaint(); break; } break; case EventType.MouseDrag: if (GUIUtility.hotControl == id) { if (EditorGUI.actionKey && current.shift && enableRayDrag) { //if (HandleUtility.ignoreRaySnapObjects == null) // Handles.SetupIgnoreRaySnapObjects(); object obj = HandleUtility.RaySnap(HandleUtility.GUIPointToWorldRay(current.mousePosition)); if (obj != null && (double)Vector3.Dot(axis.normalized, rotation * Vector3.forward) < 0.999) { Vector3 lhs = ((RaycastHit)obj).point - position; rotation = Quaternion.LookRotation(lhs - Vector3.Dot(lhs, axis.normalized) * axis.normalized, rotation * Vector3.up); } } else { Vector3 normalized = Vector3.Cross(axis, position - s_StartPosition).normalized; s_CurrentMousePosition += current.delta; s_RotationDist = (float)((double)HandleUtility.CalcLineTranslation(s_StartMousePosition, s_CurrentMousePosition, s_StartPosition, normalized) / (double)size * 30.0); s_RotationDist = Handles.SnapValue(s_RotationDist, snap); rotation = Quaternion.AngleAxis(s_RotationDist * -1f, s_StartAxis) * s_StartRotation; } GUI.changed = true; current.Use(); break; } break; case EventType.KeyDown: if (current.keyCode == KeyCode.Escape && GUIUtility.hotControl == id) { ToolsEx.UnlockHandlePosition(); EditorGUIUtility.SetWantsMouseJumping(0); break; } break; case EventType.Repaint: Color color1 = Color.white; if (id == GUIUtility.hotControl) { color1 = Handles.color; Handles.color = Handles.selectedColor; } else if (id == HandleUtility.nearestControl && GUIUtility.hotControl == 0) { color1 = Handles.color; Handles.color = Handles.secondaryColor; } if (GUIUtility.hotControl == id) { Color color2 = Handles.color; Vector3 normalized = (s_StartPosition - position).normalized; Handles.color = fillColor; Handles.DrawLine(position, position + normalized * size); float angle = -Mathf.Sign(s_RotationDist) * Mathf.Repeat(Mathf.Abs(s_RotationDist), 360f); Vector3 vector3 = Quaternion.AngleAxis(angle, axis) * normalized; Handles.DrawLine(position, position + vector3 * size); Handles.color = fillColor * new Color(1f, 1f, 1f, 0.2f); int num = 0; for (int index = (int)Mathf.Abs(s_RotationDist * (1f / 360f)); num < index; ++num) { Handles.DrawSolidDisc(position, axis, size); } Handles.DrawSolidArc(position, axis, normalized, angle, size); if (EditorGUI.actionKey && snap > 0) { DrawRotationUnitSnapMarkers(position, axis, size, 0.1f, snap, normalized); DrawRotationUnitSnapMarkers(position, axis, size, 0.2f, 45f, normalized); } Handles.color = color2; } if (showHotArc && GUIUtility.hotControl == id || GUIUtility.hotControl != id && !cutoffPlane) { Handles.DrawWireDisc(position, axis, size); } else if (GUIUtility.hotControl != id && cutoffPlane) { Vector3 normalized = Vector3.Cross(axis, Camera.current.transform.forward).normalized; Handles.DrawWireArc(position, axis, normalized, 180f, size); } if (id == GUIUtility.hotControl || id == HandleUtility.nearestControl && GUIUtility.hotControl == 0) { Handles.color = color1; break; } break; case EventType.Layout: float distance; if (cutoffPlane) { Vector3 normalized = Vector3.Cross(axis, Camera.current.transform.forward).normalized; distance = HandleUtility.DistanceToArc(position, axis, normalized, 180f, size) * 0.3f; } else { distance = HandleUtility.DistanceToDisc(position, axis, size) * 0.3f; } HandleUtility.AddControl(id, distance); break; } return(s_RotationDist); }
public static Quaternion Do(int id, Quaternion rotation, Vector3 position, Vector3 axis, float size, bool cutoffPlane, float snap) { float num; if (Mathf.Abs(Vector3.Dot(Camera.current.transform.forward, axis)) > 0.999f) { cutoffPlane = false; } Event current = Event.current; switch (current.GetTypeForControl(id)) { case EventType.MouseDown: if (((HandleUtility.nearestControl == id) && (current.button == 0)) || ((GUIUtility.keyboardControl == id) && (current.button == 2))) { int num3 = id; GUIUtility.keyboardControl = num3; GUIUtility.hotControl = num3; Tools.LockHandlePosition(); if (!cutoffPlane) { s_StartPosition = HandleUtility.ClosestPointToDisc(position, axis, size); } else { Vector3 normalized = Vector3.Cross(axis, Camera.current.transform.forward).normalized; s_StartPosition = HandleUtility.ClosestPointToArc(position, axis, normalized, 180f, size); } s_RotationDist = 0f; s_StartRotation = rotation; s_StartAxis = axis; s_CurrentMousePosition = s_StartMousePosition = Event.current.mousePosition; current.Use(); EditorGUIUtility.SetWantsMouseJumping(1); } return(rotation); case EventType.MouseUp: if ((GUIUtility.hotControl == id) && ((current.button == 0) || (current.button == 2))) { Tools.UnlockHandlePosition(); GUIUtility.hotControl = 0; current.Use(); EditorGUIUtility.SetWantsMouseJumping(0); } return(rotation); case EventType.MouseMove: case EventType.KeyUp: case EventType.ScrollWheel: return(rotation); case EventType.MouseDrag: if (GUIUtility.hotControl == id) { if (!(EditorGUI.actionKey && current.shift)) { Vector3 constraintDir = Vector3.Cross(axis, position - s_StartPosition).normalized; s_CurrentMousePosition += current.delta; s_RotationDist = (HandleUtility.CalcLineTranslation(s_StartMousePosition, s_CurrentMousePosition, s_StartPosition, constraintDir) / size) * 30f; s_RotationDist = Handles.SnapValue(s_RotationDist, snap); rotation = Quaternion.AngleAxis(s_RotationDist * -1f, s_StartAxis) * s_StartRotation; } else { if (HandleUtility.ignoreRaySnapObjects == null) { Handles.SetupIgnoreRaySnapObjects(); } object obj2 = HandleUtility.RaySnap(HandleUtility.GUIPointToWorldRay(current.mousePosition)); if ((obj2 != null) && (Vector3.Dot(axis.normalized, (Vector3)(rotation * Vector3.forward)) < 0.999)) { RaycastHit hit = (RaycastHit)obj2; Vector3 lhs = hit.point - position; Vector3 forward = lhs - ((Vector3)(Vector3.Dot(lhs, axis.normalized) * axis.normalized)); rotation = Quaternion.LookRotation(forward, (Vector3)(rotation * Vector3.up)); } } GUI.changed = true; current.Use(); } return(rotation); case EventType.KeyDown: if ((current.keyCode == KeyCode.Escape) && (GUIUtility.hotControl == id)) { Tools.UnlockHandlePosition(); EditorGUIUtility.SetWantsMouseJumping(0); } return(rotation); case EventType.Repaint: { Color white = Color.white; if (id == GUIUtility.keyboardControl) { white = Handles.color; Handles.color = Handles.selectedColor; } if (GUIUtility.hotControl == id) { Color color = Handles.color; Vector3 vector12 = s_StartPosition - position; Vector3 from = vector12.normalized; Handles.color = Handles.secondaryColor; Handles.DrawLine(position, position + ((Vector3)((from * size) * 1.1f))); float angle = Mathf.Repeat(-s_RotationDist - 180f, 360f) - 180f; Vector3 vector7 = (Vector3)(Quaternion.AngleAxis(angle, axis) * from); Handles.DrawLine(position, position + ((Vector3)((vector7 * size) * 1.1f))); Handles.color = Handles.secondaryColor * new Color(1f, 1f, 1f, 0.2f); Handles.DrawSolidArc(position, axis, from, angle, size); Handles.color = color; } if (cutoffPlane) { Vector3 vector8 = Vector3.Cross(axis, Camera.current.transform.forward).normalized; Handles.DrawWireArc(position, axis, vector8, 180f, size); } else { Handles.DrawWireDisc(position, axis, size); } if (id == GUIUtility.keyboardControl) { Handles.color = white; } return(rotation); } case EventType.Layout: { if (!cutoffPlane) { num = HandleUtility.DistanceToDisc(position, axis, size) / 2f; break; } Vector3 vector = Vector3.Cross(axis, Camera.current.transform.forward).normalized; num = HandleUtility.DistanceToArc(position, axis, vector, 180f, size) / 2f; break; } default: return(rotation); } HandleUtility.AddControl(id, num); return(rotation); }
public static Quaternion Do(int id, Quaternion rotation, Vector3 position, Vector3 axis, float size, bool cutoffPlane, float snap) { if (Mathf.Abs(Vector3.Dot(Camera.current.transform.forward, axis)) > 0.999f) { cutoffPlane = false; } Event current = Event.current; switch (current.GetTypeForControl(id)) { case EventType.MouseDown: if ((HandleUtility.nearestControl == id && current.button == 0) || (GUIUtility.keyboardControl == id && current.button == 2)) { GUIUtility.keyboardControl = id; GUIUtility.hotControl = id; Tools.LockHandlePosition(); if (cutoffPlane) { Vector3 normalized = Vector3.Cross(axis, Camera.current.transform.forward).normalized; Disc.s_StartPosition = HandleUtility.ClosestPointToArc(position, axis, normalized, 180f, size); } else { Disc.s_StartPosition = HandleUtility.ClosestPointToDisc(position, axis, size); } Disc.s_RotationDist = 0f; Disc.s_StartRotation = rotation; Disc.s_StartAxis = axis; Disc.s_CurrentMousePosition = (Disc.s_StartMousePosition = Event.current.mousePosition); current.Use(); EditorGUIUtility.SetWantsMouseJumping(1); } break; case EventType.MouseUp: if (GUIUtility.hotControl == id && (current.button == 0 || current.button == 2)) { Tools.UnlockHandlePosition(); GUIUtility.hotControl = 0; current.Use(); EditorGUIUtility.SetWantsMouseJumping(0); } break; case EventType.MouseDrag: if (GUIUtility.hotControl == id) { bool flag = EditorGUI.actionKey && current.shift; if (flag) { if (HandleUtility.ignoreRaySnapObjects == null) { Handles.SetupIgnoreRaySnapObjects(); } object obj = HandleUtility.RaySnap(HandleUtility.GUIPointToWorldRay(current.mousePosition)); if (obj != null && (double)Vector3.Dot(axis.normalized, rotation * Vector3.forward) < 0.999) { Vector3 vector = ((RaycastHit)obj).point - position; Vector3 forward = vector - Vector3.Dot(vector, axis.normalized) * axis.normalized; rotation = Quaternion.LookRotation(forward, rotation * Vector3.up); } } else { Vector3 normalized2 = Vector3.Cross(axis, position - Disc.s_StartPosition).normalized; Disc.s_CurrentMousePosition += current.delta; Disc.s_RotationDist = HandleUtility.CalcLineTranslation(Disc.s_StartMousePosition, Disc.s_CurrentMousePosition, Disc.s_StartPosition, normalized2) / size * 30f; Disc.s_RotationDist = Handles.SnapValue(Disc.s_RotationDist, snap); rotation = Quaternion.AngleAxis(Disc.s_RotationDist * -1f, Disc.s_StartAxis) * Disc.s_StartRotation; } GUI.changed = true; current.Use(); } break; case EventType.KeyDown: if (current.keyCode == KeyCode.Escape && GUIUtility.hotControl == id) { Tools.UnlockHandlePosition(); EditorGUIUtility.SetWantsMouseJumping(0); } break; case EventType.Repaint: { Color color = Color.white; if (id == GUIUtility.keyboardControl) { color = Handles.color; Handles.color = Handles.selectedColor; } if (GUIUtility.hotControl == id) { Color color2 = Handles.color; Vector3 normalized3 = (Disc.s_StartPosition - position).normalized; Handles.color = Handles.secondaryColor; Handles.DrawLine(position, position + normalized3 * size * 1.1f); float angle = Mathf.Repeat(-Disc.s_RotationDist - 180f, 360f) - 180f; Vector3 a = Quaternion.AngleAxis(angle, axis) * normalized3; Handles.DrawLine(position, position + a * size * 1.1f); Handles.color = Handles.secondaryColor * new Color(1f, 1f, 1f, 0.2f); Handles.DrawSolidArc(position, axis, normalized3, angle, size); Handles.color = color2; } if (cutoffPlane) { Vector3 normalized4 = Vector3.Cross(axis, Camera.current.transform.forward).normalized; Handles.DrawWireArc(position, axis, normalized4, 180f, size); } else { Handles.DrawWireDisc(position, axis, size); } if (id == GUIUtility.keyboardControl) { Handles.color = color; } break; } case EventType.Layout: { float distance; if (cutoffPlane) { Vector3 normalized5 = Vector3.Cross(axis, Camera.current.transform.forward).normalized; distance = HandleUtility.DistanceToArc(position, axis, normalized5, 180f, size) / 2f; } else { distance = HandleUtility.DistanceToDisc(position, axis, size) / 2f; } HandleUtility.AddControl(id, distance); break; } } return(rotation); }
public static Quaternion Do(Camera camera, int id, string name, Quaternion rotation, Vector3 position, Vector3 axis, float size, bool cutoffPlane, bool snapping, float snap, CSGHandles.InitFunction initFunction, CSGHandles.InitFunction shutdownFunction) { if (Mathf.Abs(Vector3.Dot(camera.transform.forward, axis)) > .999f) { cutoffPlane = false; } var evt = Event.current; switch (evt.GetTypeForControl(id)) { case EventType.Layout: { float d; if (cutoffPlane) { var from = Vector3.Cross(axis, camera.transform.forward).normalized; d = HandleUtility.DistanceToArc(position, axis, from, 180, size) / 2; } else { d = HandleUtility.DistanceToDisc(position, axis, size) / 2; } HandleUtility.AddControl(id, d); break; } case EventType.MouseDown: { if (CSGHandles.disabled) { break; } if (((HandleUtility.nearestControl == id && evt.button == 0) || (GUIUtility.keyboardControl == id && evt.button == 2)) && GUIUtility.hotControl == 0) { if (initFunction != null) { initFunction(); } GUIUtility.hotControl = GUIUtility.keyboardControl = id; // Grab mouse focus //Tools.LockHandlePosition(); if (cutoffPlane) { Vector3 from = Vector3.Cross(axis, camera.transform.forward).normalized; s_StartPosition = HandleUtility.ClosestPointToArc(position, axis, from, 180, size); } else { s_StartPosition = HandleUtility.ClosestPointToDisc(position, axis, size); } s_RotationDist = 0; s_StartRotation = rotation; s_StartAxis = axis; s_CurrentMousePosition = s_StartMousePosition = Event.current.mousePosition; evt.Use(); EditorGUIUtility.SetWantsMouseJumping(1); } break; } case EventType.MouseDrag: { if (GUIUtility.hotControl == id) { var direction = Vector3.Cross(axis, position - s_StartPosition).normalized; s_CurrentMousePosition += evt.delta; s_RotationDist = HandleUtility.CalcLineTranslation(s_StartMousePosition, s_CurrentMousePosition, s_StartPosition, direction) / size * 30; s_RotationDist = SnapValue(s_RotationDist, snap, snapping); rotation = Quaternion.AngleAxis(s_RotationDist * -1, s_StartAxis) * s_StartRotation; GUI.changed = true; evt.Use(); } break; } case EventType.MouseUp: { if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) { //Tools.UnlockHandlePosition(); GUIUtility.hotControl = 0; evt.Use(); if (shutdownFunction != null) { shutdownFunction(); } EditorGUIUtility.SetWantsMouseJumping(0); } break; } case EventType.KeyDown: { if (evt.keyCode == KeyCode.Escape && GUIUtility.hotControl == id) { // We do not use the event nor clear hotcontrol to ensure auto revert value kicks in from native side //Tools.UnlockHandlePosition(); EditorGUIUtility.SetWantsMouseJumping(0); } break; } case EventType.Repaint: { var originalColor = Handles.color; if (id == GUIUtility.keyboardControl) { Handles.color = Handles.selectedColor; } // If we're dragging it, we'll go a bit further and draw a selection pie if (GUIUtility.hotControl == id) { Vector3 from = Vector3.Cross(axis, Vector3.Cross(axis, (s_StartPosition - position).normalized).normalized); float radius = size * 1.1f; float endAngle = s_RotationDist; PaintUtility.DrawRotateCircle(camera, position, axis, from, radius, 0, 0, endAngle, Handles.color, name, true); PaintUtility.DrawRotateCirclePie(position, axis, from, radius, 0, 0, endAngle, Handles.color); /* * Color t = Handles.color; * Vector3 from = (s_StartPosition - position).normalized; * Handles.color = Handles.secondaryColor; * Handles.DrawLine(position, position + from * size * 1.1f); * float d = Mathf.Repeat(-s_RotationDist - 180, 360) - 180; * Vector3 to = Quaternion.AngleAxis(d, axis) * from; * Handles.DrawLine(position, position + to * size * 1.1f); * * Handles.color = Handles.secondaryColor * new Color(1, 1, 1, .2f); * Handles.DrawSolidArc(position, axis, from, d, size); * Handles.color = t; */ } else if (CSGHandles.disabled) { Handles.color = Color.Lerp(originalColor, Handles.secondaryColor, 0.75f); } if (cutoffPlane) { Vector3 from = Vector3.Cross(axis, camera.transform.forward).normalized; Handles.DrawWireArc(position, axis, from, 180, size); } else { Handles.DrawWireDisc(position, axis, size); } Handles.color = originalColor; break; } } return(rotation); }
public float DrawAngleHandle(int id, Vector3 center, Vector3 normal, Vector3 tangent, float angle, float radius) { Vector3 direction = Vector3.Dot(Vector3.forward, normal) == 0 ? Vector3.forward : Vector3.up; Vector3 AngleDir = Quaternion.AngleAxis(angle, normal) * direction * radius; Vector3 handlePos = AngleDir + center; Quaternion handleRot = Quaternion.AngleAxis(-angle + 90, tangent); float handleSize = HandleUtility.GetHandleSize(handlePos) * .125f; Event evt = Event.current; switch (evt.GetTypeForControl(id)) { case EventType.Layout: Handles.CylinderHandleCap(id, handlePos, handleRot, handleSize, EventType.Layout); break; case EventType.MouseDown: if (evt.button == 0 && GUIUtility.hotControl == 0 && HandleUtility.nearestControl == id) { GUIUtility.hotControl = id; currentMousePos = startMousePos = evt.mousePosition; startMousePos = currentMousePos; evt.Use(); EditorGUIUtility.SetWantsMouseJumping(1); } break; case EventType.MouseDrag: if (GUIUtility.hotControl == id) { currentMousePos += evt.delta; Vector3 tempPos = HandleUtility.ClosestPointToArc(center, normal, AngleDir, 360, radius); angle += Vector3.SignedAngle(AngleDir, tempPos - center, normal); evt.Use(); } break; case EventType.MouseUp: if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) { GUIUtility.hotControl = 0; evt.Use(); EditorGUIUtility.SetWantsMouseJumping(0); } break; case EventType.Repaint: Color tempColor = Handles.color; if (id == GUIUtility.hotControl) { Handles.color = Handles.selectedColor; } Handles.Label(handlePos, id.ToString()); Handles.CylinderHandleCap(id, handlePos, handleRot, handleSize, EventType.Repaint); Handles.color = tempColor; break; } return(angle); }