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:
parent
a7e4f2a971
commit
4d144dfbf2
2 changed files with 64 additions and 12 deletions
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue