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