#options GAME (IW3, IW4, IW5, T4, T5, T6) #filename "Game/" + GAME + "/Image/ImageDumper" + GAME + ".cpp" #set DUMPER_HEADER "\"ImageDumper" + GAME + ".h\"" #if GAME == "IW3" #define FEATURE_IW3 #define DX9 #define IWI6 #elif GAME == "T4" #define FEATURE_T4 #define DX9 #define IWI6 #elif GAME == "IW4" #define FEATURE_IW4 #define DX9 #define IWI8 #elif GAME == "IW5" #define FEATURE_IW5 #define DX9 #define IWI8 #elif GAME == "T5" #define FEATURE_T5 #define DX9 #define IWI13 #elif GAME == "T6" #define FEATURE_T6 #define DX11 #define IWI27 #endif // This file was templated. // See ImageDumper.cpp.template. // Do not modify, changes will be lost. #include DUMPER_HEADER #ifdef DX9 #include "Image/Dx9TextureLoader.h" #else #include "Image/Dx12TextureLoader.h" #endif #ifdef FEATURE_T6 #include "ObjContainer/IPak/IPak.h" #endif #if defined(IWI6) #include "Image/IwiWriter6.h" #define IWI_NS iwi6 #elif defined(IWI8) #include "Image/IwiWriter8.h" #define IWI_NS iwi8 #elif defined(IWI13) #include "Image/IwiWriter13.h" #define IWI_NS iwi13 #elif defined(IWI27) #include "Image/IwiWriter27.h" #define IWI_NS iwi27 #endif #include "Image/DdsWriter.h" #include "Image/ImageCommon.h" #include "Image/IwiLoader.h" #include "ObjWriting.h" #include "Utils/Logging/Log.h" #include #include #include using namespace GAME; using namespace image; namespace { std::unique_ptr LoadImageFromLoadDef(const GfxImage& image) { #ifdef DX9 Dx9TextureLoader textureLoader; #else Dx12TextureLoader textureLoader; #endif const auto& loadDef = *image.texture.loadDef; #if defined(FEATURE_IW3) || defined(FEATURE_T4) textureLoader.Width(loadDef.dimensions[0]).Height(loadDef.dimensions[1]).Depth(loadDef.dimensions[2]); #else textureLoader.Width(image.width).Height(image.height).Depth(image.depth); #endif #if defined(IWI8) if ((loadDef.flags & image::IWI_NS::IMG_FLAG_MAPTYPE_MASK) == image::IWI_NS::IMG_FLAG_MAPTYPE_3D) textureLoader.Type(TextureType::T_3D); else if ((loadDef.flags & image::IWI_NS::IMG_FLAG_MAPTYPE_MASK) == image::IWI_NS::IMG_FLAG_MAPTYPE_CUBE) textureLoader.Type(TextureType::T_CUBE); else textureLoader.Type(TextureType::T_2D); #else if (loadDef.flags & image::IWI_NS::IMG_FLAG_VOLMAP) textureLoader.Type(TextureType::T_3D); else if (loadDef.flags & image::IWI_NS::IMG_FLAG_CUBEMAP) textureLoader.Type(TextureType::T_CUBE); else textureLoader.Type(TextureType::T_2D); #endif #ifdef DX9 textureLoader.Format(static_cast(loadDef.format)); #else textureLoader.Format(static_cast(loadDef.format)); #endif textureLoader.HasMipMaps(!(loadDef.flags & image::IWI_NS::IMG_FLAG_NOMIPMAPS)); return textureLoader.LoadTexture(loadDef.data); } std::unique_ptr LoadImageFromIwi(const GfxImage& image, ISearchPath& searchPath) { #ifdef FEATURE_T6 if (image.streamedPartCount > 0) { for (auto* ipak : IIPak::Repository) { auto ipakStream = ipak->GetEntryStream(image.hash, image.streamedParts[0].hash); if (ipakStream) { auto loadResult = image::LoadIwi(*ipakStream); ipakStream->close(); if (loadResult) return std::move(loadResult->m_texture); } } } #endif const auto imageFileName = image::GetFileNameForAsset(image.name, ".iwi"); const auto filePathImage = searchPath.Open(imageFileName); if (!filePathImage.IsOpen()) { con::error("Could not find data for image \"{}\"", image.name); return nullptr; } auto loadResult = image::LoadIwi(*filePathImage.m_stream); return loadResult ? std::move(loadResult->m_texture) : nullptr; } std::unique_ptr LoadImageData(ISearchPath& searchPath, const GfxImage& image) { if (image.texture.loadDef && image.texture.loadDef->resourceSize > 0) return LoadImageFromLoadDef(image); return LoadImageFromIwi(image, searchPath); } } // namespace #set CLASS_NAME "Dumper" + GAME namespace image { CLASS_NAME::CLASS_NAME() { switch (ObjWriting::Configuration.ImageOutputFormat) { case ImageOutputFormat_e::DDS: m_writer = std::make_unique(); break; case ImageOutputFormat_e::IWI: m_writer = std::make_unique(); break; default: assert(false); m_writer = nullptr; break; } } void CLASS_NAME::DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) { const auto* image = asset.Asset(); const auto texture = LoadImageData(context.m_obj_search_path, *image); if (!texture) return; if (!m_writer->SupportsImageFormat(texture->GetFormat())) { con::warn("Not dumping image {} as {} does not support the image format {}", image->name, GetImageOutputFormatName(ObjWriting::Configuration.ImageOutputFormat), GetImageFormatName(texture->GetFormat()->GetId())); return; } const auto assetFile = context.OpenAssetFile(GetFileNameForAsset(asset.m_name, m_writer->GetFileExtension())); if (!assetFile) return; auto& stream = *assetFile; m_writer->DumpImage(stream, texture.get()); } } // namespace image