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 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); }