mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-04 05:26:39 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			693 lines
		
	
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			693 lines
		
	
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include "particles.hpp"
 | 
						|
 | 
						|
#include <OgreStringConverter.h>
 | 
						|
#include <OgreParticleSystem.h>
 | 
						|
#include <OgreParticleEmitter.h>
 | 
						|
#include <OgreParticleAffector.h>
 | 
						|
#include <OgreParticle.h>
 | 
						|
 | 
						|
/* FIXME: "Nif" isn't really an appropriate emitter name. */
 | 
						|
class NifEmitter : public Ogre::ParticleEmitter
 | 
						|
{
 | 
						|
public:
 | 
						|
    /** Command object for the emitter width (see Ogre::ParamCommand).*/
 | 
						|
    class CmdWidth : public Ogre::ParamCommand
 | 
						|
    {
 | 
						|
    public:
 | 
						|
        Ogre::String doGet(const void *target) const
 | 
						|
        {
 | 
						|
            return Ogre::StringConverter::toString(static_cast<const NifEmitter*>(target)->getWidth());
 | 
						|
        }
 | 
						|
        void doSet(void *target, const Ogre::String &val)
 | 
						|
        {
 | 
						|
            static_cast<NifEmitter*>(target)->setWidth(Ogre::StringConverter::parseReal(val));
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    /** Command object for the emitter height (see Ogre::ParamCommand).*/
 | 
						|
    class CmdHeight : public Ogre::ParamCommand
 | 
						|
    {
 | 
						|
    public:
 | 
						|
        Ogre::String doGet(const void *target) const
 | 
						|
        {
 | 
						|
            return Ogre::StringConverter::toString(static_cast<const NifEmitter*>(target)->getHeight());
 | 
						|
        }
 | 
						|
        void doSet(void *target, const Ogre::String &val)
 | 
						|
        {
 | 
						|
            static_cast<NifEmitter*>(target)->setHeight(Ogre::StringConverter::parseReal(val));
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    /** Command object for the emitter depth (see Ogre::ParamCommand).*/
 | 
						|
    class CmdDepth : public Ogre::ParamCommand
 | 
						|
    {
 | 
						|
    public:
 | 
						|
        Ogre::String doGet(const void *target) const
 | 
						|
        {
 | 
						|
            return Ogre::StringConverter::toString(static_cast<const NifEmitter*>(target)->getDepth());
 | 
						|
        }
 | 
						|
        void doSet(void *target, const Ogre::String &val)
 | 
						|
        {
 | 
						|
            static_cast<NifEmitter*>(target)->setDepth(Ogre::StringConverter::parseReal(val));
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    /** Command object for the emitter vertical_direction (see Ogre::ParamCommand).*/
 | 
						|
    class CmdVerticalDir : public Ogre::ParamCommand
 | 
						|
    {
 | 
						|
    public:
 | 
						|
        Ogre::String doGet(const void *target) const
 | 
						|
        {
 | 
						|
            const NifEmitter *self = static_cast<const NifEmitter*>(target);
 | 
						|
            return Ogre::StringConverter::toString(self->getVerticalDirection().valueDegrees());
 | 
						|
        }
 | 
						|
        void doSet(void *target, const Ogre::String &val)
 | 
						|
        {
 | 
						|
            NifEmitter *self = static_cast<NifEmitter*>(target);
 | 
						|
            self->setVerticalDirection(Ogre::Degree(Ogre::StringConverter::parseReal(val)));
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    /** Command object for the emitter vertical_angle (see Ogre::ParamCommand).*/
 | 
						|
    class CmdVerticalAngle : public Ogre::ParamCommand
 | 
						|
    {
 | 
						|
    public:
 | 
						|
        Ogre::String doGet(const void *target) const
 | 
						|
        {
 | 
						|
            const NifEmitter *self = static_cast<const NifEmitter*>(target);
 | 
						|
            return Ogre::StringConverter::toString(self->getVerticalAngle().valueDegrees());
 | 
						|
        }
 | 
						|
        void doSet(void *target, const Ogre::String &val)
 | 
						|
        {
 | 
						|
            NifEmitter *self = static_cast<NifEmitter*>(target);
 | 
						|
            self->setVerticalAngle(Ogre::Degree(Ogre::StringConverter::parseReal(val)));
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    /** Command object for the emitter horizontal_direction (see Ogre::ParamCommand).*/
 | 
						|
    class CmdHorizontalDir : public Ogre::ParamCommand
 | 
						|
    {
 | 
						|
    public:
 | 
						|
        Ogre::String doGet(const void *target) const
 | 
						|
        {
 | 
						|
            const NifEmitter *self = static_cast<const NifEmitter*>(target);
 | 
						|
            return Ogre::StringConverter::toString(self->getHorizontalDirection().valueDegrees());
 | 
						|
        }
 | 
						|
        void doSet(void *target, const Ogre::String &val)
 | 
						|
        {
 | 
						|
            NifEmitter *self = static_cast<NifEmitter*>(target);
 | 
						|
            self->setHorizontalDirection(Ogre::Degree(Ogre::StringConverter::parseReal(val)));
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    /** Command object for the emitter horizontal_angle (see Ogre::ParamCommand).*/
 | 
						|
    class CmdHorizontalAngle : public Ogre::ParamCommand
 | 
						|
    {
 | 
						|
    public:
 | 
						|
        Ogre::String doGet(const void *target) const
 | 
						|
        {
 | 
						|
            const NifEmitter *self = static_cast<const NifEmitter*>(target);
 | 
						|
            return Ogre::StringConverter::toString(self->getHorizontalAngle().valueDegrees());
 | 
						|
        }
 | 
						|
        void doSet(void *target, const Ogre::String &val)
 | 
						|
        {
 | 
						|
            NifEmitter *self = static_cast<NifEmitter*>(target);
 | 
						|
            self->setHorizontalAngle(Ogre::Degree(Ogre::StringConverter::parseReal(val)));
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
 | 
						|
    NifEmitter(Ogre::ParticleSystem *psys)
 | 
						|
      : Ogre::ParticleEmitter(psys)
 | 
						|
    {
 | 
						|
        initDefaults("Nif");
 | 
						|
    }
 | 
						|
 | 
						|
    /** See Ogre::ParticleEmitter. */
 | 
						|
    unsigned short _getEmissionCount(Ogre::Real timeElapsed)
 | 
						|
    {
 | 
						|
        // Use basic constant emission
 | 
						|
        return genConstantEmissionCount(timeElapsed);
 | 
						|
    }
 | 
						|
 | 
						|
    /** See Ogre::ParticleEmitter. */
 | 
						|
    void _initParticle(Ogre::Particle *particle)
 | 
						|
    {
 | 
						|
        Ogre::Vector3 xOff, yOff, zOff;
 | 
						|
 | 
						|
        // Call superclass
 | 
						|
        ParticleEmitter::_initParticle(particle);
 | 
						|
 | 
						|
        xOff = Ogre::Math::SymmetricRandom() * mXRange;
 | 
						|
        yOff = Ogre::Math::SymmetricRandom() * mYRange;
 | 
						|
        zOff = Ogre::Math::SymmetricRandom() * mZRange;
 | 
						|
 | 
						|
        particle->position = mPosition + xOff + yOff + zOff;
 | 
						|
 | 
						|
        // Generate complex data by reference
 | 
						|
        genEmissionColour(particle->colour);
 | 
						|
 | 
						|
        // NOTE: We do not use mDirection/mAngle for the initial direction.
 | 
						|
        Ogre::Radian hdir = mHorizontalDir + mHorizontalAngle*Ogre::Math::SymmetricRandom();
 | 
						|
        Ogre::Radian vdir = mVerticalDir + mVerticalAngle*Ogre::Math::SymmetricRandom();
 | 
						|
        particle->direction = (Ogre::Quaternion(hdir, Ogre::Vector3::UNIT_Z) *
 | 
						|
                               Ogre::Quaternion(vdir, Ogre::Vector3::UNIT_X)) *
 | 
						|
                              Ogre::Vector3::UNIT_Z;
 | 
						|
 | 
						|
        genEmissionVelocity(particle->direction);
 | 
						|
 | 
						|
        // Generate simpler data
 | 
						|
        particle->timeToLive = particle->totalTimeToLive = genEmissionTTL();
 | 
						|
    }
 | 
						|
 | 
						|
    /** Overloaded to update the trans. matrix */
 | 
						|
    void setDirection(const Ogre::Vector3 &dir)
 | 
						|
    {
 | 
						|
        ParticleEmitter::setDirection(dir);
 | 
						|
        genAreaAxes();
 | 
						|
    }
 | 
						|
 | 
						|
    /** Sets the size of the area from which particles are emitted.
 | 
						|
    @param
 | 
						|
        size Vector describing the size of the area. The area extends
 | 
						|
        around the center point by half the x, y and z components of
 | 
						|
        this vector. The box is aligned such that it's local Z axis points
 | 
						|
        along it's direction (see setDirection)
 | 
						|
    */
 | 
						|
    void setSize(const Ogre::Vector3 &size)
 | 
						|
    {
 | 
						|
        mSize = size;
 | 
						|
        genAreaAxes();
 | 
						|
    }
 | 
						|
 | 
						|
    /** Sets the size of the area from which particles are emitted.
 | 
						|
    @param x,y,z
 | 
						|
        Individual axis lengths describing the size of the area. The area
 | 
						|
        extends around the center point by half the x, y and z components
 | 
						|
        of this vector. The box is aligned such that it's local Z axis
 | 
						|
        points along it's direction (see setDirection)
 | 
						|
    */
 | 
						|
    void setSize(Ogre::Real x, Ogre::Real y, Ogre::Real z)
 | 
						|
    {
 | 
						|
        mSize.x = x;
 | 
						|
        mSize.y = y;
 | 
						|
        mSize.z = z;
 | 
						|
        genAreaAxes();
 | 
						|
    }
 | 
						|
 | 
						|
    /** Sets the width (local x size) of the emitter. */
 | 
						|
    void setWidth(Ogre::Real width)
 | 
						|
    {
 | 
						|
        mSize.x = width;
 | 
						|
        genAreaAxes();
 | 
						|
    }
 | 
						|
    /** Gets the width (local x size) of the emitter. */
 | 
						|
    Ogre::Real getWidth(void) const
 | 
						|
    { return mSize.x; }
 | 
						|
    /** Sets the height (local y size) of the emitter. */
 | 
						|
    void setHeight(Ogre::Real height)
 | 
						|
    {
 | 
						|
        mSize.y = height;
 | 
						|
        genAreaAxes();
 | 
						|
    }
 | 
						|
    /** Gets the height (local y size) of the emitter. */
 | 
						|
    Ogre::Real getHeight(void) const
 | 
						|
    { return mSize.y; }
 | 
						|
    /** Sets the depth (local y size) of the emitter. */
 | 
						|
    void setDepth(Ogre::Real depth)
 | 
						|
    {
 | 
						|
        mSize.z = depth;
 | 
						|
        genAreaAxes();
 | 
						|
    }
 | 
						|
    /** Gets the depth (local y size) of the emitter. */
 | 
						|
    Ogre::Real getDepth(void) const
 | 
						|
    { return mSize.z; }
 | 
						|
 | 
						|
    void setVerticalDirection(Ogre::Radian vdir)
 | 
						|
    { mVerticalDir = vdir; }
 | 
						|
    Ogre::Radian getVerticalDirection(void) const
 | 
						|
    { return mVerticalDir; }
 | 
						|
 | 
						|
    void setVerticalAngle(Ogre::Radian vangle)
 | 
						|
    { mVerticalAngle = vangle; }
 | 
						|
    Ogre::Radian getVerticalAngle(void) const
 | 
						|
    { return mVerticalAngle; }
 | 
						|
 | 
						|
    void setHorizontalDirection(Ogre::Radian hdir)
 | 
						|
    { mHorizontalDir = hdir; }
 | 
						|
    Ogre::Radian getHorizontalDirection(void) const
 | 
						|
    { return mHorizontalDir; }
 | 
						|
 | 
						|
    void setHorizontalAngle(Ogre::Radian hangle)
 | 
						|
    { mHorizontalAngle = hangle; }
 | 
						|
    Ogre::Radian getHorizontalAngle(void) const
 | 
						|
    { return mHorizontalAngle; }
 | 
						|
 | 
						|
 | 
						|
protected:
 | 
						|
    /// Size of the area
 | 
						|
    Ogre::Vector3 mSize;
 | 
						|
 | 
						|
    Ogre::Radian mVerticalDir;
 | 
						|
    Ogre::Radian mVerticalAngle;
 | 
						|
    Ogre::Radian mHorizontalDir;
 | 
						|
    Ogre::Radian mHorizontalAngle;
 | 
						|
 | 
						|
    /// Local axes, not normalised, their magnitude reflects area size
 | 
						|
    Ogre::Vector3 mXRange, mYRange, mZRange;
 | 
						|
 | 
						|
    /// Internal method for generating the area axes
 | 
						|
    void genAreaAxes(void)
 | 
						|
    {
 | 
						|
        Ogre::Vector3 mLeft = mUp.crossProduct(mDirection);
 | 
						|
        mXRange = mLeft * (mSize.x * 0.5f);
 | 
						|
        mYRange = mUp * (mSize.y * 0.5f);
 | 
						|
        mZRange = mDirection * (mSize.z * 0.5f);
 | 
						|
    }
 | 
						|
 | 
						|
    /** Internal for initializing some defaults and parameters
 | 
						|
    @return True if custom parameters need initialising
 | 
						|
    */
 | 
						|
    bool initDefaults(const Ogre::String &t)
 | 
						|
    {
 | 
						|
        // Defaults
 | 
						|
        mDirection = Ogre::Vector3::UNIT_Z;
 | 
						|
        mUp = Ogre::Vector3::UNIT_Y;
 | 
						|
        setSize(100.0f, 100.0f, 100.0f);
 | 
						|
        mType = t;
 | 
						|
 | 
						|
        // Set up parameters
 | 
						|
        if(createParamDictionary(mType + "Emitter"))
 | 
						|
        {
 | 
						|
            addBaseParameters();
 | 
						|
            Ogre::ParamDictionary *dict = getParamDictionary();
 | 
						|
 | 
						|
            // Custom params
 | 
						|
            dict->addParameter(Ogre::ParameterDef("width",
 | 
						|
                                                  "Width of the shape in world coordinates.",
 | 
						|
                                                  Ogre::PT_REAL),
 | 
						|
                               &msWidthCmd);
 | 
						|
            dict->addParameter(Ogre::ParameterDef("height",
 | 
						|
                                                  "Height of the shape in world coordinates.",
 | 
						|
                                                  Ogre::PT_REAL),
 | 
						|
                               &msHeightCmd);
 | 
						|
            dict->addParameter(Ogre::ParameterDef("depth",
 | 
						|
                                                  "Depth of the shape in world coordinates.",
 | 
						|
                                                  Ogre::PT_REAL),
 | 
						|
                               &msDepthCmd);
 | 
						|
 | 
						|
            dict->addParameter(Ogre::ParameterDef("vertical_direction",
 | 
						|
                                                  "Vertical direction of emitted particles (in degrees).",
 | 
						|
                                                  Ogre::PT_REAL),
 | 
						|
                               &msVerticalDirCmd);
 | 
						|
            dict->addParameter(Ogre::ParameterDef("vertical_angle",
 | 
						|
                                                  "Vertical direction variance of emitted particles (in degrees).",
 | 
						|
                                                  Ogre::PT_REAL),
 | 
						|
                               &msVerticalAngleCmd);
 | 
						|
            dict->addParameter(Ogre::ParameterDef("horizontal_direction",
 | 
						|
                                                  "Horizontal direction of emitted particles (in degrees).",
 | 
						|
                                                  Ogre::PT_REAL),
 | 
						|
                               &msHorizontalDirCmd);
 | 
						|
            dict->addParameter(Ogre::ParameterDef("horizontal_angle",
 | 
						|
                                                  "Horizontal direction variance of emitted particles (in degrees).",
 | 
						|
                                                  Ogre::PT_REAL),
 | 
						|
                               &msHorizontalAngleCmd);
 | 
						|
 | 
						|
            return true;
 | 
						|
        }
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    /// Command objects
 | 
						|
    static CmdWidth msWidthCmd;
 | 
						|
    static CmdHeight msHeightCmd;
 | 
						|
    static CmdDepth msDepthCmd;
 | 
						|
    static CmdVerticalDir msVerticalDirCmd;
 | 
						|
    static CmdVerticalAngle msVerticalAngleCmd;
 | 
						|
    static CmdHorizontalDir msHorizontalDirCmd;
 | 
						|
    static CmdHorizontalAngle msHorizontalAngleCmd;
 | 
						|
};
 | 
						|
NifEmitter::CmdWidth NifEmitter::msWidthCmd;
 | 
						|
NifEmitter::CmdHeight NifEmitter::msHeightCmd;
 | 
						|
NifEmitter::CmdDepth NifEmitter::msDepthCmd;
 | 
						|
NifEmitter::CmdVerticalDir NifEmitter::msVerticalDirCmd;
 | 
						|
NifEmitter::CmdVerticalAngle NifEmitter::msVerticalAngleCmd;
 | 
						|
NifEmitter::CmdHorizontalDir NifEmitter::msHorizontalDirCmd;
 | 
						|
NifEmitter::CmdHorizontalAngle NifEmitter::msHorizontalAngleCmd;
 | 
						|
 | 
						|
Ogre::ParticleEmitter* NifEmitterFactory::createEmitter(Ogre::ParticleSystem *psys)
 | 
						|
{
 | 
						|
    Ogre::ParticleEmitter *emit = OGRE_NEW NifEmitter(psys);
 | 
						|
    mEmitters.push_back(emit);
 | 
						|
    return emit;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
class GrowFadeAffector : public Ogre::ParticleAffector
 | 
						|
{
 | 
						|
public:
 | 
						|
    /** Command object for grow_time (see Ogre::ParamCommand).*/
 | 
						|
    class CmdGrowTime : public Ogre::ParamCommand
 | 
						|
    {
 | 
						|
    public:
 | 
						|
        Ogre::String doGet(const void *target) const
 | 
						|
        {
 | 
						|
            const GrowFadeAffector *self = static_cast<const GrowFadeAffector*>(target);
 | 
						|
            return Ogre::StringConverter::toString(self->getGrowTime());
 | 
						|
        }
 | 
						|
        void doSet(void *target, const Ogre::String &val)
 | 
						|
        {
 | 
						|
            GrowFadeAffector *self = static_cast<GrowFadeAffector*>(target);
 | 
						|
            self->setGrowTime(Ogre::StringConverter::parseReal(val));
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    /** Command object for fade_time (see Ogre::ParamCommand).*/
 | 
						|
    class CmdFadeTime : public Ogre::ParamCommand
 | 
						|
    {
 | 
						|
    public:
 | 
						|
        Ogre::String doGet(const void *target) const
 | 
						|
        {
 | 
						|
            const GrowFadeAffector *self = static_cast<const GrowFadeAffector*>(target);
 | 
						|
            return Ogre::StringConverter::toString(self->getFadeTime());
 | 
						|
        }
 | 
						|
        void doSet(void *target, const Ogre::String &val)
 | 
						|
        {
 | 
						|
            GrowFadeAffector *self = static_cast<GrowFadeAffector*>(target);
 | 
						|
            self->setFadeTime(Ogre::StringConverter::parseReal(val));
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    /** Default constructor. */
 | 
						|
    GrowFadeAffector(Ogre::ParticleSystem *psys) : ParticleAffector(psys)
 | 
						|
    {
 | 
						|
        mGrowTime = 0.0f;
 | 
						|
        mFadeTime = 0.0f;
 | 
						|
 | 
						|
        mType = "GrowFade";
 | 
						|
 | 
						|
        // Init parameters
 | 
						|
        if(createParamDictionary("GrowFadeAffector"))
 | 
						|
        {
 | 
						|
            Ogre::ParamDictionary *dict = getParamDictionary();
 | 
						|
 | 
						|
            Ogre::String grow_title("grow_time");
 | 
						|
            Ogre::String fade_title("fade_time");
 | 
						|
            Ogre::String grow_descr("Time from begin to reach full size.");
 | 
						|
            Ogre::String fade_descr("Time from end to shrink.");
 | 
						|
 | 
						|
            dict->addParameter(Ogre::ParameterDef(grow_title, grow_descr, Ogre::PT_REAL), &msGrowCmd);
 | 
						|
            dict->addParameter(Ogre::ParameterDef(fade_title, fade_descr, Ogre::PT_REAL), &msFadeCmd);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /** See Ogre::ParticleAffector. */
 | 
						|
    void _initParticle(Ogre::Particle *particle)
 | 
						|
    {
 | 
						|
        const Ogre::Real life_time     = particle->totalTimeToLive;
 | 
						|
        Ogre::Real       particle_time = particle->timeToLive;
 | 
						|
 | 
						|
        Ogre::Real width = mParent->getDefaultWidth();
 | 
						|
        Ogre::Real height = mParent->getDefaultHeight();
 | 
						|
        if(life_time-particle_time < mGrowTime)
 | 
						|
        {
 | 
						|
            Ogre::Real scale = (life_time-particle_time) / mGrowTime;
 | 
						|
            width *= scale;
 | 
						|
            height *= scale;
 | 
						|
        }
 | 
						|
        if(particle_time < mFadeTime)
 | 
						|
        {
 | 
						|
            Ogre::Real scale = particle_time / mFadeTime;
 | 
						|
            width *= scale;
 | 
						|
            height *= scale;
 | 
						|
        }
 | 
						|
        particle->setDimensions(width, height);
 | 
						|
    }
 | 
						|
 | 
						|
    /** See Ogre::ParticleAffector. */
 | 
						|
    void _affectParticles(Ogre::ParticleSystem *psys, Ogre::Real timeElapsed)
 | 
						|
    {
 | 
						|
        Ogre::ParticleIterator pi = psys->_getIterator();
 | 
						|
        while (!pi.end())
 | 
						|
        {
 | 
						|
            Ogre::Particle *p = pi.getNext();
 | 
						|
            const Ogre::Real life_time     = p->totalTimeToLive;
 | 
						|
            Ogre::Real       particle_time = p->timeToLive;
 | 
						|
 | 
						|
            Ogre::Real width = mParent->getDefaultWidth();
 | 
						|
            Ogre::Real height = mParent->getDefaultHeight();
 | 
						|
            if(life_time-particle_time < mGrowTime)
 | 
						|
            {
 | 
						|
                Ogre::Real scale = (life_time-particle_time) / mGrowTime;
 | 
						|
                width *= scale;
 | 
						|
                height *= scale;
 | 
						|
            }
 | 
						|
            if(particle_time < mFadeTime)
 | 
						|
            {
 | 
						|
                Ogre::Real scale = particle_time / mFadeTime;
 | 
						|
                width *= scale;
 | 
						|
                height *= scale;
 | 
						|
            }
 | 
						|
            p->setDimensions(width, height);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    void setGrowTime(Ogre::Real time)
 | 
						|
    {
 | 
						|
        mGrowTime = time;
 | 
						|
    }
 | 
						|
    Ogre::Real getGrowTime() const
 | 
						|
    { return mGrowTime; }
 | 
						|
 | 
						|
    void setFadeTime(Ogre::Real time)
 | 
						|
    {
 | 
						|
        mFadeTime = time;
 | 
						|
    }
 | 
						|
    Ogre::Real getFadeTime() const
 | 
						|
    { return mFadeTime; }
 | 
						|
 | 
						|
    static CmdGrowTime msGrowCmd;
 | 
						|
    static CmdFadeTime msFadeCmd;
 | 
						|
 | 
						|
protected:
 | 
						|
    Ogre::Real mGrowTime;
 | 
						|
    Ogre::Real mFadeTime;
 | 
						|
};
 | 
						|
GrowFadeAffector::CmdGrowTime GrowFadeAffector::msGrowCmd;
 | 
						|
GrowFadeAffector::CmdFadeTime GrowFadeAffector::msFadeCmd;
 | 
						|
 | 
						|
Ogre::ParticleAffector *GrowFadeAffectorFactory::createAffector(Ogre::ParticleSystem *psys)
 | 
						|
{
 | 
						|
    Ogre::ParticleAffector *p = new GrowFadeAffector(psys);
 | 
						|
    mAffectors.push_back(p);
 | 
						|
    return p;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
class GravityAffector : public Ogre::ParticleAffector
 | 
						|
{
 | 
						|
    enum ForceType {
 | 
						|
        Type_Wind,
 | 
						|
        Type_Point
 | 
						|
    };
 | 
						|
 | 
						|
public:
 | 
						|
    /** Command object for force (see Ogre::ParamCommand).*/
 | 
						|
    class CmdForce : public Ogre::ParamCommand
 | 
						|
    {
 | 
						|
    public:
 | 
						|
        Ogre::String doGet(const void *target) const
 | 
						|
        {
 | 
						|
            const GravityAffector *self = static_cast<const GravityAffector*>(target);
 | 
						|
            return Ogre::StringConverter::toString(self->getForce());
 | 
						|
        }
 | 
						|
        void doSet(void *target, const Ogre::String &val)
 | 
						|
        {
 | 
						|
            GravityAffector *self = static_cast<GravityAffector*>(target);
 | 
						|
            self->setForce(Ogre::StringConverter::parseReal(val));
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    /** Command object for force_type (see Ogre::ParamCommand).*/
 | 
						|
    class CmdForceType : public Ogre::ParamCommand
 | 
						|
    {
 | 
						|
        static ForceType getTypeFromString(const Ogre::String &type)
 | 
						|
        {
 | 
						|
            if(type == "wind")
 | 
						|
                return Type_Wind;
 | 
						|
            if(type == "point")
 | 
						|
                return Type_Point;
 | 
						|
            OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS, "Invalid force type string: "+type,
 | 
						|
                        "CmdForceType::getTypeFromString");
 | 
						|
        }
 | 
						|
 | 
						|
        static Ogre::String getStringFromType(ForceType type)
 | 
						|
        {
 | 
						|
            switch(type)
 | 
						|
            {
 | 
						|
                case Type_Wind: return "wind";
 | 
						|
                case Type_Point: return "point";
 | 
						|
            }
 | 
						|
            OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS, "Invalid force type enum: "+Ogre::StringConverter::toString(type),
 | 
						|
                        "CmdForceType::getStringFromType");
 | 
						|
        }
 | 
						|
 | 
						|
    public:
 | 
						|
        Ogre::String doGet(const void *target) const
 | 
						|
        {
 | 
						|
            const GravityAffector *self = static_cast<const GravityAffector*>(target);
 | 
						|
            return getStringFromType(self->getForceType());
 | 
						|
        }
 | 
						|
        void doSet(void *target, const Ogre::String &val)
 | 
						|
        {
 | 
						|
            GravityAffector *self = static_cast<GravityAffector*>(target);
 | 
						|
            self->setForceType(getTypeFromString(val));
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    /** Command object for direction (see Ogre::ParamCommand).*/
 | 
						|
    class CmdDirection : public Ogre::ParamCommand
 | 
						|
    {
 | 
						|
    public:
 | 
						|
        Ogre::String doGet(const void *target) const
 | 
						|
        {
 | 
						|
            const GravityAffector *self = static_cast<const GravityAffector*>(target);
 | 
						|
            return Ogre::StringConverter::toString(self->getDirection());
 | 
						|
        }
 | 
						|
        void doSet(void *target, const Ogre::String &val)
 | 
						|
        {
 | 
						|
            GravityAffector *self = static_cast<GravityAffector*>(target);
 | 
						|
            self->setDirection(Ogre::StringConverter::parseVector3(val));
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    /** Command object for position (see Ogre::ParamCommand).*/
 | 
						|
    class CmdPosition : public Ogre::ParamCommand
 | 
						|
    {
 | 
						|
    public:
 | 
						|
        Ogre::String doGet(const void *target) const
 | 
						|
        {
 | 
						|
            const GravityAffector *self = static_cast<const GravityAffector*>(target);
 | 
						|
            return Ogre::StringConverter::toString(self->getPosition());
 | 
						|
        }
 | 
						|
        void doSet(void *target, const Ogre::String &val)
 | 
						|
        {
 | 
						|
            GravityAffector *self = static_cast<GravityAffector*>(target);
 | 
						|
            self->setPosition(Ogre::StringConverter::parseVector3(val));
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
 | 
						|
    /** Default constructor. */
 | 
						|
    GravityAffector(Ogre::ParticleSystem *psys)
 | 
						|
      : ParticleAffector(psys)
 | 
						|
      , mForce(0.0f)
 | 
						|
      , mForceType(Type_Wind)
 | 
						|
      , mPosition(0.0f)
 | 
						|
      , mDirection(0.0f)
 | 
						|
    {
 | 
						|
        mType = "Gravity";
 | 
						|
 | 
						|
        // Init parameters
 | 
						|
        if(createParamDictionary("GravityAffector"))
 | 
						|
        {
 | 
						|
            Ogre::ParamDictionary *dict = getParamDictionary();
 | 
						|
 | 
						|
            Ogre::String force_title("force");
 | 
						|
            Ogre::String force_descr("Amount of force applied to particles.");
 | 
						|
            Ogre::String force_type_title("force_type");
 | 
						|
            Ogre::String force_type_descr("Type of force applied to particles (point or wind).");
 | 
						|
            Ogre::String direction_title("direction");
 | 
						|
            Ogre::String direction_descr("Direction of wind forces.");
 | 
						|
            Ogre::String position_title("position");
 | 
						|
            Ogre::String position_descr("Position of point forces.");
 | 
						|
 | 
						|
            dict->addParameter(Ogre::ParameterDef(force_title, force_descr, Ogre::PT_REAL), &msForceCmd);
 | 
						|
            dict->addParameter(Ogre::ParameterDef(force_type_title, force_type_descr, Ogre::PT_STRING), &msForceTypeCmd);
 | 
						|
            dict->addParameter(Ogre::ParameterDef(direction_title, direction_descr, Ogre::PT_VECTOR3), &msDirectionCmd);
 | 
						|
            dict->addParameter(Ogre::ParameterDef(position_title, position_descr, Ogre::PT_VECTOR3), &msPositionCmd);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /** See Ogre::ParticleAffector. */
 | 
						|
    void _affectParticles(Ogre::ParticleSystem *psys, Ogre::Real timeElapsed)
 | 
						|
    {
 | 
						|
        switch(mForceType)
 | 
						|
        {
 | 
						|
            case Type_Wind:
 | 
						|
                applyWindForce(psys, timeElapsed);
 | 
						|
                break;
 | 
						|
            case Type_Point:
 | 
						|
                applyPointForce(psys, timeElapsed);
 | 
						|
                break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    void setForce(Ogre::Real force)
 | 
						|
    { mForce = force; }
 | 
						|
    Ogre::Real getForce() const
 | 
						|
    { return mForce; }
 | 
						|
 | 
						|
    void setForceType(ForceType type)
 | 
						|
    { mForceType = type; }
 | 
						|
    ForceType getForceType() const
 | 
						|
    { return mForceType; }
 | 
						|
 | 
						|
    void setDirection(const Ogre::Vector3 &dir)
 | 
						|
    { mDirection = dir; }
 | 
						|
    const Ogre::Vector3 &getDirection() const
 | 
						|
    { return mDirection; }
 | 
						|
 | 
						|
    void setPosition(const Ogre::Vector3 &pos)
 | 
						|
    { mPosition = pos; }
 | 
						|
    const Ogre::Vector3 &getPosition() const
 | 
						|
    { return mPosition; }
 | 
						|
 | 
						|
    static CmdForce msForceCmd;
 | 
						|
    static CmdForceType msForceTypeCmd;
 | 
						|
    static CmdDirection msDirectionCmd;
 | 
						|
    static CmdPosition msPositionCmd;
 | 
						|
 | 
						|
protected:
 | 
						|
    void applyWindForce(Ogre::ParticleSystem *psys, Ogre::Real timeElapsed)
 | 
						|
    {
 | 
						|
        const Ogre::Vector3 vec = mDirection * mForce * timeElapsed;
 | 
						|
        Ogre::ParticleIterator pi = psys->_getIterator();
 | 
						|
        while (!pi.end())
 | 
						|
        {
 | 
						|
            Ogre::Particle *p = pi.getNext();
 | 
						|
            p->direction += vec;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    void applyPointForce(Ogre::ParticleSystem *psys, Ogre::Real timeElapsed)
 | 
						|
    {
 | 
						|
        const Ogre::Real force = mForce * timeElapsed;
 | 
						|
        Ogre::ParticleIterator pi = psys->_getIterator();
 | 
						|
        while (!pi.end())
 | 
						|
        {
 | 
						|
            Ogre::Particle *p = pi.getNext();
 | 
						|
            const Ogre::Vector3 vec = (p->position - mPosition).normalisedCopy() * force;
 | 
						|
            p->direction += vec;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    float mForce;
 | 
						|
 | 
						|
    ForceType mForceType;
 | 
						|
 | 
						|
    Ogre::Vector3 mPosition;
 | 
						|
    Ogre::Vector3 mDirection;
 | 
						|
};
 | 
						|
GravityAffector::CmdForce GravityAffector::msForceCmd;
 | 
						|
GravityAffector::CmdForceType GravityAffector::msForceTypeCmd;
 | 
						|
GravityAffector::CmdDirection GravityAffector::msDirectionCmd;
 | 
						|
GravityAffector::CmdPosition GravityAffector::msPositionCmd;
 | 
						|
 | 
						|
Ogre::ParticleAffector *GravityAffectorFactory::createAffector(Ogre::ParticleSystem *psys)
 | 
						|
{
 | 
						|
    Ogre::ParticleAffector *p = new GravityAffector(psys);
 | 
						|
    mAffectors.push_back(p);
 | 
						|
    return p;
 | 
						|
}
 |