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