Esempio n. 1
0
        static bool FindCustomSnappingPoints(Vector3 startWorldPoint, Vector3 currentWorldPoint, Grid worldSlideGrid, int contextIndex, List <Vector3> foundWorldspacePoints)
        {
            if (!s_SnappingContext.TryGetValue(contextIndex, out var snappingContext))
            {
                s_SnappingContext[contextIndex] = snappingContext = new SnappingContext();
            }

            snappingContext.Clear();
            s_DrawSurfaceSnapEvents.Clear();
            s_DrawEdgeSnapEvents.Clear();
            s_DrawVertexSnapEvents.Clear();

            var edgeSnappingActive    = Snapping.EdgeSnappingActive;
            var vertexSnappingActive  = Snapping.VertexSnappingActive;
            var surfaceSnappingActive = Snapping.SurfaceSnappingActive;

            if (!edgeSnappingActive &&
                !vertexSnappingActive &&
                !surfaceSnappingActive)
            {
                return(false);
            }

            var surfaceSnapEvents = surfaceSnappingActive ? snappingContext.s_AllSurfaceSnapEvents : null;
            var edgeSnapEvents    = edgeSnappingActive    ? snappingContext.s_AllEdgeSnapEvents    : null;
            var vertexSnapEvents  = vertexSnappingActive  ? snappingContext.s_AllVertexSnapEvents  : null;

            var selection = Selection.gameObjects;

            FindClosestSnapPointsToPlane(selection, startWorldPoint, currentWorldPoint, worldSlideGrid, kArbitrarySnapDistance, surfaceSnapEvents, edgeSnapEvents, vertexSnapEvents);

            snappingContext.CollectAllSnapPoints(foundWorldspacePoints);
            return(true);
        }
Esempio n. 2
0
        static void FindClosestSnapPointsToPlane(GameObject[] selection, Vector3 startWorldPoint, Vector3 currentWorldPoint, Grid worldSlideGrid, float maxSnapDistance, List <SurfaceSnap> allSurfaceSnapEvents, List <EdgeSnap> allEdgeSnapEvents, List <VertexSnap> allVertexSnapEvents)
        {
            if (selection == null || selection.Length == 0)
            {
                return;
            }

            if (allSurfaceSnapEvents == null &&
                allEdgeSnapEvents == null &&
                allVertexSnapEvents == null)
            {
                return;
            }

            var worldSlidePlane = worldSlideGrid.PlaneXZ;

            var gridSnapping = Snapping.GridSnappingActive;

            if (gridSnapping)
            {
                var vectorX = worldSlideGrid.Right * maxSnapDistance;
                var vectorZ = worldSlideGrid.Forward * maxSnapDistance;

                var snappedWorldPoint = Snapping.SnapPoint(currentWorldPoint, worldSlideGrid);
                FindSnapPointsAlongRay(selection, snappedWorldPoint, vectorX, allSurfaceSnapEvents, allEdgeSnapEvents, allVertexSnapEvents);
                FindSnapPointsAlongRay(selection, snappedWorldPoint, vectorZ, allSurfaceSnapEvents, allEdgeSnapEvents, allVertexSnapEvents);

                snappedWorldPoint = Snapping.SnapPoint(startWorldPoint, worldSlideGrid);
                FindSnapPointsAlongRay(selection, snappedWorldPoint, vectorX, allSurfaceSnapEvents, allEdgeSnapEvents, allVertexSnapEvents);
                FindSnapPointsAlongRay(selection, snappedWorldPoint, vectorZ, allSurfaceSnapEvents, allEdgeSnapEvents, allVertexSnapEvents);
            }


            worldSlidePlane = new Plane(worldSlidePlane.normal, currentWorldPoint);

            s_SelectedBrushes.Clear();
            foreach (var go in selection)
            {
                if (!go)
                {
                    continue;
                }

                var node = go.GetComponent <ChiselNode>();
                if (!node)
                {
                    continue;
                }

                s_SelectedNodes.Clear();
                node.CollectCSGTreeNodes(s_SelectedNodes);
                foreach (var child in s_SelectedNodes)
                {
                    if (!child.Valid || child.Type != CSGNodeType.Brush)
                    {
                        continue;
                    }
                    s_SelectedBrushes.Add((CSGTreeBrush)child);
                }
            }

            if (s_SelectedBrushes.Count == 0)
            {
                return;
            }

            var snapDistanceSqr = maxSnapDistance * maxSnapDistance;

            EdgeSnap[] foundEdges = new EdgeSnap[2];
            int        foundEdgeCount;

            foreach (var csgBrush in s_SelectedBrushes)
            {
                var csgTree   = csgBrush.Tree;
                var brushMesh = BrushMeshManager.GetBrushMesh(csgBrush.BrushMesh);
                var polygons  = brushMesh.polygons;
                var halfEdges = brushMesh.halfEdges;
                var vertices  = brushMesh.vertices;
                var planes    = brushMesh.planes;
                var halfEdgePolygonIndices = brushMesh.halfEdgePolygonIndices;

                // TODO: store this information with brush
                var model       = ChiselNodeHierarchyManager.FindChiselNodeByInstanceID(csgTree.UserID) as ChiselModel;
                var worldToNode = csgBrush.TreeToNodeSpaceMatrix * model.hierarchyItem.WorldToLocalMatrix;
                var nodeToWorld = model.hierarchyItem.LocalToWorldMatrix * csgBrush.NodeToTreeSpaceMatrix;

                var brushPoint = worldToNode.MultiplyPoint(currentWorldPoint);
                var brushPlane = worldToNode.TransformPlane(worldSlidePlane);

                if (allVertexSnapEvents != null)
                {
                    if (gridSnapping)
                    {
                        for (int i = 0; i < vertices.Length; i++)
                        {
                            var vertex = vertices[i];
                            var dist0  = brushPlane.GetDistanceToPoint(vertex);
                            if (math.abs(dist0) > snapDistanceSqr)
                            {
                                continue;
                            }
                            allVertexSnapEvents.Add(new VertexSnap
                            {
                                brush        = csgBrush,
                                vertexIndex  = i,
                                intersection = nodeToWorld.MultiplyPoint(vertex)
                            });
                        }
                    }
                    else
                    {
                        for (int i = 0; i < vertices.Length; i++)
                        {
                            var vertex = vertices[i];
                            if (math.lengthsq(vertex - (float3)brushPoint) > snapDistanceSqr)
                            {
                                continue;
                            }
                            var dist0 = brushPlane.GetDistanceToPoint(vertex);
                            if (math.abs(dist0) > snapDistanceSqr)
                            {
                                continue;
                            }
                            allVertexSnapEvents.Add(new VertexSnap
                            {
                                brush        = csgBrush,
                                vertexIndex  = i,
                                intersection = nodeToWorld.MultiplyPoint(vertex)
                            });
                        }
                    }
                }


                if (allSurfaceSnapEvents == null &&
                    allEdgeSnapEvents == null)
                {
                    continue;
                }


                for (int surfaceIndex = 0; surfaceIndex < polygons.Length; surfaceIndex++)
                {
                    var polygon   = polygons[surfaceIndex];
                    var firstEdge = polygon.firstEdge;
                    var lastEdge  = firstEdge + polygon.edgeCount;

                    // TODO: If point is ON plane, ignore. We don't want to "snap" to every point on that surface b/c then we won't be snapping at all

                    foundEdgeCount = 0;
                    for (int e0 = lastEdge - 1, e1 = firstEdge; e1 < lastEdge; e0 = e1, e1++)
                    {
                        var i0 = halfEdges[e0].vertexIndex;
                        var i1 = halfEdges[e1].vertexIndex;

                        var vertex0 = vertices[i0];
                        var vertex1 = vertices[i1];

                        var distance0 = brushPlane.GetDistanceToPoint(vertex0);
                        var distance1 = brushPlane.GetDistanceToPoint(vertex1);

                        // Edge is plane aligned
                        if (math.abs(distance0) < kPlaneDistanceEpsilon &&
                            math.abs(distance1) < kPlaneDistanceEpsilon)
                        {
                            if (i0 < i1 && // skip duplicate edges
                                allEdgeSnapEvents != null)
                            {
                                if (gridSnapping)
                                {
                                }
                                else
                                {
                                    if (ClosestPointToLine(brushPoint, vertex0, vertex1, out Vector3 newVertex))
                                    {
                                        allEdgeSnapEvents.Add(new EdgeSnap
                                        {
                                            brush         = csgBrush,
                                            surfaceIndex0 = surfaceIndex,
                                            surfaceIndex1 = halfEdgePolygonIndices[halfEdges[e1].twinIndex],
                                            vertexIndex0  = i0,
                                            vertexIndex1  = i1,
                                            intersection  = nodeToWorld.MultiplyPoint(newVertex),
                                            from          = nodeToWorld.MultiplyPoint(vertex0),
                                            to            = nodeToWorld.MultiplyPoint(vertex1)
                                        });
                                    }
                                }
                            }
                            continue;
                        }

                        {
                            if ((distance0 < -snapDistanceSqr && distance1 < -snapDistanceSqr) ||
                                (distance0 > snapDistanceSqr && distance1 > snapDistanceSqr))
                            {
                                continue;
                            }

                            // TODO: Find intersection between plane and edge
                            var vector = vertex0 - vertex1;
                            var length = distance0 - distance1;
                            var delta  = distance0 / length;

                            if (float.IsNaN(delta) || float.IsInfinity(delta))
                            {
                                continue;
                            }

                            var newVertex = (Vector3)(vertex0 - (vector * delta));
                            var distanceN = brushPlane.GetDistanceToPoint(newVertex);

                            if ((distanceN <= distance0 && distanceN <= distance1) ||
                                (distanceN >= distance0 && distanceN >= distance1))
                            {
                                continue;
                            }

                            if ((newVertex - brushPoint).sqrMagnitude > snapDistanceSqr)
                            {
                                continue;
                            }

                            foundEdges[foundEdgeCount] = new EdgeSnap
                            {
                                brush         = csgBrush,
                                surfaceIndex0 = surfaceIndex,
                                surfaceIndex1 = halfEdgePolygonIndices[halfEdges[e1].twinIndex],
                                vertexIndex0  = i0,
                                vertexIndex1  = i1,
                                intersection  = nodeToWorld.MultiplyPoint(newVertex),
                                from          = nodeToWorld.MultiplyPoint(vertex0),
                                to            = nodeToWorld.MultiplyPoint(vertex1)
                            };
                            if (i0 < i1 && // skip duplicate edges
                                allEdgeSnapEvents != null)
                            {
                                allEdgeSnapEvents.Add(foundEdges[foundEdgeCount]);
                            }

                            foundEdgeCount++;
                            if (foundEdgeCount == 2)
                            {
                                break;
                            }
                        }
                    }

                    if (allSurfaceSnapEvents != null && foundEdgeCount > 0 && !gridSnapping)
                    {
                        if (foundEdgeCount == 2)
                        {
                            var plane      = planes[surfaceIndex];
                            var unityPlane = new Plane(plane.xyz, plane.w);

                            var vertex0 = foundEdges[0].intersection;
                            var vertex1 = foundEdges[1].intersection;

                            if (ClosestPointToLine(currentWorldPoint, vertex0, vertex1, out Vector3 closestWorldPoint))
                            {
                                allSurfaceSnapEvents.Add(new SurfaceSnap
                                {
                                    brush        = csgBrush,
                                    surfaceIndex = surfaceIndex,
                                    intersection = closestWorldPoint,
                                    normal       = nodeToWorld.MultiplyVector(unityPlane.normal),
                                });
                            }
                        }
                    }
                }
            }
        }
Esempio n. 3
0
 public static Vector3 SnapPoint(Vector3 position, Grid grid, Axes enabledAxes = Axes.XYZ)
 {
     return(SnappingUtility.SnapPoint3D(position, grid.Spacing, grid.Right, grid.Up, grid.Forward, grid.Center, enabledAxes));
 }
Esempio n. 4
0
 public static bool GetCustomSnappingPoints(Vector3 startWorldPoint, Vector3 currentWorldPoint, Grid worldSlideGrid, int contextIndex, List <Vector3> foundWorldspacePoints)
 {
     foundWorldspacePoints.Clear();
     return(Snapping.FindCustomSnappingPointsMethod == null ? false :
            Snapping.FindCustomSnappingPointsMethod(startWorldPoint, currentWorldPoint, worldSlideGrid, contextIndex, foundWorldspacePoints) &&
            foundWorldspacePoints.Count > 0);
 }
Esempio n. 5
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 (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 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 localPointDelta     = s_Snapping2D.WorldSnappedDelta;

                        var pointDelta			= handleInverseMatrix.MultiplyVector(localPointDelta);

                        if (axes != Axes.None)
                        {
                            if ((axes & Axes.X) == Axes.None) pointDelta.x = 0;
                            if ((axes & Axes.Y) == Axes.None) pointDelta.y = 0;
                            if ((axes & Axes.Z) == Axes.None) pointDelta.z = 0;
                        }

                        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;
                            s_Snapping2D.Reset();
                            evt.Use();
                            EditorGUIUtility.SetWantsMouseJumping(0);
                            SceneView.RepaintAll();
                            if (!s_MovedMouse && selectLockingAxisOnClick)
                                Snapping.ActiveAxes = axes;
                        }
                        break;
                    }
                    case EventType.Layout:
                    {
                        if (SceneHandles.InCameraOrbitMode)
                            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 &&
                                s_Snapping2D.WorldSlideGrid != null)
                            {
                                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;
            }