예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        public static void Initialize(ref PositionHandleIDs handleIDs)
        {
            GUI.SetNextControlName("xAxis");   handleIDs.xAxisId   = GUIUtility.GetControlID(s_xAxisMoveHandleHash, FocusType.Passive);
            GUI.SetNextControlName("yAxis");   handleIDs.yAxisId   = GUIUtility.GetControlID(s_yAxisMoveHandleHash, FocusType.Passive);
            GUI.SetNextControlName("zAxis");   handleIDs.zAxisId   = GUIUtility.GetControlID(s_zAxisMoveHandleHash, FocusType.Passive);
            GUI.SetNextControlName("xzPlane"); handleIDs.xzPlaneId = GUIUtility.GetControlID(s_xzAxisMoveHandleHash, FocusType.Passive);
            GUI.SetNextControlName("xyPlane"); handleIDs.xyPlaneId = GUIUtility.GetControlID(s_xyAxisMoveHandleHash, FocusType.Passive);
            GUI.SetNextControlName("yzPlane"); handleIDs.yzPlaneId = GUIUtility.GetControlID(s_yzAxisMoveHandleHash, FocusType.Passive);
            GUI.SetNextControlName("center");  handleIDs.centerId  = GUIUtility.GetControlID(s_centerMoveHandleHash, FocusType.Passive);

            handleIDs.xAxisState   = ControlState.None;
            handleIDs.yAxisState   = ControlState.None;
            handleIDs.zAxisState   = ControlState.None;
            handleIDs.xzPlaneState = ControlState.None;
            handleIDs.xyPlaneState = ControlState.None;
            handleIDs.yzPlaneState = ControlState.None;
            handleIDs.centerState  = ControlState.None;

            var hotControl = GUIUtility.hotControl;

            if (handleIDs.xAxisId == hotControl)
            {
                handleIDs.xAxisState |= ControlState.Hot;
            }
            if (handleIDs.yAxisId == hotControl)
            {
                handleIDs.yAxisState |= ControlState.Hot;
            }
            if (handleIDs.zAxisId == hotControl)
            {
                handleIDs.zAxisState |= ControlState.Hot;
            }
            if (handleIDs.xzPlaneId == hotControl)
            {
                handleIDs.xzPlaneState |= ControlState.Hot;
            }
            if (handleIDs.xyPlaneId == hotControl)
            {
                handleIDs.xyPlaneState |= ControlState.Hot;
            }
            if (handleIDs.yzPlaneId == hotControl)
            {
                handleIDs.yzPlaneState |= ControlState.Hot;
            }
            if (handleIDs.centerId == hotControl)
            {
                handleIDs.centerState |= ControlState.Hot;
            }
            var xzPlaneIsHot       = (handleIDs.xzPlaneState & ControlState.Hot) == ControlState.Hot;
            var xyPlaneIsHot       = (handleIDs.xyPlaneState & ControlState.Hot) == ControlState.Hot;
            var yzPlaneIsHot       = (handleIDs.yzPlaneState & ControlState.Hot) == ControlState.Hot;
            var xAxisIndirectlyHot = (handleIDs.xAxisIndirectState & ControlState.Hot) == ControlState.Hot;
            var yAxisIndirectlyHot = (handleIDs.yAxisIndirectState & ControlState.Hot) == ControlState.Hot;
            var zAxisIndirectlyHot = (handleIDs.zAxisIndirectState & ControlState.Hot) == ControlState.Hot;
            var centerIsHot        = (handleIDs.centerState & ControlState.Hot) == ControlState.Hot;
            var isAnyHot           = (handleIDs.combinedState & ControlState.Hot) == ControlState.Hot;

            var focusControl = SceneHandleUtility.focusControl;

            if (handleIDs.xAxisId == focusControl)
            {
                handleIDs.xAxisState |= ControlState.Focused;
            }
            if (handleIDs.yAxisId == focusControl)
            {
                handleIDs.yAxisState |= ControlState.Focused;
            }
            if (handleIDs.zAxisId == focusControl)
            {
                handleIDs.zAxisState |= ControlState.Focused;
            }
            if (handleIDs.xzPlaneId == focusControl)
            {
                handleIDs.xzPlaneState |= ControlState.Focused;
            }
            if (handleIDs.xyPlaneId == focusControl)
            {
                handleIDs.xyPlaneState |= ControlState.Focused;
            }
            if (handleIDs.yzPlaneId == focusControl)
            {
                handleIDs.yzPlaneState |= ControlState.Focused;
            }
            if (handleIDs.centerId == focusControl)
            {
                handleIDs.centerState |= ControlState.Focused;
            }

            var xAxisLocked   = Snapping.AxisLocking[0];
            var yAxisLocked   = Snapping.AxisLocking[1];
            var zAxisLocked   = Snapping.AxisLocking[2];
            var xzPlaneLocked = xAxisLocked && zAxisLocked;
            var xyPlaneLocked = xAxisLocked && yAxisLocked;
            var yzPlaneLocked = yAxisLocked && zAxisLocked;

            if (xAxisLocked)
            {
                handleIDs.xAxisState |= ControlState.Locked;
            }
            if (yAxisLocked)
            {
                handleIDs.yAxisState |= ControlState.Locked;
            }
            if (zAxisLocked)
            {
                handleIDs.zAxisState |= ControlState.Locked;
            }
            if (xzPlaneLocked)
            {
                handleIDs.xzPlaneState |= ControlState.Locked;
            }
            if (xyPlaneLocked)
            {
                handleIDs.xyPlaneState |= ControlState.Locked;
            }
            if (yzPlaneLocked)
            {
                handleIDs.yzPlaneState |= ControlState.Locked;
            }

            var activeAxes = Snapping.ActiveAxes;

            if (activeAxes == Axes.X)
            {
                handleIDs.xAxisState |= ControlState.Active;
            }
            if (activeAxes == Axes.Y)
            {
                handleIDs.yAxisState |= ControlState.Active;
            }
            if (activeAxes == Axes.Z)
            {
                handleIDs.zAxisState |= ControlState.Active;
            }
            if (activeAxes == Axes.XZ)
            {
                handleIDs.xzPlaneState |= ControlState.Active;
            }
            if (activeAxes == Axes.XY)
            {
                handleIDs.xyPlaneState |= ControlState.Active;
            }
            if (activeAxes == Axes.YZ)
            {
                handleIDs.yzPlaneState |= ControlState.Active;
            }

            var isStatic   = (!Tools.hidden && EditorApplication.isPlaying && GameObjectUtility.ContainsStatic(Selection.gameObjects));
            var isDisabled = SceneHandles.disabled;

            var xAxisDisabled   = isStatic || isDisabled || xAxisLocked || (isAnyHot && !xAxisIndirectlyHot);
            var yAxisDisabled   = isStatic || isDisabled || yAxisLocked || (isAnyHot && !yAxisIndirectlyHot);
            var zAxisDisabled   = isStatic || isDisabled || zAxisLocked || (isAnyHot && !zAxisIndirectlyHot);
            var xzPlaneDisabled = isStatic || isDisabled || xzPlaneLocked || (isAnyHot && !xzPlaneIsHot);
            var xyPlaneDisabled = isStatic || isDisabled || xyPlaneLocked || (isAnyHot && !xyPlaneIsHot);
            var yzPlaneDisabled = isStatic || isDisabled || yzPlaneLocked || (isAnyHot && !yzPlaneIsHot);
            var centerDisabled  = isStatic || isDisabled || (isAnyHot && !centerIsHot);

            if (xAxisDisabled)
            {
                handleIDs.xAxisState |= ControlState.Disabled;
            }
            if (yAxisDisabled)
            {
                handleIDs.yAxisState |= ControlState.Disabled;
            }
            if (zAxisDisabled)
            {
                handleIDs.zAxisState |= ControlState.Disabled;
            }
            if (xzPlaneDisabled)
            {
                handleIDs.xzPlaneState |= ControlState.Disabled;
            }
            if (xyPlaneDisabled)
            {
                handleIDs.xyPlaneState |= ControlState.Disabled;
            }
            if (yzPlaneDisabled)
            {
                handleIDs.yzPlaneState |= ControlState.Disabled;
            }
            if (centerDisabled)
            {
                handleIDs.centerState |= ControlState.Disabled;
            }
        }
예제 #4
0
        static Vector3[] PlanarHandle(int id, PlaneAxes planarAxes, Vector3[] points, Vector3 position, Quaternion rotation, float handleSize, bool selectLockingAxisOnClick = false)
        {
            int axis1index = 0;
            int axis2index = 0;
            var isStatic   = (!Tools.hidden && EditorApplication.isPlaying && GameObjectUtility.ContainsStatic(Selection.gameObjects));
            var axes       = Axes.None;

            switch (planarAxes)
            {
            case PlaneAxes.XZ: { axis1index = 0; axis2index = 2; axes = Axes.XZ; break; }

            case PlaneAxes.XY: { axis1index = 0; axis2index = 1; axes = Axes.XY; break; }

            case PlaneAxes.YZ: { axis1index = 1; axis2index = 2; axes = Axes.YZ; break; }
            }

            int axisNormalIndex = 3 - axis2index - axis1index;
            var prevColor       = SceneHandles.color;

            var handleTransform             = Matrix4x4.TRS(position, rotation, Vector3.one);
            var sceneView                   = SceneView.currentDrawingSceneView;
            var cameraToTransformToolVector = handleTransform.inverse.MultiplyPoint(sceneView.camera.transform.position).normalized;

            /*
             * if (Mathf.Abs (cameraToTransformToolVector[axisNormalIndex]) < 0.05f && GUIUtility.hotControl != id)
             * {
             *  Handles.color = prevColor;
             *  return points;
             * }*/

            if (EditorGUIUtility.hotControl == 0)
            {
                s_PlanarHandlesOctant[axis1index] = (cameraToTransformToolVector[axis1index] < -0.01f ? -1 : 1);
                s_PlanarHandlesOctant[axis2index] = (cameraToTransformToolVector[axis2index] < -0.01f ? -1 : 1);
            }

            var handleOffset = s_PlanarHandlesOctant;

            handleOffset[axisNormalIndex] = 0;
            handleOffset = rotation * (handleOffset * handleSize * 0.5f);

            var axis1      = Vector3.zero;
            var axis2      = Vector3.zero;
            var axisNormal = Vector3.zero;

            axis1[axis1index]           = 1;
            axis2[axis2index]           = 1;
            axisNormal[axisNormalIndex] = 1;
            axis1      = rotation * axis1;
            axis2      = rotation * axis2;
            axisNormal = rotation * axisNormal;

            s_Vertices[0] = position + handleOffset + (axis1 + axis2) * handleSize * 0.5f;
            s_Vertices[1] = position + handleOffset + (-axis1 + axis2) * handleSize * 0.5f;
            s_Vertices[2] = position + handleOffset + (-axis1 - axis2) * handleSize * 0.5f;
            s_Vertices[3] = position + handleOffset + (axis1 - axis2) * handleSize * 0.5f;

            var innerColor = SceneHandles.color;
            var outerColor = Color.black;

            innerColor = new Color(innerColor.r, innerColor.g, innerColor.b, 0.1f);
            if (!isStatic && !SceneHandles.disabled)
            {
                SceneHandles.DrawSolidRectangleWithOutline(s_Vertices, innerColor, outerColor);
            }

            points = Slider2DHandle(id, points, position, handleOffset, axisNormal, axis1, axis2, handleSize * 0.5f, RectangleHandleCap, axes, selectLockingAxisOnClick);

            SceneHandles.color = prevColor;

            return(points);
        }
예제 #5
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);
        }
        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);
        }
예제 #7
0
        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);
        }
예제 #8
0
        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;
        }
예제 #9
0
        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);
        }
예제 #10
0
        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));
        }
예제 #11
0
        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);
        }
예제 #12
0
        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);
        }