]> git.mxchange.org Git - flightgear.git/commitdiff
Allow scenarios to have load/unload scripts.
authorJames Turner <zakalawe@mac.com>
Thu, 28 Mar 2013 16:50:55 +0000 (16:50 +0000)
committerJames Turner <zakalawe@mac.com>
Thu, 28 Mar 2013 16:50:55 +0000 (16:50 +0000)
This makes it possible for the balloons scenario (for example) to
work correctly with dynamic loading and unloading.

src/AIModel/AIManager.cxx
src/AIModel/AIManager.hxx

index 0771b2f24d655a4fc0574030f7077b8bdca9b537..f2af74acb2a77ded98e56c999719a95a9b531338 100644 (file)
 #include <simgear/props/props_io.hxx>
 #include <simgear/structure/exception.hxx>
 #include <simgear/structure/commands.hxx>
+#include <simgear/structure/SGBinding.hxx>
 
 #include <boost/mem_fn.hpp>
 #include <boost/foreach.hpp>
 
 #include <Main/globals.hxx>
 #include <Airports/airport.hxx>
+#include <Scripting/NasalSys.hxx>
 
 #include "AIManager.hxx"
 #include "AIAircraft.hxx"
@@ -50,8 +52,8 @@
 class FGAIManager::Scenario
 {
 public:
-    Scenario(FGAIManager* man, SGPropertyNode* scenarios) :
-        _manager(man)
+    Scenario(FGAIManager* man, const std::string& nm, SGPropertyNode* scenarios) :
+        _internalName(nm)
     {
         BOOST_FOREACH(SGPropertyNode* scEntry, scenarios->getChildren("entry")) {
             FGAIBasePtr ai = man->addObject(scEntry);
@@ -59,6 +61,21 @@ public:
                 _objects.push_back(ai);
             }
         } // of scenario entry iteration
+        
+        SGPropertyNode* nasalScripts = scenarios->getChild("nasal");
+        if (!nasalScripts) {
+            return;
+        }
+        
+        _unloadScript = nasalScripts->getStringValue("unload");
+        std::string loadScript = nasalScripts->getStringValue("load");
+        if (!loadScript.empty()) {
+            FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal");
+            std::string moduleName = "scenario_" + _internalName;
+            nasalSys->createModule(moduleName.c_str(), moduleName.c_str(),
+                                   loadScript.c_str(), loadScript.size(),
+                                   0);
+        }
     }
     
     ~Scenario()
@@ -66,10 +83,21 @@ public:
         BOOST_FOREACH(FGAIBasePtr ai, _objects) {
             ai->setDie(true);
         }
+        
+        FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal");
+        std::string moduleName = "scenario_" + _internalName;
+        if (!_unloadScript.empty()) {
+            nasalSys->createModule(moduleName.c_str(), moduleName.c_str(),
+                                   _unloadScript.c_str(), _unloadScript.size(),
+                                   0);
+        }
+        
+        nasalSys->deleteModule(moduleName.c_str());
     }
 private:
-    FGAIManager* _manager;
     std::vector<FGAIBasePtr> _objects;
+    std::string _internalName;
+    std::string _unloadScript;
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -275,14 +303,28 @@ FGAIManager::processThermal( double dt, FGAIThermal* thermal ) {
 bool FGAIManager::loadScenarioCommand(const SGPropertyNode* args)
 {
     std::string name = args->getStringValue("name");
-    return loadScenario(name);
+    if (_scenarios.find(name) != _scenarios.end()) {
+        SG_LOG(SG_AI, SG_WARN, "scenario '" << name << "' already loaded");
+        return false;
+    }
+    
+    bool ok = loadScenario(name);
+    if (ok) {
+        // create /sim/ai node for consistency
+        int index = 0;
+        for (; root->hasChild("scenario", index); ++index) {}
+        
+        SGPropertyNode* scenarioNode = root->getChild("scenario", index, true);
+        scenarioNode->setStringValue(name);
+    }
+    
+    return ok;
 }
 
 bool FGAIManager::unloadScenarioCommand(const SGPropertyNode* args)
 {
     std::string name = args->getStringValue("name");
-    unloadScenario(name);
-    return true;
+    return unloadScenario(name);
 }
 
 bool FGAIManager::addObjectCommand(const SGPropertyNode* definition)
@@ -351,22 +393,32 @@ FGAIManager::loadScenario( const string &filename )
         return false;
     }
     
-    _scenarios[filename] = new Scenario(this, scNode);
+    _scenarios[filename] = new Scenario(this, filename, scNode);
     return true;
 }
 
 
-void
+bool
 FGAIManager::unloadScenario( const string &filename)
 {
     ScenarioDict::iterator it = _scenarios.find(filename);
     if (it == _scenarios.end()) {
         SG_LOG(SG_AI, SG_WARN, "unload scenario: not found:" << filename);
-        return;
+        return false;
+    }
+    
+// remove /sim/ai node
+    unsigned int index = 0;
+    for (SGPropertyNode* n = NULL; (n = root->getChild("scenario", index)) != NULL; ++index) {
+        if (n->getStringValue() == filename) {
+            root->removeChild("scenario", index);
+            break;
+        }
     }
     
     delete it->second;
     _scenarios.erase(it);
+    return true;
 }
 
 SGPropertyNode_ptr
index 98b461cb2e7dff262ed279dd8d566f9040862814..383eba6485e6bdd1ff022044b99c8be979e3f1cd 100644 (file)
@@ -81,11 +81,11 @@ public:
 
     int getNumAiObjects(void) const;
 
-    bool loadScenario( const string &filename );
+    bool loadScenario( const std::string &filename );
 
     static SGPropertyNode_ptr loadScenarioFile(const std::string& filename);
 
-    static bool getStartPosition(const string& id, const string& pid,
+    static bool getStartPosition(const std::string& id, const std::string& pid,
         SGGeod& geodPos, double& hdng, SGVec3d& uvw);
 
     FGAIBasePtr addObject(const SGPropertyNode* definition);
@@ -100,7 +100,7 @@ private:
     bool addObjectCommand(const SGPropertyNode* definition);
     
     bool removeObject(const SGPropertyNode* args);
-    void unloadScenario( const string &filename );
+    bool unloadScenario( const std::string &filename );
     
     SGPropertyNode_ptr root;
     SGPropertyNode_ptr enabled;