Make sure all paths are passed as std::filesystem::path instead of std::string where possible.

crashfix_debugdraw
Project579 3 years ago
parent 35fe214588
commit e5c417c968

@ -17,7 +17,7 @@ namespace bpo = boost::program_options;
struct Arguments struct Arguments
{ {
std::string mode; std::string mode;
std::string filename; std::filesystem::path filename;
std::string extractfile; std::string extractfile;
std::string addfile; std::string addfile;
std::string outdir; std::string outdir;
@ -112,7 +112,7 @@ bool parseOptions (int argc, char** argv, Arguments &info)
<< desc << std::endl; << desc << std::endl;
return false; return false;
} }
info.filename = variables["input-file"].as< std::vector<std::string> >()[0]; info.filename = variables["input-file"].as< std::vector<std::string> >()[0]; //TODO(Project579): This will probably break in windows with unicode paths
// Default output to the working directory // Default output to the working directory
info.outdir = "."; info.outdir = ".";

@ -33,6 +33,7 @@ namespace
namespace bpo = boost::program_options; namespace bpo = boost::program_options;
using StringsVector = std::vector<std::string>; using StringsVector = std::vector<std::string>;
using PathsVector = std::vector<std::filesystem::path>;
bpo::options_description makeOptionsDescription() bpo::options_description makeOptionsDescription()
{ {
@ -145,7 +146,7 @@ namespace
const auto fsStrict = variables["fs-strict"].as<bool>(); const auto fsStrict = variables["fs-strict"].as<bool>();
const auto resDir = variables["resources"].as<Files::MaybeQuotedPath>(); const auto resDir = variables["resources"].as<Files::MaybeQuotedPath>();
Version::Version v = Version::getOpenmwVersion(resDir.string()); Version::Version v = Version::getOpenmwVersion(resDir);
Log(Debug::Info) << v.describe(); Log(Debug::Info) << v.describe();
dataDirs.insert(dataDirs.begin(), resDir / "vfs"); dataDirs.insert(dataDirs.begin(), resDir / "vfs");
const auto fileCollections = Files::Collections(dataDirs, !fsStrict); const auto fileCollections = Files::Collections(dataDirs, !fsStrict);

@ -3,7 +3,7 @@
#include <vector> #include <vector>
#include <optional> #include <optional>
#include <string> #include <filesystem>
#include <components/esm/format.hpp> #include <components/esm/format.hpp>
@ -18,8 +18,8 @@ namespace EsmTool
std::string mode; std::string mode;
std::string encoding; std::string encoding;
std::string filename; std::filesystem::path filename;
std::string outname; std::filesystem::path outname;
std::vector<std::string> types; std::vector<std::string> types;
std::string name; std::string name;

@ -154,9 +154,9 @@ bool parseOptions (int argc, char** argv, Arguments &info)
return false; return false;
}*/ }*/
info.filename = variables["input-file"].as< std::vector<std::string> >()[0]; info.filename = variables["input-file"].as< std::vector<std::filesystem::path> >()[0];
if (variables["input-file"].as< std::vector<std::string> >().size() > 1) if (variables["input-file"].as< std::vector<std::string> >().size() > 1)
info.outname = variables["input-file"].as< std::vector<std::string> >()[1]; info.outname = variables["input-file"].as< std::vector<std::filesystem::path> >()[1];
if (const auto it = variables.find("raw"); it != variables.end()) if (const auto it = variables.find("raw"); it != variables.end())
info.mRawFormat = ESM::parseFormat(it->second.as<std::string>()); info.mRawFormat = ESM::parseFormat(it->second.as<std::string>());
@ -284,9 +284,9 @@ void loadCell(const Arguments& info, ESM::Cell &cell, ESM::ESMReader &esm, ESMDa
} }
} }
void printRawTes3(std::string_view path) void printRawTes3(const std::filesystem::path &path)
{ {
std::cout << "TES3 RAW file listing: " << path << '\n'; std::cout << "TES3 RAW file listing: " << path << '\n'; //TODO(Project579): This will probably break in windows with unicode paths
ESM::ESMReader esm; ESM::ESMReader esm;
esm.openRaw(path); esm.openRaw(path);
while(esm.hasMoreRecs()) while(esm.hasMoreRecs())
@ -310,7 +310,7 @@ void printRawTes3(std::string_view path)
int loadTes3(const Arguments& info, std::unique_ptr<std::ifstream>&& stream, ESMData* data) int loadTes3(const Arguments& info, std::unique_ptr<std::ifstream>&& stream, ESMData* data)
{ {
std::cout << "Loading TES3 file: " << info.filename << '\n'; std::cout << "Loading TES3 file: " << info.filename << '\n'; //TODO(Project579): This will probably break in windows with unicode paths
ESM::ESMReader esm; ESM::ESMReader esm;
ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding(info.encoding)); ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding(info.encoding));
@ -419,7 +419,7 @@ int load(const Arguments& info, ESMData* data)
printRawTes3(info.filename); printRawTes3(info.filename);
break; break;
case ESM::Format::Tes4: case ESM::Format::Tes4:
std::cout << "Printing raw TES4 file is not supported: " << info.filename << "\n"; std::cout << "Printing raw TES4 file is not supported: " << info.filename << "\n"; //TODO(Project579): This will probably break in windows with unicode paths
break; break;
} }
return 0; return 0;
@ -490,7 +490,7 @@ int clone(const Arguments& info)
if (i % 3 != 0) if (i % 3 != 0)
std::cout << '\n'; std::cout << '\n';
std::cout << "\nSaving records to: " << info.outname << "...\n"; std::cout << "\nSaving records to: " << info.outname << "...\n"; //TODO(Project579): This will probably break in windows with unicode paths
ESM::ESMWriter esm; ESM::ESMWriter esm;
ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding(info.encoding)); ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding(info.encoding));
@ -499,7 +499,7 @@ int clone(const Arguments& info)
esm.setVersion(ESM::VER_13); esm.setVersion(ESM::VER_13);
esm.setRecordCount (recordCount); esm.setRecordCount (recordCount);
std::fstream save(info.outname.c_str(), std::fstream::out | std::fstream::binary); std::fstream save(info.outname, std::fstream::out | std::fstream::binary);
esm.save(save); esm.save(save);
int saved = 0; int saved = 0;
@ -563,14 +563,14 @@ int comp(const Arguments& info)
ESMData dataOne; ESMData dataOne;
if (load(fileOne, &dataOne) != 0) if (load(fileOne, &dataOne) != 0)
{ {
std::cout << "Failed to load " << info.filename << ", aborting comparison." << std::endl; std::cout << "Failed to load " << info.filename << ", aborting comparison." << std::endl; //TODO(Project579): This will probably break in windows with unicode paths
return 1; return 1;
} }
ESMData dataTwo; ESMData dataTwo;
if (load(fileTwo, &dataTwo) != 0) if (load(fileTwo, &dataTwo) != 0)
{ {
std::cout << "Failed to load " << info.outname << ", aborting comparison." << std::endl; std::cout << "Failed to load " << info.outname << ", aborting comparison." << std::endl; //TODO(Project579): This will probably break in windows with unicode paths
return 1; return 1;
} }

@ -289,7 +289,7 @@ namespace EsmTool
int loadTes4(const Arguments& info, std::unique_ptr<std::ifstream>&& stream) int loadTes4(const Arguments& info, std::unique_ptr<std::ifstream>&& stream)
{ {
std::cout << "Loading TES4 file: " << info.filename << '\n'; std::cout << "Loading TES4 file: " << info.filename << '\n'; //TODO(Project579): This will probably break in windows with unicode paths
try try
{ {

@ -230,7 +230,7 @@ void Launcher::DataFilesPage::populateFileViews(const QString& contentModelName)
if (!mDataLocal.isEmpty()) if (!mDataLocal.isEmpty())
directories.insert(0, mDataLocal); directories.insert(0, mDataLocal);
const auto globalDataDir = QString(mGameSettings.getGlobalDataDir().c_str()); const auto globalDataDir = QString(mGameSettings.getGlobalDataDir().string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths
if (!globalDataDir.isEmpty()) if (!globalDataDir.isEmpty())
directories.insert(0, globalDataDir); directories.insert(0, globalDataDir);

@ -155,7 +155,7 @@ Launcher::FirstRunDialogResult Launcher::MainDialog::showFirstRunDialog()
return FirstRunDialogResultFailure; return FirstRunDialogResultFailure;
// Dialog wizard and setup will fail if the config directory does not already exist // Dialog wizard and setup will fail if the config directory does not already exist
QDir userConfigDir = QDir(QString::fromStdString(mCfgMgr.getUserConfigPath().string())); QDir userConfigDir = QDir(QString::fromStdString(mCfgMgr.getUserConfigPath().string())); //TODO(Project579): This will probably break in windows with unicode paths, in Qt 6 it's possible to convert directly from std::filesystem::path to QDir and that would solve the issue
if ( ! userConfigDir.exists() ) { if ( ! userConfigDir.exists() ) {
if ( ! userConfigDir.mkpath(".") ) if ( ! userConfigDir.mkpath(".") )
{ {
@ -295,7 +295,7 @@ bool Launcher::MainDialog::setupLauncherSettings()
mLauncherSettings.setMultiValueEnabled(true); mLauncherSettings.setMultiValueEnabled(true);
QString userPath = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str()); QString userPath = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths
QStringList paths; QStringList paths;
paths.append(QString(Config::LauncherSettings::sLauncherConfigFileName)); paths.append(QString(Config::LauncherSettings::sLauncherConfigFileName));
@ -328,9 +328,9 @@ bool Launcher::MainDialog::setupGameSettings()
{ {
mGameSettings.clear(); mGameSettings.clear();
QString localPath = QString::fromUtf8(mCfgMgr.getLocalPath().string().c_str()); QString localPath = QString::fromUtf8(mCfgMgr.getLocalPath().string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths
QString userPath = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str()); QString userPath = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths
QString globalPath = QString::fromUtf8(mCfgMgr.getGlobalPath().string().c_str()); QString globalPath = QString::fromUtf8(mCfgMgr.getGlobalPath().string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths
QFile file; QFile file;
@ -479,7 +479,7 @@ bool Launcher::MainDialog::writeSettings()
mSettingsPage->saveSettings(); mSettingsPage->saveSettings();
mAdvancedPage->saveSettings(); mAdvancedPage->saveSettings();
QString userPath = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str()); QString userPath = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths
QDir dir(userPath); QDir dir(userPath);
if (!dir.exists()) { if (!dir.exists()) {
@ -509,13 +509,13 @@ bool Launcher::MainDialog::writeSettings()
file.close(); file.close();
// Graphics settings // Graphics settings
const std::string settingsPath = (mCfgMgr.getUserConfigPath() / "settings.cfg").string(); const auto settingsPath = mCfgMgr.getUserConfigPath() / "settings.cfg";
try { try {
Settings::Manager::saveUser(settingsPath); Settings::Manager::saveUser(settingsPath);
} }
catch (std::exception& e) { catch (std::exception& e) {
std::string msg = "<br><b>Error writing settings.cfg</b><br><br>" + std::string msg = "<br><b>Error writing settings.cfg</b><br><br>" +
settingsPath + "<br><br>" + e.what(); settingsPath.string() + "<br><br>" + e.what(); //TODO(Project579): This will probably break in windows with unicode paths
cfgError(tr("Error writing user settings file"), tr(msg.c_str())); cfgError(tr("Error writing user settings file"), tr(msg.c_str()));
return false; return false;
} }

@ -102,7 +102,7 @@ void Launcher::SettingsPage::on_importerButton_clicked()
mMain->writeSettings(); mMain->writeSettings();
// Create the file if it doesn't already exist, else the importer will fail // Create the file if it doesn't already exist, else the importer will fail
QString path(QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str())); QString path(QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str())); //TODO(Project579): This will probably break in windows with unicode paths
path.append(QLatin1String("openmw.cfg")); path.append(QLatin1String("openmw.cfg"));
QFile file(path); QFile file(path);

@ -661,7 +661,7 @@ MwIniImporter::multistrmap MwIniImporter::loadIniFile(const std::filesystem::pat
std::string section(""); std::string section("");
MwIniImporter::multistrmap map; MwIniImporter::multistrmap map;
std::ifstream file((sfs::path(filename))); std::ifstream file(filename);
ToUTF8::Utf8Encoder encoder(mEncoding); ToUTF8::Utf8Encoder encoder(mEncoding);
std::string line; std::string line;
@ -721,7 +721,7 @@ MwIniImporter::multistrmap MwIniImporter::loadCfgFile(const std::filesystem::pat
std::cout << "load cfg file: " << filename << std::endl; std::cout << "load cfg file: " << filename << std::endl;
MwIniImporter::multistrmap map; MwIniImporter::multistrmap map;
std::ifstream file((sfs::path(filename))); std::ifstream file(filename);
std::string line; std::string line;
while (std::getline(file, line)) { while (std::getline(file, line)) {
@ -938,13 +938,13 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini, co
reader.setEncoder(&encoder); reader.setEncoder(&encoder);
for (auto& file : contentFiles) for (auto& file : contentFiles)
{ {
reader.open(file.second.string()); reader.open(file.second);
std::vector<std::string> dependencies; std::vector<std::string> dependencies;
for (auto& gameFile : reader.getGameFiles()) for (auto& gameFile : reader.getGameFiles())
{ {
dependencies.push_back(gameFile.name); dependencies.push_back(gameFile.name);
} }
unsortedFiles.emplace_back(std::filesystem::path(reader.getName()).filename().string(), dependencies); unsortedFiles.emplace_back(reader.getName().filename().string(), dependencies); //TODO(Project579): This will probably break in windows with unicode paths
reader.close(); reader.close();
} }

@ -52,8 +52,6 @@ private:
int wmain(int argc, wchar_t *wargv[]) { int wmain(int argc, wchar_t *wargv[]) {
utf8argv converter(argc, wargv); utf8argv converter(argc, wargv);
char **argv = converter.get(); char **argv = converter.get();
// TODO(Project579): Temporarly disabled until a good solution is found (no solution might actually be needed)
//boost::filesystem::path::imbue(boost::locale::generator().generate(""));
#endif #endif
try try

@ -143,7 +143,7 @@ namespace NavMeshTool
const auto fsStrict = variables["fs-strict"].as<bool>(); const auto fsStrict = variables["fs-strict"].as<bool>();
const auto resDir = variables["resources"].as<Files::MaybeQuotedPath>(); const auto resDir = variables["resources"].as<Files::MaybeQuotedPath>();
Version::Version v = Version::getOpenmwVersion(resDir.string()); Version::Version v = Version::getOpenmwVersion(resDir);
Log(Debug::Info) << v.describe(); Log(Debug::Info) << v.describe();
dataDirs.insert(dataDirs.begin(), resDir / "vfs"); dataDirs.insert(dataDirs.begin(), resDir / "vfs");
const auto fileCollections = Files::Collections(dataDirs, !fsStrict); const auto fileCollections = Files::Collections(dataDirs, !fsStrict);
@ -179,9 +179,9 @@ namespace NavMeshTool
const osg::Vec3f agentHalfExtents = Settings::Manager::getVector3("default actor pathfind half extents", "Game"); const osg::Vec3f agentHalfExtents = Settings::Manager::getVector3("default actor pathfind half extents", "Game");
const DetourNavigator::AgentBounds agentBounds {agentCollisionShape, agentHalfExtents}; const DetourNavigator::AgentBounds agentBounds {agentCollisionShape, agentHalfExtents};
const std::uint64_t maxDbFileSize = static_cast<std::uint64_t>(Settings::Manager::getInt64("max navmeshdb file size", "Navigator")); const std::uint64_t maxDbFileSize = static_cast<std::uint64_t>(Settings::Manager::getInt64("max navmeshdb file size", "Navigator"));
const std::string dbPath = (config.getUserDataPath() / "navmesh.db").string(); const auto dbPath = config.getUserDataPath() / "navmesh.db";
DetourNavigator::NavMeshDb db(dbPath, maxDbFileSize); DetourNavigator::NavMeshDb db(dbPath.string(), maxDbFileSize); //TODO(Project579): This will probably break in windows with unicode paths
ESM::ReadersCache readers; ESM::ReadersCache readers;
EsmLoader::Query query; EsmLoader::Query query;

@ -16,45 +16,45 @@
namespace bpo = boost::program_options; namespace bpo = boost::program_options;
///See if the file has the named extension ///See if the file has the named extension
bool hasExtension(std::string filename, std::string extensionToFind) bool hasExtension(const std::filesystem::path& filename, const std::string& extensionToFind)
{ {
std::string extension = filename.substr(filename.find_last_of('.')+1); std::string extension = filename.extension().string(); //TODO(Project579): let's hope unicode characters are never used in these extensions on windows or this will break
return Misc::StringUtils::ciEqual(extension, extensionToFind); return Misc::StringUtils::ciEqual(extension, extensionToFind);
} }
///See if the file has the "nif" extension. ///See if the file has the "nif" extension.
bool isNIF(const std::string & filename) bool isNIF(const std::filesystem::path &filename)
{ {
return hasExtension(filename,"nif"); return hasExtension(filename,"nif");
} }
///See if the file has the "bsa" extension. ///See if the file has the "bsa" extension.
bool isBSA(const std::string & filename) bool isBSA(const std::filesystem::path &filename)
{ {
return hasExtension(filename,"bsa"); return hasExtension(filename,"bsa");
} }
/// Check all the nif files in a given VFS::Archive /// Check all the nif files in a given VFS::Archive
/// \note Can not read a bsa file inside of a bsa file. /// \note Can not read a bsa file inside of a bsa file.
void readVFS(std::unique_ptr<VFS::Archive>&& anArchive, std::string archivePath = "") void readVFS(std::unique_ptr<VFS::Archive>&& anArchive, const std::filesystem::path& archivePath = {})
{ {
VFS::Manager myManager(true); VFS::Manager myManager(true);
myManager.addArchive(std::move(anArchive)); myManager.addArchive(std::move(anArchive));
myManager.buildIndex(); myManager.buildIndex();
for(const auto& name : myManager.getRecursiveDirectoryIterator("")) for(const auto& name : myManager.getRecursiveDirectoryIterator("")) //TODO(Project579): This will probably break in windows with unicode paths
{ {
try{ try{
if(isNIF(name)) if(isNIF(name))
{ {
// std::cout << "Decoding: " << name << std::endl; // std::cout << "Decoding: " << name << std::endl;
Nif::NIFFile temp_nif(myManager.get(name),archivePath+name); Nif::NIFFile temp_nif(myManager.get(name),archivePath / name);
} }
else if(isBSA(name)) else if(isBSA(name))
{ {
if(!archivePath.empty() && !isBSA(archivePath)) if(!archivePath.empty() && !isBSA(archivePath))
{ {
// std::cout << "Reading BSA File: " << name << std::endl; // std::cout << "Reading BSA File: " << name << std::endl;
readVFS(std::make_unique<VFS::BsaArchive>(archivePath + name), archivePath + name + "/"); readVFS(std::make_unique<VFS::BsaArchive>(archivePath / name), archivePath / name);
// std::cout << "Done with BSA File: " << name << std::endl; // std::cout << "Done with BSA File: " << name << std::endl;
} }
} }
@ -75,7 +75,7 @@ bool parseOptions (int argc, char** argv, std::vector<std::string>& files)
"Allowed options"); "Allowed options");
desc.add_options() desc.add_options()
("help,h", "print help message.") ("help,h", "print help message.")
("input-file", bpo::value< std::vector<std::string> >(), "input file") ("input-file", bpo::value< std::vector<std::filesystem::path> >(), "input file")
; ;
//Default option if none provided //Default option if none provided
@ -120,30 +120,30 @@ int main(int argc, char **argv)
Nif::NIFFile::setLoadUnsupportedFiles(true); Nif::NIFFile::setLoadUnsupportedFiles(true);
// std::cout << "Reading Files" << std::endl; // std::cout << "Reading Files" << std::endl;
for(auto it=files.begin(); it!=files.end(); ++it) for(const auto& name : files)
{ {
std::string name = *it;
try try
{ {
if(isNIF(name)) const std::filesystem::path path(name); //TODO(Project579): This will probably break in windows with unicode paths
if(isNIF(path))
{ {
//std::cout << "Decoding: " << name << std::endl; //std::cout << "Decoding: " << name << std::endl;
Nif::NIFFile temp_nif(Files::openConstrainedFileStream(name), name); Nif::NIFFile temp_nif(Files::openConstrainedFileStream(path), path);
} }
else if(isBSA(name)) else if(isBSA(path))
{ {
// std::cout << "Reading BSA File: " << name << std::endl; // std::cout << "Reading BSA File: " << name << std::endl;
readVFS(std::make_unique<VFS::BsaArchive>(name)); readVFS(std::make_unique<VFS::BsaArchive>(path));
} }
else if(std::filesystem::is_directory(std::filesystem::path(name))) else if(std::filesystem::is_directory(path))
{ {
// std::cout << "Reading All Files in: " << name << std::endl; // std::cout << "Reading All Files in: " << name << std::endl;
readVFS(std::make_unique<VFS::FileSystemArchive>(name), name); readVFS(std::make_unique<VFS::FileSystemArchive>(path), path);
} }
else else
{ {
std::cerr << "ERROR: \"" << name << "\" is not a nif file, bsa file, or directory!" << std::endl; std::cerr << "ERROR: \"" << path << "\" is not a nif file, bsa file, or directory!" << std::endl;
} }
} }
catch (std::exception& e) catch (std::exception& e)

@ -78,8 +78,7 @@ CS::Editor::~Editor ()
mPidFile.close(); mPidFile.close();
if(mServer && std::filesystem::exists(mPid)) if(mServer && std::filesystem::exists(mPid))
static_cast<void> ( // silence coverity warning std::filesystem::remove(mPid);
remove(mPid.string().c_str())); // ignore any error
} }
boost::program_options::variables_map CS::Editor::readConfiguration() boost::program_options::variables_map CS::Editor::readConfiguration()
@ -107,7 +106,7 @@ boost::program_options::variables_map CS::Editor::readConfiguration()
mCfgMgr.readConfiguration(variables, desc, false); mCfgMgr.readConfiguration(variables, desc, false);
Settings::Manager::load(mCfgMgr, true); Settings::Manager::load(mCfgMgr, true);
setupLogging(mCfgMgr.getLogPath().string(), "OpenMW-CS"); setupLogging(mCfgMgr.getLogPath(), "OpenMW-CS");
return variables; return variables;
} }
@ -298,7 +297,7 @@ bool CS::Editor::makeIPCServer()
mPidFile.open(mPid); mPidFile.open(mPid);
mLock = boost::interprocess::file_lock(mPid.string().c_str()); mLock = boost::interprocess::file_lock(mPid.c_str());
if(!mLock.try_lock()) if(!mLock.try_lock())
{ {
Log(Debug::Error) << "Error: OpenMW-CS is already running."; Log(Debug::Error) << "Error: OpenMW-CS is already running.";
@ -374,7 +373,7 @@ int CS::Editor::run()
ESM::ESMReader fileReader; ESM::ESMReader fileReader;
ToUTF8::Utf8Encoder encoder(ToUTF8::calculateEncoding(mEncodingName)); ToUTF8::Utf8Encoder encoder(ToUTF8::calculateEncoding(mEncodingName));
fileReader.setEncoder(&encoder); fileReader.setEncoder(&encoder);
fileReader.open(mFileToLoad.string()); fileReader.open(mFileToLoad);
std::vector<std::filesystem::path> discoveredFiles; std::vector<std::filesystem::path> discoveredFiles;
@ -394,7 +393,7 @@ int CS::Editor::run()
} }
discoveredFiles.push_back(mFileToLoad); discoveredFiles.push_back(mFileToLoad);
QString extension = QString::fromStdString(mFileToLoad.extension().string()).toLower(); QString extension = QString::fromStdString(mFileToLoad.extension().string()).toLower(); //TODO(Project579): let's hope unicode characters are never used in these extensions on windows or this will break
if (extension == ".esm") if (extension == ".esm")
{ {
mFileToLoad.replace_extension(".omwgame"); mFileToLoad.replace_extension(".omwgame");

@ -283,7 +283,7 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
: mSavePath (savePath), mContentFiles (std::move(files)), mNew (new_), mData (encoding, fsStrict, dataPaths, archives, resDir), : mSavePath (savePath), mContentFiles (std::move(files)), mNew (new_), mData (encoding, fsStrict, dataPaths, archives, resDir),
mTools (*this, encoding), mTools (*this, encoding),
mProjectPath ((configuration.getUserDataPath() / "projects") / mProjectPath ((configuration.getUserDataPath() / "projects") /
(savePath.filename().string() + ".project")), (savePath.filename().u8string() + u8".project")),
mSavingOperation (*this, mProjectPath, encoding), mSavingOperation (*this, mProjectPath, encoding),
mSaving (&mSavingOperation), mSaving (&mSavingOperation),
mResDir(resDir), mRunner (mProjectPath), mResDir(resDir), mRunner (mProjectPath),
@ -298,7 +298,7 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
std::ofstream destination(mProjectPath, std::ios::out | std::ios::binary); std::ofstream destination(mProjectPath, std::ios::out | std::ios::binary);
if (!destination.is_open()) if (!destination.is_open())
throw std::runtime_error("Can not create project file: " + mProjectPath.string()); throw std::runtime_error("Can not create project file: " + mProjectPath.string()); //TODO(Project579): This will probably break in windows with unicode paths
destination.exceptions(std::ios::failbit | std::ios::badbit); destination.exceptions(std::ios::failbit | std::ios::badbit);
if (!std::filesystem::exists (filtersPath)) if (!std::filesystem::exists (filtersPath))
@ -306,7 +306,7 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
std::ifstream source(filtersPath, std::ios::in | std::ios::binary); std::ifstream source(filtersPath, std::ios::in | std::ios::binary);
if (!source.is_open()) if (!source.is_open())
throw std::runtime_error("Can not read filters file: " + filtersPath.string()); throw std::runtime_error("Can not read filters file: " + filtersPath.string()); //TODO(Project579): This will probably break in windows with unicode paths
source.exceptions(std::ios::failbit | std::ios::badbit); source.exceptions(std::ios::failbit | std::ios::badbit);
destination << source.rdbuf(); destination << source.rdbuf();
@ -484,7 +484,7 @@ void CSMDoc::Document::startRunning (const std::string& profile,
for (std::vector<std::filesystem::path>::const_iterator iter (mContentFiles.begin()); for (std::vector<std::filesystem::path>::const_iterator iter (mContentFiles.begin());
iter!=mContentFiles.end(); ++iter) iter!=mContentFiles.end(); ++iter)
contentFiles.push_back (iter->filename().string()); contentFiles.push_back (iter->filename().string()); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break
mRunner.configure (getData().getDebugProfiles().getRecord (profile).get(), contentFiles, mRunner.configure (getData().getDebugProfiles().getRecord (profile).get(), contentFiles,
startupInstruction); startupInstruction);

@ -93,7 +93,7 @@ void CSMDoc::Loader::load()
iter->second.mRecordsLeft = true; iter->second.mRecordsLeft = true;
iter->second.mRecordsLoaded = 0; iter->second.mRecordsLoaded = 0;
emit nextStage (document, path.filename().string(), steps); emit nextStage (document, path.filename().string(), steps); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break
} }
else if (iter->second.mFile==size) // start loading the last (project) file else if (iter->second.mFile==size) // start loading the last (project) file
{ {

@ -83,7 +83,7 @@ void CSMDoc::Runner::start (bool delayed)
arguments << ("--script-run="+mStartup->fileName()); arguments << ("--script-run="+mStartup->fileName());
arguments << arguments <<
QString::fromUtf8 (("--data=\""+mProjectPath.parent_path().string()+"\"").c_str()); QString::fromUtf8 (("--data=\""+mProjectPath.parent_path().string()+"\"").c_str()); //TODO(Project579): This will probably break in windows with unicode paths
arguments << "--replace=content"; arguments << "--replace=content";
@ -94,7 +94,7 @@ void CSMDoc::Runner::start (bool delayed)
} }
arguments arguments
<< QString::fromUtf8 (("--content="+mProjectPath.filename().string()).c_str()); << QString::fromUtf8 (("--content="+mProjectPath.filename().string()).c_str()); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break
mProcess.start (path, arguments); mProcess.start (path, arguments);
} }

@ -72,7 +72,7 @@ void CSMDoc::WriteHeaderStage::perform (int stage, Messages& messages)
for (std::vector<std::filesystem::path>::const_iterator iter (dependencies.begin()); for (std::vector<std::filesystem::path>::const_iterator iter (dependencies.begin());
iter!=end; ++iter) iter!=end; ++iter)
{ {
std::string name = iter->filename().string(); std::string name = iter->filename().string(); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break
uint64_t size = std::filesystem::file_size (*iter); uint64_t size = std::filesystem::file_size (*iter);
mState.getWriter().addMaster (name, size); mState.getWriter().addMaster (name, size);

@ -34,7 +34,7 @@ void CSMDoc::SavingState::start (Document& document, bool project)
else else
mPath = document.getSavePath(); mPath = document.getSavePath();
std::filesystem::path file (mPath.filename().string() + ".tmp"); std::filesystem::path file (mPath.filename().u8string() + u8".tmp");
mTmpPath = mPath.parent_path(); mTmpPath = mPath.parent_path();

@ -649,7 +649,7 @@ CSMPrefs::State::~State()
void CSMPrefs::State::save() void CSMPrefs::State::save()
{ {
std::filesystem::path user = mConfigurationManager.getUserConfigPath() / mConfigFile; std::filesystem::path user = mConfigurationManager.getUserConfigPath() / mConfigFile;
Settings::Manager::saveUser (user.string()); Settings::Manager::saveUser (user);
} }
CSMPrefs::State::Iterator CSMPrefs::State::begin() CSMPrefs::State::Iterator CSMPrefs::State::begin()

@ -44,7 +44,7 @@ void CSMTools::FinishMergedDocumentStage::perform (int stage, CSMDoc::Messages&
ESM::ESMReader reader; ESM::ESMReader reader;
reader.setEncoder (&mEncoder); reader.setEncoder (&mEncoder);
reader.open (path.string()); reader.open (path);
CSMWorld::MetaData source; CSMWorld::MetaData source;
source.mId = "sys::meta"; source.mId = "sys::meta";

@ -88,7 +88,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, bool fsStrict, const Files::Pat
defines[define.first] = define.second; defines[define.first] = define.second;
mResourceSystem->getSceneManager()->getShaderManager().setGlobalDefines(defines); mResourceSystem->getSceneManager()->getShaderManager().setGlobalDefines(defines);
mResourceSystem->getSceneManager()->setShaderPath((resDir / "shaders").string()); mResourceSystem->getSceneManager()->setShaderPath(resDir / "shaders");
int index = 0; int index = 0;
@ -969,7 +969,7 @@ int CSMWorld::Data::getTotalRecords (const std::vector<std::filesystem::path>& f
if (!std::filesystem::exists(files[i])) if (!std::filesystem::exists(files[i]))
continue; continue;
reader->open(files[i].string()); reader->open(files[i]);
records += reader->getRecordCount(); records += reader->getRecordCount();
reader->close(); reader->close();
} }
@ -989,9 +989,9 @@ int CSMWorld::Data::startLoading (const std::filesystem::path& path, bool base,
mReader = new ESM::ESMReader; mReader = new ESM::ESMReader;
mReader->setEncoder (&mEncoder); mReader->setEncoder (&mEncoder);
mReader->setIndex((project || !base) ? 0 : mReaderIndex++); mReader->setIndex((project || !base) ? 0 : mReaderIndex++);
mReader->open (path.string()); mReader->open (path);
mContentFileNames.insert(std::make_pair(path.filename().string(), mReader->getIndex())); mContentFileNames.insert(std::make_pair(path.filename().string(), mReader->getIndex())); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break
mBase = base; mBase = base;
mProject = project; mProject = project;

@ -68,14 +68,14 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon)
} }
else else
{ {
std::filesystem::path path (name.toUtf8().data()); std::filesystem::path path (name.toUtf8().data()); //TODO(Project579): Replace with char8_t in C++20
std::string extension = Misc::StringUtils::lowerCase(path.extension().string()); std::string extension = Misc::StringUtils::lowerCase(path.extension().string()); //TODO(Project579): let's hope unicode characters are never used in these extensions on windows or this will break
bool isLegacyPath = (extension == ".esm" || bool isLegacyPath = (extension == ".esm" ||
extension == ".esp"); extension == ".esp");
bool isFilePathChanged = (path.parent_path().string() != mLocalData.string()); bool isFilePathChanged = (path.parent_path() != mLocalData);
if (isLegacyPath) if (isLegacyPath)
path.replace_extension (addon ? ".omwaddon" : ".omwgame"); path.replace_extension (addon ? ".omwaddon" : ".omwgame");
@ -85,7 +85,7 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon)
if (!isFilePathChanged && !isLegacyPath) if (!isFilePathChanged && !isLegacyPath)
{ {
// path already points to the local data directory // path already points to the local data directory
message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str()); message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str()); //TODO(Project579): This is probably broken on windows with unicode paths
mResultPath = path; mResultPath = path;
} }
//in all other cases, ensure the path points to data-local and do an existing file check //in all other cases, ensure the path points to data-local and do an existing file check
@ -95,7 +95,7 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon)
if (isFilePathChanged) if (isFilePathChanged)
path = mLocalData / path.filename(); path = mLocalData / path.filename();
message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str()); message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str()); //TODO(Project579): This is probably broken on windows with unicode paths
mResultPath = path; mResultPath = path;
if (std::filesystem::exists (path)) if (std::filesystem::exists (path))

@ -19,7 +19,7 @@ void CSVDoc::LoadingDocument::closeEvent (QCloseEvent *event)
CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document)
: mDocument (document), mTotalRecordsLabel (0), mRecordsLabel (0), mAborted (false), mMessages (nullptr), mRecords(0) : mDocument (document), mTotalRecordsLabel (0), mRecordsLabel (0), mAborted (false), mMessages (nullptr), mRecords(0)
{ {
setWindowTitle (QString::fromUtf8((std::string("Opening ") + document->getSavePath().filename().string()).c_str())); setWindowTitle (QString::fromUtf8((std::string("Opening ") + document->getSavePath().filename().string()).c_str())); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break
setMinimumWidth (400); setMinimumWidth (400);

@ -387,7 +387,7 @@ void CSVDoc::View::updateTitle()
{ {
std::ostringstream stream; std::ostringstream stream;
stream << mDocument->getSavePath().filename().string(); stream << mDocument->getSavePath().filename().string(); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break
if (mDocument->getState() & CSMDoc::State_Modified) if (mDocument->getState() & CSMDoc::State_Modified)
stream << " *"; stream << " *";
@ -747,7 +747,7 @@ void CSVDoc::View::tutorial()
void CSVDoc::View::infoAbout() void CSVDoc::View::infoAbout()
{ {
// Get current OpenMW version // Get current OpenMW version
QString versionInfo = (Version::getOpenmwVersionDescription(mDocument->getResourceDir().string())+ QString versionInfo = (Version::getOpenmwVersionDescription(mDocument->getResourceDir())+
#if defined(__x86_64__) || defined(_M_X64) #if defined(__x86_64__) || defined(_M_X64)
" (64-bit)").c_str(); " (64-bit)").c_str();
#else #else

@ -261,7 +261,7 @@ bool CSVDoc::ViewManager::showModifiedDocumentMessageBox (CSVDoc::View *view)
QMessageBox messageBox(view); QMessageBox messageBox(view);
CSMDoc::Document *document = view->getDocument(); CSMDoc::Document *document = view->getDocument();
messageBox.setWindowTitle (QString::fromUtf8(document->getSavePath().filename().string().c_str())); messageBox.setWindowTitle (QString::fromUtf8(document->getSavePath().filename().string().c_str())); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break
messageBox.setText ("The document has been modified."); messageBox.setText ("The document has been modified.");
messageBox.setInformativeText ("Do you want to save your changes?"); messageBox.setInformativeText ("Do you want to save your changes?");
messageBox.setStandardButtons (QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); messageBox.setStandardButtons (QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);

@ -102,7 +102,7 @@ void CSVTools::Merge::configure (CSMDoc::Document *document)
for (std::vector<std::filesystem::path>::const_iterator iter (files.begin()); for (std::vector<std::filesystem::path>::const_iterator iter (files.begin());
iter!=files.end(); ++iter) iter!=files.end(); ++iter)
mFiles->addItem (QString::fromUtf8 (iter->filename().string().c_str())); mFiles->addItem (QString::fromUtf8 (iter->filename().string().c_str())); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break
} }
void CSVTools::Merge::setLocalData (const std::filesystem::path& localData) void CSVTools::Merge::setLocalData (const std::filesystem::path& localData)

@ -528,7 +528,7 @@ void OMW::Engine::enableFSStrict(bool fsStrict)
void OMW::Engine::setDataDirs (const Files::PathContainer& dataDirs) void OMW::Engine::setDataDirs (const Files::PathContainer& dataDirs)
{ {
mDataDirs = dataDirs; mDataDirs = dataDirs;
mDataDirs.insert(mDataDirs.begin(), (mResDir / "vfs")); mDataDirs.insert(mDataDirs.begin(), mResDir / "vfs");
mFileCollections = Files::Collections (mDataDirs, !mFSStrict); mFileCollections = Files::Collections (mDataDirs, !mFSStrict);
} }
@ -708,10 +708,10 @@ void OMW::Engine::createWindow()
void OMW::Engine::setWindowIcon() void OMW::Engine::setWindowIcon()
{ {
std::ifstream windowIconStream; std::ifstream windowIconStream;
std::string windowIcon = (mResDir / "openmw.png").string(); const auto windowIcon = mResDir / "openmw.png";
windowIconStream.open(windowIcon, std::ios_base::in | std::ios_base::binary); windowIconStream.open(windowIcon, std::ios_base::in | std::ios_base::binary);
if (windowIconStream.fail()) if (windowIconStream.fail())
Log(Debug::Error) << "Error: Failed to open " << windowIcon; Log(Debug::Error) << "Error: Failed to open " << windowIcon; //TODO(Project579): This will probably break in windows with unicode paths
osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension("png"); osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension("png");
if (!reader) if (!reader)
{ {
@ -720,7 +720,7 @@ void OMW::Engine::setWindowIcon()
} }
osgDB::ReaderWriter::ReadResult result = reader->readImage(windowIconStream); osgDB::ReaderWriter::ReadResult result = reader->readImage(windowIconStream);
if (!result.success()) if (!result.success())
Log(Debug::Error) << "Error: Failed to read " << windowIcon << ": " << result.message() << " code " << result.status(); Log(Debug::Error) << "Error: Failed to read " << windowIcon << ": " << result.message() << " code " << result.status(); //TODO(Project579): This will probably break in windows with unicode paths
else else
{ {
osg::ref_ptr<osg::Image> image = result.getImage(); osg::ref_ptr<osg::Image> image = result.getImage();
@ -765,7 +765,7 @@ void OMW::Engine::prepareEngine()
mScreenCaptureOperation = new SceneUtil::AsyncScreenCaptureOperation( mScreenCaptureOperation = new SceneUtil::AsyncScreenCaptureOperation(
mWorkQueue, mWorkQueue,
new SceneUtil::WriteScreenshotToFileOperation( new SceneUtil::WriteScreenshotToFileOperation(
mCfgMgr.getScreenshotPath().string(), mCfgMgr.getScreenshotPath(),
Settings::Manager::getString("screenshot format", "General"), Settings::Manager::getString("screenshot format", "General"),
Settings::Manager::getBool("notify on saved screenshot", "General") Settings::Manager::getBool("notify on saved screenshot", "General")
? std::function<void (std::string)>(ScheduleNonDialogMessageBox {}) ? std::function<void (std::string)>(ScheduleNonDialogMessageBox {})
@ -777,35 +777,34 @@ void OMW::Engine::prepareEngine()
mViewer->addEventHandler(mScreenCaptureHandler); mViewer->addEventHandler(mScreenCaptureHandler);
mLuaManager = std::make_unique<MWLua::LuaManager>(mVFS.get(), (mResDir / "lua_libs").string()); mLuaManager = std::make_unique<MWLua::LuaManager>(mVFS.get(), mResDir / "lua_libs");
mEnvironment.setLuaManager(*mLuaManager); mEnvironment.setLuaManager(*mLuaManager);
// Create input and UI first to set up a bootstrapping environment for // Create input and UI first to set up a bootstrapping environment for
// showing a loading screen and keeping the window responsive while doing so // showing a loading screen and keeping the window responsive while doing so
std::string keybinderUser = (mCfgMgr.getUserConfigPath() / "input_v3.xml").string(); const auto keybinderUser = mCfgMgr.getUserConfigPath() / "input_v3.xml";
bool keybinderUserExists = std::filesystem::exists(keybinderUser); bool keybinderUserExists = std::filesystem::exists(keybinderUser);
if(!keybinderUserExists) if(!keybinderUserExists)
{ {
std::string input2 = (mCfgMgr.getUserConfigPath() / "input_v2.xml").string(); const auto input2 = (mCfgMgr.getUserConfigPath() / "input_v2.xml");
if(std::filesystem::exists(input2)) { if(std::filesystem::exists(input2)) {
std::filesystem::copy_file(input2, keybinderUser); keybinderUserExists = std::filesystem::copy_file(input2, keybinderUser);
keybinderUserExists = std::filesystem::exists(keybinderUser); Log(Debug::Info) << "Loading keybindings file: " << keybinderUser; //TODO(Project579): This will probably break in windows with unicode paths
Log(Debug::Info) << "Loading keybindings file: " << keybinderUser;
} }
} }
else else
Log(Debug::Info) << "Loading keybindings file: " << keybinderUser; Log(Debug::Info) << "Loading keybindings file: " << keybinderUser; //TODO(Project579): This will probably break in windows with unicode paths
const std::string userdefault = mCfgMgr.getUserConfigPath().string() + "/gamecontrollerdb.txt"; const auto userdefault = mCfgMgr.getUserConfigPath() / "gamecontrollerdb.txt";
const std::string localdefault = mCfgMgr.getLocalPath().string() + "/gamecontrollerdb.txt"; const auto localdefault = mCfgMgr.getLocalPath() / "gamecontrollerdb.txt";
const std::string globaldefault = mCfgMgr.getGlobalPath().string() + "/gamecontrollerdb.txt"; const auto globaldefault = mCfgMgr.getGlobalPath() / "gamecontrollerdb.txt";
std::string userGameControllerdb; std::filesystem::path userGameControllerdb;
if (std::filesystem::exists(userdefault)) if (std::filesystem::exists(userdefault))
userGameControllerdb = userdefault; userGameControllerdb = userdefault;
std::string gameControllerdb; std::filesystem::path gameControllerdb;
if (std::filesystem::exists(localdefault)) if (std::filesystem::exists(localdefault))
gameControllerdb = localdefault; gameControllerdb = localdefault;
else if (std::filesystem::exists(globaldefault)) else if (std::filesystem::exists(globaldefault))
@ -813,7 +812,7 @@ void OMW::Engine::prepareEngine()
//else if it doesn't exist, pass in an empty string //else if it doesn't exist, pass in an empty string
// gui needs our shaders path before everything else // gui needs our shaders path before everything else
mResourceSystem->getSceneManager()->setShaderPath((mResDir / "shaders").string()); mResourceSystem->getSceneManager()->setShaderPath(mResDir / "shaders");
osg::ref_ptr<osg::GLExtensions> exts = osg::GLExtensions::Get(0, false); osg::ref_ptr<osg::GLExtensions> exts = osg::GLExtensions::Get(0, false);
bool shadersSupported = exts && (exts->glslLanguageVersion >= 1.2f); bool shadersSupported = exts && (exts->glslLanguageVersion >= 1.2f);
@ -831,9 +830,9 @@ void OMW::Engine::prepareEngine()
rootNode->addChild(guiRoot); rootNode->addChild(guiRoot);
mWindowManager = std::make_unique<MWGui::WindowManager>(mWindow, mViewer, guiRoot, mResourceSystem.get(), mWorkQueue.get(), mWindowManager = std::make_unique<MWGui::WindowManager>(mWindow, mViewer, guiRoot, mResourceSystem.get(), mWorkQueue.get(),
mCfgMgr.getLogPath().string() + std::string("/"), mCfgMgr.getLogPath(),
mScriptConsoleMode, mTranslationDataStorage, mEncoding, mScriptConsoleMode, mTranslationDataStorage, mEncoding,
Version::getOpenmwVersionDescription(mResDir.string()), shadersSupported); Version::getOpenmwVersionDescription(mResDir), shadersSupported);
mEnvironment.setWindowManager(*mWindowManager); mEnvironment.setWindowManager(*mWindowManager);
mInputManager = std::make_unique<MWInput::InputManager>(mWindow, mViewer, mScreenCaptureHandler, mInputManager = std::make_unique<MWInput::InputManager>(mWindow, mViewer, mScreenCaptureHandler,
@ -854,7 +853,7 @@ void OMW::Engine::prepareEngine()
// Create the world // Create the world
mWorld = std::make_unique<MWWorld::World>(mViewer, rootNode, mResourceSystem.get(), mWorkQueue.get(), *mUnrefQueue, mWorld = std::make_unique<MWWorld::World>(mViewer, rootNode, mResourceSystem.get(), mWorkQueue.get(), *mUnrefQueue,
mFileCollections, mContentFiles, mGroundcoverFiles, mEncoder.get(), mActivationDistanceOverride, mCellName, mFileCollections, mContentFiles, mGroundcoverFiles, mEncoder.get(), mActivationDistanceOverride, mCellName,
mStartupScript, mResDir.string(), mCfgMgr.getUserDataPath().string()); mStartupScript, mResDir, mCfgMgr.getUserDataPath());
mWorld->setupPlayer(); mWorld->setupPlayer();
mWorld->setRandomSeed(mRandomSeed); mWorld->setRandomSeed(mRandomSeed);
mEnvironment.setWorld(*mWorld); mEnvironment.setWorld(*mWorld);
@ -865,8 +864,8 @@ void OMW::Engine::prepareEngine()
//Load translation data //Load translation data
mTranslationDataStorage.setEncoder(mEncoder.get()); mTranslationDataStorage.setEncoder(mEncoder.get());
for (size_t i = 0; i < mContentFiles.size(); i++) for (auto & mContentFile : mContentFiles)
mTranslationDataStorage.loadTranslationData(mFileCollections, mContentFiles[i]); mTranslationDataStorage.loadTranslationData(mFileCollections, mContentFile);
Compiler::registerExtensions (mExtensions); Compiler::registerExtensions (mExtensions);
@ -910,7 +909,7 @@ void OMW::Engine::prepareEngine()
} }
mLuaManager->init(); mLuaManager->init();
mLuaManager->loadPermanentStorage(mCfgMgr.getUserConfigPath().string()); mLuaManager->loadPermanentStorage(mCfgMgr.getUserConfigPath());
} }
class OMW::Engine::LuaWorker class OMW::Engine::LuaWorker
@ -1014,7 +1013,7 @@ void OMW::Engine::go()
Misc::Rng::init(mRandomSeed); Misc::Rng::init(mRandomSeed);
Settings::ShaderManager::get().load((mCfgMgr.getUserConfigPath() / "shaders.yaml").string()); Settings::ShaderManager::get().load(mCfgMgr.getUserConfigPath() / "shaders.yaml");
MWClass::registerClasses(); MWClass::registerClasses();
@ -1033,13 +1032,13 @@ void OMW::Engine::go()
prepareEngine(); prepareEngine();
std::ofstream stats; std::ofstream stats;
if (const auto path = std::getenv("OPENMW_OSG_STATS_FILE")) if (const auto path = std::getenv("OPENMW_OSG_STATS_FILE")) //TODO(Project579): This will probably break in windows with unicode paths
{ {
stats.open(path, std::ios_base::out); stats.open(path, std::ios_base::out); //TODO(Project579): This will probably break in windows with unicode paths
if (stats.is_open()) if (stats.is_open())
Log(Debug::Info) << "Stats will be written to: " << path; Log(Debug::Info) << "Stats will be written to: " << path; //TODO(Project579): This will probably break in windows with unicode paths
else else
Log(Debug::Warning) << "Failed to open file for stats: " << path; Log(Debug::Warning) << "Failed to open file for stats: " << path; //TODO(Project579): This will probably break in windows with unicode paths
} }
// Setup profiler // Setup profiler
@ -1136,9 +1135,9 @@ void OMW::Engine::go()
luaWorker.join(); luaWorker.join();
// Save user settings // Save user settings
Settings::Manager::saveUser((mCfgMgr.getUserConfigPath() / "settings.cfg").string()); Settings::Manager::saveUser(mCfgMgr.getUserConfigPath() / "settings.cfg");
Settings::ShaderManager::get().save(); Settings::ShaderManager::get().save();
mLuaManager->savePermanentStorage(mCfgMgr.getUserConfigPath().string()); mLuaManager->savePermanentStorage(mCfgMgr.getUserConfigPath());
Log(Debug::Info) << "Quitting peacefully."; Log(Debug::Info) << "Quitting peacefully.";
} }
@ -1193,7 +1192,7 @@ void OMW::Engine::setScriptBlacklistUse (bool use)
mScriptBlacklistUse = use; mScriptBlacklistUse = use;
} }
void OMW::Engine::setSaveGameFile(const std::string &savegame) void OMW::Engine::setSaveGameFile(const std::filesystem::path &savegame)
{ {
mSaveGameFile = savegame; mSaveGameFile = savegame;
} }

@ -158,7 +158,7 @@ namespace OMW
bool mScriptConsoleMode; bool mScriptConsoleMode;
std::string mStartupScript; std::string mStartupScript;
int mActivationDistanceOverride; int mActivationDistanceOverride;
std::string mSaveGameFile; std::filesystem::path mSaveGameFile;
// Grab mouse? // Grab mouse?
bool mGrab; bool mGrab;
@ -256,7 +256,7 @@ namespace OMW
void setScriptBlacklistUse (bool use); void setScriptBlacklistUse (bool use);
/// Set the save game file to load after initialising the engine. /// Set the save game file to load after initialising the engine.
void setSaveGameFile(const std::string& savegame); void setSaveGameFile(const std::filesystem::path &savegame);
void setRandomSeed(unsigned int seed); void setRandomSeed(unsigned int seed);

@ -61,7 +61,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
{ {
cfgMgr.readConfiguration(variables, desc, true); cfgMgr.readConfiguration(variables, desc, true);
Version::Version v = Version::getOpenmwVersion(variables["resources"].as<Files::MaybeQuotedPath>().string()); Version::Version v = Version::getOpenmwVersion(variables["resources"].as<Files::MaybeQuotedPath>());
getRawStdout() << v.describe() << std::endl; getRawStdout() << v.describe() << std::endl;
return false; return false;
} }
@ -69,10 +69,10 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
cfgMgr.readConfiguration(variables, desc); cfgMgr.readConfiguration(variables, desc);
Settings::Manager::load(cfgMgr); Settings::Manager::load(cfgMgr);
setupLogging(cfgMgr.getLogPath().string(), "OpenMW"); setupLogging(cfgMgr.getLogPath(), "OpenMW");
MWGui::DebugWindow::startLogRecording(); MWGui::DebugWindow::startLogRecording();
Version::Version v = Version::getOpenmwVersion(variables["resources"].as<Files::MaybeQuotedPath>().string()); Version::Version v = Version::getOpenmwVersion(variables["resources"].as<Files::MaybeQuotedPath>());
Log(Debug::Info) << v.describe(); Log(Debug::Info) << v.describe();
engine.setGrabMouse(!variables["no-grab"].as<bool>()); engine.setGrabMouse(!variables["no-grab"].as<bool>());
@ -150,7 +150,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
engine.setWarningsMode (variables["script-warn"].as<int>()); engine.setWarningsMode (variables["script-warn"].as<int>());
engine.setScriptBlacklist (variables["script-blacklist"].as<StringsVector>()); engine.setScriptBlacklist (variables["script-blacklist"].as<StringsVector>());
engine.setScriptBlacklistUse (variables["script-blacklist-use"].as<bool>()); engine.setScriptBlacklistUse (variables["script-blacklist-use"].as<bool>());
engine.setSaveGameFile (variables["load-savegame"].as<Files::MaybeQuotedPath>().string()); engine.setSaveGameFile (variables["load-savegame"].as<Files::MaybeQuotedPath>());
// other settings // other settings
Fallback::Map::init(variables["fallback"].as<FallbackMap>().mMap); Fallback::Map::init(variables["fallback"].as<FallbackMap>().mMap);

@ -62,12 +62,12 @@ namespace MWBase
/// ///
/// \note Slot must belong to the current character. /// \note Slot must belong to the current character.
virtual void loadGame (const std::string& filepath) = 0; virtual void loadGame (const std::filesystem::path &filepath) = 0;
///< Load a saved game directly from the given file path. This will search the CharacterManager ///< Load a saved game directly from the given file path. This will search the CharacterManager
/// for a Character containing this save file, and set this Character current if one was found. /// for a Character containing this save file, and set this Character current if one was found.
/// Otherwise, a new Character will be created. /// Otherwise, a new Character will be created.
virtual void loadGame (const MWState::Character *character, const std::string& filepath) = 0; virtual void loadGame (const MWState::Character *character, const std::filesystem::path &filepath) = 0;
///< Load a saved game file belonging to the given character. ///< Load a saved game file belonging to the given character.
///Simple saver, writes over the file if already existing ///Simple saver, writes over the file if already existing

@ -639,7 +639,7 @@ namespace MWBase
/// Export scene graph to a file and return the filename. /// Export scene graph to a file and return the filename.
/// \param ptr object to export scene graph for (if empty, export entire scene graph) /// \param ptr object to export scene graph for (if empty, export entire scene graph)
virtual std::string exportSceneGraph(const MWWorld::Ptr& ptr) = 0; virtual std::filesystem::path exportSceneGraph(const MWWorld::Ptr& ptr) = 0;
/// Preload VFX associated with this effect list /// Preload VFX associated with this effect list
virtual void preloadEffects(const ESM::EffectList* effectList) = 0; virtual void preloadEffects(const ESM::EffectList* effectList) = 0;

@ -200,7 +200,7 @@ namespace MWGui
if (mCurrentCharacter == &*it || if (mCurrentCharacter == &*it ||
(!mCurrentCharacter && !mSaving && directory==Misc::StringUtils::lowerCase ( (!mCurrentCharacter && !mSaving && directory==Misc::StringUtils::lowerCase (
it->begin()->mPath.parent_path().filename().string()))) it->begin()->mPath.parent_path().filename().string()))) //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break
{ {
mCurrentCharacter = &*it; mCurrentCharacter = &*it;
selectedIndex = mCharacterSelection->getItemCount()-1; selectedIndex = mCharacterSelection->getItemCount()-1;
@ -303,7 +303,7 @@ namespace MWGui
else else
{ {
assert (mCurrentCharacter && mCurrentSlot); assert (mCurrentCharacter && mCurrentSlot);
MWBase::Environment::get().getStateManager()->loadGame (mCurrentCharacter, mCurrentSlot->mPath.string()); MWBase::Environment::get().getStateManager()->loadGame (mCurrentCharacter, mCurrentSlot->mPath);
} }
} }

@ -120,7 +120,7 @@ namespace MWGui
{ {
WindowManager::WindowManager( WindowManager::WindowManager(
SDL_Window* window, osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue, SDL_Window* window, osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
const std::string& logpath, bool consoleOnlyScripts, Translation::Storage& translationDataStorage, const std::filesystem::path& logpath, bool consoleOnlyScripts, Translation::Storage& translationDataStorage,
ToUTF8::FromType encoding, const std::string& versionDescription, bool useShaders) ToUTF8::FromType encoding, const std::string& versionDescription, bool useShaders)
: mOldUpdateMask(0) : mOldUpdateMask(0)
, mOldCullMask(0) , mOldCullMask(0)
@ -180,7 +180,7 @@ namespace MWGui
mScalingFactor = std::clamp(Settings::Manager::getFloat("scaling factor", "GUI"), 0.5f, 8.f); mScalingFactor = std::clamp(Settings::Manager::getFloat("scaling factor", "GUI"), 0.5f, 8.f);
mGuiPlatform = std::make_unique<osgMyGUI::Platform>(viewer, guiRoot, resourceSystem->getImageManager(), mGuiPlatform = std::make_unique<osgMyGUI::Platform>(viewer, guiRoot, resourceSystem->getImageManager(),
resourceSystem->getVFS(), mScalingFactor, "mygui", resourceSystem->getVFS(), mScalingFactor, "mygui",
(std::filesystem::path(logpath) / "MyGUI.log").generic_string()); logpath / "MyGUI.log");
mGui = std::make_unique<MyGUI::Gui>(); mGui = std::make_unique<MyGUI::Gui>();
mGui->initialise(""); mGui->initialise("");

@ -37,6 +37,7 @@
#include <MyGUI_Gui.h> #include <MyGUI_Gui.h>
#include <MyGUI_KeyCode.h> #include <MyGUI_KeyCode.h>
#include <MyGUI_Types.h> #include <MyGUI_Types.h>
#include <filesystem>
namespace MyGUI namespace MyGUI
{ {
@ -124,7 +125,7 @@ namespace MWGui
typedef std::vector<Faction> FactionList; typedef std::vector<Faction> FactionList;
WindowManager(SDL_Window* window, osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue, WindowManager(SDL_Window* window, osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
const std::string& logpath, bool consoleOnlyScripts, Translation::Storage& translationDataStorage, const std::filesystem::path& logpath, bool consoleOnlyScripts, Translation::Storage& translationDataStorage,
ToUTF8::FromType encoding, const std::string& versionDescription, bool useShaders); ToUTF8::FromType encoding, const std::string& versionDescription, bool useShaders);
virtual ~WindowManager(); virtual ~WindowManager();

@ -43,8 +43,8 @@ namespace MWInput
class InputControlSystem : public ICS::InputControlSystem class InputControlSystem : public ICS::InputControlSystem
{ {
public: public:
InputControlSystem(const std::string& bindingsFile) InputControlSystem(const std::filesystem::path &bindingsFile)
: ICS::InputControlSystem(bindingsFile, true, nullptr, nullptr, A_Last) : ICS::InputControlSystem(bindingsFile.string(), true, nullptr, nullptr, A_Last) //TODO(Project579): This is probably broken on windows with unicode paths
{ {
} }
}; };
@ -167,11 +167,11 @@ namespace MWInput
bool mDetectingKeyboard; bool mDetectingKeyboard;
}; };
BindingsManager::BindingsManager(const std::string& userFile, bool userFileExists) BindingsManager::BindingsManager(const std::filesystem::path &userFile, bool userFileExists)
: mUserFile(userFile) : mUserFile(userFile)
, mDragDrop(false) , mDragDrop(false)
{ {
std::string file = userFileExists ? userFile : ""; const auto file = userFileExists ? userFile : std::filesystem::path();
mInputBinder = std::make_unique<InputControlSystem>(file); mInputBinder = std::make_unique<InputControlSystem>(file);
mListener = std::make_unique<BindingsListener>(mInputBinder.get(), this); mListener = std::make_unique<BindingsListener>(mInputBinder.get(), this);
mInputBinder->setDetectingBindingListener(mListener.get()); mInputBinder->setDetectingBindingListener(mListener.get());
@ -192,7 +192,7 @@ namespace MWInput
BindingsManager::~BindingsManager() BindingsManager::~BindingsManager()
{ {
mInputBinder->save(mUserFile); mInputBinder->save(mUserFile.string()); //TODO(Project579): This will probably break in windows with unicode paths
} }
void BindingsManager::update(float dt) void BindingsManager::update(float dt)

@ -4,6 +4,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#include <filesystem>
#include <components/sdlutil/events.hpp> #include <components/sdlutil/events.hpp>
@ -15,7 +16,7 @@ namespace MWInput
class BindingsManager class BindingsManager
{ {
public: public:
BindingsManager(const std::string& userFile, bool userFileExists); BindingsManager(const std::filesystem::path &userFile, bool userFileExists);
virtual ~BindingsManager(); virtual ~BindingsManager();
@ -70,7 +71,7 @@ namespace MWInput
std::unique_ptr<InputControlSystem> mInputBinder; std::unique_ptr<InputControlSystem> mInputBinder;
std::unique_ptr<BindingsListener> mListener; std::unique_ptr<BindingsListener> mListener;
std::string mUserFile; std::filesystem::path mUserFile;
bool mDragDrop; bool mDragDrop;
}; };

@ -27,8 +27,8 @@ namespace MWInput
ControllerManager::ControllerManager(BindingsManager* bindingsManager, ControllerManager::ControllerManager(BindingsManager* bindingsManager,
ActionManager* actionManager, ActionManager* actionManager,
MouseManager* mouseManager, MouseManager* mouseManager,
const std::string& userControllerBindingsFile, const std::filesystem::path &userControllerBindingsFile,
const std::string& controllerBindingsFile) const std::filesystem::path &controllerBindingsFile)
: mBindingsManager(bindingsManager) : mBindingsManager(bindingsManager)
, mActionManager(actionManager) , mActionManager(actionManager)
, mMouseManager(mouseManager) , mMouseManager(mouseManager)
@ -43,12 +43,12 @@ namespace MWInput
{ {
if (!controllerBindingsFile.empty()) if (!controllerBindingsFile.empty())
{ {
SDL_GameControllerAddMappingsFromFile(controllerBindingsFile.c_str()); SDL_GameControllerAddMappingsFromFile(controllerBindingsFile.string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths
} }
if (!userControllerBindingsFile.empty()) if (!userControllerBindingsFile.empty())
{ {
SDL_GameControllerAddMappingsFromFile(userControllerBindingsFile.c_str()); SDL_GameControllerAddMappingsFromFile(userControllerBindingsFile.string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths
} }
// Open all presently connected sticks // Open all presently connected sticks

@ -5,6 +5,7 @@
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
#include <components/sdlutil/events.hpp> #include <components/sdlutil/events.hpp>
#include <filesystem>
namespace MWInput namespace MWInput
{ {
@ -18,8 +19,8 @@ namespace MWInput
ControllerManager(BindingsManager* bindingsManager, ControllerManager(BindingsManager* bindingsManager,
ActionManager* actionManager, ActionManager* actionManager,
MouseManager* mouseManager, MouseManager* mouseManager,
const std::string& userControllerBindingsFile, const std::filesystem::path &userControllerBindingsFile,
const std::string& controllerBindingsFile); const std::filesystem::path &controllerBindingsFile);
virtual ~ControllerManager() = default; virtual ~ControllerManager() = default;

@ -28,8 +28,8 @@ namespace MWInput
osg::ref_ptr<osgViewer::Viewer> viewer, osg::ref_ptr<osgViewer::Viewer> viewer,
osg::ref_ptr<osgViewer::ScreenCaptureHandler> screenCaptureHandler, osg::ref_ptr<osgViewer::ScreenCaptureHandler> screenCaptureHandler,
osgViewer::ScreenCaptureHandler::CaptureOperation *screenCaptureOperation, osgViewer::ScreenCaptureHandler::CaptureOperation *screenCaptureOperation,
const std::string& userFile, bool userFileExists, const std::string& userControllerBindingsFile, const std::filesystem::path &userFile, bool userFileExists, const std::filesystem::path &userControllerBindingsFile,
const std::string& controllerBindingsFile, bool grab) const std::filesystem::path &controllerBindingsFile, bool grab)
: mControlsDisabled(false) : mControlsDisabled(false)
, mInputWrapper(std::make_unique<SDLUtil::InputWrapper>(window, viewer, grab)) , mInputWrapper(std::make_unique<SDLUtil::InputWrapper>(window, viewer, grab))
, mBindingsManager(std::make_unique<BindingsManager>(userFile, userFileExists)) , mBindingsManager(std::make_unique<BindingsManager>(userFile, userFileExists))

@ -8,6 +8,7 @@
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
#include <components/sdlutil/events.hpp> #include <components/sdlutil/events.hpp>
#include <filesystem>
#include "../mwbase/inputmanager.hpp" #include "../mwbase/inputmanager.hpp"
@ -52,9 +53,9 @@ namespace MWInput
osg::ref_ptr<osgViewer::Viewer> viewer, osg::ref_ptr<osgViewer::Viewer> viewer,
osg::ref_ptr<osgViewer::ScreenCaptureHandler> screenCaptureHandler, osg::ref_ptr<osgViewer::ScreenCaptureHandler> screenCaptureHandler,
osgViewer::ScreenCaptureHandler::CaptureOperation *screenCaptureOperation, osgViewer::ScreenCaptureHandler::CaptureOperation *screenCaptureOperation,
const std::string& userFile, bool userFileExists, const std::filesystem::path &userFile, bool userFileExists,
const std::string& userControllerBindingsFile, const std::filesystem::path &userControllerBindingsFile,
const std::string& controllerBindingsFile, bool grab); const std::filesystem::path &controllerBindingsFile, bool grab);
~InputManager() final; ~InputManager() final;

@ -31,7 +31,7 @@
namespace MWLua namespace MWLua
{ {
LuaManager::LuaManager(const VFS::Manager* vfs, const std::string& libsDir) LuaManager::LuaManager(const VFS::Manager* vfs, const std::filesystem::path &libsDir)
: mLua(vfs, &mConfiguration) : mLua(vfs, &mConfiguration)
, mUiResourceManager(vfs) , mUiResourceManager(vfs)
, mL10n(vfs, &mLua) , mL10n(vfs, &mLua)
@ -110,21 +110,20 @@ namespace MWLua
return mL10n.translate(contextName, key); return mL10n.translate(contextName, key);
} }
void LuaManager::loadPermanentStorage(const std::string& userConfigPath) void LuaManager::loadPermanentStorage(const std::filesystem::path &userConfigPath)
{ {
auto globalPath = std::filesystem::path(userConfigPath) / "global_storage.bin"; const auto globalPath = userConfigPath / "global_storage.bin";
auto playerPath = std::filesystem::path(userConfigPath) / "player_storage.bin"; const auto playerPath = userConfigPath / "player_storage.bin";
if (std::filesystem::exists(globalPath)) if (std::filesystem::exists(globalPath))
mGlobalStorage.load(globalPath.string()); mGlobalStorage.load(globalPath);
if (std::filesystem::exists(playerPath)) if (std::filesystem::exists(playerPath))
mPlayerStorage.load(playerPath.string()); mPlayerStorage.load(playerPath);
} }
void LuaManager::savePermanentStorage(const std::string& userConfigPath) void LuaManager::savePermanentStorage(const std::filesystem::path &userConfigPath)
{ {
std::filesystem::path confDir(userConfigPath); mGlobalStorage.save(userConfigPath / "global_storage.bin");
mGlobalStorage.save((confDir / "global_storage.bin").string()); mPlayerStorage.save(userConfigPath / "player_storage.bin");
mPlayerStorage.save((confDir / "player_storage.bin").string());
} }
void LuaManager::update() void LuaManager::update()

@ -11,6 +11,7 @@
#include <components/lua_ui/resources.hpp> #include <components/lua_ui/resources.hpp>
#include <components/misc/color.hpp> #include <components/misc/color.hpp>
#include <filesystem>
#include "../mwbase/luamanager.hpp" #include "../mwbase/luamanager.hpp"
@ -26,7 +27,7 @@ namespace MWLua
class LuaManager : public MWBase::LuaManager class LuaManager : public MWBase::LuaManager
{ {
public: public:
LuaManager(const VFS::Manager* vfs, const std::string& libsDir); LuaManager(const VFS::Manager* vfs, const std::filesystem::path &libsDir);
// Called by engine.cpp before UI setup. // Called by engine.cpp before UI setup.
void initL10n(); void initL10n();
@ -34,8 +35,8 @@ namespace MWLua
// Called by engine.cpp when the environment is fully initialized. // Called by engine.cpp when the environment is fully initialized.
void init(); void init();
void loadPermanentStorage(const std::string& userConfigPath); void loadPermanentStorage(const std::filesystem::path &userConfigPath);
void savePermanentStorage(const std::string& userConfigPath); void savePermanentStorage(const std::filesystem::path &userConfigPath);
// Called by engine.cpp every frame. For performance reasons it works in a separate // Called by engine.cpp every frame. For performance reasons it works in a separate
// thread (in parallel with osg Cull). Can not use scene graph. // thread (in parallel with osg Cull). Can not use scene graph.

@ -218,11 +218,11 @@ namespace MWRender
for (const auto& name : mVFS->getRecursiveDirectoryIterator(fx::Technique::sSubdir)) for (const auto& name : mVFS->getRecursiveDirectoryIterator(fx::Technique::sSubdir))
{ {
std::filesystem::path path = name; std::filesystem::path path = name;
std::string fileExt = Misc::StringUtils::lowerCase(path.extension().string()); std::string fileExt = Misc::StringUtils::lowerCase(path.extension().string()); //TODO(Project579): let's hope unicode characters are never used in these extensions on windows or this will break
if (!path.parent_path().has_parent_path() && fileExt == fx::Technique::sExt) if (!path.parent_path().has_parent_path() && fileExt == fx::Technique::sExt)
{ {
auto absolutePath = std::filesystem::path(mVFS->getAbsoluteFileName(name)); const auto absolutePath = mVFS->getAbsoluteFileName(name); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break
mTechniqueFileMap[absolutePath.stem().string()] = absolutePath; mTechniqueFileMap[absolutePath.stem().string()] = absolutePath; //TODO(Project579): This will probably break in windows with unicode paths
} }
} }
} }
@ -387,7 +387,7 @@ namespace MWRender
std::this_thread::sleep_for(std::chrono::milliseconds(5)); std::this_thread::sleep_for(std::chrono::milliseconds(5));
if (technique->compile()) if (technique->compile())
Log(Debug::Info) << "Reloaded technique : " << mTechniqueFileMap[technique->getName()].string(); Log(Debug::Info) << "Reloaded technique : " << mTechniqueFileMap[technique->getName()].string(); //TODO(Project579): This will probably break in windows with unicode paths
mReload = technique->isValid(); mReload = technique->isValid();
} }

@ -369,7 +369,7 @@ namespace MWRender
}; };
RenderingManager::RenderingManager(osgViewer::Viewer* viewer, osg::ref_ptr<osg::Group> rootNode, RenderingManager::RenderingManager(osgViewer::Viewer* viewer, osg::ref_ptr<osg::Group> rootNode,
Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue, const std::string& resourcePath, Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue, const std::filesystem::path& resourcePath,
DetourNavigator::Navigator& navigator, const MWWorld::GroundcoverStore& groundcoverStore, DetourNavigator::Navigator& navigator, const MWWorld::GroundcoverStore& groundcoverStore,
SceneUtil::UnrefQueue& unrefQueue) SceneUtil::UnrefQueue& unrefQueue)
: mSkyBlending(Settings::Manager::getBool("sky blending", "Fog")) : mSkyBlending(Settings::Manager::getBool("sky blending", "Fog"))
@ -1526,7 +1526,7 @@ namespace MWRender
updateProjectionMatrix(); updateProjectionMatrix();
} }
} }
void RenderingManager::exportSceneGraph(const MWWorld::Ptr &ptr, const std::string &filename, const std::string &format) void RenderingManager::exportSceneGraph(const MWWorld::Ptr &ptr, const std::filesystem::path& filename, const std::string &format)
{ {
osg::Node* node = mViewer->getSceneData(); osg::Node* node = mViewer->getSceneData();
if (!ptr.isEmpty()) if (!ptr.isEmpty())

@ -102,7 +102,7 @@ namespace MWRender
{ {
public: public:
RenderingManager(osgViewer::Viewer* viewer, osg::ref_ptr<osg::Group> rootNode, RenderingManager(osgViewer::Viewer* viewer, osg::ref_ptr<osg::Group> rootNode,
Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue, const std::string& resourcePath, Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue, const std::filesystem::path& resourcePath,
DetourNavigator::Navigator& navigator, const MWWorld::GroundcoverStore& groundcoverStore, DetourNavigator::Navigator& navigator, const MWWorld::GroundcoverStore& groundcoverStore,
SceneUtil::UnrefQueue& unrefQueue); SceneUtil::UnrefQueue& unrefQueue);
~RenderingManager(); ~RenderingManager();
@ -232,7 +232,7 @@ namespace MWRender
osg::Vec3f getHalfExtents(const MWWorld::ConstPtr& object) const; osg::Vec3f getHalfExtents(const MWWorld::ConstPtr& object) const;
void exportSceneGraph(const MWWorld::Ptr& ptr, const std::string& filename, const std::string& format); void exportSceneGraph(const MWWorld::Ptr& ptr, const std::filesystem::path& filename, const std::string& format);
LandManager* getLandManager() const; LandManager* getLandManager() const;

@ -238,21 +238,21 @@ private:
float mRainIntensity; float mRainIntensity;
}; };
osg::ref_ptr<osg::Image> readPngImage (const std::string& file) osg::ref_ptr<osg::Image> readPngImage (const std::filesystem::path& file)
{ {
std::ifstream inStream; std::ifstream inStream;
inStream.open(file, std::ios_base::in | std::ios_base::binary); inStream.open(file, std::ios_base::in | std::ios_base::binary);
if (inStream.fail()) if (inStream.fail())
Log(Debug::Error) << "Error: Failed to open " << file; Log(Debug::Error) << "Error: Failed to open " << file; //TODO(Project579): This will probably break in windows with unicode paths
osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension("png"); osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension("png");
if (!reader) if (!reader)
{ {
Log(Debug::Error) << "Error: Failed to read " << file << ", no png readerwriter found"; Log(Debug::Error) << "Error: Failed to read " << file << ", no png readerwriter found"; //TODO(Project579): This will probably break in windows with unicode paths
return osg::ref_ptr<osg::Image>(); return osg::ref_ptr<osg::Image>();
} }
osgDB::ReaderWriter::ReadResult result = reader->readImage(inStream); osgDB::ReaderWriter::ReadResult result = reader->readImage(inStream);
if (!result.success()) if (!result.success())
Log(Debug::Error) << "Error: Failed to read " << file << ": " << result.message() << " code " << result.status(); Log(Debug::Error) << "Error: Failed to read " << file << ": " << result.message() << " code " << result.status(); //TODO(Project579): This will probably break in windows with unicode paths
return result.getImage(); return result.getImage();
} }
@ -444,7 +444,7 @@ public:
}; };
Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem *resourceSystem, Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem *resourceSystem,
osgUtil::IncrementalCompileOperation *ico, const std::string& resourcePath) osgUtil::IncrementalCompileOperation *ico, const std::filesystem::path& resourcePath)
: mRainIntensityUpdater(nullptr) : mRainIntensityUpdater(nullptr)
, mParent(parent) , mParent(parent)
, mSceneRoot(sceneRoot) , mSceneRoot(sceneRoot)
@ -695,7 +695,7 @@ void Water::createShaderWaterStateSet(osg::Node* node, Reflection* reflection, R
osg::ref_ptr<osg::Shader> fragmentShader(shaderMgr.getShader("water_fragment.glsl", defineMap, osg::Shader::FRAGMENT)); osg::ref_ptr<osg::Shader> fragmentShader(shaderMgr.getShader("water_fragment.glsl", defineMap, osg::Shader::FRAGMENT));
osg::ref_ptr<osg::Program> program = shaderMgr.getProgram(vertexShader, fragmentShader); osg::ref_ptr<osg::Program> program = shaderMgr.getProgram(vertexShader, fragmentShader);
osg::ref_ptr<osg::Texture2D> normalMap(new osg::Texture2D(readPngImage(mResourcePath + "/shaders/water_nm.png"))); osg::ref_ptr<osg::Texture2D> normalMap(new osg::Texture2D(readPngImage(mResourcePath / "shaders" / "water_nm.png")));
if (normalMap->getImage()) if (normalMap->getImage())
normalMap->getImage()->flipVertical(); normalMap->getImage()->flipVertical();

@ -65,7 +65,7 @@ namespace MWRender
osg::ref_ptr<Refraction> mRefraction; osg::ref_ptr<Refraction> mRefraction;
osg::ref_ptr<Reflection> mReflection; osg::ref_ptr<Reflection> mReflection;
const std::string mResourcePath; const std::filesystem::path mResourcePath;
bool mEnabled; bool mEnabled;
bool mToggled; bool mToggled;
@ -90,7 +90,7 @@ namespace MWRender
public: public:
Water(osg::Group* parent, osg::Group* sceneRoot, Water(osg::Group* parent, osg::Group* sceneRoot,
Resource::ResourceSystem* resourceSystem, osgUtil::IncrementalCompileOperation* ico, Resource::ResourceSystem* resourceSystem, osgUtil::IncrementalCompileOperation* ico,
const std::string& resourcePath); const std::filesystem::path& resourcePath);
~Water(); ~Water();
void setCullCallback(osg::Callback* callback); void setCullCallback(osg::Callback* callback);

@ -1527,8 +1527,8 @@ namespace MWScript
runtime.getContext().report("Exporting the entire scene graph will result in a large file. Confirm this action using 'showscenegraph 1' or select an object instead."); runtime.getContext().report("Exporting the entire scene graph will result in a large file. Confirm this action using 'showscenegraph 1' or select an object instead.");
else else
{ {
const std::string& filename = MWBase::Environment::get().getWorld()->exportSceneGraph(ptr); const auto filename = MWBase::Environment::get().getWorld()->exportSceneGraph(ptr);
runtime.getContext().report("Wrote '" + filename + "'"); runtime.getContext().report("Wrote '" + filename.string() + "'"); //TODO(Project579): This will probably break in windows with unicode paths
} }
} }
}; };

@ -33,7 +33,7 @@ void MWState::Character::addSlot (const std::filesystem::path& path, const std::
slot.mTimeStamp = std::filesystem::last_write_time (path); slot.mTimeStamp = std::filesystem::last_write_time (path);
ESM::ESMReader reader; ESM::ESMReader reader;
reader.open (slot.mPath.string()); reader.open (slot.mPath);
if (reader.getRecName()!=ESM::REC_SAVE) if (reader.getRecName()!=ESM::REC_SAVE)
return; // invalid save file -> ignore return; // invalid save file -> ignore
@ -91,13 +91,11 @@ MWState::Character::Character (std::filesystem::path saves, const std::string& g
} }
else else
{ {
for (std::filesystem::directory_iterator iter (mPath); iter!=std::filesystem::directory_iterator(); ++iter) for (const auto& iter : std::filesystem::directory_iterator (mPath))
{ {
std::filesystem::path slotPath = *iter;
try try
{ {
addSlot (slotPath, game); addSlot (iter, game);
} }
catch (...) {} // ignoring bad saved game files for now catch (...) {} // ignoring bad saved game files for now
} }

@ -305,7 +305,7 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
throw std::runtime_error("Write operation failed (file stream)"); throw std::runtime_error("Write operation failed (file stream)");
Settings::Manager::setString ("character", "Saves", Settings::Manager::setString ("character", "Saves",
slot->mPath.parent_path().filename().string()); slot->mPath.parent_path().filename().string()); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break
const auto finish = std::chrono::steady_clock::now(); const auto finish = std::chrono::steady_clock::now();
@ -364,15 +364,15 @@ void MWState::StateManager::quickSave (std::string name)
saveGame(name, saveFinder.getNextQuickSaveSlot()); saveGame(name, saveFinder.getNextQuickSaveSlot());
} }
void MWState::StateManager::loadGame(const std::string& filepath) void MWState::StateManager::loadGame(const std::filesystem::path &filepath)
{ {
for (const auto& character : mCharacterManager) for (const auto& character : mCharacterManager)
{ {
for (const auto& slot : character) for (const auto& slot : character)
{ {
if (slot.mPath == std::filesystem::path(filepath)) if (slot.mPath == filepath)
{ {
loadGame(&character, slot.mPath.string()); loadGame(&character, slot.mPath);
return; return;
} }
} }
@ -382,13 +382,13 @@ void MWState::StateManager::loadGame(const std::string& filepath)
loadGame(character, filepath); loadGame(character, filepath);
} }
void MWState::StateManager::loadGame (const Character *character, const std::string& filepath) void MWState::StateManager::loadGame (const Character *character, const std::filesystem::path &filepath)
{ {
try try
{ {
cleanup(); cleanup();
Log(Debug::Info) << "Reading save file " << std::filesystem::path(filepath).filename().string(); Log(Debug::Info) << "Reading save file " << filepath.filename(); //TODO(Project579): This will probably break in windows with unicode paths
ESM::ESMReader reader; ESM::ESMReader reader;
reader.open (filepath); reader.open (filepath);
@ -521,7 +521,7 @@ void MWState::StateManager::loadGame (const Character *character, const std::str
if (character) if (character)
Settings::Manager::setString ("character", "Saves", Settings::Manager::setString ("character", "Saves",
character->getPath().filename().string()); character->getPath().filename().string()); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break
MWBase::Environment::get().getWindowManager()->setNewGame(false); MWBase::Environment::get().getWindowManager()->setNewGame(false);
MWBase::Environment::get().getWorld()->saveLoaded(); MWBase::Environment::get().getWorld()->saveLoaded();
@ -593,7 +593,7 @@ void MWState::StateManager::quickLoad()
{ {
if (currentCharacter->begin() == currentCharacter->end()) if (currentCharacter->begin() == currentCharacter->end())
return; return;
loadGame (currentCharacter, currentCharacter->begin()->mPath.string()); //Get newest save loadGame (currentCharacter, currentCharacter->begin()->mPath); //Get newest save
} }
} }
@ -632,7 +632,7 @@ void MWState::StateManager::update (float duration)
//Load last saved game for current character //Load last saved game for current character
MWState::Slot lastSave = *curCharacter->begin(); MWState::Slot lastSave = *curCharacter->begin();
loadGame(curCharacter, lastSave.mPath.string()); loadGame(curCharacter, lastSave.mPath);
} }
else if(iButton==1) else if(iButton==1)
{ {

@ -66,12 +66,12 @@ namespace MWState
/** Used for quickload **/ /** Used for quickload **/
void quickLoad() override; void quickLoad() override;
void loadGame (const std::string& filepath) override; void loadGame (const std::filesystem::path &filepath) override;
///< Load a saved game directly from the given file path. This will search the CharacterManager ///< Load a saved game directly from the given file path. This will search the CharacterManager
/// for a Character containing this save file, and set this Character current if one was found. /// for a Character containing this save file, and set this Character current if one was found.
/// Otherwise, a new Character will be created. /// Otherwise, a new Character will be created.
void loadGame (const Character *character, const std::string &filepath) override; void loadGame (const Character *character, const std::filesystem::path &filepath) override;
///< Load a saved game file belonging to the given character. ///< Load a saved game file belonging to the given character.
Character *getCurrentCharacter () override; Character *getCurrentCharacter () override;

@ -22,13 +22,13 @@ void EsmLoader::load(const std::filesystem::path& filepath, int& index, Loading:
reader->setEncoder(mEncoder); reader->setEncoder(mEncoder);
reader->setIndex(index); reader->setIndex(index);
reader->open(filepath.string()); reader->open(filepath);
reader->resolveParentFileIndices(mReaders); reader->resolveParentFileIndices(mReaders);
assert(reader->getGameFiles().size() == reader->getParentFileIndices().size()); assert(reader->getGameFiles().size() == reader->getParentFileIndices().size());
for (std::size_t i = 0, n = reader->getParentFileIndices().size(); i < n; ++i) for (std::size_t i = 0, n = reader->getParentFileIndices().size(); i < n; ++i)
if (i == static_cast<std::size_t>(reader->getIndex())) if (i == static_cast<std::size_t>(reader->getIndex()))
throw std::runtime_error("File " + reader->getName() + " asks for parent file " throw std::runtime_error("File " + reader->getName().string() + " asks for parent file " //TODO(Project579): This will probably break in windows with unicode paths
+ reader->getGameFiles()[i].name + reader->getGameFiles()[i].name
+ ", but it is not available or has been loaded in the wrong order. " + ", but it is not available or has been loaded in the wrong order. "
"Please run the launcher to fix this issue."); "Please run the launcher to fix this issue.");
@ -36,8 +36,8 @@ void EsmLoader::load(const std::filesystem::path& filepath, int& index, Loading:
mESMVersions[index] = reader->getVer(); mESMVersions[index] = reader->getVer();
mStore.load(*reader, listener, mDialogue); mStore.load(*reader, listener, mDialogue);
if (!mMasterFileFormat.has_value() && (Misc::StringUtils::ciEndsWith(reader->getName(), ".esm") if (!mMasterFileFormat.has_value() && (Misc::StringUtils::ciEndsWith(reader->getName().string(), ".esm") //TODO(Project579): This will probably break in windows with unicode paths
|| Misc::StringUtils::ciEndsWith(reader->getName(), ".omwgame"))) || Misc::StringUtils::ciEndsWith(reader->getName().string(), ".omwgame"))) //TODO(Project579): This will probably break in windows with unicode paths
mMasterFileFormat = reader->getFormat(); mMasterFileFormat = reader->getFormat();
} }

@ -321,13 +321,13 @@ ESM::LuaScriptsCfg ESMStore::getLuaScriptsCfg() const
ESM::LuaScriptsCfg cfg; ESM::LuaScriptsCfg cfg;
for (const LuaContent& c : mLuaContent) for (const LuaContent& c : mLuaContent)
{ {
if (std::holds_alternative<std::string>(c)) if (std::holds_alternative<std::filesystem::path>(c))
{ {
// *.omwscripts are intentionally reloaded every time when `getLuaScriptsCfg` is called. // *.omwscripts are intentionally reloaded every time when `getLuaScriptsCfg` is called.
// It is important for the `reloadlua` console command. // It is important for the `reloadlua` console command.
try try
{ {
auto file = std::ifstream(std::get<std::string>(c)); auto file = std::ifstream(std::get<std::filesystem::path>(c));
std::string fileContent(std::istreambuf_iterator<char>(file), {}); std::string fileContent(std::istreambuf_iterator<char>(file), {});
LuaUtil::parseOMWScripts(cfg, fileContent); LuaUtil::parseOMWScripts(cfg, fileContent);
} }

@ -5,6 +5,7 @@
#include <stdexcept> #include <stdexcept>
#include <unordered_map> #include <unordered_map>
#include <tuple> #include <tuple>
#include <filesystem>
#include <components/esm/luascripts.hpp> #include <components/esm/luascripts.hpp>
#include <components/esm3/loadgmst.hpp> #include <components/esm3/loadgmst.hpp>
@ -159,11 +160,11 @@ namespace MWWorld
using LuaContent = std::variant< using LuaContent = std::variant<
ESM::LuaScriptsCfg, // data from an omwaddon ESM::LuaScriptsCfg, // data from an omwaddon
std::string>; // path to an omwscripts file std::filesystem::path>; // path to an omwscripts file
std::vector<LuaContent> mLuaContent; std::vector<LuaContent> mLuaContent;
public: public:
void addOMWScripts(std::string filePath) { mLuaContent.push_back(std::move(filePath)); } void addOMWScripts(std::filesystem::path filePath) { mLuaContent.push_back(std::move(filePath)); }
ESM::LuaScriptsCfg getLuaScriptsCfg() const; ESM::LuaScriptsCfg getLuaScriptsCfg() const;
/// \todo replace with SharedIterator<StoreBase> /// \todo replace with SharedIterator<StoreBase>

@ -104,10 +104,10 @@ namespace MWWorld
void load(const std::filesystem::path& filepath, int& index, Loading::Listener* listener) override void load(const std::filesystem::path& filepath, int& index, Loading::Listener* listener) override
{ {
const auto it = mLoaders.find(Misc::StringUtils::lowerCase(filepath.extension().string())); const auto it = mLoaders.find(Misc::StringUtils::lowerCase(filepath.extension().string())); //TODO(Project579): let's hope unicode characters are never used in these extensions on windows or this will break
if (it != mLoaders.end()) if (it != mLoaders.end())
{ {
const std::string filename = filepath.filename().string(); const std::string filename = filepath.filename().string(); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break
Log(Debug::Info) << "Loading content file " << filename; Log(Debug::Info) << "Loading content file " << filename;
if (listener != nullptr) if (listener != nullptr)
listener->setLabel(MyGUI::TextIterator::toTagsString(filename)); listener->setLabel(MyGUI::TextIterator::toTagsString(filename));
@ -116,7 +116,7 @@ namespace MWWorld
else else
{ {
std::string msg("Cannot load file: "); std::string msg("Cannot load file: ");
msg += filepath.string(); msg += filepath.string(); //TODO(Project579): This will probably break in windows with unicode paths
throw std::runtime_error(msg.c_str()); throw std::runtime_error(msg.c_str());
} }
} }
@ -131,7 +131,7 @@ namespace MWWorld
OMWScriptsLoader(ESMStore& store) : mStore(store) {} OMWScriptsLoader(ESMStore& store) : mStore(store) {}
void load(const std::filesystem::path& filepath, int& /*index*/, Loading::Listener* /*listener*/) override void load(const std::filesystem::path& filepath, int& /*index*/, Loading::Listener* /*listener*/) override
{ {
mStore.addOMWScripts(filepath.string()); mStore.addOMWScripts(filepath);
} }
}; };
@ -156,7 +156,7 @@ namespace MWWorld
const std::vector<std::string>& groundcoverFiles, const std::vector<std::string>& groundcoverFiles,
ToUTF8::Utf8Encoder* encoder, int activationDistanceOverride, ToUTF8::Utf8Encoder* encoder, int activationDistanceOverride,
const std::string& startCell, const std::string& startupScript, const std::string& startCell, const std::string& startupScript,
const std::string& resourcePath, const std::string& userDataPath) const std::filesystem::path& resourcePath, const std::filesystem::path& userDataPath)
: mResourceSystem(resourceSystem), mLocalScripts(mStore), : mResourceSystem(resourceSystem), mLocalScripts(mStore),
mCells(mStore, mReaders), mSky(true), mCells(mStore, mReaders), mSky(true),
mGodMode(false), mScriptsEnabled(true), mDiscardMovements(true), mContentFiles (contentFiles), mGodMode(false), mScriptsEnabled(true), mDiscardMovements(true), mContentFiles (contentFiles),
@ -2964,7 +2964,7 @@ namespace MWWorld
for (const std::string &file : content) for (const std::string &file : content)
{ {
std::filesystem::path filename(file); std::filesystem::path filename(file);
const Files::MultiDirCollection& col = fileCollections.getCollection(filename.extension().string()); const Files::MultiDirCollection& col = fileCollections.getCollection(filename.extension().string()); //TODO(Project579): let's hope unicode characters are never used in these extensions on windows or this will break
if (col.doesExist(file)) if (col.doesExist(file))
{ {
gameContentLoader.load(col.getPath(file), idx, listener); gameContentLoader.load(col.getPath(file), idx, listener);
@ -3694,9 +3694,9 @@ namespace MWWorld
return mPhysics->getHalfExtents(object); return mPhysics->getHalfExtents(object);
} }
std::string World::exportSceneGraph(const Ptr &ptr) std::filesystem::path World::exportSceneGraph(const Ptr& ptr)
{ {
std::string file = mUserDataPath + "/openmw.osgt"; auto file = mUserDataPath / "openmw.osgt";
if (!ptr.isEmpty()) if (!ptr.isEmpty())
{ {
mRendering->pagingBlacklistObject(mStore.find(ptr.getCellRef().getRefId()), ptr); mRendering->pagingBlacklistObject(mStore.find(ptr.getCellRef().getRefId()), ptr);

@ -109,7 +109,7 @@ namespace MWWorld
bool mDiscardMovements; bool mDiscardMovements;
std::vector<std::string> mContentFiles; std::vector<std::string> mContentFiles;
std::string mUserDataPath; std::filesystem::path mUserDataPath;
osg::Vec3f mDefaultHalfExtents; osg::Vec3f mDefaultHalfExtents;
DetourNavigator::CollisionShapeType mDefaultActorCollisionShapeType; DetourNavigator::CollisionShapeType mDefaultActorCollisionShapeType;
@ -203,7 +203,7 @@ namespace MWWorld
const std::vector<std::string>& groundcoverFiles, const std::vector<std::string>& groundcoverFiles,
ToUTF8::Utf8Encoder* encoder, int activationDistanceOverride, ToUTF8::Utf8Encoder* encoder, int activationDistanceOverride,
const std::string& startCell, const std::string& startupScript, const std::string& startCell, const std::string& startupScript,
const std::string& resourcePath, const std::string& userDataPath); const std::filesystem::path& resourcePath, const std::filesystem::path& userDataPath);
virtual ~World(); virtual ~World();
@ -730,7 +730,7 @@ namespace MWWorld
/// Export scene graph to a file and return the filename. /// Export scene graph to a file and return the filename.
/// \param ptr object to export scene graph for (if empty, export entire scene graph) /// \param ptr object to export scene graph for (if empty, export entire scene graph)
std::string exportSceneGraph(const MWWorld::Ptr& ptr) override; std::filesystem::path exportSceneGraph(const MWWorld::Ptr& ptr) override;
/// Preload VFX associated with this effect list /// Preload VFX associated with this effect list
void preloadEffects(const ESM::EffectList* effectList) override; void preloadEffects(const ESM::EffectList* effectList) override;

@ -42,7 +42,7 @@ namespace
const Files::PathContainer mDataDirs {{std::string(OPENMW_DATA_DIR)}}; const Files::PathContainer mDataDirs {{std::string(OPENMW_DATA_DIR)}};
const Files::Collections mFileCollections {mDataDirs, true}; const Files::Collections mFileCollections {mDataDirs, true};
const std::string mContentFile = "template.omwgame"; const std::string mContentFile = "template.omwgame";
const std::string mContentFilePath = mFileCollections.getCollection(".omwgame").getPath(mContentFile).string(); const std::filesystem::path mContentFilePath = mFileCollections.getCollection(".omwgame").getPath(mContentFile);
}; };
TEST_F(ESM3ReadersCacheWithContentFile, shouldKeepOpenReleasedOpenReader) TEST_F(ESM3ReadersCacheWithContentFile, shouldKeepOpenReleasedOpenReader)

@ -27,7 +27,7 @@ namespace
TEST(FilesGetHash, shouldClearErrors) TEST(FilesGetHash, shouldClearErrors)
{ {
const std::string fileName = temporaryFilePath("fileName"); const auto fileName = temporaryFilePath("fileName");
std::string content; std::string content;
std::fill_n(std::back_inserter(content), 1, 'a'); std::fill_n(std::back_inserter(content), 1, 'a');
std::istringstream stream(content); std::istringstream stream(content);
@ -37,7 +37,7 @@ namespace
TEST_P(FilesGetHash, shouldReturnHashForStringStream) TEST_P(FilesGetHash, shouldReturnHashForStringStream)
{ {
const std::string fileName = temporaryFilePath("fileName"); const auto fileName = temporaryFilePath("fileName");
std::string content; std::string content;
std::fill_n(std::back_inserter(content), GetParam().mSize, 'a'); std::fill_n(std::back_inserter(content), GetParam().mSize, 'a');
std::istringstream stream(content); std::istringstream stream(content);
@ -50,10 +50,10 @@ namespace
std::replace(fileName.begin(), fileName.end(), '/', '_'); std::replace(fileName.begin(), fileName.end(), '/', '_');
std::string content; std::string content;
std::fill_n(std::back_inserter(content), GetParam().mSize, 'a'); std::fill_n(std::back_inserter(content), GetParam().mSize, 'a');
fileName = outputFilePath(fileName); fileName = outputFilePath(fileName).string(); //TODO(Project579): This will probably break in windows with unicode paths
std::fstream(fileName, std::ios_base::out | std::ios_base::binary) std::fstream(fileName, std::ios_base::out | std::ios_base::binary)
.write(content.data(), static_cast<std::streamsize>(content.size())); .write(content.data(), static_cast<std::streamsize>(content.size()));
const auto stream = Files::openConstrainedFileStream(fileName, 0, content.size()); const auto stream = Files::openConstrainedFileStream(fileName, 0, content.size()); //TODO(Project579): This will probably break in windows with unicode paths
EXPECT_EQ(getHash(fileName, *stream), GetParam().mHash); EXPECT_EQ(getHash(fileName, *stream), GetParam().mHash);
} }

@ -88,7 +88,7 @@ namespace
mLua.safe_script("permanent:set('x', 1)"); mLua.safe_script("permanent:set('x', 1)");
mLua.safe_script("temporary:set('y', 2)"); mLua.safe_script("temporary:set('y', 2)");
std::string tmpFile = (std::filesystem::temp_directory_path() / "test_storage.bin").string(); const auto tmpFile = std::filesystem::temp_directory_path() / "test_storage.bin";
storage.save(tmpFile); storage.save(tmpFile);
EXPECT_EQ(get<int>(mLua, "permanent:get('x')"), 1); EXPECT_EQ(get<int>(mLua, "permanent:get('x')"), 1);
EXPECT_EQ(get<int>(mLua, "temporary:get('y')"), 2); EXPECT_EQ(get<int>(mLua, "temporary:get('y')"), 2);

@ -41,7 +41,7 @@ struct ContentFileTest : public ::testing::Test
ESM::ESMReader lEsm; ESM::ESMReader lEsm;
lEsm.setEncoder(nullptr); lEsm.setEncoder(nullptr);
lEsm.setIndex(index); lEsm.setIndex(index);
lEsm.open(mContentFile.string()); lEsm.open(mContentFile);
mEsmStore.load(lEsm, &dummyListener, dialogue); mEsmStore.load(lEsm, &dummyListener, dialogue);
++index; ++index;
@ -109,7 +109,7 @@ TEST_F(ContentFileTest, dialogue_merging_test)
return; return;
} }
const std::string file = TestingOpenMW::outputFilePath("test_dialogue_merging.txt"); const auto file = TestingOpenMW::outputFilePath("test_dialogue_merging.txt");
std::ofstream stream(file); std::ofstream stream(file);
const MWWorld::Store<ESM::Dialogue>& dialStore = mEsmStore.get<ESM::Dialogue>(); const MWWorld::Store<ESM::Dialogue>& dialStore = mEsmStore.get<ESM::Dialogue>();
@ -124,7 +124,7 @@ TEST_F(ContentFileTest, dialogue_merging_test)
stream << std::endl; stream << std::endl;
} }
std::cout << "dialogue_merging_test successful, results printed to " << file << std::endl; std::cout << "dialogue_merging_test successful, results printed to " << file << std::endl; //TODO(Project579): This will probably break in windows with unicode paths
} }
// Note: here we don't test records that don't use string names (e.g. Land, Pathgrid, Cell) // Note: here we don't test records that don't use string names (e.g. Land, Pathgrid, Cell)
@ -189,12 +189,12 @@ TEST_F(ContentFileTest, content_diagnostics_test)
return; return;
} }
const std::string file = TestingOpenMW::outputFilePath("test_content_diagnostics.txt"); const auto file = TestingOpenMW::outputFilePath("test_content_diagnostics.txt");
std::ofstream stream(file); std::ofstream stream(file);
RUN_TEST_FOR_TYPES(printRecords, mEsmStore, stream); RUN_TEST_FOR_TYPES(printRecords, mEsmStore, stream);
std::cout << "diagnostics_test successful, results printed to " << file << std::endl; std::cout << "diagnostics_test successful, results printed to " << file << std::endl; //TODO(Project579): This will probably break in windows with unicode paths
} }
// TODO: // TODO:

@ -353,7 +353,7 @@ namespace
MOCK_METHOD(std::string, getString, (uint32_t), (const, override)); MOCK_METHOD(std::string, getString, (uint32_t), (const, override));
MOCK_METHOD(void, setUseSkinning, (bool), (override)); MOCK_METHOD(void, setUseSkinning, (bool), (override));
MOCK_METHOD(bool, getUseSkinning, (), (const, override)); MOCK_METHOD(bool, getUseSkinning, (), (const, override));
MOCK_METHOD(std::string, getFilename, (), (const, override)); MOCK_METHOD(std::filesystem::path, getFilename, (), (const, override));
MOCK_METHOD(std::string, getHash, (), (const, override)); MOCK_METHOD(std::string, getHash, (), (const, override));
MOCK_METHOD(unsigned int, getVersion, (), (const, override)); MOCK_METHOD(unsigned int, getVersion, (), (const, override));
MOCK_METHOD(unsigned int, getUserVersion, (), (const, override)); MOCK_METHOD(unsigned int, getUserVersion, (), (const, override));

@ -19,7 +19,7 @@ namespace
template <typename F> template <typename F>
void withSettingsFile( const std::string& content, F&& f) void withSettingsFile( const std::string& content, F&& f)
{ {
std::string path = TestingOpenMW::outputFilePath( auto path = TestingOpenMW::outputFilePath(
std::string(UnitTest::GetInstance()->current_test_info()->name()) + ".cfg"); std::string(UnitTest::GetInstance()->current_test_info()->name()) + ".cfg");
{ {

@ -17,7 +17,7 @@ namespace
template <typename F> template <typename F>
void withSettingsFile( const std::string& content, F&& f) void withSettingsFile( const std::string& content, F&& f)
{ {
std::string path = TestingOpenMW::outputFilePath( auto path = TestingOpenMW::outputFilePath(
std::string(UnitTest::GetInstance()->current_test_info()->name()) + ".yaml"); std::string(UnitTest::GetInstance()->current_test_info()->name()) + ".yaml");
{ {

@ -30,7 +30,7 @@ namespace
template <class F> template <class F>
void withShaderFile(const std::string& suffix, const std::string& content, F&& f) void withShaderFile(const std::string& suffix, const std::string& content, F&& f)
{ {
std::string path = TestingOpenMW::outputFilePath( auto path = TestingOpenMW::outputFilePath(
std::string(UnitTest::GetInstance()->current_test_info()->name()) + suffix + ".glsl"); std::string(UnitTest::GetInstance()->current_test_info()->name()) + suffix + ".glsl");
{ {
@ -47,8 +47,8 @@ namespace
{ {
const std::string content; const std::string content;
withShaderFile(content, [this] (const std::string& templateName) { withShaderFile(content, [this] (const std::filesystem::path& templateName) {
EXPECT_TRUE(mManager.getShader(templateName, {}, osg::Shader::VERTEX)); EXPECT_TRUE(mManager.getShader(templateName.string(), {}, osg::Shader::VERTEX)); //TODO(Project579): This will probably break in windows with unicode paths
}); });
} }
@ -58,8 +58,8 @@ namespace
"#version 120\n" "#version 120\n"
"void main() {}\n"; "void main() {}\n";
withShaderFile(content, [&] (const std::string& templateName) { withShaderFile(content, [&] (const std::filesystem::path& templateName) {
const auto shader = mManager.getShader(templateName, mDefines, osg::Shader::VERTEX); const auto shader = mManager.getShader(templateName.string(), mDefines, osg::Shader::VERTEX); //TODO(Project579): This will probably break in windows with unicode paths
ASSERT_TRUE(shader); ASSERT_TRUE(shader);
EXPECT_EQ(shader->getShaderSource(), content); EXPECT_EQ(shader->getShaderSource(), content);
}); });
@ -70,19 +70,19 @@ namespace
const std::string content0 = const std::string content0 =
"void foo() {}\n"; "void foo() {}\n";
withShaderFile("_0", content0, [&] (const std::string& templateName0) { withShaderFile("_0", content0, [&] (const std::filesystem::path& templateName0) {
const std::string content1 = const std::string content1 =
"#include \"" + templateName0 + "\"\n" "#include \"" + templateName0.string() + "\"\n" //TODO(Project579): This will probably break in windows with unicode paths
"void bar() { foo() }\n"; "void bar() { foo() }\n";
withShaderFile("_1", content1, [&] (const std::string& templateName1) { withShaderFile("_1", content1, [&] (const std::filesystem::path& templateName1) {
const std::string content2 = const std::string content2 =
"#version 120\n" "#version 120\n"
"#include \"" + templateName1 + "\"\n" "#include \"" + templateName1.string() + "\"\n" //TODO(Project579): This will probably break in windows with unicode paths
"void main() { bar() }\n"; "void main() { bar() }\n";
withShaderFile(content2, [&] (const std::string& templateName2) { withShaderFile(content2, [&] (const std::filesystem::path& templateName2) {
const auto shader = mManager.getShader(templateName2, mDefines, osg::Shader::VERTEX); const auto shader = mManager.getShader(templateName2.string(), mDefines, osg::Shader::VERTEX); //TODO(Project579): This will probably break in windows with unicode paths
ASSERT_TRUE(shader); ASSERT_TRUE(shader);
const std::string expected = const std::string expected =
"#version 120\n" "#version 120\n"
@ -111,9 +111,9 @@ namespace
"void main() {}\n" "void main() {}\n"
; ;
withShaderFile(content, [&] (const std::string& templateName) { withShaderFile(content, [&] (const std::filesystem::path& templateName) {
mDefines["flag"] = "1"; mDefines["flag"] = "1";
const auto shader = mManager.getShader(templateName, mDefines, osg::Shader::VERTEX); const auto shader = mManager.getShader(templateName.string(), mDefines, osg::Shader::VERTEX); //TODO(Project579): This will probably break in windows with unicode paths
ASSERT_TRUE(shader); ASSERT_TRUE(shader);
const std::string expected = const std::string expected =
"#version 120\n" "#version 120\n"
@ -133,9 +133,9 @@ namespace
"void main() {}\n" "void main() {}\n"
; ;
withShaderFile(content, [&] (const std::string& templateName) { withShaderFile(content, [&] (const std::filesystem::path& templateName) {
mDefines["list"] = "1,2,3"; mDefines["list"] = "1,2,3";
const auto shader = mManager.getShader(templateName, mDefines, osg::Shader::VERTEX); const auto shader = mManager.getShader(templateName.string(), mDefines, osg::Shader::VERTEX); //TODO(Project579): This will probably break in windows with unicode paths
ASSERT_TRUE(shader); ASSERT_TRUE(shader);
const std::string expected = const std::string expected =
"#version 120\n" "#version 120\n"
@ -174,9 +174,9 @@ namespace
"}\n" "}\n"
; ;
withShaderFile(content, [&] (const std::string& templateName) { withShaderFile(content, [&] (const std::filesystem::path& templateName) {
mDefines["list"] = "1,2,3"; mDefines["list"] = "1,2,3";
const auto shader = mManager.getShader(templateName, mDefines, osg::Shader::VERTEX); const auto shader = mManager.getShader(templateName.string(), mDefines, osg::Shader::VERTEX); //TODO(Project579): This will probably break in windows with unicode paths
ASSERT_TRUE(shader); ASSERT_TRUE(shader);
const std::string expected = const std::string expected =
"#version 120\n" "#version 120\n"
@ -222,8 +222,8 @@ namespace
"void main() {}\n" "void main() {}\n"
; ;
withShaderFile(content, [&] (const std::string& templateName) { withShaderFile(content, [&] (const std::filesystem::path& templateName) {
EXPECT_FALSE(mManager.getShader(templateName, mDefines, osg::Shader::VERTEX)); EXPECT_FALSE(mManager.getShader(templateName.string(), mDefines, osg::Shader::VERTEX)); //TODO(Project579): This will probably break in windows with unicode paths
}); });
} }
@ -235,8 +235,8 @@ namespace
"void main() {}\n" "void main() {}\n"
; ;
withShaderFile(content, [&] (const std::string& templateName) { withShaderFile(content, [&] (const std::filesystem::path& templateName) {
EXPECT_FALSE(mManager.getShader(templateName, mDefines, osg::Shader::VERTEX)); EXPECT_FALSE(mManager.getShader(templateName.string(), mDefines, osg::Shader::VERTEX)); //TODO(Project579): This will probably break in windows with unicode paths
}); });
} }
} }

@ -10,16 +10,16 @@
namespace TestingOpenMW namespace TestingOpenMW
{ {
inline std::string outputFilePath(const std::string name) inline std::filesystem::path outputFilePath(const std::string name)
{ {
std::filesystem::path dir("tests_output"); std::filesystem::path dir("tests_output");
std::filesystem::create_directory(dir); std::filesystem::create_directory(dir);
return (dir / name).string(); return dir / name;
} }
inline std::string temporaryFilePath(const std::string name) inline std::filesystem::path temporaryFilePath(const std::string name)
{ {
return (std::filesystem::temp_directory_path() / name).string(); return std::filesystem::temp_directory_path() / name;
} }
class VFSTestFile : public VFS::File class VFSTestFile : public VFS::File
@ -32,7 +32,7 @@ namespace TestingOpenMW
return std::make_unique<std::stringstream>(mContent, std::ios_base::in); return std::make_unique<std::stringstream>(mContent, std::ios_base::in);
} }
std::string getPath() override std::filesystem::path getPath() override
{ {
return "TestFile"; return "TestFile";
} }

@ -19,7 +19,7 @@ Wizard::InstallationTargetPage::InstallationTargetPage(QWidget *parent, const Fi
void Wizard::InstallationTargetPage::initializePage() void Wizard::InstallationTargetPage::initializePage()
{ {
QString path(QFile::decodeName(mCfgMgr.getUserDataPath().string().c_str())); QString path(QFile::decodeName(mCfgMgr.getUserDataPath().string().c_str())); //TODO(Project579): This will probably break in windows with unicode paths
path.append(QDir::separator() + QLatin1String("basedata")); path.append(QDir::separator() + QLatin1String("basedata"));
QDir dir(path); QDir dir(path);

@ -471,5 +471,5 @@ bool Wizard::MainWizard::findFiles(const QString &name, const QString &path)
QString Wizard::MainWizard::toQString(const std::filesystem::path& path) QString Wizard::MainWizard::toQString(const std::filesystem::path& path)
{ {
return QString::fromUtf8(path.string().c_str()); return QString::fromUtf8(path.string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths
} }

@ -37,7 +37,7 @@ using namespace Bsa;
/// Error handling /// Error handling
[[noreturn]] void BSAFile::fail(const std::string &msg) [[noreturn]] void BSAFile::fail(const std::string &msg)
{ {
throw std::runtime_error("BSA Error: " + msg + "\nArchive: " + mFilename); throw std::runtime_error("BSA Error: " + msg + "\nArchive: " + mFilepath.string()); //TODO(Project579): This will probably break in windows with unicode paths
} }
//the getHash code is from bsapack from ghostwheel //the getHash code is from bsapack from ghostwheel
@ -100,7 +100,7 @@ void BSAFile::readHeader()
*/ */
assert(!mIsLoaded); assert(!mIsLoaded);
std::ifstream input(std::filesystem::path(mFilename), std::ios_base::binary); std::ifstream input(mFilepath, std::ios_base::binary);
// Total archive size // Total archive size
std::streamoff fsize = 0; std::streamoff fsize = 0;
@ -196,7 +196,7 @@ void BSAFile::readHeader()
/// Write header information to the output sink /// Write header information to the output sink
void Bsa::BSAFile::writeHeader() void Bsa::BSAFile::writeHeader()
{ {
std::fstream output(mFilename, std::ios::binary | std::ios::in | std::ios::out); std::fstream output(mFilepath, std::ios::binary | std::ios::in | std::ios::out);
uint32_t head[3]; uint32_t head[3];
head[0] = 0x100; head[0] = 0x100;
@ -231,17 +231,17 @@ void Bsa::BSAFile::writeHeader()
} }
/// Open an archive file. /// Open an archive file.
void BSAFile::open(const std::string &file) void BSAFile::open(const std::filesystem::path &file)
{ {
if (mIsLoaded) if (mIsLoaded)
close(); close();
mFilename = file; mFilepath = file;
if(std::filesystem::exists(file)) if(std::filesystem::exists(file))
readHeader(); readHeader();
else else
{ {
{ std::fstream(mFilename, std::ios::binary | std::ios::out); } { std::fstream(mFilepath, std::ios::binary | std::ios::out); }
writeHeader(); writeHeader();
mIsLoaded = true; mIsLoaded = true;
} }
@ -270,9 +270,9 @@ void Bsa::BSAFile::addFile(const std::string& filename, std::istream& file)
auto newStartOfDataBuffer = 12 + (12 + 8) * (mFiles.size() + 1) + mStringBuf.size() + filename.size() + 1; auto newStartOfDataBuffer = 12 + (12 + 8) * (mFiles.size() + 1) + mStringBuf.size() + filename.size() + 1;
if (mFiles.empty()) if (mFiles.empty())
std::filesystem::resize_file(mFilename, newStartOfDataBuffer); std::filesystem::resize_file(mFilepath, newStartOfDataBuffer);
std::fstream stream(mFilename, std::ios::binary | std::ios::in | std::ios::out); std::fstream stream(mFilepath, std::ios::binary | std::ios::in | std::ios::out);
FileStruct newFile; FileStruct newFile;
file.seekg(0, std::ios::end); file.seekg(0, std::ios::end);

@ -27,6 +27,7 @@
#include <cstdint> #include <cstdint>
#include <string> #include <string>
#include <vector> #include <vector>
#include <filesystem>
#include <components/files/istreamptr.hpp> #include <components/files/istreamptr.hpp>
@ -85,7 +86,7 @@ protected:
bool mIsLoaded; bool mIsLoaded;
/// Used for error messages /// Used for error messages
std::string mFilename; std::filesystem::path mFilepath;
/// Error handling /// Error handling
[[noreturn]] void fail(const std::string &msg); [[noreturn]] void fail(const std::string &msg);
@ -110,7 +111,7 @@ public:
} }
/// Open an archive file. /// Open an archive file.
void open(const std::string &file); void open(const std::filesystem::path &file);
void close(); void close();
@ -131,9 +132,9 @@ public:
const FileList &getList() const const FileList &getList() const
{ return mFiles; } { return mFiles; }
const std::string& getFilename() const std::string getFilename() const
{ {
return mFilename; return mFilepath.string(); //TODO(Project579): This will probably break in windows with unicode paths
} }
}; };

@ -119,7 +119,7 @@ void CompressedBSAFile::readHeader()
{ {
assert(!mIsLoaded); assert(!mIsLoaded);
std::ifstream input(std::filesystem::path(mFilename), std::ios_base::binary); std::ifstream input(mFilepath, std::ios_base::binary);
// Total archive size // Total archive size
std::streamoff fsize = 0; std::streamoff fsize = 0;
@ -299,17 +299,22 @@ void CompressedBSAFile::readHeader()
CompressedBSAFile::FileRecord CompressedBSAFile::getFileRecord(const std::string& str) const CompressedBSAFile::FileRecord CompressedBSAFile::getFileRecord(const std::string& str) const
{ {
// Force-convert the path into something both Windows and UNIX can handle first #ifdef _WIN32
// to make sure Boost doesn't think the entire path is the filename on Linux const auto& path = str;
#else
// Force-convert the path into something UNIX can handle first
// to make sure std::filesystem::path doesn't think the entire path is the filename on Linux
// and subsequently purge it to determine the file folder. // and subsequently purge it to determine the file folder.
std::string path = str; std::string path = str;
std::replace(path.begin(), path.end(), '\\', '/'); std::replace(path.begin(), path.end(), '\\', '/');
#endif
std::filesystem::path p(path); std::filesystem::path p(path);
std::string stem = p.stem().string(); std::string stem = p.stem().string();
std::string ext = p.extension().string(); std::string ext = p.extension().string();
p.remove_filename();
std::string folder = p.parent_path().string(); std::string folder = p.string();
std::uint64_t folderHash = generateHash(folder, std::string()); std::uint64_t folderHash = generateHash(folder, std::string());
auto it = mFolders.find(folderHash); auto it = mFolders.find(folderHash);

@ -29,6 +29,7 @@
#include <map> #include <map>
#include <components/bsa/bsa_file.hpp> #include <components/bsa/bsa_file.hpp>
#include <filesystem>
namespace Bsa namespace Bsa
{ {
@ -82,7 +83,7 @@ namespace Bsa
//mFiles used by OpenMW will contain uncompressed file sizes //mFiles used by OpenMW will contain uncompressed file sizes
void convertCompressedSizesToUncompressed(); void convertCompressedSizesToUncompressed();
/// \brief Normalizes given filename or folder and generates format-compatible hash. See https://en.uesp.net/wiki/Tes4Mod:Hash_Calculation. /// \brief Normalizes given filename or folder and generates format-compatible hash. See https://en.uesp.net/wiki/Tes4Mod:Hash_Calculation.
static std::uint64_t generateHash(std::string stem, std::string extension) ; static std::uint64_t generateHash(std::filesystem::path stem, std::string extension) ;
Files::IStreamPtr getFile(const FileRecord& fileRecord); Files::IStreamPtr getFile(const FileRecord& fileRecord);
public: public:
using BSAFile::open; using BSAFile::open;
@ -93,7 +94,7 @@ namespace Bsa
virtual ~CompressedBSAFile(); virtual ~CompressedBSAFile();
//checks version of BSA from file header //checks version of BSA from file header
static BsaVersion detectVersion(const std::string& filePath); static BsaVersion detectVersion(const std::filesystem::path &filePath);
/// Read header information from the input source /// Read header information from the input source
void readHeader() override; void readHeader() override;

@ -32,7 +32,7 @@ void Config::GameSettings::validatePaths()
mDataDirs.clear(); mDataDirs.clear();
for (auto & dataDir : dataDirs) { for (auto & dataDir : dataDirs) {
QString path = QString::fromUtf8(dataDir.string().c_str()); QString path = QString::fromUtf8(dataDir.string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths
QDir dir(path); QDir dir(path);
if (dir.exists()) if (dir.exists())
@ -57,7 +57,7 @@ void Config::GameSettings::validatePaths()
mCfgMgr.processPaths(dataDirs, /*basePath=*/""); mCfgMgr.processPaths(dataDirs, /*basePath=*/"");
if (!dataDirs.empty()) { if (!dataDirs.empty()) {
QString path = QString::fromUtf8(dataDirs.front().string().c_str()); QString path = QString::fromUtf8(dataDirs.front().string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths
QDir dir(path); QDir dir(path);
if (dir.exists()) if (dir.exists())
@ -65,11 +65,11 @@ void Config::GameSettings::validatePaths()
} }
} }
std::string Config::GameSettings::getGlobalDataDir() const std::filesystem::path Config::GameSettings::getGlobalDataDir() const
{ {
// global data dir may not exists if OpenMW is not installed (ie if run from build directory) // global data dir may not exists if OpenMW is not installed (ie if run from build directory)
if (std::filesystem::exists(mCfgMgr.getGlobalDataPath())) if (std::filesystem::exists(mCfgMgr.getGlobalDataPath()))
return std::filesystem::canonical(mCfgMgr.getGlobalDataPath()).string(); return std::filesystem::canonical(mCfgMgr.getGlobalDataPath());
return {}; return {};
} }

@ -54,7 +54,7 @@ namespace Config
} }
QStringList getDataDirs() const; QStringList getDataDirs() const;
std::string getGlobalDataDir() const; std::filesystem::path getGlobalDataDir() const;
inline void removeDataDir(const QString &dir) { if(!dir.isEmpty()) mDataDirs.removeAll(dir); } inline void removeDataDir(const QString &dir) { if(!dir.isEmpty()) mDataDirs.removeAll(dir); }
inline void addDataDir(const QString &dir) { if(!dir.isEmpty()) mDataDirs.append(dir); } inline void addDataDir(const QString &dir) { if(!dir.isEmpty()) mDataDirs.append(dir); }

@ -119,7 +119,7 @@ void Config::LauncherSettings::setContentList(const GameSettings& gameSettings)
} }
// global and local data directories are not part of any profile // global and local data directories are not part of any profile
const auto globalDataDir = QString(gameSettings.getGlobalDataDir().c_str()); const auto globalDataDir = QString(gameSettings.getGlobalDataDir().string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths
const auto dataLocal = gameSettings.getDataLocal(); const auto dataLocal = gameSettings.getDataLocal();
dirs.removeAll(globalDataDir); dirs.removeAll(globalDataDir);
dirs.removeAll(dataLocal); dirs.removeAll(dataLocal);

@ -559,7 +559,7 @@ static bool is_debugger_present()
#endif #endif
} }
void crashCatcherInstall(int argc, char **argv, const std::string &crashLogPath) void crashCatcherInstall(int argc, char **argv, const std::filesystem::path &crashLogPath)
{ {
if ((argc == 2 && strcmp(argv[1], crash_switch) == 0) || !is_debugger_present()) if ((argc == 2 && strcmp(argv[1], crash_switch) == 0) || !is_debugger_present())
{ {

@ -12,7 +12,7 @@
constexpr char crash_switch[] = "--cc-handle-crash"; constexpr char crash_switch[] = "--cc-handle-crash";
#if USE_CRASH_CATCHER #if USE_CRASH_CATCHER
extern void crashCatcherInstall(int argc, char **argv, const std::string &crashLogPath); extern void crashCatcherInstall(int argc, char **argv, const std::filesystem::path &crashLogPath);
#else #else
inline void crashCatcherInstall(int, char **, const std::string &crashLogPath) inline void crashCatcherInstall(int, char **, const std::string &crashLogPath)
{ {

@ -9,6 +9,8 @@
#include "windows_crashshm.hpp" #include "windows_crashshm.hpp"
#include <SDL_messagebox.h> #include <SDL_messagebox.h>
#include <components/misc/stringops.hpp>
namespace Crash namespace Crash
{ {
@ -26,7 +28,7 @@ namespace Crash
CrashCatcher* CrashCatcher::sInstance = nullptr; CrashCatcher* CrashCatcher::sInstance = nullptr;
CrashCatcher::CrashCatcher(int argc, char **argv, const std::string& crashLogPath) CrashCatcher::CrashCatcher(int argc, char **argv, const std::filesystem::path& crashLogPath)
{ {
assert(sInstance == nullptr); // don't allow two instances assert(sInstance == nullptr); // don't allow two instances
@ -124,7 +126,7 @@ namespace Crash
SetUnhandledExceptionFilter(vectoredExceptionHandler); SetUnhandledExceptionFilter(vectoredExceptionHandler);
} }
void CrashCatcher::startMonitorProcess(const std::string& crashLogPath) void CrashCatcher::startMonitorProcess(const std::filesystem::path& crashLogPath)
{ {
std::wstring executablePath; std::wstring executablePath;
DWORD copied = 0; DWORD copied = 0;
@ -135,9 +137,10 @@ namespace Crash
executablePath.resize(copied); executablePath.resize(copied);
memset(mShm->mStartup.mLogFilePath, 0, sizeof(mShm->mStartup.mLogFilePath)); memset(mShm->mStartup.mLogFilePath, 0, sizeof(mShm->mStartup.mLogFilePath));
size_t length = crashLogPath.length(); const auto str = crashLogPath.u8string();
size_t length = str.length();
if (length >= MAX_LONG_PATH) length = MAX_LONG_PATH - 1; if (length >= MAX_LONG_PATH) length = MAX_LONG_PATH - 1;
strncpy(mShm->mStartup.mLogFilePath, crashLogPath.c_str(), length); strncpy_s(mShm->mStartup.mLogFilePath, sizeof mShm->mStartup.mLogFilePath, Misc::StringUtils::char8_to_char(str.c_str()), length); //TODO(Project579): This will probably break in windows with unicode paths
mShm->mStartup.mLogFilePath[length] = '\0'; mShm->mStartup.mLogFilePath[length] = '\0';
// note that we don't need to lock the SHM here, the other process has not started yet // note that we don't need to lock the SHM here, the other process has not started yet

@ -1,7 +1,7 @@
#ifndef WINDOWS_CRASHCATCHER_HPP #ifndef WINDOWS_CRASHCATCHER_HPP
#define WINDOWS_CRASHCATCHER_HPP #define WINDOWS_CRASHCATCHER_HPP
#include <string> #include <filesystem>
#include <components/windows.hpp> #include <components/windows.hpp>
#include <components/crashcatcher/crashcatcher.hpp> #include <components/crashcatcher/crashcatcher.hpp>
@ -28,7 +28,7 @@ namespace Crash
{ {
public: public:
CrashCatcher(int argc, char **argv, const std::string& crashLogPath); CrashCatcher(int argc, char **argv, const std::filesystem::path& crashLogPath);
~CrashCatcher(); ~CrashCatcher();
private: private:
@ -56,7 +56,7 @@ namespace Crash
void shmUnlock(); void shmUnlock();
void startMonitorProcess(const std::string& crashLogPath); void startMonitorProcess(const std::filesystem::path& crashLogPath);
void waitMonitor(); void waitMonitor();

@ -269,7 +269,7 @@ Misc::Locked<std::ostream&> getLockedRawStderr()
} }
// Redirect cout and cerr to the log file // Redirect cout and cerr to the log file
void setupLogging(const std::string& logDir, const std::string& appName, std::ios_base::openmode mode) void setupLogging(const std::filesystem::path &logDir, const std::string& appName, std::ios_base::openmode mode)
{ {
#if defined(_WIN32) && defined(_DEBUG) #if defined(_WIN32) && defined(_DEBUG)
// Redirect cout and cerr to VS debug output when running in debug mode // Redirect cout and cerr to VS debug output when running in debug mode
@ -278,7 +278,7 @@ void setupLogging(const std::string& logDir, const std::string& appName, std::io
std::cerr.rdbuf(&sb); std::cerr.rdbuf(&sb);
#else #else
const std::string logName = Misc::StringUtils::lowerCase(appName) + ".log"; const std::string logName = Misc::StringUtils::lowerCase(appName) + ".log";
logfile.open(std::filesystem::path(logDir) / logName, mode); logfile.open(logDir / logName, mode);
coutsb.open(Debug::Tee(logfile, *rawStdout)); coutsb.open(Debug::Tee(logfile, *rawStdout));
cerrsb.open(Debug::Tee(logfile, *rawStderr)); cerrsb.open(Debug::Tee(logfile, *rawStderr));
@ -311,7 +311,7 @@ int wrapApplication(int (*innerApplication)(int argc, char *argv[]), int argc, c
if (argc == 2 && strcmp(argv[1], crash_switch) == 0) if (argc == 2 && strcmp(argv[1], crash_switch) == 0)
mode |= std::ios::app; mode |= std::ios::app;
setupLogging(cfgMgr.getLogPath().string(), appName, mode); setupLogging(cfgMgr.getLogPath(), appName, mode);
} }
if (const auto env = std::getenv("OPENMW_DISABLE_CRASH_CATCHER"); env == nullptr || std::atol(env) == 0) if (const auto env = std::getenv("OPENMW_DISABLE_CRASH_CATCHER"); env == nullptr || std::atol(env) == 0)

@ -34,7 +34,7 @@ std::ostream& getRawStderr();
Misc::Locked<std::ostream&> getLockedRawStderr(); Misc::Locked<std::ostream&> getLockedRawStderr();
void setupLogging(const std::string& logDir, const std::string& appName, std::ios_base::openmode = std::ios::out); void setupLogging(const std::filesystem::path &logDir, const std::string& appName, std::ios_base::openmode mode = std::ios::out);
int wrapApplication(int (*innerApplication)(int argc, char *argv[]), int argc, char *argv[], int wrapApplication(int (*innerApplication)(int argc, char *argv[]), int argc, char *argv[],
const std::string& appName, bool autoSetupLogging = true); const std::string& appName, bool autoSetupLogging = true);

@ -7,7 +7,7 @@
namespace DetourNavigator namespace DetourNavigator
{ {
std::unique_ptr<Navigator> makeNavigator(const Settings& settings, const std::string& userDataPath) std::unique_ptr<Navigator> makeNavigator(const Settings& settings, const std::filesystem::path& userDataPath)
{ {
DetourNavigator::RecastGlobalAllocator::init(); DetourNavigator::RecastGlobalAllocator::init();
@ -16,7 +16,7 @@ namespace DetourNavigator
{ {
try try
{ {
db = std::make_unique<NavMeshDb>(userDataPath + "/navmesh.db", settings.mMaxDbFileSize); db = std::make_unique<NavMeshDb>((userDataPath / "navmesh.db").string(), settings.mMaxDbFileSize); //TODO(Project579): This will probably break in windows with unicode paths
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {

@ -1,6 +1,8 @@
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_NAVIGATOR_H #ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_NAVIGATOR_H
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_NAVIGATOR_H #define OPENMW_COMPONENTS_DETOURNAVIGATOR_NAVIGATOR_H
#include <filesystem>
#include "objectid.hpp" #include "objectid.hpp"
#include "sharednavmeshcacheitem.hpp" #include "sharednavmeshcacheitem.hpp"
#include "recastmeshtiles.hpp" #include "recastmeshtiles.hpp"
@ -10,7 +12,6 @@
#include <components/resource/bulletshape.hpp> #include <components/resource/bulletshape.hpp>
#include <string_view>
namespace ESM namespace ESM
{ {
@ -195,7 +196,7 @@ namespace DetourNavigator
virtual float getMaxNavmeshAreaRealRadius() const = 0; virtual float getMaxNavmeshAreaRealRadius() const = 0;
}; };
std::unique_ptr<Navigator> makeNavigator(const Settings& settings, const std::string& userDataPath); std::unique_ptr<Navigator> makeNavigator(const Settings& settings, const std::filesystem::path& userDataPath);
std::unique_ptr<Navigator> makeNavigatorStub(); std::unique_ptr<Navigator> makeNavigatorStub();
} }

@ -9,6 +9,7 @@
#include <cassert> #include <cassert>
#include <limits> #include <limits>
#include <type_traits> #include <type_traits>
#include <filesystem>
namespace ESM namespace ESM
{ {
@ -187,7 +188,7 @@ static_assert(sizeof(NAME64) == 64);
*/ */
struct ESM_Context struct ESM_Context
{ {
std::string filename; std::filesystem::path filename;
uint32_t leftRec, leftSub; uint32_t leftRec, leftSub;
size_t leftFile; size_t leftFile;
NAME recName, subName; NAME recName, subName;

@ -73,8 +73,7 @@ void ESMReader::resolveParentFileIndices(ReadersCache& readers)
const ESM::ReadersCache::BusyItem reader = readers.get(static_cast<std::size_t>(i)); const ESM::ReadersCache::BusyItem reader = readers.get(static_cast<std::size_t>(i));
if (reader->getFileSize() == 0) if (reader->getFileSize() == 0)
continue; // Content file in non-ESM format continue; // Content file in non-ESM format
const std::string& candidate = reader->getName(); std::string fnamecandidate = reader->getName().filename().string(); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break
std::string fnamecandidate = std::filesystem::path(candidate).filename().string();
if (Misc::StringUtils::ciEqual(fname, fnamecandidate)) if (Misc::StringUtils::ciEqual(fname, fnamecandidate))
{ {
index = i; index = i;
@ -85,7 +84,7 @@ void ESMReader::resolveParentFileIndices(ReadersCache& readers)
} }
} }
void ESMReader::openRaw(std::unique_ptr<std::istream>&& stream, std::string_view name) void ESMReader::openRaw(std::unique_ptr<std::istream>&& stream, const std::filesystem::path &name)
{ {
close(); close();
mEsm = std::move(stream); mEsm = std::move(stream);
@ -95,12 +94,12 @@ void ESMReader::openRaw(std::unique_ptr<std::istream>&& stream, std::string_view
mEsm->seekg(0, mEsm->beg); mEsm->seekg(0, mEsm->beg);
} }
void ESMReader::openRaw(std::string_view filename) void ESMReader::openRaw(const std::filesystem::path &filename)
{ {
openRaw(Files::openBinaryInputFileStream(std::string(filename)), filename); openRaw(Files::openBinaryInputFileStream(filename), filename);
} }
void ESMReader::open(std::unique_ptr<std::istream>&& stream, const std::string &name) void ESMReader::open(std::unique_ptr<std::istream>&& stream, const std::filesystem::path &name)
{ {
openRaw(std::move(stream), name); openRaw(std::move(stream), name);
@ -112,7 +111,7 @@ void ESMReader::open(std::unique_ptr<std::istream>&& stream, const std::string &
mHeader.load (*this); mHeader.load (*this);
} }
void ESMReader::open(const std::string &file) void ESMReader::open(const std::filesystem::path &file)
{ {
open(Files::openBinaryInputFileStream(file), file); open(Files::openBinaryInputFileStream(file), file);
} }
@ -360,7 +359,7 @@ std::string ESMReader::getString(int size)
std::stringstream ss; std::stringstream ss;
ss << "ESM Error: " << msg; ss << "ESM Error: " << msg;
ss << "\n File: " << mCtx.filename; ss << "\n File: " << mCtx.filename; //TODO(Project579): This will probably break in windows with unicode paths
ss << "\n Record: " << mCtx.recName.toStringView(); ss << "\n Record: " << mCtx.recName.toStringView();
ss << "\n Subrecord: " << mCtx.subName.toStringView(); ss << "\n Subrecord: " << mCtx.subName.toStringView();
if (mEsm.get()) if (mEsm.get())

@ -5,6 +5,7 @@
#include <vector> #include <vector>
#include <istream> #include <istream>
#include <memory> #include <memory>
#include <filesystem>
#include <components/to_utf8/to_utf8.hpp> #include <components/to_utf8/to_utf8.hpp>
@ -38,7 +39,7 @@ public:
int getFormat() const { return mHeader.mFormat; }; int getFormat() const { return mHeader.mFormat; };
const NAME &retSubName() const { return mCtx.subName; } const NAME &retSubName() const { return mCtx.subName; }
uint32_t getSubSize() const { return mCtx.leftSub; } uint32_t getSubSize() const { return mCtx.leftSub; }
const std::string& getName() const { return mCtx.filename; }; const std::filesystem::path& getName() const { return mCtx.filename; };
bool isOpen() const { return mEsm != nullptr; } bool isOpen() const { return mEsm != nullptr; }
/************************************************************************* /*************************************************************************
@ -62,15 +63,15 @@ public:
/// Raw opening. Opens the file and sets everything up but doesn't /// Raw opening. Opens the file and sets everything up but doesn't
/// parse the header. /// parse the header.
void openRaw(std::unique_ptr<std::istream>&& stream, std::string_view name); void openRaw(std::unique_ptr<std::istream>&& stream, const std::filesystem::path &name);
/// Load ES file from a new stream, parses the header. Closes the /// Load ES file from a new stream, parses the header. Closes the
/// currently open file first, if any. /// currently open file first, if any.
void open(std::unique_ptr<std::istream>&& stream, const std::string &name); void open(std::unique_ptr<std::istream>&& stream, const std::filesystem::path &name);
void open(const std::string &file); void open(const std::filesystem::path &file);
void openRaw(std::string_view filename); void openRaw(const std::filesystem::path &filename);
/// Get the current position in the file. Make sure that the file has been opened! /// Get the current position in the file. Make sure that the file has been opened!
size_t getFileOffset() const { return mEsm->tellg(); }; size_t getFileOffset() const { return mEsm->tellg(); };

@ -131,7 +131,7 @@ namespace ESM
{ {
if(!overriding) if(!overriding)
mWater = std::numeric_limits<float>::max(); mWater = std::numeric_limits<float>::max();
Log(Debug::Warning) << "Warning: Encountered invalid water level in cell " << mName << " defined in " << esm.getContext().filename; Log(Debug::Warning) << "Warning: Encountered invalid water level in cell " << mName << " defined in " << esm.getContext().filename; //TODO(Project579): This will probably break in windows with unicode paths
} }
else else
mWater = waterLevel; mWater = waterLevel;

@ -25,7 +25,7 @@ namespace ESM
{ {
State mState = State::Busy; State mState = State::Busy;
ESMReader mReader; ESMReader mReader;
std::optional<std::string> mName; std::optional<std::filesystem::path> mName;
Item() = default; Item() = default;
}; };

@ -67,7 +67,7 @@ ReaderContext::ReaderContext() : modIndex(0), recHeaderSize(sizeof(RecordHeader)
subRecordHeader.dataSize = 0; subRecordHeader.dataSize = 0;
} }
Reader::Reader(Files::IStreamPtr&& esmStream, const std::string& filename) Reader::Reader(Files::IStreamPtr&& esmStream, const std::filesystem::path &filename)
: mEncoder(nullptr), mFileSize(0), mStream(std::move(esmStream)) : mEncoder(nullptr), mFileSize(0), mStream(std::move(esmStream))
{ {
// used by ESMReader only? // used by ESMReader only?
@ -150,7 +150,7 @@ void Reader::close()
//mHeader.blank(); //mHeader.blank();
} }
void Reader::openRaw(Files::IStreamPtr&& stream, const std::string& filename) void Reader::openRaw(Files::IStreamPtr&& stream, const std::filesystem::path &filename)
{ {
close(); close();
@ -163,7 +163,7 @@ void Reader::openRaw(Files::IStreamPtr&& stream, const std::string& filename)
} }
void Reader::open(Files::IStreamPtr&& stream, const std::string &filename) void Reader::open(Files::IStreamPtr&& stream, const std::filesystem::path &filename)
{ {
openRaw(std::move(stream), filename); openRaw(std::move(stream), filename);
@ -199,21 +199,20 @@ void Reader::setRecHeaderSize(const std::size_t size)
mCtx.recHeaderSize = size; mCtx.recHeaderSize = size;
} }
// FIXME: only "English" strings supported for now
void Reader::buildLStringIndex() void Reader::buildLStringIndex()
{ {
if ((mHeader.mFlags & Rec_ESM) == 0 || (mHeader.mFlags & Rec_Localized) == 0) if ((mHeader.mFlags & Rec_ESM) == 0 || (mHeader.mFlags & Rec_Localized) == 0)
return; return;
std::filesystem::path p(mCtx.filename); const auto filename = mCtx.filename.stem().filename().u8string();
std::string filename = p.stem().filename().string();
buildLStringIndex("Strings/" + filename + "_English.STRINGS", Type_Strings); static const std::filesystem::path s("Strings");
buildLStringIndex("Strings/" + filename + "_English.ILSTRINGS", Type_ILStrings); buildLStringIndex(s / (filename + u8"_English.STRINGS"), Type_Strings);
buildLStringIndex("Strings/" + filename + "_English.DLSTRINGS", Type_DLStrings); buildLStringIndex(s / (filename + u8"_English.ILSTRINGS"), Type_ILStrings);
buildLStringIndex(s / (filename + u8"_English.DLSTRINGS"), Type_DLStrings);
} }
void Reader::buildLStringIndex(const std::string& stringFile, LocalizedStringType stringType) void Reader::buildLStringIndex(const std::filesystem::path &stringFile, LocalizedStringType stringType)
{ {
std::uint32_t numEntries; std::uint32_t numEntries;
std::uint32_t dataSize; std::uint32_t dataSize;
@ -638,7 +637,7 @@ void Reader::adjustGRUPFormId()
std::stringstream ss; std::stringstream ss;
ss << "ESM Error: " << msg; ss << "ESM Error: " << msg;
ss << "\n File: " << mCtx.filename; ss << "\n File: " << mCtx.filename.string(); //TODO(Project579): This will probably break in windows with unicode paths
ss << "\n Record: " << ESM::printName(mCtx.recordHeader.record.typeId); ss << "\n Record: " << ESM::printName(mCtx.recordHeader.record.typeId);
ss << "\n Subrecord: " << ESM::printName(mCtx.subRecordHeader.typeId); ss << "\n Subrecord: " << ESM::printName(mCtx.subRecordHeader.typeId);
if (mStream.get()) if (mStream.get())

@ -47,7 +47,7 @@ namespace ESM4 {
struct ReaderContext struct ReaderContext
{ {
std::string filename; // in case we need to reopen to restore the context std::filesystem::path filename; // in case we need to reopen to restore the context
std::uint32_t modIndex; // the sequential position of this file in the load order: std::uint32_t modIndex; // the sequential position of this file in the load order:
// 0x00 reserved, 0xFF in-game (see notes below) // 0x00 reserved, 0xFF in-game (see notes below)
@ -113,7 +113,7 @@ namespace ESM4 {
std::vector<Reader*>* mGlobalReaderList = nullptr; std::vector<Reader*>* mGlobalReaderList = nullptr;
void buildLStringIndex(const std::string& stringFile, LocalizedStringType stringType); void buildLStringIndex(const std::filesystem::path& stringFile, LocalizedStringType stringType);
inline bool hasLocalizedStrings() const { return (mHeader.mFlags & Rec_Localized) != 0; } inline bool hasLocalizedStrings() const { return (mHeader.mFlags & Rec_Localized) != 0; }
@ -124,11 +124,11 @@ namespace ESM4 {
//void close(); //void close();
// Raw opening. Opens the file and sets everything up but doesn't parse the header. // Raw opening. Opens the file and sets everything up but doesn't parse the header.
void openRaw(Files::IStreamPtr&& stream, const std::string& filename); void openRaw(Files::IStreamPtr&& stream, const std::filesystem::path& filename);
// Load ES file from a new stream, parses the header. // Load ES file from a new stream, parses the header.
// Closes the currently open file first, if any. // Closes the currently open file first, if any.
void open(Files::IStreamPtr&& stream, const std::string& filename); void open(Files::IStreamPtr&& stream, const std::filesystem::path& filename);
Reader() = default; Reader() = default;
@ -137,13 +137,12 @@ namespace ESM4 {
public: public:
Reader(Files::IStreamPtr&& esmStream, const std::string& filename); Reader(Files::IStreamPtr&& esmStream, const std::filesystem::path& filename);
~Reader(); ~Reader();
// FIXME: should be private but ESMTool uses it
void openRaw(const std::string& filename);
void open(const std::string& filename);
void open(const std::filesystem::path& filename);
void close(); void close();
@ -158,7 +157,7 @@ namespace ESM4 {
inline int getFormat() const { return 0; }; // prob. not relevant for ESM4 inline int getFormat() const { return 0; }; // prob. not relevant for ESM4
inline const std::string getDesc() const { return mHeader.mDesc; } inline const std::string getDesc() const { return mHeader.mDesc; }
inline std::string getFileName() const { return mCtx.filename; }; // not used inline std::filesystem::path getFileName() const { return mCtx.filename; }; // not used
inline bool hasMoreRecs() const { return (mFileSize - mCtx.fileRead) > 0; } inline bool hasMoreRecs() const { return (mFileSize - mCtx.fileRead) > 0; }

@ -228,7 +228,7 @@ namespace EsmLoader
for (std::size_t i = 0; i < contentFiles.size(); ++i) for (std::size_t i = 0; i < contentFiles.size(); ++i)
{ {
const std::string &file = contentFiles[i]; const std::string &file = contentFiles[i];
const std::string extension = Misc::StringUtils::lowerCase(std::filesystem::path(file).extension().string()); const std::string extension = Misc::StringUtils::lowerCase(std::filesystem::path(file).extension().string()); //TODO(Project579): let's hope unicode characters are never used in these extensions on windows or this will break
if (supportedFormats.find(extension) == supportedFormats.end()) if (supportedFormats.find(extension) == supportedFormats.end())
{ {
@ -247,7 +247,7 @@ namespace EsmLoader
const ESM::ReadersCache::BusyItem reader = readers.get(i); const ESM::ReadersCache::BusyItem reader = readers.get(i);
reader->setEncoder(encoder); reader->setEncoder(encoder);
reader->setIndex(static_cast<int>(i)); reader->setIndex(static_cast<int>(i));
reader->open(collection.getPath(file).string()); reader->open(collection.getPath(file));
if (query.mLoadCells) if (query.mLoadCells)
reader->resolveParentFileIndices(readers); reader->resolveParentFileIndices(readers);

@ -36,21 +36,19 @@ namespace Files
std::filesystem::path Collections::getPath(const std::string& file) const std::filesystem::path Collections::getPath(const std::string& file) const
{ {
for (Files::PathContainer::const_iterator iter = mDirectories.begin(); for (const auto & mDirectorie : mDirectories)
iter != mDirectories.end(); ++iter)
{ {
for (std::filesystem::directory_iterator iter2 (*iter); for (const auto& iter2 :
iter2!=std::filesystem::directory_iterator(); ++iter2) std::filesystem::directory_iterator (mDirectorie))
{ {
std::filesystem::path path = *iter2; const auto& path = iter2.path();
if (mFoldCase) if (mFoldCase)
{ {
if (Misc::StringUtils::ciEqual(file, path.filename().string())) if (Misc::StringUtils::ciEqual(file, path.filename().string())) //TODO(Project579): This will probably break in windows with unicode paths
return path.string(); return path;
} }
else if (path.filename().string() == file) else if (path.filename().string() == file) //TODO(Project579): This will probably break in windows with unicode paths
return path.string(); return path;
} }
} }
@ -59,20 +57,19 @@ namespace Files
bool Collections::doesExist(const std::string& file) const bool Collections::doesExist(const std::string& file) const
{ {
for (Files::PathContainer::const_iterator iter = mDirectories.begin(); for (const auto & mDirectorie : mDirectories)
iter != mDirectories.end(); ++iter)
{ {
for (std::filesystem::directory_iterator iter2 (*iter); for (const auto& iter2 :
iter2!=std::filesystem::directory_iterator(); ++iter2) std::filesystem::directory_iterator (mDirectorie))
{ {
std::filesystem::path path = *iter2; const auto& path = iter2.path();
if (mFoldCase) if (mFoldCase)
{ {
if (Misc::StringUtils::ciEqual(file, path.filename().string())) if (Misc::StringUtils::ciEqual(file, path.filename().string())) //TODO(Project579): This will probably break in windows with unicode paths
return true; return true;
} }
else if (path.filename().string() == file) else if (path.filename().string() == file) //TODO(Project579): This will probably break in windows with unicode paths
return true; return true;
} }
} }

@ -19,14 +19,14 @@ namespace Files
/// leading dot and must be all lower-case. /// leading dot and must be all lower-case.
const MultiDirCollection& getCollection(const std::string& extension) const; const MultiDirCollection& getCollection(const std::string& extension) const;
std::filesystem::path getPath(const std::string& file) const; std::filesystem::path getPath(const std::string& file) const; //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break
///< Return full path (including filename) of \a file. ///< Return full path (including filename) of \a file.
/// ///
/// If the file does not exist in any of the collection's /// If the file does not exist in any of the collection's
/// directories, an exception is thrown. \a file must include the /// directories, an exception is thrown. \a file must include the
/// extension. /// extension.
bool doesExist(const std::string& file) const; bool doesExist(const std::string& file) const; //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break
///< \return Does a file with the given name exist? ///< \return Does a file with the given name exist?
const Files::PathContainer& getPaths() const; const Files::PathContainer& getPaths() const;

@ -155,9 +155,9 @@ void ConfigurationManager::readConfiguration(bpo::variables_map& variables,
if (!quiet) if (!quiet)
{ {
Log(Debug::Info) << "Logs dir: " << getUserConfigPath().string(); Log(Debug::Info) << "Logs dir: " << getUserConfigPath().string(); //TODO(Project579): This will probably break in windows with unicode paths
Log(Debug::Info) << "User data dir: " << mUserDataPath.string(); Log(Debug::Info) << "User data dir: " << mUserDataPath.string(); //TODO(Project579): This will probably break in windows with unicode paths
Log(Debug::Info) << "Screenshots dir: " << mScreenshotPath.string(); Log(Debug::Info) << "Screenshots dir: " << mScreenshotPath.string(); //TODO(Project579): This will probably break in windows with unicode paths
} }
mSilent = silent; mSilent = silent;
@ -270,7 +270,7 @@ void mergeComposingVariables(bpo::variables_map& first, bpo::variables_map& seco
void ConfigurationManager::processPath(std::filesystem::path& path, const std::filesystem::path& basePath) const void ConfigurationManager::processPath(std::filesystem::path& path, const std::filesystem::path& basePath) const
{ {
std::string str = path.string(); std::string str = path.string(); //TODO(Project579): This will probably break in windows with unicode paths
if (str.empty() || str[0] != '?') if (str.empty() || str[0] != '?')
{ {
@ -285,7 +285,7 @@ void ConfigurationManager::processPath(std::filesystem::path& path, const std::f
auto tokenIt = mTokensMapping.find(str.substr(0, pos + 1)); auto tokenIt = mTokensMapping.find(str.substr(0, pos + 1));
if (tokenIt != mTokensMapping.end()) if (tokenIt != mTokensMapping.end())
{ {
std::filesystem::path tempPath(((mFixedPath).*(tokenIt->second))()); std::filesystem::path tempPath(((mFixedPath).*(tokenIt->second))()); //TODO(Project579): This will probably break in windows with unicode paths
if (pos < str.length() - 1) if (pos < str.length() - 1)
{ {
// There is something after the token, so we should // There is something after the token, so we should
@ -293,7 +293,7 @@ void ConfigurationManager::processPath(std::filesystem::path& path, const std::f
tempPath /= str.substr(pos + 1, str.length() - pos); tempPath /= str.substr(pos + 1, str.length() - pos);
} }
path = tempPath; path = tempPath; //TODO(Project579): This will probably break in windows with unicode paths
} }
else else
{ {
@ -351,7 +351,7 @@ std::optional<bpo::variables_map> ConfigurationManager::loadConfig(
if (std::filesystem::is_regular_file(cfgFile)) if (std::filesystem::is_regular_file(cfgFile))
{ {
if (!mSilent) if (!mSilent)
Log(Debug::Info) << "Loading config file: " << cfgFile.string(); Log(Debug::Info) << "Loading config file: " << cfgFile.string(); //TODO(Project579): This will probably break in windows with unicode paths
std::ifstream configFileStream(cfgFile); std::ifstream configFileStream(cfgFile);
@ -438,7 +438,7 @@ std::istream& operator>> (std::istream& istream, MaybeQuotedPath& MaybeQuotedPat
if (istream && !istream.eof() && istream.peek() != EOF) if (istream && !istream.eof() && istream.peek() != EOF)
{ {
std::string remainder{std::istreambuf_iterator(istream), {}}; std::string remainder{std::istreambuf_iterator(istream), {}};
Log(Debug::Warning) << "Trailing data in path setting. Used '" << MaybeQuotedPath.string() << "' but '" << remainder << "' remained"; Log(Debug::Warning) << "Trailing data in path setting. Used '" << MaybeQuotedPath.string() << "' but '" << remainder << "' remained"; //TODO(Project579): This will probably break in windows with unicode paths
} }
} }
else else

@ -1,8 +1,10 @@
#include <filesystem>
#include "constrainedfilestream.hpp" #include "constrainedfilestream.hpp"
namespace Files namespace Files
{ {
IStreamPtr openConstrainedFileStream(const std::string& filename, std::size_t start, std::size_t length) IStreamPtr openConstrainedFileStream(const std::filesystem::path &filename, std::size_t start, std::size_t length)
{ {
return std::make_unique<ConstrainedFileStream>(std::make_unique<ConstrainedFileStreamBuf>(filename, start, length)); return std::make_unique<ConstrainedFileStream>(std::make_unique<ConstrainedFileStreamBuf>(filename, start, length));
} }

@ -14,7 +14,7 @@ namespace Files
/// A file stream constrained to a specific region in the file, specified by the 'start' and 'length' parameters. /// A file stream constrained to a specific region in the file, specified by the 'start' and 'length' parameters.
using ConstrainedFileStream = StreamWithBuffer<ConstrainedFileStreamBuf>; using ConstrainedFileStream = StreamWithBuffer<ConstrainedFileStreamBuf>;
IStreamPtr openConstrainedFileStream(const std::string& filename, std::size_t start = 0, IStreamPtr openConstrainedFileStream(const std::filesystem::path &filename, std::size_t start = 0,
std::size_t length = std::numeric_limits<std::size_t>::max()); std::size_t length = std::numeric_limits<std::size_t>::max());
} }

@ -2,12 +2,13 @@
#include <algorithm> #include <algorithm>
#include <limits> #include <limits>
#include <filesystem>
namespace Files namespace Files
{ {
namespace File = Platform::File; namespace File = Platform::File;
ConstrainedFileStreamBuf::ConstrainedFileStreamBuf(const std::string& fname, std::size_t start, std::size_t length) ConstrainedFileStreamBuf::ConstrainedFileStreamBuf(const std::filesystem::path& fname, std::size_t start, std::size_t length)
: mOrigin(start) : mOrigin(start)
{ {
mFile = File::open(fname.c_str()); mFile = File::open(fname.c_str());

@ -11,7 +11,7 @@ namespace Files
class ConstrainedFileStreamBuf final : public std::streambuf class ConstrainedFileStreamBuf final : public std::streambuf
{ {
public: public:
ConstrainedFileStreamBuf(const std::string& fname, std::size_t start, std::size_t length); ConstrainedFileStreamBuf(const std::filesystem::path &fname, std::size_t start, std::size_t length);
int_type underflow() final; int_type underflow() final;

@ -9,7 +9,7 @@
namespace Files namespace Files
{ {
std::array<std::uint64_t, 2> getHash(const std::string& fileName, std::istream& stream) std::array<std::uint64_t, 2> getHash(const std::filesystem::path& fileName, std::istream& stream)
{ {
std::array<std::uint64_t, 2> hash {0, 0}; std::array<std::uint64_t, 2> hash {0, 0};
try try
@ -34,7 +34,7 @@ namespace Files
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
throw std::runtime_error("Error while reading \"" + fileName + "\" to get hash: " + std::string(e.what())); throw std::runtime_error("Error while reading \"" + fileName.string() + "\" to get hash: " + std::string(e.what())); //TODO(Project579): This will probably break in windows with unicode paths
} }
return hash; return hash;
} }

@ -4,11 +4,11 @@
#include <array> #include <array>
#include <cstdint> #include <cstdint>
#include <iosfwd> #include <iosfwd>
#include <string> #include <filesystem>
namespace Files namespace Files
{ {
std::array<std::uint64_t, 2> getHash(const std::string& fileName, std::istream& stream); std::array<std::uint64_t, 2> getHash(const std::filesystem::path& fileName, std::istream& stream);
} }
#endif #endif

@ -51,9 +51,12 @@ namespace Files
LinuxPath::LinuxPath(const std::string& application_name) LinuxPath::LinuxPath(const std::string& application_name)
: mName(application_name) : mName(application_name)
{ {
std::filesystem::path localPath = getLocalPath(); std::error_code ec;
if (chdir(localPath.string().c_str()) != 0) current_path(getLocalPath(), ec);
Log(Debug::Warning) << "Error " << errno << " when changing current directory"; const auto err = ec.value();
if (err != 0) {
Log(Debug::Warning) << "Error " << err << " " << std::strerror(err) << " when changing current directory";
}
} }
std::filesystem::path LinuxPath::getUserConfigPath() const std::filesystem::path LinuxPath::getUserConfigPath() const
@ -79,18 +82,16 @@ std::filesystem::path LinuxPath::getGlobalConfigPath() const
std::filesystem::path LinuxPath::getLocalPath() const std::filesystem::path LinuxPath::getLocalPath() const
{ {
std::filesystem::path localPath("./"); auto localPath = std::filesystem::current_path();
const char *statusPaths[] = {"/proc/self/exe", "/proc/self/file", "/proc/curproc/exe", "/proc/curproc/file"}; static const std::filesystem::path statusPaths[] = {"/proc/self/exe", "/proc/self/file", "/proc/curproc/exe", "/proc/curproc/file"};
for(const char *path : statusPaths) for(const auto& path : statusPaths)
{ {
std::filesystem::path statusPath(path); std::error_code ec;
if (!std::filesystem::exists(statusPath)) continue; const auto binPath = read_symlink(path, ec);
if (ec.value() != -1)
statusPath = std::filesystem::read_symlink(statusPath);
if (!std::filesystem::is_empty(statusPath))
{ {
localPath = statusPath.parent_path() / "/"; localPath = binPath.parent_path();
break; break;
} }
} }

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save