diff --git a/CMakeLists.txt b/CMakeLists.txt index 30975c92..7195ee02 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1299,6 +1299,7 @@ add_executable(wowee_editor tools/editor/content_pack.cpp tools/editor/wowee_terrain.cpp tools/editor/editor_project.cpp + tools/editor/texture_exporter.cpp tools/editor/asset_browser.cpp tools/editor/editor_water.cpp tools/editor/editor_markers.cpp diff --git a/tools/editor/editor_app.cpp b/tools/editor/editor_app.cpp index f7fa58f3..d8e70df4 100644 --- a/tools/editor/editor_app.cpp +++ b/tools/editor/editor_app.cpp @@ -3,6 +3,7 @@ #include "zone_manifest.hpp" #include "content_pack.hpp" #include "wowee_terrain.hpp" +#include "texture_exporter.hpp" #include "core/coordinates.hpp" #include "rendering/vk_context.hpp" #include "pipeline/adt_loader.hpp" @@ -731,6 +732,14 @@ void EditorApp::exportZone(const std::string& outputDir) { objectPlacer_.saveToFile(objPath); } + // Export used textures as PNG (open format replacement for BLP) + auto usedTextures = TextureExporter::collectUsedTextures(terrain_); + if (!usedTextures.empty()) { + int exported = TextureExporter::exportTexturesAsPng( + assetManager_.get(), usedTextures, base + "/textures"); + LOG_INFO("Exported ", exported, " textures as PNG"); + } + // Export open terrain format alongside ADT std::string openBase = base + "/" + loadedMap_ + "_" + std::to_string(loadedTileX_) + "_" + std::to_string(loadedTileY_); diff --git a/tools/editor/texture_exporter.cpp b/tools/editor/texture_exporter.cpp new file mode 100644 index 00000000..fd9c7257 --- /dev/null +++ b/tools/editor/texture_exporter.cpp @@ -0,0 +1,64 @@ +#include "texture_exporter.hpp" +#include "pipeline/asset_manager.hpp" +#include "pipeline/blp_loader.hpp" +#include "core/logger.hpp" +#include +#include + +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image_write.h" + +namespace wowee { +namespace editor { + +std::vector TextureExporter::collectUsedTextures(const pipeline::ADTTerrain& terrain) { + std::unordered_set unique; + for (const auto& tex : terrain.textures) + unique.insert(tex); + std::vector result(unique.begin(), unique.end()); + std::sort(result.begin(), result.end()); + return result; +} + +int TextureExporter::exportTexturesAsPng(pipeline::AssetManager* am, + const std::vector& texturePaths, + const std::string& outputDir) { + namespace fs = std::filesystem; + int exported = 0; + + for (const auto& texPath : texturePaths) { + auto blpImage = am->loadTexture(texPath); + if (!blpImage.isValid()) { + LOG_WARNING("Texture not found or invalid: ", texPath); + continue; + } + + // Build output path: replace backslashes, change .blp to .png + std::string outPath = texPath; + std::replace(outPath.begin(), outPath.end(), '\\', '/'); + // Lowercase + std::transform(outPath.begin(), outPath.end(), outPath.begin(), + [](unsigned char c) { return std::tolower(c); }); + // Change extension + auto dotPos = outPath.rfind('.'); + if (dotPos != std::string::npos) + outPath = outPath.substr(0, dotPos) + ".png"; + + std::string fullPath = outputDir + "/" + outPath; + fs::create_directories(fs::path(fullPath).parent_path()); + + // Write RGBA data as PNG + if (stbi_write_png(fullPath.c_str(), blpImage.width, blpImage.height, 4, + blpImage.data.data(), blpImage.width * 4)) { + exported++; + } else { + LOG_WARNING("Failed to write PNG: ", fullPath); + } + } + + LOG_INFO("Exported ", exported, "/", texturePaths.size(), " textures as PNG to ", outputDir); + return exported; +} + +} // namespace editor +} // namespace wowee diff --git a/tools/editor/texture_exporter.hpp b/tools/editor/texture_exporter.hpp new file mode 100644 index 00000000..f483be3a --- /dev/null +++ b/tools/editor/texture_exporter.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include "pipeline/adt_loader.hpp" +#include +#include +#include + +namespace wowee { +namespace pipeline { class AssetManager; } + +namespace editor { + +class TextureExporter { +public: + // Collect all texture paths referenced by the terrain + static std::vector collectUsedTextures(const pipeline::ADTTerrain& terrain); + + // Export all used textures as PNG to an output directory + // Returns count of successfully exported textures + static int exportTexturesAsPng(pipeline::AssetManager* am, + const std::vector& texturePaths, + const std::string& outputDir); +}; + +} // namespace editor +} // namespace wowee