#region CPL License /* Nuclex Framework Copyright (C) 2002-2009 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #endregion using System; using System.Collections.Generic; using System.Diagnostics; using Microsoft.Xna.Framework.Graphics; using Nuclex.Graphics.Batching; using Nuclex.Support; namespace Nuclex.Graphics.SpecialEffects.Particles.HighLevel { partial class ParticleSystemManager { #region class PrimitiveBatchHolder /// Holds a primitive batch used to render particles private abstract class PrimitiveBatchHolder { /// Initializes a new primitive batch holder /// Particle system manager the holder belongs to public PrimitiveBatchHolder(ParticleSystemManager manager) { this.Manager = manager; this.ReferenceCount = 1; } /// Begins drawing with the contained primitive batch public abstract void Begin(); /// Ends drawing with the contained primitve batch public abstract void End(); /// Releases or destroys the referenced primitive batch public abstract void Release(); /// Particle system manager this holder belongs to protected ParticleSystemManager Manager; /// Number of active references to the primitive batch holder public int ReferenceCount; } #endregion // class PrimitiveBatchHolder #region class PrimitiveBatchHolder<> /// Holds a type-safe primitive batch used to render particles private class PrimitiveBatchHolder : PrimitiveBatchHolder where VertexType : struct, IVertexType { /// Initializes a new primitive batch holder /// /// Particle system manager the primitive batch belongs to /// /// Primitive batch being held public PrimitiveBatchHolder( ParticleSystemManager manager, PrimitiveBatch primitiveBatch ) : base(manager) { this.PrimitiveBatch = primitiveBatch; } /// Begins drawing with the contained primitive batch public override void Begin() { this.PrimitiveBatch.Begin(QueueingStrategy.Deferred); } /// Ends drawing with the contained primitive batch public override void End() { this.PrimitiveBatch.End(); } /// Releases or destroys the referenced primitive batch public override void Release() { if(this.ReferenceCount > 1) { --this.ReferenceCount; } else { this.PrimitiveBatch.Dispose(); base.Manager.primitiveBatches.Remove(typeof(VertexType)); } } /// Primitive batch for the holder's vertex type public PrimitiveBatch PrimitiveBatch; } #endregion // class PrimitiveBatchHolder<> /// Delegate for creating a new primitive batch holder internal delegate void InduceErrorDelegate(); /// /// Retrieves or creates the primitive batch for the specified vertex type /// /// /// Vertex type a primitive batch will be returned for /// /// A primitive batch that renders the specified vertex type private PrimitiveBatchHolder getOrCreatePrimitiveBatch() where VertexType : struct, IVertexType { PrimitiveBatchHolder holder; // Find out if we a primitive batch and vertex declaration already exist if(this.primitiveBatches.TryGetValue(typeof(VertexType), out holder)) { // Yes, add another reference to this primitive batch and vertex declaration ++holder.ReferenceCount; return (holder as PrimitiveBatchHolder); } else { // No, let's create one // Create the primitive batch for rendering this vertex structure PrimitiveBatchHolder newHolder; #if UNITTEST if(this.InducePrimitiveBatchErrorDelegate != null) { this.InducePrimitiveBatchErrorDelegate(); } #endif newHolder = new PrimitiveBatchHolder( this, new PrimitiveBatch(GraphicsDevice) ); this.primitiveBatches.Add(typeof(VertexType), newHolder); this.holderArraysDirty = true; return newHolder; } } #if UNITTEST /// /// Can be used to induce a construction error in the primitive batch holder /// internal InduceErrorDelegate InducePrimitiveBatchErrorDelegate; #endif /// Primitive batches for the vertex types of all particle systems private Dictionary primitiveBatches; } } // namespace Nuclex.Graphics.SpecialEffects.Particles.HighLevel