using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.Linq;
using System.Text;
using UnityEngine.Serialization;
namespace UnityEngine.ProBuilder
{
///
/// Defines associations between vertex positions that are [coincident](../manual/gloss.html#coincident).
/// The indexes stored in this collection correspond to the array.
///
///
/// Coincident vertices are vertices that share the same coordinate position, but are separate entries
/// in the vertex array.
///
[Serializable]
public sealed class SharedVertex : ICollection
{
///
/// Stores an array of vertex indices that are coincident.
///
[SerializeField]
[FormerlySerializedAs("array")]
[FormerlySerializedAs("m_Vertexes")]
int[] m_Vertices;
internal int[] arrayInternal
{
get { return m_Vertices; }
}
///
/// Creates a new SharedVertex from the specified indices.
///
/// An array of indices to set.
public SharedVertex(IEnumerable indexes)
{
if (indexes == null)
throw new ArgumentNullException("indexes");
m_Vertices = indexes.ToArray();
}
///
/// Creates a new SharedVertex from the specified SharedVertex object.
///
/// The SharedVertex object to copy.
public SharedVertex(SharedVertex sharedVertex)
{
if (sharedVertex == null)
throw new ArgumentNullException("sharedVertex");
m_Vertices = new int[sharedVertex.Count];
Array.Copy(sharedVertex.m_Vertices, m_Vertices, m_Vertices.Length);
}
///
/// Gets and sets the vertex by index.
///
/// The index to access.
public int this[int i]
{
get { return m_Vertices[i]; }
set { m_Vertices[i] = value; }
}
///
/// Returns an enumerator that iterates through this collection.
///
/// An IEnumerator object that you can use to iterate through the collection.
public IEnumerator GetEnumerator()
{
return ((IEnumerable)m_Vertices).GetEnumerator();
}
///
/// Returns a string that represents this SharedVertex.
///
/// A comma-delimited string (for example `"2,0,6,3"`).
public override string ToString()
{
return m_Vertices.ToString(",");
}
///
/// Returns an enumerator that iterates through this collection.
///
/// An IEnumerator object that you can use to iterate through the collection.
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
///
/// Adds a new entry using the specified index.
///
/// The index to add.
public void Add(int item)
{
m_Vertices = ArrayUtility.Add(m_Vertices, item);
}
///
/// Resets this SharedVertex object to an empty collection.
///
public void Clear()
{
m_Vertices = new int[0];
}
///
/// Returns whether the specified item exists in this collection.
///
/// The index of the item to check.
/// True if the index was found; false otherwise
public bool Contains(int item)
{
return Array.IndexOf(m_Vertices, item) > -1;
}
///
/// Copies the elements of this collection to an array, starting at the specified `arrayIndex`.
///
/// The destination array.
/// The index in the destination array where the collection items will be copied.
public void CopyTo(int[] array, int arrayIndex)
{
m_Vertices.CopyTo(array, arrayIndex);
}
///
/// Removes the specified item from this collection.
///
/// The index of the item to remove.
/// True if the index was found and removed; false otherwise
public bool Remove(int item)
{
int ind = Array.IndexOf(m_Vertices, item);
if (ind < 0)
return false;
m_Vertices = m_Vertices.RemoveAt(item);
return true;
}
///
/// Gets the number of items in this collection.
///
/// The length of this collection
public int Count
{
get { return m_Vertices.Length; }
}
///
/// Gets whether this collection is read-only.
///
/// The value of the IsReadOnly flag.
public bool IsReadOnly
{
get { return m_Vertices.IsReadOnly; }
}
///
/// Creates a lookup Dictionary in order to quickly find the index of a `SharedVertex` in the
/// array using a vertex index.
///
/// A collection of SharedVertex values.
///
/// A Dictionary where the 'key' represents an index in the Mesh positions array, and the
/// 'value' is the index of its placement in the sharedVertices array.
///
public static void GetSharedVertexLookup(IList sharedVertices, Dictionary lookup)
{
lookup.Clear();
for(int i = 0, c = sharedVertices.Count; i < c; i++)
{
foreach (var index in sharedVertices[i])
{
if (!lookup.ContainsKey(index))
lookup.Add(index, i);
}
}
}
internal void ShiftIndexes(int offset)
{
for (int i = 0, c = Count; i < c; i++)
m_Vertices[i] += offset;
}
///
/// Converts a lookup Dictionary () to a `SharedVertex` array.
///
/// An existing Dictionary where the 'key' corresponds to a vertex index, and the 'value'
/// corresponds to a common index.
/// A new IntArray[] converted from the lookup dictionary.
internal static SharedVertex[] ToSharedVertices(IEnumerable> lookup)
{
if (lookup == null)
return new SharedVertex[0];
Dictionary map = new Dictionary();
List> shared = new List>();
foreach (var kvp in lookup)
{
if (kvp.Value < 0)
{
shared.Add(new List() { kvp.Key });
}
else
{
int index = -1;
if (map.TryGetValue(kvp.Value, out index))
{
shared[index].Add(kvp.Key);
}
else
{
map.Add(kvp.Value, shared.Count);
shared.Add(new List() { kvp.Key });
}
}
}
return ToSharedVertices(shared);
}
static SharedVertex[] ToSharedVertices(List> list)
{
if (list == null)
throw new ArgumentNullException("list");
SharedVertex[] arr = new SharedVertex[list.Count];
for (int i = 0; i < arr.Length; i++)
arr[i] = new SharedVertex(list[i]);
return arr;
}
///
/// Creates a new array of SharedVertex objects by comparing points in the specified positions collection.
///
///
/// ```lang-csharp
/// ();
/// mesh.SetPositions(myNewPositions);
/// mesh.SetFaces(myNewFaces);
/// mesh.SetSharedIndexes(SharedVertex.GetSharedVerticesWithPositions(myNewPositions));]]>
/// ```
///
/// A collection of Vector3 positions to test for equality.
/// A new SharedVertex array where each item is a list of indices that share the same position.
public static SharedVertex[] GetSharedVerticesWithPositions(IList positions)
{
if (positions == null)
throw new ArgumentNullException("positions");
Dictionary> sorted = new Dictionary>();
for (int i = 0; i < positions.Count; i++)
{
List ind;
if (sorted.TryGetValue(positions[i], out ind))
ind.Add(i);
else
sorted.Add(new IntVec3(positions[i]), new List() { i });
}
SharedVertex[] share = new SharedVertex[sorted.Count];
int t = 0;
foreach (KeyValuePair> kvp in sorted)
share[t++] = new SharedVertex(kvp.Value.ToArray());
return share;
}
internal static SharedVertex[] RemoveAndShift(Dictionary lookup, IEnumerable remove)
{
var removedVertices = new List(remove);
removedVertices.Sort();
return SortedRemoveAndShift(lookup, removedVertices);
}
internal static SharedVertex[] SortedRemoveAndShift(Dictionary lookup, List remove)
{
foreach (int i in remove)
lookup[i] = -1;
var shared = ToSharedVertices(lookup.Where(x => x.Value > -1));
for (int i = 0, c = shared.Length; i < c; i++)
{
for (int n = 0, l = shared[i].Count; n < l; n++)
{
int index = ArrayUtility.NearestIndexPriorToValue(remove, shared[i][n]);
// add 1 because index is zero based
shared[i][n] -= index + 1;
}
}
return shared;
}
internal static void SetCoincident(ref Dictionary lookup, IEnumerable vertices)
{
int index = lookup.Count;
foreach (var v in vertices)
lookup[v] = index;
}
}
}