Commit ca6029b5 authored by cutealien's avatar cutealien

Allow more control over particle behavior when the ParticleSystemSceneNode is invisible.


git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@4769 dfc29bdd-3216-0410-991c-e03cc46cb475
parent b7083aaa
-------------------------- --------------------------
Changes in 1.9 (not yet released) Changes in 1.9 (not yet released)
- Allow more control over particle behavior when the ParticleSystemSceneNode is invisible.
- ISceneNodeAnimators can now be disabled and paused. - ISceneNodeAnimators can now be disabled and paused.
- Maya camera no longer get's stuck in "rotating" state when a mouse-up event is lost (thx @ JLouisB for reporting). - Maya camera no longer get's stuck in "rotating" state when a mouse-up event is lost (thx @ JLouisB for reporting).
- Focus behavior of IGUIEnvironment now controllable (right-click focus, mouse-over focus). Disabled elements no longer get the focus unless users enforce it. - Focus behavior of IGUIEnvironment now controllable (right-click focus, mouse-over focus). Disabled elements no longer get the focus unless users enforce it.
......
...@@ -41,8 +41,21 @@ You can for example easily create a campfire by doing this: ...@@ -41,8 +41,21 @@ You can for example easily create a campfire by doing this:
p->addAffector(paf); p->addAffector(paf);
paf->drop(); paf->drop();
\endcode \endcode
*/ */
//! Bitflags to control particle behavior when the IParticleSystemSceneNode is invisible
enum EParticleInvisible
{
//! Stop emitting new particles when invisible
EPI_STOP_EMITTERS = 1,
//! No longer affect particles when invisible
EPI_STOP_AFFECTORS = 2,
//! Stop updating particle positions or deleting them when invisible
EPI_STOP_ANIMATING = 4,
//! Clear all particles when node gets invisible
EPI_CLEAR_ON_INVISIBLE = 8
};
class IParticleSystemSceneNode : public ISceneNode class IParticleSystemSceneNode : public ISceneNode
{ {
public: public:
...@@ -52,7 +65,10 @@ public: ...@@ -52,7 +65,10 @@ public:
const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& position = core::vector3df(0,0,0),
const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0),
const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f))
: ISceneNode(parent, mgr, id, position, rotation, scale) {} : ISceneNode(parent, mgr, id, position, rotation, scale)
, ParticleInvisibleBehavior(EPI_STOP_EMITTERS|EPI_STOP_AFFECTORS|EPI_STOP_ANIMATING|EPI_CLEAR_ON_INVISIBLE)
{
}
//! Sets the size of all particles. //! Sets the size of all particles.
virtual void setParticleSize( virtual void setParticleSize(
...@@ -64,6 +80,24 @@ public: ...@@ -64,6 +80,24 @@ public:
Default is true. */ Default is true. */
virtual void setParticlesAreGlobal(bool global=true) = 0; virtual void setParticlesAreGlobal(bool global=true) = 0;
//! Sets how particles behave when this node is invisible
/** Default is: EPIB_STOP_EMITTERS|EPIB_STOP_AFFECTORS|EPIB_STOP_ANIMATING|EPI_CLEAR_ON_INVISIBLE
\param flags Any combination of ::EParticleInvisibleBehavior flags
*/
virtual void setInvisibleBehavior(irr::u32 flags)
{
ParticleInvisibleBehavior = flags;
}
//! Gets how particles behave when this node is invisible
/**
\return A combination of ::EParticleInvisibleBehavior flags
*/
virtual irr::u32 getInvisibleBehavior() const
{
return ParticleInvisibleBehavior;
}
//! Remove all currently visible particles //! Remove all currently visible particles
virtual void clearParticles() = 0; virtual void clearParticles() = 0;
...@@ -503,11 +537,24 @@ public: ...@@ -503,11 +537,24 @@ public:
virtual IParticleRotationAffector* createRotationAffector( virtual IParticleRotationAffector* createRotationAffector(
const core::vector3df& speed = core::vector3df(5.0f,5.0f,5.0f), const core::vector3df& speed = core::vector3df(5.0f,5.0f,5.0f),
const core::vector3df& pivotPoint = core::vector3df(0.0f,0.0f,0.0f) ) = 0; const core::vector3df& pivotPoint = core::vector3df(0.0f,0.0f,0.0f) ) = 0;
//! Writes attributes of the scene node.
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const _IRR_OVERRIDE_
{
out->addInt("ParticleInvisibleBehavior", ParticleInvisibleBehavior);
}
//! Reads attributes of the scene node.
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) _IRR_OVERRIDE_
{
ParticleInvisibleBehavior = in->getAttributeAsInt("ParticleInvisibleBehavior", ParticleInvisibleBehavior);
}
protected:
s32 ParticleInvisibleBehavior;
}; };
} // end namespace scene } // end namespace scene
} // end namespace irr } // end namespace irr
#endif #endif
...@@ -417,9 +417,11 @@ void CParticleSystemSceneNode::doParticleSystem(u32 time) ...@@ -417,9 +417,11 @@ void CParticleSystemSceneNode::doParticleSystem(u32 time)
u32 timediff = time - LastEmitTime; u32 timediff = time - LastEmitTime;
LastEmitTime = time; LastEmitTime = time;
int stop = isVisible() ? 0 : getInvisibleBehavior();
// run emitter // run emitter
if (Emitter && IsVisible) if (Emitter && !(stop & EPI_STOP_EMITTERS) )
{ {
SParticle* array = 0; SParticle* array = 0;
s32 newParticles = Emitter->emitt(now, timediff, array); s32 newParticles = Emitter->emitt(now, timediff, array);
...@@ -441,9 +443,12 @@ void CParticleSystemSceneNode::doParticleSystem(u32 time) ...@@ -441,9 +443,12 @@ void CParticleSystemSceneNode::doParticleSystem(u32 time)
} }
// run affectors // run affectors
core::list<IParticleAffector*>::Iterator ait = AffectorList.begin(); if ( !(stop & EPI_STOP_AFFECTORS) )
for (; ait != AffectorList.end(); ++ait) {
(*ait)->affect(now, Particles.pointer(), Particles.size()); core::list<IParticleAffector*>::Iterator ait = AffectorList.begin();
for (; ait != AffectorList.end(); ++ait)
(*ait)->affect(now, Particles.pointer(), Particles.size());
}
if (ParticlesAreGlobal) if (ParticlesAreGlobal)
Buffer->BoundingBox.reset(AbsoluteTransformation.getTranslation()); Buffer->BoundingBox.reset(AbsoluteTransformation.getTranslation());
...@@ -451,25 +456,28 @@ void CParticleSystemSceneNode::doParticleSystem(u32 time) ...@@ -451,25 +456,28 @@ void CParticleSystemSceneNode::doParticleSystem(u32 time)
Buffer->BoundingBox.reset(core::vector3df(0,0,0)); Buffer->BoundingBox.reset(core::vector3df(0,0,0));
// animate all particles // animate all particles
f32 scale = (f32)timediff; if ( !(stop & EPI_STOP_ANIMATING) )
for (u32 i=0; i<Particles.size();)
{ {
// erase is pretty expensive! f32 scale = (f32)timediff;
if (now > Particles[i].endTime)
{ for (u32 i=0; i<Particles.size();)
// Particle order does not seem to matter.
// So we can delete by switching with last particle and deleting that one.
// This is a lot faster and speed is very important here as the erase otherwise
// can cause noticable freezes.
Particles[i] = Particles[Particles.size()-1];
Particles.erase( Particles.size()-1 );
}
else
{ {
Particles[i].pos += (Particles[i].vector * scale); // erase is pretty expensive!
Buffer->BoundingBox.addInternalPoint(Particles[i].pos); if (now > Particles[i].endTime)
++i; {
// Particle order does not seem to matter.
// So we can delete by switching with last particle and deleting that one.
// This is a lot faster and speed is very important here as the erase otherwise
// can cause noticable freezes.
Particles[i] = Particles[Particles.size()-1];
Particles.erase( Particles.size()-1 );
}
else
{
Particles[i].pos += (Particles[i].vector * scale);
Buffer->BoundingBox.addInternalPoint(Particles[i].pos);
++i;
}
} }
} }
...@@ -504,6 +512,14 @@ void CParticleSystemSceneNode::clearParticles() ...@@ -504,6 +512,14 @@ void CParticleSystemSceneNode::clearParticles()
Particles.set_used(0); Particles.set_used(0);
} }
//! Sets if the node should be visible or not.
void CParticleSystemSceneNode::setVisible(bool isVisible)
{
IParticleSystemSceneNode::setVisible(isVisible);
if ( !isVisible && getInvisibleBehavior() & EPI_CLEAR_ON_INVISIBLE )
clearParticles();
}
//! Sets the size of all particles. //! Sets the size of all particles.
void CParticleSystemSceneNode::setParticleSize(const core::dimension2d<f32> &size) void CParticleSystemSceneNode::setParticleSize(const core::dimension2d<f32> &size)
{ {
......
...@@ -194,6 +194,9 @@ public: ...@@ -194,6 +194,9 @@ public:
//! Remove all currently visible particles //! Remove all currently visible particles
virtual void clearParticles() _IRR_OVERRIDE_; virtual void clearParticles() _IRR_OVERRIDE_;
//! Sets if the node should be visible or not.
virtual void setVisible(bool isVisible) _IRR_OVERRIDE_;
//! Do manually update the particles. //! Do manually update the particles.
//! This should only be called when you want to render the node outside the scenegraph, //! This should only be called when you want to render the node outside the scenegraph,
//! as the node will care about this otherwise automatically. //! as the node will care about this otherwise automatically.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment