public void Reset() { startWorldPlanePosition = Vector3.zero; worldSlidePlane = new Plane(Vector3.up, 0); worldSlideGrid = null; gridSlideExtents = new Extents3D(Vector3.zero); worldSlideOrigin = Vector3.zero; worldSlidePosition = Vector3.zero; worldSnappedPosition = Vector3.zero; localToWorldMatrix = Matrix4x4.identity; snapResult = SnapResult3D.None; }
public void Initialize(Grid worldSlideGrid, Vector2 currentGUIPosition, Vector3 localSlideOrigin, Matrix4x4 localToWorldMatrix) { this.localToWorldMatrix = localToWorldMatrix; this.worldSlidePosition = this.worldSlideOrigin; this.worldSlideGrid = worldSlideGrid; var worldSlideOrigin = this.localToWorldMatrix.MultiplyPoint(localSlideOrigin); var gridSlideOrigin = this.worldSlideGrid.WorldToGridSpace.MultiplyPoint(worldSlideOrigin); this.gridSlideExtents.min = gridSlideOrigin; this.gridSlideExtents.max = gridSlideOrigin; this.worldSlideOrigin = worldSlideOrigin; this.worldSnappedPosition = worldSlideOrigin; this.worldSlidePlane = this.worldSlideGrid.PlaneXZ; this.snapResult = SnapResult3D.None; GetPlaneIntersection(currentGUIPosition, out startWorldPlanePosition); }
public void Reset() { startWorldPlanePosition = Vector3.zero; worldSlidePlane = new Plane(Vector3.up, 0); vectorX = Vector3.right; vectorZ = Vector3.forward; worldSlideGrid = null; gridSlideExtents = new Extents3D(Vector3.zero); worldSlideOrigin = Vector3.zero; worldSlidePosition = Vector3.zero; worldSnappedPosition = Vector3.zero; localToWorldMatrix = Matrix4x4.identity; snapResult = SnapResult3D.None; #if ENABLE_DEBUG_GRID Grid.debugGrid = null; #endif }
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 static void RenderCrossXZ(Extents3D extents, float y, Vector3 handleOrigin, SnapResult3D snapResult) { if ((snapResult & SnapResult3D.MinX) != 0) { InfiniteLine(extents.min.x, y, handleOrigin.z, Axis.Z); } if ((snapResult & SnapResult3D.MaxX) != 0) { InfiniteLine(extents.max.x, y, handleOrigin.z, Axis.Z); } if ((snapResult & SnapResult3D.MinZ) != 0) { InfiniteLine(handleOrigin.x, y, extents.min.z, Axis.X); } if ((snapResult & SnapResult3D.MaxZ) != 0) { InfiniteLine(handleOrigin.x, y, extents.max.z, Axis.X); } if ((snapResult & SnapResult3D.PivotX) != 0) { InfiniteLine(handleOrigin.x, y, handleOrigin.z, Axis.Z); } if ((snapResult & SnapResult3D.PivotZ) != 0) { InfiniteLine(handleOrigin.x, y, handleOrigin.z, Axis.X); } }
public static void RenderSnapping3D(Grid grid, Extents3D extents, Vector3 pivotPosition, SnapResult3D snapResult, bool ignorePivot = false) { if (Event.current.type != EventType.Repaint) { return; } using (new SceneHandles.DrawingScope(grid.GridToWorldSpace)) { if (extents.min.x == extents.max.x && (snapResult & SnapResult3D.MinX) != 0) { snapResult &= ~SnapResult3D.MaxX; } if (extents.min.y == extents.max.y && (snapResult & SnapResult3D.MinY) != 0) { snapResult &= ~SnapResult3D.MaxY; } if (extents.min.z == extents.max.z && (snapResult & SnapResult3D.MinZ) != 0) { snapResult &= ~SnapResult3D.MaxZ; } if (ignorePivot) { snapResult &= ~SnapResult3D.PivotX; snapResult &= ~SnapResult3D.PivotY; snapResult &= ~SnapResult3D.PivotZ; } else { if (extents.min.x == pivotPosition.x && (snapResult & SnapResult3D.MinX) != 0) { snapResult &= ~SnapResult3D.PivotX; } if (extents.min.y == pivotPosition.y && (snapResult & SnapResult3D.MinY) != 0) { snapResult &= ~SnapResult3D.PivotY; } if (extents.min.z == pivotPosition.z && (snapResult & SnapResult3D.MinZ) != 0) { snapResult &= ~SnapResult3D.PivotZ; } if (extents.max.x == pivotPosition.x && (snapResult & SnapResult3D.MaxX) != 0) { snapResult &= ~SnapResult3D.PivotX; } if (extents.max.y == pivotPosition.y && (snapResult & SnapResult3D.MaxY) != 0) { snapResult &= ~SnapResult3D.PivotY; } if (extents.max.z == pivotPosition.z && (snapResult & SnapResult3D.MaxZ) != 0) { snapResult &= ~SnapResult3D.PivotZ; } } float y = 0; if (extents.min.y > 0) { y = extents.min.y; } else if (extents.max.y < 0) { y = extents.max.y; } RenderCrossXZ(extents, y, pivotPosition, snapResult); RenderBox(extents); var color = SceneHandles.color; color.a *= 0.5f; SceneHandles.color = color; if (y != 0) { RenderSquareXZ(extents, 0); if ((snapResult & SnapResult3D.MinX) != 0) { var center = new Vector3(extents.min.x, y, pivotPosition.z); if ((snapResult & SnapResult3D.MinZ) != 0) { SceneHandles.DrawDottedLine(new Vector3(center.x, 0, extents.min.z), new Vector3(center.x, center.y, extents.min.z), 4.0f); } if ((snapResult & SnapResult3D.MaxZ) != 0) { SceneHandles.DrawDottedLine(new Vector3(center.x, 0, extents.max.z), new Vector3(center.x, center.y, extents.max.z), 4.0f); } } if ((snapResult & SnapResult3D.MinZ) != 0) { var center = new Vector3(pivotPosition.x, y, extents.min.z); if ((snapResult & SnapResult3D.MinX) != 0) { SceneHandles.DrawDottedLine(new Vector3(extents.min.x, 0, center.z), new Vector3(extents.min.x, center.y, center.z), 4.0f); } if ((snapResult & SnapResult3D.MaxX) != 0) { SceneHandles.DrawDottedLine(new Vector3(extents.max.x, 0, center.z), new Vector3(extents.max.x, center.y, center.z), 4.0f); } } if ((snapResult & SnapResult3D.MaxX) != 0) { var center = new Vector3(extents.max.x, y, pivotPosition.z); if ((snapResult & SnapResult3D.MinZ) != 0) { SceneHandles.DrawDottedLine(new Vector3(center.x, 0, extents.min.z), new Vector3(center.x, center.y, extents.min.z), 4.0f); } if ((snapResult & SnapResult3D.MaxZ) != 0) { SceneHandles.DrawDottedLine(new Vector3(center.x, 0, extents.max.z), new Vector3(center.x, center.y, extents.max.z), 4.0f); } } if ((snapResult & SnapResult3D.MaxZ) != 0) { var center = new Vector3(pivotPosition.x, y, extents.max.z); if ((snapResult & SnapResult3D.MinX) != 0) { SceneHandles.DrawDottedLine(new Vector3(extents.min.x, 0, center.z), new Vector3(extents.min.x, center.y, center.z), 4.0f); } if ((snapResult & SnapResult3D.MaxX) != 0) { SceneHandles.DrawDottedLine(new Vector3(extents.max.x, 0, center.z), new Vector3(extents.max.x, center.y, center.z), 4.0f); } } } } }
public static void RenderSnapping3D(Grid grid, Extents3D extents, SnapResult3D snapResult) { RenderSnapping3D(grid, extents, extents.min, snapResult, true); }
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); }