using UnityEngine; using System.Collections; using System.Collections.Generic; namespace UnityEngine.ProBuilder { /// /// Represents an edge connecting two vertices. /// /// This might point to an index in the vertices (local) or the (common) array. The ProBuilder terminology "local" and "common" refers to whether this is an index from the list of all vertices in the ProBuilderMesh or an index from the list of only shared vertices. /// /// UnityEngine.ProBuilder.ProBuilderMesh.sharedVertices /// UnityEngine.ProBuilder.EdgeLookup [System.Serializable] public struct Edge : System.IEquatable { /// /// Stores an index that corresponds to a mesh vertex array. /// public int a; /// /// Stores an index that corresponds to a mesh vertex array. /// public int b; /// /// Creates an empty edge defined as `(-1, -1)`. /// public static readonly Edge Empty = new Edge(-1, -1); /// /// Creates a new edge from two vertex indexes. /// /// An index corresponding to a mesh vertex array. /// An index corresponding to a mesh vertex array. public Edge(int a, int b) { this.a = a; this.b = b; } /// /// Tests whether this edge points to valid vertex indexes. /// /// True if x and y are both greater than -1. public bool IsValid() { return a > -1 && b > -1 && a != b; } /// /// Returns a string representation of the edge. /// /// String formatted as `[a, b]`. public override string ToString() { return "[" + a + ", " + b + "]"; } /// /// Tests whether this Edge is equal to another Edge object. /// /// The Edge to compare against. /// True if the edges are equal, false if not. public bool Equals(Edge other) { return (a == other.a && b == other.b) || (a == other.b && b == other.a); } /// /// Tests whether this object is equal to another object. /// /// The object to compare against. /// True if the edges are equal, false if not. public override bool Equals(object obj) { return obj is Edge && Equals((Edge)obj); } /// /// Returns the hash code for this instance. /// /// An integer that is the hash code for this instance. public override int GetHashCode() { // http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode/263416#263416 int hash = 27; unchecked { hash = hash * 29 + (a < b ? a : b); hash = hash * 29 + (a < b ? b : a); } return hash; } /// /// Creates a new Edge by adding the two left indices together and the two right indices together from both Edge objects. /// /// Left edge. /// Right edge. /// A new edge where `{x, y} = {(a.a + b.a), (a.b + b.b)}`. public static Edge operator+(Edge a, Edge b) { return new Edge(a.a + b.a, a.b + b.b); } /// /// Creates a new Edge by subtracting the two left indices together and the two right indices together from both Edge objects. /// /// Left edge. /// Right edge. /// A new edge where `{x, y} = {(a.a - b.a), (a.b - b.b)}`. public static Edge operator-(Edge a, Edge b) { return new Edge(a.a - b.a, a.b - b.b); } /// /// Creates a new Edge by adding an integer to both indices on an Edge object. /// /// The Edge to add to. /// The value to add. /// A new edge where `{x, y} = {(a.a + b), (a.b + b)}`. public static Edge operator+(Edge a, int b) { return new Edge(a.a + b, a.b + b); } /// /// Creates a new Edge by subtracting an integer from both indices on an Edge object. /// /// The Edge to subtract from. /// The value to subtract. /// A new edge where `{x, y} = {(a.a - b), (a.b - b)}`. public static Edge operator-(Edge a, int b) { return new Edge(a.a - b, a.b - b); } /// /// Compares two objects for equality. /// /// The first Edge instance. /// The second Edge instance. /// True if the objects are equal; false if not. public static bool operator==(Edge a, Edge b) { return a.Equals(b); } /// /// Returns true if the two objects are not equal. /// /// The first Edge instance. /// The second Edge instance. /// True if the objects are not equal; false if they are equal. public static bool operator!=(Edge a, Edge b) { return !(a == b); } /// /// Adds two edges index values. /// /// /// {0, 1} + {4, 5} = {5, 6} /// /// Left edge parameter. /// Right edge parameter. /// The sum of `a + b`. public static Edge Add(Edge a, Edge b) { return a + b; } /// /// Subtracts edge b from a. /// /// /// Subtract( {7, 10}, {4, 5} ) = {3, 5} /// /// The edge to subtract from. /// The value to subtract. /// The difference of `a - b`. public static Edge Subtract(Edge a, Edge b) { return a - b; } /// /// Compares edges and takes shared triangles into account. /// /// The edge to compare against. /// A common vertex indexes lookup dictionary. See pb_IntArray for more information. /// Generally you just pass ProBuilderMesh.sharedIndexes.ToDictionary() to lookup, but it's more efficient to do it once and reuse that dictionary if possible. /// True if edges are perceptually equal (that is, they point to the same common indexes). public bool Equals(Edge other, Dictionary lookup) { if (lookup == null) return Equals(other); int x0 = lookup[a], y0 = lookup[b], x1 = lookup[other.a], y1 = lookup[other.b]; return (x0 == x1 && y0 == y1) || (x0 == y1 && y0 == x1); } /// /// Tests whether this edge contains an index. /// /// The index to compare against x and y. /// True if x or y is equal to a. False if not. public bool Contains(int index) { return (a == index || b == index); } /// /// Tests whether this edge has any matching index to the other edge `b`. /// /// The edge to compare against. /// True if x or y matches either b.x or b.y. public bool Contains(Edge other) { return (a == other.a || b == other.a || a == other.b || b == other.a); } internal bool Contains(int index, Dictionary lookup) { var common = lookup[index]; return lookup[a] == common || lookup[b] == common; } internal static void GetIndices(IEnumerable edges, List indices) { indices.Clear(); foreach (var edge in edges) { indices.Add(edge.a); indices.Add(edge.b); } } } }