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); }
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); }
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)); }
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); }
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)); }
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); }
public bool Move(Vector2 currentMousePosition) { var distanceOnLine = SceneHandleUtility.CalcLineTranslation(this.startMousePosition, currentMousePosition, this.slideOrigin, this.slideDirection); if (distanceOnLine == 0) { return(false); } var delta = this.slideDirection * distanceOnLine; if (delta.sqrMagnitude == 0) { return(false); } this.slidePosition = this.slideOrigin + delta; var newSnappedPosition = this.slidePosition; //if (Snapping.BoundsSnappingActive) newSnappedPosition = SnapExtents1D(this.slideExtents, newSnappedPosition, this.slideOrigin, this.slideDirection, this.snappingStep, out this.snapResult); //else // this.snapResult = SnapResult1D.None; newSnappedPosition = SnappingUtility.PerformAxisLocking(this.slidePosition, newSnappedPosition, slideAxis); if ((this.snappedPosition - newSnappedPosition).sqrMagnitude == 0) { return(false); } this.snappedPosition = newSnappedPosition; return(true); }
public static 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); }
internal static Vector3[] Do(int id, Axis axis, Vector3[] points, Vector3 handleOrigin, Vector3 handleDirection, Vector3 slideDirection, float snappingStep = 0, float handleSize = 0, SceneHandles.CapFunction capFunction = null, bool selectLockingAxisOnClick = false) { if (snappingStep == 0) { snappingStep = Snapping.MoveSnappingSteps[(int)axis]; } if (handleSize == 0) { handleSize = UnityEditor.HandleUtility.GetHandleSize(handleOrigin) * 0.05f; } if (handleDirection.sqrMagnitude == 0) { return(points); } var evt = Event.current; var type = evt.GetTypeForControl(id); switch (type) { case EventType.MouseDown: { if (SceneHandles.InCameraOrbitMode) { break; } if (GUIUtility.hotControl != 0) { break; } if ((UnityEditor.HandleUtility.nearestControl != id || evt.button != 0) && (GUIUtility.keyboardControl != id || evt.button != 2)) { break; } GUIUtility.hotControl = GUIUtility.keyboardControl = id; evt.Use(); EditorGUIUtility.SetWantsMouseJumping(1); s_CurrentMousePosition = evt.mousePosition; s_StartPoints = points.ToArray(); var handleMatrix = SceneHandles.matrix; s_Snapping1D.Initialize(s_CurrentMousePosition, handleMatrix.MultiplyPoint(handleOrigin), handleMatrix.MultiplyVector(slideDirection), snappingStep, axis); s_Snapping1D.CalculateExtents(SceneHandles.inverseMatrix, s_StartPoints); s_MovedMouse = false; break; } case EventType.MouseDrag: { if (GUIUtility.hotControl != id) { break; } s_MovedMouse = true; if (SceneHandles.disabled || Snapping.IsAxisLocked(axis)) { break; } s_CurrentMousePosition += evt.delta; evt.Use(); if (!s_Snapping1D.Move(s_CurrentMousePosition)) { break; } var handleInverseMatrix = SceneHandles.inverseMatrix; var pointDelta = handleInverseMatrix.MultiplyVector(s_Snapping1D.WorldSnappedOffset); if (s_StartPoints != null) { points = new Vector3[points.Length]; // if we don't, it's hard to do Undo properly for (int i = 0; i < points.Length; i++) { points[i] = SnappingUtility.Quantize(s_StartPoints[i] + pointDelta); } } //SceneView.RepaintAll(); GUI.changed = true; break; } case EventType.MouseUp: { if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) { GUIUtility.hotControl = 0; GUIUtility.keyboardControl = 0; //Grid.currentGrid = s_PrevGrid; s_StartPoints = null; evt.Use(); EditorGUIUtility.SetWantsMouseJumping(0); if (!s_MovedMouse && selectLockingAxisOnClick) { switch (axis) { case Axis.X: { Snapping.ActiveAxes = Axes.X; break; } case Axis.Y: { Snapping.ActiveAxes = Axes.Y; break; } case Axis.Z: { Snapping.ActiveAxes = Axes.Z; break; } } } SceneView.RepaintAll(); } break; } #if UNITY_2020_1_OR_NEWER case EventType.MouseMove: { if (SceneHandles.InCameraOrbitMode) { break; } var position = handleOrigin; var rotation = Quaternion.LookRotation(handleDirection); if (handleSize > 0) { if (capFunction != null) { capFunction(id, position, rotation, handleSize, type); } } int currentFocusControl = SceneHandleUtility.focusControl; if ((currentFocusControl == id && s_PrevFocusControl != id) || (currentFocusControl != id && s_PrevFocusControl == id)) { s_PrevFocusControl = currentFocusControl; SceneView.RepaintAll(); } break; } #endif case EventType.Layout: { if (SceneHandles.InCameraOrbitMode) { break; } var position = handleOrigin; var rotation = Quaternion.LookRotation(handleDirection); if (handleSize > 0) { if (capFunction != null) { capFunction(id, position, rotation, handleSize, type); } else { UnityEditor.HandleUtility.AddControl(id, UnityEditor.HandleUtility.DistanceToCircle(position, handleSize * .2f)); } } int currentFocusControl = SceneHandleUtility.focusControl; if ((currentFocusControl == id && s_PrevFocusControl != id) || (currentFocusControl != id && s_PrevFocusControl == id)) { s_PrevFocusControl = currentFocusControl; SceneView.RepaintAll(); } break; } case EventType.Repaint: { if (axis != Axis.None) { if (GUIUtility.hotControl == id) { var selectedColor = SceneHandles.StateColor(SceneHandles.MultiplyTransparency(SceneHandles.selectedColor, 0.5f)); using (new SceneHandles.DrawingScope(selectedColor)) HandleRendering.RenderSnapping1D(s_Snapping1D.Min, s_Snapping1D.Max, s_Snapping1D.WorldSnappedPosition, s_Snapping1D.SlideDirection, s_Snapping1D.SnapResult, axis); } } if (capFunction == null) { break; } var position = handleOrigin; var rotation = Quaternion.LookRotation(handleDirection); var color = SceneHandles.StateColor(SceneHandles.color, isSelected: (id == s_PrevFocusControl)); using (new SceneHandles.DrawingScope(color)) { capFunction(id, position, rotation, handleSize, EventType.Repaint); } break; } } return(points); }
public static Vector3 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); }
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)); }