1
0
Fork 0

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.
This commit is contained in:
James Turner 2013-03-28 16:50:55 +00:00
parent a7e4f2a971
commit 4d144dfbf2
2 changed files with 64 additions and 12 deletions

View file

@ -26,12 +26,14 @@
#include <simgear/props/props_io.hxx> #include <simgear/props/props_io.hxx>
#include <simgear/structure/exception.hxx> #include <simgear/structure/exception.hxx>
#include <simgear/structure/commands.hxx> #include <simgear/structure/commands.hxx>
#include <simgear/structure/SGBinding.hxx>
#include <boost/mem_fn.hpp> #include <boost/mem_fn.hpp>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <Main/globals.hxx> #include <Main/globals.hxx>
#include <Airports/airport.hxx> #include <Airports/airport.hxx>
#include <Scripting/NasalSys.hxx>
#include "AIManager.hxx" #include "AIManager.hxx"
#include "AIAircraft.hxx" #include "AIAircraft.hxx"
@ -50,8 +52,8 @@
class FGAIManager::Scenario class FGAIManager::Scenario
{ {
public: public:
Scenario(FGAIManager* man, SGPropertyNode* scenarios) : Scenario(FGAIManager* man, const std::string& nm, SGPropertyNode* scenarios) :
_manager(man) _internalName(nm)
{ {
BOOST_FOREACH(SGPropertyNode* scEntry, scenarios->getChildren("entry")) { BOOST_FOREACH(SGPropertyNode* scEntry, scenarios->getChildren("entry")) {
FGAIBasePtr ai = man->addObject(scEntry); FGAIBasePtr ai = man->addObject(scEntry);
@ -59,6 +61,21 @@ public:
_objects.push_back(ai); _objects.push_back(ai);
} }
} // of scenario entry iteration } // 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() ~Scenario()
@ -66,10 +83,21 @@ public:
BOOST_FOREACH(FGAIBasePtr ai, _objects) { BOOST_FOREACH(FGAIBasePtr ai, _objects) {
ai->setDie(true); 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: private:
FGAIManager* _manager;
std::vector<FGAIBasePtr> _objects; 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) bool FGAIManager::loadScenarioCommand(const SGPropertyNode* args)
{ {
std::string name = args->getStringValue("name"); 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) bool FGAIManager::unloadScenarioCommand(const SGPropertyNode* args)
{ {
std::string name = args->getStringValue("name"); std::string name = args->getStringValue("name");
unloadScenario(name); return unloadScenario(name);
return true;
} }
bool FGAIManager::addObjectCommand(const SGPropertyNode* definition) bool FGAIManager::addObjectCommand(const SGPropertyNode* definition)
@ -351,22 +393,32 @@ FGAIManager::loadScenario( const string &filename )
return false; return false;
} }
_scenarios[filename] = new Scenario(this, scNode); _scenarios[filename] = new Scenario(this, filename, scNode);
return true; return true;
} }
void bool
FGAIManager::unloadScenario( const string &filename) FGAIManager::unloadScenario( const string &filename)
{ {
ScenarioDict::iterator it = _scenarios.find(filename); ScenarioDict::iterator it = _scenarios.find(filename);
if (it == _scenarios.end()) { if (it == _scenarios.end()) {
SG_LOG(SG_AI, SG_WARN, "unload scenario: not found:" << filename); 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; delete it->second;
_scenarios.erase(it); _scenarios.erase(it);
return true;
} }
SGPropertyNode_ptr SGPropertyNode_ptr

View file

@ -81,11 +81,11 @@ public:
int getNumAiObjects(void) const; int getNumAiObjects(void) const;
bool loadScenario( const string &filename ); bool loadScenario( const std::string &filename );
static SGPropertyNode_ptr loadScenarioFile(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); SGGeod& geodPos, double& hdng, SGVec3d& uvw);
FGAIBasePtr addObject(const SGPropertyNode* definition); FGAIBasePtr addObject(const SGPropertyNode* definition);
@ -100,7 +100,7 @@ private:
bool addObjectCommand(const SGPropertyNode* definition); bool addObjectCommand(const SGPropertyNode* definition);
bool removeObject(const SGPropertyNode* args); bool removeObject(const SGPropertyNode* args);
void unloadScenario( const string &filename ); bool unloadScenario( const std::string &filename );
SGPropertyNode_ptr root; SGPropertyNode_ptr root;
SGPropertyNode_ptr enabled; SGPropertyNode_ptr enabled;