// 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);
}
}
}