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. The indexes stored in this collection correspond to the ProBuilderMesh.positions array.
///
///
/// Coincident vertices are vertices that despite sharing the same coordinate position, are separate entries in the vertex array.
///
[Serializable]
public sealed class SharedVertex : ICollection
{
///
/// An array of vertex indexes that are coincident.
///
[SerializeField]
[FormerlySerializedAs("array")]
[FormerlySerializedAs("m_Vertexes")]
int[] m_Vertices;
internal int[] arrayInternal
{
get { return m_Vertices; }
}
///
/// Create a new SharedVertex from an int array.
///
/// The array to copy.
public SharedVertex(IEnumerable indexes)
{
if (indexes == null)
throw new ArgumentNullException("indexes");
m_Vertices = indexes.ToArray();
}
///
/// Copy constructor.
///
/// The array 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);
}
///
/// Index accessor.
///
/// The index to access.
public int this[int i]
{
get { return m_Vertices[i]; }
set { m_Vertices[i] = value; }
}
///
public IEnumerator GetEnumerator()
{
return ((IEnumerable)m_Vertices).GetEnumerator();
}
///
public override string ToString()
{
return m_Vertices.ToString(",");
}
///
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
///
public void Add(int item)
{
m_Vertices = ArrayUtility.Add(m_Vertices, item);
}
///
public void Clear()
{
m_Vertices = new int[0];
}
///
public bool Contains(int item)
{
return Array.IndexOf(m_Vertices, item) > -1;
}
///
public void CopyTo(int[] array, int arrayIndex)
{
m_Vertices.CopyTo(array, arrayIndex);
}
///
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;
}
///
public int Count
{
get { return m_Vertices.Length; }
}
///
public bool IsReadOnly
{
get { return m_Vertices.IsReadOnly; }
}
///
/// A is used to associate discrete vertices that share a common position. A lookup
/// Dictionary provides a fast way to find the index of a in the
/// array with 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 it's 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;
}
///
/// Convert a lookup dictionary () back to [].
///
/// A Dictionary where Key corresponds to a vertex index, and Value 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;
}
///
/// Create a new array of SharedVertex objects by comparing points in the passed positions collection.
///
///
/// ```
/// ();]]>
/// mesh.SetPositions(myNewPositions);
/// mesh.SetFaces(myNewFaces);
/// mesh.SetSharedIndexes(SharedVertex.GetSharedVerticesWithPositions(myNewPositions));
/// ```
///
/// A collection of Vector3 positions to be tested for equality.
/// A new SharedVertex[] where each SharedIndex is a list of indexes that are sharing 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;
}
}
}