From aaad0c2b2089acd434892e582e5d8f1078a587e1 Mon Sep 17 00:00:00 2001 From: wareya Date: Fri, 11 Jul 2025 11:40:50 -0400 Subject: [PATCH] texture reload debug command --- apps/openmw/mwlua/debugbindings.cpp | 8 +++++++ components/resource/imagemanager.cpp | 33 +++++++++++++++++++++++----- components/resource/imagemanager.hpp | 3 +++ 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwlua/debugbindings.cpp b/apps/openmw/mwlua/debugbindings.cpp index dcb77580ce..cdafef9a72 100644 --- a/apps/openmw/mwlua/debugbindings.cpp +++ b/apps/openmw/mwlua/debugbindings.cpp @@ -10,6 +10,7 @@ #include "../mwrender/postprocessor.hpp" #include "../mwrender/renderingmanager.hpp" +#include #include #include #include @@ -82,6 +83,13 @@ namespace MWLua }); }; + api["triggerTextureReload"] = [context]() { + context.mLuaManager->addAction([] { + auto imageManager = MWBase::Environment::get().getResourceSystem()->getImageManager(); + imageManager->attemptGlobalReload(); + }); + }; + api["setShaderHotReloadEnabled"] = [context](bool value) { context.mLuaManager->addAction([value] { auto world = MWBase::Environment::get().getWorld(); diff --git a/components/resource/imagemanager.cpp b/components/resource/imagemanager.cpp index b7a19b4d52..0b480936d1 100644 --- a/components/resource/imagemanager.cpp +++ b/components/resource/imagemanager.cpp @@ -85,12 +85,39 @@ namespace Resource return true; } + void ImageManager::attemptGlobalReload() + { + mCache->call([&](std::string name, osg::Object* obj) { + auto image = performLoad(VFS::Path::NormalizedView(name.data())); + image->swap(*static_cast(obj)); + static_cast(obj)->dirty(); + }); + } + osg::ref_ptr ImageManager::getImage(VFS::Path::NormalizedView path, bool disableFlip) { osg::ref_ptr obj = mCache->getRefFromObjectCache(path); if (obj) return osg::ref_ptr(static_cast(obj.get())); else + { + auto image = performLoad(path, disableFlip); + // Duplicate the image we got if it's the warning image, so that we can't thrash it + if (image == mWarningImage) + { + // The warning image is like 8x8 so it's not really a problem to deeply clone it. + // We want each usage to have its own osg::Image so that assigning into the cache is safe. + auto cloned = mWarningImage.get()->clone(osg::CopyOp(osg::CopyOp::Options::DEEP_COPY_ALL)); + image = static_cast(cloned); // constructs a ref_ptr during assignment + } + mCache->addEntryToObjectCache(path.value(), image); + return image; + } + } + + osg::ref_ptr ImageManager::performLoad(VFS::Path::NormalizedView path, bool disableFlip) + { + if (true) // for diff reduction indentation { Files::IStreamPtr stream; try @@ -100,7 +127,6 @@ namespace Resource catch (std::exception& e) { Log(Debug::Error) << "Failed to open image: " << e.what(); - mCache->addEntryToObjectCache(path.value(), mWarningImage); return mWarningImage; } @@ -109,7 +135,6 @@ namespace Resource if (!reader) { Log(Debug::Error) << "Error loading " << path << ": no readerwriter for '" << ext << "' found"; - mCache->addEntryToObjectCache(path.value(), mWarningImage); return mWarningImage; } @@ -122,7 +147,6 @@ namespace Resource if (stream->gcount() != 18) { Log(Debug::Error) << "Error loading " << path << ": couldn't read TGA header"; - mCache->addEntryToObjectCache(path.value(), mWarningImage); return mWarningImage; } int type = header[2]; @@ -142,7 +166,6 @@ namespace Resource { Log(Debug::Error) << "Error loading " << path << ": " << result.message() << " code " << result.status(); - mCache->addEntryToObjectCache(path.value(), mWarningImage); return mWarningImage; } @@ -155,7 +178,6 @@ namespace Resource if (!uncompress) { Log(Debug::Error) << "Error loading " << path << ": no S3TC texture compression support installed"; - mCache->addEntryToObjectCache(path.value(), mWarningImage); return mWarningImage; } else @@ -186,7 +208,6 @@ namespace Resource image = newImage; } - mCache->addEntryToObjectCache(path.value(), image); return image; } } diff --git a/components/resource/imagemanager.hpp b/components/resource/imagemanager.hpp index ead55c792a..c0692f2da6 100644 --- a/components/resource/imagemanager.hpp +++ b/components/resource/imagemanager.hpp @@ -33,6 +33,8 @@ namespace Resource void reportStats(unsigned int frameNumber, osg::Stats* stats) const override; + void attemptGlobalReload(); + private: osg::ref_ptr mWarningImage; osg::ref_ptr mOptions; @@ -40,6 +42,7 @@ namespace Resource ImageManager(const ImageManager&); void operator=(const ImageManager&); + osg::ref_ptr performLoad(VFS::Path::NormalizedView name, bool disableFlip = false); }; }