Allow cmd line & add-ons to supply FGData extensions
Allow add-ons to define an FGData subdir, and support multiple —data= command line arguments, to avoid the need to modify FG_ROOT (which might be read-only). Allow additional data paths to be either higher or lower priority than FG_ROOT, so that add-ons cannot replace files in FG_ROOT.
This commit is contained in:
parent
f97ea1f621
commit
9e00715079
6 changed files with 52 additions and 10 deletions
|
@ -204,9 +204,16 @@ AddonManager::registerAddon(const SGPath& addonPath)
|
|||
string msg = "Registered add-on '" + addon->getName() + "' (" + addonId +
|
||||
") version " + addonVersion(addonId)->str() + "; "
|
||||
"base path is '" + addonRealPath.utf8Str() + "'";
|
||||
// This preserves the registration order
|
||||
_registeredAddons.push_back(std::move(addon));
|
||||
SG_LOG(SG_GENERAL, SG_INFO, msg);
|
||||
|
||||
auto dataPath = addonRealPath / "FGData";
|
||||
if (dataPath.exists()) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Registering data path for add-on: " << addon->getName());
|
||||
globals->append_data_path(dataPath, true /* after FG_ROOT */);
|
||||
}
|
||||
|
||||
// This preserves the registration order
|
||||
_registeredAddons.push_back(addon);
|
||||
SG_LOG(SG_GENERAL, SG_INFO, msg);
|
||||
|
||||
return addonId;
|
||||
}
|
||||
|
|
|
@ -302,6 +302,7 @@ PathList FGGlobals::get_data_paths() const
|
|||
{
|
||||
PathList r(additional_data_paths);
|
||||
r.push_back(fg_root);
|
||||
r.insert(r.end(), _dataPathsAfterFGRoot.begin(), _dataPathsAfterFGRoot.end());
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -318,13 +319,23 @@ PathList FGGlobals::get_data_paths(const std::string& suffix) const
|
|||
return r;
|
||||
}
|
||||
|
||||
void FGGlobals::append_data_path(const SGPath& path)
|
||||
void FGGlobals::append_data_path(const SGPath& path, bool afterFGRoot)
|
||||
{
|
||||
if (!path.exists()) {
|
||||
SG_LOG(SG_GENERAL, SG_WARN, "adding non-existant data path:" << path);
|
||||
}
|
||||
|
||||
additional_data_paths.push_back(path);
|
||||
using RM = simgear::ResourceManager;
|
||||
auto resManager = RM::instance();
|
||||
if (afterFGRoot) {
|
||||
_dataPathsAfterFGRoot.push_back(path);
|
||||
// after FG_ROOT
|
||||
resManager->addBasePath(path, static_cast<RM::Priority>(RM::PRIORITY_DEFAULT - 10));
|
||||
} else {
|
||||
additional_data_paths.push_back(path);
|
||||
// after NORMAL prioirty, but ahead of FG_ROOT
|
||||
resManager->addBasePath(path, static_cast<RM::Priority>(RM::PRIORITY_DEFAULT + 10));
|
||||
}
|
||||
}
|
||||
|
||||
SGPath FGGlobals::find_data_dir(const std::string& pathSuffix) const
|
||||
|
@ -342,8 +353,15 @@ SGPath FGGlobals::find_data_dir(const std::string& pathSuffix) const
|
|||
return rootPath;
|
||||
}
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_WARN, "dir not found in any data path:" << pathSuffix);
|
||||
return SGPath();
|
||||
for (SGPath p : _dataPathsAfterFGRoot) {
|
||||
p.append(pathSuffix);
|
||||
if (p.exists()) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
SG_LOG(SG_IO, SG_WARN, "not found in any data path: '" << pathSuffix << "'");
|
||||
return SGPath{};
|
||||
}
|
||||
|
||||
void FGGlobals::append_fg_scenery (const PathList &paths)
|
||||
|
|
|
@ -101,6 +101,8 @@ private:
|
|||
*/
|
||||
PathList additional_data_paths;
|
||||
|
||||
PathList _dataPathsAfterFGRoot; ///< paths with a /lower/ prioirty than FGRoot
|
||||
|
||||
// Users home directory for data
|
||||
SGPath fg_home;
|
||||
|
||||
|
@ -216,7 +218,7 @@ public:
|
|||
*/
|
||||
PathList get_data_paths(const std::string& suffix) const;
|
||||
|
||||
void append_data_path(const SGPath& path);
|
||||
void append_data_path(const SGPath& path, bool afterFGRoot = false);
|
||||
|
||||
/**
|
||||
* Given a path suffix (eg 'Textures' or 'AI/Traffic'), find the
|
||||
|
|
|
@ -173,7 +173,7 @@ static void initTerrasync()
|
|||
// add the terrasync root as a data path so data can be retrieved from it
|
||||
// (even if we are in read-only mode)
|
||||
SGPath terraSyncDir(globals->get_terrasync_dir());
|
||||
globals->append_data_path(terraSyncDir);
|
||||
globals->append_data_path(terraSyncDir, false /* = ahead of FG_ROOT */);
|
||||
|
||||
if (fgGetBool("/sim/fghome-readonly", false)) {
|
||||
return;
|
||||
|
|
|
@ -727,6 +727,20 @@ fgOptAddon(const char *arg)
|
|||
return FG_OPTIONS_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
fgOptAdditionalDataDir(const char* arg)
|
||||
{
|
||||
const SGPath dataPath = SGPath::fromUtf8(arg);
|
||||
if (!dataPath.exists()) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "--data path not found:'" << dataPath << "'");
|
||||
flightgear::fatalMessageBoxWithoutExit("FlightGear", "Data path not found");
|
||||
return FG_OPTIONS_EXIT;
|
||||
}
|
||||
|
||||
globals->append_data_path(dataPath, false /* = before FG_ROOT */);
|
||||
return FG_OPTIONS_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
fgOptVOR( const char * arg )
|
||||
{
|
||||
|
@ -1821,6 +1835,7 @@ struct OptionDesc {
|
|||
{"flight-plan", true, OPTION_STRING, "/autopilot/route-manager/file-path", false, "", NULL },
|
||||
{"config", true, OPTION_IGNORE | OPTION_MULTI, "", false, "", 0 },
|
||||
{"addon", true, OPTION_FUNC | OPTION_MULTI, "", false, "", fgOptAddon },
|
||||
{"data", true, OPTION_FUNC | OPTION_MULTI, "", false, "", fgOptAdditionalDataDir },
|
||||
{"aircraft", true, OPTION_STRING, "/sim/aircraft", false, "", 0 },
|
||||
{"vehicle", true, OPTION_STRING, "/sim/aircraft", false, "", 0 },
|
||||
{"failure", true, OPTION_FUNC | OPTION_MULTI, "", false, "", fgOptFailure },
|
||||
|
|
|
@ -753,7 +753,7 @@ bool FGGeneric::close() {
|
|||
void
|
||||
FGGeneric::reinit()
|
||||
{
|
||||
SGPath path = globals->resolve_maybe_aircraft_path("Protocol/" + file_name);
|
||||
SGPath path = globals->find_data_dir("Protocol/" + file_name);
|
||||
if (!path.exists()) {
|
||||
SG_LOG(SG_NETWORK, SG_WARN, "Couldn't find protocol file for '" << file_name << "'");
|
||||
return;
|
||||
|
|
Loading…
Reference in a new issue