diff --git a/src/Linker/Linker.cpp b/src/Linker/Linker.cpp index b5ecf427..4a34dacf 100644 --- a/src/Linker/Linker.cpp +++ b/src/Linker/Linker.cpp @@ -257,9 +257,10 @@ class LinkerImpl final : public Linker return true; } - std::unique_ptr CreateZoneForDefinition(LinkerPathManager& paths, const std::string& targetName, ZoneDefinition& zoneDefinition) const + std::unique_ptr CreateZoneForDefinition( + LinkerPathManager& paths, const fs::path& outDir, const fs::path& cacheDir, const std::string& targetName, ZoneDefinition& zoneDefinition) const { - ZoneCreationContext context(&zoneDefinition, &paths.m_asset_paths.GetSearchPaths()); + ZoneCreationContext context(&zoneDefinition, &paths.m_asset_paths.GetSearchPaths(), outDir, cacheDir); if (!ProcessZoneDefinitionIgnores(paths, targetName, context)) return nullptr; if (!LoadGdtFilesFromZoneDefinition(context.m_gdt_files, zoneDefinition, &paths.m_gdt_paths.GetSearchPaths())) @@ -268,22 +269,18 @@ class LinkerImpl final : public Linker return zone_creator::CreateZoneForDefinition(zoneDefinition.m_game, context); } - bool WriteZoneToFile(const LinkerPathManager& paths, const std::string& projectName, Zone* zone) const + bool WriteZoneToFile(const LinkerPathManager& paths, const fs::path& outDir, const std::string& projectName, Zone* zone) const { - const fs::path zoneFolderPath(paths.m_linker_paths->BuildOutputFolderPath(projectName, zone->m_game->GetId())); - auto zoneFilePath(zoneFolderPath); - zoneFilePath.append(zone->m_name + ".ff"); + auto zoneFilePath(outDir); + zoneFilePath.append(std::format("{}.ff", zone->m_name)); - fs::create_directories(zoneFolderPath); + fs::create_directories(outDir); std::ofstream stream(zoneFilePath, std::fstream::out | std::fstream::binary); if (!stream.is_open()) return false; - if (m_args.m_verbose) - { - std::cout << std::format("Building zone \"{}\"\n", zoneFilePath.string()); - } + std::cout << std::format("Building zone \"{}\"\n", zoneFilePath.string()); if (!ZoneWriting::WriteZone(stream, zone)) { @@ -300,12 +297,14 @@ class LinkerImpl final : public Linker bool BuildFastFile(LinkerPathManager& paths, const std::string& projectName, const std::string& targetName, ZoneDefinition& zoneDefinition) const { - SoundBankWriter::OutputPath = fs::path(paths.m_linker_paths->BuildOutputFolderPath(projectName, zoneDefinition.m_game)); + const fs::path outDir(paths.m_linker_paths->BuildOutputFolderPath(projectName, zoneDefinition.m_game)); + const fs::path cacheDir(paths.m_linker_paths->BuildCacheFolderPath(projectName, zoneDefinition.m_game)); + SoundBankWriter::OutputPath = outDir; - const auto zone = CreateZoneForDefinition(paths, targetName, zoneDefinition); + const auto zone = CreateZoneForDefinition(paths, outDir, cacheDir, targetName, zoneDefinition); auto result = zone != nullptr; if (zone) - result = WriteZoneToFile(paths, projectName, zone.get()); + result = WriteZoneToFile(paths, outDir, projectName, zone.get()); return result; } diff --git a/src/Linker/ZoneCreation/ZoneCreationContext.cpp b/src/Linker/ZoneCreation/ZoneCreationContext.cpp index 55b45501..b8f7a2a3 100644 --- a/src/Linker/ZoneCreation/ZoneCreationContext.cpp +++ b/src/Linker/ZoneCreation/ZoneCreationContext.cpp @@ -1,13 +1,17 @@ #include "ZoneCreationContext.h" +namespace fs = std::filesystem; + ZoneCreationContext::ZoneCreationContext() : m_definition(nullptr), m_asset_search_path(nullptr) { } -ZoneCreationContext::ZoneCreationContext(ZoneDefinition* definition, ISearchPath* assetSearchPath) +ZoneCreationContext::ZoneCreationContext(ZoneDefinition* definition, ISearchPath* assetSearchPath, fs::path outDir, fs::path cacheDir) : m_definition(definition), - m_asset_search_path(assetSearchPath) + m_asset_search_path(assetSearchPath), + m_out_dir(std::move(outDir)), + m_cache_dir(std::move(cacheDir)) { } diff --git a/src/Linker/ZoneCreation/ZoneCreationContext.h b/src/Linker/ZoneCreation/ZoneCreationContext.h index 3c8a098c..2f41ae3a 100644 --- a/src/Linker/ZoneCreation/ZoneCreationContext.h +++ b/src/Linker/ZoneCreation/ZoneCreationContext.h @@ -4,6 +4,7 @@ #include "Zone/AssetList/AssetList.h" #include "Zone/Definition/ZoneDefinition.h" +#include #include #include @@ -12,9 +13,11 @@ class ZoneCreationContext public: ZoneDefinition* m_definition; ISearchPath* m_asset_search_path; + std::filesystem::path m_out_dir; + std::filesystem::path m_cache_dir; std::vector> m_gdt_files; AssetList m_ignored_assets; ZoneCreationContext(); - ZoneCreationContext(ZoneDefinition* definition, ISearchPath* assetSearchPath); + ZoneCreationContext(ZoneDefinition* definition, ISearchPath* assetSearchPath, std::filesystem::path outDir, std::filesystem::path cacheDir); }; diff --git a/src/Linker/ZoneCreation/ZoneCreator.cpp b/src/Linker/ZoneCreation/ZoneCreator.cpp index 48090bde..332465fc 100644 --- a/src/Linker/ZoneCreation/ZoneCreator.cpp +++ b/src/Linker/ZoneCreation/ZoneCreator.cpp @@ -64,7 +64,8 @@ namespace zone_creator const auto* objLoader = IObjLoader::GetObjLoaderForGame(gameId); AssetCreatorCollection creatorCollection(*zone); - objCompiler->ConfigureCreatorCollection(creatorCollection, *zone, *context.m_definition); + objCompiler->ConfigureCreatorCollection( + creatorCollection, *zone, *context.m_definition, *context.m_asset_search_path, lookup, context.m_out_dir, context.m_cache_dir); objLoader->ConfigureCreatorCollection(creatorCollection, *zone, *context.m_asset_search_path, lookup); AssetCreationContext creationContext(zone.get(), &creatorCollection, &ignoredAssetLookup); diff --git a/src/ObjCompiling/Game/IW3/ObjCompilerIW3.cpp b/src/ObjCompiling/Game/IW3/ObjCompilerIW3.cpp index cf73b2cb..632c8e62 100644 --- a/src/ObjCompiling/Game/IW3/ObjCompilerIW3.cpp +++ b/src/ObjCompiling/Game/IW3/ObjCompilerIW3.cpp @@ -1,5 +1,37 @@ #include "ObjCompilerIW3.h" -using namespace IW3; +#include "Game/IW3/IW3.h" +#include "Image/ImageIwdPostProcessor.h" -void ObjCompiler::ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, const ZoneDefinition& zoneDefinition) const {} +#include + +using namespace IW3; +namespace fs = std::filesystem; + +namespace +{ + void ConfigureCompilers(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath) + { + auto& memory = *zone.GetMemory(); + + // No compilers yet + } + + void ConfigurePostProcessors(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, const fs::path& outDir) + { + auto& memory = *zone.GetMemory(); + + collection.AddAssetPostProcessor(std::make_unique>(searchPath, outDir)); + } +} // namespace + +void ObjCompiler::ConfigureCreatorCollection(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinition& zoneDefinition, + ISearchPath& searchPath, + IGdtQueryable& gdt, + const fs::path& outDir, + const fs::path& cacheDir) const +{ + ConfigurePostProcessors(collection, zone, searchPath, outDir); +} diff --git a/src/ObjCompiling/Game/IW3/ObjCompilerIW3.h b/src/ObjCompiling/Game/IW3/ObjCompilerIW3.h index 6b161b07..c24af94f 100644 --- a/src/ObjCompiling/Game/IW3/ObjCompilerIW3.h +++ b/src/ObjCompiling/Game/IW3/ObjCompilerIW3.h @@ -7,6 +7,12 @@ namespace IW3 class ObjCompiler final : public IObjCompiler { public: - void ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, const ZoneDefinition& zoneDefinition) const override; + void ConfigureCreatorCollection(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinition& zoneDefinition, + ISearchPath& searchPath, + IGdtQueryable& gdt, + const std::filesystem::path& outDir, + const std::filesystem::path& cacheDir) const override; }; } // namespace IW3 diff --git a/src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp b/src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp index 8f7c42b8..4e290ee5 100644 --- a/src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp +++ b/src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp @@ -1,5 +1,37 @@ #include "ObjCompilerIW4.h" -using namespace IW4; +#include "Game/IW4/IW4.h" +#include "Image/ImageIwdPostProcessor.h" -void ObjCompiler::ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, const ZoneDefinition& zoneDefinition) const {} +#include + +using namespace IW4; +namespace fs = std::filesystem; + +namespace +{ + void ConfigureCompilers(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath) + { + auto& memory = *zone.GetMemory(); + + // No compilers yet + } + + void ConfigurePostProcessors(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, const fs::path& outDir) + { + auto& memory = *zone.GetMemory(); + + collection.AddAssetPostProcessor(std::make_unique>(searchPath, outDir)); + } +} // namespace + +void ObjCompiler::ConfigureCreatorCollection(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinition& zoneDefinition, + ISearchPath& searchPath, + IGdtQueryable& gdt, + const fs::path& outDir, + const fs::path& cacheDir) const +{ + ConfigurePostProcessors(collection, zone, searchPath, outDir); +} diff --git a/src/ObjCompiling/Game/IW4/ObjCompilerIW4.h b/src/ObjCompiling/Game/IW4/ObjCompilerIW4.h index 980e6a2d..c9a6185c 100644 --- a/src/ObjCompiling/Game/IW4/ObjCompilerIW4.h +++ b/src/ObjCompiling/Game/IW4/ObjCompilerIW4.h @@ -7,6 +7,12 @@ namespace IW4 class ObjCompiler final : public IObjCompiler { public: - void ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, const ZoneDefinition& zoneDefinition) const override; + void ConfigureCreatorCollection(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinition& zoneDefinition, + ISearchPath& searchPath, + IGdtQueryable& gdt, + const std::filesystem::path& outDir, + const std::filesystem::path& cacheDir) const override; }; } // namespace IW4 diff --git a/src/ObjCompiling/Game/IW5/ObjCompilerIW5.cpp b/src/ObjCompiling/Game/IW5/ObjCompilerIW5.cpp index 3d0b99d7..ae52973e 100644 --- a/src/ObjCompiling/Game/IW5/ObjCompilerIW5.cpp +++ b/src/ObjCompiling/Game/IW5/ObjCompilerIW5.cpp @@ -1,5 +1,37 @@ #include "ObjCompilerIW5.h" -using namespace IW5; +#include "Game/IW5/IW5.h" +#include "Image/ImageIwdPostProcessor.h" -void ObjCompiler::ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, const ZoneDefinition& zoneDefinition) const {} +#include + +using namespace IW5; +namespace fs = std::filesystem; + +namespace +{ + void ConfigureCompilers(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath) + { + auto& memory = *zone.GetMemory(); + + // No compilers yet + } + + void ConfigurePostProcessors(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, const fs::path& outDir) + { + auto& memory = *zone.GetMemory(); + + collection.AddAssetPostProcessor(std::make_unique>(searchPath, outDir)); + } +} // namespace + +void ObjCompiler::ConfigureCreatorCollection(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinition& zoneDefinition, + ISearchPath& searchPath, + IGdtQueryable& gdt, + const fs::path& outDir, + const fs::path& cacheDir) const +{ + ConfigurePostProcessors(collection, zone, searchPath, outDir); +} diff --git a/src/ObjCompiling/Game/IW5/ObjCompilerIW5.h b/src/ObjCompiling/Game/IW5/ObjCompilerIW5.h index 5ff7229b..b96637ce 100644 --- a/src/ObjCompiling/Game/IW5/ObjCompilerIW5.h +++ b/src/ObjCompiling/Game/IW5/ObjCompilerIW5.h @@ -7,6 +7,12 @@ namespace IW5 class ObjCompiler final : public IObjCompiler { public: - void ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, const ZoneDefinition& zoneDefinition) const override; + void ConfigureCreatorCollection(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinition& zoneDefinition, + ISearchPath& searchPath, + IGdtQueryable& gdt, + const std::filesystem::path& outDir, + const std::filesystem::path& cacheDir) const override; }; } // namespace IW5 diff --git a/src/ObjCompiling/Game/T5/ObjCompilerT5.cpp b/src/ObjCompiling/Game/T5/ObjCompilerT5.cpp index 5fae8470..5ea0be38 100644 --- a/src/ObjCompiling/Game/T5/ObjCompilerT5.cpp +++ b/src/ObjCompiling/Game/T5/ObjCompilerT5.cpp @@ -1,5 +1,37 @@ #include "ObjCompilerT5.h" -using namespace T5; +#include "Game/T5/T5.h" +#include "Image/ImageIwdPostProcessor.h" -void ObjCompiler::ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, const ZoneDefinition& zoneDefinition) const {} +#include + +using namespace T5; +namespace fs = std::filesystem; + +namespace +{ + void ConfigureCompilers(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath) + { + auto& memory = *zone.GetMemory(); + + // No compilers yet + } + + void ConfigurePostProcessors(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, const fs::path& outDir) + { + auto& memory = *zone.GetMemory(); + + collection.AddAssetPostProcessor(std::make_unique>(searchPath, outDir)); + } +} // namespace + +void ObjCompiler::ConfigureCreatorCollection(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinition& zoneDefinition, + ISearchPath& searchPath, + IGdtQueryable& gdt, + const fs::path& outDir, + const fs::path& cacheDir) const +{ + ConfigurePostProcessors(collection, zone, searchPath, outDir); +} diff --git a/src/ObjCompiling/Game/T5/ObjCompilerT5.h b/src/ObjCompiling/Game/T5/ObjCompilerT5.h index a4cd6c20..1ccd8f7c 100644 --- a/src/ObjCompiling/Game/T5/ObjCompilerT5.h +++ b/src/ObjCompiling/Game/T5/ObjCompilerT5.h @@ -7,6 +7,12 @@ namespace T5 class ObjCompiler final : public IObjCompiler { public: - void ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, const ZoneDefinition& zoneDefinition) const override; + void ConfigureCreatorCollection(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinition& zoneDefinition, + ISearchPath& searchPath, + IGdtQueryable& gdt, + const std::filesystem::path& outDir, + const std::filesystem::path& cacheDir) const override; }; } // namespace T5 diff --git a/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp b/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp index 8b82b69d..580a5cf9 100644 --- a/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp +++ b/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp @@ -1,7 +1,37 @@ #include "ObjCompilerT6.h" #include "Game/T6/T6.h" +#include "Image/ImageIwdPostProcessor.h" + +#include using namespace T6; +namespace fs = std::filesystem; -void ObjCompiler::ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, const ZoneDefinition& zoneDefinition) const {} +namespace +{ + void ConfigureCompilers(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath) + { + auto& memory = *zone.GetMemory(); + + // No compilers yet + } + + void ConfigurePostProcessors(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, const fs::path& outDir) + { + auto& memory = *zone.GetMemory(); + + collection.AddAssetPostProcessor(std::make_unique>(searchPath, outDir)); + } +} // namespace + +void ObjCompiler::ConfigureCreatorCollection(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinition& zoneDefinition, + ISearchPath& searchPath, + IGdtQueryable& gdt, + const fs::path& outDir, + const fs::path& cacheDir) const +{ + ConfigurePostProcessors(collection, zone, searchPath, outDir); +} diff --git a/src/ObjCompiling/Game/T6/ObjCompilerT6.h b/src/ObjCompiling/Game/T6/ObjCompilerT6.h index 29f312ae..2cd4705c 100644 --- a/src/ObjCompiling/Game/T6/ObjCompilerT6.h +++ b/src/ObjCompiling/Game/T6/ObjCompilerT6.h @@ -7,6 +7,12 @@ namespace T6 class ObjCompiler final : public IObjCompiler { public: - void ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, const ZoneDefinition& zoneDefinition) const override; + void ConfigureCreatorCollection(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinition& zoneDefinition, + ISearchPath& searchPath, + IGdtQueryable& gdt, + const std::filesystem::path& outDir, + const std::filesystem::path& cacheDir) const override; }; } // namespace T6 diff --git a/src/ObjCompiling/IObjCompiler.h b/src/ObjCompiling/IObjCompiler.h index e27cc588..927b3b8b 100644 --- a/src/ObjCompiling/IObjCompiler.h +++ b/src/ObjCompiling/IObjCompiler.h @@ -1,11 +1,13 @@ #pragma once #include "Asset/AssetCreatorCollection.h" +#include "Gdt/IGdtQueryable.h" #include "SearchPath/ISearchPath.h" #include "Zone/Definition/ZoneDefinition.h" #include "Zone/Zone.h" #include +#include #include class IObjCompiler @@ -18,7 +20,13 @@ public: IObjCompiler& operator=(const IObjCompiler& other) = default; IObjCompiler& operator=(IObjCompiler&& other) noexcept = default; - virtual void ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, const ZoneDefinition& zoneDefinition) const = 0; + virtual void ConfigureCreatorCollection(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinition& zoneDefinition, + ISearchPath& searchPath, + IGdtQueryable& gdt, + const std::filesystem::path& outDir, + const std::filesystem::path& cacheDir) const = 0; static const IObjCompiler* GetObjCompilerForGame(GameId game); }; diff --git a/src/ObjCompiling/Image/IPak/IPakCreator.cpp b/src/ObjCompiling/Image/IPak/IPakCreator.cpp new file mode 100644 index 00000000..bf533e5e --- /dev/null +++ b/src/ObjCompiling/Image/IPak/IPakCreator.cpp @@ -0,0 +1,17 @@ +#include "IPakCreator.h" + +#include +#include + +void IPakCreator::AddImage(std::string imageName) +{ + m_image_names.emplace_back(std::move(imageName)); +} + +void IPakCreator::Finalize(ISearchPath& searchPath, const std::filesystem::path& outPath) +{ + std::cout << std::format("Creating ipak with {} entries:\n", m_image_names.size()); + + for (const auto& imageName : m_image_names) + std::cout << std::format(" {}\n", imageName); +} diff --git a/src/ObjCompiling/Image/IPak/IPakCreator.h b/src/ObjCompiling/Image/IPak/IPakCreator.h new file mode 100644 index 00000000..19686150 --- /dev/null +++ b/src/ObjCompiling/Image/IPak/IPakCreator.h @@ -0,0 +1,16 @@ +#pragma once + +#include "Asset/IZoneAssetLoaderState.h" +#include "SearchPath/ISearchPath.h" + +#include + +class IPakCreator : public IZoneAssetLoaderState +{ +public: + void AddImage(std::string imageName); + void Finalize(ISearchPath& searchPath, const std::filesystem::path& outPath); + +private: + std::vector m_image_names; +}; diff --git a/src/ObjCompiling/Image/ImageIPakPostProcessor.cpp b/src/ObjCompiling/Image/ImageIPakPostProcessor.cpp new file mode 100644 index 00000000..f20a5dfb --- /dev/null +++ b/src/ObjCompiling/Image/ImageIPakPostProcessor.cpp @@ -0,0 +1,25 @@ +#include "ImageIPakPostProcessor.h" + +#include "IPak/IPakCreator.h" + +#include + +AbstractImageIPakPostProcessor::AbstractImageIPakPostProcessor(ISearchPath& searchPath, const std::filesystem::path& outDir) + : m_search_path(searchPath), + m_out_dir(outDir) +{ +} + +void AbstractImageIPakPostProcessor::PostProcessAsset(XAssetInfoGeneric& assetInfo, AssetCreationContext& context) +{ + if (assetInfo.m_name.empty() || assetInfo.m_name[0] == ',') + return; + + auto* ipakCreator = context.GetZoneAssetLoaderState(); + ipakCreator->AddImage(assetInfo.m_name); +} + +void AbstractImageIPakPostProcessor::FinalizeZone(AssetCreationContext& context) +{ + context.GetZoneAssetLoaderState()->Finalize(m_search_path, m_out_dir); +} diff --git a/src/ObjCompiling/Image/ImageIPakPostProcessor.h b/src/ObjCompiling/Image/ImageIPakPostProcessor.h new file mode 100644 index 00000000..34208c67 --- /dev/null +++ b/src/ObjCompiling/Image/ImageIPakPostProcessor.h @@ -0,0 +1,34 @@ +#pragma once + +#include "Asset/IAssetPostProcessor.h" + +#include + +class AbstractImageIPakPostProcessor : public IAssetPostProcessor +{ +public: + AbstractImageIPakPostProcessor(ISearchPath& searchPath, const std::filesystem::path& outDir); + + void PostProcessAsset(XAssetInfoGeneric& assetInfo, AssetCreationContext& context) override; + void FinalizeZone(AssetCreationContext& context) override; + +private: + ISearchPath& m_search_path; + const std::filesystem::path& m_out_dir; +}; + +template class ImageIPakPostProcessor final : public AbstractImageIPakPostProcessor +{ +public: + static_assert(std::is_base_of_v); + + ImageIPakPostProcessor(ISearchPath& searchPath, const std::filesystem::path& outDir) + : AbstractImageIPakPostProcessor(searchPath, outDir) + { + } + + [[nodiscard]] asset_type_t GetHandlingAssetType() const override + { + return AssetType::EnumEntry; + }; +}; diff --git a/src/ObjCompiling/Image/ImageIwdPostProcessor.cpp b/src/ObjCompiling/Image/ImageIwdPostProcessor.cpp new file mode 100644 index 00000000..af7d037d --- /dev/null +++ b/src/ObjCompiling/Image/ImageIwdPostProcessor.cpp @@ -0,0 +1,25 @@ +#include "ImageIwdPostProcessor.h" + +#include "Iwd/IwdCreator.h" + +#include + +AbstractImageIwdPostProcessor::AbstractImageIwdPostProcessor(ISearchPath& searchPath, const std::filesystem::path& outDir) + : m_search_path(searchPath), + m_out_dir(outDir) +{ +} + +void AbstractImageIwdPostProcessor::PostProcessAsset(XAssetInfoGeneric& assetInfo, AssetCreationContext& context) +{ + if (assetInfo.m_name.empty() || assetInfo.m_name[0] == ',') + return; + + auto* iwdCreator = context.GetZoneAssetLoaderState(); + iwdCreator->AddFile(std::format("images/{}.iwi", assetInfo.m_name)); +} + +void AbstractImageIwdPostProcessor::FinalizeZone(AssetCreationContext& context) +{ + context.GetZoneAssetLoaderState()->Finalize(m_search_path, m_out_dir); +} diff --git a/src/ObjCompiling/Image/ImageIwdPostProcessor.h b/src/ObjCompiling/Image/ImageIwdPostProcessor.h new file mode 100644 index 00000000..2e10bec4 --- /dev/null +++ b/src/ObjCompiling/Image/ImageIwdPostProcessor.h @@ -0,0 +1,34 @@ +#pragma once + +#include "Asset/IAssetPostProcessor.h" + +#include + +class AbstractImageIwdPostProcessor : public IAssetPostProcessor +{ +public: + AbstractImageIwdPostProcessor(ISearchPath& searchPath, const std::filesystem::path& outDir); + + void PostProcessAsset(XAssetInfoGeneric& assetInfo, AssetCreationContext& context) override; + void FinalizeZone(AssetCreationContext& context) override; + +private: + ISearchPath& m_search_path; + const std::filesystem::path& m_out_dir; +}; + +template class ImageIwdPostProcessor final : public AbstractImageIwdPostProcessor +{ +public: + static_assert(std::is_base_of_v); + + ImageIwdPostProcessor(ISearchPath& searchPath, const std::filesystem::path& outDir) + : AbstractImageIwdPostProcessor(searchPath, outDir) + { + } + + [[nodiscard]] asset_type_t GetHandlingAssetType() const override + { + return AssetType::EnumEntry; + }; +}; diff --git a/src/ObjCompiling/Iwd/IwdCreator.cpp b/src/ObjCompiling/Iwd/IwdCreator.cpp new file mode 100644 index 00000000..d2e516a2 --- /dev/null +++ b/src/ObjCompiling/Iwd/IwdCreator.cpp @@ -0,0 +1,17 @@ +#include "IwdCreator.h" + +#include +#include + +void IwdCreator::AddFile(std::string filePath) +{ + m_file_paths.emplace_back(std::move(filePath)); +} + +void IwdCreator::Finalize(ISearchPath& searchPath, const std::filesystem::path& outPath) +{ + std::cout << std::format("Creating iwd with {} entries:\n", m_file_paths.size()); + + for (const auto& filePath : m_file_paths) + std::cout << std::format(" {}\n", filePath); +} diff --git a/src/ObjCompiling/Iwd/IwdCreator.h b/src/ObjCompiling/Iwd/IwdCreator.h new file mode 100644 index 00000000..a6b2df51 --- /dev/null +++ b/src/ObjCompiling/Iwd/IwdCreator.h @@ -0,0 +1,16 @@ +#pragma once + +#include "Asset/IZoneAssetLoaderState.h" +#include "SearchPath/ISearchPath.h" + +#include + +class IwdCreator : public IZoneAssetLoaderState +{ +public: + void AddFile(std::string filePath); + void Finalize(ISearchPath& searchPath, const std::filesystem::path& outPath); + +private: + std::vector m_file_paths; +}; diff --git a/src/ObjLoading/Asset/AssetCreatorCollection.cpp b/src/ObjLoading/Asset/AssetCreatorCollection.cpp index 0e83a3b7..ee237293 100644 --- a/src/ObjLoading/Asset/AssetCreatorCollection.cpp +++ b/src/ObjLoading/Asset/AssetCreatorCollection.cpp @@ -5,6 +5,7 @@ AssetCreatorCollection::AssetCreatorCollection(const Zone& zone) { m_asset_creators_by_type.resize(zone.m_pools->GetAssetTypeCount()); + m_asset_post_processors_by_type.resize(zone.m_pools->GetAssetTypeCount()); m_default_asset_creators_by_type.resize(zone.m_pools->GetAssetTypeCount()); } @@ -18,6 +19,16 @@ void AssetCreatorCollection::AddAssetCreator(std::unique_ptr crea m_asset_creators.emplace_back(std::move(creator)); } +void AssetCreatorCollection::AddAssetPostProcessor(std::unique_ptr postProcessor) +{ + const auto handlingAssetType = postProcessor->GetHandlingAssetType(); + assert(static_cast(handlingAssetType) < m_asset_post_processors_by_type.size()); + if (static_cast(handlingAssetType) < m_asset_post_processors_by_type.size()) + m_asset_post_processors_by_type[static_cast(handlingAssetType)].emplace_back(postProcessor.get()); + + m_asset_post_processors.emplace_back(std::move(postProcessor)); +} + void AssetCreatorCollection::AddDefaultAssetCreator(std::unique_ptr defaultAssetCreator) { const auto handlingAssetType = defaultAssetCreator->GetHandlingAssetType(); @@ -38,7 +49,18 @@ AssetCreationResult AssetCreatorCollection::CreateAsset(const asset_type_t asset { const auto result = creator->CreateAsset(assetName, context); if (result.HasTakenAction()) + { + // Post process asset if creation was successful + if (result.HasBeenSuccessful()) + { + assert(static_cast(assetType) < m_asset_post_processors_by_type.size()); + for (auto* postProcessor : m_asset_post_processors_by_type[assetType]) + postProcessor->PostProcessAsset(*result.GetAssetInfo(), context); + } + + // Return result that was either successful or failed return result; + } } } @@ -61,4 +83,6 @@ void AssetCreatorCollection::FinalizeZone(AssetCreationContext& context) const { for (const auto& creator : m_asset_creators) creator->FinalizeZone(context); + for (const auto& postProcessor : m_asset_post_processors) + postProcessor->FinalizeZone(context); } diff --git a/src/ObjLoading/Asset/AssetCreatorCollection.h b/src/ObjLoading/Asset/AssetCreatorCollection.h index 206b203d..9b720b11 100644 --- a/src/ObjLoading/Asset/AssetCreatorCollection.h +++ b/src/ObjLoading/Asset/AssetCreatorCollection.h @@ -3,13 +3,16 @@ #include "AssetCreationContext.h" #include "Game/IGame.h" #include "IAssetCreator.h" +#include "IAssetPostProcessor.h" #include "IDefaultAssetCreator.h" #include "Zone/ZoneTypes.h" #include +#include class AssetCreationContext; class IAssetCreator; +class IAssetPostProcessor; class AssetCreationResult; class IDefaultAssetCreator; @@ -19,6 +22,7 @@ public: explicit AssetCreatorCollection(const Zone& zone); void AddAssetCreator(std::unique_ptr creator); + void AddAssetPostProcessor(std::unique_ptr postProcessor); void AddDefaultAssetCreator(std::unique_ptr defaultAssetCreator); AssetCreationResult CreateAsset(asset_type_t assetType, const std::string& assetName, AssetCreationContext& context) const; @@ -27,6 +31,8 @@ public: private: std::vector> m_asset_creators_by_type; - std::vector> m_default_asset_creators_by_type; std::vector> m_asset_creators; + std::vector> m_asset_post_processors_by_type; + std::vector> m_asset_post_processors; + std::vector> m_default_asset_creators_by_type; }; diff --git a/src/ObjLoading/Asset/IAssetPostProcessor.h b/src/ObjLoading/Asset/IAssetPostProcessor.h new file mode 100644 index 00000000..afc64527 --- /dev/null +++ b/src/ObjLoading/Asset/IAssetPostProcessor.h @@ -0,0 +1,29 @@ +#pragma once + +#include "AssetCreationContext.h" +#include "AssetCreationResult.h" +#include "Game/IAsset.h" +#include "Pool/XAssetInfo.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" +#include "Zone/ZoneTypes.h" + +#include +#include + +class AssetCreationContext; + +class IAssetPostProcessor +{ +public: + IAssetPostProcessor() = default; + virtual ~IAssetPostProcessor() = default; + IAssetPostProcessor(const IAssetPostProcessor& other) = default; + IAssetPostProcessor(IAssetPostProcessor&& other) noexcept = default; + IAssetPostProcessor& operator=(const IAssetPostProcessor& other) = default; + IAssetPostProcessor& operator=(IAssetPostProcessor&& other) noexcept = default; + + [[nodiscard]] virtual asset_type_t GetHandlingAssetType() const = 0; + virtual void PostProcessAsset(XAssetInfoGeneric& assetInfo, AssetCreationContext& context) = 0; + virtual void FinalizeZone(AssetCreationContext& context){}; +};