コード例 #1
0
        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);
        }
コード例 #2
0
        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;
        }
コード例 #3
0
        public static void SetCursor(int id, Vector3 from, Vector3 to)
        {
            if (UnityEditor.HandleUtility.nearestControl != id &&
                EditorGUIUtility.hotControl != id)
            {
                return;
            }

            SetArrowCursor(SceneHandleUtility.GetCursorForEdge(from, to));
        }
コード例 #4
0
        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);
        }
コード例 #5
0
        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);
        }
コード例 #6
0
        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);
        }
コード例 #7
0
        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);
        }
コード例 #8
0
        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);
        }
コード例 #9
0
        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);
        }
コード例 #10
0
        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;
        }