ソースを参照

Move data to ParticleEffect.

Aster@中国上海 11 年 前
コミット
cd5eef22ae

+ 520 - 1
Source/Engine/Graphics/ParticleEffect.cpp

@@ -22,16 +22,64 @@
 
 #include "Precompiled.h"
 #include "Context.h"
+#include "Log.h"
+#include "Material.h"
 #include "ParticleEffect.h"
+#include "ResourceCache.h"
+#include "XMLFile.h"
 
 #include "DebugNew.h"
 
 namespace Urho3D
 {
 
+static const char* emitterTypeNames[] =
+{
+    "Sphere",
+    "Box",
+    0
+};
+
+static const Vector2 DEFAULT_PARTICLE_SIZE(0.1f, 0.1f);
+static const float DEFAULT_EMISSION_RATE = 10.0f;
+static const float MIN_EMISSION_RATE = 0.01f;
+static const float DEFAULT_TIME_TO_LIVE = 1.0f;
+static const float DEFAULT_VELOCITY = 1.0f;
+static const Vector3 DEFAULT_DIRECTION_MIN(-1.0f, -1.0f, -1.0f);
+static const Vector3 DEFAULT_DIRECTION_MAX(1.0f, 1.0f, 1.0f);
+
 ParticleEffect::ParticleEffect(Context* context) :
-    Resource(context)
+    Resource(context),
+    numParticles_(10),
+    updateInvisible_(false),
+    relative_(true),
+    scaled_(true),
+    sorted_(false),
+    animationLodBias_(0.0f),
+    emitterType_(EMITTER_SPHERE),
+    emitterSize_(Vector3::ZERO),
+    directionMin_(DEFAULT_DIRECTION_MIN),
+    directionMax_(DEFAULT_DIRECTION_MAX),
+    constantForce_(Vector3::ZERO),
+    dampingForce_(0.0f),
+    activeTime_(0.0f),
+    inactiveTime_(0.0f),
+    emissionRateMin_(DEFAULT_EMISSION_RATE),
+    emissionRateMax_(DEFAULT_EMISSION_RATE),
+    sizeMin_(DEFAULT_PARTICLE_SIZE),
+    sizeMax_(DEFAULT_PARTICLE_SIZE),
+    timeToLiveMin_(DEFAULT_TIME_TO_LIVE),
+    timeToLiveMax_(DEFAULT_TIME_TO_LIVE),
+    velocityMin_(DEFAULT_VELOCITY),
+    velocityMax_(DEFAULT_VELOCITY),
+    rotationMin_(0.0f),
+    rotationMax_(0.0f),
+    rotationSpeedMin_(0.0f),
+    rotationSpeedMax_(0.0f),
+    sizeAdd_(0.0f),
+    sizeMul_(1.0f)    
 {
+    SetColor(Color::WHITE);
 }
 
 ParticleEffect::~ParticleEffect()
@@ -43,4 +91,475 @@ void ParticleEffect::RegisterObject(Context* context)
     context->RegisterFactory<ParticleEffect>();
 }
 
+bool ParticleEffect::Load(Deserializer& source)
+{
+    XMLFile file(context_);
+    if (!file.Load(source))
+    {
+        LOGERROR("Load particle effect file failed");
+        return false;
+    }
+
+    XMLElement rootElem = file.GetRoot();
+    if (!rootElem)
+    {
+        LOGERROR("Particle emitter parameter file does not have a valid root element");
+        return false;
+    }
+
+    if (rootElem.HasChild("material"))
+        SetMaterial(GetSubsystem<ResourceCache>()->GetResource<Material>(rootElem.GetChild("material").GetAttribute("name")));
+
+    if (rootElem.HasChild("numparticles"))
+        SetNumParticles(rootElem.GetChild("numparticles").GetInt("value"));
+
+    if (rootElem.HasChild("updateinvisible"))
+        updateInvisible_ = rootElem.GetChild("updateinvisible").GetBool("enable");
+
+    if (rootElem.HasChild("relative"))
+        relative_ = rootElem.GetChild("relative").GetBool("enable");
+
+    if (rootElem.HasChild("scaled"))
+        scaled_ = rootElem.GetChild("scaled").GetBool("enable");
+
+    if (rootElem.HasChild("sorted"))
+        sorted_ = rootElem.GetChild("sorted").GetBool("enable");
+
+    if (rootElem.HasChild("animlodbias"))
+        SetAnimationLodBias(rootElem.GetChild("animlodbias").GetFloat("value"));
+
+    if (rootElem.HasChild("emittertype"))
+    {
+        String type = rootElem.GetChild("emittertype").GetAttributeLower("value");
+        if (type == "point")
+        {
+            // Point emitter type is deprecated, handled as zero sized sphere
+            emitterType_ = EMITTER_SPHERE;
+            emitterSize_ = Vector3::ZERO;
+        }
+        else if (type == "box")
+            emitterType_ = EMITTER_BOX;
+        else if (type == "sphere")
+            emitterType_ = EMITTER_SPHERE;
+        else
+            LOGERROR("Unknown particle emitter type " + type);
+    }
+
+    if (rootElem.HasChild("emittersize"))
+        emitterSize_ = rootElem.GetChild("emittersize").GetVector3("value");
+
+    if (rootElem.HasChild("emitterradius"))
+        emitterSize_.x_ = emitterSize_.y_ = emitterSize_.z_ = rootElem.GetChild("emitterradius").GetFloat("value");
+
+    if (rootElem.HasChild("direction"))
+        GetVector3MinMax(rootElem.GetChild("direction"), directionMin_, directionMax_);
+
+    if (rootElem.HasChild("constantforce"))
+        constantForce_ = rootElem.GetChild("constantforce").GetVector3("value");
+
+    if (rootElem.HasChild("dampingforce"))
+        dampingForce_ = rootElem.GetChild("dampingforce").GetFloat("value");
+
+    if (rootElem.HasChild("activetime"))
+        activeTime_ = rootElem.GetChild("activetime").GetFloat("value");
+    if (activeTime_ < 0.0f)
+        activeTime_ = M_INFINITY;
+
+    if (rootElem.HasChild("inactivetime"))
+        inactiveTime_ = rootElem.GetChild("inactivetime").GetFloat("value");
+    if (inactiveTime_ < 0.0f)
+        inactiveTime_ = M_INFINITY;
+
+    if (rootElem.HasChild("emissionrate"))
+        GetFloatMinMax(rootElem.GetChild("emissionrate"), emissionRateMin_, emissionRateMax_);
+
+    if (rootElem.HasChild("interval"))
+    {
+        float intervalMin = 0.0f;
+        float intervalMax = 0.0f;
+        GetFloatMinMax(rootElem.GetChild("interval"), intervalMin, intervalMax);
+        emissionRateMax_ = 1.0f / intervalMin;
+        emissionRateMin_ = 1.0f / intervalMax;
+    }
+
+    if (rootElem.HasChild("particlesize"))
+        GetVector2MinMax(rootElem.GetChild("particlesize"), sizeMin_, sizeMax_);
+
+    if (rootElem.HasChild("timetolive"))
+        GetFloatMinMax(rootElem.GetChild("timetolive"), timeToLiveMin_, timeToLiveMax_);
+
+    if (rootElem.HasChild("velocity"))
+        GetFloatMinMax(rootElem.GetChild("velocity"), velocityMin_, velocityMax_);
+
+    if (rootElem.HasChild("rotation"))
+        GetFloatMinMax(rootElem.GetChild("rotation"), rotationMin_, rotationMax_);
+
+    if (rootElem.HasChild("rotationspeed"))
+        GetFloatMinMax(rootElem.GetChild("rotationspeed"), rotationSpeedMin_, rotationSpeedMax_);
+
+    if (rootElem.HasChild("sizedelta"))
+    {
+        XMLElement deltaElem = rootElem.GetChild("sizedelta");
+        if (deltaElem.HasAttribute("add"))
+            sizeAdd_ = deltaElem.GetFloat("add");
+        if (deltaElem.HasAttribute("mul"))
+            sizeMul_ = deltaElem.GetFloat("mul");
+    }
+
+    if (rootElem.HasChild("color"))
+        SetColor(rootElem.GetChild("color").GetColor("value"));
+
+    if (rootElem.HasChild("colorfade"))
+    {
+        Vector<ColorFrame> fades;
+        XMLElement colorFadeElem = rootElem.GetChild("colorfade");
+        while (colorFadeElem)
+        {
+            fades.Push(ColorFrame(colorFadeElem.GetColor("color"), colorFadeElem.GetFloat("time")));
+
+            colorFadeElem = colorFadeElem.GetNext("colorfade");
+        }
+        SetColors(fades);
+    }
+
+    if (rootElem.HasChild("texanim"))
+    {
+        Vector<TextureFrame> animations;
+        XMLElement animElem = rootElem.GetChild("texanim");
+        while (animElem)
+        {
+            TextureFrame animation;
+            animation.uv_ = animElem.GetRect("uv");
+            animation.time_ = animElem.GetFloat("time");
+            animations.Push(animation);
+            animElem = animElem.GetNext("texanim");
+        }
+        textureFrames_ = animations;
+    }
+
+    return true;
+}
+
+bool ParticleEffect::Save(Serializer& dest) const
+{
+    XMLFile file(context_);
+    XMLElement rootElem = file.CreateRoot("particleeffect");
+
+    XMLElement childElem = rootElem.CreateChild("material");
+    childElem.SetAttribute("name", GetResourceName(material_));
+
+    childElem = rootElem.CreateChild("numparticles");
+    childElem.SetInt("value", numParticles_);
+
+    childElem = rootElem.CreateChild("updateinvisible");
+    childElem.SetBool("enable", updateInvisible_);
+
+    childElem = rootElem.CreateChild("relative");
+    childElem.SetBool("enable", relative_);
+
+    childElem = rootElem.CreateChild("scaled");
+    childElem.SetBool("enable", scaled_);
+
+    childElem = rootElem.CreateChild("sorted");
+    childElem.SetBool("enable", sorted_);
+
+    childElem = rootElem.CreateChild("animlodbias");
+    childElem.SetFloat("value", animationLodBias_);
+
+    childElem = rootElem.CreateChild("emittertype");
+    childElem.SetAttribute("value", emitterTypeNames[emitterType_]);
+
+    childElem = rootElem.CreateChild("emittersize");
+    childElem.SetVector3("value", emitterSize_);
+
+    childElem = rootElem.CreateChild("direction");
+    childElem.SetVector3("min", directionMin_);
+    childElem.SetVector3("max", directionMax_);
+
+    childElem = rootElem.CreateChild("constantforce");
+    childElem.SetVector3("value", constantForce_);
+
+    childElem = rootElem.CreateChild("dampingforce");
+    childElem.SetFloat("value", dampingForce_);
+
+    childElem = rootElem.CreateChild("activetime");
+    childElem.SetFloat("value", activeTime_);
+
+    childElem = rootElem.CreateChild("inactivetime");
+    childElem.SetFloat("value", inactiveTime_);
+
+    childElem = rootElem.CreateChild("emissionrate");
+    childElem.SetFloat("min", emissionRateMin_);
+    childElem.SetFloat("max", emissionRateMax_);
+
+    childElem = rootElem.CreateChild("particlesize");
+    childElem.SetVector2("min", sizeMin_);
+    childElem.SetVector2("max", sizeMax_);
+
+    childElem = rootElem.CreateChild("timetolive");
+    childElem.SetFloat("min", timeToLiveMin_);
+    childElem.SetFloat("max", timeToLiveMax_);
+
+    childElem = rootElem.CreateChild("velocity");
+    childElem.SetFloat("min", velocityMin_);
+    childElem.SetFloat("max", velocityMax_);
+
+    childElem = rootElem.CreateChild("rotation");
+    childElem.SetFloat("min", rotationMin_);
+    childElem.SetFloat("max", rotationMax_);
+
+    childElem = rootElem.CreateChild("rotationspeed");
+    childElem.SetFloat("min", rotationSpeedMin_);
+    childElem.SetFloat("max", rotationSpeedMax_);
+
+    childElem = rootElem.CreateChild("sizedelta");
+    childElem.SetFloat("add", sizeAdd_);
+    childElem.SetFloat("mul", sizeMul_);
+
+    if (colorFrames_.Size() == 1)
+    {
+        childElem = rootElem.CreateChild("color");
+        childElem.SetColor("value", colorFrames_[0].color_);
+    }
+
+    if (colorFrames_.Size() > 1)
+    {
+        for (unsigned i = 0; i < colorFrames_.Size(); ++i)
+        {
+            childElem = rootElem.CreateChild("colorfade");
+            childElem.SetColor("color", colorFrames_[i].color_);
+            childElem.SetFloat("time", colorFrames_[i].time_);
+        }
+    }
+
+    for (unsigned i = 0; i < textureFrames_.Size(); ++i)
+    {
+        childElem = rootElem.CreateChild("texanim");
+        childElem.SetRect("uv", textureFrames_[i].uv_);
+        childElem.SetFloat("time", textureFrames_[i].time_);
+    }
+
+    return file.Save(dest);
+}
+
+void ParticleEffect::SetMaterial(Material* material)
+{
+    material_ = material;
+}
+
+void ParticleEffect::SetNumParticles(unsigned num)
+{
+    numParticles_ = Max(0, num);
+}
+
+void ParticleEffect::SetUpdateInvisible(bool enable)
+{
+    updateInvisible_ = enable;
+}
+
+void ParticleEffect::SetRelative(bool enable)
+{
+    relative_ = enable;
+}
+
+void ParticleEffect::SetScaled(bool enable)
+{
+    scaled_ = enable;
+}
+
+void ParticleEffect::SetSorted(bool enable)
+{
+    sorted_ = enable;
+}
+
+void ParticleEffect::SetAnimationLodBias(float lodBias)
+{
+    animationLodBias_ = lodBias;
+}
+
+void ParticleEffect::SetEmitterType(EmitterType type)
+{
+    emitterType_ = type;
+}
+
+void ParticleEffect::SetEmitterSize(const Vector3& size)
+{
+    emitterSize_ = size;
+}
+
+void ParticleEffect::SetMinDirection(const Vector3& direction)
+{
+    directionMin_ = direction;
+}
+
+void ParticleEffect::SetMaxDirection(const Vector3& direction)
+{
+    directionMax_ = direction;
+}
+
+void ParticleEffect::SetConstantForce(const Vector3& force)
+{
+    constantForce_ = force;
+}
+
+void ParticleEffect::SetDampingForce(float force)
+{
+    dampingForce_ = force;
+}
+
+void ParticleEffect::SetActiveTime(float time)
+{
+    activeTime_ = time;
+}
+
+void ParticleEffect::SetInactiveTime(float time)
+{
+    inactiveTime_ = time;
+}
+
+void ParticleEffect::SetMinEmissionRate(float rate)
+{
+    emissionRateMin_ = Max(rate, MIN_EMISSION_RATE);
+}
+
+void ParticleEffect::SetMaxEmissionRate(float rate)
+{
+    emissionRateMax_ = Max(rate, MIN_EMISSION_RATE);
+}
+
+void ParticleEffect::SetMinParticleSize(const Vector2& size)
+{
+    sizeMin_ = size;
+}
+
+void ParticleEffect::SetMaxParticleSize(const Vector2& size)
+{
+    sizeMax_ = size;
+}
+
+void ParticleEffect::SetMinTimeToLive(float time)
+{
+    timeToLiveMin_ = Max(time, 0.0f);
+}
+
+void ParticleEffect::SetMaxTimeToLive(float time)
+{
+    timeToLiveMax_ = Max(time, 0.0f);
+}
+
+void ParticleEffect::SetMinVelocity(float velocity)
+{
+    velocityMin_ = velocity;
+}
+
+void ParticleEffect::SetMaxVelocity(float velocity)
+{
+    velocityMax_ = velocity;
+}
+
+void ParticleEffect::SetMinRotation(float rotation)
+{
+    rotationMin_ = rotation;
+}
+
+void ParticleEffect::SetMaxRotation(float rotation)
+{
+    rotationMax_ = rotation;
+}
+
+void ParticleEffect::SetMinRotationSpeed(float speed)
+{
+    rotationSpeedMin_ = speed;
+}
+
+void ParticleEffect::SetMaxRotationSpeed(float speed)
+{
+    rotationSpeedMax_ = speed;
+}
+
+
+void ParticleEffect::SetSizeAdd(float sizeAdd)
+{
+    sizeAdd_ = sizeAdd;
+}
+
+void ParticleEffect::SetSizeMul(float sizeMul)
+{
+    sizeMul_ = sizeMul;
+}
+
+void ParticleEffect::SetColor(const Color& color)
+{
+    colorFrames_.Clear();
+    colorFrames_.Push(ColorFrame(color));
+}
+
+void ParticleEffect::SetColors(const Vector<ColorFrame>& colors)
+{
+    if (!colors.Size())
+        return;
+
+    colorFrames_ = colors;
+}
+
+void ParticleEffect::SetNumColors(unsigned num)
+{
+    colorFrames_.Resize(num);
+}
+
+void ParticleEffect::SetTextureFrames(const Vector<TextureFrame>& animation)
+{
+    textureFrames_ = animation;
+}
+
+void ParticleEffect::SetNumTextureFrames(unsigned num)
+{
+    textureFrames_.Resize(num);
+}
+
+void ParticleEffect::GetFloatMinMax(const XMLElement& element, float& minValue, float& maxValue)
+{
+    if (element.IsNull())
+        return;
+
+    if (element.HasAttribute("value"))
+        minValue = maxValue = element.GetFloat("value");
+
+    if (element.HasAttribute("min") && element.HasAttribute("max"))
+    {
+        minValue = element.GetFloat("min");
+        maxValue = element.GetFloat("max");
+    }
+}
+
+void ParticleEffect::GetVector2MinMax(const XMLElement& element, Vector2& minValue, Vector2& maxValue)
+{
+    if (element.IsNull())
+        return;
+
+    if (element.HasAttribute("value"))
+        minValue = maxValue = element.GetVector2("value");
+
+    if (element.HasAttribute("min") && element.HasAttribute("max"))
+    {
+        minValue = element.GetVector2("min");
+        maxValue = element.GetVector2("max");
+    }
+}
+
+void ParticleEffect::GetVector3MinMax(const XMLElement& element, Vector3& minValue, Vector3& maxValue)
+{
+    if (element.IsNull())
+        return;
+
+    if (element.HasAttribute("value"))
+        minValue = maxValue = element.GetVector3("value");
+
+    if (element.HasAttribute("min") && element.HasAttribute("max"))
+    {
+        minValue = element.GetVector3("min");
+        maxValue = element.GetVector3("max");
+    }
+}
+
 }

+ 288 - 2
Source/Engine/Graphics/ParticleEffect.h

@@ -27,11 +27,81 @@
 namespace Urho3D
 {
 
-/// %Particle effect.
+/// Particle emitter shapes.
+enum EmitterType
+{
+    EMITTER_SPHERE,
+    EMITTER_BOX
+};
+
+/// %Color animation frame definition.
+struct ColorFrame
+{
+    /// Construct with default values.
+    ColorFrame() :
+        time_(0.0f)
+    {
+    }
+
+    /// Construct with a color and zero time.
+    ColorFrame(const Color& color) :
+        color_(color),
+        time_(0.0f)
+    {
+    }
+
+    /// Construct from a color and time.
+    ColorFrame(const Color& color, float time) :
+        color_(color),
+        time_(time)
+    {
+    }
+
+    /// Return interpolated value with another color-time pair at the time specified.
+    Color Interpolate(const ColorFrame& next, float time) const
+    {
+        float timeInterval = next.time_ - time_;
+        if (timeInterval > 0.0f)
+        {
+            float t = (time - time_) / timeInterval;
+            return color_.Lerp(next.color_, t);
+        }
+        else
+            return next.color_;
+    }
+
+    /// Color.
+    Color color_;
+    /// Time.
+    float time_;
+};
+
+/// %Texture animation frame definition.
+struct TextureFrame
+{
+    /// Construct with default values.
+    TextureFrame() :
+        uv_(0.0f, 0.0f, 1.0f, 1.0f),
+        time_(0.0f)
+    {
+    }
+
+    /// UV coordinates.
+    Rect uv_;
+    /// Time.
+    float time_;
+};
+
+class Material;
+class XMLFile;
+class XMLElement;
+
+/// %Particle emitter component.
 class URHO3D_API ParticleEffect : public Resource
 {
     OBJECT(ParticleEffect);
-    
+    friend class ParticleEmitter;
+
 public:
     /// Construct.
     ParticleEffect(Context* context);
@@ -39,6 +109,222 @@ public:
     virtual ~ParticleEffect();
     /// Register object factory.
     static void RegisterObject(Context* context);
+
+    /// Load resource. Return true if successful.
+    virtual bool Load(Deserializer& source);
+    /// Save resource. Return true if successful.
+    virtual bool Save(Serializer& dest) const;
+
+    /// Set material.
+    void SetMaterial(Material* material);
+    /// Set maximum number of particles.
+    void SetNumParticles(unsigned num);
+    /// Set whether to update when particles are not visible.
+    void SetUpdateInvisible(bool enable);
+    /// Set whether billboards are relative to the scene node. Default true.
+    void SetRelative(bool enable);
+    /// Set scaled.
+    void SetScaled(bool enable);
+    /// Set sorted.
+    void SetSorted(bool enable);
+    /// Set animation LOD bias.
+    void SetAnimationLodBias(float lodBias);
+    /// Set emitter type.
+    void SetEmitterType(EmitterType type);
+    /// Set emitter size.
+    void SetEmitterSize(const Vector3& size);
+    /// Set negative direction limit.
+    void SetMinDirection(const Vector3& direction);
+    /// Set positive direction limit.
+    void SetMaxDirection(const Vector3& direction);
+    /// Set constant force acting on particles.
+    void SetConstantForce(const Vector3& force);
+    /// Set particle velocity damping force.
+    void SetDampingForce(float force);
+    /// Set emission active period length (0 = infinite.)
+    void SetActiveTime(float time);
+    /// Set emission inactive period length (0 = infinite.)
+    void SetInactiveTime(float time);
+    /// Set minimum emission rate.
+    void SetMinEmissionRate(float rate);
+    /// Set maximum emission rate.
+    void SetMaxEmissionRate(float rate);
+    /// Set particle minimum size.
+    void SetMinParticleSize(const Vector2& size);
+    /// Set particle maximum size.
+    void SetMaxParticleSize(const Vector2& size);
+    /// Set particle minimum time to live.
+    void SetMinTimeToLive(float time);
+    /// Set particle maximum time to live.
+    void SetMaxTimeToLive(float time);
+    /// Set particle minimum velocity.
+    void SetMinVelocity(float velocity);
+    /// Set particle maximum velocity.
+    void SetMaxVelocity(float velocity);
+    /// Set particle minimum rotation.
+    void SetMinRotation(float rotation);
+    /// Set particle maximum rotation.
+    void SetMaxRotation(float rotation);
+    /// Set particle minimum rotation speed.
+    void SetMinRotationSpeed(float speed);
+    /// Set particle maximum rotation speed.
+    void SetMaxRotationSpeed(float speed);    
+    /// Set particle size additive modifier.
+    void SetSizeAdd(float sizeAdd);
+    /// Set particle size multiplicative modifier.
+    void SetSizeMul(float sizeMul);
+    /// Set color of particles.
+    void SetColor(const Color& color);
+    /// Set color animation of particles.
+    void SetColors(const Vector<ColorFrame>& colors);
+    /// Set number of color animation frames.
+    void SetNumColors(unsigned num);
+    /// Set particle texture animation.
+    void SetTextureFrames(const Vector<TextureFrame>& animation);
+    /// Set number of texture animation frames.
+    void SetNumTextureFrames(unsigned num);
+
+    /// Return material.
+    Material* GetMaterial() const { return material_; }
+    /// Return maximum number of particles.
+    unsigned GetNumParticles() const { return numParticles_; }
+    /// Return whether to update when particles are not visible.
+    bool GetUpdateInvisible() const { return updateInvisible_; }
+    /// Return whether billboards are relative to the scene node.
+    bool IsRelative() const { return relative_; }
+    /// Return whether scene node scale affects billboards' size.
+    bool IsScaled() const { return scaled_; }
+    /// Return whether billboards are sorted.
+    bool IsSorted() const { return sorted_; }
+    /// Return animation Lod bias.
+    float GetAnimationLodBias() const { return animationLodBias_; }
+    /// Return emitter type.
+    EmitterType GetEmitterType() const { return emitterType_; }
+    /// Return emitter size.
+    const Vector3& GetEmitterSize() const { return emitterSize_; }
+    /// Return negative direction limit.
+    const Vector3& GetMinDirection() const { return directionMin_; }
+    /// Return positive direction limit.
+    const Vector3& GetMaxDirection() const { return directionMax_; }
+    /// Return constant force acting on particles.
+    const Vector3& GetConstantForce() const { return constantForce_; }
+    /// Return particle velocity damping force.
+    float GetDampingForce() const { return dampingForce_; }
+    /// Return emission active period length (0 = infinite.)
+    float GetActiveTime() const { return activeTime_; }
+    /// Return emission inactive period length (0 = infinite.)
+    float GetInactiveTime() const { return inactiveTime_; }
+    /// Return minimum emission rate.
+    float GetMinEmissionRate() const { return emissionRateMin_; }
+    /// Return maximum emission rate.
+    float GetMaxEmissionRate() const { return emissionRateMax_; }
+    /// Return particle minimum size.
+    const Vector2& GetMinParticleSize() const { return sizeMin_; }
+    /// Return particle maximum size.
+    const Vector2& GetMaxParticleSize() const { return sizeMax_; }
+    /// Return particle minimum time to live.
+    float GetMinTimeToLive() const { return timeToLiveMin_; }
+    /// Return particle maximum time to live.
+    float GetMaxTimeToLive() const { return timeToLiveMax_; }
+    /// Return particle minimum velocity.
+    float GetMinVelocity() const { return velocityMin_; }
+    /// Return particle maximum velocity.
+    float GetMaxVelocity() const { return velocityMax_; }
+    /// Return particle minimum rotation.
+    float GetMinRotation() const { return rotationMin_; }
+    /// Return particle maximum rotation.
+    float GetMaxRotation() const { return rotationMax_; }
+    /// Return particle minimum rotation speed.
+    float GetMinRotationSpeed() const { return rotationSpeedMin_; }
+    /// Return particle maximum rotation speed.
+    float GetMaxRotationSpeed() const { return rotationSpeedMax_; }   
+    /// Return particle size additive modifier.
+    float GetSizeAdd() const { return sizeAdd_; }
+    /// Return particle size multiplicative modifier.
+    float GetSizeMul() const { return sizeMul_; }
+    /// Return all color animation frames.
+    Vector<ColorFrame>& GetColors() { return colorFrames_; }
+    /// Return number of color animation frames.
+    unsigned GetNumColors() const { return colorFrames_.Size(); }
+    /// Return a color animation frame, or null if outside range.
+    ColorFrame* GetColor(unsigned index) { return index < colorFrames_.Size() ? &colorFrames_[index] : (ColorFrame*)0; }
+    /// Return all texture animation frames.
+    Vector<TextureFrame>& GetTextureFrame() { return textureFrames_; }
+    /// Return number of texture animation frames.
+    unsigned GetNumTextureFrames() const { return textureFrames_.Size(); }
+    /// Return a texture animation frame, or null if outside range.
+    TextureFrame* GetTextureFrame(unsigned index) { return index < colorFrames_.Size() ? &textureFrames_[index] : (TextureFrame*)0; }
+
+private:
+    /// Read a float range from an XML element.
+    void GetFloatMinMax(const XMLElement& element, float& minValue, float& maxValue);
+    /// Read a Vector2 range from an XML element.
+    void GetVector2MinMax(const XMLElement& element, Vector2& minValue, Vector2& maxValue);
+    /// Read a Vector3 from an XML element.
+    void GetVector3MinMax(const XMLElement& element, Vector3& minValue, Vector3& maxValue);
+
+    /// Material.
+    SharedPtr<Material> material_;
+    /// Number of particles.
+    unsigned numParticles_;
+    /// Update when invisible flag.
+    bool updateInvisible_;
+    /// Billboards relative flag.
+    bool relative_;
+    /// Scale affects billboard scale flag.
+    bool scaled_;
+    /// Billboards sorted flag.
+    bool sorted_;
+    /// Animation LOD bias.
+    float animationLodBias_;
+    /// Emitter shape.
+    EmitterType emitterType_;
+    /// Emitter size.
+    Vector3 emitterSize_;
+    /// Particle direction minimum.
+    Vector3 directionMin_;
+    /// Particle direction maximum.
+    Vector3 directionMax_;
+    /// Particle constant force.
+    Vector3 constantForce_;
+    /// Particle velocity damping force.
+    float dampingForce_;
+    /// Active period.
+    float activeTime_;
+    /// Inactive period.
+    float inactiveTime_;
+    /// Particles per second minimum.
+    float emissionRateMin_;
+    /// Particles per second maximum.
+    float emissionRateMax_;
+    /// Particle size minimum.
+    Vector2 sizeMin_;
+    /// Particle size maximum.
+    Vector2 sizeMax_;
+    /// Particle time to live minimum.
+    float timeToLiveMin_;
+    /// Particle time to live maximum.
+    float timeToLiveMax_;
+    /// Particle velocity minimum.
+    float velocityMin_;
+    /// Particle velocity maximum.
+    float velocityMax_;
+    /// Particle rotation angle minimum.
+    float rotationMin_;
+    /// Particle rotation angle maximum.
+    float rotationMax_;
+    /// Particle rotation speed minimum.
+    float rotationSpeedMin_;
+    /// Particle rotation speed maximum.
+    float rotationSpeedMax_;
+    /// Particle size additive parameter.
+    float sizeAdd_;
+    /// Particle size multiplicative parameter.
+    float sizeMul_;
+    /// Particle color animation frames.
+    Vector<ColorFrame> colorFrames_;
+    /// Texture animation frames.
+    Vector<TextureFrame> textureFrames_;
 };
 
 }