using System.Collections.Generic; using System.Collections; using System; namespace UnityEngine.Animations.Rigging { /// /// This struct defines a List of WeightedTransform. /// WeightedTransformArray can be animated (as opposed to System.List and C# arrays) and is implemented /// with a hard limit of eight WeightedTransform elements. /// See also and . /// [Serializable] public struct WeightedTransformArray : IList, IList { /// Maximum number of elements in WeightedTransformArray. public static readonly int k_MaxLength = 8; [SerializeField, NotKeyable] private int m_Length; [SerializeField] private WeightedTransform m_Item0; [SerializeField] private WeightedTransform m_Item1; [SerializeField] private WeightedTransform m_Item2; [SerializeField] private WeightedTransform m_Item3; [SerializeField] private WeightedTransform m_Item4; [SerializeField] private WeightedTransform m_Item5; [SerializeField] private WeightedTransform m_Item6; [SerializeField] private WeightedTransform m_Item7; /// /// Constructor. /// /// Size of the array. This will clamped to be a number in between 0 and k_MaxLength. /// public WeightedTransformArray(int size) { m_Length = ClampSize(size); m_Item0 = new WeightedTransform(); m_Item1 = new WeightedTransform(); m_Item2 = new WeightedTransform(); m_Item3 = new WeightedTransform(); m_Item4 = new WeightedTransform(); m_Item5 = new WeightedTransform(); m_Item6 = new WeightedTransform(); m_Item7 = new WeightedTransform(); } /// /// Returns an enumerator that iterates through a collection. /// /// An IEnumerator object that can be used to iterate through the collection. public IEnumerator GetEnumerator() { return new Enumerator(ref this); } /// /// Returns an enumerator that iterates through a collection. /// /// An IEnumerator object that can be used to iterate through the collection. IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(ref this); } /// /// Adds an item to the WeightedTransformArray. /// /// The object to add to the WeightedTransformArray. /// The position into which the new element was inserted, or -1 to indicate that the item was not inserted into the collection. int IList.Add(object value) { Add((WeightedTransform)value); return m_Length - 1; } /// /// Adds an item to the WeightedTransformArray. /// /// The WeightedTransform to add to the WeightedTransformArray. public void Add(WeightedTransform value) { if (m_Length >= k_MaxLength) throw new ArgumentException($"This array cannot have more than '{k_MaxLength}' items."); Set(m_Length, value); ++m_Length; } /// /// Removes all items from the WeightedTransformArray. /// public void Clear() { m_Length = 0; } /// /// Determines the index of a specific item in the WeightedTransformArray. /// /// The object to locate in the WeightedTransformArray. /// The index of value if found in the list; otherwise, -1. int IList.IndexOf(object value) => IndexOf((WeightedTransform)value); /// /// Determines the index of a specific item in the WeightedTransformArray. /// /// The WeightedTransform to locate in the WeightedTransformArray. /// The index of value if found in the list; otherwise, -1. public int IndexOf(WeightedTransform value) { for (int i = 0; i < m_Length; ++i) { if (Get(i).Equals(value)) return i; } return -1; } /// /// Determines whether the WeightedTransformArray contains a specific value. /// /// The object to locate in the WeightedTransformArray. /// true if the Object is found in the WeightedTransformArray; otherwise, false. bool IList.Contains(object value) => Contains((WeightedTransform)value); /// /// Determines whether the WeightedTransformArray contains a specific value. /// /// The WeightedTransform to locate in the WeightedTransformArray. /// true if the Object is found in the WeightedTransformArray; otherwise, false. public bool Contains(WeightedTransform value) { for (int i = 0; i < m_Length; ++i) { if (Get(i).Equals(value)) return true; } return false; } /// /// Copies the elements of the WeightedTransform to an Array, starting at a particular Array index. /// /// The one-dimensional Array that is the destination of the elements copied from WeightedTransform. The Array must have zero-based indexing. /// The zero-based index in array at which copying begins. void ICollection.CopyTo(Array array, int arrayIndex) { if (array == null) throw new ArgumentNullException("The array cannot be null."); if (arrayIndex < 0) throw new ArgumentOutOfRangeException("The starting array index cannot be negative."); if (Count > array.Length - arrayIndex + 1) throw new ArgumentException("The destination array has fewer elements than the collection."); for (int i = 0; i < m_Length; i++) { array.SetValue(Get(i), i + arrayIndex); } } /// /// Copies the elements of the WeightedTransform to an Array, starting at a particular Array index. /// /// The one-dimensional Array that is the destination of the elements copied from WeightedTransform. The Array must have zero-based indexing. /// The zero-based index in array at which copying begins. public void CopyTo(WeightedTransform[] array, int arrayIndex) { if (array == null) throw new ArgumentNullException("The array cannot be null."); if (arrayIndex < 0) throw new ArgumentOutOfRangeException("The starting array index cannot be negative."); if (Count > array.Length - arrayIndex + 1) throw new ArgumentException("The destination array has fewer elements than the collection."); for (int i = 0; i < m_Length; i++) { array[i + arrayIndex] = Get(i); } } /// /// Removes the first occurrence of a specific object from the WeightedTransformArray. /// /// The object to remove from the WeightedTransformArray. void IList.Remove(object value) { Remove((WeightedTransform)value); } /// /// Removes the first occurrence of a specific WeightedTransform from the WeightedTransformArray. /// /// The WeightedTransform to remove from the WeightedTransformArray. /// True if value was removed from the array, false otherwise. public bool Remove(WeightedTransform value) { for (int i = 0; i < m_Length; ++i) { if (Get(i).Equals(value)) { for (; i < m_Length - 1; ++i) { Set(i, Get(i + 1)); } --m_Length; return true; } } return false; } /// /// Removes the WeightedTransformArray item at the specified index. /// /// The zero-based index of the item to remove. public void RemoveAt(int index) { CheckOutOfRangeIndex(index); for (int i = index; i < m_Length - 1; ++i) { Set(i, Get(i + 1)); } --m_Length; } /// /// Inserts an item to the WeightedTransformArray at the specified index. /// /// The zero-based index at which value should be inserted. /// The object to insert into the WeightedTransformArray. void IList.Insert(int index, object value) => Insert(index, (WeightedTransform)value); /// /// Inserts an item to the WeightedTransformArray at the specified index. /// /// The zero-based index at which value should be inserted. /// The WeightedTransform to insert into the WeightedTransformArray. public void Insert(int index, WeightedTransform value) { if (m_Length >= k_MaxLength) throw new ArgumentException($"This array cannot have more than '{k_MaxLength}' items."); CheckOutOfRangeIndex(index); if (index >= m_Length) { Add(value); return; } for (int i = m_Length; i > index; --i) { Set(i, Get(i - 1)); } Set(index, value); ++m_Length; } /// /// Clamps specified value in between 0 and k_MaxLength. /// /// Size value. /// Value in between 0 and k_MaxLength. /// private static int ClampSize(int size) { return Mathf.Clamp(size, 0, k_MaxLength); } /// /// Checks whether specified index value in within bounds. /// /// Index value. /// Index value is not between 0 and k_MaxLength. /// private void CheckOutOfRangeIndex(int index) { if (index < 0 || index >= k_MaxLength) throw new IndexOutOfRangeException($"Index {index} is out of range of '{m_Length}' Length."); } /// /// Retrieves a WeightedTransform at specified index. /// /// Index value. /// The WeightedTransform value at specified index. private WeightedTransform Get(int index) { CheckOutOfRangeIndex(index); switch(index) { case 0: return m_Item0; case 1: return m_Item1; case 2: return m_Item2; case 3: return m_Item3; case 4: return m_Item4; case 5: return m_Item5; case 6: return m_Item6; case 7: return m_Item7; } // Shouldn't happen. return m_Item0; } /// /// Sets a WeightedTransform at specified index. /// /// Index value. /// The WeightedTransform value to set. private void Set(int index, WeightedTransform value) { CheckOutOfRangeIndex(index); switch(index) { case 0: m_Item0 = value; break; case 1: m_Item1 = value; break; case 2: m_Item2 = value; break; case 3: m_Item3 = value; break; case 4: m_Item4 = value; break; case 5: m_Item5 = value; break; case 6: m_Item6 = value; break; case 7: m_Item7 = value; break; } } /// /// Sets a weight on a WeightedTransform at specified index. /// /// Index value. /// The weight value to set. public void SetWeight(int index, float weight) { var weightedTransform = Get(index); weightedTransform.weight = weight; Set(index, weightedTransform); } /// /// Retrieves a weight on a WeightedTransform at specified index. /// /// Index value. /// The weight value at specified index. public float GetWeight(int index) { return Get(index).weight; } /// /// Sets the Transform reference on a WeightedTransform at specified index. /// /// Index value. /// The Transform reference to set. public void SetTransform(int index, Transform transform) { var weightedTransform = Get(index); weightedTransform.transform = transform; Set(index, weightedTransform); } /// /// Retrieves a Transform reference on a WeightedTransform at specified index. /// /// Index value. /// The Transform reference at specified index. public Transform GetTransform(int index) { return Get(index).transform; } /// /// Method to call from a provider's OnValidate() callback to ensure all weight values are within the valid range. /// See also . /// /// WeightedTransformArray to adjust. /// Minimum value to clamp array values with. /// Maximum value to clamp array values with. public static void OnValidate(ref WeightedTransformArray array, float min = 0f, float max = 1f) { for (var i = 0; i < k_MaxLength; ++i) array.SetWeight(i, Mathf.Clamp(array.GetWeight(i), min, max)); } /// /// Gets or sets the element at the specified index. /// /// The zero-based index of the element to get or set. object IList.this[int index] { get => (object)Get(index); set => Set(index, (WeightedTransform)value); } /// /// Gets or sets the WeightedTransform at the specified index. /// /// The zero-based index of the WeightedTransform to get or set. public WeightedTransform this[int index] { get => Get(index); set => Set(index, value); } /// The number of elements contained in the WeightedTransformArray. public int Count { get => m_Length; } /// /// Retrieves whether WeightedTransformArray is read-only. Always false. /// public bool IsReadOnly { get => false; } /// /// Retrieves whether WeightedTransformArray has a fixed size. Always false. /// public bool IsFixedSize { get => false; } bool ICollection.IsSynchronized { get => true; } object ICollection.SyncRoot { get => null; } [System.Serializable] private struct Enumerator : IEnumerator { private WeightedTransformArray m_Array; private int m_Index; public Enumerator(ref WeightedTransformArray array) { m_Array = array; m_Index = -1; } public bool MoveNext() { m_Index++; return (m_Index < m_Array.Count); } public void Reset() { m_Index = -1; } void IDisposable.Dispose() { } public WeightedTransform Current => m_Array.Get(m_Index); object IEnumerator.Current => Current; } } }