#region File Description //----------------------------------------------------------------------------- // ParticleManager.cs // // Microsoft XNA Community Game Platform // Copyright (C) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- #endregion #region Using Statements using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Xml; using System.Xml.Serialization; using Microsoft.Xna.Framework; using RobotGameData.Helper; #endregion namespace RobotGameData.ParticleSystem { #region Particle Reader /// /// this particle information gets ready by XML file. /// It contains the particle name, particle file path, /// and the maximum instance number that are to be used in the game. /// [Serializable] public class ParticleReaderElement { public string EntryName = String.Empty; public string RelativeFilePath = String.Empty; public int UseMaxCount = 0; } #endregion #region Particle Reader List /// /// a set of ParticleReaderElement’s to be read from an XML file. /// [Serializable] public class ParticleReaderList { public List ParticleReaderElements = null; } #endregion #region Particle Storage /// /// a storage in which particle’s instance will be contained. /// public class ParticleStorage { public string entryName = String.Empty; public List list = new List(); } #endregion /// /// It can load and add each particle and provides an interface /// that plays each particle. /// Each particle is in ParticleSequence class. /// public class ParticleManager { #region Fields bool particleOn = true; // Activate all particles List particleSequencesList = new List(); List particleInfoList = new List(); #endregion /// /// Remove all particles /// public void Clear() { ClearAllParticles(); particleInfoList.Clear(); } /// /// Adds a new particle to the storage /// /// particle name in the game /// particle file (.Particle) /// instance count /// parent scene node /// an index of new particle public int AddParticle( string entryName, string particleFile, int maxCount, NodeBase sceneParent) { if (particleOn == false) return -1; ParticleStorage storage = null; ParticleSequenceInfo particleInfo = null; // checks a registerd particle. int index = FindParticleIndexByName(entryName); if (index != -1) { storage = particleSequencesList[index]; } else { storage = new ParticleStorage(); storage.entryName = entryName; particleSequencesList.Add(storage); } // makes a resource path. string resourcePath = Path.GetDirectoryName(particleFile); particleInfo = FindParticleInfo(particleFile); if (particleInfo == null) particleInfo = LoadParticleSequenceInfo(particleFile); if (particleInfo == null) { throw new ArgumentException( "failed to load particle : " + particleFile); } ParticleSequence source = new ParticleSequence(ref particleInfo, resourcePath); // makes and stores a particle instance. for (int i = 0; i < maxCount; i++) { ParticleSequence instance = ParticleSequence.CreateInstance(ref source); instance.Name = entryName; storage.list.Add(instance); // adds particle to render scene. sceneParent.AddChild(instance); } return particleSequencesList.IndexOf(storage); } /// /// reads a particle list file. /// Loads every particle, specified in the list file, /// and registers to the manager. /// /// particle list file (.ParticleList) /// 3D scene parent node public void LoadParticleList(string fileName, NodeBase sceneParent) { if (particleOn == false) return; Stream stream = File.OpenRead(Path.Combine("Content", fileName)); XmlTextReader reader = new XmlTextReader(stream); XmlSerializer serializer = new XmlSerializer(typeof(ParticleReaderList)); ParticleReaderList list = (ParticleReaderList)serializer.Deserialize(reader); for (int i = 0; i < list.ParticleReaderElements.Count; i++) { ParticleReaderElement element = list.ParticleReaderElements[i]; AddParticle(element.EntryName, element.RelativeFilePath, element.UseMaxCount, sceneParent); } } /// /// searches for the particle information which has been /// registered with particle file name. /// /// particle file (.Particle) /// particle information public ParticleSequenceInfo FindParticleInfo(string fileName) { for (int i = 0; i < particleInfoList.Count; i++) { if (particleInfoList[i].Name == fileName) { return particleInfoList[i]; } } return null; } /// /// reads information from a particle file and registers to the list. /// /// particle file (.Particle) /// particle information public ParticleSequenceInfo LoadParticleSequenceInfo(string fileName) { ParticleSequenceInfo newData = (ParticleSequenceInfo) FrameworkCore.ContentManager.Load( fileName); particleInfoList.Add(newData); return newData; } /// /// deletes every particle from the list. /// public void ClearAllParticles() { for(int i = 0; i < particleSequencesList.Count; i++) { particleSequencesList[i].list.Clear(); } particleSequencesList.Clear(); } /// /// searches the particle index with the registered particle name. /// /// particle name /// an index of particle in the list public int FindParticleIndexByName(string entryName) { for (int i = 0; i < particleSequencesList.Count; i++) { ParticleStorage storage = particleSequencesList[i]; if (storage.entryName == entryName) { return particleSequencesList.IndexOf(storage); } } return -1; } /// /// plays the specified particle. /// /// an index of particle /// The position of a particle /// The normal vector of a particle /// The axis vector of a particle /// the plaied particle public ParticleSequence PlayParticle(int id, Vector3 position, Vector3 normal, Matrix axis) { if (particleOn == false) return null; if (id == -1) throw new ArgumentException("Cannot find particle : " + id); ParticleSequence particle = FindFreeParticle(particleSequencesList[id]); if (particle != null) { Matrix transform; if (Math.Abs(1.0f - Vector3.Dot(normal, Vector3.Up)) < 0.0001f) { transform = Helper3D.MakeMatrixWithAt(normal, Vector3.Forward); } else { transform = Helper3D.MakeMatrixWithAt(normal, Vector3.Up); } transform.Translation = position; particle.WorldTransform = axis * transform; PlayParticle(particle); return particle; } return null; } /// /// plays the specified particle. /// /// an index of particle /// matrix in the world /// The axis vector of a particle /// the plaied particle public ParticleSequence PlayParticle(int id, Matrix world, Matrix axis) { if (particleOn == false) return null; if (id == -1) throw new ArgumentException("Cannot find particle : " + id); ParticleSequence particle = FindFreeParticle(particleSequencesList[id]); if( particle != null) { particle.WorldTransform = axis * world; PlayParticle(particle); return particle; } return null; } /// /// plays the specified particle. /// /// particle /// public bool PlayParticle(ParticleSequence particle) { if (particleOn == false) return true; if (particle != null) { particle.Play(); return true; } return false; } /// /// searches for the particle (instance) whose activity has ended /// or is yet to start. /// /// particle storage /// protected ParticleSequence FindFreeParticle(ParticleStorage storage) { if (particleOn == false) return null; for (int i = 0; i < storage.list.Count; i++) { if (storage.list[i].IsPlaying == false) return storage.list[i]; } return null; } } }