_refID( _newAIModelID() ),
_otype(ot),
_initialized(false),
- _aimodel(0),
- _fxpath(""),
+ _modeldata(0),
_fx(0)
{
pitch*speed );
_fx->set_velocity( velocity );
}
- else if ((_aimodel)&&(fgGetBool("/sim/sound/aimodels/enabled",false)))
+ else if ((_modeldata)&&(_modeldata->needInitilization()))
{
- string fxpath = _aimodel->get_sound_path();
- if (fxpath != "")
+ // process deferred nasal initialization,
+ // which must be done in main thread
+ _modeldata->init();
+
+ // sound initialization
+ if (fgGetBool("/sim/sound/aimodels/enabled",false))
{
- _fxpath = 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();
+ 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();
+ }
}
}
}
else
_installed = true;
- _aimodel = new FGAIModelData(props);
- osg::Node * mdl = SGModelLib::loadDeferredModel(f, props, _aimodel);
+ _modeldata = new FGAIModelData(props);
+ osg::Node * mdl = SGModelLib::loadDeferredModel(f, props, _modeldata);
_model = new osg::LOD;
_model->setName("AI-model range animation node");
FGAIModelData::FGAIModelData(SGPropertyNode *root)
: _nasal( new FGNasalModelData(root) ),
- _path("")
+ _ready(false),
+ _initialized(false)
{
}
void FGAIModelData::modelLoaded(const string& path, SGPropertyNode *prop, osg::Node *n)
{
- const char* fxpath = prop->getStringValue("sound/path");
- if (fxpath) {
- _path = string(fxpath);
- }
- _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;
}
#define _FG_AIBASE_HXX
#include <string>
-#include <list>
#include <simgear/constants.h>
#include <simgear/math/SGMath.hxx>
using std::string;
-using std::list;
class SGMaterial;
class FGAIManager;
bool _initialized;
osg::ref_ptr<osg::LOD> _model; //The 3D model LOD object
- osg::ref_ptr<FGAIModelData> _aimodel;
+ osg::ref_ptr<FGAIModelData> _modeldata;
- string _fxpath;
SGSharedPtr<FGFX> _fx;
public:
public:
FGAIModelData(SGPropertyNode *root = 0);
~FGAIModelData();
+
+ /** osg callback, thread-safe */
void modelLoaded(const string& path, SGPropertyNode *prop, osg::Node *n);
- inline string& get_sound_path() { return _path; };
+
+ /** init hook to be called after model is loaded.
+ * Not thread-safe. Call from main thread only. */
+ void init(void);
+
+ bool needInitilization(void) { return _ready && !_initialized;}
+ bool isInitialized(void) { return _initialized;}
+ inline std::string& get_sound_path() { return _fxpath;}
private:
FGNasalModelData *_nasal;
- string _path;
+ SGPropertyNode_ptr _prop;
+ std::string _path, _fxpath;
+ bool _ready;
+ bool _initialized;
};
#endif // _FG_AIBASE_HXX