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