// MonoGame - Copyright (C) The MonoGame Team
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.
using System;
using System.Collections;
using System.Collections.Generic;
namespace Microsoft.Xna.Framework.Content.Pipeline.Graphics
{
///
/// Provides methods and properties for maintaining an animation channel. An animation channel is a collection of keyframes describing the movement of a single bone or rigid object.
///
public sealed class AnimationChannel : ICollection, IEnumerable, IEnumerable
{
List keyframes;
///
/// Gets the number of keyframes in the collection.
///
public int Count
{
get
{
return keyframes.Count;
}
}
///
/// Gets the keyframe at the specified index position.
///
public AnimationKeyframe this[int index]
{
get
{
return keyframes[index];
}
}
///
/// Returns a value indicating whether the object is read-only.
///
bool ICollection.IsReadOnly
{
get
{
return false;
}
}
///
/// Initializes a new instance of AnimationChannel.
///
public AnimationChannel()
{
keyframes = new List();
}
///
/// To satisfy ICollection
///
///
void ICollection.Add(AnimationKeyframe item)
{
keyframes.Add(item);
}
///
/// Adds a new keyframe to the collection, automatically sorting the contents according to keyframe times.
///
/// Keyframe to be added to the channel.
/// Index of the new keyframe.
public int Add(AnimationKeyframe item)
{
if (item == null)
throw new ArgumentNullException("item");
// Find the correct place at which to insert it, so we can know the index to return.
// The alternative is Add, Sort then return IndexOf, which would be horribly inefficient
// and the order returned by Sort would change each time for keyframes with the same time.
// BinarySearch returns the index of the first item found with the same time, or the bitwise
// complement of the next largest item found.
int index = keyframes.BinarySearch(item);
if (index >= 0)
{
// If a match is found, we do not know if it is at the start, middle or end of a range of
// keyframes with the same time value. So look for the end of the range and insert there
// so we have deterministic behaviour.
while (index < keyframes.Count)
{
if (item.CompareTo(keyframes[index]) != 0)
break;
++index;
}
}
else
{
// If BinarySearch returns a negative value, it is the bitwise complement of the next largest
// item in the list. So we just do a bitwise complement and insert at that index.
index = ~index;
}
keyframes.Insert(index, item);
return index;
}
///
/// Removes all keyframes from the collection.
///
public void Clear()
{
keyframes.Clear();
}
///
/// Searches the collection for the specified keyframe.
///
/// Keyframe being searched for.
/// true if the keyframe exists; false otherwise.
public bool Contains(AnimationKeyframe item)
{
return keyframes.Contains(item);
}
///
/// To satisfy ICollection
///
///
///
void ICollection.CopyTo(AnimationKeyframe[] array, int arrayIndex)
{
keyframes.CopyTo(array, arrayIndex);
}
///
/// Determines the index for the specified keyframe.
///
/// Identity of a keyframe.
/// Index of the specified keyframe.
public int IndexOf(AnimationKeyframe item)
{
return keyframes.IndexOf(item);
}
///
/// Removes the specified keyframe from the collection.
///
/// Keyframe being removed.
/// true if the keyframe was removed; false otherwise.
public bool Remove(AnimationKeyframe item)
{
return keyframes.Remove(item);
}
///
/// Removes the keyframe at the specified index position.
///
/// Index of the keyframe being removed.
public void RemoveAt(int index)
{
keyframes.RemoveAt(index);
}
///
/// Returns an enumerator that iterates through the keyframes.
///
/// Enumerator for the keyframe collection.
public IEnumerator GetEnumerator()
{
return keyframes.GetEnumerator();
}
///
/// To satisfy ICollection
///
///
IEnumerator IEnumerable.GetEnumerator()
{
return keyframes.GetEnumerator();
}
}
}