/* Sparx
* Copyright August Zinsser 2007
* This program is distributed under the terms of the GNU General Public License
*/
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Graphics;
namespace Pina3D.Particles
{
///
/// Each modifier serves as a collection of linear interpolation functions. Particles or Emitters provide their age as the parameter
/// when querying a modified value.
///
public class Modifier : SparxEntity
{
private float mInterval;
private float mDelay;
private Color mITint;
private Color mFTint;
private float mIScale;
private float mFScale;
private float mIOpacity;
private float mFOpacity;
private float mIAngularVelocity;
private float mFAngularVelocity;
///
/// Duration that this modifier affects an emission
///
public float Interval { set { mInterval = value; } get { return mInterval; } }
public float Delay { set { mDelay = value; } get { return mDelay; } }
public Color InitialTint { set { mITint = value; } get { return mITint; } }
public Color FinalTint { set { mFTint = value; } get { return mFTint; } }
public float InitialScale { set { mIScale = value; } get { return mIScale; } }
public float FinalScale { set { mFScale = value; } get { return mFScale; } }
public float InitialOpacity { set { mIOpacity = value; } get { return mIOpacity; } }
public float FinalOpacity { set { mFOpacity = MathHelper.Clamp(value, 0f, 1f); } get { return mFOpacity; } }
public float InitialAngularVelocity { set { mIAngularVelocity = value; } get { return mIAngularVelocity; } }
public float FinalAngularVelocity { set { mFAngularVelocity = value; } get { return mFAngularVelocity; } }
///
/// Create a new Modifier function set
///
/// Key for this modifier
/// Time to wait before interpolating before inital and final effects
/// How many seconds it takes to transition between the inital and final values
/// Initial RGB Color (alpha is ignored)
/// Final RGB Color (alpha is ignored)
/// Initial Scale
/// Final Scale
/// Inital Opacity [0,1]
/// Final Opacity [0,1]
/// Initial Rotation (radians)
/// Final Rotation (radians)
public Modifier(string name, float interval, float delay, Color iTint, Color fTint, float iScale, float fScale, float iOpacity, float fOpacity, float iRotation, float fRotation)
{
mName = name;
mInterval = interval;
mITint = iTint;
mFTint = fTint;
mIScale = iScale;
mFScale = fScale;
mIOpacity = iOpacity;
mFOpacity = fOpacity;
mIAngularVelocity = iRotation;
mFAngularVelocity = fRotation;
mDelay = delay;
}
public override Object Clone()
{
Modifier retMo = new Modifier();
retMo.mName = mName + "_clone";
retMo.mITint = mITint;
retMo.mFTint = mFTint;
retMo.mIScale = mIScale;
retMo.mFScale = mFScale;
retMo.mIOpacity = mIOpacity;
retMo.mFOpacity = mFOpacity;
retMo.mIAngularVelocity = mIAngularVelocity;
retMo.mFAngularVelocity = mFAngularVelocity;
retMo.mInterval = mInterval;
retMo.mDelay = mDelay;
return retMo;
}
///
/// Get the lerped color (and opacity)
///
/// Age of the emission
/// RGBA Color
public Color Color(float t)
{
if (t < mDelay)
return new Color(mITint.R, mITint.G, mITint.B, (byte)(255 * mIOpacity));
float progress = (t - mDelay) / (mInterval);
if (progress > 1 || mInterval == 0)
return new Color(mFTint.R, mFTint.G, mFTint.B, (byte)(255 * mFOpacity));
return new Color(
new Vector4(
mITint.ToVector3() + Vector3.Multiply((mFTint.ToVector3() - mITint.ToVector3()), progress),
(mIOpacity + ((mFOpacity - mIOpacity) * progress))));
}
///
/// Gets the lerped scale
///
/// Age of the emission
///
public float Scale(float t)
{
if (t < mDelay)
return mIScale;
float progress = (t - mDelay) / (mInterval);
if (progress > 1 || mInterval == 0)
return mFScale;
return mIScale * (1 - progress) + mFScale * progress;
}
///
/// Gets the lerpped angular velocity. The emission should use this and its own timing mechanism to accumulate its rotation.
///
/// Age of the emission
/// Camera-oriented rotation of the particle in radians
public float AngularVelocity(float t)
{
if (t < mDelay)
return mIAngularVelocity;
float progress = (t - mDelay) / (mInterval);
if (progress > 1 || mInterval == 0)
return mFAngularVelocity;
return (mIAngularVelocity * (1 - progress) + mFAngularVelocity * progress);
}
private Modifier() // TODO: Remove this?
{
}
}
}