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.
This commit is contained in:
parent
d1852430bf
commit
ab495d1370
11 changed files with 181 additions and 40 deletions
|
@ -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() );
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 <class T>
|
||||
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;
|
||||
}
|
||||
} // of recursive case
|
||||
|
||||
if (fgFindAircraftInDir(*p, obj, pred)) {
|
||||
return true;
|
||||
}
|
||||
} // of subdirs iteration
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
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()) {
|
||||
|
|
|
@ -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<paths.size(); ++p) {
|
||||
append_aircraft_path(paths[p]);
|
||||
}
|
||||
}
|
||||
|
||||
SGPath FGGlobals::resolve_aircraft_path(const std::string& branch) const
|
||||
{
|
||||
string_list pieces(sgPathBranchSplit(branch));
|
||||
if ((pieces.size() < 3) || (pieces.front() != "Aircraft")) {
|
||||
SG_LOG(SG_AIRCRAFT, SG_ALERT, "resolve_aircraft_path: bad path:" << branch);
|
||||
return SGPath();
|
||||
}
|
||||
|
||||
// check current aircraft dir first (takes precedence, allows Generics to be
|
||||
// over-riden
|
||||
const char* aircraftDir = fgGetString("/sim/aircraft-dir");
|
||||
string_list aircraftDirPieces(sgPathBranchSplit(aircraftDir));
|
||||
if (!aircraftDirPieces.empty() && (aircraftDirPieces.back() == pieces[1])) {
|
||||
SGPath r(aircraftDir);
|
||||
|
||||
for (unsigned int i=2; i<pieces.size(); ++i) {
|
||||
r.append(pieces[i]);
|
||||
}
|
||||
|
||||
if (r.exists()) {
|
||||
std::cout << "using aircraft-dir for:" << r.str() << std::endl;
|
||||
return r;
|
||||
}
|
||||
} // of using aircraft-dir case
|
||||
|
||||
// try each fg_aircraft_dirs in turn
|
||||
for (unsigned int p=0; p<fg_aircraft_dirs.size(); ++p) {
|
||||
SGPath r(fg_aircraft_dirs[p]);
|
||||
r.append(branch);
|
||||
if (r.exists()) {
|
||||
std::cout << "using aircraft directory for:" << r.str() << std::endl;
|
||||
return r;
|
||||
}
|
||||
} // of fg_aircraft_dirs iteration
|
||||
|
||||
// finally, try fg_root
|
||||
SGPath r(fg_root);
|
||||
r.append(branch);
|
||||
if (r.exists()) {
|
||||
std::cout << "using FG_ROOT for:" << r.str() << std::endl;
|
||||
return r;
|
||||
}
|
||||
|
||||
SG_LOG(SG_AIRCRAFT, SG_ALERT, "resolve_aircraft_path: failed to resolve:" << branch);
|
||||
return SGPath();
|
||||
}
|
||||
|
||||
SGPath FGGlobals::resolve_maybe_aircraft_path(const std::string& branch) const
|
||||
{
|
||||
if (branch.find("Aircraft/") == 0) {
|
||||
return resolve_aircraft_path(branch);
|
||||
} else {
|
||||
SGPath r(fg_root);
|
||||
r.append(branch);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
FGRenderer *
|
||||
FGGlobals::get_renderer () const
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <simgear/compiler.h>
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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()));
|
||||
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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() );
|
||||
|
|
Loading…
Reference in a new issue