From bcc5142b32ad7f4e7fb2c1f036011a1063be4e96 Mon Sep 17 00:00:00 2001 From: Nat Meo Date: Tue, 2 Jul 2019 16:07:38 +0000 Subject: [PATCH] Issue #4202: Open .omwaddon files without needing to open openmw-cs first. --- CHANGELOG.md | 1 + apps/opencs/editor.cpp | 72 ++++++++++++++++++++++++++++---- apps/opencs/editor.hpp | 5 ++- components/files/linuxpath.cpp | 21 +++++++++- components/files/windowspath.cpp | 18 +++++++- 5 files changed, 106 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6c55a525..3ba7febd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Bug #3765: DisableTeleporting makes Mark/Recall/Intervention effects undetectable Bug #3778: [Mod] Improved Thrown Weapon Projectiles - weapons have wrong transformation during throw animation Bug #3812: Wrong multiline tooltips width when word-wrapping is enabled + Bug #4202: Open .omwaddon files without needing toopen openmw-cs first Bug #4240: Ash storm origin coordinates and hand shielding animation behavior are incorrect Bug #4329: Removed birthsign abilities are restored after reloading the save Bug #4341: Error message about missing GDB is too vague diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index b22f5464d..0ce031548 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -27,6 +27,11 @@ CS::Editor::Editor (int argc, char **argv) std::pair > config = readConfig(); mViewManager = new CSVDoc::ViewManager(mDocumentManager); + if (argc > 1) + { + mFileToLoad = argv[1]; + mDataDirs = config.first; + } NifOsg::Loader::setShowMarkers(true); @@ -103,9 +108,9 @@ std::pair > CS::Editor::readConfi Fallback::Map::init(variables["fallback"].as().mMap); - const std::string encoding = variables["encoding"].as().toStdString(); - mDocumentManager.setEncoding (ToUTF8::calculateEncoding (encoding)); - mFileDialog.setEncoding (QString::fromUtf8(encoding.c_str())); + mEncodingName = variables["encoding"].as().toStdString(); + mDocumentManager.setEncoding(ToUTF8::calculateEncoding(mEncodingName)); + mFileDialog.setEncoding (QString::fromUtf8(mEncodingName.c_str())); mDocumentManager.setResourceDir (mResources = variables["resources"].as().toStdString()); @@ -217,12 +222,19 @@ void CS::Editor::loadDocument() mFileDialog.showDialog (CSVDoc::ContentAction_Edit); } -void CS::Editor::openFiles (const boost::filesystem::path &savePath) +void CS::Editor::openFiles (const boost::filesystem::path &savePath, const std::vector &discoveredFiles) { std::vector files; - foreach (const QString &path, mFileDialog.selectedFilePaths()) - files.push_back(path.toUtf8().constData()); + if(discoveredFiles.empty()) + { + foreach(const QString &path, mFileDialog.selectedFilePaths()) + files.push_back(path.toUtf8().constData()); + } + else + { + files = discoveredFiles; + } mDocumentManager.addDocument (files, savePath, false); @@ -348,9 +360,53 @@ int CS::Editor::run() Misc::Rng::init(); - mStartup.show(); + QApplication::setQuitOnLastWindowClosed(true); - QApplication::setQuitOnLastWindowClosed (true); + if (mFileToLoad.empty()) + { + mStartup.show(); + } + else + { + ESM::ESMReader fileReader; + ToUTF8::Utf8Encoder encoder = ToUTF8::calculateEncoding(mEncodingName); + fileReader.setEncoder(&encoder); + fileReader.open(mFileToLoad.string()); + + std::vector discoveredFiles; + + for (std::vector::const_iterator itemIter = fileReader.getGameFiles().begin(); + itemIter != fileReader.getGameFiles().end(); ++itemIter) + { + for (Files::PathContainer::const_iterator pathIter = mDataDirs.begin(); + pathIter != mDataDirs.end(); ++pathIter) + { + const boost::filesystem::path masterPath = *pathIter / itemIter->name; + if (boost::filesystem::exists(masterPath)) + { + discoveredFiles.push_back(masterPath); + break; + } + } + } + discoveredFiles.push_back(mFileToLoad); + + QString extension = QString::fromStdString(mFileToLoad.extension().string()).toLower(); + if (extension == ".esm") + { + mFileToLoad.replace_extension(".omwgame"); + mDocumentManager.addDocument(discoveredFiles, mFileToLoad, false); + } + else if (extension == ".esp") + { + mFileToLoad.replace_extension(".omwaddon"); + mDocumentManager.addDocument(discoveredFiles, mFileToLoad, false); + } + else + { + openFiles(mFileToLoad, discoveredFiles); + } + } return QApplication::exec(); } diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index 0c3ece905..1c9342761 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -54,6 +54,9 @@ namespace CS bool mFsStrict; CSVTools::Merge mMerge; CSVDoc::ViewManager* mViewManager; + boost::filesystem::path mFileToLoad; + Files::PathContainer mDataDirs; + std::string mEncodingName; std::pair > readConfig(bool quiet=false); ///< \return data paths @@ -81,7 +84,7 @@ namespace CS void cancelFileDialog(); void loadDocument(); - void openFiles (const boost::filesystem::path &path); + void openFiles (const boost::filesystem::path &path, const std::vector &discoveredFiles = std::vector()); void createNewFile (const boost::filesystem::path& path); void createNewGame (const boost::filesystem::path& file); diff --git a/components/files/linuxpath.cpp b/components/files/linuxpath.cpp index 3743eef4c..f2ecb7c13 100644 --- a/components/files/linuxpath.cpp +++ b/components/files/linuxpath.cpp @@ -4,8 +4,10 @@ #include #include +#include #include +#include #include @@ -50,6 +52,9 @@ namespace Files LinuxPath::LinuxPath(const std::string& application_name) : mName(application_name) { + boost::filesystem::path localPath = getLocalPath(); + if (chdir(localPath.string().c_str()) != 0) + Log(Debug::Warning) << "Error " << errno << " when changing current directory"; } boost::filesystem::path LinuxPath::getUserConfigPath() const @@ -75,7 +80,21 @@ boost::filesystem::path LinuxPath::getGlobalConfigPath() const boost::filesystem::path LinuxPath::getLocalPath() const { - return boost::filesystem::path("./"); + boost::filesystem::path localPath("./"); + char binPath[PATH_MAX]; + memset(binPath, 0, sizeof(binPath)); + const char *statusPaths[] = {"/proc/self/exe", "/proc/self/file", "/proc/curproc/exe", "/proc/curproc/file"}; + + for(const char *path : statusPaths) + { + if (readlink(path, binPath, sizeof(binPath)) != -1) + { + localPath = boost::filesystem::path(binPath).parent_path(); + break; + } + } + + return localPath; } boost::filesystem::path LinuxPath::getGlobalDataPath() const diff --git a/components/files/windowspath.cpp b/components/files/windowspath.cpp index 2354e6f31..516f26021 100644 --- a/components/files/windowspath.cpp +++ b/components/files/windowspath.cpp @@ -11,6 +11,8 @@ #include namespace bconv = boost::locale::conv; +#include + /** * FIXME: Someone with Windows system should check this and correct if necessary * FIXME: MAX_PATH is irrelevant for extended-length paths, i.e. \\?\... @@ -33,6 +35,10 @@ WindowsPath::WindowsPath(const std::string& application_name) See boost::filesystem and boost::locale reference for details. */ boost::filesystem::path::imbue(boost::locale::generator().generate("")); + + boost::filesystem::path localPath = getLocalPath(); + if (!SetCurrentDirectoryA(localPath.string().c_str())) + Log(Debug::Warning) << "Error " << GetLastError() << " when changing current directory"; } boost::filesystem::path WindowsPath::getUserConfigPath() const @@ -73,7 +79,17 @@ boost::filesystem::path WindowsPath::getGlobalConfigPath() const boost::filesystem::path WindowsPath::getLocalPath() const { - return boost::filesystem::path("./"); + boost::filesystem::path localPath("./"); + WCHAR path[MAX_PATH + 1]; + memset(path, 0, sizeof(path)); + + if (GetModuleFileNameW(nullptr, path, MAX_PATH + 1) > 0) + { + localPath = boost::filesystem::path(bconv::utf_to_utf(path)).parent_path(); + } + + // lookup exe path + return localPath; } boost::filesystem::path WindowsPath::getGlobalDataPath() const