/* * 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 } }