using System; using Chernobyl.Collections.Generic.Event; using Chernobyl.Dependency; using Chernobyl.Graphics.Polygon.Buffers; using Chernobyl.Readiness; using Microsoft.Xna.Framework.Graphics; namespace Chernobyl.Graphics.Xna.Controllers { /// /// Represents an XNA index buffer. /// /// The type of data that is going to be stored in /// this buffer like ushort or uint. It is recommend that you use /// s when possible to reduce the video memory used. /// You can use s, if the number of mesh elements /// referred to by the indices is less or equal to the highest number a /// ushort can hold. For example, a 2 byte ushort can be a max value of /// 65,535 so you would only use the type ushort if the number of mesh /// elements is equal to or less than 65,535. public class XnaIndexBuffer : XnaBuffer where TData : struct { /// /// Initializes a new instance of the /// class. /// /// The instance that gives out services for use /// by this type and takes services from this type for use by other systems. /// The index data to place in this buffer. public XnaIndexBuffer(IEventCollection services, TData[] indices) { _initialIndices = indices; _count = (uint)indices.Length; services.Inject(this); } /// /// Gets the data in the buffer. /// /// The array that is to be filled with the data in the buffer. /// The index in this buffer to start pulling the data from. /// The number of elements to pull from the buffer. /// Thrown if this /// has not been fully configured (i.e /// is false). Listen to the event /// to know when this is ready. public override void Get(out TData[] dataOut, uint startIndex, uint elementCount) { if (elementCount == 0) throw new ArgumentException("The parameter \"elementCount\" is zero. You must copy over at least 1 element.", "elementCount"); dataOut = new TData[elementCount]; IndexBuffer.GetData(dataOut, (int)startIndex, (int)elementCount); } /// /// Disposes of the resources used by this index buffer (like the XNA index buffer). /// public override void Dispose() { if (IndexBuffer != null) IndexBuffer.Dispose(); } /// /// Sets the XNA index buffer onto the graphics device. /// public override void Apply() { GraphicsDevice.Indices = IndexBuffer; } /// /// Passes this XNA buffer to the render passed in so the render takes /// into account the data of the buffer. /// /// The render that should know about this buffer. public override void SetRender(XnaRender render) { render.IndexBuffer = this; } /// /// The number of indices in this buffer. /// public override uint Count { get { return _count; } } /// /// The size of this buffer in bytes. /// public override uint SizeInBytes { get { return (uint) IndexBuffer.SizeInBytes; } } /// /// The XNA index buffer used to hold the indices. /// public IndexBuffer IndexBuffer { get; set; } /// /// The graphics device used by this index buffer controller. /// [Inject] public GraphicsDevice GraphicsDevice { get { return _graphicsDevice; } set { if (_graphicsDevice != value) { // If we are resetting the GraphicsDevice we'll need to grab a // copy of the indices so that we can recreate the IndexBuffer // with the new GraphicsDevice if (IndexBuffer != null) { _initialIndices = new TData[Count]; IndexBuffer.GetData(_initialIndices); } _graphicsDevice = value; // if the XNA index buffer was already created, dispose of it // to make room for the new one if (IndexBuffer != null) IndexBuffer.Dispose(); IndexBuffer = new IndexBuffer(_graphicsDevice, typeof(TData), _initialIndices.Length, BufferUsage.None); IndexBuffer.SetData(_initialIndices); // We no longer need this copy of the indices. _initialIndices = null; IsReady = true; } } } /// /// The indices that this instance originally received in its /// constructor or null if they have been removed following initialization. /// TData[] _initialIndices; /// /// The backing field to . /// uint _count; /// /// The backing field to . /// GraphicsDevice _graphicsDevice; } }