]> git.mxchange.org Git - flightgear.git/commitdiff
Aircraft switching command and formal support.
authorJames Turner <zakalawe@mac.com>
Wed, 11 Jun 2014 17:19:41 +0000 (18:19 +0100)
committerJames Turner <zakalawe@mac.com>
Thu, 12 Jun 2014 07:17:05 +0000 (08:17 +0100)
- /sim/aircraft can be set to package ID, including qualified
package ID. If not matching package is found, falls back to
traditional search of fg-aircraft for -set.xml files

src/Main/fg_commands.cxx
src/Main/fg_init.cxx
src/Main/globals.cxx
src/Main/globals.hxx
src/Main/options.cxx

index 9daf6db74dd1a5a4958f0da593e5cad9b5e39b53..175a9dd86b064048157b321de77efbe7abca93b7 100644 (file)
@@ -209,6 +209,19 @@ do_reset (const SGPropertyNode * arg)
     return true;
 }
 
+
+/**
+ * Change aircraft
+ */
+static bool
+do_switch_aircraft (const SGPropertyNode * arg)
+{
+    fgSetString("/sim/aircraft", arg->getStringValue("aircraft"));
+    // start a reset
+    fgResetIdleState();
+    return true;
+}
+
 /**
  */
 static bool
@@ -1462,6 +1475,7 @@ static struct {
     { "exit", do_exit },
     { "reset", do_reset },
     { "reposition", do_reposition },
+    { "switch-aircraft", do_switch_aircraft },
     { "pause", do_pause },
     { "load", do_load },
     { "save", do_save },
index 0f90d8e6d524584c07b94af036eefd45143be5cb..20c2a210faf83974ba3bf9e6d529dbcafd8449bc 100644 (file)
@@ -70,6 +70,9 @@
 #include <simgear/scene/tsync/terrasync.hxx>
 
 #include <simgear/package/Root.hxx>
+#include <simgear/package/Package.hxx>
+#include <simgear/package/Install.hxx>
+#include <simgear/package/Catalog.hxx>
 
 #include <Aircraft/controls.hxx>
 #include <Aircraft/replay.hxx>
@@ -483,37 +486,71 @@ int fgInitConfig ( int argc, char **argv, bool reinit )
     return flightgear::FG_OPTIONS_OK;
 }
 
+static void initAircraftDirsNasalSecurity()
+{
+    SGPropertyNode* sim = fgGetNode("/sim", true);
+    sim->removeChildren("fg-aircraft");
+    string_list::const_iterator it;
+    int index = 0;
+    for (it = globals->get_aircraft_paths().begin();
+         it != globals->get_aircraft_paths().end(); ++it, ++index)
+    {
+        SGPropertyNode* n = sim->getChild("fg-aircraft", index, true);
+        n->setStringValue(*it);
+        n->setAttribute(SGPropertyNode::WRITE, false);
+    }
+}
+
 int fgInitAircraft(bool reinit)
 {
-    // FIXME - use Documents/FlightGear/Aircraft
-    SGPath userAircraftDir = globals->get_fg_home();
-    userAircraftDir.append("Aircraft");
-  
-    SGSharedPtr<Root> pkgRoot(new Root(userAircraftDir, FLIGHTGEAR_VERSION));
-    // set the http client later (too early in startup right now)
-    globals->setPackageRoot(pkgRoot);
-  
-    // Scan user config files and command line for a specified aircraft.
-    if (reinit) {
-        SGPropertyNode* sim = fgGetNode("/sim", true);
-        sim->removeChildren("fg-aircraft");
-        // after reset, add aircraft dirs to props, needed for Nasal IO rules
-        string_list::const_iterator it;
-        int index = 0;
-        for (it = globals->get_aircraft_paths().begin();
-             it != globals->get_aircraft_paths().end(); ++it, ++index)
-        {
-            SGPropertyNode* n = sim->getChild("fg-aircraft", index, true);
-            n->setStringValue(*it);
-            n->setAttribute(SGPropertyNode::WRITE, false);
-        }
-        
-        SGPropertyNode* aircraftProp = fgGetNode("/sim/aircraft", true);
-        aircraftProp->setAttribute(SGPropertyNode::PRESERVE, true);
-    } else {
+    if (!reinit) {
+        // FIXME - use Documents/FlightGear/Aircraft
+        SGPath userAircraftDir = globals->get_fg_home();
+        userAircraftDir.append("Aircraft");
+
+        SGSharedPtr<Root> pkgRoot(new Root(userAircraftDir, FLIGHTGEAR_VERSION));
+        // set the http client later (too early in startup right now)
+        globals->setPackageRoot(pkgRoot);
+    }
+
+    SGSharedPtr<Root> pkgRoot(globals->packageRoot());
+    SGPropertyNode* aircraftProp = fgGetNode("/sim/aircraft", true);
+    aircraftProp->setAttribute(SGPropertyNode::PRESERVE, true);
+
+    if (!reinit) {
         flightgear::Options::sharedInstance()->initAircraft();
     }
-    
+
+    PackageRef acftPackage = pkgRoot->getPackageById(aircraftProp->getStringValue());
+    if (acftPackage) {
+        if (!acftPackage->isInstalled()) {
+            // naturally the better option would be to on-demand install it!
+            flightgear::fatalMessageBox("Aircraft not installed",
+                                        "Requested aircraft is not currently installed.",
+                                        aircraftProp->getStringValue());
+
+            return flightgear::FG_OPTIONS_ERROR;
+        }
+
+        SG_LOG(SG_GENERAL, SG_INFO, "Loading aircraft from " << acftPackage->id());
+
+        // set catalog path so intra-package dependencies within the catalog
+        // are resolved correctly.
+        globals->set_catalog_aircraft_path(acftPackage->catalog()->installRoot());
+
+        // set aircraft-dir to short circuit the search process
+        InstallRef acftInstall = acftPackage->install();
+        fgSetString("/sim/aircraft-dir", acftInstall->path().c_str());
+
+        // overwrite the fully qualified ID with the aircraft one, so the
+        // code in FindAndCacheAircraft works as normal
+
+        aircraftProp->setStringValue(acftPackage->id());
+        // run the traditional-code path below
+    }
+
+    initAircraftDirsNasalSecurity();
+
     FindAndCacheAircraft f(globals->get_props());
     if (!f.loadAircraft()) {
         return flightgear::FG_OPTIONS_ERROR;
index 2efb4ec744cf2b3ef6bff6f671dc357de94c623e..af88f381e34bb22096f7f6520d764d3295219d1e 100644 (file)
@@ -400,6 +400,22 @@ void FGGlobals::clear_fg_scenery()
   fg_scenery.clear();
 }
 
+void FGGlobals::set_catalog_aircraft_path(const SGPath& path)
+{
+    catalog_aircraft_dir = path;
+}
+
+string_list FGGlobals::get_aircraft_paths() const
+{
+    string_list r;
+    if (!catalog_aircraft_dir.isNull()) {
+        r.push_back(catalog_aircraft_dir.str());
+    }
+
+    r.insert(r.end(), fg_aircraft_dirs.begin(), fg_aircraft_dirs.end());
+    return r;
+}
+
 void FGGlobals::append_aircraft_path(const std::string& path)
 {
   SGPath dirPath(path);
@@ -419,13 +435,6 @@ void FGGlobals::append_aircraft_path(const std::string& path)
   std::string abspath = dirPath.realpath();
   unsigned int index = fg_aircraft_dirs.size();  
   fg_aircraft_dirs.push_back(abspath);
-  
-// make aircraft dirs available to Nasal
-  SGPropertyNode* sim = fgGetNode("/sim", true);
-  sim->removeChild("fg-aircraft", index);
-  SGPropertyNode* n = sim->getChild("fg-aircraft", index, true);
-  n->setStringValue(abspath);
-  n->setAttribute(SGPropertyNode::WRITE, false);
 }
 
 void FGGlobals::append_aircraft_paths(const std::string& path)
index 17708c3f72f759224b0e36edee34712920c8d3a9..cf8680ac3c9233d969df7322f374b8040a754659 100644 (file)
@@ -150,6 +150,7 @@ private:
 
     /// roots of Aircraft trees
     string_list fg_aircraft_dirs;
+    SGPath catalog_aircraft_dir;
 
     bool haveUserSettings;
 
@@ -226,8 +227,16 @@ public:
     void append_fg_scenery (const std::string &scenery);
 
     void clear_fg_scenery();
-  
-    const string_list& get_aircraft_paths() const { return fg_aircraft_dirs; }
+
+    /**
+     * specify a path we'll prepend to the aircraft paths list if non-empty.
+     * This is used with packaged aircraft, to ensure their catalog (and hence,
+     * dependency packages) are found correctly.
+     */
+    void set_catalog_aircraft_path(const SGPath& path);
+
+    string_list get_aircraft_paths() const;
+
     void append_aircraft_path(const std::string& path);
     void append_aircraft_paths(const std::string& path);
     
index d055b968a2c18cc5dd3c2e7c6f7c7d270244c18a..991b39c3631b22dfe5b08c7ab7b0c568fc46f6bc 100644 (file)
@@ -1931,10 +1931,6 @@ void Options::initAircraft()
   } else {
     SG_LOG(SG_INPUT, SG_INFO, "No user specified aircraft, using default" );
   }
-  
-// persist across reset
-  SGPropertyNode* aircraftProp = fgGetNode("/sim/aircraft", true);
-  aircraftProp->setAttribute(SGPropertyNode::PRESERVE, true);
     
   if (p->showAircraft) {
     fgOptLogLevel( "alert" );