improved path detection (and overriding) routines
(cherry picked from commit 32f33fb4b3)
This commit is contained in:
parent
3527dcf39b
commit
a0d81372d1
|
|
@ -506,12 +506,17 @@ public:
|
|||
return create_solid_contents();
|
||||
}
|
||||
|
||||
void init_filesystem(const fs::path &, const settings::common_settings &) const override
|
||||
void init_filesystem(const fs::path &, const settings::common_settings &options) const override
|
||||
{
|
||||
// Q1-like games don't care about the local
|
||||
// filesystem.
|
||||
// they do care about the palette though.
|
||||
fs::clear();
|
||||
|
||||
for (auto &path : options.paths.values()) {
|
||||
fs::addArchive(path, true);
|
||||
}
|
||||
|
||||
img::init_palette(this);
|
||||
}
|
||||
|
||||
|
|
@ -1144,52 +1149,96 @@ private:
|
|||
}
|
||||
|
||||
public:
|
||||
void init_filesystem(const fs::path &source, const settings::common_settings &settings) const override
|
||||
inline void addArchive(const fs::path &path) const
|
||||
{
|
||||
fs::addArchive(path, true);
|
||||
discoverArchives(path);
|
||||
}
|
||||
|
||||
void init_filesystem(const fs::path &source, const settings::common_settings &options) const override
|
||||
{
|
||||
fs::clear();
|
||||
|
||||
if (options.defaultpaths.value()) {
|
||||
constexpr const char *MAPS_FOLDER = "maps";
|
||||
|
||||
constexpr const char *MAPS_FOLDER = "maps";
|
||||
// detect gamedir (mod directory path)
|
||||
fs::path gamedir, basedir;
|
||||
|
||||
// pull in from settings
|
||||
if (options.gamedir.isChanged()) {
|
||||
gamedir = options.gamedir.value();
|
||||
}
|
||||
if (options.basedir.isChanged()) {
|
||||
basedir = options.basedir.value();
|
||||
}
|
||||
|
||||
// figure out the gamedir first
|
||||
if (!gamedir.is_absolute()) {
|
||||
if (!gamedir.empty() && basedir.is_absolute()) {
|
||||
// we passed in a relative gamedir. probably meant to
|
||||
// be derived from basedir.
|
||||
gamedir = basedir.parent_path() / gamedir;
|
||||
}
|
||||
|
||||
// detect gamedir (mod directory path)
|
||||
fs::path gamedir;
|
||||
// no gamedir, so calculate it from the input
|
||||
if (gamedir.empty()) {
|
||||
// expand canonicals, and fetch parent of source file
|
||||
if (auto paths = fs::splitArchivePath(source)) {
|
||||
// if the source is an archive, use the parent
|
||||
// of that folder as the mod directory
|
||||
// pak0.pak/maps/source.map -> C:/Quake/ID1
|
||||
gamedir = fs::canonical(paths.archive).parent_path();
|
||||
} else {
|
||||
// maps/source.map -> C:/Quake/ID1/maps
|
||||
// this is weak because the source may not exist yet
|
||||
gamedir = fs::weakly_canonical(source).parent_path();
|
||||
|
||||
// expand canonicals, and fetch parent of source file
|
||||
if (auto paths = fs::splitArchivePath(source)) {
|
||||
// if the source is an archive, use the parent
|
||||
// of that folder as the mod directory
|
||||
// pak0.pak/maps/source.map -> C:/Quake/ID1
|
||||
gamedir = fs::canonical(paths.archive).parent_path();
|
||||
} else {
|
||||
// maps/source.map -> C:/Quake/ID1/maps
|
||||
// this is weak because the source may not exist yet
|
||||
gamedir = fs::weakly_canonical(source).parent_path();
|
||||
if (!string_iequals(gamedir.filename().generic_string(), MAPS_FOLDER)) {
|
||||
logging::print("WARNING: '{}' is not directly inside '{}'; gamedir can't be automatically determined.\n",
|
||||
source, MAPS_FOLDER);
|
||||
}
|
||||
|
||||
if (!string_iequals(gamedir.filename().generic_string(), "maps")) {
|
||||
logging::print("WARNING: '{}' is not directly inside '{}'. This may confuse automated path detection.\n",
|
||||
source, MAPS_FOLDER);
|
||||
return;
|
||||
// C:/Quake/ID1/maps -> C:/Quake/ID1
|
||||
gamedir = gamedir.parent_path();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// C:/Quake/ID1/maps -> C:/Quake/ID1
|
||||
gamedir = gamedir.parent_path();
|
||||
if (!exists(gamedir)) {
|
||||
logging::print("WARNING: failed to find gamedir '{}'\n", gamedir);
|
||||
}
|
||||
|
||||
// now find base dir, if we haven't set it yet
|
||||
if (!basedir.is_absolute()) {
|
||||
if (!gamedir.empty() && gamedir.is_absolute()) {
|
||||
// we passed in a relative basedir. probably meant to
|
||||
// be derived from gamedir.
|
||||
basedir = gamedir.parent_path() / basedir;
|
||||
}
|
||||
|
||||
// no basedir, so calculate it from gamedir
|
||||
if (basedir.empty()) {
|
||||
basedir = gamedir.parent_path() / default_base_dir;
|
||||
}
|
||||
}
|
||||
|
||||
if (!exists(basedir)) {
|
||||
logging::print("WARNING: failed to find basedir '{}'\n", basedir);
|
||||
} else if (!equivalent(gamedir, basedir)) {
|
||||
addArchive(basedir);
|
||||
}
|
||||
|
||||
if (exists(gamedir)) {
|
||||
addArchive(gamedir);
|
||||
}
|
||||
}
|
||||
|
||||
// C:/Quake/ID1 -> C:/Quake
|
||||
fs::path qdir = gamedir.parent_path();
|
||||
|
||||
// Set base dir and make sure it exists
|
||||
fs::path basedir = qdir / (settings.basedir.isChanged() ? settings.basedir.value() : default_base_dir);
|
||||
|
||||
if (!exists(basedir)) {
|
||||
logging::print("WARNING: failed to find '{}' in '{}'\n", default_base_dir, qdir);
|
||||
} else if (!equivalent(gamedir, basedir)) {
|
||||
fs::addArchive(basedir);
|
||||
discoverArchives(basedir);
|
||||
// add secondary paths
|
||||
for (auto &path : options.paths.values()) {
|
||||
addArchive(path);
|
||||
}
|
||||
|
||||
fs::addArchive(gamedir);
|
||||
discoverArchives(gamedir);
|
||||
|
||||
// load palette
|
||||
img::init_palette(this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,8 +31,6 @@
|
|||
|
||||
namespace fs
|
||||
{
|
||||
path qdir, gamedir, basedir;
|
||||
|
||||
struct directory_archive : archive_like
|
||||
{
|
||||
using archive_like::archive_like;
|
||||
|
|
@ -213,10 +211,6 @@ std::list<std::shared_ptr<archive_like>> archives, directories;
|
|||
/** It's possible to compile quake 1/hexen 2 maps without a qdir */
|
||||
void clear()
|
||||
{
|
||||
qdir.clear();
|
||||
gamedir.clear();
|
||||
basedir.clear();
|
||||
|
||||
archives.clear();
|
||||
directories.clear();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,10 +44,6 @@ struct archive_like
|
|||
virtual data load(const path &filename) = 0;
|
||||
};
|
||||
|
||||
extern path qdir, // c:/Quake/, c:/Hexen II/ etc.
|
||||
gamedir, // c:/Quake/mymod/
|
||||
basedir; // c:/Quake/ID1/, c:/Quake 2/BASEQ2/ etc.
|
||||
|
||||
// clear all initialized/loaded data from fs
|
||||
void clear();
|
||||
|
||||
|
|
|
|||
|
|
@ -136,6 +136,11 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
// skip end of named arguments
|
||||
if (parser.token == "-" || parser.token == "--") {
|
||||
parser.parse_token();
|
||||
}
|
||||
|
||||
while (std::isspace(value.back())) {
|
||||
value.pop_back();
|
||||
}
|
||||
|
|
@ -563,6 +568,31 @@ public:
|
|||
std::string format() const override { return _format; }
|
||||
};
|
||||
|
||||
class setting_path : public setting_value<fs::path>
|
||||
{
|
||||
public:
|
||||
inline setting_path(setting_container *dictionary, const nameset &names, fs::path v,
|
||||
const setting_group *group = nullptr, const char *description = "")
|
||||
: setting_value(dictionary, names, v, group, description)
|
||||
{
|
||||
}
|
||||
|
||||
bool parse(const std::string &settingName, parser_base_t &parser, bool locked = false) override
|
||||
{
|
||||
// make sure we can parse token out
|
||||
if (!parser.parse_token()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
setValueFromParse(parser.token, locked);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string stringValue() const override { return _value.string(); }
|
||||
|
||||
std::string format() const override { return "\"relative/path\" or \"C:/absolute/path\""; }
|
||||
};
|
||||
|
||||
class setting_set : public setting_base
|
||||
{
|
||||
private:
|
||||
|
|
@ -593,7 +623,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
const std::unordered_set<std::string> &values() { return _values; }
|
||||
const std::unordered_set<std::string> &values() const { return _values; }
|
||||
|
||||
inline void setValueLocked(const std::string &f) { addValueInternal(f, source::COMMANDLINE); }
|
||||
|
||||
|
|
@ -846,10 +876,12 @@ public:
|
|||
setting_bool nostat{this, "nostat", false, &logging_group, "don't output statistic messages"};
|
||||
setting_bool noprogress{this, "noprogress", false, &logging_group, "don't output progress messages"};
|
||||
setting_redirect quiet{this, {"quiet", "noverbose"}, {&nopercent, &nostat, &noprogress}, &logging_group, "suppress non-important messages (equivalent to -nopercent -nostat -noprogress)"};
|
||||
setting_string basedir{this, "basedir", "", "dir_name", &game_group, "override the default game base directory"};
|
||||
setting_path gamedir{this, "gamedir", "", &game_group, "override the default mod base directory. if this is not set, or if it is relative, it will be derived from the input file or the basedir if specified."};
|
||||
setting_path basedir{this, "basedir", "", &game_group, "override the default game base directory. if this is not set, or if it is relative, it will be derived from the input file or the gamedir if specified."};
|
||||
setting_enum<search_priority_t> filepriority{this, "filepriority", search_priority_t::LOOSE, { { "loose", search_priority_t::LOOSE }, { "archive", search_priority_t::ARCHIVE } }, &game_group, "which types of archives (folders/loose files or packed archives) are higher priority and chosen first for path searching" };
|
||||
setting_set paths{this, "path", "\"/path/to/folder\" <multiple allowed>", &game_group, "additional paths or archives to add to the search path, mostly for loose files"};
|
||||
setting_bool q2rtx{this, "q2rtx", false, &game_group, "adjust settings to best support Q2RTX"};
|
||||
setting_invertible_bool defaultpaths{this, "defaultpaths", true, &game_group, "whether the compiler should attempt to automatically derive game/base paths for games that support it"};
|
||||
|
||||
virtual void setParameters(int argc, const char **argv);
|
||||
|
||||
|
|
|
|||
|
|
@ -1140,10 +1140,6 @@ void load_textures(const mbsp_t *bsp)
|
|||
{
|
||||
logging::print("--- {} ---\n", __func__);
|
||||
|
||||
for (auto &path : options.paths.values()) {
|
||||
fs::addArchive(path, true);
|
||||
}
|
||||
|
||||
if (bsp->loadversion->game->id == GAME_QUAKE_II) {
|
||||
LoadTextures(bsp);
|
||||
} else if (bsp->dtex.textures.size() > 0) {
|
||||
|
|
|
|||
|
|
@ -102,10 +102,6 @@ static void EnsureTexturesLoaded(const mapentity_t *entity)
|
|||
return;
|
||||
|
||||
map.textures_loaded = true;
|
||||
|
||||
for (auto &path : options.paths.values()) {
|
||||
fs::addArchive(path, true);
|
||||
}
|
||||
|
||||
// Q2 doesn't need this
|
||||
if (options.target_game->id == GAME_QUAKE_II) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue