public bool Move(Vector2 currentMousePosition) { var distanceOnLine = SceneHandleUtility.CalcLineTranslation(this.startMousePosition, currentMousePosition, this.slideStart, this.slideDirection); if (distanceOnLine == 0) { return(false); } var delta = this.slideDirection * distanceOnLine; if (delta.sqrMagnitude == 0) { return(false); } this.slidePosition = this.slideOrigin + delta; var newSnappedPosition = this.slidePosition; newSnappedPosition = SnapExtents1D(newSnappedPosition); newSnappedPosition = SnappingUtility.PerformAxisLocking(this.slidePosition, newSnappedPosition, slideAxis); if ((this.snappedPosition - newSnappedPosition).sqrMagnitude == 0) { return(false); } this.snappedPosition = newSnappedPosition; return(true); }
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 void SetCursor(int id, Vector3 from, Vector3 to) { if (UnityEditor.HandleUtility.nearestControl != id && EditorGUIUtility.hotControl != id) { return; } SetArrowCursor(SceneHandleUtility.GetCursorForEdge(from, to)); }
public static void DrawFlatArrow(UnityEngine.Vector3 center, UnityEngine.Vector3 direction, float handleSize) { var invMatrix = SceneHandles.inverseMatrix; var camera = UnityEngine.Camera.current; var camPos = invMatrix.MultiplyPoint(camera.transform.position); var camDir = (SceneHandleUtility.ProjectPointLine(camPos, center, center + direction) - camPos).normalized; DrawFlatArrow(center, direction, camDir, handleSize); }
public static Vector3 Edge2DHandleOffset(int id, Vector3 from, Vector3 to, Vector3 position, Vector3 handleDir, Vector3 slideDir1, Vector3 slideDir2, float handleSize, CapFunction capFunction, Axes axes = Axes.None, Vector3?snappingSteps = null) { var evt = Event.current; switch (evt.GetTypeForControl(id)) { case EventType.Layout: { if (Tools.current == Tool.View || Tools.current == Tool.None || evt.alt) { break; } UnityEditor.HandleUtility.AddControl(id, UnityEditor.HandleUtility.DistanceToLine(from, to) * 0.5f); break; } case EventType.Repaint: { var sceneView = SceneView.currentDrawingSceneView; if (sceneView && Tools.current != Tool.View && Tools.current != Tool.None && !evt.alt) { if (UnityEditor.HandleUtility.nearestControl == id || EditorGUIUtility.hotControl == id) { var rect = sceneView.position; rect.min = Vector2.zero; EditorGUIUtility.AddCursorRect(rect, SceneHandleUtility.GetCursorForEdge(from, to)); } } if (EditorGUIUtility.keyboardControl == id) { SceneHandles.DrawAAPolyLine(3.0f, from, to); } else { SceneHandles.DrawAAPolyLine(2.5f, from, to); } break; } } var points = new Vector3[] { from, to }; var result = Slider2D.Do(id, points, position, Vector3.zero, handleDir, slideDir1, slideDir2, handleSize, capFunction, axes, snappingSteps: snappingSteps); return(result[0] - from); }
public static Vector3 Edge1DHandleOffset(int id, Axis axis, Vector3 from, Vector3 to, Vector3 position, Vector3 direction, float snappingStep, float handleSize, CapFunction capFunction) { var evt = Event.current; switch (evt.GetTypeForControl(id)) { case EventType.Layout: { if (Tools.current == Tool.View || Tools.current == Tool.None || evt.alt) { break; } UnityEditor.HandleUtility.AddControl(id, UnityEditor.HandleUtility.DistanceToLine(from, to)); break; } case EventType.Repaint: { var sceneView = SceneView.currentDrawingSceneView; if (sceneView && Tools.current != Tool.View && Tools.current != Tool.None && !evt.alt) { var rect = sceneView.position; rect.min = Vector2.zero; var hovering = UnityEditor.HandleUtility.nearestControl == id && UnityEditor.HandleUtility.DistanceToLine(from, to) < 10; // in case multiple edges share the same id, we want to ignore those that aren't even close if (EditorGUIUtility.hotControl == id || hovering) { EditorGUIUtility.AddCursorRect(rect, SceneHandleUtility.GetCursorForEdge(from, to)); } } SceneHandles.DrawAAPolyLine(3.0f, from, to); break; } } var points = new Vector3[] { from, to }; var result = Slider1DHandle(id, axis, points, position, direction, snappingStep, handleSize, capFunction); return(result[0] - from); }
public void Initialize(Vector2 currentMousePosition, Vector3 slideOrigin, Vector3 slideDirection, float snappingStep, Axis axis) { this.slideDirection = slideDirection; this.snappingStep = snappingStep; this.slideOrigin = SceneHandleUtility.ProjectPointRay(Grid.ActiveGrid.Center, slideOrigin, slideDirection); this.slideExtents.min = this.slideExtents.max = 0; this.snappedPosition = this.slideOrigin; this.slidePosition = this.slideOrigin; this.slideOffset = slideOrigin - this.slideOrigin; this.startOffset = SnappingUtility.WorldPointToDistance(this.slidePosition - slideOrigin, slideDirection); this.startMousePosition = currentMousePosition; this.slideAxis = axis; this.snapResult = SnapResult1D.None; this.min = slideOrigin + SnappingUtility.DistanceToWorldPoint(slideExtents.min, slideDirection); this.max = slideOrigin + SnappingUtility.DistanceToWorldPoint(slideExtents.max, slideDirection); }
public bool Move(Vector2 currentMousePosition) { var distanceOnLine = SceneHandleUtility.CalcLineTranslation(this.startMousePosition, currentMousePosition, this.slideOrigin, this.slideDirection); if (distanceOnLine == 0) { return(false); } var delta = this.slideDirection * distanceOnLine; if (delta.sqrMagnitude == 0) { return(false); } this.slidePosition = this.slideOrigin + delta; var newSnappedPosition = this.slidePosition; //if (Snapping.BoundsSnappingActive) newSnappedPosition = SnapExtents1D(this.slideExtents, newSnappedPosition, this.slideOrigin, this.slideDirection, this.snappingStep, out this.snapResult); //else // this.snapResult = SnapResult1D.None; newSnappedPosition = SnappingUtility.PerformAxisLocking(this.slidePosition, newSnappedPosition, slideAxis); if ((this.snappedPosition - newSnappedPosition).sqrMagnitude == 0) { return(false); } this.snappedPosition = newSnappedPosition; return(true); }
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); }
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; }