#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;
}
}
}