using System.Linq; using System.Collections.Generic; namespace UnityEngine.ProBuilder { /// /// Utilities for working with pb_Edge. /// static class EdgeUtility { /// /// Returns new edges where each edge is composed not of vertex indexes, but rather the index in ProBuilderMesh.sharedIndexes of each vertex. /// /// /// /// public static IEnumerable GetSharedVertexHandleEdges(this ProBuilderMesh mesh, IEnumerable edges) { return edges.Select(x => GetSharedVertexHandleEdge(mesh, x)); } public static Edge GetSharedVertexHandleEdge(this ProBuilderMesh mesh, Edge edge) { return new Edge(mesh.sharedVertexLookup[edge.a], mesh.sharedVertexLookup[edge.b]); } /// /// Converts a universal edge to local. Does *not* guarantee that edges will be valid (indexes belong to the same face and edge). /// /// /// /// internal static Edge GetEdgeWithSharedVertexHandles(this ProBuilderMesh mesh, Edge edge) { return new Edge(mesh.sharedVerticesInternal[edge.a][0], mesh.sharedVerticesInternal[edge.b][0]); } /// /// Given a local edge, this guarantees that both indexes belong to the same face. /// Note that this will only return the first valid edge found - there will usually /// be multiple matches (well, 2 if your geometry is sane). /// /// /// /// /// public static bool ValidateEdge(ProBuilderMesh mesh, Edge edge, out SimpleTuple validEdge) { Face[] faces = mesh.facesInternal; SharedVertex[] sharedIndexes = mesh.sharedVerticesInternal; Edge universal = GetSharedVertexHandleEdge(mesh, edge); for (int i = 0; i < faces.Length; i++) { int dist_x = -1, dist_y = -1, shared_x = -1, shared_y = -1; if (faces[i].distinctIndexesInternal.ContainsMatch(sharedIndexes[universal.a].arrayInternal, out dist_x, out shared_x) && faces[i].distinctIndexesInternal.ContainsMatch(sharedIndexes[universal.b].arrayInternal, out dist_y, out shared_y)) { int x = faces[i].distinctIndexesInternal[dist_x]; int y = faces[i].distinctIndexesInternal[dist_y]; validEdge = new SimpleTuple(faces[i], new Edge(x, y)); return true; } } validEdge = new SimpleTuple(); return false; } /// /// Fast contains. Doesn't account for shared indexes /// internal static bool Contains(this Edge[] edges, Edge edge) { for (int i = 0; i < edges.Length; i++) { if (edges[i].Equals(edge)) return true; } return false; } /// /// Fast contains. Doesn't account for shared indexes /// /// /// /// /// internal static bool Contains(this Edge[] edges, int x, int y) { for (int i = 0; i < edges.Length; i++) { if ((x == edges[i].a && y == edges[i].b) || (x == edges[i].b && y == edges[i].a)) return true; } return false; } internal static int IndexOf(this ProBuilderMesh mesh, IList edges, Edge edge) { for (int i = 0; i < edges.Count; i++) { if (edges[i].Equals(edge, mesh.sharedVertexLookup)) return i; } return -1; } internal static int[] AllTriangles(this Edge[] edges) { int[] arr = new int[edges.Length * 2]; int n = 0; for (int i = 0; i < edges.Length; i++) { arr[n++] = edges[i].a; arr[n++] = edges[i].b; } return arr; } internal static Face GetFace(this ProBuilderMesh mesh, Edge edge) { Face res = null; foreach (var face in mesh.facesInternal) { var edges = face.edgesInternal; for (int i = 0, c = edges.Length; i < c; i++) { if (edge.Equals(edges[i])) return face; if (edges.Contains(edges[i])) res = face; } } return res; } } }