// 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 Microsoft.Xna.Framework.Design; using Microsoft.Xna.Framework.Graphics.PackedVector; using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Linq; namespace Microsoft.Xna.Framework.Content.Pipeline.Graphics { /// /// Provides methods and properties for maintaining a vertex channel. /// This is a generic implementation of VertexChannel and, therefore, can handle strongly typed content data. /// public sealed class VertexChannel : VertexChannel, IList, ICollection, IEnumerable, IEnumerable { List items; /// /// Gets the strongly-typed list for the base class to access. /// internal override IList Items { get { return items; } } /// /// Gets the type of data contained in this channel. /// public override Type ElementType { get { return typeof(T); } } /// /// Gets or sets the element at the specified index. /// public new T this[int index] { get { return items[index]; } set { items[index] = value; } } /// /// true if this object is read-only; false otherwise. /// bool ICollection.IsReadOnly { get { return false; } } /// /// Creates an instance of VertexChannel. /// /// Name of the channel. internal VertexChannel(string name) : base(name) { items = new List(); } static VertexChannel() { // Some platforms (such as Windows Store) don't support TypeConverter, which // is normally referenced with an attribute on the target type. To keep them // out of the main assembly, they are registered here before their use. //TypeDescriptor.AddAttributes(typeof(Single), new TypeConverterAttribute(typeof(SingleTypeConverter))); TypeDescriptor.AddAttributes(typeof(Vector2), new TypeConverterAttribute(typeof(Vector2TypeConverter))); TypeDescriptor.AddAttributes(typeof(Vector3), new TypeConverterAttribute(typeof(Vector3TypeConverter))); TypeDescriptor.AddAttributes(typeof(Vector4), new TypeConverterAttribute(typeof(Vector4TypeConverter))); //TypeDescriptor.AddAttributes(typeof(IPackedVector), new TypeConverterAttribute(typeof(PackedVectorTypeConverter))); } /// /// Determines whether the specified element is in the channel. /// /// Element being searched for. /// true if the element is present; false otherwise. public bool Contains(T item) { return items.Contains(item); } /// /// Copies the elements of the channel to an array, starting at the specified index. /// /// Array that will receive the copied channel elements. /// Starting index for copy operation. public void CopyTo(T[] array, int arrayIndex) { items.CopyTo(array, arrayIndex); } /// /// Gets an enumerator interface for reading channel content. /// /// Enumeration of the channel content. public new IEnumerator GetEnumerator() { return items.GetEnumerator(); } /// /// Gets the index of the specified item. /// /// Item whose index is to be retrieved. /// Index of specified item. public int IndexOf(T item) { return items.IndexOf(item); } /// /// Inserts the range of values from the enumerable into the channel. /// /// The zero-based index at which the new elements should be inserted. /// The data to insert into the channel. internal override void InsertRange(int index, IEnumerable data) { if ((index < 0) || (index > items.Count)) throw new ArgumentOutOfRangeException("index"); if (data == null) throw new ArgumentNullException("data"); if (!(data is IEnumerable)) throw new ArgumentException("data"); items.InsertRange(index, (IEnumerable)data); } /// /// Reads channel content and automatically converts it to the specified vector format. /// /// Target vector format for the converted channel data. /// The converted channel data. public override IEnumerable ReadConvertedContent() { if (typeof(TargetType).IsAssignableFrom(typeof(T))) return items.Cast(); return Convert(items); } private static IEnumerable Convert(IEnumerable items) { // The following formats are supported: // - Single // - Vector2 Structure // - Vector3 Structure // - Vector4 Structure // - Any implementation of IPackedVector Interface. var converter = TypeDescriptor.GetConverter(typeof(T)); if (!converter.CanConvertTo(typeof(TargetType))) { // If you got this exception, check out the static constructor above // to make sure your type is registered. throw new NotImplementedException( string.Format("TypeConverter for {0} -> {1} is not implemented.", typeof(T).Name, typeof(TargetType).Name)); } foreach (var item in items) yield return (TargetType)converter.ConvertTo(item, typeof(TargetType)); } /// /// Adds a new element to the end of the collection. /// /// The element to add. void ICollection.Add(T value) { ((ICollection)Items).Add(value); } /// /// Removes all elements from the collection. /// void ICollection.Clear() { Items.Clear(); } /// /// Removes a specified element from the collection. /// /// The element to remove. /// true if the channel was removed; false otherwise. bool ICollection.Remove(T value) { return ((ICollection)Items).Remove(value); } /// /// Inserts an element into the collection at the specified position. /// /// Index at which to insert the element. /// The element to insert. void IList.Insert(int index, T value) { Items.Insert(index, value); } /// /// Removes the element at the specified index position. /// /// Index of the element to remove. void IList.RemoveAt(int index) { Items.RemoveAt(index); } /// /// Removes a range of values from the channel. /// /// The zero-based starting index of the range of elements to remove. /// The number of elements to remove. internal override void RemoveRange(int index, int count) { items.RemoveRange(index, count); } } }