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)
- Allow more control over particle behavior when the ParticleSystemSceneNode is invisible.
- 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).
- 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:
p->addAffector(paf);
paf->drop();
\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
{
public:
......@@ -52,7 +65,10 @@ public:
const core::vector3df& position = 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))
: 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.
virtual void setParticleSize(
......@@ -64,6 +80,24 @@ public:
Default is true. */
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
virtual void clearParticles() = 0;
......@@ -503,11 +537,24 @@ public:
virtual IParticleRotationAffector* createRotationAffector(
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;
//! 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 irr
#endif
......@@ -417,9 +417,11 @@ void CParticleSystemSceneNode::doParticleSystem(u32 time)
u32 timediff = time - LastEmitTime;
LastEmitTime = time;
int stop = isVisible() ? 0 : getInvisibleBehavior();
// run emitter
if (Emitter && IsVisible)
if (Emitter && !(stop & EPI_STOP_EMITTERS) )
{
SParticle* array = 0;
s32 newParticles = Emitter->emitt(now, timediff, array);
......@@ -441,9 +443,12 @@ void CParticleSystemSceneNode::doParticleSystem(u32 time)
}
// run affectors
core::list<IParticleAffector*>::Iterator ait = AffectorList.begin();
for (; ait != AffectorList.end(); ++ait)
(*ait)->affect(now, Particles.pointer(), Particles.size());
if ( !(stop & EPI_STOP_AFFECTORS) )
{
core::list<IParticleAffector*>::Iterator ait = AffectorList.begin();
for (; ait != AffectorList.end(); ++ait)
(*ait)->affect(now, Particles.pointer(), Particles.size());
}
if (ParticlesAreGlobal)
Buffer->BoundingBox.reset(AbsoluteTransformation.getTranslation());
......@@ -451,25 +456,28 @@ void CParticleSystemSceneNode::doParticleSystem(u32 time)
Buffer->BoundingBox.reset(core::vector3df(0,0,0));
// animate all particles
f32 scale = (f32)timediff;
for (u32 i=0; i<Particles.size();)
if ( !(stop & EPI_STOP_ANIMATING) )
{
// erase is pretty expensive!
if (now > Particles[i].endTime)
{
// 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
f32 scale = (f32)timediff;
for (u32 i=0; i<Particles.size();)
{
Particles[i].pos += (Particles[i].vector * scale);
Buffer->BoundingBox.addInternalPoint(Particles[i].pos);
++i;
// erase is pretty expensive!
if (now > Particles[i].endTime)
{
// 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()
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.
void CParticleSystemSceneNode::setParticleSize(const core::dimension2d<f32> &size)
{
......
......@@ -194,6 +194,9 @@ public:
//! Remove all currently visible particles
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.
//! This should only be called when you want to render the node outside the scenegraph,
//! 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