public static (float, float, float, float) SnapBounds(Extents1D currentExtents, float snappingStep)
        {
            if (!Snapping.BoundsSnappingActive)
            {
                return(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
            }

            // Snap current extents against the grid (we're in grid space, so simple snap)
            var snappedExtents = currentExtents;

            snappedExtents.min = SnappingUtility.SnapValue(snappedExtents.min, snappingStep);
            snappedExtents.max = SnappingUtility.SnapValue(snappedExtents.max, snappingStep);

            // Determine the offset relative to the current extents
            var snappedExtentsOffset  = currentExtents - snappedExtents;
            var quantized_min_extents = SnappingUtility.Quantize(snappedExtentsOffset.min);
            var quantized_max_extents = SnappingUtility.Quantize(snappedExtentsOffset.max);
            var abs_min_extents       = Mathf.Abs(quantized_min_extents);
            var abs_max_extents       = Mathf.Abs(quantized_max_extents);

            // Use the smallest distance as the best snap distance
            if (abs_min_extents < abs_max_extents)
            {
                return(abs_min_extents, snappedExtentsOffset.min, quantized_min_extents, quantized_max_extents);
            }
            else
            {
                return(abs_max_extents, snappedExtentsOffset.max, quantized_min_extents, quantized_max_extents);
            }
        }
        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);
        }
Beispiel #3
0
        public Vector3 SnapExtents1D(Extents1D currentExtents, Vector3 currentPosition, Vector3 slideOrigin, Vector3 slideDirection, float snappingStep, out SnapResult1D snapResult)
        {
            snapResult = SnapResult1D.None;

            var offsetPos      = currentPosition - slideOrigin;
            var offsetDistance = SnappingUtility.WorldPointToDistance(offsetPos, slideDirection);
            var currDistance   = offsetDistance - this.startOffset;
            var movedExtents   = currentExtents + offsetDistance;

            var snappedExtents = movedExtents;

            snappedExtents.min = SnappingUtility.SnapValue(movedExtents.min, snappingStep);
            snappedExtents.max = SnappingUtility.SnapValue(movedExtents.max, snappingStep);

            var snappedExtentsOffset = snappedExtents - movedExtents;
            var snappedPivot         = SnappingUtility.SnapValue(currDistance, snappingStep) - currDistance;

            if (!Snapping.BoundsSnappingActive && !Snapping.PivotSnappingActive)
            {
                return(currentPosition);
            }
            var abs_pivot             = Snapping.PivotSnappingActive  ? SnappingUtility.Quantize(Mathf.Abs(snappedPivot)) : float.PositiveInfinity;
            var abs_min_extents       = Snapping.BoundsSnappingActive ? SnappingUtility.Quantize(Mathf.Abs(snappedExtentsOffset.min)) : float.PositiveInfinity;
            var abs_max_extents       = Snapping.BoundsSnappingActive ? SnappingUtility.Quantize(Mathf.Abs(snappedExtentsOffset.max)) : float.PositiveInfinity;
            var snappedOffsetDistance = (abs_pivot < abs_min_extents && abs_pivot < abs_max_extents) ? snappedPivot : ((abs_min_extents < abs_max_extents) ? snappedExtentsOffset.min : snappedExtentsOffset.max);

            if (abs_min_extents <= abs_max_extents && abs_min_extents <= abs_pivot)
            {
                snapResult |= SnapResult1D.Min;
            }
            if (abs_max_extents <= abs_min_extents && abs_max_extents <= abs_pivot)
            {
                snapResult |= SnapResult1D.Max;
            }
            if (abs_pivot <= abs_min_extents && abs_pivot <= abs_max_extents)
            {
                snapResult |= SnapResult1D.Pivot;
            }

            min = slideOrigin + SnappingUtility.DistanceToWorldPoint(snappedExtents.min, slideDirection);
            max = slideOrigin + SnappingUtility.DistanceToWorldPoint(snappedExtents.max, slideDirection);

            var newOffset = offsetDistance + snappedOffsetDistance;

            if (Mathf.Abs(snappedOffsetDistance) > Mathf.Abs(offsetDistance))
            {
                newOffset = 0;
            }

            var snappedDistance = SnappingUtility.DistanceToWorldPoint(newOffset, slideDirection);
            var snappedPosition = (snappedDistance + slideOrigin);

            return(snappedPosition);
        }
Beispiel #4
0
        public static Extents1D GetExtentsOfPointArray(Vector3[] points, Vector3 direction, Vector3 origin)
        {
            var min = float.PositiveInfinity;
            var max = float.NegativeInfinity;

            for (var i = 0; i < points.Length; i++)
            {
                var distance = SnappingUtility.WorldPointToDistance(points[i], direction, origin);
                min = Mathf.Min(min, distance);
                max = Mathf.Max(max, distance);
            }
            return(new Extents1D(min, max));
        }
Beispiel #5
0
        static Extents1D GetExtentsOfPointArray(Matrix4x4 matrix, Vector3[] points, Vector3 slideOrigin, Vector3 slideDirection)
        {
            var transformedDirection = matrix.MultiplyVector(slideDirection);
            var transformedOrigin    = matrix.MultiplyPoint(slideOrigin);

            var min = float.PositiveInfinity;
            var max = float.NegativeInfinity;

            for (var i = 0; i < points.Length; i++)
            {
                var distance = SnappingUtility.WorldPointToDistance(points[i], transformedDirection, transformedOrigin);
                min = Mathf.Min(min, distance);
                max = Mathf.Max(max, distance);
            }
            return(new Extents1D(min, max));
        }
        public static (float, float, float) SnapPoint(float currentPivot, float snappingStep)
        {
            if (!Snapping.PivotSnappingActive)
            {
                return(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
            }

            // Snap current pivot position against the grid (we're in grid space, so simple snap)
            var snappedPivot       = SnappingUtility.SnapValue(currentPivot, snappingStep);
            var snappedPivotOffset = currentPivot - snappedPivot;

            // Determine the offset relative to the current extents
            var quantized_pivot = SnappingUtility.Quantize(snappedPivotOffset);
            var abs_pivot       = Mathf.Abs(quantized_pivot);

            return(abs_pivot, snappedPivotOffset, quantized_pivot);
        }
Beispiel #7
0
        public static Extents3D GetExtentsOfPointArray(Vector3[] points, Vector3 axisX, Vector3 axisY, Vector3 axisZ, Vector3 origin)
        {
            var min = new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
            var max = new Vector3(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity);

            for (var i = 0; i < points.Length; i++)
            {
                var distance = SnappingUtility.WorldPointToDistances(points[i], axisX, axisY, axisZ, origin);
                min.x = Mathf.Min(min.x, distance.x);
                min.y = Mathf.Min(min.y, distance.y);
                min.z = Mathf.Min(min.z, distance.z);

                max.x = Mathf.Max(max.x, distance.x);
                max.y = Mathf.Max(max.y, distance.y);
                max.z = Mathf.Max(max.z, distance.z);
            }
            return(new Extents3D(min, max));
        }
Beispiel #8
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);
        }
        public static (float, float) SnapCustom(List <Vector3> customSnapPoints, float currentPosition, Vector3 slideDirection, float minPointSnap, List <float> customDistances)
        {
            if (customSnapPoints.Count == 0)
            {
                return(float.PositiveInfinity, float.PositiveInfinity);
            }

            float smallest_abs_distance = float.PositiveInfinity;
            float smallest_distance     = float.PositiveInfinity;

            customDistances.Clear();
            for (int i = 0; i < customSnapPoints.Count; i++)
            {
                var snappedPoint = SnappingUtility.WorldPointToDistance(customSnapPoints[i], slideDirection);

                // Determine the offset between the current position and the point we want to snap against
                var snappedPointOffset = currentPosition - snappedPoint;
                var quantized_distance = SnappingUtility.Quantize(snappedPointOffset);
                var abs_distance       = Mathf.Abs(quantized_distance);

                customDistances.Add(quantized_distance);

                // Use the smallest distance as the best snap distance
                if (smallest_abs_distance > abs_distance)
                {
                    smallest_abs_distance = abs_distance;
                    smallest_distance     = snappedPointOffset;
                }
            }

            if (float.IsInfinity(smallest_abs_distance) || smallest_abs_distance > minPointSnap)
            {
                return(float.PositiveInfinity, float.PositiveInfinity);
            }

            return(smallest_abs_distance, smallest_distance);
        }
Beispiel #10
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);
        }
Beispiel #11
0
            public static Vector3[] Do(int id, Vector3[] points, Vector3 handleOrigin, Vector3 handleCursorOffset, Vector3 handleNormal, Vector3 slideDir1, Vector3 slideDir2, float handleSize, SceneHandles.CapFunction capFunction, Axes axes = Axes.None, bool selectLockingAxisOnClick = false, bool noSnapping = false, Vector3?snappingSteps = null)
            {
                var evt = Event.current;

                switch (evt.GetTypeForControl(id))
                {
                case EventType.MouseDown:
                {
                    if (Tools.current == Tool.View ||
                        Tools.current == Tool.None ||
                        evt.alt)
                    {
                        break;
                    }

                    if (GUIUtility.hotControl != 0)
                    {
                        break;
                    }

                    if ((UnityEditor.HandleUtility.nearestControl != id || evt.button != 0) &&
                        (GUIUtility.keyboardControl != id || evt.button != 2))
                    {
                        break;
                    }

                    GUIUtility.hotControl = GUIUtility.keyboardControl = id;
                    evt.Use();
                    EditorGUIUtility.SetWantsMouseJumping(1);

                    s_CurrentMousePosition = evt.mousePosition;
                    s_StartPoints          = points.ToArray();


                    var       localToWorldMatrix = UnityEditor.Handles.matrix;
                    var       center             = Grid.ActiveGrid.Center;
                    Matrix4x4 gridSpace          = Matrix4x4.identity;
                    gridSpace.SetColumn(0, localToWorldMatrix.MultiplyVector(slideDir1).normalized);
                    gridSpace.SetColumn(1, localToWorldMatrix.MultiplyVector(handleNormal).normalized);
                    gridSpace.SetColumn(2, localToWorldMatrix.MultiplyVector(slideDir2).normalized);
                    gridSpace.SetColumn(3, new Vector4(center.x, center.y, center.z, 1.0f));

                    var workGrid = new Grid(gridSpace, snappingSteps.HasValue ? snappingSteps.Value : Snapping.MoveSnappingSteps);

                    s_Snapping2D.Initialize(workGrid, s_CurrentMousePosition, handleOrigin, localToWorldMatrix);
                    s_Snapping2D.CalculateExtents(s_StartPoints);
                    s_MovedMouse = false;
                    break;
                }

                case EventType.MouseDrag:
                {
                    if (GUIUtility.hotControl != id)
                    {
                        break;
                    }

                    s_MovedMouse = true;

                    if (SceneHandles.disabled || Snapping.AreAxisLocked(axes))
                    {
                        break;
                    }

                    s_CurrentMousePosition += evt.delta;
                    evt.Use();

                    if (!s_Snapping2D.DragTo(s_CurrentMousePosition, noSnapping ? SnappingMode.Never: SnappingMode.Default))
                    {
                        break;
                    }

                    var handleInverseMatrix = UnityEditor.Handles.inverseMatrix;
                    var pointDelta          = handleInverseMatrix.MultiplyVector(s_Snapping2D.WorldSnappedDelta);

                    if (s_StartPoints != null)
                    {
                        points = new Vector3[points.Length];     // if we don't, it's hard to do Undo properly
                        for (int i = 0; i < points.Length; i++)
                        {
                            points[i] =
                                SnappingUtility.Quantize(s_StartPoints[i] + pointDelta);
                        }
                    }

                    //SceneView.RepaintAll();
                    GUI.changed = true;
                    break;
                }

                case EventType.MouseUp:
                {
                    if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2))
                    {
                        GUIUtility.hotControl      = 0;
                        GUIUtility.keyboardControl = 0;
                        s_StartPoints = null;
                        evt.Use();
                        EditorGUIUtility.SetWantsMouseJumping(0);
                        SceneView.RepaintAll();
                        if (!s_MovedMouse && selectLockingAxisOnClick)
                        {
                            Snapping.ActiveAxes = axes;
                        }
                    }
                    break;
                }

                case EventType.Layout:
                {
                    if (Tools.current == Tool.View ||
                        Tools.current == Tool.None ||
                        evt.alt)
                    {
                        break;
                    }

                    var position = handleOrigin + handleCursorOffset;
                    var rotation = Quaternion.LookRotation(handleNormal, slideDir1);

                    if (capFunction != null)
                    {
                        capFunction(id, position, rotation, handleSize, EventType.Layout);
                    }
                    else
                    {
                        UnityEditor.HandleUtility.AddControl(id, UnityEditor.HandleUtility.DistanceToCircle(position, handleSize * .5f));
                    }

                    int currentFocusControl = SceneHandleUtility.focusControl;
                    if ((currentFocusControl == id && s_PrevFocusControl != id) ||
                        (currentFocusControl != id && s_PrevFocusControl == id))
                    {
                        s_PrevFocusControl = currentFocusControl;
                        SceneView.RepaintAll();
                    }
                    break;
                }

                case EventType.Repaint:
                {
                    if (axes != Axes.None)
                    {
                        if (GUIUtility.hotControl == id)
                        {
                            var selectedColor = UnityEditor.Handles.selectedColor;
                            selectedColor.a = 0.5f;
                            using (new SceneHandles.DrawingScope(selectedColor))
                                HandleRendering.RenderSnapping3D(s_Snapping2D.WorldSlideGrid, s_Snapping2D.WorldSnappedExtents, s_Snapping2D.GridSnappedPosition, s_Snapping2D.SnapResult);
                        }
                    }

                    if (capFunction == null)
                    {
                        break;
                    }

                    var position = handleOrigin + handleCursorOffset;
                    var rotation = Quaternion.LookRotation(handleNormal, slideDir1);
                    var color    = SceneHandles.StateColor(SceneHandles.color, isSelected: (id == s_PrevFocusControl));

                    using (new SceneHandles.DrawingScope(color))
                    {
                        capFunction(id, position, rotation, handleSize, EventType.Repaint);
                    }
                    break;
                }
                }
                return(points);
            }
        public Vector3 SnapExtents1D(Vector3 currentPosition)
        {
            this.snapResult = SnapResult1D.None;

            var boundsActive = Snapping.BoundsSnappingActive;
            var pivotActive  = Snapping.PivotSnappingActive;

            // Get custom snapping positions along the ray
            var haveCustomSnapping = Snapping.GetCustomSnappingPoints(this.slideOffset + slidePosition, this.slideDirection, 0, s_CustomSnapPoints);

            if (!boundsActive && !pivotActive && !haveCustomSnapping)
            {
                return(currentPosition);
            }


            const float kMinPointSnap = 0.25f;
            float       minPointSnap  = !(boundsActive || pivotActive) ? kMinPointSnap : float.PositiveInfinity;


            // Offset to snapped position relative to the unsnapped position
            // (used to determine which snap value is closest to unsnapped position)
            // Smallest value is used
            float snappedOffsetDistance    = float.PositiveInfinity;
            float snappedOffsetAbsDistance = float.PositiveInfinity;


            var deltaToOrigin    = currentPosition - this.slideOrigin;
            var distanceToOrigin = SnappingUtility.WorldPointToDistance(deltaToOrigin, this.slideDirection);

            var quantized_min_extents = float.PositiveInfinity;
            var quantized_max_extents = float.PositiveInfinity;
            var snappedExtents        = Extents1D.empty;

            if (boundsActive)
            {
                (float abs_distance, float snappedOffset, float quantized_min, float quantized_max) = Snapping.SnapBounds(this.slideExtents + distanceToOrigin, this.snappingStep);
                quantized_min_extents = quantized_min;
                quantized_max_extents = quantized_max;
                snappedExtents.min    = this.slideExtents.min + distanceToOrigin + Mathf.Abs(quantized_min_extents);
                snappedExtents.max    = this.slideExtents.min + distanceToOrigin + Mathf.Abs(quantized_max_extents);
                if (snappedOffsetAbsDistance > abs_distance)
                {
                    snappedOffsetAbsDistance = abs_distance; snappedOffsetDistance = snappedOffset;
                }
            }

            var quantized_pivot = float.PositiveInfinity;

            if (pivotActive)
            {
                (float abs_distance, float snappedOffset, float quantized) = Snapping.SnapPoint(this.startOffset + distanceToOrigin, this.snappingStep);
                quantized_pivot = quantized;
                if (snappedOffsetAbsDistance > abs_distance)
                {
                    snappedOffsetAbsDistance = abs_distance; snappedOffsetDistance = snappedOffset;
                }
            }

            if (haveCustomSnapping)
            {
                (float abs_distance, float snappedOffset) = Snapping.SnapCustom(s_CustomSnapPoints, this.startOffset + distanceToOrigin, this.slideDirection, minPointSnap, s_CustomDistances);
                if (snappedOffsetAbsDistance > abs_distance)
                {
                    snappedOffsetAbsDistance = abs_distance; snappedOffsetDistance = snappedOffset;
                }
            }

            // If we didn't actually snap, just return the actual unsnapped position
            if (float.IsInfinity(snappedOffsetDistance))
            {
                return(currentPosition);
            }

            // Snap against drag start position
            if (Mathf.Abs(snappedOffsetDistance) > Mathf.Abs(distanceToOrigin))
            {
                snappedOffsetDistance = distanceToOrigin;
            }

            var quantizedDistance = SnappingUtility.Quantize(snappedOffsetDistance);

            // Figure out what kind of snapping visualization to show, this needs to be done afterwards since
            // while we're snapping each type of snap can override the next one.
            // Yet at the same time it's possible to snap with multiple snap-types at the same time.

            if (boundsActive)
            {
                if (quantizedDistance == quantized_min_extents)
                {
                    this.snapResult |= SnapResult1D.Min;
                }
                if (quantizedDistance == quantized_max_extents)
                {
                    this.snapResult |= SnapResult1D.Max;
                }

                min = this.slideOrigin + SnappingUtility.DistanceToWorldPoint(snappedExtents.min, this.slideDirection);
                max = this.slideOrigin + SnappingUtility.DistanceToWorldPoint(snappedExtents.max, this.slideDirection);
            }

            if (pivotActive)
            {
                if (quantizedDistance == quantized_pivot)
                {
                    this.snapResult |= SnapResult1D.Pivot;
                }
            }

            if (haveCustomSnapping)
            {
                Snapping.SendCustomSnappedEvents(quantizedDistance, s_CustomDistances, 0);
            }


            // Calculate the new position based on the snapped offset
            var newOffset       = distanceToOrigin - snappedOffsetDistance;
            var snappedDistance = SnappingUtility.DistanceToWorldPoint(newOffset, this.slideDirection);
            var snappedPosition = (snappedDistance + this.slideOrigin);

            return(snappedPosition);
        }
        public static (Vector3, Vector3) SnapCustom(List <Vector3> customSnapPoints, Vector3 currentPosition, Axes enabledAxes, float minPointSnap, List <Vector3> customDistances)
        {
            if (customSnapPoints.Count == 0)
            {
                return(new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity),
                       new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity));
            }

            Vector3 smallest_abs_distance = new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
            Vector3 smallest_distance     = new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);

            if ((enabledAxes & Axes.X) != Axes.X)
            {
                currentPosition.x = 0;
            }
            if ((enabledAxes & Axes.Y) != Axes.Y)
            {
                currentPosition.y = 0;
            }
            if ((enabledAxes & Axes.Z) != Axes.Z)
            {
                currentPosition.z = 0;
            }

            customDistances.Clear();
            for (int i = 0; i < customSnapPoints.Count; i++)
            {
                var snappedPoint = customSnapPoints[i];
                if ((enabledAxes & Axes.X) != Axes.X)
                {
                    snappedPoint.x = 0;
                }
                if ((enabledAxes & Axes.Y) != Axes.Y)
                {
                    snappedPoint.y = 0;
                }
                if ((enabledAxes & Axes.Z) != Axes.Z)
                {
                    snappedPoint.z = 0;
                }

                // Determine the offset between the current position and the point we want to snap against
                var snappedPointOffset = currentPosition - snappedPoint;
                var quantized_distance = SnappingUtility.Quantize(snappedPointOffset);
                var abs_distance       = new Vector3(Mathf.Abs(quantized_distance.x), Mathf.Abs(quantized_distance.y), Mathf.Abs(quantized_distance.z));

                customDistances.Add(quantized_distance);

                // Use the smallest distance as the best snap distance
                if (smallest_abs_distance.sqrMagnitude > abs_distance.sqrMagnitude)
                {
                    smallest_abs_distance = abs_distance;
                    smallest_distance     = snappedPointOffset;
                }
            }
            if (float.IsInfinity(smallest_abs_distance.x) ||
                smallest_abs_distance.magnitude > minPointSnap)
            {
                return(new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity),
                       new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity));
            }

            return(smallest_abs_distance, smallest_distance);
        }
Beispiel #14
0
            internal static Vector3[] Do(int id, Axis axis, Vector3[] points, Vector3 handleOrigin, Vector3 handleDirection, Vector3 slideDirection, float snappingStep = 0, float handleSize = 0, SceneHandles.CapFunction capFunction = null, bool selectLockingAxisOnClick = false)
            {
                if (snappingStep == 0)
                {
                    snappingStep = Snapping.MoveSnappingSteps[(int)axis];
                }
                if (handleSize == 0)
                {
                    handleSize = UnityEditor.HandleUtility.GetHandleSize(handleOrigin) * 0.05f;
                }

                if (handleDirection.sqrMagnitude == 0)
                {
                    return(points);
                }

                var evt  = Event.current;
                var type = evt.GetTypeForControl(id);

                switch (type)
                {
                case EventType.MouseDown:
                {
                    if (SceneHandles.InCameraOrbitMode)
                    {
                        break;
                    }

                    if (GUIUtility.hotControl != 0)
                    {
                        break;
                    }

                    if ((UnityEditor.HandleUtility.nearestControl != id || evt.button != 0) &&
                        (GUIUtility.keyboardControl != id || evt.button != 2))
                    {
                        break;
                    }

                    GUIUtility.hotControl = GUIUtility.keyboardControl = id;
                    evt.Use();
                    EditorGUIUtility.SetWantsMouseJumping(1);

                    s_CurrentMousePosition = evt.mousePosition;
                    s_StartPoints          = points.ToArray();
                    var handleMatrix = SceneHandles.matrix;

                    s_Snapping1D.Initialize(s_CurrentMousePosition,
                                            handleMatrix.MultiplyPoint(handleOrigin),
                                            handleMatrix.MultiplyVector(slideDirection),
                                            snappingStep, axis);
                    s_Snapping1D.CalculateExtents(SceneHandles.inverseMatrix, s_StartPoints);
                    s_MovedMouse = false;
                    break;
                }

                case EventType.MouseDrag:
                {
                    if (GUIUtility.hotControl != id)
                    {
                        break;
                    }

                    s_MovedMouse = true;

                    if (SceneHandles.disabled || Snapping.IsAxisLocked(axis))
                    {
                        break;
                    }

                    s_CurrentMousePosition += evt.delta;
                    evt.Use();

                    if (!s_Snapping1D.Move(s_CurrentMousePosition))
                    {
                        break;
                    }

                    var handleInverseMatrix = SceneHandles.inverseMatrix;
                    var pointDelta          = handleInverseMatrix.MultiplyVector(s_Snapping1D.WorldSnappedOffset);

                    if (s_StartPoints != null)
                    {
                        points = new Vector3[points.Length];     // if we don't, it's hard to do Undo properly
                        for (int i = 0; i < points.Length; i++)
                        {
                            points[i] = SnappingUtility.Quantize(s_StartPoints[i] + pointDelta);
                        }
                    }
                    //SceneView.RepaintAll();
                    GUI.changed = true;
                    break;
                }

                case EventType.MouseUp:
                {
                    if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2))
                    {
                        GUIUtility.hotControl      = 0;
                        GUIUtility.keyboardControl = 0;
                        //Grid.currentGrid = s_PrevGrid;
                        s_StartPoints = null;
                        evt.Use();
                        EditorGUIUtility.SetWantsMouseJumping(0);
                        if (!s_MovedMouse && selectLockingAxisOnClick)
                        {
                            switch (axis)
                            {
                            case Axis.X: { Snapping.ActiveAxes = Axes.X; break; }

                            case Axis.Y: { Snapping.ActiveAxes = Axes.Y; break; }

                            case Axis.Z: { Snapping.ActiveAxes = Axes.Z; break; }
                            }
                        }
                        SceneView.RepaintAll();
                    }
                    break;
                }

#if UNITY_2020_1_OR_NEWER
                case EventType.MouseMove:
                {
                    if (SceneHandles.InCameraOrbitMode)
                    {
                        break;
                    }

                    var position = handleOrigin;
                    var rotation = Quaternion.LookRotation(handleDirection);

                    if (handleSize > 0)
                    {
                        if (capFunction != null)
                        {
                            capFunction(id, position, rotation, handleSize, type);
                        }
                    }

                    int currentFocusControl = SceneHandleUtility.focusControl;
                    if ((currentFocusControl == id && s_PrevFocusControl != id) ||
                        (currentFocusControl != id && s_PrevFocusControl == id))
                    {
                        s_PrevFocusControl = currentFocusControl;
                        SceneView.RepaintAll();
                    }
                    break;
                }
#endif
                case EventType.Layout:
                {
                    if (SceneHandles.InCameraOrbitMode)
                    {
                        break;
                    }

                    var position = handleOrigin;
                    var rotation = Quaternion.LookRotation(handleDirection);

                    if (handleSize > 0)
                    {
                        if (capFunction != null)
                        {
                            capFunction(id, position, rotation, handleSize, type);
                        }
                        else
                        {
                            UnityEditor.HandleUtility.AddControl(id, UnityEditor.HandleUtility.DistanceToCircle(position, handleSize * .2f));
                        }
                    }

                    int currentFocusControl = SceneHandleUtility.focusControl;
                    if ((currentFocusControl == id && s_PrevFocusControl != id) ||
                        (currentFocusControl != id && s_PrevFocusControl == id))
                    {
                        s_PrevFocusControl = currentFocusControl;
                        SceneView.RepaintAll();
                    }
                    break;
                }

                case EventType.Repaint:
                {
                    if (axis != Axis.None)
                    {
                        if (GUIUtility.hotControl == id)
                        {
                            var selectedColor = SceneHandles.StateColor(SceneHandles.MultiplyTransparency(SceneHandles.selectedColor, 0.5f));
                            using (new SceneHandles.DrawingScope(selectedColor))
                                HandleRendering.RenderSnapping1D(s_Snapping1D.Min, s_Snapping1D.Max, s_Snapping1D.WorldSnappedPosition, s_Snapping1D.SlideDirection, s_Snapping1D.SnapResult, axis);
                        }
                    }

                    if (capFunction == null)
                    {
                        break;
                    }

                    var position = handleOrigin;
                    var rotation = Quaternion.LookRotation(handleDirection);
                    var color    = SceneHandles.StateColor(SceneHandles.color, isSelected: (id == s_PrevFocusControl));

                    using (new SceneHandles.DrawingScope(color))
                    {
                        capFunction(id, position, rotation, handleSize, EventType.Repaint);
                    }
                    break;
                }
                }
                return(points);
            }
Beispiel #15
0
 public static Vector3 SnapPoint(Vector3 position, Grid grid, Axes enabledAxes = Axes.XYZ)
 {
     return(SnappingUtility.SnapPoint3D(position, Grid.defaultGrid.Spacing, Grid.defaultGrid.Right, Grid.defaultGrid.Up, Grid.defaultGrid.Forward, Grid.defaultGrid.Center, enabledAxes));
 }
        public Vector3 SnapExtents3D(Extents3D extentsInGridSpace, Vector3 worldCurrentPosition, Vector3 worldStartPosition, out SnapResult3D snapResult, Axes enabledAxes = Axes.XYZ, bool ignoreStartPoint = false)
        {
            snapResult = SnapResult3D.None;
            if (!Snapping.BoundsSnappingActive && !Snapping.PivotSnappingActive)
            {
                return(worldCurrentPosition);
            }

            var offsetInWorldSpace = worldCurrentPosition - worldStartPosition;
            var offsetInGridSpace  = _worldToGridSpace.MultiplyVector(offsetInWorldSpace);
            var pivotInGridSpace   = _worldToGridSpace.MultiplyVector(worldCurrentPosition - Center);

            // Snap our extents in grid space
            var movedExtentsInGridspace = extentsInGridSpace + offsetInGridSpace;

            if ((enabledAxes & Axes.X) > 0)
            {
                var snappedPivot      = SnappingUtility.SnapValue(pivotInGridSpace.x, _spacing.x) - pivotInGridSpace.x;
                var snappedMinExtents = SnappingUtility.SnapValue(movedExtentsInGridspace.min.x, _spacing.x) - movedExtentsInGridspace.min.x;
                var snappedMaxExtents = SnappingUtility.SnapValue(movedExtentsInGridspace.max.x, _spacing.x) - movedExtentsInGridspace.max.x;

                // Figure out on which side of the extents is closest to the grid, use that offset for each axis
                var abs_pivot       = Snapping.PivotSnappingActive  ? SnappingUtility.Quantize(Mathf.Abs(snappedPivot)) : float.PositiveInfinity;
                var abs_min_extents = Snapping.BoundsSnappingActive ? SnappingUtility.Quantize(Mathf.Abs(snappedMinExtents)) : float.PositiveInfinity;
                var abs_max_extents = Snapping.BoundsSnappingActive ? SnappingUtility.Quantize(Mathf.Abs(snappedMaxExtents)) : float.PositiveInfinity;
                offsetInGridSpace.x += (abs_pivot < abs_min_extents && abs_pivot < abs_max_extents) ? snappedPivot : ((abs_min_extents < abs_max_extents) ? snappedMinExtents : snappedMaxExtents);
                if (abs_min_extents <= abs_max_extents && abs_min_extents <= abs_pivot)
                {
                    snapResult |= SnapResult3D.MinX;
                }
                if (abs_max_extents <= abs_min_extents && abs_max_extents <= abs_pivot)
                {
                    snapResult |= SnapResult3D.MaxX;
                }
                if (abs_pivot <= abs_min_extents && abs_pivot <= abs_max_extents)
                {
                    snapResult |= SnapResult3D.PivotX;
                }
            }

            if ((enabledAxes & Axes.Y) > 0)
            {
                var snappedPivot      = SnappingUtility.SnapValue(pivotInGridSpace.y, _spacing.y) - pivotInGridSpace.y;
                var snappedMinExtents = SnappingUtility.SnapValue(movedExtentsInGridspace.min.y, _spacing.y) - movedExtentsInGridspace.min.y;
                var snappedMaxExtents = SnappingUtility.SnapValue(movedExtentsInGridspace.max.y, _spacing.y) - movedExtentsInGridspace.max.y;

                // Figure out on which side of the extents is closest to the grid, use that offset for each axis
                var abs_pivot       = Snapping.PivotSnappingActive  ? SnappingUtility.Quantize(Mathf.Abs(snappedPivot)) : float.PositiveInfinity;
                var abs_min_extents = Snapping.BoundsSnappingActive ? SnappingUtility.Quantize(Mathf.Abs(snappedMinExtents)) : float.PositiveInfinity;
                var abs_max_extents = Snapping.BoundsSnappingActive ? SnappingUtility.Quantize(Mathf.Abs(snappedMaxExtents)) : float.PositiveInfinity;
                offsetInGridSpace.y += (abs_pivot < abs_min_extents && abs_pivot < abs_max_extents) ? snappedPivot : ((abs_min_extents < abs_max_extents) ? snappedMinExtents : snappedMaxExtents);
                if (abs_min_extents <= abs_max_extents && abs_min_extents <= abs_pivot)
                {
                    snapResult |= SnapResult3D.MinY;
                }
                if (abs_max_extents <= abs_min_extents && abs_max_extents <= abs_pivot)
                {
                    snapResult |= SnapResult3D.MaxY;
                }
                if (abs_pivot <= abs_min_extents && abs_pivot <= abs_max_extents)
                {
                    snapResult |= SnapResult3D.PivotY;
                }
            }

            if ((enabledAxes & Axes.Z) > 0)
            {
                var snappedPivot      = SnappingUtility.SnapValue(pivotInGridSpace.z, _spacing.z) - pivotInGridSpace.z;
                var snappedMinExtents = SnappingUtility.SnapValue(movedExtentsInGridspace.min.z, _spacing.z) - movedExtentsInGridspace.min.z;
                var snappedMaxExtents = SnappingUtility.SnapValue(movedExtentsInGridspace.max.z, _spacing.z) - movedExtentsInGridspace.max.z;

                // Figure out on which side of the extents is closest to the grid, use that offset for each axis
                var abs_pivot       = Snapping.PivotSnappingActive  ? SnappingUtility.Quantize(Mathf.Abs(snappedPivot)) : float.PositiveInfinity;
                var abs_min_extents = Snapping.BoundsSnappingActive ? SnappingUtility.Quantize(Mathf.Abs(snappedMinExtents)) : float.PositiveInfinity;
                var abs_max_extents = Snapping.BoundsSnappingActive ? SnappingUtility.Quantize(Mathf.Abs(snappedMaxExtents)) : float.PositiveInfinity;
                offsetInGridSpace.z += (abs_pivot < abs_min_extents && abs_pivot < abs_max_extents) ? snappedPivot : ((abs_min_extents < abs_max_extents) ? snappedMinExtents : snappedMaxExtents);
                if (abs_min_extents <= abs_max_extents && abs_min_extents <= abs_pivot)
                {
                    snapResult |= SnapResult3D.MinZ;
                }
                if (abs_max_extents <= abs_min_extents && abs_max_extents <= abs_pivot)
                {
                    snapResult |= SnapResult3D.MaxZ;
                }
                if (abs_pivot <= abs_min_extents && abs_pivot <= abs_max_extents)
                {
                    snapResult |= SnapResult3D.PivotZ;
                }
            }



            var snappedOffsetInWorldSpace   = _gridToWorldSpace.MultiplyVector(offsetInGridSpace);
            var snappedPositionInWorldSpace = (worldStartPosition + snappedOffsetInWorldSpace);

            if (!ignoreStartPoint)
            {
                if (Mathf.Abs(worldCurrentPosition.x - snappedPositionInWorldSpace.x) > Mathf.Abs(offsetInWorldSpace.x))
                {
                    snappedPositionInWorldSpace.x = worldStartPosition.x;
                }
                if (Mathf.Abs(worldCurrentPosition.y - snappedPositionInWorldSpace.y) > Mathf.Abs(offsetInWorldSpace.y))
                {
                    snappedPositionInWorldSpace.y = worldStartPosition.y;
                }
                if (Mathf.Abs(worldCurrentPosition.z - snappedPositionInWorldSpace.z) > Mathf.Abs(offsetInWorldSpace.z))
                {
                    snappedPositionInWorldSpace.z = worldStartPosition.z;
                }
            }

            return(snappedPositionInWorldSpace);
        }
        public Vector3 SnapExtents3D(Extents3D extentsInGridSpace, Vector3 worldCurrentPosition, Vector3 worldStartPosition, Grid worldSlideGrid, out SnapResult3D snapResult, Axes enabledAxes = Axes.XYZ, bool ignoreStartPoint = false)
        {
            s_CustomSnapPoints.Clear();
            // TODO: have a method that handles multiple dimensions at the same time
            var haveCustomSnapping = Snapping.GetCustomSnappingPoints(worldStartPosition, worldCurrentPosition, worldSlideGrid, 0, s_CustomSnapPoints);

            var boundsActive = Snapping.BoundsSnappingActive;
            var pivotActive  = Snapping.PivotSnappingActive;

            snapResult = SnapResult3D.None;
            if (!boundsActive && !pivotActive && !haveCustomSnapping)
            {
                return(worldCurrentPosition);
            }

            const float kMinPointSnap = 0.25f;
            float       minPointSnap  = !(boundsActive || pivotActive) ? kMinPointSnap : float.PositiveInfinity;


            var offsetInWorldSpace = worldCurrentPosition - worldStartPosition;
            var offsetInGridSpace  = _worldToGridSpace.MultiplyVector(offsetInWorldSpace);
            var pivotInGridSpace   = _worldToGridSpace.MultiplyVector(worldCurrentPosition - Center);

            // Snap our extents in grid space
            var movedExtentsInGridspace = extentsInGridSpace + offsetInGridSpace;


            var snappedOffset    = Vector3.zero;
            var absSnappedOffset = new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);

            var enabledAxisLookup = new[] { (enabledAxes & Axes.X) > 0, (enabledAxes & Axes.Y) > 0, (enabledAxes & Axes.Z) > 0 };

            var quantized_pivot       = new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
            var quantized_min_extents = new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
            var quantized_max_extents = new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);

            for (int i = 0; i < 3; i++)
            {
                if (!enabledAxisLookup[i])
                {
                    continue;
                }

                if (pivotActive)
                {
                    (float abs_pivot_offset, float snappedPivot, float quantized_offset) = Snapping.SnapPoint(pivotInGridSpace[i], _spacing[i]);
                    quantized_pivot[i] = quantized_offset;
                    if (absSnappedOffset[i] > abs_pivot_offset)
                    {
                        absSnappedOffset[i] = abs_pivot_offset; snappedOffset[i] = snappedPivot;
                    }
                }

                if (boundsActive)
                {
                    (float abs_bounds_distance, float snappedBoundsOffset, float quantized_min, float quantized_max) = Snapping.SnapBounds(movedExtentsInGridspace[i], _spacing[i]);
                    quantized_min_extents[i] = quantized_min;
                    quantized_max_extents[i] = quantized_max;

                    if (absSnappedOffset[i] > abs_bounds_distance)
                    {
                        absSnappedOffset[i] = abs_bounds_distance; snappedOffset[i] = snappedBoundsOffset;
                    }
                }
            }

            if (haveCustomSnapping)
            {
                (Vector3 abs_distance, Vector3 snappedCustomOffset) = Snapping.SnapCustom(s_CustomSnapPoints, pivotInGridSpace, enabledAxes, minPointSnap, s_CustomDistances);
                if (absSnappedOffset.sqrMagnitude > abs_distance.sqrMagnitude)
                {
                    absSnappedOffset = abs_distance; snappedOffset = snappedCustomOffset;
                }
            }

            // Snap against drag start position
            if (!ignoreStartPoint)
            {
                if (Mathf.Abs(snappedOffset.x) > Mathf.Abs(offsetInGridSpace.x))
                {
                    offsetInGridSpace.x = snappedOffset.x = 0;
                }
                if (Mathf.Abs(snappedOffset.y) > Mathf.Abs(offsetInGridSpace.y))
                {
                    offsetInGridSpace.y = snappedOffset.y = 0;
                }
                if (Mathf.Abs(snappedOffset.z) > Mathf.Abs(offsetInGridSpace.z))
                {
                    offsetInGridSpace.z = snappedOffset.z = 0;
                }
            }

            var quantizedOffset = new Vector3(SnappingUtility.Quantize(snappedOffset.x),
                                              SnappingUtility.Quantize(snappedOffset.y),
                                              SnappingUtility.Quantize(snappedOffset.z));

            // Figure out what kind of snapping visualization to show, this needs to be done afterwards since
            // while we're snapping each type of snap can override the next one.
            // Yet at the same time it's possible to snap with multiple snap-types at the same time.

            if (boundsActive)
            {
                if (quantized_min_extents.x == quantizedOffset.x)
                {
                    snapResult |= SnapResult3D.MinX;
                }
                if (quantized_max_extents.x == quantizedOffset.x)
                {
                    snapResult |= SnapResult3D.MaxX;
                }

                if (quantized_min_extents.y == quantizedOffset.y)
                {
                    snapResult |= SnapResult3D.MinY;
                }
                if (quantized_max_extents.y == quantizedOffset.y)
                {
                    snapResult |= SnapResult3D.MaxY;
                }

                if (quantized_min_extents.z == quantizedOffset.z)
                {
                    snapResult |= SnapResult3D.MinZ;
                }
                if (quantized_max_extents.z == quantizedOffset.z)
                {
                    snapResult |= SnapResult3D.MaxZ;
                }
            }

            if (pivotActive)
            {
                if (quantized_pivot.x == quantizedOffset.x)
                {
                    snapResult |= SnapResult3D.PivotX;
                }
                if (quantized_pivot.y == quantizedOffset.y)
                {
                    snapResult |= SnapResult3D.PivotY;
                }
                if (quantized_pivot.z == quantizedOffset.z)
                {
                    snapResult |= SnapResult3D.PivotZ;
                }
            }

            if (haveCustomSnapping)
            {
                Snapping.SendCustomSnappedEvents(quantizedOffset, s_CustomDistances, 0);
            }

            if (absSnappedOffset.x == 0 &&
                absSnappedOffset.y == 0 &&
                absSnappedOffset.z == 0)
            {
                return(worldStartPosition);
            }

            var snappedOffsetInWorldSpace   = _gridToWorldSpace.MultiplyVector(offsetInGridSpace - snappedOffset);
            var snappedPositionInWorldSpace = (worldStartPosition + snappedOffsetInWorldSpace);

            //Debug.Log($"{(float3)snappedOffsetInWorldSpace} {(float3)snappedOffset} {(float3)snappedPositionInWorldSpace}");

            return(snappedPositionInWorldSpace);
        }
Beispiel #18
0
 public static Extents3D CreateExtent(Vector3 point, Vector3 axisX, Vector3 axisY, Vector3 axisZ, Vector3 origin)
 {
     var distance = SnappingUtility.WorldPointToDistances(point, axisX, axisY, axisZ, origin); return(new Extents3D(distance, distance));
 }