From 4d144dfbf2d85b62b4d222102f39f907f3f69bc9 Mon Sep 17 00:00:00 2001 From: James Turner Date: Thu, 28 Mar 2013 16:50:55 +0000 Subject: [PATCH] Allow scenarios to have load/unload scripts. This makes it possible for the balloons scenario (for example) to work correctly with dynamic loading and unloading. --- src/AIModel/AIManager.cxx | 70 ++++++++++++++++++++++++++++++++++----- src/AIModel/AIManager.hxx | 6 ++-- 2 files changed, 64 insertions(+), 12 deletions(-) diff --git a/src/AIModel/AIManager.cxx b/src/AIModel/AIManager.cxx index 0771b2f24..f2af74acb 100644 --- a/src/AIModel/AIManager.cxx +++ b/src/AIModel/AIManager.cxx @@ -26,12 +26,14 @@ #include #include #include +#include #include #include #include
#include +#include #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 _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 diff --git a/src/AIModel/AIManager.hxx b/src/AIModel/AIManager.hxx index 98b461cb2..383eba648 100644 --- a/src/AIModel/AIManager.hxx +++ b/src/AIModel/AIManager.hxx @@ -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;