#include <simgear/misc/sg_path.hxx>
#include <simgear/scene/model/modellib.hxx>
#include <simgear/scene/util/SGNodeMasks.hxx>
+#include <simgear/sound/soundmgr_openal.hxx>
#include <simgear/debug/logstream.hxx>
#include <simgear/props/props.hxx>
_refID( _newAIModelID() ),
_otype(ot),
_initialized(false),
- _aimodel(0),
- _fxpath(""),
+ _modeldata(0),
_fx(0)
{
model_removed->setStringValue(props->getPath());
}
- delete fp;
- fp = 0;
+ if (_fx && _refID != 0 && _refID != 1) {
+ SGSoundMgr *smgr = globals->get_soundmgr();
+ stringstream name;
+ name << "aifx:";
+ name << _refID;
+ smgr->remove(name.str());
+ }
-// delete _fx;
-// _fx = 0;
+ if (fp)
+ delete fp;
+ fp = 0;
}
/** Cleanly remove the model
void
FGAIBase::removeModel()
{
+ if (!_model.valid())
+ return;
+
FGScenery* pSceneryManager = globals->get_scenery();
if (pSceneryManager)
{
_fx->set_orientation( orient );
SGVec3d velocity;
- velocity = SGVec3d( speed_north_deg_sec, speed_east_deg_sec, pitch*speed );
+ velocity = SGVec3d( speed_north_deg_sec, speed_east_deg_sec,
+ pitch*speed );
_fx->set_velocity( velocity );
}
- else if (_aimodel)
+ else if ((_modeldata)&&(_modeldata->needInitilization()))
{
- string fxpath = _aimodel->get_sound_path();
- if (fxpath != "")
- {
- _fxpath = fxpath;
- props->setStringValue("sim/sound/path", _fxpath.c_str());
+ // process deferred nasal initialization,
+ // which must be done in main thread
+ _modeldata->init();
- // initialize the sound configuration
- SGSoundMgr *smgr = globals->get_soundmgr();
- _fx = new FGFX(smgr, "aifx:"+_name+"-"+_callsign, props);
- _fx->init();
+ // sound initialization
+ if (fgGetBool("/sim/sound/aimodels/enabled",false))
+ {
+ string fxpath = _modeldata->get_sound_path();
+ if (fxpath != "")
+ {
+ props->setStringValue("sim/sound/path", fxpath.c_str());
+
+ // initialize the sound configuration
+ SGSoundMgr *smgr = globals->get_soundmgr();
+ stringstream name;
+ name << "aifx:";
+ name << _refID;
+ _fx = new FGFX(smgr, name.str(), props);
+ _fx->init();
+ }
}
}
}
}
-bool FGAIBase::init(bool search_in_AI_path) {
-
+bool FGAIBase::init(bool search_in_AI_path)
+{
+ if (_model.valid())
+ {
+ SG_LOG(SG_AI, SG_ALERT, "AIBase: Cannot initialize a model multiple times! " << model_path);
+ return false;
+ }
+
string f;
if(search_in_AI_path)
{
else
_installed = true;
- _aimodel = new FGAIModelData(props);
- osg::Node * mdl = SGModelLib::loadDeferredModel(f, props, _aimodel);
-
- if (_model.valid())
- {
- // reinit, dump the old model
- removeModel();
- }
+ _modeldata = new FGAIModelData(props);
+ osg::Node * mdl = SGModelLib::loadDeferredModel(f, props, _modeldata);
_model = new osg::LOD;
_model->setName("AI-model range animation node");
props->setBoolValue("/sim/controls/radar/", true);
+ // drop reference to sound effects now
+ _fx = 0;
}
double FGAIBase::UpdateRadar(FGAIManager* manager) {
}
+FGAIModelData::FGAIModelData(SGPropertyNode *root)
+ : _nasal( new FGNasalModelData(root) ),
+ _ready(false),
+ _initialized(false)
+{
+}
+
+FGAIModelData::~FGAIModelData()
+{
+ delete _nasal;
+}
+
void FGAIModelData::modelLoaded(const string& path, SGPropertyNode *prop, osg::Node *n)
{
- const char* fxpath = prop->getStringValue("sound/path");
- if (fxpath) {
- string sound_path = string(fxpath);
- if (sound_path != "") {
- _path = "/AI/"+sound_path;
- }
- }
- _nasal->modelLoaded(path, prop, n);
+ // WARNING: All this is called in a separate OSG thread! Only use thread-safe stuff
+ // here that is fine to be run concurrently with stuff in the main loop!
+ if (_ready)
+ return;
+ _fxpath = _prop->getStringValue("sound/path");
+ _prop = prop;
+ _path = path;
+ _ready = true;
+}
+
+// do Nasal initialization (must be called in the main loop)
+void FGAIModelData::init()
+{
+ // call FGNasalSys to create context and run hooks (not-thread safe!)
+ _nasal->modelLoaded(_path, _prop, 0);
+ _prop = 0;
+ _initialized = true;
}