diff --git a/libs/gamelib.h b/libs/gamelib.h index 298a726c77..be41985adf 100644 --- a/libs/gamelib.h +++ b/libs/gamelib.h @@ -1,6 +1,7 @@ #pragma once #include "igame.h" +#include "itextstream.h" #include "registry/registry.h" #include "string/convert.h" #include "os/path.h" @@ -91,6 +92,26 @@ inline std::vector getLightTexturePrefixes() return prefixes; } +/** + * Returns the path where DarkRadiant is able to write custom game resources (like decls) to. + * This defaults to the mod path and falls back to the user engine path if not found. + * Does not create any directories. + */ +inline std::string getWriteableGameResourcePath() +{ + // Try the mod path first + auto targetPath = GlobalGameManager().getModPath(); + + if (targetPath.empty()) + { + targetPath = GlobalGameManager().getUserEnginePath(); + + rMessage() << "No mod path found, falling back to user engine path: " << targetPath << std::endl; + } + + return targetPath; +} + } // namespace } // namespace diff --git a/radiant/ui/materials/editor/MaterialEditor.cpp b/radiant/ui/materials/editor/MaterialEditor.cpp index 577c00ade7..716cf60ba2 100644 --- a/radiant/ui/materials/editor/MaterialEditor.cpp +++ b/radiant/ui/materials/editor/MaterialEditor.cpp @@ -1377,20 +1377,20 @@ bool MaterialEditor::saveCurrentMaterial() // Ask the user where to save it wxutil::FileChooser chooser(this, _("Select Material file"), false, "material", "." + mtrExtension); - fs::path modMaterialsPath = GlobalGameManager().getModPath(); - modMaterialsPath /= materialsFolderName; + fs::path materialsPath = game::current::getWriteableGameResourcePath(); + materialsPath /= materialsFolderName; - if (!os::fileOrDirExists(modMaterialsPath.string())) + if (!os::fileOrDirExists(materialsPath.string())) { - rMessage() << "Ensuring mod materials path: " << modMaterialsPath << std::endl; - fs::create_directories(modMaterialsPath); + rMessage() << "Ensuring materials path: " << materialsPath << std::endl; + fs::create_directories(materialsPath); } // Point the file chooser to that new file - chooser.setCurrentPath(GlobalGameManager().getModPath() + materialsFolderName); + chooser.setCurrentPath(materialsPath.string()); chooser.askForOverwrite(false); - std::string result = chooser.display(); + auto result = chooser.display(); if (result.empty()) { diff --git a/radiantcore/decl/DeclarationManager.cpp b/radiantcore/decl/DeclarationManager.cpp index 33742e33ad..20abc284c5 100644 --- a/radiantcore/decl/DeclarationManager.cpp +++ b/radiantcore/decl/DeclarationManager.cpp @@ -13,6 +13,7 @@ #include "string/trim.h" #include "os/path.h" #include "fmt/format.h" +#include "gamelib.h" #include "stream/TemporaryOutputStream.h" #include "util/ScopedBoolLock.h" @@ -418,15 +419,7 @@ void DeclarationManager::saveDeclaration(const IDeclaration::Ptr& decl) std::string relativePath = syntax.fileInfo.fullPath(); - fs::path targetPath = GlobalGameManager().getModPath(); - - if (targetPath.empty()) - { - targetPath = GlobalGameManager().getUserEnginePath(); - - rMessage() << "No mod base path found, falling back to user engine path to save particle file: " << - targetPath.string() << std::endl; - } + fs::path targetPath = game::current::getWriteableGameResourcePath(); // Ensure the target folder exists targetPath /= os::getDirectory(relativePath);