public static void DrawLength(UnityEngine.Vector3 from, UnityEngine.Vector3 to, float forceValue) { var prevColor = SceneHandles.color; SceneHandles.color = SceneHandles.StateColor(SceneHandles.measureColor); var invMatrix = SceneHandles.inverseMatrix; var camera = UnityEngine.Camera.current; var camPos = invMatrix.MultiplyPoint(camera.transform.position); var camDir = (SceneHandleUtility.ProjectPointLine(camPos, from, to) - camPos).normalized; var delta = (to - from); var length = delta.magnitude; var forward = delta / length; var right = Vector3.Cross(forward, camDir); var fromSize = UnityEditor.HandleUtility.GetHandleSize(from); var toSize = UnityEditor.HandleUtility.GetHandleSize(to); var center = (to + from) * 0.5f; SceneHandles.DrawLine(from, to); DrawFlatArrow(from, forward, camDir, fromSize * 0.2f); DrawFlatArrow(to, -forward, camDir, toSize * 0.2f); // SceneHandles.DrawLine(from - right, from + right); // SceneHandles.DrawLine(to - right, to + right); DrawUnitLabel(center, right, 2, forceValue); SceneHandles.color = prevColor; }
public static float RadiusHandle(Quaternion rotation, Vector3 position, float radius, bool renderDisc = true) { var isStatic = (!Tools.hidden && EditorApplication.isPlaying && GameObjectUtility.ContainsStatic(Selection.gameObjects)); var prevDisabled = SceneHandles.disabled; var prevColor = SceneHandles.color; var forward = rotation * Vector3.forward; var up = rotation * Vector3.up; var right = rotation * Vector3.right; // Radius handle in zenith bool temp = GUI.changed; // Radius handles at disc temp = GUI.changed; GUI.changed = false; var isDisabled = isStatic || prevDisabled || Snapping.AxisLocking[1]; SceneHandles.color = SceneHandles.StateColor(prevColor, isDisabled, false); radius = SizeSlider(position, up, forward, up, right, radius); radius = SizeSlider(position, -up, forward, up, right, radius); isDisabled = isStatic || prevDisabled || Snapping.AxisLocking[0]; SceneHandles.color = SceneHandles.StateColor(prevColor, isDisabled, false); radius = SizeSlider(position, right, forward, up, right, radius); radius = SizeSlider(position, -right, forward, up, right, radius); if (GUI.changed) { radius = Mathf.Max(0.0f, radius); } GUI.changed |= temp; isDisabled = isStatic || prevDisabled || (Snapping.AxisLocking[0] && Snapping.AxisLocking[1]); SceneHandles.color = SceneHandles.StateColor(prevColor, isDisabled, false); // Draw gizmo if (radius > 0 && renderDisc) { SceneHandles.DrawWireDisc(position, forward, radius); } SceneHandles.disabled = prevDisabled; SceneHandles.color = prevColor; return(radius); }
public static float Radius2DHandle(Quaternion rotation, Vector3 position, float radius, float minRadius = 0, float maxRadius = float.PositiveInfinity, bool renderDisc = true) { minRadius = Mathf.Abs(minRadius); maxRadius = Mathf.Abs(maxRadius); if (maxRadius < minRadius) { maxRadius = minRadius; } var isStatic = (!Tools.hidden && EditorApplication.isPlaying && GameObjectUtility.ContainsStatic(Selection.gameObjects)); var prevDisabled = SceneHandles.disabled; var prevColor = SceneHandles.color; var forward = rotation * Vector3.forward; var up = rotation * Vector3.up; var right = rotation * Vector3.right; bool temp = GUI.changed; GUI.changed = false; var isDisabled = isStatic || prevDisabled || Snapping.AxisLocking[1]; SceneHandles.color = SceneHandles.StateColor(prevColor, isDisabled, false); radius = Size2DSlider(position, up, forward, up, right, radius); radius = Size2DSlider(position, -up, forward, up, right, radius); isDisabled = isStatic || prevDisabled || Snapping.AxisLocking[0]; SceneHandles.color = SceneHandles.StateColor(prevColor, isDisabled, false); radius = Size2DSlider(position, right, forward, up, right, radius); radius = Size2DSlider(position, -right, forward, up, right, radius); radius = Mathf.Max(minRadius, Mathf.Min(Mathf.Abs(radius), maxRadius)); GUI.changed |= temp; if (radius > 0 && renderDisc) { isDisabled = isStatic || prevDisabled || (Snapping.AxisLocking[0] && Snapping.AxisLocking[1]); SceneHandles.color = SceneHandles.StateColor(prevColor, isDisabled, false); SceneHandles.DrawWireDisc(position, forward, radius); SceneHandles.disabled = prevDisabled; SceneHandles.color = prevColor; } return(radius); }
public static Vector3[] PositionHandle(ref PositionHandleIDs handleIDs, Vector3[] points, Vector3 position, Quaternion rotation, Axes enabledAxes = Axes.XYZ) { var xAxisId = handleIDs.xAxisId; var yAxisId = handleIDs.yAxisId; var zAxisId = handleIDs.zAxisId; var xzPlaneId = handleIDs.xzPlaneId; var xyPlaneId = handleIDs.xyPlaneId; var yzPlaneId = handleIDs.yzPlaneId; var centerId = handleIDs.centerId; var originalColor = SceneHandles.color; var handleSize = UnityEditor.HandleUtility.GetHandleSize(position); UnityEditor.HandleUtility.AddControl(centerId, UnityEditor.HandleUtility.DistanceToCircle(position, handleSize * 0.055f)); var evt = Event.current; var type = evt.GetTypeForControl(centerId); switch (type) { case EventType.MouseDown: { if (GUIUtility.hotControl != 0) { break; } if ((UnityEditor.HandleUtility.nearestControl != centerId || evt.button != 0) && (GUIUtility.keyboardControl != centerId || evt.button != 2)) { break; } handleIDs.originalPosition = position; GUIUtility.hotControl = GUIUtility.keyboardControl = centerId; evt.Use(); EditorGUIUtility.SetWantsMouseJumping(1); break; } case EventType.MouseMove: { handleIDs.originalPosition = position; break; } case EventType.MouseDrag: { if (GUIUtility.hotControl != centerId) { break; } break; } case EventType.MouseUp: { if (GUIUtility.hotControl == centerId && (evt.button == 0 || evt.button == 2)) { GUIUtility.hotControl = 0; GUIUtility.keyboardControl = 0; evt.Use(); Snapping.ActiveAxes = Axes.XYZ; EditorGUIUtility.SetWantsMouseJumping(0); SceneView.RepaintAll(); handleIDs.originalPosition = position; } break; } } //,.,.., look at 2018.1 how the position handle works w/ colors var xAxisLocked = (handleIDs.xAxisState & ControlState.Locked) == ControlState.Locked; var yAxisLocked = (handleIDs.yAxisState & ControlState.Locked) == ControlState.Locked; var zAxisLocked = (handleIDs.zAxisState & ControlState.Locked) == ControlState.Locked; var xzPlaneLocked = (handleIDs.xzPlaneState & ControlState.Locked) == ControlState.Locked; var xyPlaneLocked = (handleIDs.xyPlaneState & ControlState.Locked) == ControlState.Locked; var yzPlaneLocked = (handleIDs.yzPlaneState & ControlState.Locked) == ControlState.Locked; var xAxisDisabled = ((enabledAxes & Axes.X) != Axes.X) || (handleIDs.xAxisState & ControlState.Disabled) == ControlState.Disabled; var yAxisDisabled = ((enabledAxes & Axes.Y) != Axes.Y) || (handleIDs.yAxisState & ControlState.Disabled) == ControlState.Disabled; var zAxisDisabled = ((enabledAxes & Axes.Z) != Axes.Z) || (handleIDs.zAxisState & ControlState.Disabled) == ControlState.Disabled; var xyPlaneDisabled = ((enabledAxes & Axes.XY) != Axes.XY) || (handleIDs.xyPlaneState & ControlState.Disabled) == ControlState.Disabled; var yzPlaneDisabled = ((enabledAxes & Axes.YZ) != Axes.YZ) || (handleIDs.yzPlaneState & ControlState.Disabled) == ControlState.Disabled; var xzPlaneDisabled = ((enabledAxes & Axes.XZ) != Axes.XZ) || (handleIDs.xzPlaneState & ControlState.Disabled) == ControlState.Disabled; var xAxisSelected = (handleIDs.xAxisIndirectState & (ControlState.Focused | ControlState.Active)) != ControlState.None; var yAxisSelected = (handleIDs.yAxisIndirectState & (ControlState.Focused | ControlState.Active)) != ControlState.None; var zAxisSelected = (handleIDs.zAxisIndirectState & (ControlState.Focused | ControlState.Active)) != ControlState.None; var xzPlaneSelected = (handleIDs.xzPlaneState & (ControlState.Focused | ControlState.Active)) != ControlState.None; var xyPlaneSelected = (handleIDs.xyPlaneState & (ControlState.Focused | ControlState.Active)) != ControlState.None; var yzPlaneSelected = (handleIDs.yzPlaneState & (ControlState.Focused | ControlState.Active)) != ControlState.None; var xAxisColor = SceneHandles.StateColor(SceneHandles.xAxisColor, xAxisDisabled, xAxisSelected); var yAxisColor = SceneHandles.StateColor(SceneHandles.yAxisColor, yAxisDisabled, yAxisSelected); var zAxisColor = SceneHandles.StateColor(SceneHandles.zAxisColor, zAxisDisabled, zAxisSelected); var xzPlaneColor = SceneHandles.StateColor(SceneHandles.yAxisColor, xzPlaneDisabled, xzPlaneSelected); var xyPlaneColor = SceneHandles.StateColor(SceneHandles.zAxisColor, xyPlaneDisabled, xyPlaneSelected); var yzPlaneColor = SceneHandles.StateColor(SceneHandles.xAxisColor, yzPlaneDisabled, yzPlaneSelected); var prevDisabled = SceneHandles.disabled; if (!xAxisLocked) { SceneHandles.disabled = xAxisDisabled; SceneHandles.color = xAxisColor; points = Slider1DHandle(xAxisId, Axis.X, points, position, rotation * Vector3.right, Snapping.MoveSnappingSteps.x, handleSize, ArrowHandleCap, selectLockingAxisOnClick: true); } if (!yAxisLocked) { SceneHandles.disabled = yAxisDisabled; SceneHandles.color = yAxisColor; points = Slider1DHandle(yAxisId, Axis.Y, points, position, rotation * Vector3.up, Snapping.MoveSnappingSteps.y, handleSize, ArrowHandleCap, selectLockingAxisOnClick: true); } if (!zAxisLocked) { SceneHandles.disabled = zAxisDisabled; SceneHandles.color = zAxisColor; points = Slider1DHandle(zAxisId, Axis.Z, points, position, rotation * Vector3.forward, Snapping.MoveSnappingSteps.z, handleSize, ArrowHandleCap, selectLockingAxisOnClick: true); } if (!xzPlaneLocked) { SceneHandles.disabled = xzPlaneDisabled; SceneHandles.color = xzPlaneColor; points = PlanarHandle(xzPlaneId, PlaneAxes.XZ, points, position, rotation, handleSize * 0.3f, selectLockingAxisOnClick: true); } if (!xyPlaneLocked) { SceneHandles.disabled = xyPlaneDisabled; SceneHandles.color = xyPlaneColor; points = PlanarHandle(xyPlaneId, PlaneAxes.XY, points, position, rotation, handleSize * 0.3f, selectLockingAxisOnClick: true); } if (!yzPlaneLocked) { SceneHandles.disabled = yzPlaneDisabled; SceneHandles.color = yzPlaneColor; points = PlanarHandle(yzPlaneId, PlaneAxes.YZ, points, position, rotation, handleSize * 0.3f, selectLockingAxisOnClick: true); } if ((handleIDs.centerState & ControlState.Disabled) != ControlState.Disabled) { switch (type) { case EventType.Repaint: { var focused = (handleIDs.centerState & ControlState.Focused) == ControlState.Focused; SceneHandles.color = SceneHandles.StateColor(SceneHandles.centerColor, false, focused); SceneHandles.RenderBorderedCircle(position, handleSize * 0.05f); break; } } } SceneHandles.disabled = prevDisabled; SceneHandles.color = originalColor; return(points); }
public static Vector3[] Do(int id, Vector3[] points, Vector3 handleOrigin, Vector3 handleCursorOffset, Vector3 handleNormal, Vector3 slideDir1, Vector3 slideDir2, float handleSize, SceneHandles.CapFunction capFunction, Axes axes = Axes.None, bool selectLockingAxisOnClick = false, bool noSnapping = false, Vector3?snappingSteps = null) { var evt = Event.current; switch (evt.GetTypeForControl(id)) { case EventType.MouseDown: { if (Tools.current == Tool.View || Tools.current == Tool.None || evt.alt) { break; } if (GUIUtility.hotControl != 0) { break; } if ((UnityEditor.HandleUtility.nearestControl != id || evt.button != 0) && (GUIUtility.keyboardControl != id || evt.button != 2)) { break; } GUIUtility.hotControl = GUIUtility.keyboardControl = id; evt.Use(); EditorGUIUtility.SetWantsMouseJumping(1); s_CurrentMousePosition = evt.mousePosition; s_StartPoints = points.ToArray(); var localToWorldMatrix = UnityEditor.Handles.matrix; var center = Grid.ActiveGrid.Center; Matrix4x4 gridSpace = Matrix4x4.identity; gridSpace.SetColumn(0, localToWorldMatrix.MultiplyVector(slideDir1).normalized); gridSpace.SetColumn(1, localToWorldMatrix.MultiplyVector(handleNormal).normalized); gridSpace.SetColumn(2, localToWorldMatrix.MultiplyVector(slideDir2).normalized); gridSpace.SetColumn(3, new Vector4(center.x, center.y, center.z, 1.0f)); var workGrid = new Grid(gridSpace, snappingSteps.HasValue ? snappingSteps.Value : Snapping.MoveSnappingSteps); s_Snapping2D.Initialize(workGrid, s_CurrentMousePosition, handleOrigin, localToWorldMatrix); s_Snapping2D.CalculateExtents(s_StartPoints); s_MovedMouse = false; break; } case EventType.MouseDrag: { if (GUIUtility.hotControl != id) { break; } s_MovedMouse = true; if (SceneHandles.disabled || Snapping.AreAxisLocked(axes)) { break; } s_CurrentMousePosition += evt.delta; evt.Use(); if (!s_Snapping2D.DragTo(s_CurrentMousePosition, noSnapping ? SnappingMode.Never: SnappingMode.Default)) { break; } var handleInverseMatrix = UnityEditor.Handles.inverseMatrix; var pointDelta = handleInverseMatrix.MultiplyVector(s_Snapping2D.WorldSnappedDelta); if (s_StartPoints != null) { points = new Vector3[points.Length]; // if we don't, it's hard to do Undo properly for (int i = 0; i < points.Length; i++) { points[i] = SnappingUtility.Quantize(s_StartPoints[i] + pointDelta); } } //SceneView.RepaintAll(); GUI.changed = true; break; } case EventType.MouseUp: { if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) { GUIUtility.hotControl = 0; GUIUtility.keyboardControl = 0; s_StartPoints = null; evt.Use(); EditorGUIUtility.SetWantsMouseJumping(0); SceneView.RepaintAll(); if (!s_MovedMouse && selectLockingAxisOnClick) { Snapping.ActiveAxes = axes; } } break; } case EventType.Layout: { if (Tools.current == Tool.View || Tools.current == Tool.None || evt.alt) { break; } var position = handleOrigin + handleCursorOffset; var rotation = Quaternion.LookRotation(handleNormal, slideDir1); if (capFunction != null) { capFunction(id, position, rotation, handleSize, EventType.Layout); } else { UnityEditor.HandleUtility.AddControl(id, UnityEditor.HandleUtility.DistanceToCircle(position, handleSize * .5f)); } int currentFocusControl = SceneHandleUtility.focusControl; if ((currentFocusControl == id && s_PrevFocusControl != id) || (currentFocusControl != id && s_PrevFocusControl == id)) { s_PrevFocusControl = currentFocusControl; SceneView.RepaintAll(); } break; } case EventType.Repaint: { if (axes != Axes.None) { if (GUIUtility.hotControl == id) { var selectedColor = UnityEditor.Handles.selectedColor; selectedColor.a = 0.5f; using (new SceneHandles.DrawingScope(selectedColor)) HandleRendering.RenderSnapping3D(s_Snapping2D.WorldSlideGrid, s_Snapping2D.WorldSnappedExtents, s_Snapping2D.GridSnappedPosition, s_Snapping2D.SnapResult); } } if (capFunction == null) { break; } var position = handleOrigin + handleCursorOffset; var rotation = Quaternion.LookRotation(handleNormal, slideDir1); var color = SceneHandles.StateColor(SceneHandles.color, isSelected: (id == s_PrevFocusControl)); using (new SceneHandles.DrawingScope(color)) { capFunction(id, position, rotation, handleSize, EventType.Repaint); } break; } } return(points); }
public static Bounds BoundsHandle(Bounds bounds, Quaternion rotation, CapFunction sideCapFunction, CapFunction pointCapFunction, Vector3?snappingSteps = null) { var hotControl = GUIUtility.hotControl; bool isControlHot = false; for (int i = 0; i < s_BoundsControlIds.Length; i++) { s_BoundsControlIds[i] = GUIUtility.GetControlID(s_BoundsHash, FocusType.Keyboard); s_BoundsAxisHot[i] = s_BoundsControlIds[i] == hotControl; isControlHot = isControlHot || s_BoundsAxisHot[i]; } s_BoundsSlideDirs[0] = rotation * Vector3.right; s_BoundsSlideDirs[1] = rotation * Vector3.up; s_BoundsSlideDirs[2] = rotation * Vector3.forward; var min = bounds.min; var max = bounds.max; var center = bounds.center; s_BoundsValues[0] = min.x; s_BoundsValues[1] = min.y; s_BoundsValues[2] = min.z; s_BoundsValues[3] = max.x; s_BoundsValues[4] = max.y; s_BoundsValues[5] = max.z; s_BoundsVertices[0] = rotation * new Vector3(s_BoundsValues[0], s_BoundsValues[1], s_BoundsValues[2]); s_BoundsVertices[1] = rotation * new Vector3(s_BoundsValues[3], s_BoundsValues[1], s_BoundsValues[2]); s_BoundsVertices[2] = rotation * new Vector3(s_BoundsValues[3], s_BoundsValues[4], s_BoundsValues[2]); s_BoundsVertices[3] = rotation * new Vector3(s_BoundsValues[0], s_BoundsValues[4], s_BoundsValues[2]); s_BoundsVertices[4] = rotation * new Vector3(s_BoundsValues[0], s_BoundsValues[1], s_BoundsValues[5]); s_BoundsVertices[5] = rotation * new Vector3(s_BoundsValues[3], s_BoundsValues[1], s_BoundsValues[5]); s_BoundsVertices[6] = rotation * new Vector3(s_BoundsValues[3], s_BoundsValues[4], s_BoundsValues[5]); s_BoundsVertices[7] = rotation * new Vector3(s_BoundsValues[0], s_BoundsValues[4], s_BoundsValues[5]); s_BoundsSidePoint[0] = rotation * new Vector3(s_BoundsValues[0], center.y, center.z); s_BoundsSidePoint[1] = rotation * new Vector3(center.x, s_BoundsValues[1], center.z); s_BoundsSidePoint[2] = rotation * new Vector3(center.x, center.y, s_BoundsValues[2]); s_BoundsSidePoint[3] = rotation * new Vector3(s_BoundsValues[3], center.y, center.z); s_BoundsSidePoint[4] = rotation * new Vector3(center.x, s_BoundsValues[4], center.z); s_BoundsSidePoint[5] = rotation * new Vector3(center.x, center.y, s_BoundsValues[5]); // TODO: add handles in the corners of each quad on the bounds, with an offset from the vertex, to drag from there using (new SceneHandles.DrawingScope()) { var prevDisabled = SceneHandles.disabled; var isStatic = (!Tools.hidden && EditorApplication.isPlaying && GameObjectUtility.ContainsStatic(Selection.gameObjects)); for (int i = 0; i < s_BoundsAxisDisabled.Length; i++) { s_BoundsAxisDisabled[i] = isStatic || prevDisabled || Snapping.AxisLocking[i % 3] || (isControlHot && !s_BoundsAxisHot[i]); } var camera = Camera.current; var cameraLocalPos = SceneHandles.inverseMatrix.MultiplyPoint(camera.transform.position); var cameraLocalForward = SceneHandles.inverseMatrix.MultiplyVector(camera.transform.forward); var isCameraInsideBox = bounds.Contains(cameraLocalPos); var isCameraOrthographic = camera.orthographic; var boundsColor = SceneHandles.yAxisColor; var backfacedColor = new Color(boundsColor.r, boundsColor.g, boundsColor.b, boundsColor.a * SceneHandles.backfaceAlphaMultiplier); var prevGUIchanged = GUI.changed; bool haveChanged = false; var selectedAxes = Axes.None; // all sides of bounds int currentFocusControl = SceneHandleUtility.focusControl; for (int i = 0; i < s_BoundsValues.Length; i++) { var id = s_BoundsControlIds[i]; GUI.changed = false; var localPoint = s_BoundsSidePoint[i]; var handleSize = UnityEditor.HandleUtility.GetHandleSize(localPoint); var pointSize = handleSize * kPointScale; var direction = s_BoundsSlideDirs[i % 3]; var normal = (i < 3) ? -direction : direction; normal.x *= (bounds.size.x < 0) ? -1 : 1; normal.y *= (bounds.size.y < 0) ? -1 : 1; normal.z *= (bounds.size.z < 0) ? -1 : 1; if (Event.current.type == EventType.Repaint) { s_BoundsBackfaced[i] = false; if (!isCameraInsideBox) { var cosV = isCameraOrthographic ? Vector3.Dot(normal, -cameraLocalForward) : Vector3.Dot(normal, (cameraLocalPos - localPoint)); if (cosV < -0.0001f) { // TODO: do not set backfaced to true when side is infinitely thin s_BoundsBackfaced[i] = !(isControlHot && !s_BoundsAxisHot[i % 3]); } } var sideColor = (s_BoundsBackfaced[i] ? backfacedColor: boundsColor); SceneHandles.color = SceneHandles.StateColor(sideColor, s_BoundsAxisDisabled[i], (currentFocusControl == id)); if (currentFocusControl == id) { var sceneView = SceneView.currentDrawingSceneView; if (sceneView) { var rect = sceneView.position; rect.min = Vector2.zero; EditorGUIUtility.AddCursorRect(rect, SceneHandleUtility.GetCursorForDirection(localPoint, normal)); } selectedAxes = s_BoundsAxes[i]; } if (s_BoundsBackfaced[i]) { pointSize *= backfaceSizeMultiplier; } } var steps = snappingSteps ?? Snapping.MoveSnappingSteps; var newPoint = Slider1DHandle(id, (Axis)(i % 3), localPoint, normal, steps[i % 3], pointSize, sideCapFunction); if (GUI.changed) { s_BoundsValues[i] += Vector3.Dot(direction, newPoint - localPoint); haveChanged = true; } } // all edges of bounds for (int i = 0; i < s_BoundsEdgeIndices.GetLength(0); i++) { var id = GUIUtility.GetControlID(s_BoundsHash, FocusType.Keyboard); GUI.changed = false; var index1 = s_BoundsEdgeIndices[i, 0]; var index2 = s_BoundsEdgeIndices[i, 1]; var point1 = s_BoundsVertices[index1]; var point2 = s_BoundsVertices[index2]; var midPoint = (point1 + point2) * 0.5f; var offset1 = s_EdgeDirectionOffsets[i, 0]; var offset2 = s_EdgeDirectionOffsets[i, 1]; var offset3 = s_EdgeDirectionOffsets[i, 2]; var offset1_dir = offset1 % 3; var offset2_dir = offset2 % 3; if (Event.current.type == EventType.Repaint) { var highlight = (currentFocusControl == id) || (currentFocusControl == s_BoundsControlIds[offset1]) || (currentFocusControl == s_BoundsControlIds[offset2]); var edgeColor = (s_BoundsBackfaced[offset1] && s_BoundsBackfaced[offset2]) ? backfacedColor : boundsColor; var edgeDisabled = (s_BoundsAxisDisabled[offset1] && s_BoundsAxisDisabled[offset2]); SceneHandles.color = SceneHandles.StateColor(edgeColor, edgeDisabled, highlight); if (currentFocusControl == id) { selectedAxes = s_EdgeAxes[i]; } } // only use capFunction (render point) when in ortho mode & aligned with box or when side size is 0 bool isSideAlignedWithCamera = false; // TODO: determine if aligned with camera direction & in ortho mode bool showSidePoint = !isSideAlignedWithCamera && ((point2 - point1).sqrMagnitude < kShowPointThreshold); float pointSize; Vector3 offset; if (showSidePoint) { pointSize = UnityEditor.HandleUtility.GetHandleSize(midPoint) * kPointScale; offset = Edge2DHandleOffset(id, point1, point2, midPoint, s_BoundsSlideDirs[offset3], s_BoundsSlideDirs[offset1_dir], s_BoundsSlideDirs[offset2_dir], pointSize, pointCapFunction, s_EdgeAxes[i], snappingSteps: snappingSteps); } else { offset = Edge2DHandleOffset(id, point1, point2, midPoint, s_BoundsSlideDirs[offset3], s_BoundsSlideDirs[offset1_dir], s_BoundsSlideDirs[offset2_dir], 0, null, s_EdgeAxes[i], snappingSteps: snappingSteps); } if (GUI.changed) { offset = Quaternion.Inverse(rotation) * offset; if (Mathf.Abs(offset[offset1_dir]) > 0.000001f || Mathf.Abs(offset[offset2_dir]) > 0.000001f) { s_BoundsValues[offset1] += offset[offset1_dir]; s_BoundsValues[offset2] += offset[offset2_dir]; haveChanged = true; } else { GUI.changed = false; } } } GUI.changed = prevGUIchanged || haveChanged; if (haveChanged) { var size = bounds.size; center.x = (s_BoundsValues[3] + s_BoundsValues[0]) * 0.5f; size.x = (s_BoundsValues[3] - s_BoundsValues[0]); center.y = (s_BoundsValues[4] + s_BoundsValues[1]) * 0.5f; size.y = (s_BoundsValues[4] - s_BoundsValues[1]); center.z = (s_BoundsValues[5] + s_BoundsValues[2]) * 0.5f; size.z = (s_BoundsValues[5] - s_BoundsValues[2]); bounds.center = center; bounds.size = size; } // TODO: paint XZ intersection with grid plane + 'shadow' SceneHandles.disabled = prevDisabled; } return(bounds); }
internal static Vector3[] Do(int id, Axis axis, Vector3[] points, Vector3 handleOrigin, Vector3 handleDirection, Vector3 slideDirection, float snappingStep = 0, float handleSize = 0, SceneHandles.CapFunction capFunction = null, bool selectLockingAxisOnClick = false) { if (snappingStep == 0) { snappingStep = Snapping.MoveSnappingSteps[(int)axis]; } if (handleSize == 0) { handleSize = UnityEditor.HandleUtility.GetHandleSize(handleOrigin) * 0.05f; } if (handleDirection.sqrMagnitude == 0) { return(points); } var evt = Event.current; var type = evt.GetTypeForControl(id); switch (type) { case EventType.MouseDown: { if (SceneHandles.InCameraOrbitMode) { break; } if (GUIUtility.hotControl != 0) { break; } if ((UnityEditor.HandleUtility.nearestControl != id || evt.button != 0) && (GUIUtility.keyboardControl != id || evt.button != 2)) { break; } GUIUtility.hotControl = GUIUtility.keyboardControl = id; evt.Use(); EditorGUIUtility.SetWantsMouseJumping(1); s_CurrentMousePosition = evt.mousePosition; s_StartPoints = points.ToArray(); var handleMatrix = SceneHandles.matrix; s_Snapping1D.Initialize(s_CurrentMousePosition, handleMatrix.MultiplyPoint(handleOrigin), handleMatrix.MultiplyVector(slideDirection), snappingStep, axis); s_Snapping1D.CalculateExtents(SceneHandles.inverseMatrix, s_StartPoints); s_MovedMouse = false; break; } case EventType.MouseDrag: { if (GUIUtility.hotControl != id) { break; } s_MovedMouse = true; if (SceneHandles.disabled || Snapping.IsAxisLocked(axis)) { break; } s_CurrentMousePosition += evt.delta; evt.Use(); if (!s_Snapping1D.Move(s_CurrentMousePosition)) { break; } var handleInverseMatrix = SceneHandles.inverseMatrix; var pointDelta = handleInverseMatrix.MultiplyVector(s_Snapping1D.WorldSnappedOffset); if (s_StartPoints != null) { points = new Vector3[points.Length]; // if we don't, it's hard to do Undo properly for (int i = 0; i < points.Length; i++) { points[i] = SnappingUtility.Quantize(s_StartPoints[i] + pointDelta); } } //SceneView.RepaintAll(); GUI.changed = true; break; } case EventType.MouseUp: { if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) { GUIUtility.hotControl = 0; GUIUtility.keyboardControl = 0; //Grid.currentGrid = s_PrevGrid; s_StartPoints = null; evt.Use(); EditorGUIUtility.SetWantsMouseJumping(0); if (!s_MovedMouse && selectLockingAxisOnClick) { switch (axis) { case Axis.X: { Snapping.ActiveAxes = Axes.X; break; } case Axis.Y: { Snapping.ActiveAxes = Axes.Y; break; } case Axis.Z: { Snapping.ActiveAxes = Axes.Z; break; } } } SceneView.RepaintAll(); } break; } #if UNITY_2020_1_OR_NEWER case EventType.MouseMove: { if (SceneHandles.InCameraOrbitMode) { break; } var position = handleOrigin; var rotation = Quaternion.LookRotation(handleDirection); if (handleSize > 0) { if (capFunction != null) { capFunction(id, position, rotation, handleSize, type); } } int currentFocusControl = SceneHandleUtility.focusControl; if ((currentFocusControl == id && s_PrevFocusControl != id) || (currentFocusControl != id && s_PrevFocusControl == id)) { s_PrevFocusControl = currentFocusControl; SceneView.RepaintAll(); } break; } #endif case EventType.Layout: { if (SceneHandles.InCameraOrbitMode) { break; } var position = handleOrigin; var rotation = Quaternion.LookRotation(handleDirection); if (handleSize > 0) { if (capFunction != null) { capFunction(id, position, rotation, handleSize, type); } else { UnityEditor.HandleUtility.AddControl(id, UnityEditor.HandleUtility.DistanceToCircle(position, handleSize * .2f)); } } int currentFocusControl = SceneHandleUtility.focusControl; if ((currentFocusControl == id && s_PrevFocusControl != id) || (currentFocusControl != id && s_PrevFocusControl == id)) { s_PrevFocusControl = currentFocusControl; SceneView.RepaintAll(); } break; } case EventType.Repaint: { if (axis != Axis.None) { if (GUIUtility.hotControl == id) { var selectedColor = SceneHandles.StateColor(SceneHandles.MultiplyTransparency(SceneHandles.selectedColor, 0.5f)); using (new SceneHandles.DrawingScope(selectedColor)) HandleRendering.RenderSnapping1D(s_Snapping1D.Min, s_Snapping1D.Max, s_Snapping1D.WorldSnappedPosition, s_Snapping1D.SlideDirection, s_Snapping1D.SnapResult, axis); } } if (capFunction == null) { break; } var position = handleOrigin; var rotation = Quaternion.LookRotation(handleDirection); var color = SceneHandles.StateColor(SceneHandles.color, isSelected: (id == s_PrevFocusControl)); using (new SceneHandles.DrawingScope(color)) { capFunction(id, position, rotation, handleSize, EventType.Repaint); } break; } } return(points); }
public static Vector3[] PositionHandle(PositionHandleIDs handleIDs, Vector3[] points, Vector3 position, Quaternion rotation, Axes enabledAxes = Axes.XYZ) { var xAxisId = handleIDs.xAxisId; var yAxisId = handleIDs.yAxisId; var zAxisId = handleIDs.zAxisId; var xzPlaneId = handleIDs.xzPlaneId; var xyPlaneId = handleIDs.xyPlaneId; var yzPlaneId = handleIDs.yzPlaneId; var centerId = handleIDs.centerId; var isStatic = (!Tools.hidden && EditorApplication.isPlaying && GameObjectUtility.ContainsStatic(Selection.gameObjects)); var prevDisabled = SceneHandles.disabled; var hotControl = GUIUtility.hotControl; var xAxisIsHot = (xAxisId == hotControl); var yAxisIsHot = (yAxisId == hotControl); var zAxisIsHot = (zAxisId == hotControl); var xzAxisIsHot = (xzPlaneId == hotControl); var xyAxisIsHot = (xyPlaneId == hotControl); var yzAxisIsHot = (yzPlaneId == hotControl); var centerIsHot = (centerId == hotControl); var isControlHot = xAxisIsHot || yAxisIsHot || zAxisIsHot || xzAxisIsHot || xyAxisIsHot || yzAxisIsHot || centerIsHot; var handleSize = UnityEditor.HandleUtility.GetHandleSize(position); var originalColor = SceneHandles.color; var activeAxes = Snapping.ActiveAxes; UnityEditor.HandleUtility.AddControl(centerId, UnityEditor.HandleUtility.DistanceToCircle(position, handleSize * 0.055f)); var evt = Event.current; var type = evt.GetTypeForControl(centerId); switch (type) { case EventType.MouseDown: { if (GUIUtility.hotControl != 0) { break; } if ((UnityEditor.HandleUtility.nearestControl != centerId || evt.button != 0) && (GUIUtility.keyboardControl != centerId || evt.button != 2)) { break; } GUIUtility.hotControl = GUIUtility.keyboardControl = centerId; evt.Use(); EditorGUIUtility.SetWantsMouseJumping(1); break; } case EventType.MouseDrag: { if (GUIUtility.hotControl != centerId) { break; } break; } case EventType.MouseUp: { if (GUIUtility.hotControl == centerId && (evt.button == 0 || evt.button == 2)) { GUIUtility.hotControl = 0; GUIUtility.keyboardControl = 0; evt.Use(); Snapping.ActiveAxes = Axes.XYZ; EditorGUIUtility.SetWantsMouseJumping(0); SceneView.RepaintAll(); } break; } } //,.,.., look at 2018.1 how the position handle works w/ colors var xAxisActive = !Snapping.AxisLocking[0]; var yAxisActive = !Snapping.AxisLocking[1]; var zAxisActive = !Snapping.AxisLocking[2]; var xzPlaneActive = xAxisActive && zAxisActive; var xyPlaneActive = xAxisActive && yAxisActive; var yzPlaneActive = yAxisActive && zAxisActive; var xAxisDisabled = isStatic || prevDisabled || ((enabledAxes & Axes.X) == 0) || !xAxisActive || (isControlHot && !xAxisIsHot && !xzAxisIsHot && !xyAxisIsHot); var yAxisDisabled = isStatic || prevDisabled || ((enabledAxes & Axes.Y) == 0) || !yAxisActive || (isControlHot && !yAxisIsHot && !xyAxisIsHot && !yzAxisIsHot); var zAxisDisabled = isStatic || prevDisabled || ((enabledAxes & Axes.Z) == 0) || !zAxisActive || (isControlHot && !zAxisIsHot && !xzAxisIsHot && !yzAxisIsHot); var xzPlaneDisabled = isStatic || prevDisabled || ((enabledAxes & Axes.XZ) != Axes.XZ) || !xzPlaneActive || (isControlHot && !xzAxisIsHot); var xyPlaneDisabled = isStatic || prevDisabled || ((enabledAxes & Axes.XY) != Axes.XY) || !xyPlaneActive || (isControlHot && !xyAxisIsHot); var yzPlaneDisabled = isStatic || prevDisabled || ((enabledAxes & Axes.YZ) != Axes.YZ) || !yzPlaneActive || (isControlHot && !yzAxisIsHot); var currentFocusControl = SceneHandleUtility.focusControl; var xAxisIndirectlyFocused = (currentFocusControl == xyPlaneId || currentFocusControl == xzPlaneId); var yAxisIndirectlyFocused = (currentFocusControl == xyPlaneId || currentFocusControl == yzPlaneId); var zAxisIndirectlyFocused = (currentFocusControl == xzPlaneId || currentFocusControl == yzPlaneId); var xAxisIndirectlyActive = activeAxes == Axes.XY || activeAxes == Axes.XZ; var yAxisIndirectlyActive = activeAxes == Axes.XY || activeAxes == Axes.YZ; var zAxisIndirectlyActive = activeAxes == Axes.XZ || activeAxes == Axes.YZ; var xAxisSelected = xAxisIndirectlyFocused || xAxisIndirectlyActive || activeAxes == Axes.X; var yAxisSelected = yAxisIndirectlyFocused || yAxisIndirectlyActive || activeAxes == Axes.Y; var zAxisSelected = zAxisIndirectlyFocused || zAxisIndirectlyActive || activeAxes == Axes.Z; var xzAxiSelected = activeAxes == Axes.XZ; var xyAxiSelected = activeAxes == Axes.XZ; var yzAxiSelected = activeAxes == Axes.YZ; var xAxisColor = SceneHandles.StateColor(SceneHandles.xAxisColor, xAxisDisabled, xAxisSelected); var yAxisColor = SceneHandles.StateColor(SceneHandles.yAxisColor, yAxisDisabled, yAxisSelected); var zAxisColor = SceneHandles.StateColor(SceneHandles.zAxisColor, zAxisDisabled, zAxisSelected); var xzPlaneColor = SceneHandles.StateColor(SceneHandles.yAxisColor, xzPlaneDisabled, xzAxiSelected); var xyPlaneColor = SceneHandles.StateColor(SceneHandles.zAxisColor, xyPlaneDisabled, xyAxiSelected); var yzPlaneColor = SceneHandles.StateColor(SceneHandles.xAxisColor, yzPlaneDisabled, yzAxiSelected); if (xAxisActive) { SceneHandles.disabled = xAxisDisabled; SceneHandles.color = xAxisColor; points = Slider1DHandle(xAxisId, Axis.X, points, position, rotation * Vector3.right, Snapping.MoveSnappingSteps.x, handleSize, ArrowHandleCap, selectLockingAxisOnClick: true); } if (yAxisActive) { SceneHandles.disabled = yAxisDisabled; SceneHandles.color = yAxisColor; points = Slider1DHandle(yAxisId, Axis.Y, points, position, rotation * Vector3.up, Snapping.MoveSnappingSteps.y, handleSize, ArrowHandleCap, selectLockingAxisOnClick: true); } if (zAxisActive) { SceneHandles.disabled = zAxisDisabled; SceneHandles.color = zAxisColor; points = Slider1DHandle(zAxisId, Axis.Z, points, position, rotation * Vector3.forward, Snapping.MoveSnappingSteps.z, handleSize, ArrowHandleCap, selectLockingAxisOnClick: true); } if (xzPlaneActive) { SceneHandles.disabled = xzPlaneDisabled; SceneHandles.color = xzPlaneColor; points = PlanarHandle(xzPlaneId, PlaneAxes.XZ, points, position, rotation, handleSize * 0.3f, selectLockingAxisOnClick: true); } if (xyPlaneActive) { SceneHandles.disabled = xyPlaneDisabled; SceneHandles.color = xyPlaneColor; points = PlanarHandle(xyPlaneId, PlaneAxes.XY, points, position, rotation, handleSize * 0.3f, selectLockingAxisOnClick: true); } if (yzPlaneActive) { SceneHandles.disabled = yzPlaneDisabled; SceneHandles.color = yzPlaneColor; points = PlanarHandle(yzPlaneId, PlaneAxes.YZ, points, position, rotation, handleSize * 0.3f, selectLockingAxisOnClick: true); } switch (type) { case EventType.Repaint: { SceneHandles.color = SceneHandles.StateColor(SceneHandles.centerColor, false, centerId == SceneHandleUtility.focusControl); SceneHandles.RenderBorderedCircle(position, handleSize * 0.05f); break; } } SceneHandles.disabled = prevDisabled; SceneHandles.color = originalColor; return(points); }
public static Vector3 RadiusHandle(Vector3 center, Vector3 up, Vector3 radius) { var isStatic = (!Tools.hidden && EditorApplication.isPlaying && GameObjectUtility.ContainsStatic(Selection.gameObjects)); var prevDisabled = SceneHandles.disabled; var prevColor = SceneHandles.color; var prevChanged = GUI.changed; var delta1 = radius - center; var delta2 = Quaternion.AngleAxis(90, up) * delta1; var position0 = center + delta1; var position1 = center - delta1; var position2 = center + delta2; var position3 = center - delta2; float size; Vector3 forward; Vector3 right; GeometryUtility.CalculateTangents(up, out right, out forward); var isDisabled = isStatic || prevDisabled; SceneHandles.color = SceneHandles.StateColor(prevColor, isDisabled, false); GUI.changed = false; size = UnityEditor.HandleUtility.GetHandleSize(position0); position0 = Slider2DHandle(position0, Vector3.zero, up, forward, right, size * 0.05f, OutlinedDotHandleCap); if (GUI.changed) { radius = position0; prevChanged = true; } GUI.changed = false; size = UnityEditor.HandleUtility.GetHandleSize(position1); position1 = Slider2DHandle(position1, Vector3.zero, up, forward, right, size * 0.05f, OutlinedDotHandleCap); if (GUI.changed) { radius = center - (position1 - center); prevChanged = true; } GUI.changed = false; size = UnityEditor.HandleUtility.GetHandleSize(position2); position2 = Slider2DHandle(position2, Vector3.zero, up, forward, right, size * 0.05f, OutlinedDotHandleCap); if (GUI.changed) { radius = center + (Quaternion.AngleAxis(-90, up) * (position2 - center)); prevChanged = true; } GUI.changed = false; size = UnityEditor.HandleUtility.GetHandleSize(position3); position3 = Slider2DHandle(position3, Vector3.zero, up, forward, right, size * 0.05f, OutlinedDotHandleCap); if (GUI.changed) { radius = center - (Quaternion.AngleAxis(-90, up) * (position3 - center)); prevChanged = true; } GUI.changed |= prevChanged; isDisabled = isStatic || prevDisabled || (Snapping.AxisLocking[0] && Snapping.AxisLocking[1]); SceneHandles.color = SceneHandles.StateColor(prevColor, isDisabled, false); float radiusMagnitude = delta1.magnitude; if (radiusMagnitude > 0) { SceneHandles.DrawWireDisc(center, up, radiusMagnitude); } SceneHandles.disabled = prevDisabled; SceneHandles.color = prevColor; return(radius); }
public static void RadiusHandle(Vector3 center, Vector3 up, ref Vector3 radius1, ref Vector3 radius2) { var isStatic = (!Tools.hidden && EditorApplication.isPlaying && GameObjectUtility.ContainsStatic(Selection.gameObjects)); var prevColor = SceneHandles.color; var prevMatrix = SceneHandles.matrix; var prevDisabled = SceneHandles.disabled; var prevChanged = GUI.changed; var delta1 = radius1 - center; var delta2 = radius2 - center; var position0 = center + delta1; var position1 = center - delta1; var position2 = center + delta2; var position3 = center - delta2; float size; Vector3 forward; Vector3 right; GeometryUtility.CalculateTangents(up, out right, out forward); var isDisabled = isStatic || prevDisabled; SceneHandles.color = SceneHandles.StateColor(prevColor, isDisabled, false); GUI.changed = false; size = UnityEditor.HandleUtility.GetHandleSize(position0); position0 = Slider2DHandle(position0, Vector3.zero, up, forward, right, size * 0.05f, OutlinedDotHandleCap); if (GUI.changed) { radius1 = position0; radius2 = center + (Quaternion.AngleAxis(-90, up) * ((radius1 - center).normalized * (radius2 - center).magnitude)); prevChanged = true; } GUI.changed = false; size = UnityEditor.HandleUtility.GetHandleSize(position1); position1 = Slider2DHandle(position1, Vector3.zero, up, forward, right, size * 0.05f, OutlinedDotHandleCap); if (GUI.changed) { radius1 = center - (position1 - center); radius2 = center + (Quaternion.AngleAxis(-90, up) * ((radius1 - center).normalized * (radius2 - center).magnitude)); prevChanged = true; } GUI.changed = false; size = UnityEditor.HandleUtility.GetHandleSize(position2); position2 = Slider2DHandle(position2, Vector3.zero, up, forward, right, size * 0.05f, OutlinedDotHandleCap); if (GUI.changed) { radius2 = center + (position2 - center); radius1 = center + (Quaternion.AngleAxis(-90, up) * ((radius2 - center).normalized * (radius1 - center).magnitude)); prevChanged = true; } GUI.changed = false; size = UnityEditor.HandleUtility.GetHandleSize(position3); position3 = Slider2DHandle(position3, Vector3.zero, up, forward, right, size * 0.05f, OutlinedDotHandleCap); if (GUI.changed) { radius2 = center - (position3 - center); radius1 = center + (Quaternion.AngleAxis(-90, up) * ((radius2 - center).normalized * (radius1 - center).magnitude)); prevChanged = true; } GUI.changed |= prevChanged; isDisabled = isStatic || prevDisabled || (Snapping.AxisLocking[0] && Snapping.AxisLocking[1]); SceneHandles.color = SceneHandles.StateColor(prevColor, isDisabled, false); float radiusMagnitude1 = delta1.magnitude; float radiusMagnitude2 = delta2.magnitude; if (radiusMagnitude1 > 0 && radiusMagnitude2 > 0) { var ellipsis = Matrix4x4.TRS(center, Quaternion.identity, Vector3.one); ellipsis.m00 = delta1.x; ellipsis.m10 = delta1.y; ellipsis.m20 = delta1.z; ellipsis.m01 = delta2.x; ellipsis.m11 = delta2.y; ellipsis.m21 = delta2.z; ellipsis.m02 = up.x; ellipsis.m12 = up.y; ellipsis.m22 = up.z; ellipsis *= Matrix4x4.TRS(-center, Quaternion.identity, Vector3.one); var newMatrix = prevMatrix * ellipsis; SceneHandles.matrix = newMatrix; SceneHandles.DrawWireDisc(center, up, 1.0f); } SceneHandles.disabled = prevDisabled; SceneHandles.matrix = prevMatrix; SceneHandles.color = prevColor; }
public static Vector3 Radius2DHandle(Vector3 center, Vector3 up, Vector3 radius, float minRadius = 0, float maxRadius = float.PositiveInfinity, bool renderDisc = true) { minRadius = Mathf.Abs(minRadius); maxRadius = Mathf.Abs(maxRadius); if (maxRadius < minRadius) { maxRadius = minRadius; } var isStatic = (!Tools.hidden && EditorApplication.isPlaying && GameObjectUtility.ContainsStatic(Selection.gameObjects)); var prevDisabled = SceneHandles.disabled; var prevColor = SceneHandles.color; var prevChanged = GUI.changed; var hasChanged = false; var plane = new Plane(up, Vector3.zero); var delta1 = GeometryUtility.ProjectPointPlane(radius - center, plane); var delta2 = Quaternion.AngleAxis(90, up) * delta1; var position0 = center + delta1; var position1 = center - delta1; var position2 = center + delta2; var position3 = center - delta2; float size; Vector3 forward; Vector3 right; GeometryUtility.CalculateTangents(up, out right, out forward); bool noRotation = Event.current.shift; var isDisabled = isStatic || prevDisabled; SceneHandles.color = SceneHandles.StateColor(prevColor, isDisabled, false); Vector3 moveDelta = Vector3.zero; GUI.changed = false; size = UnityEditor.HandleUtility.GetHandleSize(position0); position0 = Slider2DHandle(position0, Vector3.zero, up, forward, right, size * 0.05f, OutlinedDotHandleCap); if (GUI.changed) { moveDelta = position0 - center; hasChanged = true; } GUI.changed = false; size = UnityEditor.HandleUtility.GetHandleSize(position1); position1 = Slider2DHandle(position1, Vector3.zero, up, forward, right, size * 0.05f, OutlinedDotHandleCap); if (GUI.changed) { moveDelta = -(position1 - center); hasChanged = true; } GUI.changed = false; size = UnityEditor.HandleUtility.GetHandleSize(position2); position2 = Slider2DHandle(position2, Vector3.zero, up, forward, right, size * 0.05f, OutlinedDotHandleCap); if (GUI.changed) { moveDelta = (Quaternion.AngleAxis(-90, up) * (position2 - center)); hasChanged = true; } GUI.changed = false; size = UnityEditor.HandleUtility.GetHandleSize(position3); position3 = Slider2DHandle(position3, Vector3.zero, up, forward, right, size * 0.05f, OutlinedDotHandleCap); if (GUI.changed) { moveDelta = -(Quaternion.AngleAxis(-90, up) * (position3 - center)); hasChanged = true; } if (hasChanged) { Vector3 prevRadius = radius; var newRadius = center + moveDelta; var newDelta = GeometryUtility.ProjectPointPlane((newRadius - center), plane); var length = newDelta.magnitude; if (length < minRadius || length > maxRadius) { var direction = (length > Vector3.kEpsilon) ? newDelta.normalized : ((delta1.magnitude > Vector3.kEpsilon) ? delta1.normalized : Vector3.up); length = Mathf.Max(minRadius, Mathf.Min(length, maxRadius)); radius = center + (length * direction); } else { radius = newRadius; } if (noRotation) { var magnitude = newRadius.magnitude; radius = prevRadius.normalized * magnitude; } } GUI.changed |= prevChanged | hasChanged; isDisabled = isStatic || prevDisabled || (Snapping.AxisLocking[0] && Snapping.AxisLocking[1]); SceneHandles.color = SceneHandles.StateColor(prevColor, isDisabled, false); float radiusMagnitude = delta1.magnitude; if (radiusMagnitude > 0 && renderDisc) { SceneHandles.DrawWireDisc(center, up, radiusMagnitude); } SceneHandles.disabled = prevDisabled; SceneHandles.color = prevColor; return(radius); }
public static bool Radius2DHandle(Vector3 center, Vector3 up, ref Vector3 radius1, ref Vector3 radius2, float minRadius1 = 0, float minRadius2 = 0, float maxRadius1 = float.PositiveInfinity, float maxRadius2 = float.PositiveInfinity, bool renderDisc = true) { var positionId0 = GUIUtility.GetControlID(s_Radius2DHash, FocusType.Keyboard); var positionId1 = GUIUtility.GetControlID(s_Radius2DHash, FocusType.Keyboard); var positionId2 = GUIUtility.GetControlID(s_Radius2DHash, FocusType.Keyboard); var positionId3 = GUIUtility.GetControlID(s_Radius2DHash, FocusType.Keyboard); minRadius1 = Mathf.Abs(minRadius1); minRadius2 = Mathf.Abs(minRadius2); maxRadius1 = Mathf.Abs(maxRadius1); if (maxRadius1 < minRadius1) { maxRadius1 = minRadius1; } maxRadius2 = Mathf.Abs(maxRadius2); if (maxRadius2 < minRadius2) { maxRadius2 = minRadius2; } var isStatic = (!Tools.hidden && EditorApplication.isPlaying && GameObjectUtility.ContainsStatic(Selection.gameObjects)); var prevColor = SceneHandles.color; var prevMatrix = SceneHandles.matrix; var prevDisabled = SceneHandles.disabled; var prevChanged = GUI.changed; float size; Vector3 forward; Vector3 right; GeometryUtility.CalculateTangents(up, out right, out forward); var plane = new Plane(up, Vector3.zero); var delta1 = GeometryUtility.ProjectPointPlane(radius1 - center, plane); var delta2 = GeometryUtility.ProjectPointPlane(radius2 - center, plane); var delta1Magnitude = delta1.magnitude; var delta2Magnitude = delta2.magnitude; var delta1Normalized = (delta1Magnitude < Vector3.kEpsilon) ? Vector3.zero : (delta1 / delta1Magnitude); var delta2Normalized = (delta2Magnitude < Vector3.kEpsilon) ? Vector3.zero : (delta2 / delta2Magnitude); // useful to have when modifying the 'other' one var rotatedDelta1 = Quaternion.AngleAxis(-90, up) * delta1Normalized; var rotatedDelta2 = Quaternion.AngleAxis(90, up) * delta2Normalized; var position0 = center + delta1; var position1 = center - delta1; var position2 = center + delta2; var position3 = center - delta2; var isDisabled = isStatic || prevDisabled; SceneHandles.color = SceneHandles.StateColor(prevColor, isDisabled, false); bool noRotation = Event.current.shift; GUI.changed = false; size = UnityEditor.HandleUtility.GetHandleSize(position0); position0 = Slider2DHandle(positionId0, position0, Vector3.zero, up, forward, right, size * 0.05f, OutlinedDotHandleCap); if (GUI.changed) { var moveDelta = (position0 - center); Vector3 newRadius; if (noRotation) { newRadius = GeometryUtility.ProjectPointRay(center + moveDelta, center, rotatedDelta2); } else { newRadius = center + moveDelta; } var newDelta = GeometryUtility.ProjectPointPlane(newRadius - center, plane); delta1Magnitude = newDelta.magnitude; if (!noRotation && delta1Magnitude > Vector3.kEpsilon) { radius2 = center + ((Quaternion.AngleAxis(-90, up) * (newDelta / delta1Magnitude)) * delta2Magnitude); } // set this after setting radius2 since both may lead to same variable delta1 = newDelta; radius1 = newRadius; prevChanged = true; } GUI.changed = false; size = UnityEditor.HandleUtility.GetHandleSize(position1); position1 = Slider2DHandle(positionId1, position1, Vector3.zero, up, forward, right, size * 0.05f, OutlinedDotHandleCap); if (GUI.changed) { var moveDelta = (position1 - center); Vector3 newRadius; if (noRotation) { newRadius = GeometryUtility.ProjectPointRay(center - moveDelta, center, rotatedDelta2); } else { newRadius = center - moveDelta; } var newDelta = GeometryUtility.ProjectPointPlane(newRadius - center, plane); delta1Magnitude = newDelta.magnitude; if (!noRotation && delta1Magnitude > Vector3.kEpsilon) { radius2 = center + ((Quaternion.AngleAxis(-90, up) * (newDelta / delta1Magnitude)) * delta2Magnitude); } // set this after setting radius2 since both may lead to same variable delta1 = newDelta; radius1 = newRadius; prevChanged = true; } GUI.changed = false; size = UnityEditor.HandleUtility.GetHandleSize(position2); position2 = Slider2DHandle(positionId2, position2, Vector3.zero, up, forward, right, size * 0.05f, OutlinedDotHandleCap); if (GUI.changed) { var moveDelta = (position2 - center); Vector3 newRadius; if (noRotation) { newRadius = GeometryUtility.ProjectPointRay(center + moveDelta, center, rotatedDelta1); } else { newRadius = center + moveDelta; } var newDelta = GeometryUtility.ProjectPointPlane(newRadius - center, plane); delta2Magnitude = newDelta.magnitude; if (!noRotation && delta2Magnitude > Vector3.kEpsilon) { radius1 = center + ((Quaternion.AngleAxis(90, up) * (newDelta / delta2Magnitude)) * delta1Magnitude); } // set this after setting radius1 since both may lead to same variable delta2 = newDelta; radius2 = newRadius; prevChanged = true; } GUI.changed = false; size = UnityEditor.HandleUtility.GetHandleSize(position3); position3 = Slider2DHandle(positionId3, position3, Vector3.zero, up, forward, right, size * 0.05f, OutlinedDotHandleCap); if (GUI.changed) { var moveDelta = (position3 - center); Vector3 newRadius; if (noRotation) { newRadius = GeometryUtility.ProjectPointRay(center - moveDelta, center, rotatedDelta1); } else { newRadius = center - moveDelta; } var newDelta = GeometryUtility.ProjectPointPlane(newRadius - center, plane); delta2Magnitude = newDelta.magnitude; if (!noRotation && delta2Magnitude > Vector3.kEpsilon) { radius1 = center + ((Quaternion.AngleAxis(90, up) * (newDelta / delta2Magnitude)) * delta1Magnitude); } // set this after setting radius1 since both may lead to same variable delta2 = newDelta; radius2 = newRadius; prevChanged = true; } GUI.changed |= prevChanged; if (delta1Magnitude < minRadius1 || delta1Magnitude > maxRadius1) { if (delta2Magnitude < minRadius2 || delta2Magnitude > maxRadius2) { delta1Magnitude = Mathf.Max(minRadius1, Mathf.Min(delta1Magnitude, maxRadius1)); delta2Magnitude = Mathf.Max(minRadius2, Mathf.Min(delta2Magnitude, maxRadius2)); delta1Normalized = right; delta2Normalized = up; delta1 = GeometryUtility.ProjectPointPlane(delta1Normalized * delta1Magnitude, plane); delta2 = GeometryUtility.ProjectPointPlane(delta2Normalized * delta2Magnitude, plane); rotatedDelta2 = delta2Normalized; rotatedDelta1 = delta1Normalized; radius1 = center + delta1; radius2 = center + delta2; GUI.changed = true; } else { delta1Magnitude = Mathf.Max(minRadius1, Mathf.Min(delta1Magnitude, maxRadius1)); delta1Normalized = rotatedDelta2; delta1 = GeometryUtility.ProjectPointPlane(delta1Normalized * delta1Magnitude, plane); radius1 = center + delta1; GUI.changed = true; } } else if (delta2Magnitude < minRadius2 || delta2Magnitude > maxRadius2) { delta2Magnitude = Mathf.Max(minRadius2, Mathf.Min(delta2Magnitude, maxRadius2)); delta2Normalized = rotatedDelta1; delta2 = delta2Normalized * delta2Magnitude; radius2 = center + delta2; GUI.changed = true; } if (Event.current.type == EventType.Repaint) { isDisabled = isStatic || prevDisabled || (Snapping.AxisLocking[0] && Snapping.AxisLocking[1]); SceneHandles.color = SceneHandles.StateColor(prevColor, isDisabled, false); if (delta1Magnitude > Vector3.kEpsilon && delta2Magnitude > Vector3.kEpsilon) { var ellipsis = Matrix4x4.TRS(center, Quaternion.identity, Vector3.one); ellipsis.m00 = delta1.x; ellipsis.m10 = delta1.y; ellipsis.m20 = delta1.z; ellipsis.m01 = delta2.x; ellipsis.m11 = delta2.y; ellipsis.m21 = delta2.z; ellipsis.m02 = up.x; ellipsis.m12 = up.y; ellipsis.m22 = up.z; ellipsis *= Matrix4x4.TRS(-center, Quaternion.identity, Vector3.one); var newMatrix = prevMatrix * ellipsis; SceneHandles.matrix = newMatrix; if (renderDisc) { SceneHandles.DrawWireDisc(center, Vector3.forward, 1.0f); } } else if (delta1Magnitude > Vector3.kEpsilon) { SceneHandles.DrawLine(position0, position1); } else if (delta2Magnitude > Vector3.kEpsilon) { SceneHandles.DrawLine(position2, position3); } } SceneHandles.disabled = prevDisabled; SceneHandles.matrix = prevMatrix; SceneHandles.color = prevColor; var focus = SceneHandleUtility.focusControl; return((focus == positionId0) || (focus == positionId1) || (focus == positionId2) || (focus == positionId3)); }
public static Rect RectHandle(Rect rect, CapFunction capFunction) { var handlesMatrix = SceneHandles.matrix; var direction = Vector3.forward; var slideDirX = Vector3.right; var slideDirY = Vector3.up; var point1Id = GUIUtility.GetControlID(s_RectHash0, FocusType.Keyboard); var point2Id = GUIUtility.GetControlID(s_RectHash1, FocusType.Keyboard); var point3Id = GUIUtility.GetControlID(s_RectHash2, FocusType.Keyboard); var point4Id = GUIUtility.GetControlID(s_RectHash3, FocusType.Keyboard); var edge1Id = GUIUtility.GetControlID(s_RectHash4, FocusType.Keyboard); var edge2Id = GUIUtility.GetControlID(s_RectHash5, FocusType.Keyboard); var edge3Id = GUIUtility.GetControlID(s_RectHash6, FocusType.Keyboard); var edge4Id = GUIUtility.GetControlID(s_RectHash7, FocusType.Keyboard); int currentFocusControl = SceneHandleUtility.focusControl; bool highlightEdge1 = (currentFocusControl == edge1Id) || (currentFocusControl == point1Id) || (currentFocusControl == point2Id); bool highlightEdge2 = (currentFocusControl == edge2Id) || (currentFocusControl == point3Id) || (currentFocusControl == point4Id); bool highlightEdge3 = (currentFocusControl == edge3Id) || (currentFocusControl == point2Id) || (currentFocusControl == point3Id); bool highlightEdge4 = (currentFocusControl == edge4Id) || (currentFocusControl == point4Id) || (currentFocusControl == point1Id); var selectedAxes = ((highlightEdge3 || highlightEdge4) ? Axes.X : Axes.None) | ((highlightEdge1 || highlightEdge2) ? Axes.Y : Axes.None); var xMin = rect.xMin; var xMax = rect.xMax; var yMin = rect.yMin; var yMax = rect.yMax; var point1 = new Vector3(xMin, yMin, 0); var point2 = new Vector3(xMax, yMin, 0); var point3 = new Vector3(xMax, yMax, 0); var point4 = new Vector3(xMin, yMax, 0); var isStatic = (!Tools.hidden && EditorApplication.isPlaying && GameObjectUtility.ContainsStatic(Selection.gameObjects)); var prevDisabled = SceneHandles.disabled; var prevColor = SceneHandles.color; var xAxisDisabled = isStatic || prevDisabled || Snapping.AxisLocking[0]; var yAxisDisabled = isStatic || prevDisabled || Snapping.AxisLocking[1]; var xyAxiDisabled = xAxisDisabled && yAxisDisabled; Vector3 position, offset; var prevGUIchanged = GUI.changed; SceneHandles.disabled = yAxisDisabled; { GUI.changed = false; position = (point1 + point2) * 0.5f; SceneHandles.color = SceneHandles.StateColor(SceneHandles.yAxisColor, xAxisDisabled, highlightEdge1); offset = Edge1DHandleOffset(edge1Id, Axis.Y, point1, point2, position, slideDirY, Snapping.MoveSnappingSteps.y, UnityEditor.HandleUtility.GetHandleSize(position) * 0.05f, null); if (GUI.changed) { yMin += offset.y; prevGUIchanged = true; } GUI.changed = false; position = (point3 + point4) * 0.5f; SceneHandles.color = SceneHandles.StateColor(SceneHandles.yAxisColor, xAxisDisabled, highlightEdge2); offset = Edge1DHandleOffset(edge2Id, Axis.Y, point3, point4, position, slideDirY, Snapping.MoveSnappingSteps.y, UnityEditor.HandleUtility.GetHandleSize(position) * 0.05f, null); if (GUI.changed) { yMax += offset.y; prevGUIchanged = true; } } SceneHandles.disabled = xAxisDisabled; { GUI.changed = false; position = (point2 + point3) * 0.5f; SceneHandles.color = SceneHandles.StateColor(SceneHandles.yAxisColor, xAxisDisabled, highlightEdge3); offset = Edge1DHandleOffset(edge3Id, Axis.X, point2, point3, position, slideDirX, Snapping.MoveSnappingSteps.x, UnityEditor.HandleUtility.GetHandleSize(position) * 0.05f, null); if (GUI.changed) { xMax += offset.x; prevGUIchanged = true; } GUI.changed = false; position = (point4 + point1) * 0.5f; SceneHandles.color = SceneHandles.StateColor(SceneHandles.yAxisColor, xAxisDisabled, highlightEdge4); offset = Edge1DHandleOffset(edge4Id, Axis.X, point4, point1, position, slideDirX, Snapping.MoveSnappingSteps.x, UnityEditor.HandleUtility.GetHandleSize(position) * 0.05f, null); if (GUI.changed) { xMin += offset.x; prevGUIchanged = true; } } SceneHandles.disabled = xyAxiDisabled; SceneHandles.color = SceneHandles.StateColor(SceneHandles.yAxisColor, xyAxiDisabled, false); { GUI.changed = false; point1 = Slider2DHandle(point1Id, point1, Vector3.zero, direction, slideDirX, slideDirY, UnityEditor.HandleUtility.GetHandleSize(point1) * 0.05f, capFunction, Axes.XZ); if (GUI.changed) { xMin = point1.x; yMin = point1.y; prevGUIchanged = true; } GUI.changed = false; point2 = Slider2DHandle(point2Id, point2, Vector3.zero, direction, slideDirX, slideDirY, UnityEditor.HandleUtility.GetHandleSize(point2) * 0.05f, capFunction, Axes.XZ); if (GUI.changed) { xMax = point2.x; yMin = point2.y; prevGUIchanged = true; } GUI.changed = false; point3 = Slider2DHandle(point3Id, point3, Vector3.zero, direction, slideDirX, slideDirY, UnityEditor.HandleUtility.GetHandleSize(point3) * 0.05f, capFunction, Axes.XZ); if (GUI.changed) { xMax = point3.x; yMax = point3.y; prevGUIchanged = true; } GUI.changed = false; point4 = Slider2DHandle(point4Id, point4, Vector3.zero, direction, slideDirX, slideDirY, UnityEditor.HandleUtility.GetHandleSize(point4) * 0.05f, capFunction, Axes.XZ); if (GUI.changed) { xMin = point4.x; yMax = point4.y; prevGUIchanged = true; } } GUI.changed = prevGUIchanged; rect.x = xMin; rect.width = xMax - xMin; rect.y = yMin; rect.height = yMax - yMin; SceneHandles.disabled = prevDisabled; SceneHandles.color = prevColor; return(rect); }
public static void DrawAngle(UnityEngine.Vector3 center, UnityEngine.Vector3 direction, UnityEngine.Vector3 axis, float angle) { var rotation = UnityEngine.Quaternion.AngleAxis(angle, axis); var centerSize = UnityEditor.HandleUtility.GetHandleSize(center); var maxSize = direction.magnitude; var xdir = direction / maxSize; //var ydir = UnityEngine.Vector3.Cross(xdir, axis); var handleSize = Mathf.Min(centerSize, maxSize); var drawAngle = UnityEngine.Mathf.Clamp(angle, -360, 360); var realLength = Mathf.Max(1, Mathf.CeilToInt((anglePoints.Length / 360.0f) * Mathf.Abs(drawAngle))); var pointSize = centerSize * 0.04f; SceneHandles.color = SceneHandles.StateColor(SceneHandles.measureColor); SceneHandles.DrawAAPolyLine(center + (xdir * pointSize), center + direction); SceneHandles.DrawAAPolyLine(center + (rotation * (xdir * pointSize)), center + (rotation * direction)); SceneHandles.DrawWireDisc(center, Vector3.forward, pointSize); direction = xdir * handleSize; if (UnityEngine.Mathf.Abs(angle) > 0.0f) { var angleStep = drawAngle / realLength; var curAngle = 0.0f; for (int i = 0; i < realLength; i++) { anglePoints[i] = center + (UnityEngine.Quaternion.AngleAxis(curAngle, axis) * direction); curAngle += angleStep; } SceneHandles.DrawDottedLines(anglePoints.Take(realLength).ToArray(), 4.0f); rotation = UnityEngine.Quaternion.AngleAxis(angle, axis); var right = rotation * Vector3.right; var endPoint = center + (rotation * direction); var arrowSize = handleSize * 0.2f; // UnityEditor.HandleUtility.GetHandleSize(endPoint) * 0.2f; if (angle < 0.0f) { DrawFlatArrow(endPoint, -right, arrowSize); } else { DrawFlatArrow(endPoint, right, arrowSize); } } Vector3 facing; Vector3 position; if (handleSize == maxSize) { facing = rotation * xdir; position = center + (facing * handleSize); } else { var halfRotation = UnityEngine.Quaternion.AngleAxis(drawAngle / 2.0f, axis); facing = halfRotation * xdir; position = center; } DrawLabel(position, facing, 5, angle + "°"); }
public static void DrawLengths(Bounds bounds, Axes activeAxes = Axes.XYZ, Axes visibleAxes = Axes.XYZ, Axes selectedAxes = Axes.None) { // TODO: what if camera is inside of bounds? // TODO: what if length is outside of camera, but other option is inside of camera view? // TODO: don't make the side lines move around when resizing, be smarter about handlesize // -> maybe limit the projected line to the screen? var invMatrix = SceneHandles.inverseMatrix; var prevColor = SceneHandles.color; var color = prevColor; var color2 = color; color2.a *= 0.5f; var camera = UnityEngine.Camera.current; var camPos = invMatrix.MultiplyPoint(camera.transform.position); var lengthX = bounds.size.x; var lengthY = bounds.size.y; var lengthZ = bounds.size.z; var absLengthX = Mathf.Abs(lengthX); var absLengthY = Mathf.Abs(lengthY); var absLengthZ = Mathf.Abs(lengthZ); var delta = (bounds.center - camPos) * 2; var dotX = delta.x < 0 ? -1 : 1; var dotY = delta.y < 0 ? -1 : 1; var dotZ = delta.z < 0 ? -1 : 1; var insideX = (delta.x >= -absLengthX && delta.x <= absLengthX); var insideY = (delta.y >= -absLengthY && delta.y <= absLengthY); var insideZ = (delta.z >= -absLengthZ && delta.z <= absLengthZ); bool showX = !(insideY && insideZ); bool showY = !(insideX && insideZ); bool showZ = !(insideX && insideY); Vector3 fromX, toX; Vector3 fromY, toY; Vector3 fromZ, toZ; var min = bounds.min; var max = bounds.max; // min/max of bounds can potentially be inverted min.x = Mathf.Min(min.x, max.x); min.y = Mathf.Min(min.y, max.y); min.z = Mathf.Min(min.z, max.z); fromX = min; toX = fromX + new Vector3(absLengthX, 0, 0); fromY = min; toY = fromY + new Vector3(0, absLengthY, 0); fromZ = min; toZ = fromZ + new Vector3(0, 0, absLengthZ); var signZ = Vector3.one; if (showZ) { bool swapX = (dotX > 0) ^ insideY; bool swapY = (dotY < 0) ^ insideY; signZ.x = swapX ? 1 : -1; signZ.y = swapY ? 1 : -1; var ofsX = swapX ? absLengthX : 0; fromZ.x += ofsX; toZ.x += ofsX; var ofsY = swapY ? absLengthY : 0; fromZ.y += ofsY; toZ.y += ofsY; } var signY = Vector3.one; if (showY) { bool swapX = (dotX > 0) ^ insideZ; bool swapZ = (dotZ < 0); signY.x = swapX ? 1 : -1; signY.z = swapZ ? 1 : -1; var ofsX = swapX ? absLengthX : 0; fromY.x += ofsX; toY.x += ofsX; var ofsZ = swapZ ? absLengthZ : 0; fromY.z += ofsZ; toY.z += ofsZ; } var signX = Vector3.one; if (showX) { bool swapY = (dotY > 0) ^ insideZ; bool swapZ = (dotZ < 0); signX.y = swapY ? 1 : -1; signX.z = swapZ ? 1 : -1; var ofsY = swapY ? absLengthY : 0; fromX.y += ofsY; toX.y += ofsY; var ofsZ = swapZ ? absLengthZ : 0; fromX.z += ofsZ; toX.z += ofsZ; } var lineHandleX = SceneHandleUtility.ProjectPointLine(camPos, fromX, toX); var lineHandleY = SceneHandleUtility.ProjectPointLine(camPos, fromY, toY); var lineHandleZ = SceneHandleUtility.ProjectPointLine(camPos, fromZ, toZ); var lineOfsX = (UnityEditor.HandleUtility.GetHandleSize(lineHandleX) * 0.25f); var lineOfsY = (UnityEditor.HandleUtility.GetHandleSize(lineHandleY) * 0.25f); var lineOfsZ = (UnityEditor.HandleUtility.GetHandleSize(lineHandleZ) * 0.25f); var angleX = lineHandleX - camPos; var angleY = lineHandleY - camPos; var angleZ = lineHandleZ - camPos; var directionX = Mathf.Abs(angleX.y) <= Mathf.Abs(angleX.z); var directionY = Mathf.Abs(angleY.x) <= Mathf.Abs(angleY.z); var directionZ = Mathf.Abs(angleZ.y) <= Mathf.Abs(angleZ.x); var disabled = SceneHandles.disabled; const int labelPadding = 2; if (showX && ((visibleAxes & Axes.X) == Axes.X)) { var axisDisabled = ((activeAxes & Axes.X) != Axes.X) || disabled; var selected = ((selectedAxes & Axes.X) == Axes.X) && !axisDisabled; var offsetY = new Vector3(0, (lineOfsY * signX.y), 0); var offsetZ = new Vector3(0, 0, (lineOfsZ * signX.z)); var offset = directionX ? offsetY : offsetZ; var fromOfs = fromX + offset; var toOfs = toX + offset; var camDir = SceneHandleUtility.ProjectPointLine(camPos, fromOfs, toOfs) - camPos; var fromSize = Mathf.Min(absLengthX / 3.0f, UnityEditor.HandleUtility.GetHandleSize(fromOfs) * 0.2f); var toSize = Mathf.Min(absLengthX / 3.0f, UnityEditor.HandleUtility.GetHandleSize(toOfs) * 0.2f); var center = (toOfs + fromOfs) * 0.5f; SceneHandles.color = SceneHandles.StateColor(color2, axisDisabled, selected); SceneHandles.DrawLine(fromX, fromOfs); SceneHandles.DrawLine(toX, toOfs); SceneHandles.color = SceneHandles.StateColor(color, axisDisabled, selected); SceneHandles.DrawLine(fromOfs, toOfs); DrawFlatArrow(fromOfs, Vector3.right, camDir, fromSize); DrawFlatArrow(toOfs, -Vector3.right, camDir, toSize); DrawUnitLabel(center, offset, labelPadding, lengthX, "X"); } if (showY && ((visibleAxes & Axes.Y) == Axes.Y)) { var axisDisabled = ((activeAxes & Axes.Y) != Axes.Y) || disabled; var selected = ((selectedAxes & Axes.Y) == Axes.Y) && !axisDisabled; var offsetX = new Vector3((lineOfsX * signY.x), 0, 0); var offsetZ = new Vector3(0, 0, (lineOfsZ * signY.z)); var offset = directionY ? offsetX : offsetZ; var fromOfs = fromY + offset; var toOfs = toY + offset; var camDir = SceneHandleUtility.ProjectPointLine(camPos, fromOfs, toOfs) - camPos; var fromSize = Mathf.Min(absLengthY / 3.0f, UnityEditor.HandleUtility.GetHandleSize(fromOfs) * 0.2f); var toSize = Mathf.Min(absLengthY / 3.0f, UnityEditor.HandleUtility.GetHandleSize(toOfs) * 0.2f); var center = (toOfs + fromOfs) * 0.5f; SceneHandles.color = SceneHandles.StateColor(color2, axisDisabled, selected); SceneHandles.DrawLine(fromY, fromOfs); SceneHandles.DrawLine(toY, toOfs); SceneHandles.color = SceneHandles.StateColor(color, axisDisabled, selected); SceneHandles.DrawLine(fromOfs, toOfs); DrawFlatArrow(fromOfs, Vector3.up, camDir, fromSize); DrawFlatArrow(toOfs, -Vector3.up, camDir, toSize); DrawUnitLabel(center, offset, labelPadding, lengthY, "Y"); } if (showZ && ((visibleAxes & Axes.Z) == Axes.Z)) { var axisDisabled = ((activeAxes & Axes.Z) != Axes.Z) || disabled; var selected = ((selectedAxes & Axes.Z) == Axes.Z) && !axisDisabled; var offsetX = new Vector3((lineOfsX * signZ.x), 0, 0); var offsetY = new Vector3(0, (lineOfsY * signZ.y), 0); var offset = directionZ ? offsetY : offsetX; var fromOfs = fromZ + offset; var toOfs = toZ + offset; var camDir = SceneHandleUtility.ProjectPointLine(camPos, fromOfs, toOfs) - camPos; var fromSize = Mathf.Min(absLengthZ / 3.0f, UnityEditor.HandleUtility.GetHandleSize(fromOfs) * 0.2f); var toSize = Mathf.Min(absLengthZ / 3.0f, UnityEditor.HandleUtility.GetHandleSize(toOfs) * 0.2f); var center = (toOfs + fromOfs) * 0.5f; SceneHandles.color = SceneHandles.StateColor(color2, axisDisabled, selected); SceneHandles.DrawLine(fromZ, fromOfs); SceneHandles.DrawLine(toZ, toOfs); SceneHandles.color = SceneHandles.StateColor(color, axisDisabled, selected); SceneHandles.DrawLine(fromOfs, toOfs); DrawFlatArrow(fromOfs, Vector3.forward, camDir, fromSize); DrawFlatArrow(toOfs, -Vector3.forward, camDir, toSize); DrawUnitLabel(center, offset, labelPadding, lengthZ, "Z"); } SceneHandles.color = prevColor; }
public static float Radius3DHandle(Quaternion rotation, Vector3 position, float radius, float minRadius = 0, float maxRadius = float.PositiveInfinity) { minRadius = Mathf.Abs(minRadius); maxRadius = Mathf.Abs(maxRadius); if (maxRadius < minRadius) { maxRadius = minRadius; } const float kEpsilon = 0.000001F; var camera = Camera.current; var cameraLocalPos = SceneHandles.inverseMatrix.MultiplyPoint(camera.transform.position); var cameraLocalForward = SceneHandles.inverseMatrix.MultiplyVector(camera.transform.forward); var isCameraInsideSphere = (cameraLocalPos - position).magnitude < radius; var isCameraOrthographic = camera.orthographic; var isStatic = (!Tools.hidden && EditorApplication.isPlaying && GameObjectUtility.ContainsStatic(Selection.gameObjects)); var prevDisabled = SceneHandles.disabled; var prevColor = SceneHandles.color; var forward = rotation * Vector3.forward; var up = rotation * Vector3.up; var right = rotation * Vector3.right; bool guiHasChanged = GUI.changed; GUI.changed = false; Vector3 positiveXDir = right; Vector3 negativeXDir = -right; Vector3 positiveYDir = up; Vector3 negativeYDir = -up; Vector3 positiveZDir = forward; Vector3 negativeZDir = -forward; Vector3 positiveXHandle = position + positiveXDir * radius; Vector3 negativeXHandle = position + negativeXDir * radius; Vector3 positiveYHandle = position + positiveYDir * radius; Vector3 negativeYHandle = position + negativeYDir * radius; Vector3 positiveZHandle = position + positiveZDir * radius; Vector3 negativeZHandle = position + negativeZDir * radius; bool positiveXBackfaced = false; bool negativeXBackfaced = false; bool positiveYBackfaced = false; bool negativeYBackfaced = false; bool positiveZBackfaced = false; bool negativeZBackfaced = false; if (!isCameraInsideSphere) { float cosV; cosV = isCameraOrthographic ? Vector3.Dot(positiveXDir, -cameraLocalForward) : Vector3.Dot(positiveXDir, (cameraLocalPos - positiveXHandle)); positiveXBackfaced = (cosV < -0.0001f); cosV = isCameraOrthographic ? Vector3.Dot(negativeXDir, -cameraLocalForward) : Vector3.Dot(negativeXDir, (cameraLocalPos - negativeXHandle)); negativeXBackfaced = (cosV < -0.0001f); cosV = isCameraOrthographic ? Vector3.Dot(positiveYDir, -cameraLocalForward) : Vector3.Dot(positiveYDir, (cameraLocalPos - positiveYHandle)); positiveYBackfaced = (cosV < -0.0001f); cosV = isCameraOrthographic ? Vector3.Dot(negativeYDir, -cameraLocalForward) : Vector3.Dot(negativeYDir, (cameraLocalPos - negativeYHandle)); negativeYBackfaced = (cosV < -0.0001f); cosV = isCameraOrthographic ? Vector3.Dot(positiveZDir, -cameraLocalForward) : Vector3.Dot(positiveZDir, (cameraLocalPos - positiveZHandle)); positiveZBackfaced = (cosV < -0.0001f); cosV = isCameraOrthographic ? Vector3.Dot(negativeZDir, -cameraLocalForward) : Vector3.Dot(negativeZDir, (cameraLocalPos - negativeZHandle)); negativeZBackfaced = (cosV < -0.0001f); } float positiveXSize = UnityEditor.HandleUtility.GetHandleSize(positiveXHandle) * 0.05f * (positiveXBackfaced ? backfaceSizeMultiplier : 1); float negativeXSize = UnityEditor.HandleUtility.GetHandleSize(negativeXHandle) * 0.05f * (negativeXBackfaced ? backfaceSizeMultiplier : 1); float positiveYSize = UnityEditor.HandleUtility.GetHandleSize(positiveYHandle) * 0.05f * (positiveYBackfaced ? backfaceSizeMultiplier : 1); float negativeYSize = UnityEditor.HandleUtility.GetHandleSize(negativeYHandle) * 0.05f * (negativeYBackfaced ? backfaceSizeMultiplier : 1); float positiveZSize = UnityEditor.HandleUtility.GetHandleSize(positiveZHandle) * 0.05f * (positiveZBackfaced ? backfaceSizeMultiplier : 1); float negativeZSize = UnityEditor.HandleUtility.GetHandleSize(negativeZHandle) * 0.05f * (negativeZBackfaced ? backfaceSizeMultiplier : 1); var isDisabled = isStatic || prevDisabled || Snapping.AxisLocking[0]; var color = SceneHandles.StateColor(prevColor, isDisabled, false); var backfacedColor = SceneHandles.MultiplyTransparency(color, SceneHandles.backfaceAlphaMultiplier); GUI.changed = false; SceneHandles.color = positiveXBackfaced ? backfacedColor : color; positiveXHandle = Slider2DHandle(positiveXHandle, Vector3.zero, forward, up, right, positiveXSize, OutlinedDotHandleCap); if (GUI.changed) { radius = Vector3.Dot(positiveXHandle - position, positiveXDir); guiHasChanged = true; } GUI.changed = false; SceneHandles.color = negativeXBackfaced ? backfacedColor : color; negativeXHandle = Slider2DHandle(negativeXHandle, Vector3.zero, forward, up, right, negativeXSize, OutlinedDotHandleCap); if (GUI.changed) { radius = Vector3.Dot(negativeXHandle - position, negativeXDir); guiHasChanged = true; } isDisabled = isStatic || prevDisabled || Snapping.AxisLocking[1]; color = SceneHandles.StateColor(prevColor, isDisabled, false); backfacedColor = SceneHandles.MultiplyTransparency(color, SceneHandles.backfaceAlphaMultiplier); GUI.changed = false; SceneHandles.color = positiveYBackfaced ? backfacedColor : color; positiveYHandle = Slider2DHandle(positiveYHandle, Vector3.zero, forward, up, right, positiveYSize, OutlinedDotHandleCap); if (GUI.changed) { radius = Vector3.Dot(positiveYHandle - position, positiveYDir); guiHasChanged = true; } GUI.changed = false; SceneHandles.color = negativeYBackfaced ? backfacedColor : color; negativeYHandle = Slider2DHandle(negativeYHandle, Vector3.zero, forward, up, right, negativeYSize, OutlinedDotHandleCap); if (GUI.changed) { radius = Vector3.Dot(negativeYHandle - position, negativeYDir); guiHasChanged = true; } isDisabled = isStatic || prevDisabled || Snapping.AxisLocking[2]; color = SceneHandles.StateColor(prevColor, isDisabled, false); backfacedColor = SceneHandles.MultiplyTransparency(color, SceneHandles.backfaceAlphaMultiplier); GUI.changed = false; SceneHandles.color = positiveZBackfaced ? backfacedColor : color; positiveZHandle = Slider2DHandle(positiveZHandle, Vector3.zero, up, forward, right, positiveZSize, OutlinedDotHandleCap); if (GUI.changed) { radius = Vector3.Dot(positiveZHandle - position, positiveZDir); guiHasChanged = true; } GUI.changed = false; SceneHandles.color = negativeZBackfaced ? backfacedColor : color; negativeZHandle = Slider2DHandle(negativeZHandle, Vector3.zero, up, forward, right, negativeZSize, OutlinedDotHandleCap); if (GUI.changed) { radius = Vector3.Dot(negativeZHandle - position, negativeZDir); guiHasChanged = true; } radius = Mathf.Max(minRadius, Mathf.Min(Mathf.Abs(radius), maxRadius)); GUI.changed |= guiHasChanged; if (radius > 0) { isDisabled = isStatic || prevDisabled || (Snapping.AxisLocking[0] && Snapping.AxisLocking[1]); color = SceneHandles.StateColor(prevColor, isDisabled, false); backfacedColor = SceneHandles.MultiplyTransparency(color, SceneHandles.backfaceAlphaMultiplier); var discOrientations = new Vector3[] { rotation *Vector3.right, rotation *Vector3.up, rotation *Vector3.forward }; var currentCamera = Camera.current; var cameraTransform = currentCamera.transform; if (currentCamera.orthographic) { var planeNormal = cameraTransform.forward; SceneHandles.DrawWireDisc(position, planeNormal, radius); planeNormal.Normalize(); for (int i = 0; i < 3; i++) { var discOrientation = discOrientations[i]; var discTangent = Vector3.Cross(discOrientation, planeNormal); // we may have view dir locked to one axis if (discTangent.sqrMagnitude > kEpsilon) { SceneHandles.color = color; SceneHandles.DrawWireArc(position, discOrientation, discTangent, 180, radius); SceneHandles.color = backfacedColor; SceneHandles.DrawWireArc(position, discOrientation, discTangent, -180, radius); } } } else { // Since the geometry is transformed by Handles.matrix during rendering, we transform the camera position // by the inverse matrix so that the two-shaded wireframe will have the proper orientation. var invMatrix = SceneHandles.inverseMatrix; var cameraCenter = cameraTransform.position; var cameraToCenter = position - invMatrix.MultiplyPoint(cameraCenter); // vector from camera to center var sqrDistCameraToCenter = cameraToCenter.sqrMagnitude; var sqrRadius = radius * radius; // squared radius var sqrOffset = sqrRadius * sqrRadius / sqrDistCameraToCenter; // squared distance from actual center to drawn disc center var insideAmount = sqrOffset / sqrRadius; if (insideAmount < 1) { if (Mathf.Abs(sqrDistCameraToCenter) < kEpsilon) { return(radius); } var horizonRadius = Mathf.Sqrt(sqrRadius - sqrOffset); var horizonCenter = position - sqrRadius * cameraToCenter / sqrDistCameraToCenter; SceneHandles.color = color; SceneHandles.DrawWireDisc(horizonCenter, cameraToCenter, horizonRadius); var planeNormal = cameraToCenter.normalized; for (int i = 0; i < 3; i++) { var discOrientation = discOrientations[i]; var angleBetweenDiscAndNormal = Mathf.Acos(Vector3.Dot(discOrientation, planeNormal)); angleBetweenDiscAndNormal = (Mathf.PI * 0.5f) - Mathf.Min(angleBetweenDiscAndNormal, Mathf.PI - angleBetweenDiscAndNormal); float f = Mathf.Tan(angleBetweenDiscAndNormal); float g = Mathf.Sqrt(sqrOffset + f * f * sqrOffset) / radius; if (g < 1) { var angleToHorizon = Mathf.Asin(g) * Mathf.Rad2Deg; var discTangent = Vector3.Cross(discOrientation, planeNormal); var vectorToPointOnHorizon = Quaternion.AngleAxis(angleToHorizon, discOrientation) * discTangent; var horizonArcLength = (90 - angleToHorizon) * 2.0f; SceneHandles.color = color; SceneHandles.DrawWireArc(position, discOrientation, vectorToPointOnHorizon, horizonArcLength, radius); SceneHandles.color = backfacedColor; SceneHandles.DrawWireArc(position, discOrientation, vectorToPointOnHorizon, horizonArcLength - 360, radius); } else { SceneHandles.color = backfacedColor; SceneHandles.DrawWireDisc(position, discOrientation, radius); } } } else { SceneHandles.color = backfacedColor; for (int i = 0; i < 3; i++) { var discOrientation = discOrientations[i]; SceneHandles.DrawWireDisc(position, discOrientation, radius); } } } } SceneHandles.disabled = prevDisabled; SceneHandles.color = prevColor; return(radius); }