Change particle emitters into track objects so that they can be animated. I think I also fixed a few relatively minor leaks along the way

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@11415 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria 2012-07-21 02:05:51 +00:00
parent f766785302
commit 8760f28450
6 changed files with 82 additions and 44 deletions

View File

@ -200,8 +200,8 @@ ParticleEmitter::ParticleEmitter(const ParticleKind* type,
ParticleEmitter::~ParticleEmitter()
{
assert(m_magic_number == 0x58781325);
assert(m_node != NULL);
irr_driver->removeNode(m_node);
if (m_node != NULL)
irr_driver->removeNode(m_node);
m_emitter->drop();
m_magic_number = 0xDEADBEEF;

View File

@ -25,6 +25,7 @@ namespace irr
}
using namespace irr;
#include "utils/leak_check.hpp"
#include "utils/no_copy.hpp"
#include "utils/vec3.hpp"
@ -74,6 +75,8 @@ private:
public:
LEAK_CHECK()
ParticleEmitter (const ParticleKind* type,
const Vec3 &position,
scene::ISceneNode* parent = NULL);
@ -95,6 +98,9 @@ public:
scene::IParticleSystemSceneNode* getNode() { return m_node; }
/** call this if the node was freed otherwise */
void unsetNode() { m_node = NULL; }
void addHeightMapAffector(Track* t);
};
#endif

View File

@ -1334,41 +1334,7 @@ void Track::loadTrackModel(World* parent, bool reverse_track,
{
if (UserConfigParams::m_graphical_effects)
{
std::string path;
irr::core::vector3df emitter_origin;
node->get("kind", &path);
node->getXYZ(&emitter_origin);
int clip_distance = -1;
node->get("clip_distance", &clip_distance);
try
{
ParticleKind* kind = ParticleKindManager::get()->getParticles( path.c_str() );
if (kind == NULL)
{
throw std::runtime_error(path + " could not be loaded");
}
ParticleEmitter* emitter = new ParticleEmitter( kind, emitter_origin );
if (clip_distance > 0)
{
scene::ISceneManager* sm = irr_driver->getSceneManager();
scene::ISceneNode* sroot = sm->getRootSceneNode();
LODNode* lod = new LODNode("particles", sroot, sm);
lod->add(clip_distance, (scene::ISceneNode*)emitter->getNode(), true);
//m_all_emitters.push_back(emitter);
m_all_nodes.push_back( lod );
}
else
{
m_all_emitters.push_back(emitter);
}
}
catch (std::runtime_error& e)
{
fprintf(stderr, "[Track] WARNING: Could not load particles '%s'; cause :\n %s", path.c_str(), e.what());
}
m_track_object_manager->add(*node);
}
}
else if(name=="sky-dome" || name=="sky-box" || name=="sky-color")

View File

@ -22,6 +22,9 @@
#include "audio/sfx_buffer.hpp"
#include "audio/sfx_manager.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/lod_node.hpp"
#include "graphics/particle_emitter.hpp"
#include "graphics/particle_kind_manager.hpp"
#include "io/file_manager.hpp"
#include "io/xml_node.hpp"
#include "items/item_manager.hpp"
@ -30,6 +33,8 @@
#include "tracks/track.hpp"
#include <IMeshSceneNode.h>
#include <ISceneManager.h>
#include <IParticleSystemSceneNode.h>
/** A track object: any additional object on the track. This object implements
* a graphics-only representation, i.e. there is no physical representation.
@ -49,7 +54,9 @@ TrackObject::TrackObject(const XMLNode &xml_node)
m_sound = NULL;
m_mesh = NULL;
m_node = NULL;
m_emitter = NULL;
m_lod_emitter_node = NULL;
xml_node.get("xyz", &m_init_xyz );
xml_node.get("hpr", &m_init_hpr );
xml_node.get("scale", &m_init_scale);
@ -72,9 +79,50 @@ TrackObject::TrackObject(const XMLNode &xml_node)
bool trigger_when_near = false;
float trigger_distance = 1.0f;
if (xml_node.getName() == "particle-emitter")
{
std::string path;
irr::core::vector3df emitter_origin;
xml_node.get("kind", &path);
xml_node.getXYZ(&emitter_origin);
int clip_distance = -1;
xml_node.get("clip_distance", &clip_distance);
try
{
ParticleKind* kind = ParticleKindManager::get()->getParticles( path.c_str() );
if (kind == NULL)
{
throw std::runtime_error(path + " could not be loaded");
}
ParticleEmitter* emitter = new ParticleEmitter( kind, emitter_origin );
if (clip_distance > 0)
{
scene::ISceneManager* sm = irr_driver->getSceneManager();
scene::ISceneNode* sroot = sm->getRootSceneNode();
LODNode* lod = new LODNode("particles", sroot, sm);
lod->add(clip_distance, (scene::ISceneNode*)emitter->getNode(), true);
//m_all_emitters.push_back(emitter);
m_node = lod;
m_lod_emitter_node = lod;
m_emitter = emitter;
}
else
{
m_node = emitter->getNode(); // FIXME: this leaks
m_emitter = emitter;
}
}
catch (std::runtime_error& e)
{
fprintf(stderr, "[Track] WARNING: Could not load particles '%s'; cause :\n %s", path.c_str(), e.what());
}
}
// FIXME: at this time sound emitters are just disabled in multiplayer
// otherwise the sounds would be constantly heard
if (sound.size() > 0 && race_manager->getNumLocalPlayers() < 2)
else if (sound.size() > 0 && race_manager->getNumLocalPlayers() < 2)
{
float rolloff = 0.5;
xml_node.get("rolloff", &rolloff );
@ -155,9 +203,8 @@ TrackObject::TrackObject(const XMLNode &xml_node)
// don't use this scene node
if (model_name == "")
{
m_node = NULL;
m_mesh = NULL;
if (trigger_when_near)
{
item_manager->newItem(m_init_xyz, trigger_distance, this);
@ -321,8 +368,18 @@ TrackObject::TrackObject()
*/
TrackObject::~TrackObject()
{
if(m_node)
if (m_emitter)
{
if (m_lod_emitter_node != NULL)
{
irr_driver->removeNode(m_lod_emitter_node);
m_emitter->unsetNode();
}
delete m_emitter; // this will also delete m_node
}
else if (m_node)
irr_driver->removeNode(m_node);
if(m_mesh)
{
irr_driver->dropAllTextures(m_mesh);
@ -336,7 +393,6 @@ TrackObject::~TrackObject()
delete m_sound->getBuffer();
sfx_manager->deleteSFX(m_sound);
}
} // ~TrackObject
// ----------------------------------------------------------------------------

View File

@ -34,6 +34,7 @@ using namespace irr;
class XMLNode;
class SFXBase;
class ParticleEmitter;
/**
* \ingroup tracks
@ -68,6 +69,8 @@ private:
virtual void OnAnimationEnd(scene::IAnimatedMeshSceneNode* node);
ParticleEmitter* m_emitter;
protected:
/** The irrlicht scene node this object is attached to. */
scene::ISceneNode *m_node;
@ -98,6 +101,8 @@ protected:
std::string m_type;
LODNode* m_lod_emitter_node;
public:
TrackObject(const XMLNode &xml_node);
TrackObject();

View File

@ -56,7 +56,12 @@ void TrackObjectManager::add(const XMLNode &xml_node)
std::string type;
xml_node.get("type", &type);
if(type=="movable")
if (xml_node.getName() == "particle-emitter")
{
m_all_objects.push_back(new ThreeDAnimation(xml_node));
}
else if (type=="movable")
{
if (is_lod)
{