]> git.mxchange.org Git - flightgear.git/blobdiff - src/AIModel/AIBase.cxx
NavDisplay: fix update lag when switching range or centre.
[flightgear.git] / src / AIModel / AIBase.cxx
index d8c87f90fe2202f46433ff032ccf5265f57faaab..a9d64e341683d619fa4cc78132faf1cb9c0720c3 100644 (file)
@@ -24,6 +24,8 @@
 #  include <config.h>
 #endif
 
+#include <string.h>
+
 #include <simgear/compiler.h>
 
 #include <string>
@@ -36,6 +38,7 @@
 #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>
 
@@ -72,6 +75,7 @@ FGAIBase::FGAIBase(object_type ot, bool enableHot) :
     _refID( _newAIModelID() ),
     _otype(ot),
     _initialized(false),
+    _modeldata(0),
     _fx(0)
 
 {
@@ -139,10 +143,17 @@ FGAIBase::~FGAIBase() {
         if (parent)
             model_removed->setStringValue(props->getPath());
     }
-    delete _fx;
-    _fx = 0;
 
-    delete fp;
+    if (_fx && _refID != 0 && _refID !=  1) {
+        SGSoundMgr *smgr = globals->get_soundmgr();
+        stringstream name; 
+        name <<  "aifx:";
+        name << _refID;
+        smgr->remove(name.str());
+    }
+
+    if (fp)
+        delete fp;
     fp = 0;
 }
 
@@ -152,6 +163,9 @@ FGAIBase::~FGAIBase() {
 void
 FGAIBase::removeModel()
 {
+    if (!_model.valid())
+        return;
+
     FGScenery* pSceneryManager = globals->get_scenery();
     if (pSceneryManager)
     {
@@ -213,9 +227,34 @@ void FGAIBase::update(double dt) {
         _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 ((_modeldata)&&(_modeldata->needInitilization()))
+    {
+        // process deferred nasal initialization,
+        // which must be done in main thread
+        _modeldata->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();
+            }
+        }
+    }
 }
 
 /** update LOD properties of the model */
@@ -258,8 +297,14 @@ void FGAIBase::Transform() {
 
 }
 
-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)
     {
@@ -285,13 +330,8 @@ bool FGAIBase::init(bool search_in_AI_path) {
     else
         _installed = true;
 
-    osg::Node * mdl = SGModelLib::loadDeferredModel(f, props, new FGNasalModelData(props));
-
-    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");
@@ -314,17 +354,6 @@ bool FGAIBase::init(bool search_in_AI_path) {
 
         // Get the sound-path tag from the configuration file and store it
         // in the property tree.
-        string fxpath = props->getStringValue("/sim/sound/path");
-        if ( !fxpath.empty() )
-        {
-            props->setStringValue("sim/sound/path", fxpath.c_str());
-
-            // initialize the sound configuration
-            SGSoundMgr *smgr = globals->get_soundmgr();
-            _fx = new FGFX(smgr, "aifx:"+f, props);
-            _fx->init();
-        }
-
         _initialized = true;
 
     } else if (!model_path.empty()) {
@@ -473,6 +502,8 @@ void FGAIBase::unbind() {
 
     props->setBoolValue("/sim/controls/radar/", true);
 
+    // drop reference to sound effects now
+    _fx = 0;
 }
 
 double FGAIBase::UpdateRadar(FGAIManager* manager) {
@@ -884,3 +915,36 @@ int FGAIBase::_newAIModelID() {
     return id;
 }
 
+
+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)
+{
+    // 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;
+}