Fix a memory leak, and brownian animation, if not motion. I have 2 new files : personality.[ch]xx . They store the personality data that would be deleted when the object is destroyed, instead of staying in the animation maps. I also manage the current animation step better and the towers are not flashing randomly now. Makefile.am is updated.
108 lines
3.3 KiB
C++
108 lines
3.3 KiB
C++
// modellib.cxx - implement an SSG model library.
|
|
|
|
#include <simgear/compiler.h>
|
|
#include <simgear/props/props.hxx>
|
|
|
|
#include "model.hxx"
|
|
#include "animation.hxx"
|
|
#include "personality.hxx"
|
|
|
|
#include "modellib.hxx"
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// Implementation of SGModelLib.
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
SGModelLib::SGModelLib ()
|
|
{
|
|
}
|
|
|
|
SGModelLib::~SGModelLib ()
|
|
{
|
|
map<string, ssgBase *>::iterator it = _table.begin();
|
|
while (it != _table.end()) {
|
|
it->second->deRef();
|
|
_table.erase(it);
|
|
}
|
|
}
|
|
|
|
void
|
|
SGModelLib::flush1()
|
|
{
|
|
// This routine is disabled because I believe I see multiple
|
|
// problems with it.
|
|
//
|
|
// 1. It blindly deletes all managed models that aren't used
|
|
// elsewhere. Is this what we really want???? In the one
|
|
// FlightGear case that calls this method, this clearly is not the
|
|
// intention. I believe it makes more sense to simply leave items
|
|
// in the lbrary, even if they are not currently used, they will be
|
|
// there already when/if we want to use them later.
|
|
//
|
|
// 2. This routine only does a deRef() on the model. This doesn't actually
|
|
// delete the ssg tree so there is a memory leak.
|
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT,
|
|
"WARNGING: a disabled/broken routine has been called. This should be fixed!" );
|
|
|
|
return;
|
|
|
|
map<string, ssgBase *>::iterator it = _table.begin();
|
|
while (it != _table.end()) {
|
|
ssgBase *item = it->second;
|
|
// If there is only one reference, it's
|
|
// ours; no one else is using the item.
|
|
if (item->getRef() == 1) {
|
|
item->deRef();
|
|
_table.erase(it);
|
|
}
|
|
it++;
|
|
}
|
|
}
|
|
|
|
static int
|
|
personality_pretrav_callback(ssgEntity * entity, int mask)
|
|
{
|
|
((SGPersonalityBranch *)entity)->_old_current = SGAnimation::current_object;
|
|
SGAnimation::current_object = (SGPersonalityBranch *)entity;
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
personality_posttrav_callback(ssgEntity * entity, int mask)
|
|
{
|
|
SGAnimation::current_object = ((SGPersonalityBranch *)entity)->_old_current;
|
|
((SGPersonalityBranch *)entity)->_old_current = 0;
|
|
return 1;
|
|
}
|
|
|
|
ssgEntity *
|
|
SGModelLib::load_model( const string &fg_root,
|
|
const string &path,
|
|
SGPropertyNode *prop_root,
|
|
double sim_time_sec )
|
|
{
|
|
ssgBranch *personality_branch = new SGPersonalityBranch;
|
|
personality_branch->setTravCallback(SSG_CALLBACK_PRETRAV, personality_pretrav_callback);
|
|
personality_branch->setTravCallback(SSG_CALLBACK_POSTTRAV, personality_posttrav_callback);
|
|
|
|
// FIXME: normalize path to
|
|
// avoid duplicates.
|
|
map<string, ssgBase *>::iterator it = _table.find(path);
|
|
if (it == _table.end()) {
|
|
ssgEntity *model = sgLoad3DModel( fg_root, path, prop_root,
|
|
sim_time_sec );
|
|
model->ref();
|
|
_table[path] = model; // add one reference to keep it around
|
|
personality_branch->addKid( model );
|
|
} else {
|
|
personality_branch->addKid( (ssgEntity *)it->second );
|
|
}
|
|
return personality_branch;
|
|
}
|
|
|
|
|
|
// end of modellib.cxx
|