#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