diff --git a/lib/ivis_opengl/imd.h b/lib/ivis_opengl/imd.h index f23944372bd..703308eff01 100644 --- a/lib/ivis_opengl/imd.h +++ b/lib/ivis_opengl/imd.h @@ -67,4 +67,6 @@ const WzString &modelName(const iIMDShape *model); iIMDBaseShape *modelGet(const WzString &filename); +void modelReloadAllModelTextures(); + #endif diff --git a/lib/ivis_opengl/imdload.cpp b/lib/ivis_opengl/imdload.cpp index cfaa470d827..72e7e42bc12 100644 --- a/lib/ivis_opengl/imdload.cpp +++ b/lib/ivis_opengl/imdload.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include "lib/framework/frame.h" @@ -115,6 +116,30 @@ void modelShutdown() models.clear(); } +void modelReloadAllModelTextures() +{ + std::unordered_set texPagesToReloadFromDisk; + enumerateLoadedModels([&texPagesToReloadFromDisk](const std::string &modelName, iIMDBaseShape &s){ + for (iIMDShape *pDisplayShape = s.displayModel(); pDisplayShape != nullptr; pDisplayShape = pDisplayShape->next.get()) + { + const iIMDShapeTextures& textures = pDisplayShape->getTextures(); + if (!textures.initialized) + { + continue; + } + std::array pages = {textures.texpage, textures.tcmaskpage, textures.normalpage, textures.specularpage}; + for (auto page : pages) + { + if (page != iV_TEX_INVALID) + { + texPagesToReloadFromDisk.insert(page); + } + } + } + }); + debugReloadTexturesFromDisk(texPagesToReloadFromDisk); +} + void modelUpdateTilesetIdx(size_t tilesetIdx) { if (tilesetIdx == currentTilesetIdx) diff --git a/lib/ivis_opengl/tex.cpp b/lib/ivis_opengl/tex.cpp index 0734a71b475..39c235d575f 100644 --- a/lib/ivis_opengl/tex.cpp +++ b/lib/ivis_opengl/tex.cpp @@ -244,6 +244,25 @@ bool replaceTexture(const WzString &oldfile, const WzString &newfile) return false; } +bool debugReloadTexturesFromDisk(const std::unordered_set& texPages) +{ + std::string filename; + for (auto page : texPages) + { + gfx_api::texture_type existingTextureType = _TEX_PAGE[page].textureType; + filename = _TEX_PAGE[page].filename; + debug(LOG_TEXTURE, "Reloading texture %s from index %zu", filename.c_str(), page); + gfx_api::texture *pTexture = loadTextureHandleGraphicsOverrides(filename.c_str(), existingTextureType); + if (!pTexture) + { + debug(LOG_INFO, "Failed to reload texture: %s", filename.c_str()); + continue; + } + pie_AddTexPage(pTexture, filename.c_str(), existingTextureType, page); + } + return true; +} + void pie_TexShutDown() { // TODO, lazy deletions for faster loading of next level diff --git a/lib/ivis_opengl/tex.h b/lib/ivis_opengl/tex.h index 2f54c3503bf..cb302c23791 100644 --- a/lib/ivis_opengl/tex.h +++ b/lib/ivis_opengl/tex.h @@ -25,6 +25,7 @@ #include "png_util.h" #include +#include #include using nonstd::optional; using nonstd::nullopt; @@ -55,6 +56,8 @@ void pie_TexInit(); std::string pie_MakeTexPageName(const std::string& filename); std::string pie_MakeTexPageTCMaskName(const std::string& filename); +bool debugReloadTexturesFromDisk(const std::unordered_set& texPages); + //************************************************************************* void pie_TexShutDown(); diff --git a/src/wzscriptdebug.cpp b/src/wzscriptdebug.cpp index 65c55d9e5c9..c95e4518274 100644 --- a/src/wzscriptdebug.cpp +++ b/src/wzscriptdebug.cpp @@ -918,14 +918,19 @@ class WzGraphicsPanel : public W_FORM { auto panel = std::make_shared(); - auto prevButton = panel->createButton(0, "Reload terrain and water textures", [](){ + auto prevButton = panel->createButton(0, "Reload terrain & water textures", [](){ loadTerrainTextures(currentMapTileset); debug(LOG_INFO, "Done"); }); - panel->createButton(0, "Reload decal textures", [](){ + prevButton = panel->createButton(0, "Reload decals", [](){ reloadTileTextures(); debug(LOG_INFO, "Done"); }, prevButton); + prevButton = panel->createButton(0, "Reload model textures", [](){ + debug(LOG_INFO, "Reloading all model textures"); + modelReloadAllModelTextures(); + debug(LOG_INFO, "Done"); + }, prevButton); prevButton = panel->createButton(1, "Recompile All Shaders", [](){ debug(LOG_INFO, "Recompiling all shader pipelines");