/*
* ParticleManager.cs
* Authors: Brian Murphy
* Copyright (c) 2007-2008 Cornell University
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program 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
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using TACParticleEngine.Emitters;
using TACParticleEngine.Particles;
using tAC_Engine.Graphics.Cameras;
using Util;
namespace TACParticleEngine
{
///
/// Manages all the various particle engines used in the game
///
public class ParticleManager : DrawableGameScreenComponent
{
#region Fields
// Dictionary for storing all loaded engines
private readonly List mParticleEngines;
private readonly Dictionary mEngineStorer;
private readonly List mCleanUpList;
// Whether to draw using GPU or CPU
private readonly bool mGPURendering;
// Current content manager for managing content
private readonly ContentManager Content;
// Current viewport for drawing to for CPU rendering
private Viewport mViewport;
// Current active camera for rendering
private Camera mActiveCamera;
// Current sprite batch renderer for CPU rendering
private SpriteBatch mSpriteBatch;
#endregion
#region Properties
///
/// Sets current viewport for drawing to for CPU rendering
///
public Camera ActiveCamera
{
set
{
mActiveCamera = value;
foreach (ParticleEngine pEngine in mParticleEngines)
{
pEngine.ActiveCamera = value;
}
}
}
///
/// Sets current active camera for rendering
///
public SpriteBatch SpriteBatch
{
set
{
mSpriteBatch = value;
foreach (ParticleEngine pEngine in mParticleEngines)
{
pEngine.SpriteBatch = value;
}
}
}
///
/// Sets current sprite batch renderer for CPU rendering
///
public Viewport Viewport
{
set
{
mViewport = value;
foreach (ParticleEngine pEngine in mParticleEngines)
{
pEngine.Viewport = value;
}
}
}
#endregion
#region Creation
///
/// Construct a ParticleManager for rendering on the GPU
///
public ParticleManager(ContentManager content, Camera activeCamera)
{
mParticleEngines = new List();
mEngineStorer = new Dictionary();
mCleanUpList = new List();
Content = content;
mActiveCamera = activeCamera;
mGPURendering = true;
}
///
/// Construct a ParticleManager for rendering on the CPU
///
public ParticleManager(ContentManager content, Camera activeCamera, SpriteBatch spriteBatch, Viewport viewport)
{
mParticleEngines = new List();
mEngineStorer = new Dictionary();
mCleanUpList = new List();
Content = content;
mActiveCamera = activeCamera;
mSpriteBatch = spriteBatch;
mViewport = viewport;
}
#endregion
#region Management
///
/// Directly adds a particle engine into the manager to allow the particle engine to update and draw
/// *Note* Only used for the particle editor
///
/// The particle engine to add in
/// Indicates that the current engines reference has already been added in
public void Add(ParticleEngine pEngine, bool alreadyAdded)
{
pEngine.GPURendering = mGPURendering;
pEngine.Viewport = mViewport;
pEngine.Content = Content;
pEngine.SpriteBatch = mSpriteBatch;
pEngine.ActiveCamera = mActiveCamera;
pEngine.DrawOrder = DrawOrder;
for (int i = pEngine.Emitters.Count - 1; i >= 0; --i)
{
pEngine.Emitters[i].InitializeRenderer(Game, Content);
}
if (!alreadyAdded)
{
mParticleEngines.Add(pEngine);
}
parent.PublicAddComponent(pEngine);
}
///
/// Loads and returns a particle engine
///
/// The path and filename of the particle engine
/// Returns a particle engine
public ParticleEngine Load(string particleEngineFilename)
{
ParticleEngine retVal;
if (!mEngineStorer.ContainsKey(particleEngineFilename))
{
retVal = ParticleEngine.LoadFromFile(Content.RootDirectory + particleEngineFilename + @".particle");
retVal.Content = Content;
retVal.Load();
mEngineStorer.Add(particleEngineFilename, retVal);
mCleanUpList.Add(particleEngineFilename);
}
retVal = (ParticleEngine)mEngineStorer[particleEngineFilename].Clone();
retVal.ActiveCamera = mActiveCamera;
retVal.GPURendering = mGPURendering;
retVal.Viewport = mViewport;
retVal.SpriteBatch = mSpriteBatch;
retVal.Content = Content;
retVal.DrawOrder = DrawOrder;
foreach (Emitter emitter in retVal.Emitters)
{
emitter.InitializeRenderer(Game, Content);
}
if (!mParticleEngines.Contains(retVal))
{
mParticleEngines.Add(retVal);
}
parent.PublicAddComponent(retVal);
return retVal;
}
///
/// Unloads the specified particle engine for the stored list of particle engines
///
/// The name of the particle engine to remove
public void Unload(string particleEngineName)
{
if (mEngineStorer.ContainsKey(particleEngineName))
{
mEngineStorer.Remove(particleEngineName);
mCleanUpList.Remove(particleEngineName);
}
}
///
/// Reloads in content that we are using whenever the graphics device loses focus so as to not crash program
///
protected override void LoadContent()
{
for (int i = mParticleEngines.Count - 1; i >= 0; i--)
{
mParticleEngines[i].Load();
}
}
///
/// Unloads content so as to not take up too much memory. Primarily used for minigames.
///
protected override void UnloadContent()
{
for (int i = mParticleEngines.Count - 1; i >= 0; i--)
{
mParticleEngines[i].Unload();
}
}
///
/// Disposes necessary objects.
///
protected override void Dispose(bool disposing)
{
if (disposing)
{
for (int i = mParticleEngines.Count - 1; i >= 0; i--)
{
mParticleEngines[i].Dispose();
mParticleEngines[i] = null;
}
mParticleEngines.Clear();
for (int i = mCleanUpList.Count - 1; i >= 0; i--)
{
mEngineStorer[mCleanUpList[i]].Dispose();
mEngineStorer[mCleanUpList[i]] = null;
mCleanUpList[i] = null;
}
mEngineStorer.Clear();
mCleanUpList.Clear();
}
base.Dispose(disposing);
}
#endregion
#region Update
///
/// Updates all paticle engines in the manager
///
/// The total game time
public override void Update(GameTime gameTime)
{
float time = (float)gameTime.ElapsedGameTime.TotalSeconds;
for (int i = mParticleEngines.Count - 1; i >= 0; --i)
{
if (!mParticleEngines[i].ToDestory || mParticleEngines[i].EmitterActive)
{
mParticleEngines[i].Update(time);
}
else
{
mParticleEngines[i].Dispose();
}
}
mParticleEngines.RemoveAll(ParticleEngine.NotAlive);
}
#endregion
}
}