]> git.mxchange.org Git - flightgear.git/commitdiff
Commands to control scenarios / AI-objects.
authorJames Turner <zakalawe@mac.com>
Sat, 16 Mar 2013 16:53:05 +0000 (16:53 +0000)
committerJames Turner <zakalawe@mac.com>
Sat, 16 Mar 2013 16:53:12 +0000 (16:53 +0000)
New commands allow runtime scenario loading and unloading, and AI object creation and removal at runtime.

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

index 3d71f087f544e8131ab96436ac5b17044786beec..bf7fe5c7718e6ea00199a7091d90451fcc169ca6 100644 (file)
@@ -25,6 +25,8 @@
 #include <simgear/math/sg_geodesy.hxx>
 #include <simgear/props/props_io.hxx>
 #include <simgear/structure/exception.hxx>
+#include <simgear/structure/commands.hxx>
+
 #include <boost/mem_fn.hpp>
 #include <boost/foreach.hpp>
 
 #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<FGAIBasePtr> _objects;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
 FGAIManager::FGAIManager() :
     cb_ai_bare(SGPropertyChangeCallback<FGAIManager>(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<std::string> 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<SGPropertyNode*>(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
index 663b3c694645b9109ce327bff0d22292d57eafc1..233b708eefa0e213e0987c39e0ba0535523f3f6f 100644 (file)
@@ -24,6 +24,7 @@
 #define _FG_AIMANAGER_HXX
 
 #include <list>
+#include <map>
 
 #include <simgear/structure/subsystem_mgr.hxx>
 #include <simgear/structure/SGSharedPtr.hxx>
 #include <Traffic/SchedFlight.hxx>
 #include <Traffic/Schedule.hxx>
 
-using std::list;
-
 class FGAIThermal;
 
+typedef SGSharedPtr<FGAIBase> FGAIBasePtr;
+
 class FGAIManager : public SGSubsystem
 {
 
 public:
 
     // A list of pointers to AI objects
-    typedef list <SGSharedPtr<FGAIBase> > ai_list_type;
+    typedef std::list <FGAIBasePtr> 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<FGAIManager> cb_ai_bare;
     SGPropertyChangeCallback<FGAIManager> cb_ai_detailed;
+    
+    class Scenario;
+    typedef std::map<std::string, Scenario*> ScenarioDict;
+    ScenarioDict _scenarios;
 };
 
 #endif  // _FG_AIMANAGER_HXX