From 96a40fe70ce33603a6e273ecbd344c30151a1c67 Mon Sep 17 00:00:00 2001 From: James Turner Date: Sat, 16 Mar 2013 16:53:05 +0000 Subject: [PATCH] Commands to control scenarios / AI-objects. New commands allow runtime scenario loading and unloading, and AI object creation and removal at runtime. --- src/AIModel/AIManager.cxx | 190 ++++++++++++++++++++++++-------------- src/AIModel/AIManager.hxx | 32 ++++--- 2 files changed, 141 insertions(+), 81 deletions(-) diff --git a/src/AIModel/AIManager.cxx b/src/AIModel/AIManager.cxx index 3d71f087f..bf7fe5c77 100644 --- a/src/AIModel/AIManager.cxx +++ b/src/AIModel/AIManager.cxx @@ -25,6 +25,8 @@ #include #include #include +#include + #include #include @@ -45,6 +47,33 @@ #include "AIGroundVehicle.hxx" #include "AIEscort.hxx" +class FGAIManager::Scenario +{ +public: + Scenario(FGAIManager* man, SGPropertyNode* scenarios) : + _manager(man) + { + BOOST_FOREACH(SGPropertyNode* scEntry, scenarios->getChildren("entry")) { + FGAIBasePtr ai = man->addObject(scEntry); + if (ai) { + _objects.push_back(ai); + } + } // of scenario entry iteration + } + + ~Scenario() + { + BOOST_FOREACH(FGAIBasePtr ai, _objects) { + ai->setDie(true); + } + } +private: + FGAIManager* _manager; + std::vector _objects; +}; + +/////////////////////////////////////////////////////////////////////////////// + FGAIManager::FGAIManager() : cb_ai_bare(SGPropertyChangeCallback(this,&FGAIManager::updateLOD, fgGetNode("/sim/rendering/static-lod/ai-bare", true))), @@ -72,6 +101,9 @@ FGAIManager::init() { user_altitude_agl_node = fgGetNode("/position/altitude-agl-ft", true); user_yaw_node = fgGetNode("/orientation/side-slip-deg", true); user_speed_node = fgGetNode("/velocities/uBody-fps", true); + + globals->get_commands()->addCommand("load-scenario", this, &FGAIManager::loadScenarioCommand); + globals->get_commands()->addCommand("unload-scenario", this, &FGAIManager::unloadScenarioCommand); } void @@ -86,20 +118,18 @@ FGAIManager::postinit() { enabled->setBoolValue(true); // process all scenarios - std::set loadedScenarios; BOOST_FOREACH(SGPropertyNode* n, root->getChildren("scenario")) { const string& name = n->getStringValue(); if (name.empty()) continue; - if (loadedScenarios.find(name) != loadedScenarios.end()) { + if (_scenarios.find(name) != _scenarios.end()) { SG_LOG(SG_AI, SG_WARN, "won't load scenario '" << name << "' twice"); continue; } SG_LOG(SG_AI, SG_INFO, "loading scenario '" << name << '\''); loadScenario(name); - loadedScenarios.insert(name); } } @@ -242,81 +272,101 @@ FGAIManager::processThermal( double dt, FGAIThermal* thermal ) { } +bool FGAIManager::loadScenarioCommand(const SGPropertyNode* args) +{ + std::string name = args->getStringValue("name"); + return loadScenario(name); +} +bool FGAIManager::unloadScenarioCommand(const SGPropertyNode* args) +{ + std::string name = args->getStringValue("name"); + unloadScenario(name); + return true; +} -void -FGAIManager::loadScenario( const string &filename ) { +bool FGAIManager::addObjectCommand(const SGPropertyNode* definition) +{ + addObject(definition); + return true; +} - SGPropertyNode_ptr scenarioTop = loadScenarioFile(filename); +FGAIBasePtr FGAIManager::addObject(const SGPropertyNode* definition) +{ + const std::string& type = definition->getStringValue("type", "aircraft"); + + FGAIBase* ai = NULL; + if (type == "tanker") { // refueling scenarios + ai = new FGAITanker; + } else if (type == "wingman") { + ai = new FGAIWingman; + } else if (type == "aircraft") { + ai = new FGAIAircraft; + } else if (type == "ship") { + ai = new FGAIShip; + } else if (type == "carrier") { + ai = new FGAICarrier; + } else if (type == "groundvehicle") { + ai = new FGAIGroundVehicle; + } else if (type == "escort") { + ai = new FGAIEscort; + } else if (type == "thunderstorm") { + ai = new FGAIStorm; + } else if (type == "thermal") { + ai = new FGAIThermal; + } else if (type == "ballistic") { + ai = new FGAIBallistic; + } else if (type == "static") { + ai = new FGAIStatic; + } - if (!scenarioTop) - return; + ai->readFromScenario(const_cast(definition)); + attach(ai); + return ai; +} - SGPropertyNode* scenarios = scenarioTop->getChild("scenario"); +bool FGAIManager::removeObject(const SGPropertyNode* args) +{ + int id = args->getIntValue("id"); + BOOST_FOREACH(FGAIBase* ai, get_ai_list()) { + if (ai->getID() == id) { + ai->setDie(true); + break; + } + } + + return false; +} - if (!scenarios) - return; +bool +FGAIManager::loadScenario( const string &filename ) +{ + SGPropertyNode_ptr file = loadScenarioFile(filename); + if (!file) { + return false; + } + + SGPropertyNode_ptr scNode = file->getChild("scenario"); + if (!scNode) { + return false; + } + + _scenarios[filename] = new Scenario(this, scNode); + return true; +} - BOOST_FOREACH(SGPropertyNode* scEntry, scenarios->getChildren("entry")) { - const std::string& type = scEntry->getStringValue("type", "aircraft"); - - if (type == "tanker") { // refueling scenarios - FGAITanker* tanker = new FGAITanker; - tanker->readFromScenario(scEntry); - attach(tanker); - - } else if (type == "wingman") { - FGAIWingman* wingman = new FGAIWingman; - wingman->readFromScenario(scEntry); - attach(wingman); - - } else if (type == "aircraft") { - FGAIAircraft* aircraft = new FGAIAircraft; - aircraft->readFromScenario(scEntry); - attach(aircraft); - - } else if (type == "ship") { - FGAIShip* ship = new FGAIShip; - ship->readFromScenario(scEntry); - attach(ship); - - } else if (type == "carrier") { - FGAICarrier* carrier = new FGAICarrier; - carrier->readFromScenario(scEntry); - attach(carrier); - - } else if (type == "groundvehicle") { - FGAIGroundVehicle* groundvehicle = new FGAIGroundVehicle; - groundvehicle->readFromScenario(scEntry); - attach(groundvehicle); - - } else if (type == "escort") { - FGAIEscort* escort = new FGAIEscort; - escort->readFromScenario(scEntry); - attach(escort); - - } else if (type == "thunderstorm") { - FGAIStorm* storm = new FGAIStorm; - storm->readFromScenario(scEntry); - attach(storm); - - } else if (type == "thermal") { - FGAIThermal* thermal = new FGAIThermal; - thermal->readFromScenario(scEntry); - attach(thermal); - - } else if (type == "ballistic") { - FGAIBallistic* ballistic = new FGAIBallistic; - ballistic->readFromScenario(scEntry); - attach(ballistic); - - } else if (type == "static") { - FGAIStatic* aistatic = new FGAIStatic; - aistatic->readFromScenario(scEntry); - attach(aistatic); - } - } // of scenario entry iteration +void +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; + } + + delete it->second; + _scenarios.erase(it); } SGPropertyNode_ptr diff --git a/src/AIModel/AIManager.hxx b/src/AIModel/AIManager.hxx index 663b3c694..233b708ee 100644 --- a/src/AIModel/AIManager.hxx +++ b/src/AIModel/AIManager.hxx @@ -24,6 +24,7 @@ #define _FG_AIMANAGER_HXX #include +#include #include #include @@ -37,24 +38,21 @@ #include #include -using std::list; - class FGAIThermal; +typedef SGSharedPtr FGAIBasePtr; + class FGAIManager : public SGSubsystem { public: // A list of pointers to AI objects - typedef list > ai_list_type; + typedef std::list ai_list_type; typedef ai_list_type::iterator ai_list_iterator; typedef ai_list_type::const_iterator ai_list_const_iterator; - ai_list_type ai_list; - - inline const ai_list_type& get_ai_list() const { - SG_LOG(SG_AI, SG_DEBUG, "AI Manager: AI model return list size " << ai_list.size()); + const ai_list_type& get_ai_list() const { return ai_list; } @@ -72,9 +70,6 @@ public: const FGAIBase *calcCollision(double alt, double lat, double lon, double fuse_range); - // inline double get_user_latitude() const { return user_latitude; } - // inline double get_user_longitude() const { return user_longitude; } - // inline double get_user_altitude() const { return user_altitude; } inline double get_user_heading() const { return user_heading; } inline double get_user_pitch() const { return user_pitch; } inline double get_user_yaw() const { return user_yaw; } @@ -86,18 +81,27 @@ public: int getNumAiObjects(void) const; - void loadScenario( const string &filename ); + bool loadScenario( const string &filename ); static SGPropertyNode_ptr loadScenarioFile(const std::string& filename); static bool getStartPosition(const string& id, const string& pid, SGGeod& geodPos, double& hdng, SGVec3d& uvw); + FGAIBasePtr addObject(const SGPropertyNode* definition); + private: void removeDeadItem(FGAIBase* base); double calcRange(const SGVec3d& aCartPos, FGAIBase* aObject) const; + bool loadScenarioCommand(const SGPropertyNode* args); + bool unloadScenarioCommand(const SGPropertyNode* args); + bool addObjectCommand(const SGPropertyNode* definition); + + bool removeObject(const SGPropertyNode* args); + void unloadScenario( const string &filename ); + SGPropertyNode_ptr root; SGPropertyNode_ptr enabled; SGPropertyNode_ptr thermal_lift_node; @@ -108,6 +112,8 @@ private: SGPropertyNode_ptr wind_from_north_node; + ai_list_type ai_list; + double user_altitude_agl; double user_heading; double user_pitch; @@ -127,6 +133,10 @@ private: SGPropertyChangeCallback cb_ai_bare; SGPropertyChangeCallback cb_ai_detailed; + + class Scenario; + typedef std::map ScenarioDict; + ScenarioDict _scenarios; }; #endif // _FG_AIMANAGER_HXX -- 2.39.5