296 lines
11 KiB
C#
Raw Normal View History

#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Reflection;
#endregion
// This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license.
// For details see: http://anxframework.codeplex.com/license
namespace ANX.Framework.Content.Pipeline.Graphics
{
public sealed class VertexChannelCollection : IList<VertexChannel>, ICollection<VertexChannel>, IEnumerable<VertexChannel>, IEnumerable
{
private List<VertexChannel> channels = new List<VertexChannel>();
private VertexContent container;
internal VertexChannelCollection(VertexContent container)
{
this.container = container;
}
public VertexChannel this[string name]
{
get
{
if (string.IsNullOrEmpty(name))
throw new ArgumentNullException("name");
int index = this.IndexOf(name);
if (index < 0)
throw new KeyNotFoundException(string.Format("Vertex channel \"{0}\" was not found.", name));
return this.channels[index];
}
}
public VertexChannel this[int index]
{
get
{
return this.channels[index];
}
set
{
throw new NotSupportedException("VertexChannelCollection does not support adding channels via the ICollection or IList interfaces. Use the VertexChannelCollection Add or Insert methods instead.");
}
}
public int Count
{
get
{
return this.channels.Count;
}
}
bool ICollection<VertexChannel>.IsReadOnly
{
get
{
return false;
}
}
public VertexChannel<ElementType> Add<ElementType>(string name, IEnumerable<ElementType> channelData)
{
return this.Insert<ElementType>(this.channels.Count, name, channelData);
}
public VertexChannel Add(string name, Type elementType, IEnumerable channelData)
{
return this.Insert(this.channels.Count, name, elementType, channelData);
}
public VertexChannel<ElementType> Insert<ElementType>(int index, string name, IEnumerable<ElementType> channelData)
{
if (index < 0 || index > this.channels.Count)
throw new ArgumentOutOfRangeException("index");
if (string.IsNullOrEmpty(name))
throw new ArgumentNullException("name");
if (this.Contains(name))
throw new ArgumentException(string.Format("VertexChannelCollection already contains a channel with name \"{0}\".", name));
VertexChannel<ElementType> vertexChannel = new VertexChannel<ElementType>(name);
if (channelData != null)
{
vertexChannel.AddRange(channelData);
if (vertexChannel.Count != this.container.VertexCount)
{
throw new ArgumentException(string.Format("Wrong number of VertexChannel entries in \"{0}\". Channel size is {1}, but the parent VertexContent has a count of {2}.", name, vertexChannel.Count, this.container.VertexCount));
}
}
else
{
vertexChannel.AddRange(this.container.VertexCount);
}
this.channels.Insert(index, vertexChannel);
return vertexChannel;
}
public VertexChannel Insert(int index, string name, Type elementType, IEnumerable channelData)
{
if (index < 0 || index > this.channels.Count)
throw new ArgumentOutOfRangeException("index");
if (string.IsNullOrEmpty(name))
throw new ArgumentNullException("name");
if (elementType == null)
throw new ArgumentNullException("elementType");
if (this.Contains(name))
throw new ArgumentException(string.Format("VertexChannelCollection already contains a channel with name \"{0}\".", name));
Type type = typeof(VertexChannel<>).MakeGenericType(elementType);
VertexChannel vertexChannel = (VertexChannel)Activator.CreateInstance(type, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, new [] { name }, null);
if (channelData != null)
{
vertexChannel.AddRange(channelData);
if (vertexChannel.Count != this.container.VertexCount)
{
throw new ArgumentException(string.Format("Wrong number of VertexChannel entries in \"{0}\". Channel size is {1}, but the parent VertexContent has a count of {2}.", name, vertexChannel.Count, this.container.VertexCount));
}
}
else
{
vertexChannel.AddRange(this.container.VertexCount);
}
this.channels.Insert(index, vertexChannel);
return vertexChannel;
}
internal void Add(VertexChannel channel)
{
if (this.Contains(channel.Name))
throw new ArgumentException(string.Format("VertexChannelCollection already contains a channel with name \"{0}\".", channel.Name));
if (channel.Count != this.container.VertexCount)
throw new ArgumentException(string.Format("Wrong number of VertexChannel entries in \"{0}\". Channel size is {1}, but the parent VertexContent has a count of {2}.", channel.Name, channel.Count, this.container.VertexCount));
this.channels.Add(channel);
}
/// <summary>
/// Converts the specified channel to the target content type.
/// </summary>
/// <typeparam name="TargetType"></typeparam>
/// <param name="index"></param>
/// <returns></returns>
public VertexChannel<TargetType> ConvertChannelContent<TargetType>(int index)
{
VertexChannel vertexChannel = this[index];
this.RemoveAt(index);
VertexChannel<TargetType> result;
try
{
result = this.Insert<TargetType>(index, vertexChannel.Name, vertexChannel.ReadConvertedContent<TargetType>());
}
catch
{
this.Insert(index, vertexChannel.Name, vertexChannel.ElementType, vertexChannel);
throw;
}
return result;
}
public VertexChannel<TargetType> ConvertChannelContent<TargetType>(string name)
{
int index = this.IndexOf(name);
if (index < 0)
throw new KeyNotFoundException(string.Format("Vertex channel \"{0}\" was not found.", name));
return this.ConvertChannelContent<TargetType>(index);
}
public bool Contains(string name)
{
return this.IndexOf(name) >= 0;
}
public int IndexOf(string name)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentNullException("name");
return this.channels.FindIndex((VertexChannel channel) => channel.Name == name);
}
public bool Remove(string name)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException("name");
}
int index = this.IndexOf(name);
if (index < 0)
return false;
this.channels.RemoveAt(index);
return true;
}
public VertexChannel<T> Get<T>(string name)
{
VertexChannel vertexChannel = this[name];
if (vertexChannel.ElementType != typeof(T))
{
throw new InvalidOperationException(string.Format("Vertex channel \"{0}\" is the wrong type. It has element type {1}. Type {2} is expected.", name, vertexChannel.ElementType, typeof(T)));
}
return (VertexChannel<T>)vertexChannel;
}
/// <summary>
/// Returns the vertex channel at the specified index. If the element type is not equal to <paramref name="T"/> an <see cref="InvalidOperationException"/> gets thrown.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="index"></param>
/// <returns></returns>
/// <exception cref="System.InvalidOperationException"></exception>
public VertexChannel<T> Get<T>(int index)
{
VertexChannel vertexChannel = this[index];
if (vertexChannel.ElementType != typeof(T))
{
throw new InvalidOperationException(string.Format("Vertex channel \"{0}\" is the wrong type. It has element type {1}. Type {2} is expected.", this[index].Name, vertexChannel.ElementType, typeof(T)));
}
return (VertexChannel<T>)vertexChannel;
}
public IEnumerator<VertexChannel> GetEnumerator()
{
return this.channels.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.channels.GetEnumerator();
}
public void Clear()
{
this.channels.Clear();
}
public bool Contains(VertexChannel item)
{
return this.channels.Contains(item);
}
public int IndexOf(VertexChannel item)
{
return this.channels.IndexOf(item);
}
public bool Remove(VertexChannel item)
{
return this.channels.Remove(item);
}
public void RemoveAt(int index)
{
this.channels.RemoveAt(index);
}
void ICollection<VertexChannel>.CopyTo(VertexChannel[] array, int arrayIndex)
{
this.channels.CopyTo(array, arrayIndex);
}
void ICollection<VertexChannel>.Add(VertexChannel item)
{
throw new NotSupportedException("VertexChannelCollection does not support adding channels via the ICollection or IList interfaces. Use the VertexChannelCollection Add or Insert methods instead.");
}
void IList<VertexChannel>.Insert(int index, VertexChannel item)
{
throw new NotSupportedException("VertexChannelCollection does not support adding channels via the ICollection or IList interfaces. Use the VertexChannelCollection Add or Insert methods instead.");
}
}
}