455 lines
17 KiB
C#
455 lines
17 KiB
C#
using System.Collections.Generic;
|
|
using System.Collections;
|
|
using System;
|
|
|
|
namespace UnityEngine.Animations.Rigging
|
|
{
|
|
/// <summary>
|
|
/// 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 <seealso cref="WeightedTransform"/> and <seealso cref="WeightRangeAttribute"/>.
|
|
/// </summary>
|
|
[Serializable]
|
|
public struct WeightedTransformArray : IList<WeightedTransform>, IList
|
|
{
|
|
/// <summary>Maximum number of elements in WeightedTransformArray.</summary>
|
|
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;
|
|
|
|
/// <summary>
|
|
/// Constructor.
|
|
/// </summary>
|
|
/// <param name="size">Size of the array. This will clamped to be a number in between 0 and k_MaxLength.</param>
|
|
/// <seealso cref="WeightedTransformArray.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();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns an enumerator that iterates through a collection.
|
|
/// </summary>
|
|
/// <returns>An IEnumerator object that can be used to iterate through the collection.</returns>
|
|
public IEnumerator<WeightedTransform> GetEnumerator()
|
|
{
|
|
return new Enumerator(ref this);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns an enumerator that iterates through a collection.
|
|
/// </summary>
|
|
/// <returns>An IEnumerator object that can be used to iterate through the collection.</returns>
|
|
IEnumerator IEnumerable.GetEnumerator()
|
|
{
|
|
return new Enumerator(ref this);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds an item to the WeightedTransformArray.
|
|
/// </summary>
|
|
/// <param name="value">The object to add to the WeightedTransformArray.</param>
|
|
/// <returns>The position into which the new element was inserted, or -1 to indicate that the item was not inserted into the collection.</returns>
|
|
int IList.Add(object value)
|
|
{
|
|
Add((WeightedTransform)value);
|
|
return m_Length - 1;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds an item to the WeightedTransformArray.
|
|
/// </summary>
|
|
/// <param name="value">The WeightedTransform to add to the WeightedTransformArray.</param>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes all items from the WeightedTransformArray.
|
|
/// </summary>
|
|
public void Clear()
|
|
{
|
|
m_Length = 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines the index of a specific item in the WeightedTransformArray.
|
|
/// </summary>
|
|
/// <param name="value">The object to locate in the WeightedTransformArray.</param>
|
|
/// <returns>The index of value if found in the list; otherwise, -1.</returns>
|
|
int IList.IndexOf(object value) => IndexOf((WeightedTransform)value);
|
|
|
|
/// <summary>
|
|
/// Determines the index of a specific item in the WeightedTransformArray.
|
|
/// </summary>
|
|
/// <param name="value">The WeightedTransform to locate in the WeightedTransformArray.</param>
|
|
/// <returns>The index of value if found in the list; otherwise, -1.</returns>
|
|
public int IndexOf(WeightedTransform value)
|
|
{
|
|
for (int i = 0; i < m_Length; ++i)
|
|
{
|
|
if (Get(i).Equals(value))
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines whether the WeightedTransformArray contains a specific value.
|
|
/// </summary>
|
|
/// <param name="value">The object to locate in the WeightedTransformArray.</param>
|
|
/// <returns>true if the Object is found in the WeightedTransformArray; otherwise, false.</returns>
|
|
bool IList.Contains(object value) => Contains((WeightedTransform)value);
|
|
|
|
/// <summary>
|
|
/// Determines whether the WeightedTransformArray contains a specific value.
|
|
/// </summary>
|
|
/// <param name="value">The WeightedTransform to locate in the WeightedTransformArray.</param>
|
|
/// <returns>true if the Object is found in the WeightedTransformArray; otherwise, false.</returns>
|
|
public bool Contains(WeightedTransform value)
|
|
{
|
|
for (int i = 0; i < m_Length; ++i)
|
|
{
|
|
if (Get(i).Equals(value))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copies the elements of the WeightedTransform to an Array, starting at a particular Array index.
|
|
/// </summary>
|
|
/// <param name="array">The one-dimensional Array that is the destination of the elements copied from WeightedTransform. The Array must have zero-based indexing.</param>
|
|
/// <param name="arrayIndex">The zero-based index in array at which copying begins.</param>
|
|
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);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copies the elements of the WeightedTransform to an Array, starting at a particular Array index.
|
|
/// </summary>
|
|
/// <param name="array">The one-dimensional Array that is the destination of the elements copied from WeightedTransform. The Array must have zero-based indexing.</param>
|
|
/// <param name="arrayIndex">The zero-based index in array at which copying begins.</param>
|
|
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);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes the first occurrence of a specific object from the WeightedTransformArray.
|
|
/// </summary>
|
|
/// <param name="value">The object to remove from the WeightedTransformArray.</param>
|
|
void IList.Remove(object value) { Remove((WeightedTransform)value); }
|
|
|
|
/// <summary>
|
|
/// Removes the first occurrence of a specific WeightedTransform from the WeightedTransformArray.
|
|
/// </summary>
|
|
/// <param name="value">The WeightedTransform to remove from the WeightedTransformArray.</param>
|
|
/// <returns>True if value was removed from the array, false otherwise.</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes the WeightedTransformArray item at the specified index.
|
|
/// </summary>
|
|
/// <param name="index">The zero-based index of the item to remove.</param>
|
|
public void RemoveAt(int index)
|
|
{
|
|
CheckOutOfRangeIndex(index);
|
|
|
|
for (int i = index; i < m_Length - 1; ++i)
|
|
{
|
|
Set(i, Get(i + 1));
|
|
}
|
|
|
|
--m_Length;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Inserts an item to the WeightedTransformArray at the specified index.
|
|
/// </summary>
|
|
/// <param name="index">The zero-based index at which value should be inserted.</param>
|
|
/// <param name="value">The object to insert into the WeightedTransformArray.</param>
|
|
void IList.Insert(int index, object value) => Insert(index, (WeightedTransform)value);
|
|
|
|
/// <summary>
|
|
/// Inserts an item to the WeightedTransformArray at the specified index.
|
|
/// </summary>
|
|
/// <param name="index">The zero-based index at which value should be inserted.</param>
|
|
/// <param name="value">The WeightedTransform to insert into the WeightedTransformArray.</param>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clamps specified value in between 0 and k_MaxLength.
|
|
/// </summary>
|
|
/// <param name="size">Size value.</param>
|
|
/// <returns>Value in between 0 and k_MaxLength.</returns>
|
|
/// <seealso cref="WeightedTransformArray.k_MaxLength"/>
|
|
private static int ClampSize(int size)
|
|
{
|
|
return Mathf.Clamp(size, 0, k_MaxLength);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks whether specified index value in within bounds.
|
|
/// </summary>
|
|
/// <param name="index">Index value.</param>
|
|
/// <exception cref="IndexOutOfRangeException">Index value is not between 0 and k_MaxLength.</exception>
|
|
/// <seealso cref="WeightedTransformArray.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.");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieves a WeightedTransform at specified index.
|
|
/// </summary>
|
|
/// <param name="index">Index value.</param>
|
|
/// <returns>The WeightedTransform value at specified index.</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets a WeightedTransform at specified index.
|
|
/// </summary>
|
|
/// <param name="index">Index value.</param>
|
|
/// <param name="value">The WeightedTransform value to set.</param>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets a weight on a WeightedTransform at specified index.
|
|
/// </summary>
|
|
/// <param name="index">Index value.</param>
|
|
/// <param name="weight">The weight value to set.</param>
|
|
public void SetWeight(int index, float weight)
|
|
{
|
|
var weightedTransform = Get(index);
|
|
weightedTransform.weight = weight;
|
|
|
|
Set(index, weightedTransform);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieves a weight on a WeightedTransform at specified index.
|
|
/// </summary>
|
|
/// <param name="index">Index value.</param>
|
|
/// <returns>The weight value at specified index.</returns>
|
|
public float GetWeight(int index)
|
|
{
|
|
return Get(index).weight;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the Transform reference on a WeightedTransform at specified index.
|
|
/// </summary>
|
|
/// <param name="index">Index value.</param>
|
|
/// <param name="transform">The Transform reference to set.</param>
|
|
public void SetTransform(int index, Transform transform)
|
|
{
|
|
var weightedTransform = Get(index);
|
|
weightedTransform.transform = transform;
|
|
|
|
Set(index, weightedTransform);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieves a Transform reference on a WeightedTransform at specified index.
|
|
/// </summary>
|
|
/// <param name="index">Index value.</param>
|
|
/// <returns>The Transform reference at specified index.</returns>
|
|
public Transform GetTransform(int index)
|
|
{
|
|
return Get(index).transform;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Method to call from a provider's OnValidate() callback to ensure all weight values are within the valid range.
|
|
/// See also <seealso cref="WeightRangeAttribute"/>.
|
|
/// </summary>
|
|
/// <param name="array">WeightedTransformArray to adjust.</param>
|
|
/// <param name="min">Minimum value to clamp array values with.</param>
|
|
/// <param name="max">Maximum value to clamp array values with.</param>
|
|
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));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the element at the specified index.
|
|
/// </summary>
|
|
/// <param name="index">The zero-based index of the element to get or set.</param>
|
|
object IList.this[int index] { get => (object)Get(index); set => Set(index, (WeightedTransform)value); }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the WeightedTransform at the specified index.
|
|
/// </summary>
|
|
/// <param name="index">The zero-based index of the WeightedTransform to get or set.</param>
|
|
public WeightedTransform this[int index] { get => Get(index); set => Set(index, value); }
|
|
|
|
/// <summary>The number of elements contained in the WeightedTransformArray.</summary>
|
|
public int Count { get => m_Length; }
|
|
|
|
/// <summary>
|
|
/// Retrieves whether WeightedTransformArray is read-only. Always false.
|
|
/// </summary>
|
|
public bool IsReadOnly { get => false; }
|
|
|
|
/// <summary>
|
|
/// Retrieves whether WeightedTransformArray has a fixed size. Always false.
|
|
/// </summary>
|
|
public bool IsFixedSize { get => false; }
|
|
|
|
bool ICollection.IsSynchronized { get => true; }
|
|
|
|
object ICollection.SyncRoot { get => null; }
|
|
|
|
[System.Serializable]
|
|
private struct Enumerator : IEnumerator<WeightedTransform>
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|