From ab495d137084226b66badce500f166fb047eaaac Mon Sep 17 00:00:00 2001 From: James Turner Date: Sun, 18 Jul 2010 13:21:30 +0100 Subject: [PATCH] Add --fg-aircraft option, and aircraft dir path list. Partial support in places that load files, for respecting the setting. Add helper to look for an aircraft branch path in multiple candidate locations. Update the main subsystems to use the helper, and hence load from any aircraft dir. --- src/Autopilot/autopilotgroup.cxx | 3 +- src/Cockpit/panel_io.cxx | 5 +- src/Instrumentation/instrument_mgr.cxx | 5 +- src/Main/fg_init.cxx | 78 +++++++++++++++++++------- src/Main/globals.cxx | 76 +++++++++++++++++++++++++ src/Main/globals.hxx | 23 ++++++++ src/Main/options.cxx | 13 ++++- src/Main/splash.cxx | 7 ++- src/Scripting/NasalSys.cxx | 3 +- src/Sound/fg_fx.cxx | 5 +- src/Systems/system_mgr.cxx | 3 +- 11 files changed, 181 insertions(+), 40 deletions(-) diff --git a/src/Autopilot/autopilotgroup.cxx b/src/Autopilot/autopilotgroup.cxx index 81b4d8101..e5bb6d03c 100644 --- a/src/Autopilot/autopilotgroup.cxx +++ b/src/Autopilot/autopilotgroup.cxx @@ -194,8 +194,7 @@ void FGXMLAutopilotGroup::init() continue; } - SGPath config( globals->get_fg_root() ); - config.append( pathNode->getStringValue() ); + SGPath config = globals->resolve_aircraft_path(pathNode->getStringValue()); SG_LOG( SG_ALL, SG_INFO, "Reading autopilot configuration from " << config.str() ); diff --git a/src/Cockpit/panel_io.cxx b/src/Cockpit/panel_io.cxx index 7ef58b6e1..ecd6efd89 100644 --- a/src/Cockpit/panel_io.cxx +++ b/src/Cockpit/panel_io.cxx @@ -839,10 +839,9 @@ fgReadPanel (istream &input) FGPanel * fgReadPanel (const string &relative_path) { - SGPath path(globals->get_fg_root()); - path.append(relative_path); + SGPath path = globals->resolve_aircraft_path(relative_path); SGPropertyNode root; - + try { readProperties(path.str(), &root); } catch (const sg_exception &e) { diff --git a/src/Instrumentation/instrument_mgr.cxx b/src/Instrumentation/instrument_mgr.cxx index 6bfecbb27..27f5e3948 100644 --- a/src/Instrumentation/instrument_mgr.cxx +++ b/src/Instrumentation/instrument_mgr.cxx @@ -62,9 +62,8 @@ FGInstrumentMgr::FGInstrumentMgr () : SGPropertyNode *path_n = fgGetNode("/sim/instrumentation/path"); if (path_n) { - SGPath config( globals->get_fg_root() ); - config.append( path_n->getStringValue() ); - + SGPath config = globals->resolve_aircraft_path(path_n->getStringValue()); + SG_LOG( SG_ALL, SG_INFO, "Reading instruments from " << config.str() ); try { diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx index 4c2404dba..179b46e0e 100644 --- a/src/Main/fg_init.cxx +++ b/src/Main/fg_init.cxx @@ -240,7 +240,9 @@ static string fgScanForOption( const string& option ) { // Read in configuration (files and command line options) but only set -// fg_root +// fg_root and aircraft_paths, which are needed *before* do_options() is called +// in fgInitConfig + bool fgInitFGRoot ( int argc, char **argv ) { string root; @@ -291,7 +293,7 @@ bool fgInitFGRoot ( int argc, char **argv ) { SG_LOG(SG_INPUT, SG_INFO, "fg_root = " << root ); globals->set_fg_root(root); - + return true; } @@ -299,6 +301,21 @@ bool fgInitFGRoot ( int argc, char **argv ) { // Read in configuration (files and command line options) but only set // aircraft bool fgInitFGAircraft ( int argc, char **argv ) { + + string aircraftDir = fgScanForOption("--fg-aircraft=", argc, argv); + if (aircraftDir.empty()) { + aircraftDir = fgScanForOption("--fg-aircraft="); + } + + const char* envp = ::getenv("FG_AIRCRAFT"); + if (aircraftDir.empty() && envp) { + globals->append_aircraft_paths(envp); + } + + if (!aircraftDir.empty()) { + globals->append_aircraft_paths(aircraftDir); + } + string aircraft; // First parse command line options looking for --aircraft=, this @@ -501,13 +518,13 @@ do_options (int argc, char ** argv) } template -void fgFindAircraftInDir(const SGPath& dirPath, T* obj, bool (T::*pred)(const SGPath& p)) +bool fgFindAircraftInDir(const SGPath& dirPath, T* obj, bool (T::*pred)(const SGPath& p)) { if (!dirPath.exists()) { SG_LOG(SG_GENERAL, SG_WARN, "fgFindAircraftInDir: no such path:" << dirPath.str()); - return; + return false; } - + bool recurse = true; simgear::Dir dir(dirPath); simgear::PathList setFiles(dir.children(simgear::Dir::TYPE_FILE, "-set.xml")); @@ -520,20 +537,44 @@ void fgFindAircraftInDir(const SGPath& dirPath, T* obj, bool (T::*pred)(const SG bool done = (obj->*pred)(*p); if (done) { - return; + return true; } } // of -set.xml iteration - if (recurse) { - simgear::PathList subdirs(dir.children(simgear::Dir::TYPE_DIR | simgear::Dir::NO_DOT_OR_DOTDOT)); - for (p = subdirs.begin(); p != subdirs.end(); ++p) { - if (p->file() == "CVS") { - continue; - } - - fgFindAircraftInDir(*p, obj, pred); + if (!recurse) { + return false; + } + + simgear::PathList subdirs(dir.children(simgear::Dir::TYPE_DIR | simgear::Dir::NO_DOT_OR_DOTDOT)); + for (p = subdirs.begin(); p != subdirs.end(); ++p) { + if (p->file() == "CVS") { + continue; + } + + if (fgFindAircraftInDir(*p, obj, pred)) { + return true; } - } // of recursive case + } // of subdirs iteration + + return false; +} + +template +void fgFindAircraft(T* obj, bool (T::*pred)(const SGPath& p)) +{ + const string_list& paths(globals->get_aircraft_paths()); + string_list::const_iterator it = paths.begin(); + for (; it != paths.end(); ++it) { + bool done = fgFindAircraftInDir(SGPath(*it), obj, pred); + if (done) { + return; + } + } // of aircraft paths iteration + + // if we reach this point, search the default location (always last) + SGPath rootAircraft(globals->get_fg_root()); + rootAircraft.append("Aircraft"); + fgFindAircraftInDir(rootAircraft, obj, pred); } class FindAndCacheAircraft @@ -559,11 +600,8 @@ public: n->setStringValue(globals->get_fg_root().c_str()); n->setAttribute(SGPropertyNode::USERARCHIVE, true); _cache->removeChildren("aircraft"); - - SGPath aircraftDir(globals->get_fg_root()); - aircraftDir.append("Aircraft"); - - fgFindAircraftInDir(aircraftDir, this, &FindAndCacheAircraft::checkAircraft); + + fgFindAircraft(this, &FindAndCacheAircraft::checkAircraft); } if (_foundPath.str().empty()) { diff --git a/src/Main/globals.cxx b/src/Main/globals.cxx index ad3808919..a7023045d 100644 --- a/src/Main/globals.cxx +++ b/src/Main/globals.cxx @@ -234,6 +234,82 @@ void FGGlobals::set_fg_scenery (const string &scenery) } // of path list iteration } +void FGGlobals::append_aircraft_path(const std::string& path) +{ + SGPath dirPath(path); + if (!dirPath.exists()) { + SG_LOG(SG_GENERAL, SG_WARN, "aircraft path not found:" << path); + return; + } + + fg_aircraft_dirs.push_back(path); +} + +void FGGlobals::append_aircraft_paths(const std::string& path) +{ + string_list paths = sgPathSplit(path); + for (unsigned int p = 0; p #include #include +#include #include #include @@ -181,6 +182,8 @@ private: //Mulitplayer managers FGMultiplayMgr *multiplayer_mgr; + /// roots of Aircraft trees + string_list fg_aircraft_dirs; public: FGGlobals(); @@ -212,6 +215,26 @@ public: inline const string_list &get_fg_scenery () const { return fg_scenery; } void set_fg_scenery (const std::string &scenery); + const string_list& get_aircraft_paths() const { return fg_aircraft_dirs; } + void append_aircraft_path(const std::string& path); + void append_aircraft_paths(const std::string& path); + + /** + * Given a path to an aircraft-related resource file, resolve it + * against the appropriate root. This means looking at the location + * defined by /sim/aircraft-dir, and then aircraft_path in turn, + * finishing with fg_root/Aircraft. + * + * if the path could not be resolved, an empty path is returned. + */ + SGPath resolve_aircraft_path(const std::string& branch) const; + + /** + * Same as above, but test for non 'Aircraft/' branch paths, and + * always resolve them against fg_root. + */ + SGPath resolve_maybe_aircraft_path(const std::string& branch) const; + inline const std::string &get_browser () const { return browser; } void set_browser (const std::string &b) { browser = b; } diff --git a/src/Main/options.cxx b/src/Main/options.cxx index e3dd7ab38..e572ebf84 100644 --- a/src/Main/options.cxx +++ b/src/Main/options.cxx @@ -114,6 +114,7 @@ fgSetDefaults () // Otherwise, default to Scenery being in $FG_ROOT/Scenery globals->set_fg_scenery(""); } + // Position (deliberately out of range) fgSetDouble("/position/longitude-deg", 9999.0); fgSetDouble("/position/latitude-deg", 9999.0); @@ -772,7 +773,7 @@ fgOptRoc( const char *arg ) static int fgOptFgRoot( const char *arg ) { - globals->set_fg_root(arg); + // this option is dealt with by fgInitFGRoot return FG_OPTIONS_OK; } @@ -783,6 +784,13 @@ fgOptFgScenery( const char *arg ) return FG_OPTIONS_OK; } +static int +fgOptFgAircraft(const char* arg) +{ + // this option is dealt with by fgInitFGAircraft + return FG_OPTIONS_OK; +} + static int fgOptFov( const char *arg ) { @@ -1339,6 +1347,7 @@ struct OptionDesc { {"roc", true, OPTION_FUNC, "", false, "", fgOptRoc }, {"fg-root", true, OPTION_FUNC, "", false, "", fgOptFgRoot }, {"fg-scenery", true, OPTION_FUNC, "", false, "", fgOptFgScenery }, + {"fg-aircraft", true, OPTION_FUNC, "", false, "", fgOptFgAircraft }, {"fdm", true, OPTION_STRING, "/sim/flight-model", false, "", 0 }, {"aero", true, OPTION_STRING, "/sim/aero", false, "", 0 }, {"aircraft-dir", true, OPTION_STRING, "/sim/aircraft-dir", false, "", 0 }, @@ -1622,7 +1631,7 @@ fgParseArgs (int argc, char **argv) bool verbose = false; bool help = false; - SG_LOG(SG_GENERAL, SG_INFO, "Processing command line arguments"); + SG_LOG(SG_GENERAL, SG_ALERT, "Processing command line arguments"); for (int i = 1; i < argc; i++) { string arg = argv[i]; diff --git a/src/Main/splash.cxx b/src/Main/splash.cxx index 403617891..19b123488 100644 --- a/src/Main/splash.cxx +++ b/src/Main/splash.cxx @@ -197,9 +197,10 @@ static osg::Node* fgCreateSplashCamera() tpath.append( "Textures/Splash" ); tpath.concat( num_str ); tpath.concat( ".png" ); - } else - tpath.append( splash_texture ); - + } else { + tpath = globals->resolve_maybe_aircraft_path(splash_texture); + } + osg::Texture2D* splashTexture = new osg::Texture2D; splashTexture->setImage(osgDB::readImageFile(tpath.c_str())); diff --git a/src/Scripting/NasalSys.cxx b/src/Scripting/NasalSys.cxx index a210d0356..055ad879d 100644 --- a/src/Scripting/NasalSys.cxx +++ b/src/Scripting/NasalSys.cxx @@ -750,8 +750,7 @@ void FGNasalSys::loadPropertyScripts() while((fn = n->getChild("file", j)) != NULL) { file_specified = true; const char* file = fn->getStringValue(); - SGPath p(globals->get_fg_root()); - p.append(file); + SGPath p = globals->resolve_maybe_aircraft_path(file); loadModule(p, module); j++; } diff --git a/src/Sound/fg_fx.cxx b/src/Sound/fg_fx.cxx index f1c11f775..950e0bdd0 100644 --- a/src/Sound/fg_fx.cxx +++ b/src/Sound/fg_fx.cxx @@ -69,13 +69,12 @@ FGFX::init() SGPropertyNode *node = fgGetNode("/sim/sound", true); string path_str = node->getStringValue("path"); - SGPath path( globals->get_fg_root() ); if (path_str.empty()) { SG_LOG(SG_GENERAL, SG_ALERT, "No path in /sim/sound/path"); return; } - - path.append(path_str.c_str()); + + SGPath path = globals->resolve_aircraft_path(path_str); SG_LOG(SG_GENERAL, SG_INFO, "Reading sound " << node->getName() << " from " << path.str()); diff --git a/src/Systems/system_mgr.cxx b/src/Systems/system_mgr.cxx index 4936ea638..0ca9efb7a 100644 --- a/src/Systems/system_mgr.cxx +++ b/src/Systems/system_mgr.cxx @@ -34,8 +34,7 @@ FGSystemMgr::FGSystemMgr () SGPropertyNode *path_n = fgGetNode("/sim/systems/path"); if (path_n) { - SGPath config( globals->get_fg_root() ); - config.append( path_n->getStringValue() ); + SGPath config = globals->resolve_aircraft_path(path_n->getStringValue()); SG_LOG( SG_ALL, SG_INFO, "Reading systems from " << config.str() ); -- 2.39.5