public static List <ElementGroup> GetElementGroups(ProBuilderMesh mesh, bool collectCoincident)
        {
            var groups     = new List <ElementGroup>();
            var selectMode = ProBuilderEditor.selectMode;

            if (selectMode.ContainsFlag(SelectMode.Vertex | SelectMode.TextureVertex))
            {
                foreach (var list in GetVertexSelectionGroups(mesh, collectCoincident))
                {
                    var pos = PHandleUtility.GetActiveElementPosition(mesh, list);
                    var rot = PHandleUtility.GetVertexRotation(mesh, HandleOrientation.ActiveElement, list);
                    groups.Add(new ElementGroup(list, pos, rot));
                }
            }
            else if (selectMode.ContainsFlag(SelectMode.Edge | SelectMode.TextureEdge))
            {
                foreach (var list in GetEdgeSelectionGroups(mesh))
                {
                    var pos = PHandleUtility.GetActiveElementPosition(mesh, list);
                    var rot = PHandleUtility.GetEdgeRotation(mesh, HandleOrientation.ActiveElement, list);

                    List <int> indices;

                    if (collectCoincident)
                    {
                        indices = new List <int>();
                        mesh.GetCoincidentVertices(list, indices);
                    }
                    else
                    {
                        indices = list.SelectMany(x => new int[] { x.a, x.b }).ToList();
                    }

                    groups.Add(new ElementGroup(indices, pos, rot));
                }
            }
            else if (selectMode.ContainsFlag(SelectMode.Face | SelectMode.TextureFace))
            {
                foreach (var list in GetFaceSelectionGroups(mesh))
                {
                    var        pos = PHandleUtility.GetActiveElementPosition(mesh, list);
                    var        rot = PHandleUtility.GetFaceRotation(mesh, HandleOrientation.ActiveElement, list);
                    List <int> indices;

                    if (collectCoincident)
                    {
                        indices = new List <int>();
                        mesh.GetCoincidentVertices(list, indices);
                    }
                    else
                    {
                        indices = list.SelectMany(x => x.distinctIndexesInternal).ToList();
                    }

                    groups.Add(new ElementGroup(indices, pos, rot));
                }
            }

            return(groups);
        }
예제 #2
0
        static EdgeAndDistance GetNearestEdgeOnMesh(ProBuilderMesh mesh, Vector3 mousePosition)
        {
            Ray ray = UHandleUtility.GUIPointToWorldRay(mousePosition);

            var res = new EdgeAndDistance()
            {
                edge     = Edge.Empty,
                distance = Mathf.Infinity
            };

            SimpleTuple <Face, Vector3> s_DualCullModeRaycastBackFace  = new SimpleTuple <Face, Vector3>();
            SimpleTuple <Face, Vector3> s_DualCullModeRaycastFrontFace = new SimpleTuple <Face, Vector3>();

            // get the nearest hit face and point for both cull mode front and back, then prefer the result that is nearest the camera.
            if (PHandleUtility.FaceRaycastBothCullModes(ray, mesh, ref s_DualCullModeRaycastBackFace, ref s_DualCullModeRaycastFrontFace))
            {
                Vector3[] v = mesh.positionsInternal;

                if (s_DualCullModeRaycastBackFace.item1 != null)
                {
                    foreach (var edge in s_DualCullModeRaycastBackFace.item1.edgesInternal)
                    {
                        float d = UHandleUtility.DistancePointLine(s_DualCullModeRaycastBackFace.item2, v[edge.a], v[edge.b]);

                        if (d < res.distance)
                        {
                            res.edge     = edge;
                            res.distance = d;
                        }
                    }
                }

                if (s_DualCullModeRaycastFrontFace.item1 != null)
                {
                    var a = mesh.transform.TransformPoint(s_DualCullModeRaycastBackFace.item2);
                    var b = mesh.transform.TransformPoint(s_DualCullModeRaycastFrontFace.item2);
                    var c = SceneView.lastActiveSceneView.camera.transform.position;

                    if (Vector3.Distance(c, b) < Vector3.Distance(c, a))
                    {
                        foreach (var edge in s_DualCullModeRaycastFrontFace.item1.edgesInternal)
                        {
                            float d = UHandleUtility.DistancePointLine(s_DualCullModeRaycastFrontFace.item2, v[edge.a], v[edge.b]);

                            if (d < res.distance)
                            {
                                res.edge     = edge;
                                res.distance = d;
                            }
                        }
                    }
                }

                if (res.edge.IsValid())
                {
                    res.distance = UHandleUtility.DistanceToLine(
                        mesh.transform.TransformPoint(v[res.edge.a]),
                        mesh.transform.TransformPoint(v[res.edge.b]));
                }
            }

            return(res);
        }