using System; using System.Collections; using System.Collections.Generic; using Unity.Mathematics; namespace UnityEngine.Splines { /// /// Describes the direction that a interpolates. Use and /// to create paths that interpolate along a in either a forward /// or backward direction. /// /// /// public enum SliceDirection { /// /// The interpolates along the direction of the referenced spline. /// Forward, /// /// The interpolates in the reverse direction of the referenced spline. /// Backward } /// /// Describes a subset of knot indices in a . The range might iterate in either the /// forward or backward direction. /// [Serializable] public struct SplineRange : IEnumerable { [SerializeField] int m_Start; [SerializeField] int m_Count; [SerializeField] SliceDirection m_Direction; /// /// The inclusive first index, starting at 0. /// public int Start { get => m_Start; set => m_Start = value; } /// /// The inclusive end index of this range. /// public int End => this[Count - 1]; /// /// Returns the number of indices. /// public int Count { get => m_Count; set => m_Count = math.max(value, 0); } /// /// The direction that this range interpolates. increments /// the knot index when it iterates, whereas decrements this index. /// public SliceDirection Direction { get => m_Direction; set => m_Direction = value; } /// /// Creates a new from a start index and count. /// /// The inclusive first index of a range. /// The number of elements this range encompasses. This value might be negative, /// which is shorthand to call the constructor with an explicit parameter. /// public SplineRange(int start, int count) : this(start, count, count < 0 ? SliceDirection.Backward : SliceDirection.Forward) { } /// /// Creates a new from a start index and count. /// /// The inclusive first index of a range. /// The number of elements this range encompasses. /// Whether when iterating this range it is incrementing from start to start + count, or /// decrementing from start to start - count. /// public SplineRange(int start, int count, SliceDirection direction) { m_Start = start; m_Count = math.abs(count); m_Direction = direction; } /// /// Get or set the knot index at an index . /// This indexer allows you to write a for loop to iterate through a range without needing to know in which /// direction the range is iterating. /// /// /// /// // Create a new range into an existing Spline starting at knot 5, and interpolating the span of 3 knots. /// // range[0,1,2] will map to { 6, 5, 4 } respectively. /// var range = new SplineRange(6, 3, SplineDirection.Backward); /// /// /// The zero-based index of the element to get or set. public int this[int index] => Direction == SliceDirection.Backward ? m_Start - index : m_Start + index; /// /// Get an enumerator that iterates through the index collection. Note that this will either increment or /// decrement indices depending on the value of the property. /// /// An IEnumerator that is used to iterate the collection. public IEnumerator GetEnumerator() => new SplineRangeEnumerator(this); /// /// Gets an enumerator that iterates through the index collection. It either increments or /// decrements indices depending on the value of the property. /// /// Returns an IEnumerator that is used to iterate the collection. IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); /// /// A struct for iterating a . /// public struct SplineRangeEnumerator : IEnumerator { int m_Index, m_Start, m_End, m_Count; bool m_Reverse; /// /// Advances the enumerator to the next element of the collection. /// /// Returns true if the enumerator was successfully advanced to the next element; /// false if the enumerator has passed the end of the collection. public bool MoveNext() => ++m_Index < m_Count; /// /// Sets the enumerator to its initial position, which is before the first element in the collection. /// public void Reset() => m_Index = -1; /// /// Gets the element in the collection at the current position of the enumerator. /// public int Current => m_Reverse ? m_End - m_Index : m_Start + m_Index; object IEnumerator.Current => Current; /// /// Constructor for an IEnumerator of a . /// /// The to iterate. public SplineRangeEnumerator(SplineRange range) { m_Index = -1; m_Reverse = range.Direction == SliceDirection.Backward; int a = range.Start, b = m_Reverse ? range.Start - range.Count : range.Start + range.Count; m_Start = math.min(a, b); m_End = math.max(a, b); m_Count = range.Count; } /// /// IDisposable implementation. SplineSliceEnumerator does not allocate any resources. /// public void Dispose() { } } /// /// Returns a string summary of this range. /// /// Returns a string summary of this range. public override string ToString() => $"{{{Start}..{End}}}"; } }