diff --git a/premake5.lua b/premake5.lua index 651de911..331ae3e4 100644 --- a/premake5.lua +++ b/premake5.lua @@ -126,6 +126,7 @@ include "src/ZoneLoading.lua" include "src/ZoneWriting.lua" include "src/ZoneCommon.lua" include "src/ObjCommon.lua" +include "src/ObjCompiling.lua" include "src/ObjImage.lua" include "src/ObjLoading.lua" include "src/ObjWriting.lua" @@ -143,6 +144,7 @@ group "Components" ZoneLoading:project() ZoneWriting:project() ObjCommon:project() + ObjCompiling:project() ObjImage:project() ObjLoading:project() ObjWriting:project() @@ -168,6 +170,7 @@ group "" -- ======================== -- Tests -- ======================== +include "test/ObjCommonTestUtils.lua" include "test/ObjCommonTests.lua" include "test/ObjLoadingTests.lua" include "test/ParserTestUtils.lua" @@ -177,6 +180,7 @@ include "test/ZoneCommonTests.lua" -- Tests group: Unit test and other tests projects group "Tests" + ObjCommonTestUtils:project() ObjCommonTests:project() ObjLoadingTests:project() ParserTestUtils:project() diff --git a/scripts/check-format-docker.sh b/scripts/check-format-docker.sh new file mode 100755 index 00000000..2fbf867b --- /dev/null +++ b/scripts/check-format-docker.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +# Go to repository root +cd "$(dirname "$0")/.." || exit 2 + +docker run --rm -v ".:/code" --user "$(id -u):$(id -g)" silkeh/clang:17 /code/scripts/check-format.sh diff --git a/scripts/reformat-all-docker.sh b/scripts/reformat-all-docker.sh new file mode 100755 index 00000000..ad0d2077 --- /dev/null +++ b/scripts/reformat-all-docker.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +# Go to repository root +cd "$(dirname "$0")/.." || exit 2 + +docker run --rm -v ".:/code" --user "$(id -u):$(id -g)" silkeh/clang:17 /code/scripts/reformat-all.sh diff --git a/src/Common/Game/IAsset.h b/src/Common/Game/IAsset.h index a63c373c..0cd7d6fd 100644 --- a/src/Common/Game/IAsset.h +++ b/src/Common/Game/IAsset.h @@ -2,6 +2,9 @@ #include "Zone/ZoneTypes.h" +#include +#include + struct IAssetBase { }; @@ -12,3 +15,42 @@ public: static constexpr auto EnumEntry = AssetTypeEnum; using Type = AssetType; }; + +template struct AssetNameAccessor +{ +public: + static_assert(std::is_base_of_v); + // static constexpr bool IS_SINGLETON = false; + + // const char*& operator()(AssetType::Type& asset) + // { + // throw std::runtime_error("Not implemented"); + // } +}; + +#define DEFINE_ASSET_NAME_ACCESSOR(assetType, nameProperty) \ + template<> struct AssetNameAccessor \ + { \ + public: \ + static_assert(std::is_base_of_v); \ + static constexpr bool IS_SINGLETON = false; \ + \ + const char*& operator()(assetType::Type& asset) \ + { \ + return asset.nameProperty; \ + } \ + } + +#define DEFINE_ASSET_NAME_ACCESSOR_SINGLETON(assetType, singletonName) \ + template<> struct AssetNameAccessor \ + { \ + public: \ + static_assert(std::is_base_of_v); \ + static constexpr bool IS_SINGLETON = true; \ + \ + const char* const& operator()(assetType::Type& asset) \ + { \ + static const char* NAME = singletonName; \ + return NAME; \ + } \ + } diff --git a/src/Common/Game/IW3/IW3.h b/src/Common/Game/IW3/IW3.h index a489583c..1a3bda98 100644 --- a/src/Common/Game/IW3/IW3.h +++ b/src/Common/Game/IW3/IW3.h @@ -113,3 +113,32 @@ namespace IW3 using AssetRawFile = Asset; using AssetStringTable = Asset; } // namespace IW3 + +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetXModelPieces, name); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetPhysPreset, name); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetXAnim, name); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetXModel, name); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetMaterial, info.name); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetTechniqueSet, name); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetImage, name); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetSound, aliasName); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetSoundCurve, filename); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetLoadedSound, name); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetClipMap, name); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetClipMapPvs, name); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetComWorld, name); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetGameWorldSp, name); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetGameWorldMp, name); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetMapEnts, name); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetGfxWorld, name); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetLightDef, name); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetFont, fontName); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetMenuList, name); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetMenu, window.name); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetLocalize, name); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetWeapon, szInternalName); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetSoundDriverGlobals, name); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetFx, name); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetImpactFx, name); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetRawFile, name); +DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetStringTable, name); diff --git a/src/Common/Game/IW4/IW4.h b/src/Common/Game/IW4/IW4.h index 4335bdb1..fe9c7e03 100644 --- a/src/Common/Game/IW4/IW4.h +++ b/src/Common/Game/IW4/IW4.h @@ -168,3 +168,41 @@ namespace IW4 using AssetVehicle = Asset; using AssetAddonMapEnts = Asset; } // namespace IW4 + +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetPhysPreset, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetPhysCollMap, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetXAnim, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetXModelSurfs, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetXModel, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetMaterial, info.name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetPixelShader, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetVertexShader, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetVertexDecl, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetTechniqueSet, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetImage, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetSound, aliasName); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetSoundCurve, filename); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetLoadedSound, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetClipMapSp, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetClipMapMp, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetComWorld, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetGameWorldSp, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetGameWorldMp, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetMapEnts, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetFxWorld, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetGfxWorld, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetLightDef, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetFont, fontName); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetMenuList, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetMenu, window.name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetLocalize, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetWeapon, szInternalName); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetFx, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetImpactFx, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetRawFile, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetStringTable, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetLeaderboard, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetStructuredDataDef, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetTracer, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetVehicle, name); +DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetAddonMapEnts, name); diff --git a/src/Common/Game/IW5/IW5.h b/src/Common/Game/IW5/IW5.h index ba6b314d..c2018a64 100644 --- a/src/Common/Game/IW5/IW5.h +++ b/src/Common/Game/IW5/IW5.h @@ -179,3 +179,44 @@ namespace IW5 using AssetVehicle = Asset; using AssetAddonMapEnts = Asset; } // namespace IW5 + +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetPhysPreset, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetPhysCollMap, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetXAnim, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetXModelSurfs, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetXModel, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetMaterial, info.name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetPixelShader, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetVertexShader, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetVertexDecl, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetTechniqueSet, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetImage, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetSound, aliasName); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetSoundCurve, filename); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetLoadedSound, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetClipMap, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetComWorld, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetGlassWorld, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetPathData, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetVehicleTrack, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetMapEnts, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetFxWorld, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetGfxWorld, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetLightDef, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetFont, fontName); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetMenuList, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetMenu, window.name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetLocalize, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetAttachment, szInternalName); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetWeapon, szInternalName); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetFx, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetImpactFx, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetSurfaceFx, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetRawFile, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetScript, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetStringTable, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetLeaderboard, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetStructuredDataDef, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetTracer, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetVehicle, name); +DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetAddonMapEnts, name); diff --git a/src/Common/Game/T5/T5.h b/src/Common/Game/T5/T5.h index c493782d..2683e62f 100644 --- a/src/Common/Game/T5/T5.h +++ b/src/Common/Game/T5/T5.h @@ -148,5 +148,38 @@ namespace T5 using AssetDDL = Asset; using AssetGlasses = Asset; using AssetEmblemSet = Asset; - } // namespace T5 + +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetPhysPreset, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetPhysConstraints, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetDestructibleDef, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetXAnim, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetXModel, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetMaterial, info.name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetTechniqueSet, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetImage, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetSoundBank, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetSoundPatch, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetClipMap, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetClipMapPvs, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetComWorld, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetGameWorldSp, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetGameWorldMp, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetMapEnts, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetGfxWorld, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetLightDef, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetFont, fontName); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetMenuList, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetMenu, window.name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetLocalize, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetWeapon, szInternalName); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetSoundDriverGlobals, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetFx, name); +DEFINE_ASSET_NAME_ACCESSOR_SINGLETON(T5::AssetImpactFx, "ImpactFx"); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetRawFile, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetStringTable, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetPackIndex, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetXGlobals, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetDDL, name); +DEFINE_ASSET_NAME_ACCESSOR(T5::AssetGlasses, name); +DEFINE_ASSET_NAME_ACCESSOR_SINGLETON(T5::AssetEmblemSet, "EmblemSet"); diff --git a/src/Common/Game/T5/T5_Assets.h b/src/Common/Game/T5/T5_Assets.h index e69347ad..03235510 100644 --- a/src/Common/Game/T5/T5_Assets.h +++ b/src/Common/Game/T5/T5_Assets.h @@ -1311,7 +1311,7 @@ namespace T5 struct SndPatch { - char* name; + const char* name; unsigned int elementCount; unsigned int* elements; unsigned int fileCount; diff --git a/src/Common/Game/T6/T6.h b/src/Common/Game/T6/T6.h index 0b9bc5c6..72cd851b 100644 --- a/src/Common/Game/T6/T6.h +++ b/src/Common/Game/T6/T6.h @@ -209,3 +209,53 @@ namespace T6 using AssetFootstepFxTable = Asset; using AssetZBarrier = Asset; } // namespace T6 + +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetPhysPreset, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetPhysConstraints, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetDestructibleDef, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetXAnim, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetXModel, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetMaterial, info.name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetTechniqueSet, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetImage, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetSoundBank, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetSoundPatch, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetClipMap, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetClipMapPvs, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetComWorld, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetGameWorldSp, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetGameWorldMp, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetMapEnts, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetGfxWorld, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetLightDef, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetFont, fontName); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetFontIcon, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetMenuList, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetMenu, window.name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetLocalize, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetWeapon, szInternalName); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetAttachment, szInternalName); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetAttachmentUnique, szInternalName); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetWeaponCamo, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetSoundDriverGlobals, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetFx, name); +DEFINE_ASSET_NAME_ACCESSOR_SINGLETON(T6::AssetImpactFx, "ImpactFx"); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetRawFile, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetStringTable, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetLeaderboard, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetXGlobals, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetDDL, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetGlasses, name); +DEFINE_ASSET_NAME_ACCESSOR_SINGLETON(T6::AssetEmblemSet, "EmblemSet"); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetScript, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetKeyValuePairs, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetVehicle, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetMemoryBlock, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetAddonMapEnts, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetTracer, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetSkinnedVerts, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetQdb, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetSlug, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetFootstepTable, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetFootstepFxTable, name); +DEFINE_ASSET_NAME_ACCESSOR(T6::AssetZBarrier, name); diff --git a/src/Common/Game/T6/T6_Assets.h b/src/Common/Game/T6/T6_Assets.h index 89394044..95800cf3 100644 --- a/src/Common/Game/T6/T6_Assets.h +++ b/src/Common/Game/T6/T6_Assets.h @@ -2114,7 +2114,7 @@ namespace T6 struct KeyValuePairs { const char* name; - int numVariables; + unsigned int numVariables; KeyValuePair* keyValuePairs; }; @@ -5569,8 +5569,8 @@ namespace T6 struct KeyValuePair { - int keyHash; - int namespaceHash; + unsigned int keyHash; + unsigned int namespaceHash; const char* value; }; diff --git a/src/Linker.lua b/src/Linker.lua index 168c1dd2..a4a736d7 100644 --- a/src/Linker.lua +++ b/src/Linker.lua @@ -39,6 +39,7 @@ function Linker:project() self:include(includes) Utils:include(includes) ZoneLoading:include(includes) + ObjCompiling:include(includes) ObjLoading:include(includes) ObjWriting:include(includes) ZoneWriting:include(includes) @@ -46,6 +47,7 @@ function Linker:project() Raw:use() links:linkto(Utils) + links:linkto(ObjCompiling) links:linkto(ZoneLoading) links:linkto(ZoneWriting) links:linkto(ObjLoading) diff --git a/src/Linker/Game/IW3/ZoneCreatorIW3.cpp b/src/Linker/Game/IW3/ZoneCreatorIW3.cpp deleted file mode 100644 index 7266fc52..00000000 --- a/src/Linker/Game/IW3/ZoneCreatorIW3.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "ZoneCreatorIW3.h" - -#include "AssetLoading/AssetLoadingContext.h" -#include "Game/IW3/GameAssetPoolIW3.h" -#include "Game/IW3/GameIW3.h" -#include "IObjLoader.h" -#include "ObjLoading.h" -#include "Utils/StringUtils.h" - -using namespace IW3; - -std::vector ZoneCreator::CreateGdtList(const ZoneCreationContext& context) -{ - std::vector gdtList; - gdtList.reserve(context.m_gdt_files.size()); - for (const auto& gdt : context.m_gdt_files) - gdtList.push_back(gdt.get()); - - return gdtList; -} - -void ZoneCreator::ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext) -{ - for (const auto& ignoreEntry : creationContext.m_ignored_assets.m_entries) - loadingContext.m_ignored_asset_map[ignoreEntry.m_name] = ignoreEntry.m_type; -} - -void ZoneCreator::CreateZoneAssetPools(Zone* zone) const -{ - zone->m_pools = std::make_unique(zone, zone->m_priority); - - for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++) - zone->m_pools->InitPoolDynamic(assetType); -} - -GameId ZoneCreator::GetGameId() const -{ - return GameId::IW3; -} - -std::unique_ptr ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& context) const -{ - auto zone = std::make_unique(context.m_definition->m_name, 0, IGame::GetGameById(GameId::IW3)); - CreateZoneAssetPools(zone.get()); - - for (const auto& assetEntry : context.m_definition->m_assets) - { - if (!assetEntry.m_is_reference) - continue; - - context.m_ignored_assets.m_entries.emplace_back(assetEntry.m_asset_type, assetEntry.m_asset_name, assetEntry.m_is_reference); - } - - const auto assetLoadingContext = std::make_unique(*zone, *context.m_asset_search_path, CreateGdtList(context)); - ApplyIgnoredAssets(context, *assetLoadingContext); - - const auto* objLoader = IObjLoader::GetObjLoaderForGame(GameId::IW3); - for (const auto& assetEntry : context.m_definition->m_assets) - { - if (!objLoader->LoadAssetForZone(*assetLoadingContext, assetEntry.m_asset_type, assetEntry.m_asset_name)) - return nullptr; - } - - objLoader->FinalizeAssetsForZone(*assetLoadingContext); - - return zone; -} - -asset_type_t ZoneCreator::GetImageAssetType() const -{ - return ASSET_TYPE_IMAGE; -} diff --git a/src/Linker/Game/IW3/ZoneCreatorIW3.h b/src/Linker/Game/IW3/ZoneCreatorIW3.h deleted file mode 100644 index 7c756cf7..00000000 --- a/src/Linker/Game/IW3/ZoneCreatorIW3.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "AssetLoading/AssetLoadingContext.h" -#include "Zone/ZoneTypes.h" -#include "ZoneCreation/ZoneCreator.h" - -namespace IW3 -{ - class ZoneCreator final : public IZoneCreator - { - static std::vector CreateGdtList(const ZoneCreationContext& context); - static void ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext); - void CreateZoneAssetPools(Zone* zone) const; - - public: - [[nodiscard]] GameId GetGameId() const override; - [[nodiscard]] std::unique_ptr CreateZoneForDefinition(ZoneCreationContext& context) const override; - [[nodiscard]] asset_type_t GetImageAssetType() const override; - }; -} // namespace IW3 diff --git a/src/Linker/Game/IW4/ZoneCreatorIW4.cpp b/src/Linker/Game/IW4/ZoneCreatorIW4.cpp deleted file mode 100644 index 5a1165bb..00000000 --- a/src/Linker/Game/IW4/ZoneCreatorIW4.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "ZoneCreatorIW4.h" - -#include "Game/IW4/GameAssetPoolIW4.h" -#include "Game/IW4/GameIW4.h" -#include "IObjLoader.h" -#include "ObjLoading.h" -#include "Utils/StringUtils.h" - -using namespace IW4; - -std::vector ZoneCreator::CreateGdtList(const ZoneCreationContext& context) -{ - std::vector gdtList; - gdtList.reserve(context.m_gdt_files.size()); - for (const auto& gdt : context.m_gdt_files) - gdtList.push_back(gdt.get()); - - return gdtList; -} - -void ZoneCreator::ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext) -{ - for (const auto& ignoreEntry : creationContext.m_ignored_assets.m_entries) - loadingContext.m_ignored_asset_map[ignoreEntry.m_name] = ignoreEntry.m_type; -} - -void ZoneCreator::CreateZoneAssetPools(Zone* zone) const -{ - zone->m_pools = std::make_unique(zone, zone->m_priority); - - for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++) - zone->m_pools->InitPoolDynamic(assetType); -} - -GameId ZoneCreator::GetGameId() const -{ - return GameId::IW4; -} - -std::unique_ptr ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& context) const -{ - auto zone = std::make_unique(context.m_definition->m_name, 0, IGame::GetGameById(GameId::IW4)); - CreateZoneAssetPools(zone.get()); - - for (const auto& assetEntry : context.m_definition->m_assets) - { - if (!assetEntry.m_is_reference) - continue; - - context.m_ignored_assets.m_entries.emplace_back(assetEntry.m_asset_type, assetEntry.m_asset_name, assetEntry.m_is_reference); - } - - const auto assetLoadingContext = std::make_unique(*zone, *context.m_asset_search_path, CreateGdtList(context)); - ApplyIgnoredAssets(context, *assetLoadingContext); - - const auto* objLoader = IObjLoader::GetObjLoaderForGame(GameId::IW4); - for (const auto& assetEntry : context.m_definition->m_assets) - { - if (!objLoader->LoadAssetForZone(*assetLoadingContext, assetEntry.m_asset_type, assetEntry.m_asset_name)) - return nullptr; - } - - objLoader->FinalizeAssetsForZone(*assetLoadingContext); - - return zone; -} - -asset_type_t ZoneCreator::GetImageAssetType() const -{ - return ASSET_TYPE_IMAGE; -} diff --git a/src/Linker/Game/IW4/ZoneCreatorIW4.h b/src/Linker/Game/IW4/ZoneCreatorIW4.h deleted file mode 100644 index 7523c790..00000000 --- a/src/Linker/Game/IW4/ZoneCreatorIW4.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "AssetLoading/AssetLoadingContext.h" -#include "Zone/ZoneTypes.h" -#include "ZoneCreation/ZoneCreator.h" - -namespace IW4 -{ - class ZoneCreator final : public IZoneCreator - { - static std::vector CreateGdtList(const ZoneCreationContext& context); - static void ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext); - void CreateZoneAssetPools(Zone* zone) const; - - public: - [[nodiscard]] GameId GetGameId() const override; - [[nodiscard]] std::unique_ptr CreateZoneForDefinition(ZoneCreationContext& context) const override; - [[nodiscard]] asset_type_t GetImageAssetType() const override; - }; -} // namespace IW4 diff --git a/src/Linker/Game/IW5/ZoneCreatorIW5.cpp b/src/Linker/Game/IW5/ZoneCreatorIW5.cpp deleted file mode 100644 index a31841a6..00000000 --- a/src/Linker/Game/IW5/ZoneCreatorIW5.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "ZoneCreatorIW5.h" - -#include "Game/IW5/GameAssetPoolIW5.h" -#include "Game/IW5/GameIW5.h" -#include "IObjLoader.h" -#include "ObjLoading.h" -#include "Utils/StringUtils.h" - -using namespace IW5; - -std::vector ZoneCreator::CreateGdtList(const ZoneCreationContext& context) -{ - std::vector gdtList; - gdtList.reserve(context.m_gdt_files.size()); - for (const auto& gdt : context.m_gdt_files) - gdtList.push_back(gdt.get()); - - return gdtList; -} - -void ZoneCreator::ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext) -{ - for (const auto& ignoreEntry : creationContext.m_ignored_assets.m_entries) - loadingContext.m_ignored_asset_map[ignoreEntry.m_name] = ignoreEntry.m_type; -} - -void ZoneCreator::CreateZoneAssetPools(Zone* zone) const -{ - zone->m_pools = std::make_unique(zone, zone->m_priority); - - for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++) - zone->m_pools->InitPoolDynamic(assetType); -} - -GameId ZoneCreator::GetGameId() const -{ - return GameId::IW5; -} - -std::unique_ptr ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& context) const -{ - auto zone = std::make_unique(context.m_definition->m_name, 0, IGame::GetGameById(GameId::IW5)); - CreateZoneAssetPools(zone.get()); - - for (const auto& assetEntry : context.m_definition->m_assets) - { - if (!assetEntry.m_is_reference) - continue; - - context.m_ignored_assets.m_entries.emplace_back(assetEntry.m_asset_type, assetEntry.m_asset_name, assetEntry.m_is_reference); - } - - const auto assetLoadingContext = std::make_unique(*zone, *context.m_asset_search_path, CreateGdtList(context)); - ApplyIgnoredAssets(context, *assetLoadingContext); - - const auto* objLoader = IObjLoader::GetObjLoaderForGame(GameId::IW5); - for (const auto& assetEntry : context.m_definition->m_assets) - { - if (!objLoader->LoadAssetForZone(*assetLoadingContext, assetEntry.m_asset_type, assetEntry.m_asset_name)) - return nullptr; - } - - objLoader->FinalizeAssetsForZone(*assetLoadingContext); - - return zone; -} - -asset_type_t ZoneCreator::GetImageAssetType() const -{ - return ASSET_TYPE_IMAGE; -} diff --git a/src/Linker/Game/IW5/ZoneCreatorIW5.h b/src/Linker/Game/IW5/ZoneCreatorIW5.h deleted file mode 100644 index cee48755..00000000 --- a/src/Linker/Game/IW5/ZoneCreatorIW5.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include "AssetLoading/AssetLoadingContext.h" -#include "Zone/ZoneTypes.h" -#include "ZoneCreation/ZoneCreator.h" - -namespace IW5 -{ - class ZoneCreator final : public IZoneCreator - { - static std::vector CreateGdtList(const ZoneCreationContext& context); - static void ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext); - void CreateZoneAssetPools(Zone* zone) const; - - public: - [[nodiscard]] GameId GetGameId() const override; - [[nodiscard]] std::unique_ptr CreateZoneForDefinition(ZoneCreationContext& context) const override; - [[nodiscard]] asset_type_t GetImageAssetType() const override; - }; -} // namespace IW5 diff --git a/src/Linker/Game/T5/ZoneCreatorT5.cpp b/src/Linker/Game/T5/ZoneCreatorT5.cpp deleted file mode 100644 index ee72e9df..00000000 --- a/src/Linker/Game/T5/ZoneCreatorT5.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "ZoneCreatorT5.h" - -#include "AssetLoading/AssetLoadingContext.h" -#include "Game/T5/GameAssetPoolT5.h" -#include "Game/T5/GameT5.h" -#include "IObjLoader.h" -#include "ObjLoading.h" -#include "Utils/StringUtils.h" - -using namespace T5; - -std::vector ZoneCreator::CreateGdtList(ZoneCreationContext& context) -{ - std::vector gdtList; - gdtList.reserve(context.m_gdt_files.size()); - for (const auto& gdt : context.m_gdt_files) - gdtList.push_back(gdt.get()); - - return gdtList; -} - -void ZoneCreator::ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext) -{ - for (const auto& ignoreEntry : creationContext.m_ignored_assets.m_entries) - loadingContext.m_ignored_asset_map[ignoreEntry.m_name] = ignoreEntry.m_type; -} - -void ZoneCreator::CreateZoneAssetPools(Zone* zone) const -{ - zone->m_pools = std::make_unique(zone, zone->m_priority); - - for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++) - zone->m_pools->InitPoolDynamic(assetType); -} - -GameId ZoneCreator::GetGameId() const -{ - return GameId::T5; -} - -std::unique_ptr ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& context) const -{ - auto zone = std::make_unique(context.m_definition->m_name, 0, IGame::GetGameById(GameId::T5)); - CreateZoneAssetPools(zone.get()); - - for (const auto& assetEntry : context.m_definition->m_assets) - { - if (!assetEntry.m_is_reference) - continue; - - context.m_ignored_assets.m_entries.emplace_back(assetEntry.m_asset_type, assetEntry.m_asset_name, assetEntry.m_is_reference); - } - - const auto assetLoadingContext = std::make_unique(*zone, *context.m_asset_search_path, CreateGdtList(context)); - ApplyIgnoredAssets(context, *assetLoadingContext); - - const auto* objLoader = IObjLoader::GetObjLoaderForGame(GameId::T5); - for (const auto& assetEntry : context.m_definition->m_assets) - { - if (!objLoader->LoadAssetForZone(*assetLoadingContext, assetEntry.m_asset_type, assetEntry.m_asset_name)) - return nullptr; - } - - objLoader->FinalizeAssetsForZone(*assetLoadingContext); - - return zone; -} - -asset_type_t ZoneCreator::GetImageAssetType() const -{ - return ASSET_TYPE_IMAGE; -} diff --git a/src/Linker/Game/T5/ZoneCreatorT5.h b/src/Linker/Game/T5/ZoneCreatorT5.h deleted file mode 100644 index a7c8e2e6..00000000 --- a/src/Linker/Game/T5/ZoneCreatorT5.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include "AssetLoading/AssetLoadingContext.h" -#include "Zone/ZoneTypes.h" -#include "ZoneCreation/ZoneCreator.h" - -namespace T5 -{ - class ZoneCreator final : public IZoneCreator - { - static std::vector CreateGdtList(ZoneCreationContext& context); - static void ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext); - void CreateZoneAssetPools(Zone* zone) const; - - public: - [[nodiscard]] GameId GetGameId() const override; - [[nodiscard]] std::unique_ptr CreateZoneForDefinition(ZoneCreationContext& context) const override; - [[nodiscard]] asset_type_t GetImageAssetType() const override; - }; -} // namespace T5 diff --git a/src/Linker/Game/T6/ZoneCreatorT6.cpp b/src/Linker/Game/T6/ZoneCreatorT6.cpp deleted file mode 100644 index 960e258d..00000000 --- a/src/Linker/Game/T6/ZoneCreatorT6.cpp +++ /dev/null @@ -1,125 +0,0 @@ -#include "ZoneCreatorT6.h" - -#include "Game/T6/CommonT6.h" -#include "Game/T6/GameAssetPoolT6.h" -#include "Game/T6/GameT6.h" -#include "Game/T6/T6.h" -#include "IObjLoader.h" -#include "ObjLoading.h" -#include "Utils/StringUtils.h" - -#include - -using namespace T6; - -std::vector ZoneCreator::CreateGdtList(const ZoneCreationContext& context) -{ - std::vector gdtList; - gdtList.reserve(context.m_gdt_files.size()); - for (const auto& gdt : context.m_gdt_files) - gdtList.push_back(gdt.get()); - - return gdtList; -} - -void ZoneCreator::ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext) -{ - for (const auto& ignoreEntry : creationContext.m_ignored_assets.m_entries) - loadingContext.m_ignored_asset_map[ignoreEntry.m_name] = ignoreEntry.m_type; -} - -void ZoneCreator::CreateZoneAssetPools(Zone* zone) const -{ - zone->m_pools = std::make_unique(zone, zone->m_priority); - - for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++) - zone->m_pools->InitPoolDynamic(assetType); -} - -void ZoneCreator::HandleMetadata(Zone* zone, const ZoneCreationContext& context) const -{ - std::vector kvpList; - - for (const auto& metaData : context.m_definition->m_properties.m_properties) - { - if (metaData.first.rfind("level.", 0) == 0) - { - const std::string strValue = metaData.first.substr(std::char_traits::length("level.")); - if (strValue.empty()) - continue; - - int keyHash; - if (strValue[0] == '@') - { - char* endPtr; - keyHash = strtol(&strValue[1], &endPtr, 16); - - if (endPtr != &strValue[strValue.size()]) - { - std::cout << "Could not parse metadata key \"" << metaData.first << "\" as hash\n"; - continue; - } - } - else - { - keyHash = Common::Com_HashKey(strValue.c_str(), 64); - } - - KeyValuePair kvp{keyHash, Common::Com_HashKey(zone->m_name.c_str(), 64), zone->GetMemory()->Dup(metaData.second.c_str())}; - kvpList.push_back(kvp); - } - } - - if (!kvpList.empty()) - { - auto* kvps = zone->GetMemory()->Create(); - kvps->name = zone->GetMemory()->Dup(zone->m_name.c_str()); - kvps->numVariables = kvpList.size(); - kvps->keyValuePairs = zone->GetMemory()->Alloc(kvpList.size()); - - for (auto i = 0u; i < kvpList.size(); i++) - kvps->keyValuePairs[i] = kvpList[i]; - - zone->m_pools->AddAsset(std::make_unique>(ASSET_TYPE_KEYVALUEPAIRS, zone->m_name, kvps)); - } -} - -GameId ZoneCreator::GetGameId() const -{ - return GameId::T6; -} - -std::unique_ptr ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& context) const -{ - auto zone = std::make_unique(context.m_definition->m_name, 0, IGame::GetGameById(GameId::T6)); - CreateZoneAssetPools(zone.get()); - - for (const auto& assetEntry : context.m_definition->m_assets) - { - if (!assetEntry.m_is_reference) - continue; - - context.m_ignored_assets.m_entries.emplace_back(assetEntry.m_asset_type, assetEntry.m_asset_name, assetEntry.m_is_reference); - } - - const auto assetLoadingContext = std::make_unique(*zone, *context.m_asset_search_path, CreateGdtList(context)); - ApplyIgnoredAssets(context, *assetLoadingContext); - - HandleMetadata(zone.get(), context); - - const auto* objLoader = IObjLoader::GetObjLoaderForGame(GameId::T6); - for (const auto& assetEntry : context.m_definition->m_assets) - { - if (!objLoader->LoadAssetForZone(*assetLoadingContext, assetEntry.m_asset_type, assetEntry.m_asset_name)) - return nullptr; - } - - objLoader->FinalizeAssetsForZone(*assetLoadingContext); - - return zone; -} - -asset_type_t ZoneCreator::GetImageAssetType() const -{ - return ASSET_TYPE_IMAGE; -} diff --git a/src/Linker/Game/T6/ZoneCreatorT6.h b/src/Linker/Game/T6/ZoneCreatorT6.h deleted file mode 100644 index 17e24c78..00000000 --- a/src/Linker/Game/T6/ZoneCreatorT6.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once -#include "AssetLoading/AssetLoadingContext.h" -#include "Zone/ZoneTypes.h" -#include "ZoneCreation/ZoneCreator.h" - -namespace T6 -{ - class ZoneCreator final : public IZoneCreator - { - static std::vector CreateGdtList(const ZoneCreationContext& context); - static void ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext); - void CreateZoneAssetPools(Zone* zone) const; - void HandleMetadata(Zone* zone, const ZoneCreationContext& context) const; - - public: - [[nodiscard]] GameId GetGameId() const override; - [[nodiscard]] std::unique_ptr CreateZoneForDefinition(ZoneCreationContext& context) const override; - [[nodiscard]] asset_type_t GetImageAssetType() const override; - }; -} // namespace T6 diff --git a/src/Linker/Linker.cpp b/src/Linker/Linker.cpp index fbe52b00..7eada9cd 100644 --- a/src/Linker/Linker.cpp +++ b/src/Linker/Linker.cpp @@ -1,16 +1,13 @@ #include "Linker.h" #include "LinkerArgs.h" -#include "LinkerSearchPaths.h" -#include "ObjContainer/IPak/IPakWriter.h" -#include "ObjContainer/IWD/IWD.h" +#include "LinkerPaths.h" #include "ObjContainer/SoundBank/SoundBankWriter.h" -#include "ObjLoading.h" #include "ObjWriting.h" #include "SearchPath/SearchPaths.h" #include "Utils/ObjFileStream.h" #include "Zone/AssetList/AssetList.h" -#include "Zone/AssetList/AssetListStream.h" +#include "Zone/AssetList/AssetListReader.h" #include "Zone/Definition/ZoneDefinitionStream.h" #include "ZoneCreation/ZoneCreationContext.h" #include "ZoneCreation/ZoneCreator.h" @@ -21,133 +18,157 @@ #include #include #include -#include +#include namespace fs = std::filesystem; +namespace +{ + class LinkerSearchPathContext + { + public: + explicit LinkerSearchPathContext(const ILinkerSearchPathBuilder& searchPathBuilder) + : m_search_path_builder(searchPathBuilder) + { + m_independent_search_paths = m_search_path_builder.BuildIndependentSearchPaths(); + if (m_independent_search_paths) + m_search_paths.IncludeSearchPath(m_independent_search_paths.get()); + } + + [[nodiscard]] ISearchPath& GetSearchPaths() + { + return m_search_paths; + } + + void LoadProjectSpecific(const std::string& projectName) + { + m_project_specific_search_paths = m_search_path_builder.BuildSearchPathsSpecificToProject(projectName); + if (m_project_specific_search_paths) + m_search_paths.IncludeSearchPath(m_project_specific_search_paths.get()); + } + + void UnloadProjectSpecific() + { + if (!m_project_specific_search_paths) + return; + + m_search_paths.RemoveSearchPath(m_project_specific_search_paths.get()); + m_project_specific_search_paths.reset(); + } + + void LoadGameSpecific(const std::string& projectName, const GameId game) + { + m_game_specific_search_paths = m_search_path_builder.BuildSearchPathsSpecificToProjectAndGame(projectName, game); + if (m_game_specific_search_paths) + m_search_paths.IncludeSearchPath(m_game_specific_search_paths.get()); + } + + void UnloadGameSpecific() + { + if (!m_game_specific_search_paths) + return; + + m_search_paths.RemoveSearchPath(m_game_specific_search_paths.get()); + m_game_specific_search_paths.reset(); + } + + private: + const ILinkerSearchPathBuilder& m_search_path_builder; + std::unique_ptr m_independent_search_paths; + std::unique_ptr m_project_specific_search_paths; + std::unique_ptr m_game_specific_search_paths; + SearchPaths m_search_paths; + }; + + class LinkerPathManager + { + public: + explicit LinkerPathManager(const LinkerArgs& args) + : m_linker_paths(ILinkerPaths::FromArgs(args)), + m_asset_paths(m_linker_paths->AssetSearchPaths()), + m_gdt_paths(m_linker_paths->GdtSearchPaths()), + m_source_paths(m_linker_paths->SourceSearchPaths()) + { + } + + std::unique_ptr m_linker_paths; + LinkerSearchPathContext m_asset_paths; + LinkerSearchPathContext m_gdt_paths; + LinkerSearchPathContext m_source_paths; + }; + + class PathProjectContext + { + public: + PathProjectContext(LinkerPathManager& paths, const std::string& projectName) + : m_paths(paths) + { + m_paths.m_asset_paths.LoadProjectSpecific(projectName); + m_paths.m_gdt_paths.LoadProjectSpecific(projectName); + m_paths.m_source_paths.LoadProjectSpecific(projectName); + } + + ~PathProjectContext() + { + m_paths.m_asset_paths.UnloadProjectSpecific(); + m_paths.m_gdt_paths.UnloadProjectSpecific(); + m_paths.m_source_paths.UnloadProjectSpecific(); + } + + PathProjectContext(const PathProjectContext& other) = delete; + PathProjectContext(PathProjectContext&& other) noexcept = delete; + PathProjectContext& operator=(const PathProjectContext& other) = delete; + PathProjectContext& operator=(PathProjectContext&& other) noexcept = delete; + + private: + LinkerPathManager& m_paths; + }; + + class PathGameContext + { + public: + PathGameContext(LinkerPathManager& paths, const std::string& projectName, const GameId game) + : m_paths(paths) + { + m_paths.m_asset_paths.LoadGameSpecific(projectName, game); + m_paths.m_gdt_paths.LoadGameSpecific(projectName, game); + m_paths.m_source_paths.LoadGameSpecific(projectName, game); + } + + ~PathGameContext() + { + m_paths.m_asset_paths.UnloadGameSpecific(); + m_paths.m_gdt_paths.UnloadGameSpecific(); + m_paths.m_source_paths.UnloadGameSpecific(); + } + + PathGameContext(const PathGameContext& other) = delete; + PathGameContext(PathGameContext&& other) noexcept = delete; + PathGameContext& operator=(const PathGameContext& other) = delete; + PathGameContext& operator=(PathGameContext&& other) noexcept = delete; + + private: + LinkerPathManager& m_paths; + }; +} // namespace + class LinkerImpl final : public Linker { - LinkerArgs m_args; - LinkerSearchPaths m_search_paths; - std::vector> m_loaded_zones; - - bool IncludeAdditionalZoneDefinitions(const std::string& initialFileName, ZoneDefinition& zoneDefinition, ISearchPath* sourceSearchPath) const - { - std::set sourceNames; - sourceNames.emplace(initialFileName); - - std::deque toIncludeQueue; - for (const auto& include : zoneDefinition.m_includes) - toIncludeQueue.emplace_back(include); - - while (!toIncludeQueue.empty()) - { - const auto& source = toIncludeQueue.front(); - - if (sourceNames.find(source) == sourceNames.end()) - { - sourceNames.emplace(source); - - std::unique_ptr includeDefinition; - { - const auto definitionFileName = std::format("{}.zone", source); - const auto definitionStream = sourceSearchPath->Open(definitionFileName); - if (!definitionStream.IsOpen()) - { - std::cerr << std::format("Could not find zone definition file for project \"{}\".\n", source); - return false; - } - - ZoneDefinitionInputStream zoneDefinitionInputStream(*definitionStream.m_stream, source, definitionFileName, m_args.m_verbose); - zoneDefinitionInputStream.SetPreviouslySetGame(zoneDefinition.m_game); - includeDefinition = zoneDefinitionInputStream.ReadDefinition(); - } - - if (!includeDefinition) - { - std::cerr << std::format("Failed to read zone definition file for project \"{}\".\n", source); - return false; - } - - for (const auto& include : includeDefinition->m_includes) - toIncludeQueue.emplace_back(include); - - zoneDefinition.Include(*includeDefinition); - } - - toIncludeQueue.pop_front(); - } - - return true; - } - - bool ReadAssetList(const std::string& zoneName, const GameId game, AssetList& assetList, ISearchPath* sourceSearchPath) const - { - { - const auto assetListFileName = std::format("assetlist/{}.csv", zoneName); - const auto assetListStream = sourceSearchPath->Open(assetListFileName); - - if (assetListStream.IsOpen()) - { - const AssetListInputStream stream(*assetListStream.m_stream, game); - AssetListEntry entry; - - bool failure; - while (stream.NextEntry(entry, &failure)) - { - assetList.m_entries.emplace_back(std::move(entry)); - } - - return !failure; - } - } - - { - const auto zoneDefinition = ReadZoneDefinition(zoneName, sourceSearchPath); - - if (zoneDefinition) - { - for (const auto& entry : zoneDefinition->m_assets) - { - assetList.m_entries.emplace_back(entry.m_asset_type, entry.m_asset_name, entry.m_is_reference); - } - return true; - } - } - - return false; - } - - bool IncludeAssetLists(ZoneDefinition& zoneDefinition, ISearchPath* sourceSearchPath) const - { - for (const auto& assetListName : zoneDefinition.m_asset_lists) - { - AssetList assetList; - if (!ReadAssetList(assetListName, zoneDefinition.m_game, assetList, sourceSearchPath)) - { - std::cerr << std::format("Failed to read asset list \"{}\"\n", assetListName); - return false; - } - - zoneDefinition.Include(assetList); - } - - return true; - } - - std::unique_ptr ReadZoneDefinition(const std::string& targetName, ISearchPath* sourceSearchPath) const + std::unique_ptr ReadZoneDefinition(LinkerPathManager& paths, const std::string& targetName, bool logMissing = true) const { + auto& sourceSearchPath = paths.m_source_paths.GetSearchPaths(); std::unique_ptr zoneDefinition; { const auto definitionFileName = std::format("{}.zone", targetName); - const auto definitionStream = sourceSearchPath->Open(definitionFileName); + const auto definitionStream = sourceSearchPath.Open(definitionFileName); if (!definitionStream.IsOpen()) { - std::cerr << std::format("Could not find zone definition file for target \"{}\".\n", targetName); + if (logMissing) + std::cerr << std::format("Could not find zone definition file for target \"{}\".\n", targetName); return nullptr; } - ZoneDefinitionInputStream zoneDefinitionInputStream(*definitionStream.m_stream, targetName, definitionFileName, m_args.m_verbose); + ZoneDefinitionInputStream zoneDefinitionInputStream(*definitionStream.m_stream, targetName, definitionFileName, sourceSearchPath); zoneDefinition = zoneDefinitionInputStream.ReadDefinition(); } @@ -157,20 +178,41 @@ class LinkerImpl final : public Linker return nullptr; } - // If no type was defined explicitly make it fastfile - if (zoneDefinition->m_type == ProjectType::NONE) - zoneDefinition->m_type = ProjectType::FASTFILE; - - if (!IncludeAdditionalZoneDefinitions(targetName, *zoneDefinition, sourceSearchPath)) - return nullptr; - - if (!IncludeAssetLists(*zoneDefinition, sourceSearchPath)) - return nullptr; - return zoneDefinition; } - bool ProcessZoneDefinitionIgnores(const std::string& targetName, ZoneCreationContext& context, ISearchPath* sourceSearchPath) const + bool ReadIgnoreEntries(LinkerPathManager& paths, const std::string& zoneName, const GameId game, AssetList& assetList) const + { + { + AssetListReader assetListReader(paths.m_source_paths.GetSearchPaths(), game); + const auto maybeReadAssetList = assetListReader.ReadAssetList(zoneName, false); + if (maybeReadAssetList) + { + assetList.m_entries.reserve(assetList.m_entries.size() + maybeReadAssetList->m_entries.size()); + for (auto& entry : maybeReadAssetList->m_entries) + assetList.m_entries.emplace_back(std::move(entry)); + + return true; + } + } + + { + const auto zoneDefinition = ReadZoneDefinition(paths, zoneName, false); + + if (zoneDefinition) + { + assetList.m_entries.reserve(assetList.m_entries.size() + zoneDefinition->m_assets.size()); + for (const auto& entry : zoneDefinition->m_assets) + assetList.m_entries.emplace_back(entry.m_asset_type, entry.m_asset_name, entry.m_is_reference); + + return true; + } + } + + return false; + } + + bool ProcessZoneDefinitionIgnores(LinkerPathManager& paths, const std::string& targetName, ZoneCreationContext& context) const { if (context.m_definition->m_ignores.empty()) return true; @@ -180,8 +222,7 @@ class LinkerImpl final : public Linker if (ignore == targetName) continue; - std::vector assetList; - if (!ReadAssetList(ignore, context.m_definition->m_game, context.m_ignored_assets, sourceSearchPath)) + if (!ReadIgnoreEntries(paths, ignore, context.m_definition->m_game, context.m_ignored_assets)) { std::cerr << std::format("Failed to read asset listing for ignoring assets of project \"{}\".\n", ignore); return false; @@ -215,38 +256,30 @@ class LinkerImpl final : public Linker return true; } - std::unique_ptr CreateZoneForDefinition(const std::string& targetName, - ZoneDefinition& zoneDefinition, - ISearchPath* assetSearchPath, - ISearchPath* gdtSearchPath, - ISearchPath* sourceSearchPath) const + std::unique_ptr CreateZoneForDefinition( + LinkerPathManager& paths, const fs::path& outDir, const fs::path& cacheDir, const std::string& targetName, ZoneDefinition& zoneDefinition) const { - const auto context = std::make_unique(&zoneDefinition, assetSearchPath); - if (!ProcessZoneDefinitionIgnores(targetName, *context, sourceSearchPath)) + ZoneCreationContext context(&zoneDefinition, &paths.m_asset_paths.GetSearchPaths(), outDir, cacheDir); + if (!ProcessZoneDefinitionIgnores(paths, targetName, context)) return nullptr; - if (!LoadGdtFilesFromZoneDefinition(context->m_gdt_files, zoneDefinition, gdtSearchPath)) + if (!LoadGdtFilesFromZoneDefinition(context.m_gdt_files, zoneDefinition, &paths.m_gdt_paths.GetSearchPaths())) return nullptr; - const auto* creator = IZoneCreator::GetCreatorForGame(zoneDefinition.m_game); - return creator->CreateZoneForDefinition(*context); + return zone_creator::CreateZoneForDefinition(zoneDefinition.m_game, context); } - bool WriteZoneToFile(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(m_args.GetOutputFolderPathForProject(projectName)); - 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)) { @@ -261,112 +294,58 @@ class LinkerImpl final : public Linker return true; } - bool BuildFastFile(const std::string& projectName, - const std::string& targetName, - ZoneDefinition& zoneDefinition, - SearchPaths& assetSearchPaths, - SearchPaths& gdtSearchPaths, - SearchPaths& sourceSearchPaths) const + bool BuildFastFile(LinkerPathManager& paths, const std::string& projectName, const std::string& targetName, ZoneDefinition& zoneDefinition) const { - SoundBankWriter::OutputPath = fs::path(m_args.GetOutputFolderPathForProject(projectName)); + 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(targetName, zoneDefinition, &assetSearchPaths, &gdtSearchPaths, &sourceSearchPaths); + const auto zone = CreateZoneForDefinition(paths, outDir, cacheDir, targetName, zoneDefinition); auto result = zone != nullptr; if (zone) - result = WriteZoneToFile(projectName, zone.get()); + result = WriteZoneToFile(paths, outDir, projectName, zone.get()); return result; } - bool BuildIPak(const std::string& projectName, const ZoneDefinition& zoneDefinition, SearchPaths& assetSearchPaths) const + bool BuildProject(LinkerPathManager& paths, const std::string& projectName, const std::string& targetName) const { - const fs::path ipakFolderPath(m_args.GetOutputFolderPathForProject(projectName)); - auto ipakFilePath(ipakFolderPath); - ipakFilePath.append(std::format("{}.ipak", zoneDefinition.m_name)); + std::deque targetsToBuild; + std::unordered_set alreadyBuiltTargets; - fs::create_directories(ipakFolderPath); + targetsToBuild.emplace_back(targetName); - std::ofstream stream(ipakFilePath, std::fstream::out | std::fstream::binary); - if (!stream.is_open()) - return false; - - const auto ipakWriter = IPakWriter::Create(stream, &assetSearchPaths); - const auto imageAssetType = IZoneCreator::GetCreatorForGame(zoneDefinition.m_game)->GetImageAssetType(); - for (const auto& assetEntry : zoneDefinition.m_assets) + while (!targetsToBuild.empty()) { - if (assetEntry.m_is_reference) - continue; + const auto currentTarget = std::move(targetsToBuild.front()); + targetsToBuild.pop_front(); + alreadyBuiltTargets.emplace(currentTarget); - if (assetEntry.m_asset_type == imageAssetType) - ipakWriter->AddImage(assetEntry.m_asset_name); - } + PathProjectContext projectContext(paths, projectName); - if (!ipakWriter->Write()) - { - std::cerr << "Writing ipak failed.\n"; - stream.close(); - return false; - } + const auto zoneDefinition = ReadZoneDefinition(paths, targetName); + if (!zoneDefinition) + return false; - std::cout << std::format("Created ipak \"{}\"\n", ipakFilePath.string()); + PathGameContext gameContext(paths, projectName, zoneDefinition->m_game); - stream.close(); - return true; - } - - bool BuildReferencedTargets(const std::string& projectName, const std::string& targetName, const ZoneDefinition& zoneDefinition) - { - return std::ranges::all_of(zoneDefinition.m_targets_to_build, - [this, &projectName, &targetName](const std::string& buildTargetName) - { - if (buildTargetName == targetName) - { - std::cerr << std::format("Cannot build target with same name: \"{}\"\n", targetName); - return false; - } - - std::cout << std::format("Building referenced target \"{}\"\n", buildTargetName); - return BuildProject(projectName, buildTargetName); - }); - } - - bool BuildProject(const std::string& projectName, const std::string& targetName) - { - auto sourceSearchPaths = m_search_paths.GetSourceSearchPathsForProject(projectName); - - const auto zoneDefinition = ReadZoneDefinition(targetName, &sourceSearchPaths); - if (!zoneDefinition) - return false; - - auto result = true; - if (zoneDefinition->m_type != ProjectType::NONE) - { - const auto& gameName = GameId_Names[static_cast(zoneDefinition->m_game)]; - auto assetSearchPaths = m_search_paths.GetAssetSearchPathsForProject(gameName, projectName); - auto gdtSearchPaths = m_search_paths.GetGdtSearchPathsForProject(gameName, projectName); - - switch (zoneDefinition->m_type) + if (!zoneDefinition->m_assets.empty()) { - case ProjectType::FASTFILE: - result = BuildFastFile(projectName, targetName, *zoneDefinition, assetSearchPaths, gdtSearchPaths, sourceSearchPaths); - break; + if (!BuildFastFile(paths, projectName, targetName, *zoneDefinition)) + return false; - case ProjectType::IPAK: - result = BuildIPak(projectName, *zoneDefinition, assetSearchPaths); - break; - - default: - assert(false); - result = false; - break; + for (const auto& referencedTarget : zoneDefinition->m_targets_to_build) + { + if (alreadyBuiltTargets.find(referencedTarget) == alreadyBuiltTargets.end()) + { + targetsToBuild.emplace_back(referencedTarget); + std::cout << std::format("Building referenced target \"{}\"\n", referencedTarget); + } + } } } - m_search_paths.UnloadProjectSpecificSearchPaths(); - - result = result && BuildReferencedTargets(projectName, targetName, *zoneDefinition); - - return result; + return true; } bool LoadZones() @@ -384,8 +363,8 @@ class LinkerImpl final : public Linker zoneDirectory = fs::current_path(); auto absoluteZoneDirectory = absolute(zoneDirectory).string(); - auto zone = std::unique_ptr(ZoneLoading::LoadZone(zonePath)); - if (zone == nullptr) + auto zone = ZoneLoading::LoadZone(zonePath); + if (!zone) { std::cerr << std::format("Failed to load zone \"{}\".\n", zonePath); return false; @@ -452,11 +431,6 @@ class LinkerImpl final : public Linker } public: - LinkerImpl() - : m_search_paths(m_args) - { - } - bool Start(const int argc, const char** argv) override { auto shouldContinue = true; @@ -466,8 +440,7 @@ public: if (!shouldContinue) return true; - if (!m_search_paths.BuildProjectIndependentSearchPaths()) - return false; + LinkerPathManager paths(m_args); if (!LoadZones()) return false; @@ -483,7 +456,7 @@ public: break; } - if (!BuildProject(projectName, targetName)) + if (!BuildProject(paths, projectName, targetName)) { result = false; break; @@ -494,6 +467,10 @@ public: return result; } + +private: + LinkerArgs m_args; + std::vector> m_loaded_zones; }; std::unique_ptr Linker::Create() diff --git a/src/Linker/LinkerArgs.cpp b/src/Linker/LinkerArgs.cpp index b7ca5f4e..a0d0f7fe 100644 --- a/src/Linker/LinkerArgs.cpp +++ b/src/Linker/LinkerArgs.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include namespace fs = std::filesystem; @@ -46,7 +45,7 @@ const CommandLineOption* const OPTION_BASE_FOLDER = const CommandLineOption* const OPTION_OUTPUT_FOLDER = CommandLineOption::Builder::Create() .WithLongName("output-folder") - .WithDescription("Specifies the output folder containing the build artifacts. Defaults to \"" + std::string(LinkerArgs::DEFAULT_OUTPUT_FOLDER) + "\".") + .WithDescription(std::format("Specifies the output folder containing the build artifacts. Defaults to \"{}\".", LinkerArgs::DEFAULT_OUTPUT_FOLDER)) .WithParameter("outputFolderPath") .Build(); @@ -61,14 +60,14 @@ const CommandLineOption* const OPTION_ADD_ASSET_SEARCH_PATH = const CommandLineOption* const OPTION_ASSET_SEARCH_PATH = CommandLineOption::Builder::Create() .WithLongName("asset-search-path") - .WithDescription("Specifies the search paths used for assets. Defaults to \"" + std::string(LinkerArgs::DEFAULT_ASSET_SEARCH_PATH) + "\".") + .WithDescription(std::format("Specifies the search paths used for assets. Defaults to \"{}\".", LinkerArgs::DEFAULT_ASSET_SEARCH_PATH)) .WithParameter("assetSearchPathString") .Build(); const CommandLineOption* const OPTION_GDT_SEARCH_PATH = CommandLineOption::Builder::Create() .WithLongName("gdt-search-path") - .WithDescription("Specifies the search paths used for gdt files. Defaults to \"" + std::string(LinkerArgs::DEFAULT_GDT_SEARCH_PATH) + "\".") + .WithDescription(std::format("Specifies the search paths used for gdt files. Defaults to \"{}\".", LinkerArgs::DEFAULT_GDT_SEARCH_PATH)) .WithParameter("gdtSearchPathString") .Build(); @@ -83,7 +82,7 @@ const CommandLineOption* const OPTION_ADD_SOURCE_SEARCH_PATH = const CommandLineOption* const OPTION_SOURCE_SEARCH_PATH = CommandLineOption::Builder::Create() .WithLongName("source-search-path") - .WithDescription("Specifies the search paths used for source files. Defaults to \"" + std::string(LinkerArgs::DEFAULT_SOURCE_SEARCH_PATH) + "\".") + .WithDescription(std::format("Specifies the search paths used for source files. Defaults to \"{}\".", LinkerArgs::DEFAULT_SOURCE_SEARCH_PATH)) .WithParameter("sourceSearchPathString") .Build(); @@ -129,13 +128,7 @@ const CommandLineOption* const COMMAND_LINE_OPTIONS[]{ LinkerArgs::LinkerArgs() : m_verbose(false), - m_base_folder_depends_on_project(false), - m_out_folder_depends_on_project(false), - m_argument_parser(COMMAND_LINE_OPTIONS, std::extent_v), - m_bin_pattern(R"(\?bin\?)"), - m_base_pattern(R"(\?base\?)"), - m_game_pattern(R"(\?game\?)"), - m_project_pattern(R"(\?project\?)") + m_argument_parser(COMMAND_LINE_OPTIONS, std::extent_v) { } @@ -172,76 +165,6 @@ void LinkerArgs::SetVerbose(const bool isVerbose) ObjWriting::Configuration.Verbose = isVerbose; } -std::string LinkerArgs::GetBasePathForProject(const std::string& projectName) const -{ - return std::regex_replace(m_base_folder, m_project_pattern, projectName); -} - -void LinkerArgs::SetDefaultBasePath() -{ - const auto currentDir = fs::absolute(fs::current_path()); - - if (currentDir.filename() == "bin") - { - m_base_folder = currentDir.parent_path().string(); - } - else - { - m_base_folder = currentDir.string(); - } -} - -std::set LinkerArgs::GetProjectIndependentSearchPaths(const std::set& set) const -{ - std::set out; - - for (const auto& path : set) - { - if (path.find(PATTERN_GAME) != std::string::npos) - continue; - if (path.find(PATTERN_PROJECT) != std::string::npos) - continue; - - if (path.find(PATTERN_BASE) != std::string::npos) - { - if (m_base_folder_depends_on_project) - continue; - - out.emplace(std::regex_replace(path, m_base_pattern, m_base_folder)); - } - else - { - out.emplace(path); - } - } - - return out; -} - -std::set LinkerArgs::GetSearchPathsForProject(const std::set& set, const std::string& gameName, const std::string& projectName) const -{ - std::set out; - const auto basePath = GetBasePathForProject(projectName); - - for (const auto& path : set) - { - if (path.find(PATTERN_GAME) == std::string::npos && path.find(PATTERN_PROJECT) == std::string::npos - && (!m_base_folder_depends_on_project || path.find(PATTERN_BASE) == std::string::npos)) - { - continue; - } - - fs::path p(std::regex_replace(std::regex_replace(std::regex_replace(std::regex_replace(path, m_project_pattern, projectName), m_game_pattern, gameName), - m_base_pattern, - basePath), - m_bin_pattern, - m_bin_folder)); - out.emplace(p.make_preferred().string()); - } - - return out; -} - bool LinkerArgs::ParseArgs(const int argc, const char** argv, bool& shouldContinue) { shouldContinue = true; @@ -284,15 +207,13 @@ bool LinkerArgs::ParseArgs(const int argc, const char** argv, bool& shouldContin if (m_argument_parser.IsOptionSpecified(OPTION_BASE_FOLDER)) m_base_folder = m_argument_parser.GetValueForOption(OPTION_BASE_FOLDER); else - SetDefaultBasePath(); - m_base_folder_depends_on_project = m_base_folder.find(PATTERN_GAME) != std::string::npos || m_base_folder.find(PATTERN_PROJECT) != std::string::npos; + m_base_folder = DEFAULT_BASE_FOLDER; // --output-folder if (m_argument_parser.IsOptionSpecified(OPTION_OUTPUT_FOLDER)) m_out_folder = m_argument_parser.GetValueForOption(OPTION_OUTPUT_FOLDER); else m_out_folder = DEFAULT_OUTPUT_FOLDER; - m_out_folder_depends_on_project = m_out_folder.find(PATTERN_PROJECT) != std::string::npos; // --asset-search-path if (m_argument_parser.IsOptionSpecified(OPTION_ASSET_SEARCH_PATH)) @@ -358,38 +279,3 @@ bool LinkerArgs::ParseArgs(const int argc, const char** argv, bool& shouldContin return true; } - -std::string LinkerArgs::GetOutputFolderPathForProject(const std::string& projectName) const -{ - return std::regex_replace(std::regex_replace(m_out_folder, m_project_pattern, projectName), m_base_pattern, GetBasePathForProject(projectName)); -} - -std::set LinkerArgs::GetProjectIndependentAssetSearchPaths() const -{ - return GetProjectIndependentSearchPaths(m_asset_search_paths); -} - -std::set LinkerArgs::GetProjectIndependentGdtSearchPaths() const -{ - return GetProjectIndependentSearchPaths(m_gdt_search_paths); -} - -std::set LinkerArgs::GetProjectIndependentSourceSearchPaths() const -{ - return GetProjectIndependentSearchPaths(m_source_search_paths); -} - -std::set LinkerArgs::GetAssetSearchPathsForProject(const std::string& gameName, const std::string& projectName) const -{ - return GetSearchPathsForProject(m_asset_search_paths, gameName, projectName); -} - -std::set LinkerArgs::GetGdtSearchPathsForProject(const std::string& gameName, const std::string& projectName) const -{ - return GetSearchPathsForProject(m_gdt_search_paths, gameName, projectName); -} - -std::set LinkerArgs::GetSourceSearchPathsForProject(const std::string& projectName) const -{ - return GetSearchPathsForProject(m_source_search_paths, "", projectName); -} diff --git a/src/Linker/LinkerArgs.h b/src/Linker/LinkerArgs.h index 41fb32dd..fe2b8f4b 100644 --- a/src/Linker/LinkerArgs.h +++ b/src/Linker/LinkerArgs.h @@ -1,22 +1,14 @@ #pragma once #include "Utils/Arguments/ArgumentParser.h" -#include "Utils/ClassUtils.h" -#include "Zone/Zone.h" -#include #include #include class LinkerArgs { public: - static constexpr auto PATTERN_BIN = "?bin?"; - static constexpr auto PATTERN_BASE = "?base?"; - static constexpr auto PATTERN_GAME = "?game?"; - static constexpr auto PATTERN_PROJECT = "?project?"; - static constexpr auto DEFAULT_BASE_FOLDER = "."; - static constexpr auto DEFAULT_BASE_FOLDER_MOD_TOOLS = ".."; + static constexpr auto DEFAULT_CACHE_FOLDER = "?base?/.oat/cache/?project?"; static constexpr auto DEFAULT_OUTPUT_FOLDER = "?base?/zone_out/?project?"; static constexpr auto DEFAULT_ASSET_SEARCH_PATH = "?bin?/raw/?game?;?base?/raw;?base?/raw/?game?;?base?/zone_raw/?project?"; static constexpr auto DEFAULT_GDT_SEARCH_PATH = "?base?/source_data;?base?/zone_raw/?project?/source_data"; @@ -25,21 +17,6 @@ public: LinkerArgs(); bool ParseArgs(int argc, const char** argv, bool& shouldContinue); - /** - * \brief Converts the output path specified by command line arguments to a path applies for the specified project. - * \param projectName The name of the project to resolve the path input for. - * \return An output path for the project based on the user input. - */ - _NODISCARD std::string GetOutputFolderPathForProject(const std::string& projectName) const; - - _NODISCARD std::set GetProjectIndependentAssetSearchPaths() const; - _NODISCARD std::set GetProjectIndependentGdtSearchPaths() const; - _NODISCARD std::set GetProjectIndependentSourceSearchPaths() const; - - _NODISCARD std::set GetAssetSearchPathsForProject(const std::string& gameName, const std::string& projectName) const; - _NODISCARD std::set GetGdtSearchPathsForProject(const std::string& gameName, const std::string& projectName) const; - _NODISCARD std::set GetSourceSearchPathsForProject(const std::string& projectName) const; - bool m_verbose; std::vector m_zones_to_load; @@ -48,8 +25,6 @@ public: std::string m_bin_folder; std::string m_base_folder; std::string m_out_folder; - bool m_base_folder_depends_on_project; - bool m_out_folder_depends_on_project; std::set m_asset_search_paths; std::set m_gdt_search_paths; @@ -63,18 +38,7 @@ private: static void PrintVersion(); void SetBinFolder(const char* argv0); - void SetVerbose(bool isVerbose); - _NODISCARD std::string GetBasePathForProject(const std::string& projectName) const; - void SetDefaultBasePath(); - _NODISCARD std::set GetProjectIndependentSearchPaths(const std::set& set) const; - _NODISCARD std::set - GetSearchPathsForProject(const std::set& set, const std::string& gameName, const std::string& projectName) const; - ArgumentParser m_argument_parser; - std::regex m_bin_pattern; - std::regex m_base_pattern; - std::regex m_game_pattern; - std::regex m_project_pattern; }; diff --git a/src/Linker/LinkerPaths.cpp b/src/Linker/LinkerPaths.cpp new file mode 100644 index 00000000..2be5b015 --- /dev/null +++ b/src/Linker/LinkerPaths.cpp @@ -0,0 +1,338 @@ +#include "LinkerPaths.h" + +#include "SearchPath/IWD.h" +#include "SearchPath/SearchPathFilesystem.h" +#include "SearchPath/SearchPaths.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fs = std::filesystem; + +namespace +{ + enum class PathTemplateParameterType : std::uint8_t + { + BIN = 1 << 0, + BASE = 1 << 1, + PROJECT = 1 << 2, + GAME = 1 << 3, + }; + + class LinkerPathTemplate + { + static constexpr auto PATTERN_BIN = "?bin?"; + static constexpr auto PATTERN_BASE = "?base?"; + static constexpr auto PATTERN_GAME = "?game?"; + static constexpr auto PATTERN_PROJECT = "?project?"; + + struct Pattern + { + const char* m_str; + PathTemplateParameterType m_type; + }; + + static constexpr Pattern PATTERNS[]{ + {PATTERN_BIN, PathTemplateParameterType::BIN }, + {PATTERN_BASE, PathTemplateParameterType::BASE }, + {PATTERN_GAME, PathTemplateParameterType::GAME }, + {PATTERN_PROJECT, PathTemplateParameterType::PROJECT}, + }; + + public: + LinkerPathTemplate() + : m_parameter_type_flags(0u) + { + } + + void CreateFromString(const std::string& templateString) + { + const auto templateStringLength = templateString.size(); + auto partStart = 0u; + for (auto i = 0u; i < templateStringLength; i++) + { + if (templateString[i] != '?') + continue; + + for (const auto& pattern : PATTERNS) + { + const auto patternLength = std::strlen(pattern.m_str); + if (templateString.compare(i, patternLength, pattern.m_str) == 0) + { + m_parts.emplace_back(templateString.substr(partStart, i - partStart)); + m_parameters.emplace_back(pattern.m_type); + m_parameter_type_flags |= static_cast>(pattern.m_type); + i += patternLength; + + partStart = i; + break; + } + } + } + + if (partStart < templateStringLength) + m_parts.emplace_back(templateString.substr(partStart, templateStringLength - partStart)); + } + + [[nodiscard]] std::string + Render(const std::string& binDir, const std::string& baseDir, const std::string& projectName, const std::string& gameName) const + { + if (m_parts.empty()) + return ""; + + if (m_parameters.empty()) + return m_parts[0]; + + std::ostringstream ss; + ss << m_parts[0]; + + const auto partsCount = m_parts.size(); + const auto parameterCount = m_parameters.size(); + for (auto parameterIndex = 0u; parameterIndex < parameterCount; parameterIndex++) + { + switch (m_parameters[parameterIndex]) + { + case PathTemplateParameterType::BIN: + ss << binDir; + break; + case PathTemplateParameterType::BASE: + ss << baseDir; + break; + case PathTemplateParameterType::PROJECT: + ss << projectName; + break; + case PathTemplateParameterType::GAME: + ss << gameName; + break; + default: + assert(false); + break; + } + + if (parameterIndex + 1 < partsCount) + ss << m_parts[parameterIndex + 1]; + } + + return fs::path(ss.str()).make_preferred().string(); + } + + [[nodiscard]] bool CanRender(const std::underlying_type_t availableParameters) const + { + return (m_parameter_type_flags & ~availableParameters) == 0; + } + + private: + std::vector m_parts; + std::vector m_parameters; + std::underlying_type_t m_parameter_type_flags; + }; + + class LinkerSearchPathBuilder final : public ILinkerSearchPathBuilder + { + static constexpr auto INDEPENDENT_MASK = static_cast(PathTemplateParameterType::BIN) | static_cast(PathTemplateParameterType::BASE); + static constexpr auto PROJECT_MASK = static_cast(PathTemplateParameterType::BIN) | static_cast(PathTemplateParameterType::BASE) + | static_cast(PathTemplateParameterType::PROJECT); + static constexpr auto GAME_MASK = static_cast(PathTemplateParameterType::BIN) | static_cast(PathTemplateParameterType::BASE) + | static_cast(PathTemplateParameterType::PROJECT) | static_cast(PathTemplateParameterType::GAME); + + public: + LinkerSearchPathBuilder(const char* typeName, std::string binDir, std::string baseDir) + : m_type_name(typeName), + m_bin_dir(std::move(binDir)), + m_base_dir(std::move(baseDir)) + { + } + + void BuildFromArgs(const std::set& templates) + { + m_templates.reserve(templates.size()); + for (const auto& templateString : templates) + { + LinkerPathTemplate templateStruct; + templateStruct.CreateFromString(templateString); + m_templates.emplace_back(std::move(templateStruct)); + } + } + + [[nodiscard]] std::unique_ptr BuildIndependentSearchPaths() const override + { + SearchPaths searchPaths; + std::unordered_set addedSearchPaths; + auto hasSearchPath = false; + + for (const auto& curTemplate : m_templates) + { + if (curTemplate.CanRender(INDEPENDENT_MASK)) + { + auto renderedTemplate = curTemplate.Render(m_bin_dir, m_base_dir, std::string(), std::string()); + if (AddSearchPath(addedSearchPaths, searchPaths, renderedTemplate)) + hasSearchPath = true; + } + } + + if (hasSearchPath) + return std::make_unique(std::move(searchPaths)); + + return {}; + } + + [[nodiscard]] std::unique_ptr BuildSearchPathsSpecificToProject(const std::string& projectName) const override + { + SearchPaths searchPaths; + std::unordered_set addedSearchPaths; + auto hasSearchPath = false; + + for (const auto& curTemplate : m_templates) + { + if (!curTemplate.CanRender(INDEPENDENT_MASK) && curTemplate.CanRender(PROJECT_MASK)) + { + auto renderedTemplate = curTemplate.Render(m_bin_dir, m_base_dir, projectName, std::string()); + if (AddSearchPath(addedSearchPaths, searchPaths, renderedTemplate)) + hasSearchPath = true; + } + } + + if (hasSearchPath) + return std::make_unique(std::move(searchPaths)); + + return {}; + } + + [[nodiscard]] std::unique_ptr BuildSearchPathsSpecificToProjectAndGame(const std::string& projectName, GameId game) const override + { + SearchPaths searchPaths; + std::unordered_set addedSearchPaths; + auto hasSearchPath = false; + + for (const auto& curTemplate : m_templates) + { + if (!curTemplate.CanRender(PROJECT_MASK) && curTemplate.CanRender(GAME_MASK)) + { + auto renderedTemplate = curTemplate.Render(m_bin_dir, m_base_dir, projectName, GameId_Names[static_cast(game)]); + if (AddSearchPath(addedSearchPaths, searchPaths, renderedTemplate)) + hasSearchPath = true; + } + } + + if (hasSearchPath) + return std::make_unique(std::move(searchPaths)); + + return {}; + } + + private: + bool AddSearchPath(std::unordered_set& existingSearchPaths, SearchPaths& searchPaths, const std::string& path) const + { + const auto existingSearchPath = existingSearchPaths.find(path); + if (existingSearchPath != existingSearchPaths.end()) + return false; + existingSearchPaths.emplace(path); + + if (!fs::is_directory(path)) + { + std::cout << std::format("Adding {} search path (Not found): {}\n", m_type_name, path); + return false; + } + + std::cout << std::format("Adding {} search path: {}\n", m_type_name, path); + searchPaths.CommitSearchPath(std::make_unique(path)); + return true; + } + + const char* m_type_name; + std::vector m_templates; + std::string m_bin_dir; + std::string m_base_dir; + }; + + class LinkerPaths final : public ILinkerPaths + { + public: + LinkerPaths(std::string binDir, + std::string baseDir, + LinkerSearchPathBuilder assetSearchPaths, + LinkerSearchPathBuilder gdtSearchPaths, + LinkerSearchPathBuilder sourceSearchPaths, + LinkerPathTemplate cacheTemplate, + LinkerPathTemplate outTemplate) + : m_bin_dir(std::move(binDir)), + m_base_dir(std::move(baseDir)), + m_asset_search_paths(std::move(assetSearchPaths)), + m_gdt_search_paths(std::move(gdtSearchPaths)), + m_source_search_paths(std::move(sourceSearchPaths)), + m_cache_template(std::move(cacheTemplate)), + m_out_template(std::move(outTemplate)) + { + } + + [[nodiscard]] const ILinkerSearchPathBuilder& AssetSearchPaths() const override + { + return m_asset_search_paths; + } + + [[nodiscard]] const ILinkerSearchPathBuilder& GdtSearchPaths() const override + { + return m_gdt_search_paths; + } + + [[nodiscard]] const ILinkerSearchPathBuilder& SourceSearchPaths() const override + { + return m_source_search_paths; + } + + [[nodiscard]] std::string BuildCacheFolderPath(const std::string& projectName, GameId game) const override + { + return m_cache_template.Render(m_bin_dir, m_base_dir, projectName, GameId_Names[static_cast(game)]); + } + + [[nodiscard]] std::string BuildOutputFolderPath(const std::string& projectName, GameId game) const override + { + return m_out_template.Render(m_bin_dir, m_base_dir, projectName, GameId_Names[static_cast(game)]); + } + + private: + std::string m_bin_dir; + std::string m_base_dir; + LinkerSearchPathBuilder m_asset_search_paths; + LinkerSearchPathBuilder m_gdt_search_paths; + LinkerSearchPathBuilder m_source_search_paths; + LinkerPathTemplate m_cache_template; + LinkerPathTemplate m_out_template; + }; +} // namespace + +std::unique_ptr ILinkerPaths::FromArgs(const LinkerArgs& args) +{ + std::string normalizedBinPath = fs::canonical(args.m_bin_folder).make_preferred().string(); + std::string normalizedBasePath = fs::canonical(args.m_base_folder).make_preferred().string(); + + LinkerSearchPathBuilder assetSearchPaths("asset", normalizedBinPath, normalizedBasePath); + assetSearchPaths.BuildFromArgs(args.m_asset_search_paths); + + LinkerSearchPathBuilder gdtSearchPaths("gdt", normalizedBinPath, normalizedBasePath); + gdtSearchPaths.BuildFromArgs(args.m_gdt_search_paths); + + LinkerSearchPathBuilder sourceSearchPaths("source", normalizedBinPath, normalizedBasePath); + sourceSearchPaths.BuildFromArgs(args.m_source_search_paths); + + LinkerPathTemplate cacheTemplate; + cacheTemplate.CreateFromString(LinkerArgs::DEFAULT_CACHE_FOLDER); + + LinkerPathTemplate outTemplate; + outTemplate.CreateFromString(args.m_out_folder); + + return std::make_unique(std::move(normalizedBinPath), + std::move(normalizedBasePath), + std::move(assetSearchPaths), + std::move(gdtSearchPaths), + std::move(sourceSearchPaths), + std::move(cacheTemplate), + std::move(outTemplate)); +} diff --git a/src/Linker/LinkerPaths.h b/src/Linker/LinkerPaths.h new file mode 100644 index 00000000..d0464128 --- /dev/null +++ b/src/Linker/LinkerPaths.h @@ -0,0 +1,74 @@ +#pragma once + +#include "Game/IGame.h" +#include "LinkerArgs.h" +#include "SearchPath/ISearchPath.h" + +#include + +class ILinkerSearchPathBuilder +{ +public: + ILinkerSearchPathBuilder() = default; + virtual ~ILinkerSearchPathBuilder() = default; + ILinkerSearchPathBuilder(const ILinkerSearchPathBuilder& other) = default; + ILinkerSearchPathBuilder(ILinkerSearchPathBuilder&& other) noexcept = default; + ILinkerSearchPathBuilder& operator=(const ILinkerSearchPathBuilder& other) = default; + ILinkerSearchPathBuilder& operator=(ILinkerSearchPathBuilder&& other) noexcept = default; + + [[nodiscard]] virtual std::unique_ptr BuildIndependentSearchPaths() const = 0; + [[nodiscard]] virtual std::unique_ptr BuildSearchPathsSpecificToProject(const std::string& projectName) const = 0; + [[nodiscard]] virtual std::unique_ptr BuildSearchPathsSpecificToProjectAndGame(const std::string& projectName, GameId game) const = 0; +}; + +class ILinkerPaths +{ +public: + ILinkerPaths() = default; + virtual ~ILinkerPaths() = default; + ILinkerPaths(const ILinkerPaths& other) = default; + ILinkerPaths(ILinkerPaths&& other) noexcept = default; + ILinkerPaths& operator=(const ILinkerPaths& other) = default; + ILinkerPaths& operator=(ILinkerPaths&& other) noexcept = default; + + /** + * \brief Creates linker search paths based on templates from user specified args. + * \param args The user specified args. + * \return Linker search paths based on user specified templates. + */ + static std::unique_ptr FromArgs(const LinkerArgs& args); + + /** + * \brief Grants access to the builder for asset search paths. + * \return A builder instance for building asset search paths. + */ + [[nodiscard]] virtual const ILinkerSearchPathBuilder& AssetSearchPaths() const = 0; + + /** + * \brief Grants access to the builder for gdt search paths. + * \return A builder instance for building gdt search paths. + */ + [[nodiscard]] virtual const ILinkerSearchPathBuilder& GdtSearchPaths() const = 0; + + /** + * \brief Grants access to the builder for source search paths. + * \return A builder instance for building source search paths. + */ + [[nodiscard]] virtual const ILinkerSearchPathBuilder& SourceSearchPaths() const = 0; + + /** + * \brief Builds the cache path based on the specified information. + * \param projectName The name of the project to resolve the path input for. + * \param game The game to resolve the path input for. + * \return A cache path based on the input and preconfigured template. + */ + [[nodiscard]] virtual std::string BuildCacheFolderPath(const std::string& projectName, GameId game) const = 0; + + /** + * \brief Builds the output path based on the specified information. + * \param projectName The name of the project to resolve the path input for. + * \param game The game to resolve the path input for. + * \return An output path based on the input and preconfigured template. + */ + [[nodiscard]] virtual std::string BuildOutputFolderPath(const std::string& projectName, GameId game) const = 0; +}; diff --git a/src/Linker/LinkerSearchPaths.cpp b/src/Linker/LinkerSearchPaths.cpp deleted file mode 100644 index c3dd6668..00000000 --- a/src/Linker/LinkerSearchPaths.cpp +++ /dev/null @@ -1,190 +0,0 @@ -#include "LinkerSearchPaths.h" - -#include "ObjContainer/IWD/IWD.h" -#include "ObjLoading.h" -#include "SearchPath/SearchPathFilesystem.h" - -#include -#include -#include - -namespace fs = std::filesystem; - -LinkerSearchPaths::LinkerSearchPaths(const LinkerArgs& args) - : m_args(args) -{ -} - -void LinkerSearchPaths::LoadSearchPath(ISearchPath& searchPath) const -{ - if (m_args.m_verbose) - { - std::cout << std::format("Loading search path: \"{}\"\n", searchPath.GetPath()); - } - - ObjLoading::LoadIWDsInSearchPath(searchPath); -} - -void LinkerSearchPaths::UnloadSearchPath(ISearchPath& searchPath) const -{ - if (m_args.m_verbose) - { - std::cout << std::format("Unloading search path: \"{}\"\n", searchPath.GetPath()); - } - - ObjLoading::UnloadIWDsInSearchPath(searchPath); -} - -SearchPaths LinkerSearchPaths::GetAssetSearchPathsForProject(const std::string& gameName, const std::string& projectName) -{ - SearchPaths searchPathsForProject; - - for (const auto& searchPathStr : m_args.GetAssetSearchPathsForProject(gameName, projectName)) - { - auto absolutePath = fs::absolute(searchPathStr); - - if (!fs::is_directory(absolutePath)) - { - if (m_args.m_verbose) - std::cout << std::format("Adding asset search path (Not found): {}\n", absolutePath.string()); - continue; - } - - if (m_args.m_verbose) - std::cout << std::format("Adding asset search path: {}\n", absolutePath.string()); - - auto searchPath = std::make_unique(searchPathStr); - LoadSearchPath(*searchPath); - searchPathsForProject.IncludeSearchPath(searchPath.get()); - m_loaded_project_search_paths.emplace_back(std::move(searchPath)); - } - - searchPathsForProject.IncludeSearchPath(&m_asset_search_paths); - - for (auto* iwd : IWD::Repository) - { - searchPathsForProject.IncludeSearchPath(iwd); - } - - return searchPathsForProject; -} - -SearchPaths LinkerSearchPaths::GetGdtSearchPathsForProject(const std::string& gameName, const std::string& projectName) -{ - SearchPaths searchPathsForProject; - - for (const auto& searchPathStr : m_args.GetGdtSearchPathsForProject(gameName, projectName)) - { - auto absolutePath = fs::absolute(searchPathStr); - - if (!fs::is_directory(absolutePath)) - { - if (m_args.m_verbose) - std::cout << std::format("Adding gdt search path (Not found): {}\n", absolutePath.string()); - continue; - } - - if (m_args.m_verbose) - std::cout << std::format("Adding gdt search path: {}\n", absolutePath.string()); - - searchPathsForProject.CommitSearchPath(std::make_unique(searchPathStr)); - } - - searchPathsForProject.IncludeSearchPath(&m_gdt_search_paths); - - return searchPathsForProject; -} - -SearchPaths LinkerSearchPaths::GetSourceSearchPathsForProject(const std::string& projectName) -{ - SearchPaths searchPathsForProject; - - for (const auto& searchPathStr : m_args.GetSourceSearchPathsForProject(projectName)) - { - auto absolutePath = fs::absolute(searchPathStr); - - if (!fs::is_directory(absolutePath)) - { - if (m_args.m_verbose) - std::cout << std::format("Adding source search path (Not found): {}\n", absolutePath.string()); - continue; - } - - if (m_args.m_verbose) - std::cout << std::format("Adding source search path: {}\n", absolutePath.string()); - - searchPathsForProject.CommitSearchPath(std::make_unique(searchPathStr)); - } - - searchPathsForProject.IncludeSearchPath(&m_source_search_paths); - - return searchPathsForProject; -} - -bool LinkerSearchPaths::BuildProjectIndependentSearchPaths() -{ - for (const auto& path : m_args.GetProjectIndependentAssetSearchPaths()) - { - auto absolutePath = fs::absolute(path); - - if (!fs::is_directory(absolutePath)) - { - if (m_args.m_verbose) - std::cout << std::format("Adding asset search path (Not found): {}\n", absolutePath.string()); - continue; - } - - if (m_args.m_verbose) - std::cout << std::format("Adding asset search path: {}\n", absolutePath.string()); - - auto searchPath = std::make_unique(absolutePath.string()); - LoadSearchPath(*searchPath); - m_asset_search_paths.CommitSearchPath(std::move(searchPath)); - } - - for (const auto& path : m_args.GetProjectIndependentGdtSearchPaths()) - { - auto absolutePath = fs::absolute(path); - - if (!fs::is_directory(absolutePath)) - { - if (m_args.m_verbose) - std::cout << std::format("Loading gdt search path (Not found): {}\n", absolutePath.string()); - continue; - } - - if (m_args.m_verbose) - std::cout << std::format("Adding gdt search path: {}\n", absolutePath.string()); - - m_gdt_search_paths.CommitSearchPath(std::make_unique(absolutePath.string())); - } - - for (const auto& path : m_args.GetProjectIndependentSourceSearchPaths()) - { - auto absolutePath = fs::absolute(path); - - if (!fs::is_directory(absolutePath)) - { - if (m_args.m_verbose) - std::cout << std::format("Loading source search path (Not found): {}\n", absolutePath.string()); - continue; - } - - if (m_args.m_verbose) - std::cout << std::format("Adding source search path: {}\n", absolutePath.string()); - - m_source_search_paths.CommitSearchPath(std::make_unique(absolutePath.string())); - } - - return true; -} - -void LinkerSearchPaths::UnloadProjectSpecificSearchPaths() -{ - for (const auto& loadedSearchPath : m_loaded_project_search_paths) - { - UnloadSearchPath(*loadedSearchPath); - } - - m_loaded_project_search_paths.clear(); -} diff --git a/src/Linker/LinkerSearchPaths.h b/src/Linker/LinkerSearchPaths.h deleted file mode 100644 index f570965e..00000000 --- a/src/Linker/LinkerSearchPaths.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once -#include "LinkerArgs.h" -#include "SearchPath/SearchPaths.h" - -#include -#include - -class LinkerSearchPaths -{ -public: - explicit LinkerSearchPaths(const LinkerArgs& args); - - /** - * \brief Loads a search path. - * \param searchPath The search path to load. - */ - void LoadSearchPath(ISearchPath& searchPath) const; - - /** - * \brief Unloads a search path. - * \param searchPath The search path to unload. - */ - void UnloadSearchPath(ISearchPath& searchPath) const; - - SearchPaths GetAssetSearchPathsForProject(const std::string& gameName, const std::string& projectName); - - SearchPaths GetGdtSearchPathsForProject(const std::string& gameName, const std::string& projectName); - - SearchPaths GetSourceSearchPathsForProject(const std::string& projectName); - - /** - * \brief Initializes the Linker object's search paths based on the user's input. - * \return \c true if building the search paths was successful, otherwise \c false. - */ - bool BuildProjectIndependentSearchPaths(); - - void UnloadProjectSpecificSearchPaths(); - -private: - const LinkerArgs& m_args; - std::vector> m_loaded_project_search_paths; - SearchPaths m_asset_search_paths; - SearchPaths m_gdt_search_paths; - SearchPaths m_source_search_paths; -}; 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 9e1f1004..21bc80f0 100644 --- a/src/Linker/ZoneCreation/ZoneCreator.cpp +++ b/src/Linker/ZoneCreation/ZoneCreator.cpp @@ -1,27 +1,88 @@ #include "ZoneCreator.h" -#include "AssetLoading/AssetLoadingContext.h" -#include "Game/IW3/ZoneCreatorIW3.h" -#include "Game/IW4/ZoneCreatorIW4.h" -#include "Game/IW5/ZoneCreatorIW5.h" -#include "Game/T5/ZoneCreatorT5.h" -#include "Game/T6/ZoneCreatorT6.h" +#include "Gdt/GdtLookup.h" +#include "IObjCompiler.h" +#include "IObjLoader.h" #include -const IZoneCreator* IZoneCreator::GetCreatorForGame(GameId game) +namespace { - static const IZoneCreator* zoneCreators[static_cast(GameId::COUNT)]{ - new IW3::ZoneCreator(), - new IW4::ZoneCreator(), - new IW5::ZoneCreator(), - new T5::ZoneCreator(), - new T6::ZoneCreator(), - }; + std::unique_ptr CreateZone(const ZoneCreationContext& context, const GameId gameId) + { + return std::make_unique(context.m_definition->m_name, 0, IGame::GetGameById(gameId)); + } - assert(static_cast(game) < static_cast(GameId::COUNT)); - const auto* result = zoneCreators[static_cast(game)]; - assert(result); + std::vector CreateGdtList(const ZoneCreationContext& context) + { + std::vector gdtList; + gdtList.reserve(context.m_gdt_files.size()); + for (const auto& gdt : context.m_gdt_files) + gdtList.push_back(gdt.get()); - return result; -} + return gdtList; + } + + void IgnoreReferencesFromAssets(ZoneCreationContext& context) + { + for (const auto& assetEntry : context.m_definition->m_assets) + { + if (!assetEntry.m_is_reference) + continue; + + context.m_ignored_assets.m_entries.emplace_back(assetEntry.m_asset_type, assetEntry.m_asset_name, assetEntry.m_is_reference); + } + } +} // namespace + +namespace zone_creator +{ + void InitLookup(const ZoneCreationContext& context, GdtLookup& lookup) + { + std::vector gdtFiles; + gdtFiles.reserve(context.m_gdt_files.size()); + + for (const auto& gdt : context.m_gdt_files) + { + gdtFiles.emplace_back(gdt.get()); + } + + lookup.Initialize(gdtFiles); + } + + std::unique_ptr CreateZoneForDefinition(GameId gameId, ZoneCreationContext& context) + { + auto zone = CreateZone(context, gameId); + + IgnoreReferencesFromAssets(context); + IgnoredAssetLookup ignoredAssetLookup(context.m_ignored_assets); + + GdtLookup lookup; + InitLookup(context, lookup); + + const auto* objCompiler = IObjCompiler::GetObjCompilerForGame(gameId); + const auto* objLoader = IObjLoader::GetObjLoaderForGame(gameId); + + AssetCreatorCollection creatorCollection(*zone); + ZoneDefinitionContext zoneDefinitionContext(*context.m_definition); + AssetCreationContext creationContext(*zone, &creatorCollection, &ignoredAssetLookup); + + objCompiler->ConfigureCreatorCollection( + creatorCollection, *zone, zoneDefinitionContext, *context.m_asset_search_path, lookup, creationContext, context.m_out_dir, context.m_cache_dir); + objLoader->ConfigureCreatorCollection(creatorCollection, *zone, *context.m_asset_search_path, lookup); + + for (const auto& assetEntry : context.m_definition->m_assets) + { + const auto* createdAsset = creationContext.LoadDependencyGeneric(assetEntry.m_asset_type, assetEntry.m_asset_name); + + if (!createdAsset) + return nullptr; + + ++zoneDefinitionContext.m_asset_index_in_definition; + } + + creatorCollection.FinalizeZone(creationContext); + + return zone; + } +} // namespace zone_creator diff --git a/src/Linker/ZoneCreation/ZoneCreator.h b/src/Linker/ZoneCreation/ZoneCreator.h index 470c595d..c95c7cd9 100644 --- a/src/Linker/ZoneCreation/ZoneCreator.h +++ b/src/Linker/ZoneCreation/ZoneCreator.h @@ -3,19 +3,7 @@ #include "Zone/Zone.h" #include "ZoneCreationContext.h" -class IZoneCreator +namespace zone_creator { -public: - IZoneCreator() = default; - virtual ~IZoneCreator() = default; - IZoneCreator(const IZoneCreator& other) = default; - IZoneCreator(IZoneCreator&& other) noexcept = default; - IZoneCreator& operator=(const IZoneCreator& other) = default; - IZoneCreator& operator=(IZoneCreator&& other) noexcept = default; - - [[nodiscard]] virtual GameId GetGameId() const = 0; - [[nodiscard]] virtual std::unique_ptr CreateZoneForDefinition(ZoneCreationContext& context) const = 0; - [[nodiscard]] virtual asset_type_t GetImageAssetType() const = 0; - - static const IZoneCreator* GetCreatorForGame(GameId game); -}; + [[nodiscard]] std::unique_ptr CreateZoneForDefinition(GameId game, ZoneCreationContext& context); +} diff --git a/src/ObjCommon.lua b/src/ObjCommon.lua index df91eae8..bcbed0e1 100644 --- a/src/ObjCommon.lua +++ b/src/ObjCommon.lua @@ -5,6 +5,7 @@ function ObjCommon:include(includes) Common:include(includes) json:include(includes) minizip:include(includes) + Parser:include(includes) includedirs { path.join(ProjectFolder(), "ObjCommon") } @@ -16,6 +17,7 @@ function ObjCommon:link(links) links:linkto(Utils) links:linkto(Common) links:linkto(minizip) + links:linkto(Parser) end function ObjCommon:use() diff --git a/src/ObjCommon/Game/IW4/InfoString/PhysPresetFields.h b/src/ObjCommon/Game/IW4/PhysPreset/PhysPresetFields.h similarity index 99% rename from src/ObjCommon/Game/IW4/InfoString/PhysPresetFields.h rename to src/ObjCommon/Game/IW4/PhysPreset/PhysPresetFields.h index bc3ab22e..1423f3a8 100644 --- a/src/ObjCommon/Game/IW4/InfoString/PhysPresetFields.h +++ b/src/ObjCommon/Game/IW4/PhysPreset/PhysPresetFields.h @@ -1,4 +1,5 @@ #pragma once + #include "Game/IW4/IW4.h" namespace IW4 diff --git a/src/ObjCommon/Game/IW4/InfoString/TracerFields.h b/src/ObjCommon/Game/IW4/Tracer/TracerFields.h similarity index 100% rename from src/ObjCommon/Game/IW4/InfoString/TracerFields.h rename to src/ObjCommon/Game/IW4/Tracer/TracerFields.h diff --git a/src/ObjCommon/Game/IW4/InfoString/VehicleFields.h b/src/ObjCommon/Game/IW4/Vehicle/VehicleFields.h similarity index 100% rename from src/ObjCommon/Game/IW4/InfoString/VehicleFields.h rename to src/ObjCommon/Game/IW4/Vehicle/VehicleFields.h diff --git a/src/ObjCommon/Game/IW4/InfoString/WeaponFields.h b/src/ObjCommon/Game/IW4/Weapon/WeaponFields.h similarity index 100% rename from src/ObjCommon/Game/IW4/InfoString/WeaponFields.h rename to src/ObjCommon/Game/IW4/Weapon/WeaponFields.h diff --git a/src/ObjCommon/Game/IW5/InfoString/WeaponFields.h b/src/ObjCommon/Game/IW5/Weapon/WeaponFields.h similarity index 100% rename from src/ObjCommon/Game/IW5/InfoString/WeaponFields.h rename to src/ObjCommon/Game/IW5/Weapon/WeaponFields.h diff --git a/src/ObjCommon/Game/T6/InfoString/PhysConstraintsFields.h b/src/ObjCommon/Game/T6/PhysConstraints/PhysConstraintsFields.h similarity index 96% rename from src/ObjCommon/Game/T6/InfoString/PhysConstraintsFields.h rename to src/ObjCommon/Game/T6/PhysConstraints/PhysConstraintsFields.h index 39d1eaee..a161fd83 100644 --- a/src/ObjCommon/Game/T6/InfoString/PhysConstraintsFields.h +++ b/src/ObjCommon/Game/T6/PhysConstraints/PhysConstraintsFields.h @@ -81,4 +81,17 @@ namespace T6 {"c4_yaw", offsetof(PhysConstraints, data[3].scale.y), CSPFT_FLOAT }, {"c4_pitch", offsetof(PhysConstraints, data[3].scale.x), CSPFT_FLOAT }, }; -} + + inline const char* s_constraintTypeNames[]{ + "none", + "point", + "distance", + "hinge", + "joint", + "actuator", + "fake_shake", + "launch", + "rope", + "light", + }; +} // namespace T6 diff --git a/src/ObjCommon/Game/T6/InfoString/PhysPresetFields.h b/src/ObjCommon/Game/T6/PhysPreset/PhysPresetFields.h similarity index 100% rename from src/ObjCommon/Game/T6/InfoString/PhysPresetFields.h rename to src/ObjCommon/Game/T6/PhysPreset/PhysPresetFields.h diff --git a/src/ObjCommon/Game/T6/InfoString/TracerFields.h b/src/ObjCommon/Game/T6/Tracer/TracerFields.h similarity index 96% rename from src/ObjCommon/Game/T6/InfoString/TracerFields.h rename to src/ObjCommon/Game/T6/Tracer/TracerFields.h index 80b2e3e7..2fd24d09 100644 --- a/src/ObjCommon/Game/T6/InfoString/TracerFields.h +++ b/src/ObjCommon/Game/T6/Tracer/TracerFields.h @@ -36,4 +36,9 @@ namespace T6 {"colorB4", offsetof(TracerDef, colors[4].b), CSPFT_FLOAT }, {"colorA4", offsetof(TracerDef, colors[4].a), CSPFT_FLOAT }, }; -} + + inline const char* tracerTypeNames[]{ + "Laser", + "Smoke", + }; +} // namespace T6 diff --git a/src/ObjCommon/Game/T6/InfoString/VehicleFields.h b/src/ObjCommon/Game/T6/Vehicle/VehicleFields.h similarity index 99% rename from src/ObjCommon/Game/T6/InfoString/VehicleFields.h rename to src/ObjCommon/Game/T6/Vehicle/VehicleFields.h index 3cfe0dcc..ead970fb 100644 --- a/src/ObjCommon/Game/T6/InfoString/VehicleFields.h +++ b/src/ObjCommon/Game/T6/Vehicle/VehicleFields.h @@ -561,4 +561,31 @@ namespace T6 {"customBool1", offsetof(VehicleDef, customBool1), CSPFT_BOOL }, {"customBool2", offsetof(VehicleDef, customBool2), CSPFT_BOOL }, }; -} + + inline const char* s_vehicleClassNames[]{ + "4 wheel", + "motorcycle", + "tank", + "plane", + "boat", + "artillery", + "helicopter", + }; + + inline const char* s_vehicleCameraModes[]{ + "first", + "chase", + "view", + "strafe", + "horse", + "oldtank", + "hover", + "vtol", + }; + + inline const char* s_tractionTypeNames[]{ + "TRACTION_TYPE_FRONT", + "TRACTION_TYPE_BACK", + "TRACTION_TYPE_ALL_WD", + }; +} // namespace T6 diff --git a/src/ObjCommon/Game/T6/InfoString/WeaponAttachmentFields.h b/src/ObjCommon/Game/T6/Weapon/AttachmentFields.h similarity index 99% rename from src/ObjCommon/Game/T6/InfoString/WeaponAttachmentFields.h rename to src/ObjCommon/Game/T6/Weapon/AttachmentFields.h index eff3387c..7fd2d40d 100644 --- a/src/ObjCommon/Game/T6/InfoString/WeaponAttachmentFields.h +++ b/src/ObjCommon/Game/T6/Weapon/AttachmentFields.h @@ -81,4 +81,4 @@ namespace T6 {"customBool1", offsetof(WeaponAttachment, customBool1), CSPFT_BOOL }, {"customBool2", offsetof(WeaponAttachment, customBool2), CSPFT_BOOL }, }; -} +} // namespace T6 diff --git a/src/ObjCommon/Game/T6/InfoString/WeaponAttachmentUniqueFields.h b/src/ObjCommon/Game/T6/Weapon/AttachmentUniqueFields.h similarity index 99% rename from src/ObjCommon/Game/T6/InfoString/WeaponAttachmentUniqueFields.h rename to src/ObjCommon/Game/T6/Weapon/AttachmentUniqueFields.h index 654a6627..819b7a16 100644 --- a/src/ObjCommon/Game/T6/InfoString/WeaponAttachmentUniqueFields.h +++ b/src/ObjCommon/Game/T6/Weapon/AttachmentUniqueFields.h @@ -206,4 +206,4 @@ namespace T6 {"customBool1", offsetof(WeaponAttachmentUniqueFull, attachment.customBool1), CSPFT_BOOL }, {"customBool2", offsetof(WeaponAttachmentUniqueFull, attachment.customBool2), CSPFT_BOOL }, }; -} +} // namespace T6 diff --git a/src/ObjCommon/Game/T6/InfoString/WeaponFields.h b/src/ObjCommon/Game/T6/Weapon/WeaponFields.h similarity index 100% rename from src/ObjCommon/Game/T6/InfoString/WeaponFields.h rename to src/ObjCommon/Game/T6/Weapon/WeaponFields.h diff --git a/src/ObjCommon/Game/T6/InfoString/EnumStrings.h b/src/ObjCommon/Game/T6/Weapon/WeaponStrings.h similarity index 86% rename from src/ObjCommon/Game/T6/InfoString/EnumStrings.h rename to src/ObjCommon/Game/T6/Weapon/WeaponStrings.h index 756db3e1..1bdcae24 100644 --- a/src/ObjCommon/Game/T6/InfoString/EnumStrings.h +++ b/src/ObjCommon/Game/T6/Weapon/WeaponStrings.h @@ -36,31 +36,11 @@ namespace T6 "crosshair", }; - inline const char* szWeapInventoryTypeNames[]{ - "primary", - "offhand", - "item", - "altmode", - "melee", - "dwlefthand", - }; - - inline const char* szWeapClipTypeNames[]{ - "bottom", - "top", - "left", - "dp28", - "ptrs", - "lmg", - }; - - inline const char* barrelTypeNames[]{ - "Single", - "Dual Barrel", - "Dual Barrel Alternate", - "Quad Barrel", - "Quad Barrel Alternate", - "Quad Barrel Double Alternate", + inline const char* penetrateTypeNames[]{ + "none", + "small", + "medium", + "large", }; inline const char* impactTypeNames[]{ @@ -165,6 +145,37 @@ namespace T6 "Turret Scope", }; + inline const char* szWeapInventoryTypeNames[]{ + "primary", + "offhand", + "item", + "altmode", + "melee", + "dwlefthand", + }; + + inline const char* szWeapFireTypeNames[]{ + "Full Auto", + "Single Shot", + "2-Round Burst", + "3-Round Burst", + "4-Round Burst", + "5-Round Burst", + "Stacked Fire", + "Minigun", + "Charge Shot", + "Jetgun", + }; + + inline const char* szWeapClipTypeNames[]{ + "bottom", + "top", + "left", + "dp28", + "ptrs", + "lmg", + }; + inline const char* ammoCounterClipNames[]{ "None", "Magazine", @@ -181,75 +192,13 @@ namespace T6 "4:1", }; - inline const char* szAttachmentTypeNames[]{ - "none", "acog", "dualclip", "dualoptic", "dw", "extbarrel", "extclip", "extramags", "fastads", "fastreload", - "fmj", "gl", "grip", "holo", "ir", "is", "longbreath", "mk", "mms", "rangefinder", - "reflex", "rf", "sf", "silencer", "stackfire", "stalker", "steadyaim", "swayreduc", "tacknife", "vzoom", - }; - - inline const char* szWeapFireTypeNames[]{ - "Full Auto", - "Single Shot", - "2-Round Burst", - "3-Round Burst", - "4-Round Burst", - "5-Round Burst", - "Stacked Fire", - "Minigun", - "Charge Shot", - "Jetgun", - }; - - inline const char* penetrateTypeNames[]{ - "none", - "small", - "medium", - "large", - }; - - inline const char* s_constraintTypeNames[]{ - "none", - "point", - "distance", - "hinge", - "joint", - "actuator", - "fake_shake", - "launch", - "rope", - "light", - }; - - inline const char* s_vehicleClassNames[]{ - "4 wheel", - "motorcycle", - "tank", - "plane", - "boat", - "artillery", - "helicopter", - }; - - inline const char* s_vehicleCameraModes[]{ - "first", - "chase", - "view", - "strafe", - "horse", - "oldtank", - "hover", - "vtol", - }; - - inline const char* s_tractionTypeNames[]{ - "TRACTION_TYPE_FRONT", - "TRACTION_TYPE_BACK", - "TRACTION_TYPE_ALL_WD", - }; - - inline const char* tracerTypeNames[]{ - "Laser", - "Smoke", + inline const char* barrelTypeNames[]{ + "Single", + "Dual Barrel", + "Dual Barrel Alternate", + "Quad Barrel", + "Quad Barrel Alternate", + "Quad Barrel Double Alternate", }; inline const char* bounceSoundSuffixes[]{ @@ -257,4 +206,10 @@ namespace T6 "_gravel", "_ice", "_metal", "_mud", "_paper", "_plaster", "_rock", "_sand", "_snow", "_water", "_wood", "_asphalt", "_ceramic", "_plastic", "_rubber", "_cushion", "_fruit", "_paintedmetal", "_player", "_tallgrass", "_riotshield", }; + + inline const char* szAttachmentTypeNames[]{ + "none", "acog", "dualclip", "dualoptic", "dw", "extbarrel", "extclip", "extramags", "fastads", "fastreload", + "fmj", "gl", "grip", "holo", "ir", "is", "longbreath", "mk", "mms", "rangefinder", + "reflex", "rf", "sf", "silencer", "stackfire", "stalker", "steadyaim", "swayreduc", "tacknife", "vzoom", + }; } // namespace T6 diff --git a/src/ObjCommon/Game/T6/InfoString/ZBarrierFields.h b/src/ObjCommon/Game/T6/ZBarrier/ZBarrierFields.h similarity index 100% rename from src/ObjCommon/Game/T6/InfoString/ZBarrierFields.h rename to src/ObjCommon/Game/T6/ZBarrier/ZBarrierFields.h diff --git a/src/ObjLoading/SearchPath/ISearchPath.cpp b/src/ObjCommon/SearchPath/ISearchPath.cpp similarity index 100% rename from src/ObjLoading/SearchPath/ISearchPath.cpp rename to src/ObjCommon/SearchPath/ISearchPath.cpp diff --git a/src/ObjLoading/SearchPath/ISearchPath.h b/src/ObjCommon/SearchPath/ISearchPath.h similarity index 96% rename from src/ObjLoading/SearchPath/ISearchPath.h rename to src/ObjCommon/SearchPath/ISearchPath.h index 737f9eee..c174f2f3 100644 --- a/src/ObjLoading/SearchPath/ISearchPath.h +++ b/src/ObjCommon/SearchPath/ISearchPath.h @@ -7,6 +7,7 @@ #include #include #include +#include class SearchPathOpenFile { @@ -42,7 +43,7 @@ public: * \brief Returns the path to the search path. * \return The path to the search path. */ - virtual std::string GetPath() = 0; + virtual const std::string& GetPath() = 0; /** * \brief Iterates through all files of the search path. diff --git a/src/ObjLoading/SearchPath/SearchPathFilesystem.cpp b/src/ObjCommon/SearchPath/SearchPathFilesystem.cpp similarity index 88% rename from src/ObjLoading/SearchPath/SearchPathFilesystem.cpp rename to src/ObjCommon/SearchPath/SearchPathFilesystem.cpp index 6d6804a6..a87f972e 100644 --- a/src/ObjLoading/SearchPath/SearchPathFilesystem.cpp +++ b/src/ObjCommon/SearchPath/SearchPathFilesystem.cpp @@ -3,16 +3,18 @@ #include "Utils/ObjFileStream.h" #include +#include #include +#include namespace fs = std::filesystem; SearchPathFilesystem::SearchPathFilesystem(std::string path) + : m_path(std::move(path)) { - m_path = std::move(path); } -std::string SearchPathFilesystem::GetPath() +const std::string& SearchPathFilesystem::GetPath() { return m_path; } @@ -23,9 +25,7 @@ SearchPathOpenFile SearchPathFilesystem::Open(const std::string& fileName) std::ifstream file(filePath.string(), std::fstream::in | std::fstream::binary); if (file.is_open()) - { return SearchPathOpenFile(std::make_unique(std::move(file)), static_cast(file_size(filePath))); - } return SearchPathOpenFile(); } @@ -59,6 +59,6 @@ void SearchPathFilesystem::Find(const SearchPathSearchOptions& options, const st } catch (std::filesystem::filesystem_error& e) { - printf("Directory Iterator threw error when trying to find files: \"%s\"\n", e.what()); + std::cerr << std::format("Directory Iterator threw error when trying to find files: \"{}\"\n", e.what()); } } diff --git a/src/ObjLoading/SearchPath/SearchPathFilesystem.h b/src/ObjCommon/SearchPath/SearchPathFilesystem.h similarity index 90% rename from src/ObjLoading/SearchPath/SearchPathFilesystem.h rename to src/ObjCommon/SearchPath/SearchPathFilesystem.h index c6c200aa..e1d015cf 100644 --- a/src/ObjLoading/SearchPath/SearchPathFilesystem.h +++ b/src/ObjCommon/SearchPath/SearchPathFilesystem.h @@ -12,6 +12,6 @@ public: explicit SearchPathFilesystem(std::string path); SearchPathOpenFile Open(const std::string& fileName) override; - std::string GetPath() override; + const std::string& GetPath() override; void Find(const SearchPathSearchOptions& options, const std::function& callback) override; }; diff --git a/src/ObjCommon/SearchPath/SearchPathMultiInputStream.cpp b/src/ObjCommon/SearchPath/SearchPathMultiInputStream.cpp new file mode 100644 index 00000000..09477982 --- /dev/null +++ b/src/ObjCommon/SearchPath/SearchPathMultiInputStream.cpp @@ -0,0 +1,15 @@ +#include "SearchPathMultiInputStream.h" + +SearchPathMultiInputStream::SearchPathMultiInputStream(ISearchPath& searchPath) + : m_search_path(searchPath) +{ +} + +std::unique_ptr SearchPathMultiInputStream::OpenIncludedFile(const std::string& filename, const std::string& sourceFile) +{ + auto foundFileToInclude = m_search_path.Open(filename); + if (!foundFileToInclude.IsOpen() || !foundFileToInclude.m_stream) + return nullptr; + + return std::move(foundFileToInclude.m_stream); +} diff --git a/src/ObjCommon/SearchPath/SearchPathMultiInputStream.h b/src/ObjCommon/SearchPath/SearchPathMultiInputStream.h new file mode 100644 index 00000000..7c966295 --- /dev/null +++ b/src/ObjCommon/SearchPath/SearchPathMultiInputStream.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Parsing/Impl/ParserMultiInputStream.h" +#include "SearchPath/ISearchPath.h" + +class SearchPathMultiInputStream : public IInclusionCallback +{ +public: + explicit SearchPathMultiInputStream(ISearchPath& searchPath); + + std::unique_ptr OpenIncludedFile(const std::string& filename, const std::string& sourceFile) override; + +protected: + ISearchPath& m_search_path; +}; diff --git a/src/ObjLoading/SearchPath/SearchPathSearchOptions.cpp b/src/ObjCommon/SearchPath/SearchPathSearchOptions.cpp similarity index 100% rename from src/ObjLoading/SearchPath/SearchPathSearchOptions.cpp rename to src/ObjCommon/SearchPath/SearchPathSearchOptions.cpp diff --git a/src/ObjLoading/SearchPath/SearchPathSearchOptions.h b/src/ObjCommon/SearchPath/SearchPathSearchOptions.h similarity index 100% rename from src/ObjLoading/SearchPath/SearchPathSearchOptions.h rename to src/ObjCommon/SearchPath/SearchPathSearchOptions.h diff --git a/src/ObjLoading/SearchPath/SearchPaths.cpp b/src/ObjCommon/SearchPath/SearchPaths.cpp similarity index 91% rename from src/ObjLoading/SearchPath/SearchPaths.cpp rename to src/ObjCommon/SearchPath/SearchPaths.cpp index 58cf62a4..80ed1300 100644 --- a/src/ObjLoading/SearchPath/SearchPaths.cpp +++ b/src/ObjCommon/SearchPath/SearchPaths.cpp @@ -18,9 +18,10 @@ SearchPathOpenFile SearchPaths::Open(const std::string& fileName) return SearchPathOpenFile(); } -std::string SearchPaths::GetPath() +const std::string& SearchPaths::GetPath() { - return "SearchPaths: " + std::to_string(m_search_paths.size()) + " entries"; + static const std::string STATIC_NAME = "SearchPaths"; + return STATIC_NAME; } void SearchPaths::Find(const SearchPathSearchOptions& options, const std::function& callback) diff --git a/src/ObjLoading/SearchPath/SearchPaths.h b/src/ObjCommon/SearchPath/SearchPaths.h similarity index 96% rename from src/ObjLoading/SearchPath/SearchPaths.h rename to src/ObjCommon/SearchPath/SearchPaths.h index a1a06252..36fe54e1 100644 --- a/src/ObjLoading/SearchPath/SearchPaths.h +++ b/src/ObjCommon/SearchPath/SearchPaths.h @@ -2,6 +2,7 @@ #include "ISearchPath.h" +#include #include class SearchPaths final : public ISearchPath @@ -16,7 +17,7 @@ public: ~SearchPaths() override = default; SearchPathOpenFile Open(const std::string& fileName) override; - std::string GetPath() override; + const std::string& GetPath() override; void Find(const SearchPathSearchOptions& options, const std::function& callback) override; SearchPaths(const SearchPaths& other) = delete; diff --git a/src/ObjCompiling.lua b/src/ObjCompiling.lua new file mode 100644 index 00000000..38691e33 --- /dev/null +++ b/src/ObjCompiling.lua @@ -0,0 +1,58 @@ +ObjCompiling = {} + +function ObjCompiling:include(includes) + if includes:handle(self:name()) then + ObjCommon:include(includes) + ObjLoading:include(includes) + ObjImage:include(includes) + ZoneCommon:include(includes) + includedirs { + path.join(ProjectFolder(), "ObjCompiling") + } + end +end + +function ObjCompiling:link(links) + links:add(self:name()) + links:linkto(minilzo) + links:linkto(Utils) + links:linkto(ObjCommon) + links:linkto(ObjLoading) + links:linkto(ObjImage) + links:linkto(ZoneCommon) +end + +function ObjCompiling:use() + +end + +function ObjCompiling:name() + return "ObjCompiling" +end + +function ObjCompiling:project() + local folder = ProjectFolder() + local includes = Includes:create() + + project(self:name()) + targetdir(TargetDirectoryLib) + location "%{wks.location}/src/%{prj.name}" + kind "StaticLib" + language "C++" + + files { + path.join(folder, "ObjCompiling/**.h"), + path.join(folder, "ObjCompiling/**.cpp") + } + + vpaths { + ["*"] = { + path.join(folder, "ObjCompiling") + } + } + + self:include(includes) + minilzo:include(includes) + Utils:include(includes) + json:include(includes) +end diff --git a/src/ObjCompiling/Game/IW3/ObjCompilerIW3.cpp b/src/ObjCompiling/Game/IW3/ObjCompilerIW3.cpp new file mode 100644 index 00000000..b3914ae8 --- /dev/null +++ b/src/ObjCompiling/Game/IW3/ObjCompilerIW3.cpp @@ -0,0 +1,44 @@ +#include "ObjCompilerIW3.h" + +#include "Game/IW3/IW3.h" +#include "Image/ImageIwdPostProcessor.h" + +#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, + const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + ZoneAssetCreationStateContainer& zoneStates, + const fs::path& outDir) + { + auto& memory = *zone.GetMemory(); + + if (ImageIwdPostProcessor::AppliesToZoneDefinition(zoneDefinition)) + collection.AddAssetPostProcessor(std::make_unique>(zoneDefinition, searchPath, zoneStates, outDir)); + } +} // namespace + +void ObjCompiler::ConfigureCreatorCollection(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + IGdtQueryable& gdt, + ZoneAssetCreationStateContainer& zoneStates, + const fs::path& outDir, + const fs::path& cacheDir) const +{ + ConfigurePostProcessors(collection, zone, zoneDefinition, searchPath, zoneStates, outDir); +} diff --git a/src/ObjCompiling/Game/IW3/ObjCompilerIW3.h b/src/ObjCompiling/Game/IW3/ObjCompilerIW3.h new file mode 100644 index 00000000..771821a7 --- /dev/null +++ b/src/ObjCompiling/Game/IW3/ObjCompilerIW3.h @@ -0,0 +1,19 @@ +#pragma once + +#include "IObjCompiler.h" + +namespace IW3 +{ + class ObjCompiler final : public IObjCompiler + { + public: + void ConfigureCreatorCollection(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + IGdtQueryable& gdt, + ZoneAssetCreationStateContainer& zoneStates, + 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 new file mode 100644 index 00000000..12f8e839 --- /dev/null +++ b/src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp @@ -0,0 +1,44 @@ +#include "ObjCompilerIW4.h" + +#include "Game/IW4/IW4.h" +#include "Image/ImageIwdPostProcessor.h" + +#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, + const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + ZoneAssetCreationStateContainer& zoneStates, + const fs::path& outDir) + { + auto& memory = *zone.GetMemory(); + + if (ImageIwdPostProcessor::AppliesToZoneDefinition(zoneDefinition)) + collection.AddAssetPostProcessor(std::make_unique>(zoneDefinition, searchPath, zoneStates, outDir)); + } +} // namespace + +void ObjCompiler::ConfigureCreatorCollection(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + IGdtQueryable& gdt, + ZoneAssetCreationStateContainer& zoneStates, + const fs::path& outDir, + const fs::path& cacheDir) const +{ + ConfigurePostProcessors(collection, zone, zoneDefinition, searchPath, zoneStates, outDir); +} diff --git a/src/ObjCompiling/Game/IW4/ObjCompilerIW4.h b/src/ObjCompiling/Game/IW4/ObjCompilerIW4.h new file mode 100644 index 00000000..522b3c51 --- /dev/null +++ b/src/ObjCompiling/Game/IW4/ObjCompilerIW4.h @@ -0,0 +1,19 @@ +#pragma once + +#include "IObjCompiler.h" + +namespace IW4 +{ + class ObjCompiler final : public IObjCompiler + { + public: + void ConfigureCreatorCollection(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + IGdtQueryable& gdt, + ZoneAssetCreationStateContainer& zoneStates, + 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 new file mode 100644 index 00000000..dbfc20d0 --- /dev/null +++ b/src/ObjCompiling/Game/IW5/ObjCompilerIW5.cpp @@ -0,0 +1,44 @@ +#include "ObjCompilerIW5.h" + +#include "Game/IW5/IW5.h" +#include "Image/ImageIwdPostProcessor.h" + +#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, + const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + ZoneAssetCreationStateContainer& zoneStates, + const fs::path& outDir) + { + auto& memory = *zone.GetMemory(); + + if (ImageIwdPostProcessor::AppliesToZoneDefinition(zoneDefinition)) + collection.AddAssetPostProcessor(std::make_unique>(zoneDefinition, searchPath, zoneStates, outDir)); + } +} // namespace + +void ObjCompiler::ConfigureCreatorCollection(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + IGdtQueryable& gdt, + ZoneAssetCreationStateContainer& zoneStates, + const fs::path& outDir, + const fs::path& cacheDir) const +{ + ConfigurePostProcessors(collection, zone, zoneDefinition, searchPath, zoneStates, outDir); +} diff --git a/src/ObjCompiling/Game/IW5/ObjCompilerIW5.h b/src/ObjCompiling/Game/IW5/ObjCompilerIW5.h new file mode 100644 index 00000000..80805f77 --- /dev/null +++ b/src/ObjCompiling/Game/IW5/ObjCompilerIW5.h @@ -0,0 +1,19 @@ +#pragma once + +#include "IObjCompiler.h" + +namespace IW5 +{ + class ObjCompiler final : public IObjCompiler + { + public: + void ConfigureCreatorCollection(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + IGdtQueryable& gdt, + ZoneAssetCreationStateContainer& zoneStates, + 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 new file mode 100644 index 00000000..5fb02146 --- /dev/null +++ b/src/ObjCompiling/Game/T5/ObjCompilerT5.cpp @@ -0,0 +1,44 @@ +#include "ObjCompilerT5.h" + +#include "Game/T5/T5.h" +#include "Image/ImageIwdPostProcessor.h" + +#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, + const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + ZoneAssetCreationStateContainer& zoneStates, + const fs::path& outDir) + { + auto& memory = *zone.GetMemory(); + + if (ImageIwdPostProcessor::AppliesToZoneDefinition(zoneDefinition)) + collection.AddAssetPostProcessor(std::make_unique>(zoneDefinition, searchPath, zoneStates, outDir)); + } +} // namespace + +void ObjCompiler::ConfigureCreatorCollection(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + IGdtQueryable& gdt, + ZoneAssetCreationStateContainer& zoneStates, + const fs::path& outDir, + const fs::path& cacheDir) const +{ + ConfigurePostProcessors(collection, zone, zoneDefinition, searchPath, zoneStates, outDir); +} diff --git a/src/ObjCompiling/Game/T5/ObjCompilerT5.h b/src/ObjCompiling/Game/T5/ObjCompilerT5.h new file mode 100644 index 00000000..bd216b7c --- /dev/null +++ b/src/ObjCompiling/Game/T5/ObjCompilerT5.h @@ -0,0 +1,19 @@ +#pragma once + +#include "IObjCompiler.h" + +namespace T5 +{ + class ObjCompiler final : public IObjCompiler + { + public: + void ConfigureCreatorCollection(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + IGdtQueryable& gdt, + ZoneAssetCreationStateContainer& zoneStates, + const std::filesystem::path& outDir, + const std::filesystem::path& cacheDir) const override; + }; +} // namespace T5 diff --git a/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderPhysPreset.cpp b/src/ObjCompiling/Game/T6/Image/ImageCompilerT6.cpp similarity index 100% rename from src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderPhysPreset.cpp rename to src/ObjCompiling/Game/T6/Image/ImageCompilerT6.cpp diff --git a/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderPhysPreset.h b/src/ObjCompiling/Game/T6/Image/ImageCompilerT6.h similarity index 100% rename from src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderPhysPreset.h rename to src/ObjCompiling/Game/T6/Image/ImageCompilerT6.h diff --git a/src/ObjCompiling/Game/T6/KeyValuePairs/KeyValuePairsCompilerT6.cpp b/src/ObjCompiling/Game/T6/KeyValuePairs/KeyValuePairsCompilerT6.cpp new file mode 100644 index 00000000..11c98ea1 --- /dev/null +++ b/src/ObjCompiling/Game/T6/KeyValuePairs/KeyValuePairsCompilerT6.cpp @@ -0,0 +1,62 @@ +#include "KeyValuePairsCompilerT6.h" + +#include "Game/T6/CommonT6.h" +#include "Game/T6/T6.h" + +#include +#include +#include + +using namespace T6; + +KeyValuePairsCompiler::KeyValuePairsCompiler(MemoryManager& memory, + const Zone& zone, + const ZoneDefinition& zoneDefinition, + ZoneAssetCreationStateContainer& zoneStates) + : m_memory(memory), + m_zone(zone), + m_zone_definition(zoneDefinition), + m_kvp_creator(zoneStates.GetZoneAssetCreationState()) +{ +} + +std::optional KeyValuePairsCompiler::GetHandlingAssetType() const +{ + return std::nullopt; +} + +AssetCreationResult KeyValuePairsCompiler::CreateAsset(const std::string& assetName, AssetCreationContext& context) +{ + return AssetCreationResult::NoAction(); +} + +void KeyValuePairsCompiler::FinalizeZone(AssetCreationContext& context) +{ + m_kvp_creator.Finalize(m_zone_definition); + const auto commonKvps = m_kvp_creator.GetFinalKeyValuePairs(); + if (commonKvps.empty()) + return; + + auto* gameKvps = m_memory.Alloc(); + gameKvps->name = m_memory.Dup(m_zone.m_name.c_str()); + gameKvps->numVariables = commonKvps.size(); + gameKvps->keyValuePairs = m_memory.Alloc(commonKvps.size()); + + const auto namespaceHash = Common::Com_HashKey(m_zone.m_name.c_str(), 64); + for (auto kvpIndex = 0u; kvpIndex < gameKvps->numVariables; kvpIndex++) + { + const auto& commonKvp = commonKvps[kvpIndex]; + auto& gameKvp = gameKvps->keyValuePairs[kvpIndex]; + + assert(commonKvp.m_key_str || commonKvp.m_key_hash); + if (commonKvp.m_key_str) + gameKvp.keyHash = Common::Com_HashKey(commonKvp.m_key_str->c_str(), 64); + else + gameKvp.keyHash = *commonKvp.m_key_hash; + + gameKvp.namespaceHash = namespaceHash; + gameKvp.value = m_memory.Dup(commonKvp.m_value.c_str()); + } + + context.AddAsset(AssetRegistration(m_zone.m_name, gameKvps)); +} diff --git a/src/ObjCompiling/Game/T6/KeyValuePairs/KeyValuePairsCompilerT6.h b/src/ObjCompiling/Game/T6/KeyValuePairs/KeyValuePairsCompilerT6.h new file mode 100644 index 00000000..fa5ea50e --- /dev/null +++ b/src/ObjCompiling/Game/T6/KeyValuePairs/KeyValuePairsCompilerT6.h @@ -0,0 +1,27 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "KeyValuePairs/KeyValuePairsCreator.h" +#include "Utils/MemoryManager.h" +#include "Zone/Definition/ZoneDefinition.h" +#include "Zone/Zone.h" + +namespace T6 +{ + class KeyValuePairsCompiler final : public IAssetCreator + { + public: + KeyValuePairsCompiler(MemoryManager& memory, const Zone& zone, const ZoneDefinition& zoneDefinition, ZoneAssetCreationStateContainer& zoneStates); + + [[nodiscard]] std::optional GetHandlingAssetType() const override; + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override; + void FinalizeZone(AssetCreationContext& context) override; + + private: + MemoryManager& m_memory; + const Zone& m_zone; + const ZoneDefinition& m_zone_definition; + KeyValuePairsCreator& m_kvp_creator; + }; +} // namespace T6 diff --git a/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp b/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp new file mode 100644 index 00000000..807f8aae --- /dev/null +++ b/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp @@ -0,0 +1,54 @@ +#include "ObjCompilerT6.h" + +#include "Game/T6/T6.h" +#include "Image/ImageIPakPostProcessor.h" +#include "Image/ImageIwdPostProcessor.h" +#include "KeyValuePairs/KeyValuePairsCompilerT6.h" + +#include + +using namespace T6; +namespace fs = std::filesystem; + +namespace +{ + void ConfigureCompilers(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + ZoneAssetCreationStateContainer& zoneStates) + { + auto& memory = *zone.GetMemory(); + + collection.AddAssetCreator(std::make_unique(memory, zone, zoneDefinition.m_zone_definition, zoneStates)); + } + + void ConfigurePostProcessors(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + ZoneAssetCreationStateContainer& zoneStates, + const fs::path& outDir) + { + auto& memory = *zone.GetMemory(); + + if (ImageIPakPostProcessor::AppliesToZoneDefinition(zoneDefinition)) + collection.AddAssetPostProcessor(std::make_unique>(zoneDefinition, searchPath, zoneStates, outDir)); + + if (ImageIwdPostProcessor::AppliesToZoneDefinition(zoneDefinition)) + collection.AddAssetPostProcessor(std::make_unique>(zoneDefinition, searchPath, zoneStates, outDir)); + } +} // namespace + +void ObjCompiler::ConfigureCreatorCollection(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + IGdtQueryable& gdt, + ZoneAssetCreationStateContainer& zoneStates, + const fs::path& outDir, + const fs::path& cacheDir) const +{ + ConfigureCompilers(collection, zone, zoneDefinition, searchPath, zoneStates); + ConfigurePostProcessors(collection, zone, zoneDefinition, searchPath, zoneStates, outDir); +} diff --git a/src/ObjCompiling/Game/T6/ObjCompilerT6.h b/src/ObjCompiling/Game/T6/ObjCompilerT6.h new file mode 100644 index 00000000..73d30655 --- /dev/null +++ b/src/ObjCompiling/Game/T6/ObjCompilerT6.h @@ -0,0 +1,19 @@ +#pragma once + +#include "IObjCompiler.h" + +namespace T6 +{ + class ObjCompiler final : public IObjCompiler + { + public: + void ConfigureCreatorCollection(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + IGdtQueryable& gdt, + ZoneAssetCreationStateContainer& zoneStates, + const std::filesystem::path& outDir, + const std::filesystem::path& cacheDir) const override; + }; +} // namespace T6 diff --git a/src/ObjCompiling/IObjCompiler.cpp b/src/ObjCompiling/IObjCompiler.cpp new file mode 100644 index 00000000..702f8865 --- /dev/null +++ b/src/ObjCompiling/IObjCompiler.cpp @@ -0,0 +1,27 @@ +#include "IObjCompiler.h" + +#include "Game/IW3/ObjCompilerIW3.h" +#include "Game/IW4/ObjCompilerIW4.h" +#include "Game/IW5/ObjCompilerIW5.h" +#include "Game/T5/ObjCompilerT5.h" +#include "Game/T6/ObjCompilerT6.h" + +#include + +const IObjCompiler* IObjCompiler::GetObjCompilerForGame(GameId game) +{ + static const IObjCompiler* objCompilers[static_cast(GameId::COUNT)]{ + new IW3::ObjCompiler(), + new IW4::ObjCompiler(), + new IW5::ObjCompiler(), + new T5::ObjCompiler(), + new T6::ObjCompiler(), + }; + static_assert(std::extent_v == static_cast(GameId::COUNT)); + + assert(static_cast(game) < static_cast(GameId::COUNT)); + const auto* result = objCompilers[static_cast(game)]; + assert(result); + + return result; +} diff --git a/src/ObjCompiling/IObjCompiler.h b/src/ObjCompiling/IObjCompiler.h new file mode 100644 index 00000000..26bac9ba --- /dev/null +++ b/src/ObjCompiling/IObjCompiler.h @@ -0,0 +1,35 @@ +#pragma once + +#include "Asset/AssetCreatorCollection.h" +#include "Asset/IZoneAssetCreationState.h" +#include "Asset/ZoneDefinitionContext.h" +#include "Gdt/IGdtQueryable.h" +#include "SearchPath/ISearchPath.h" +#include "Zone/Definition/ZoneDefinition.h" +#include "Zone/Zone.h" + +#include +#include +#include + +class IObjCompiler +{ +public: + IObjCompiler() = default; + virtual ~IObjCompiler() = default; + IObjCompiler(const IObjCompiler& other) = default; + IObjCompiler(IObjCompiler&& other) noexcept = default; + IObjCompiler& operator=(const IObjCompiler& other) = default; + IObjCompiler& operator=(IObjCompiler&& other) noexcept = default; + + virtual void ConfigureCreatorCollection(AssetCreatorCollection& collection, + Zone& zone, + const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + IGdtQueryable& gdt, + ZoneAssetCreationStateContainer& zoneStates, + 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..d18c127c --- /dev/null +++ b/src/ObjCompiling/Image/IPak/IPakCreator.cpp @@ -0,0 +1,431 @@ +#include "IPakCreator.h" + +#include "Game/T6/CommonT6.h" +#include "Game/T6/GameT6.h" +#include "GitVersion.h" +#include "ObjContainer/IPak/IPakTypes.h" +#include "Utils/Alignment.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + constexpr auto USE_IPAK_COMPRESSION = true; + + class IPakWriter + { + static constexpr char BRANDING[] = "Created with OpenAssetTools " GIT_VERSION; + static constexpr auto SECTION_COUNT = 3; // Index + Data + Branding + + inline static const std::string PAD_DATA = std::string(256, '\xA7'); + + public: + IPakWriter(std::ostream& stream, ISearchPath& searchPath, const std::vector& images) + : m_stream(stream), + m_search_path(searchPath), + m_images(images), + m_current_offset(0), + m_total_size(0), + m_data_section_offset(0), + m_data_section_size(0u), + m_index_section_offset(0), + m_branding_section_offset(0), + m_file_offset(0u), + m_chunk_buffer_window_start(0), + m_current_block{}, + m_current_block_header_offset(0) + { + m_decompressed_buffer = std::make_unique(ipak_consts::IPAK_CHUNK_SIZE); + m_lzo_work_buffer = std::make_unique(LZO1X_1_MEM_COMPRESS); + } + + bool Write() + { + // We will write the header and sections later since they need complementary data + GoTo(sizeof(IPakHeader) + sizeof(IPakSection) * SECTION_COUNT); + AlignToChunk(); + + WriteDataSection(); + WriteIndexSection(); + WriteBrandingSection(); + WriteFileEnding(); + + WriteHeaderData(); + + return true; + } + + private: + void GoTo(const int64_t offset) + { + m_stream.seekp(offset, std::ios::beg); + m_current_offset = offset; + } + + void Write(const void* data, const size_t dataSize) + { + m_stream.write(static_cast(data), dataSize); + m_current_offset += dataSize; + } + + void Pad(const size_t paddingSize) + { + auto paddingSizeLeft = paddingSize; + while (paddingSizeLeft > 0) + { + const auto writeSize = std::min(paddingSizeLeft, PAD_DATA.size()); + Write(PAD_DATA.data(), writeSize); + + paddingSizeLeft -= writeSize; + } + } + + void AlignToChunk() + { + Pad(static_cast(utils::Align(m_current_offset, static_cast(ipak_consts::IPAK_CHUNK_SIZE)) - m_current_offset)); + } + + void AlignToBlockHeader() + { + Pad(static_cast(utils::Align(m_current_offset, static_cast(sizeof(IPakDataBlockHeader))) - m_current_offset)); + } + + void WriteHeaderData() + { + GoTo(0); + + const IPakHeader header{ipak_consts::IPAK_MAGIC, ipak_consts::IPAK_VERSION, static_cast(m_total_size), SECTION_COUNT}; + + const IPakSection dataSection{ + ipak_consts::IPAK_DATA_SECTION, + static_cast(m_data_section_offset), + static_cast(m_data_section_size), + static_cast(m_index_entries.size()), + }; + + const IPakSection indexSection{ + ipak_consts::IPAK_INDEX_SECTION, + static_cast(m_index_section_offset), + static_cast(sizeof(IPakIndexEntry) * m_index_entries.size()), + static_cast(m_index_entries.size()), + }; + + const IPakSection brandingSection{ + ipak_consts::IPAK_BRANDING_SECTION, + static_cast(m_branding_section_offset), + std::extent_v, + 1, + }; + + Write(&header, sizeof(header)); + Write(&dataSection, sizeof(dataSection)); + Write(&indexSection, sizeof(indexSection)); + Write(&brandingSection, sizeof(brandingSection)); + } + + static std::string ImageFileName(const std::string& imageName) + { + return std::format("images/{}.iwi", imageName); + } + + std::unique_ptr ReadImageDataFromSearchPath(const std::string& imageName, size_t& imageSize) const + { + const auto fileName = ImageFileName(imageName); + + const auto openFile = m_search_path.Open(fileName); + if (!openFile.IsOpen()) + { + std::cerr << std::format("Failed to open file for ipak: {}\n", fileName); + return nullptr; + } + + imageSize = static_cast(openFile.m_length); + auto imageData = std::make_unique(imageSize); + openFile.m_stream->read(imageData.get(), imageSize); + + return imageData; + } + + void FlushBlock() + { + if (m_current_block_header_offset > 0) + { + const auto previousOffset = m_current_offset; + + GoTo(m_current_block_header_offset); + Write(&m_current_block, sizeof(m_current_block)); + GoTo(previousOffset); + } + } + + void FlushChunk() + { + FlushBlock(); + AlignToBlockHeader(); + + const auto nextChunkOffset = utils::Align(m_current_offset, static_cast(ipak_consts::IPAK_CHUNK_SIZE)); + const auto sizeToSkip = static_cast(nextChunkOffset - m_current_offset); + + if (sizeToSkip >= sizeof(IPakDataBlockHeader)) + { + IPakDataBlockHeader skipBlockHeader{}; + skipBlockHeader.countAndOffset.count = 1; + skipBlockHeader.commands[0].compressed = ipak_consts::IPAK_COMMAND_SKIP; + skipBlockHeader.commands[0].size = sizeToSkip - sizeof(IPakDataBlockHeader); + Write(&skipBlockHeader, sizeof(skipBlockHeader)); + } + + AlignToChunk(); + m_chunk_buffer_window_start = m_current_offset; + } + + void StartNewBlock() + { + AlignToBlockHeader(); + + // Skip to the next chunk when only the header could fit into the current chunk anyway + if (static_cast(utils::Align(m_current_offset, static_cast(ipak_consts::IPAK_CHUNK_SIZE)) - m_current_offset) + <= sizeof(IPakDataBlockHeader)) + FlushChunk(); + + m_current_block_header_offset = m_current_offset; + m_current_block = {}; + m_current_block.countAndOffset.offset = static_cast(m_file_offset); + + // Reserve space to later write actual block header data + GoTo(m_current_offset + sizeof(IPakDataBlockHeader)); + } + + void WriteChunkData(const void* data, const size_t dataSize) + { + auto dataOffset = 0u; + while (dataOffset < dataSize) + { + if (m_current_block.countAndOffset.count >= std::extent_v) + { + FlushBlock(); + StartNewBlock(); + } + + const auto remainingSize = dataSize - dataOffset; + const auto remainingChunkBufferWindowSize = std::max((ipak_consts::IPAK_CHUNK_COUNT_PER_READ * ipak_consts::IPAK_CHUNK_SIZE) + - static_cast(m_current_offset - m_chunk_buffer_window_start), + 0u); + + if (remainingChunkBufferWindowSize == 0) + { + FlushChunk(); + StartNewBlock(); + continue; + } + + const auto commandSize = std::min(std::min(remainingSize, ipak_consts::IPAK_COMMAND_DEFAULT_SIZE), remainingChunkBufferWindowSize); + + auto writeUncompressed = true; + if (USE_IPAK_COMPRESSION) + { + auto outLen = static_cast(ipak_consts::IPAK_CHUNK_SIZE); + const auto result = lzo1x_1_compress(&static_cast(data)[dataOffset], + commandSize, + reinterpret_cast(m_decompressed_buffer.get()), + &outLen, + m_lzo_work_buffer.get()); + + if (result == LZO_E_OK && outLen < commandSize) + { + writeUncompressed = false; + Write(m_decompressed_buffer.get(), outLen); + + const auto currentCommand = m_current_block.countAndOffset.count; + m_current_block.commands[currentCommand].size = static_cast(outLen); + m_current_block.commands[currentCommand].compressed = ipak_consts::IPAK_COMMAND_COMPRESSED; + m_current_block.countAndOffset.count = currentCommand + 1u; + } + } + + if (writeUncompressed) + { + Write(&static_cast(data)[dataOffset], commandSize); + + const auto currentCommand = m_current_block.countAndOffset.count; + m_current_block.commands[currentCommand].size = commandSize; + m_current_block.commands[currentCommand].compressed = ipak_consts::IPAK_COMMAND_UNCOMPRESSED; + m_current_block.countAndOffset.count = currentCommand + 1u; + } + + dataOffset += commandSize; + m_file_offset += commandSize; + } + } + + void StartNewFile() + { + FlushBlock(); + + m_file_offset = 0u; + StartNewBlock(); + m_chunk_buffer_window_start = utils::AlignToPrevious(m_current_offset, static_cast(ipak_consts::IPAK_CHUNK_SIZE)); + } + + void WriteImageData(const std::string& imageName) + { + size_t imageSize; + const auto imageData = ReadImageDataFromSearchPath(imageName, imageSize); + if (!imageData) + return; + + const auto nameHash = T6::Common::R_HashString(imageName.c_str(), 0); + const auto dataHash = static_cast(crc32(0u, reinterpret_cast(imageData.get()), imageSize)); + + StartNewFile(); + const auto startOffset = m_current_block_header_offset; + + IPakIndexEntry indexEntry; + indexEntry.key.nameHash = nameHash; + indexEntry.key.dataHash = dataHash & 0x1FFFFFFF; + indexEntry.offset = static_cast(startOffset - m_data_section_offset); + + WriteChunkData(imageData.get(), imageSize); + const auto writtenImageSize = static_cast(m_current_offset - startOffset); + + indexEntry.size = writtenImageSize; + m_index_entries.emplace_back(indexEntry); + } + + void WriteDataSection() + { + AlignToChunk(); + m_data_section_offset = m_current_offset; + m_data_section_size = 0u; + + m_index_entries.reserve(m_images.size()); + + for (const auto& imageName : m_images) + WriteImageData(imageName); + + FlushBlock(); + m_data_section_size = static_cast(m_current_offset - m_data_section_offset); + } + + static bool CompareIndices(const IPakIndexEntry& entry1, const IPakIndexEntry& entry2) + { + return entry1.key.combinedKey < entry2.key.combinedKey; + } + + void SortIndexSectionEntries() + { + std::ranges::sort(m_index_entries, CompareIndices); + } + + void WriteIndexSection() + { + AlignToChunk(); + m_index_section_offset = m_current_offset; + + SortIndexSectionEntries(); + + for (const auto& indexEntry : m_index_entries) + Write(&indexEntry, sizeof(indexEntry)); + } + + void WriteBrandingSection() + { + AlignToChunk(); + m_branding_section_offset = m_current_offset; + + Write(BRANDING, std::extent_v); + } + + void WriteFileEnding() + { + AlignToChunk(); + m_total_size = m_current_offset; + } + + std::ostream& m_stream; + ISearchPath& m_search_path; + const std::vector& m_images; + + int64_t m_current_offset; + std::vector m_index_entries; + int64_t m_total_size; + int64_t m_data_section_offset; + size_t m_data_section_size; + int64_t m_index_section_offset; + int64_t m_branding_section_offset; + + std::unique_ptr m_decompressed_buffer; + std::unique_ptr m_lzo_work_buffer; + size_t m_file_offset; + int64_t m_chunk_buffer_window_start; + IPakDataBlockHeader m_current_block; + int64_t m_current_block_header_offset; + }; +} // namespace + +IPakToCreate::IPakToCreate(std::string name) + : m_name(std::move(name)) +{ +} + +void IPakToCreate::AddImage(std::string imageName) +{ + m_image_names.emplace_back(std::move(imageName)); +} + +void IPakToCreate::Build(ISearchPath& searchPath, const std::filesystem::path& outPath) +{ + auto filePath = outPath / std::format("{}.ipak", m_name); + std::ofstream file(filePath, std::ios::out | std::ios::binary); + if (!file.is_open()) + { + std::cerr << std::format("Failed to open file for ipak {}\n", m_name); + return; + } + + IPakWriter writer(file, searchPath, m_image_names); + writer.Write(); + + std::cout << std::format("Created ipak {} with {} entries\n", m_name, m_image_names.size()); +} + +IPakCreator::IPakCreator() + : m_kvp_creator(nullptr) +{ +} + +void IPakCreator::Inject(ZoneAssetCreationInjection& inject) +{ + m_kvp_creator = &inject.m_zone_states.GetZoneAssetCreationState(); +} + +IPakToCreate* IPakCreator::GetOrAddIPak(const std::string& ipakName) +{ + const auto existingIPak = m_ipak_lookup.find(ipakName); + if (existingIPak != m_ipak_lookup.end()) + return existingIPak->second; + + auto newIPak = std::make_unique(ipakName); + auto* result = newIPak.get(); + m_ipaks.emplace_back(std::move(newIPak)); + + assert(m_kvp_creator); + m_kvp_creator->AddKeyValuePair(CommonKeyValuePair("ipak_read", ipakName)); + + return result; +} + +void IPakCreator::Finalize(ISearchPath& searchPath, const std::filesystem::path& outPath) +{ + for (const auto& ipakToCreate : m_ipaks) + ipakToCreate->Build(searchPath, outPath); + + m_ipaks.clear(); + m_ipak_lookup.clear(); +} diff --git a/src/ObjCompiling/Image/IPak/IPakCreator.h b/src/ObjCompiling/Image/IPak/IPakCreator.h new file mode 100644 index 00000000..6b9a7565 --- /dev/null +++ b/src/ObjCompiling/Image/IPak/IPakCreator.h @@ -0,0 +1,39 @@ +#pragma once + +#include "Asset/IZoneAssetCreationState.h" +#include "KeyValuePairs/KeyValuePairsCreator.h" +#include "SearchPath/ISearchPath.h" + +#include +#include +#include +#include + +class IPakToCreate +{ +public: + explicit IPakToCreate(std::string name); + + void AddImage(std::string imageName); + void Build(ISearchPath& searchPath, const std::filesystem::path& outPath); + +private: + std::string m_name; + std::vector m_image_names; +}; + +class IPakCreator : public IZoneAssetCreationState +{ +public: + IPakCreator(); + + void Inject(ZoneAssetCreationInjection& inject) override; + + IPakToCreate* GetOrAddIPak(const std::string& ipakName); + void Finalize(ISearchPath& searchPath, const std::filesystem::path& outPath); + +private: + KeyValuePairsCreator* m_kvp_creator; + std::unordered_map m_ipak_lookup; + std::vector> m_ipaks; +}; diff --git a/src/ObjCompiling/Image/ImageIPakPostProcessor.cpp b/src/ObjCompiling/Image/ImageIPakPostProcessor.cpp new file mode 100644 index 00000000..6c712d70 --- /dev/null +++ b/src/ObjCompiling/Image/ImageIPakPostProcessor.cpp @@ -0,0 +1,75 @@ +#include "ImageIPakPostProcessor.h" + +#include "IPak/IPakCreator.h" + +#include + +AbstractImageIPakPostProcessor::AbstractImageIPakPostProcessor(const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + ZoneAssetCreationStateContainer& zoneStates, + const std::filesystem::path& outDir) + : m_zone_definition(zoneDefinition), + m_search_path(searchPath), + m_ipak_creator(zoneStates.GetZoneAssetCreationState()), + m_out_dir(outDir), + m_initialized(false), + m_obj_container_index(0u), + m_current_ipak(nullptr), + m_current_ipak_start_index(0u), + m_current_ipak_end_index(0u) +{ +} + +bool AbstractImageIPakPostProcessor::AppliesToZoneDefinition(const ZoneDefinitionContext& zoneDefinition) +{ + for (const auto& objContainer : zoneDefinition.m_zone_definition.m_obj_containers) + { + if (objContainer.m_type == ZoneDefinitionObjContainerType::IPAK) + return true; + } + + return false; +} + +void AbstractImageIPakPostProcessor::FindNextObjContainer(AssetCreationContext& context) +{ + const auto objContainerCount = m_zone_definition.m_zone_definition.m_obj_containers.size(); + while (m_obj_container_index < objContainerCount) + { + const auto& objContainer = m_zone_definition.m_zone_definition.m_obj_containers[m_obj_container_index++]; + + if (objContainer.m_type != ZoneDefinitionObjContainerType::IPAK) + continue; + + m_current_ipak = m_ipak_creator.GetOrAddIPak(objContainer.m_name); + m_current_ipak_start_index = objContainer.m_asset_start; + m_current_ipak_end_index = objContainer.m_asset_end; + return; + } + + m_current_ipak = nullptr; +} + +void AbstractImageIPakPostProcessor::PostProcessAsset(XAssetInfoGeneric& assetInfo, AssetCreationContext& context) +{ + if (assetInfo.m_name.empty() || assetInfo.m_name[0] == ',') + return; + + // Initialize on first image occurance + if (!m_initialized) + { + FindNextObjContainer(context); + m_initialized = true; + } + + while (m_current_ipak && m_zone_definition.m_asset_index_in_definition >= m_current_ipak_end_index) + FindNextObjContainer(context); + + if (m_current_ipak && m_zone_definition.m_asset_index_in_definition <= m_current_ipak_start_index) + m_current_ipak->AddImage(assetInfo.m_name); +} + +void AbstractImageIPakPostProcessor::FinalizeZone(AssetCreationContext& context) +{ + m_ipak_creator.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..36638f34 --- /dev/null +++ b/src/ObjCompiling/Image/ImageIPakPostProcessor.h @@ -0,0 +1,54 @@ +#pragma once + +#include "Asset/IAssetPostProcessor.h" +#include "Asset/ZoneDefinitionContext.h" +#include "Image/IPak/IPakCreator.h" + +#include + +class AbstractImageIPakPostProcessor : public IAssetPostProcessor +{ +public: + AbstractImageIPakPostProcessor(const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + ZoneAssetCreationStateContainer& zoneStates, + const std::filesystem::path& outDir); + + static bool AppliesToZoneDefinition(const ZoneDefinitionContext& zoneDefinition); + + void PostProcessAsset(XAssetInfoGeneric& assetInfo, AssetCreationContext& context) override; + void FinalizeZone(AssetCreationContext& context) override; + +private: + void FindNextObjContainer(AssetCreationContext& context); + + const ZoneDefinitionContext& m_zone_definition; + ISearchPath& m_search_path; + IPakCreator& m_ipak_creator; + const std::filesystem::path& m_out_dir; + + bool m_initialized; + unsigned m_obj_container_index; + IPakToCreate* m_current_ipak; + unsigned m_current_ipak_start_index; + unsigned m_current_ipak_end_index; +}; + +template class ImageIPakPostProcessor final : public AbstractImageIPakPostProcessor +{ +public: + static_assert(std::is_base_of_v); + + ImageIPakPostProcessor(const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + ZoneAssetCreationStateContainer& zoneStates, + const std::filesystem::path& outDir) + : AbstractImageIPakPostProcessor(zoneDefinition, searchPath, zoneStates, 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..c9b05254 --- /dev/null +++ b/src/ObjCompiling/Image/ImageIwdPostProcessor.cpp @@ -0,0 +1,76 @@ +#include "ImageIwdPostProcessor.h" + +#include "Iwd/IwdCreator.h" + +#include +#include + +AbstractImageIwdPostProcessor::AbstractImageIwdPostProcessor(const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + ZoneAssetCreationStateContainer& zoneStates, + const std::filesystem::path& outDir) + : m_zone_definition(zoneDefinition), + m_search_path(searchPath), + m_iwd_creator(zoneStates.GetZoneAssetCreationState()), + m_out_dir(outDir), + m_initialized(false), + m_obj_container_index(0u), + m_current_iwd(nullptr), + m_current_iwd_start_index(0u), + m_current_iwd_end_index(0u) +{ +} + +bool AbstractImageIwdPostProcessor::AppliesToZoneDefinition(const ZoneDefinitionContext& zoneDefinition) +{ + for (const auto& objContainer : zoneDefinition.m_zone_definition.m_obj_containers) + { + if (objContainer.m_type == ZoneDefinitionObjContainerType::IWD) + return true; + } + + return false; +} + +void AbstractImageIwdPostProcessor::FindNextObjContainer(AssetCreationContext& context) +{ + const auto objContainerCount = m_zone_definition.m_zone_definition.m_obj_containers.size(); + while (m_obj_container_index < objContainerCount) + { + const auto& objContainer = m_zone_definition.m_zone_definition.m_obj_containers[m_obj_container_index++]; + + if (objContainer.m_type != ZoneDefinitionObjContainerType::IWD) + continue; + + m_current_iwd = m_iwd_creator.GetOrAddIwd(objContainer.m_name); + m_current_iwd_start_index = objContainer.m_asset_start; + m_current_iwd_end_index = objContainer.m_asset_end; + return; + } + + m_current_iwd = nullptr; +} + +void AbstractImageIwdPostProcessor::PostProcessAsset(XAssetInfoGeneric& assetInfo, AssetCreationContext& context) +{ + if (assetInfo.m_name.empty() || assetInfo.m_name[0] == ',') + return; + + // Initialize on first image occurance + if (!m_initialized) + { + FindNextObjContainer(context); + m_initialized = true; + } + + while (m_current_iwd && m_zone_definition.m_asset_index_in_definition >= m_current_iwd_end_index) + FindNextObjContainer(context); + + if (m_current_iwd && m_zone_definition.m_asset_index_in_definition <= m_current_iwd_start_index) + m_current_iwd->AddFile(std::format("images/{}.iwi", assetInfo.m_name)); +} + +void AbstractImageIwdPostProcessor::FinalizeZone(AssetCreationContext& context) +{ + m_iwd_creator.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..62cfe50a --- /dev/null +++ b/src/ObjCompiling/Image/ImageIwdPostProcessor.h @@ -0,0 +1,54 @@ +#pragma once + +#include "Asset/IAssetPostProcessor.h" +#include "Asset/ZoneDefinitionContext.h" +#include "Iwd/IwdCreator.h" + +#include + +class AbstractImageIwdPostProcessor : public IAssetPostProcessor +{ +public: + AbstractImageIwdPostProcessor(const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + ZoneAssetCreationStateContainer& zoneStates, + const std::filesystem::path& outDir); + + static bool AppliesToZoneDefinition(const ZoneDefinitionContext& zoneDefinition); + + void PostProcessAsset(XAssetInfoGeneric& assetInfo, AssetCreationContext& context) override; + void FinalizeZone(AssetCreationContext& context) override; + +private: + void FindNextObjContainer(AssetCreationContext& context); + + const ZoneDefinitionContext& m_zone_definition; + ISearchPath& m_search_path; + IwdCreator& m_iwd_creator; + const std::filesystem::path& m_out_dir; + + bool m_initialized; + unsigned m_obj_container_index; + IwdToCreate* m_current_iwd; + unsigned m_current_iwd_start_index; + unsigned m_current_iwd_end_index; +}; + +template class ImageIwdPostProcessor final : public AbstractImageIwdPostProcessor +{ +public: + static_assert(std::is_base_of_v); + + ImageIwdPostProcessor(const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + ZoneAssetCreationStateContainer& zoneStates, + const std::filesystem::path& outDir) + : AbstractImageIwdPostProcessor(zoneDefinition, searchPath, zoneStates, 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..f995c32b --- /dev/null +++ b/src/ObjCompiling/Iwd/IwdCreator.cpp @@ -0,0 +1,103 @@ +#include "IwdCreator.h" + +#include "Utils/FileToZlibWrapper.h" + +#include +#include +#include +#include +#include + +IwdToCreate::IwdToCreate(std::string name) + : m_name(std::move(name)) +{ +} + +void IwdToCreate::AddFile(std::string filePath) +{ + m_file_paths.emplace_back(std::move(filePath)); +} + +void IwdToCreate::Build(ISearchPath& searchPath, const std::filesystem::path& outPath) +{ + auto filePath = outPath / std::format("{}.iwd", m_name); + std::ofstream file(filePath, std::ios::out | std::ios::binary); + if (!file.is_open()) + { + std::cerr << std::format("Failed to open file for iwd {}\n", m_name); + return; + } + + auto functions = FileToZlibWrapper::CreateFunctions32ForFile(&file); + + auto zipFile = zipOpen2(filePath.string().c_str(), APPEND_STATUS_CREATE, nullptr, &functions); + if (!zipFile) + { + std::cerr << std::format("Failed to open file as zip for iwd {}\n", m_name); + return; + } + + for (const auto& filePath : m_file_paths) + { + auto readFile = searchPath.Open(filePath); + if (!readFile.IsOpen()) + { + std::cerr << std::format("Failed to open file for iwd: {}\n", filePath); + continue; + } + + auto localNow = std::chrono::zoned_time{std::chrono::current_zone(), std::chrono::system_clock::now()}.get_local_time(); + auto nowDays = std::chrono::floor(localNow); + std::chrono::year_month_day ymd(std::chrono::floor(localNow)); + std::chrono::hh_mm_ss hms(std::chrono::floor(localNow - nowDays)); + + zip_fileinfo fileInfo{}; + fileInfo.dosDate = 0u; + fileInfo.tmz_date.tm_year = static_cast(ymd.year()); + fileInfo.tmz_date.tm_mon = static_cast(static_cast(ymd.month()) - static_cast(std::chrono::January)); + fileInfo.tmz_date.tm_mday = static_cast(static_cast(ymd.day())); + fileInfo.tmz_date.tm_hour = static_cast(hms.hours().count()); + fileInfo.tmz_date.tm_min = static_cast(hms.minutes().count()); + fileInfo.tmz_date.tm_sec = static_cast(hms.seconds().count()); + zipOpenNewFileInZip(zipFile, filePath.c_str(), &fileInfo, nullptr, 0, nullptr, 0, nullptr, Z_DEFLATED, Z_DEFAULT_COMPRESSION); + + char tempBuffer[0x1000]; + + do + { + readFile.m_stream->read(tempBuffer, sizeof(tempBuffer)); + const auto readCount = readFile.m_stream->gcount(); + if (readCount > 0) + zipWriteInFileInZip(zipFile, tempBuffer, static_cast(readCount)); + } while (!readFile.m_stream->eof()); + + zipCloseFileInZip(zipFile); + } + + zipClose(zipFile, nullptr); + + std::cout << std::format("Created iwd {} with {} entries\n", m_name, m_file_paths.size()); +} + +IwdToCreate* IwdCreator::GetOrAddIwd(const std::string& iwdName) +{ + const auto existingIwd = m_iwd_lookup.find(iwdName); + if (existingIwd != m_iwd_lookup.end()) + return existingIwd->second; + + auto newIwd = std::make_unique(iwdName); + auto* result = newIwd.get(); + m_iwds.emplace_back(std::move(newIwd)); + + return result; +} + +void IwdCreator::Finalize(ISearchPath& searchPath, const std::filesystem::path& outPath) +{ + std::cout << std::format("Writing {} iwd files to disk\n", m_iwds.size()); + for (const auto& iwdToCreate : m_iwds) + iwdToCreate->Build(searchPath, outPath); + + m_iwds.clear(); + m_iwd_lookup.clear(); +} diff --git a/src/ObjCompiling/Iwd/IwdCreator.h b/src/ObjCompiling/Iwd/IwdCreator.h new file mode 100644 index 00000000..43b31fe0 --- /dev/null +++ b/src/ObjCompiling/Iwd/IwdCreator.h @@ -0,0 +1,33 @@ +#pragma once + +#include "Asset/IZoneAssetCreationState.h" +#include "SearchPath/ISearchPath.h" + +#include +#include +#include +#include + +class IwdToCreate +{ +public: + explicit IwdToCreate(std::string name); + + void AddFile(std::string filePath); + void Build(ISearchPath& searchPath, const std::filesystem::path& outPath); + +private: + std::string m_name; + std::vector m_file_paths; +}; + +class IwdCreator : public IZoneAssetCreationState +{ +public: + IwdToCreate* GetOrAddIwd(const std::string& iwdName); + void Finalize(ISearchPath& searchPath, const std::filesystem::path& outPath); + +private: + std::unordered_map m_iwd_lookup; + std::vector> m_iwds; +}; diff --git a/src/ObjCompiling/KeyValuePairs/KeyValuePairsCreator.cpp b/src/ObjCompiling/KeyValuePairs/KeyValuePairsCreator.cpp new file mode 100644 index 00000000..eac08bae --- /dev/null +++ b/src/ObjCompiling/KeyValuePairs/KeyValuePairsCreator.cpp @@ -0,0 +1,57 @@ +#include "KeyValuePairsCreator.h" + +#include +#include + +CommonKeyValuePair::CommonKeyValuePair(std::string keyStr, std::string value) + : m_key_str(std::move(keyStr)), + m_value(std::move(value)) +{ +} + +CommonKeyValuePair::CommonKeyValuePair(const unsigned keyHash, std::string value) + : m_key_hash(keyHash), + m_value(std::move(value)) +{ +} + +void KeyValuePairsCreator::AddKeyValuePair(CommonKeyValuePair keyValuePair) +{ + m_key_value_pairs.emplace_back(std::move(keyValuePair)); +} + +void KeyValuePairsCreator::Finalize(const ZoneDefinition& zoneDefinition) +{ + for (const auto& metaData : zoneDefinition.m_properties.m_properties) + { + if (metaData.first.rfind("level.", 0) == 0) + { + std::string strValue = metaData.first.substr(std::char_traits::length("level.")); + if (strValue.empty()) + continue; + + if (strValue[0] == '@') + { + char* endPtr; + const unsigned keyHash = strtoul(&strValue[1], &endPtr, 16); + + if (endPtr != &strValue[strValue.size()]) + { + std::cerr << std::format("Could not parse metadata key \"{}\" as hash\n", metaData.first); + continue; + } + + m_key_value_pairs.emplace_back(keyHash, metaData.second); + } + else + { + m_key_value_pairs.emplace_back(std::move(strValue), metaData.second); + } + } + } +} + +std::vector KeyValuePairsCreator::GetFinalKeyValuePairs() +{ + return std::move(m_key_value_pairs); +} diff --git a/src/ObjCompiling/KeyValuePairs/KeyValuePairsCreator.h b/src/ObjCompiling/KeyValuePairs/KeyValuePairsCreator.h new file mode 100644 index 00000000..372400d1 --- /dev/null +++ b/src/ObjCompiling/KeyValuePairs/KeyValuePairsCreator.h @@ -0,0 +1,30 @@ +#pragma once + +#include "Asset/IZoneAssetCreationState.h" +#include "Zone/Definition/ZoneDefinition.h" + +#include +#include +#include + +class CommonKeyValuePair +{ +public: + CommonKeyValuePair(std::string keyStr, std::string value); + CommonKeyValuePair(unsigned keyHash, std::string value); + + std::optional m_key_str; + std::optional m_key_hash; + std::string m_value; +}; + +class KeyValuePairsCreator : public IZoneAssetCreationState +{ +public: + void AddKeyValuePair(CommonKeyValuePair keyValuePair); + void Finalize(const ZoneDefinition& zoneDefinition); + std::vector GetFinalKeyValuePairs(); + +private: + std::vector m_key_value_pairs; +}; diff --git a/src/ObjLoading/Asset/AssetCreationContext.cpp b/src/ObjLoading/Asset/AssetCreationContext.cpp new file mode 100644 index 00000000..b06886e8 --- /dev/null +++ b/src/ObjLoading/Asset/AssetCreationContext.cpp @@ -0,0 +1,139 @@ +#include "AssetCreationContext.h" + +#include +#include +#include + +IgnoredAssetLookup::IgnoredAssetLookup() = default; + +IgnoredAssetLookup::IgnoredAssetLookup(const AssetList& assetList) +{ + m_ignored_asset_lookup.reserve(assetList.m_entries.size()); + for (const auto& asset : assetList.m_entries) + { + m_ignored_asset_lookup.emplace(asset.m_name, asset.m_type); + } +} + +bool IgnoredAssetLookup::IsAssetIgnored(asset_type_t assetType, const std::string& name) const +{ + const auto entries = m_ignored_asset_lookup.equal_range(name); + + for (auto i = entries.first; i != entries.second; ++i) + { + if (i->second == assetType) + return true; + } + + return false; +} + +GenericAssetRegistration::GenericAssetRegistration(const asset_type_t type, std::string name, void* asset) + : m_type(type), + m_name(std::move(name)), + m_asset(asset) +{ +} + +void GenericAssetRegistration::AddDependency(XAssetInfoGeneric* dependency) +{ + m_dependencies.emplace(dependency); +} + +void GenericAssetRegistration::AddScriptString(scr_string_t scriptString) +{ + m_used_script_strings.emplace(scriptString); +} + +void GenericAssetRegistration::AddIndirectAssetReference(IndirectAssetReference indirectAssetReference) +{ + m_indirect_asset_references.emplace(std::move(indirectAssetReference)); +} + +std::unique_ptr GenericAssetRegistration::CreateXAssetInfo() +{ + assert(m_asset); + + std::vector dependencies(m_dependencies.begin(), m_dependencies.end()); + std::vector scriptStrings(m_used_script_strings.begin(), m_used_script_strings.end()); + std::vector indirectAssetReferences(m_indirect_asset_references.begin(), m_indirect_asset_references.end()); + + return std::make_unique( + m_type, std::move(m_name), m_asset, std::move(dependencies), std::move(scriptStrings), std::move(indirectAssetReferences)); +} + +AssetCreationContext::AssetCreationContext(Zone& zone, const AssetCreatorCollection* creators, const IgnoredAssetLookup* ignoredAssetLookup) + : ZoneAssetCreationStateContainer(zone), + m_zone(zone), + m_creators(creators), + m_ignored_asset_lookup(ignoredAssetLookup) +{ +} + +XAssetInfoGeneric* AssetCreationContext::AddAssetGeneric(GenericAssetRegistration registration) const +{ + auto xAssetInfo = registration.CreateXAssetInfo(); + xAssetInfo->m_zone = &m_zone; + + const auto assetType = xAssetInfo->m_type; + const auto* pAssetName = xAssetInfo->m_name.c_str(); + + auto* addedAsset = m_zone.m_pools->AddAsset(std::move(xAssetInfo)); + if (addedAsset == nullptr) + std::cerr << std::format("Failed to add asset of type \"{}\" to pool: \"{}\"\n", *m_zone.m_pools->GetAssetTypeName(assetType), pAssetName); + + return addedAsset; +} + +XAssetInfoGeneric* AssetCreationContext::LoadDefaultAssetDependency(const asset_type_t assetType, const std::string& assetName) +{ + const auto result = m_creators->CreateDefaultAsset(assetType, assetName, *this); + if (result.HasTakenAction() && !result.HasFailed()) + return result.GetAssetInfo(); + + std::cerr << std::format("Failed to create default asset of type {}\n", *m_zone.m_pools->GetAssetTypeName(assetType)); + + return nullptr; +} + +XAssetInfoGeneric* AssetCreationContext::LoadDependencyGeneric(const asset_type_t assetType, const std::string& assetName) +{ + auto* alreadyLoadedAsset = m_zone.m_pools->GetAssetOrAssetReference(assetType, assetName); + if (alreadyLoadedAsset) + return alreadyLoadedAsset; + + if (m_ignored_asset_lookup->IsAssetIgnored(assetType, assetName)) + return LoadDefaultAssetDependency(assetType, std::format(",{}", assetName)); + + const auto result = m_creators->CreateAsset(assetType, assetName, *this); + if (result.HasTakenAction()) + { + if (!result.HasFailed()) + return result.GetAssetInfo(); + + std::cerr << std::format("Could not load asset \"{}\" of type \"{}\"\n", assetName, *m_zone.m_pools->GetAssetTypeName(assetType)); + } + else + { + std::cerr << std::format("Missing asset \"{}\" of type \"{}\"\n", assetName, *m_zone.m_pools->GetAssetTypeName(assetType)); + } + + return nullptr; +} + +IndirectAssetReference AssetCreationContext::LoadIndirectAssetReferenceGeneric(asset_type_t assetType, const std::string& assetName) +{ + auto* alreadyLoadedAsset = m_zone.m_pools->GetAssetOrAssetReference(assetType, assetName); + if (alreadyLoadedAsset) + return IndirectAssetReference(assetType, assetName); + + if (m_ignored_asset_lookup->IsAssetIgnored(assetType, assetName)) + return IndirectAssetReference(assetType, assetName); + + const auto result = m_creators->CreateAsset(assetType, assetName, *this); + if (!result.HasTakenAction() && !result.HasFailed()) + { + std::cerr << std::format("Could not load indirectly referenced asset \"{}\" of type \"{}\"\n", assetName, *m_zone.m_pools->GetAssetTypeName(assetType)); + } + return IndirectAssetReference(assetType, assetName); +} diff --git a/src/ObjLoading/Asset/AssetCreationContext.h b/src/ObjLoading/Asset/AssetCreationContext.h new file mode 100644 index 00000000..0dca991c --- /dev/null +++ b/src/ObjLoading/Asset/AssetCreationContext.h @@ -0,0 +1,76 @@ +#pragma once + +#include "Asset/IZoneAssetCreationState.h" +#include "AssetRegistration.h" +#include "Game/IAsset.h" +#include "Pool/XAssetInfo.h" +#include "Zone/AssetList/AssetList.h" +#include "Zone/ZoneTypes.h" + +#include +#include +#include +#include +#include + +class AssetCreatorCollection; + +class IgnoredAssetLookup +{ +public: + IgnoredAssetLookup(); + explicit IgnoredAssetLookup(const AssetList& assetList); + + [[nodiscard]] bool IsAssetIgnored(asset_type_t assetType, const std::string& name) const; + + std::unordered_multimap m_ignored_asset_lookup; +}; + +class AssetCreationContext : public ZoneAssetCreationStateContainer +{ +public: + AssetCreationContext(Zone& zone, const AssetCreatorCollection* creators, const IgnoredAssetLookup* ignoredAssetLookup); + + template XAssetInfo* AddAsset(AssetRegistration registration) + { + static_assert(std::is_base_of_v); + + return static_cast*>(AddAssetGeneric(std::move(registration))); + } + + template XAssetInfo* AddAsset(std::string assetName, typename AssetType::Type* asset) + { + static_assert(std::is_base_of_v); + + return static_cast*>(AddAssetGeneric(AssetRegistration(std::move(assetName), asset))); + } + + XAssetInfoGeneric* AddAssetGeneric(GenericAssetRegistration registration) const; + + template XAssetInfo* LoadDependency(const std::string& assetName) + { + static_assert(std::is_base_of_v); + + return static_cast*>(LoadDependencyGeneric(AssetType::EnumEntry, assetName)); + } + + XAssetInfoGeneric* LoadDependencyGeneric(asset_type_t assetType, const std::string& assetName); + + template IndirectAssetReference LoadIndirectAssetReference(const std::string& assetName) + { + static_assert(std::is_base_of_v); + + return LoadIndirectAssetReferenceGeneric(AssetType::EnumEntry, assetName); + } + + IndirectAssetReference LoadIndirectAssetReferenceGeneric(asset_type_t assetType, const std::string& assetName); + +private: + [[nodiscard]] XAssetInfoGeneric* LoadDefaultAssetDependency(asset_type_t assetType, const std::string& assetName); + + Zone& m_zone; + const AssetCreatorCollection* m_creators; + const IgnoredAssetLookup* m_ignored_asset_lookup; +}; + +#include "AssetCreatorCollection.h" diff --git a/src/ObjLoading/Asset/AssetCreationResult.cpp b/src/ObjLoading/Asset/AssetCreationResult.cpp new file mode 100644 index 00000000..0a804b11 --- /dev/null +++ b/src/ObjLoading/Asset/AssetCreationResult.cpp @@ -0,0 +1,45 @@ +#include "AssetCreationResult.h" + +#include + +AssetCreationResult AssetCreationResult::Success(XAssetInfoGeneric* assetInfo) +{ + assert(assetInfo); + return AssetCreationResult(true, assetInfo); +} + +AssetCreationResult AssetCreationResult::Failure() +{ + return AssetCreationResult(true, nullptr); +} + +AssetCreationResult AssetCreationResult::NoAction() +{ + return AssetCreationResult(false, nullptr); +} + +bool AssetCreationResult::HasBeenSuccessful() const +{ + return m_taken_action && m_asset_info != nullptr; +} + +bool AssetCreationResult::HasTakenAction() const +{ + return m_taken_action; +} + +bool AssetCreationResult::HasFailed() const +{ + return m_taken_action && m_asset_info == nullptr; +} + +XAssetInfoGeneric* AssetCreationResult::GetAssetInfo() const +{ + return m_asset_info; +} + +AssetCreationResult::AssetCreationResult(const bool takenAction, XAssetInfoGeneric* assetInfo) + : m_taken_action(takenAction), + m_asset_info(assetInfo) +{ +} diff --git a/src/ObjLoading/Asset/AssetCreationResult.h b/src/ObjLoading/Asset/AssetCreationResult.h new file mode 100644 index 00000000..856e9ad0 --- /dev/null +++ b/src/ObjLoading/Asset/AssetCreationResult.h @@ -0,0 +1,22 @@ +#pragma once + +#include "Pool/XAssetInfo.h" + +class AssetCreationResult +{ +public: + static AssetCreationResult Success(XAssetInfoGeneric* assetInfo); + static AssetCreationResult Failure(); + static AssetCreationResult NoAction(); + + [[nodiscard]] bool HasBeenSuccessful() const; + [[nodiscard]] bool HasTakenAction() const; + [[nodiscard]] bool HasFailed() const; + [[nodiscard]] XAssetInfoGeneric* GetAssetInfo() const; + +private: + AssetCreationResult(bool takenAction, XAssetInfoGeneric* assetInfo); + + bool m_taken_action; + XAssetInfoGeneric* m_asset_info; +}; diff --git a/src/ObjLoading/Asset/AssetCreatorCollection.cpp b/src/ObjLoading/Asset/AssetCreatorCollection.cpp new file mode 100644 index 00000000..ee237293 --- /dev/null +++ b/src/ObjLoading/Asset/AssetCreatorCollection.cpp @@ -0,0 +1,88 @@ +#include "AssetCreatorCollection.h" + +#include + +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()); +} + +void AssetCreatorCollection::AddAssetCreator(std::unique_ptr creator) +{ + const auto maybeHandlingAssetType = creator->GetHandlingAssetType(); + assert(!maybeHandlingAssetType || static_cast(*maybeHandlingAssetType) < m_asset_creators_by_type.size()); + if (maybeHandlingAssetType && static_cast(*maybeHandlingAssetType) < m_asset_creators_by_type.size()) + m_asset_creators_by_type[static_cast(*maybeHandlingAssetType)].emplace_back(creator.get()); + + 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(); + assert(static_cast(handlingAssetType) < m_default_asset_creators_by_type.size()); + assert(!m_default_asset_creators_by_type[handlingAssetType]); + + if (static_cast(handlingAssetType) < m_default_asset_creators_by_type.size()) + m_default_asset_creators_by_type[handlingAssetType] = std::move(defaultAssetCreator); +} + +AssetCreationResult AssetCreatorCollection::CreateAsset(const asset_type_t assetType, const std::string& assetName, AssetCreationContext& context) const +{ + assert(assetType >= 0 && static_cast(assetType) < m_asset_creators_by_type.size()); + + if (assetType >= 0 && static_cast(assetType) < m_asset_creators_by_type.size()) + { + for (const auto& creator : m_asset_creators_by_type[assetType]) + { + 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; + } + } + } + + return AssetCreationResult::NoAction(); +} + +AssetCreationResult AssetCreatorCollection::CreateDefaultAsset(const asset_type_t assetType, const std::string& assetName, AssetCreationContext& context) const +{ + assert(assetType >= 0 && static_cast(assetType) < m_default_asset_creators_by_type.size()); + + if (assetType >= 0 && static_cast(assetType) < m_default_asset_creators_by_type.size() && m_default_asset_creators_by_type[assetType]) + { + return m_default_asset_creators_by_type[assetType]->CreateDefaultAsset(assetName, context); + } + + return AssetCreationResult::NoAction(); +} + +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 new file mode 100644 index 00000000..9b720b11 --- /dev/null +++ b/src/ObjLoading/Asset/AssetCreatorCollection.h @@ -0,0 +1,38 @@ +#pragma once + +#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; + +class AssetCreatorCollection +{ +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; + AssetCreationResult CreateDefaultAsset(asset_type_t assetType, const std::string& assetName, AssetCreationContext& context) const; + void FinalizeZone(AssetCreationContext& context) const; + +private: + std::vector> m_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/AssetRegistration.h b/src/ObjLoading/Asset/AssetRegistration.h new file mode 100644 index 00000000..a0b549ec --- /dev/null +++ b/src/ObjLoading/Asset/AssetRegistration.h @@ -0,0 +1,61 @@ +#pragma once + +#include "Game/IAsset.h" +#include "Pool/XAssetInfo.h" +#include "Zone/ZoneTypes.h" + +#include +#include +#include + +class GenericAssetRegistration +{ +protected: + GenericAssetRegistration(asset_type_t type, std::string name, void* asset); + +public: + GenericAssetRegistration(const GenericAssetRegistration& other) = delete; + GenericAssetRegistration(GenericAssetRegistration&& other) = default; + GenericAssetRegistration& operator=(const GenericAssetRegistration& other) = delete; + GenericAssetRegistration& operator=(GenericAssetRegistration&& other) noexcept = default; + + void AddDependency(XAssetInfoGeneric* dependency); + void AddScriptString(scr_string_t scriptString); + void AddIndirectAssetReference(IndirectAssetReference indirectAssetReference); + + std::unique_ptr CreateXAssetInfo(); + +protected: + asset_type_t m_type; + std::string m_name; + void* m_asset; + std::unordered_set m_dependencies; + std::unordered_set m_used_script_strings; + std::unordered_set m_indirect_asset_references; +}; + +template class AssetRegistration : public GenericAssetRegistration +{ + static_assert(std::is_base_of_v); + +public: + AssetRegistration(std::string assetName) + : GenericAssetRegistration(AssetType::EnumEntry, std::move(assetName), nullptr) + { + } + + AssetRegistration(std::string assetName, typename AssetType::Type* asset) + : GenericAssetRegistration(AssetType::EnumEntry, std::move(assetName), asset) + { + } + + AssetRegistration(const AssetRegistration& other) = delete; + AssetRegistration(AssetRegistration&& other) = default; + AssetRegistration& operator=(const AssetRegistration& other) = delete; + AssetRegistration& operator=(AssetRegistration&& other) noexcept = default; + + void SetAsset(typename AssetType::Type* asset) + { + m_asset = asset; + } +}; diff --git a/src/ObjLoading/Asset/GlobalAssetPoolsLoader.h b/src/ObjLoading/Asset/GlobalAssetPoolsLoader.h new file mode 100644 index 00000000..b9f3bd23 --- /dev/null +++ b/src/ObjLoading/Asset/GlobalAssetPoolsLoader.h @@ -0,0 +1,46 @@ +#pragma once +#include "Asset/IAssetCreator.h" +#include "Pool/GlobalAssetPool.h" + +template class GlobalAssetPoolsLoader : public AssetCreator +{ +public: + static_assert(std::is_base_of_v); + + GlobalAssetPoolsLoader(Zone& zone) + : m_zone(zone) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + auto* existingAsset = GlobalAssetPool::GetAssetByName(assetName); + + if (!existingAsset) + return AssetCreationResult::NoAction(); + + AssetRegistration registration(assetName, existingAsset->Asset()); + + for (const auto* dependency : existingAsset->m_dependencies) + { + auto* newDependency = context.LoadDependencyGeneric(dependency->m_type, dependency->m_name); + if (newDependency) + registration.AddDependency(newDependency); + else + return AssetCreationResult::Failure(); + } + + for (const auto& indirectAssetReference : existingAsset->m_indirect_asset_references) + registration.AddIndirectAssetReference(context.LoadIndirectAssetReferenceGeneric(indirectAssetReference.m_type, indirectAssetReference.m_name)); + + // Make sure any used script string is available in the created zone + // The replacement of the scr_string_t values will be done upon writing + for (const auto scrString : existingAsset->m_used_script_strings) + m_zone.m_script_strings.AddOrGetScriptString(existingAsset->m_zone->m_script_strings.CValue(scrString)); + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); + } + +private: + Zone& m_zone; +}; diff --git a/src/ObjLoading/Asset/IAssetCreator.h b/src/ObjLoading/Asset/IAssetCreator.h new file mode 100644 index 00000000..8d0bc25d --- /dev/null +++ b/src/ObjLoading/Asset/IAssetCreator.h @@ -0,0 +1,40 @@ +#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 IAssetCreator +{ +public: + IAssetCreator() = default; + virtual ~IAssetCreator() = default; + IAssetCreator(const IAssetCreator& other) = default; + IAssetCreator(IAssetCreator&& other) noexcept = default; + IAssetCreator& operator=(const IAssetCreator& other) = default; + IAssetCreator& operator=(IAssetCreator&& other) noexcept = default; + + [[nodiscard]] virtual std::optional GetHandlingAssetType() const = 0; + virtual AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) = 0; + virtual void FinalizeZone(AssetCreationContext& context){}; +}; + +template class AssetCreator : public IAssetCreator +{ +public: + static_assert(std::is_base_of_v); + + [[nodiscard]] std::optional GetHandlingAssetType() const override + { + return AssetType::EnumEntry; + }; +}; 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){}; +}; diff --git a/src/ObjLoading/Asset/IDefaultAssetCreator.h b/src/ObjLoading/Asset/IDefaultAssetCreator.h new file mode 100644 index 00000000..bcd0963f --- /dev/null +++ b/src/ObjLoading/Asset/IDefaultAssetCreator.h @@ -0,0 +1,52 @@ +#pragma once + +#include "AssetCreationContext.h" +#include "AssetCreationResult.h" +#include "Game/IAsset.h" +#include "IAssetCreator.h" +#include "Utils/MemoryManager.h" +#include "Zone/ZoneTypes.h" + +#include +#include + +class IDefaultAssetCreator +{ +public: + IDefaultAssetCreator() = default; + virtual ~IDefaultAssetCreator() = default; + IDefaultAssetCreator(const IDefaultAssetCreator& other) = default; + IDefaultAssetCreator(IDefaultAssetCreator&& other) noexcept = default; + IDefaultAssetCreator& operator=(const IDefaultAssetCreator& other) = default; + IDefaultAssetCreator& operator=(IDefaultAssetCreator&& other) noexcept = default; + + [[nodiscard]] virtual asset_type_t GetHandlingAssetType() const = 0; + virtual AssetCreationResult CreateDefaultAsset(const std::string& assetName, AssetCreationContext& context) const = 0; +}; + +template class DefaultAssetCreator : public IDefaultAssetCreator +{ +public: + static_assert(std::is_base_of_v); + + DefaultAssetCreator(MemoryManager& memory) + : m_memory(memory) + { + } + + [[nodiscard]] asset_type_t GetHandlingAssetType() const override + { + return AssetType::EnumEntry; + } + + AssetCreationResult CreateDefaultAsset(const std::string& assetName, AssetCreationContext& context) const override + { + auto* asset = m_memory.Alloc(); + AssetNameAccessor{}(*asset) = m_memory.Dup(assetName.c_str()); + + return AssetCreationResult::Success(context.AddAsset(assetName, asset)); + } + +private: + MemoryManager& m_memory; +}; diff --git a/src/ObjLoading/Asset/IZoneAssetCreationState.h b/src/ObjLoading/Asset/IZoneAssetCreationState.h new file mode 100644 index 00000000..c63b1861 --- /dev/null +++ b/src/ObjLoading/Asset/IZoneAssetCreationState.h @@ -0,0 +1,70 @@ +#pragma once + +#include "Zone/Zone.h" + +#include +#include +#include + +class ZoneAssetCreationStateContainer; + +class ZoneAssetCreationInjection +{ +public: + ZoneAssetCreationInjection(ZoneAssetCreationStateContainer& zoneStates, Zone& zone) + : m_zone_states(zoneStates), + m_zone(zone) + { + } + + ZoneAssetCreationStateContainer& m_zone_states; + Zone& m_zone; +}; + +class IZoneAssetCreationState +{ +protected: + IZoneAssetCreationState() = default; + +public: + virtual ~IZoneAssetCreationState() = default; + IZoneAssetCreationState(const IZoneAssetCreationState& other) = default; + IZoneAssetCreationState(IZoneAssetCreationState&& other) noexcept = default; + IZoneAssetCreationState& operator=(const IZoneAssetCreationState& other) = default; + IZoneAssetCreationState& operator=(IZoneAssetCreationState&& other) noexcept = default; + + virtual void Inject(ZoneAssetCreationInjection& inject) + { + // Do nothing by default + } +}; + +class ZoneAssetCreationStateContainer +{ +public: + ZoneAssetCreationStateContainer(Zone& zone) + : m_injection(*this, zone) + { + } + + template T& GetZoneAssetCreationState() + { + static_assert(std::is_base_of_v, "T must inherit IZoneAssetCreationState"); + // T must also have a public default constructor + + const auto foundEntry = m_zone_asset_creation_states.find(typeid(T)); + if (foundEntry != m_zone_asset_creation_states.end()) + return *dynamic_cast(foundEntry->second.get()); + + auto newState = std::make_unique(); + newState->Inject(m_injection); + auto* newStatePtr = newState.get(); + m_zone_asset_creation_states.emplace(std::make_pair>(typeid(T), std::move(newState))); + + return *newStatePtr; + } + +private: + ZoneAssetCreationInjection m_injection; + std::unordered_map> m_zone_asset_creation_states; +}; diff --git a/src/ObjLoading/Asset/ZoneDefinitionContext.h b/src/ObjLoading/Asset/ZoneDefinitionContext.h new file mode 100644 index 00000000..780b959c --- /dev/null +++ b/src/ObjLoading/Asset/ZoneDefinitionContext.h @@ -0,0 +1,16 @@ +#pragma once + +#include "Zone/Definition/ZoneDefinition.h" + +class ZoneDefinitionContext +{ +public: + ZoneDefinitionContext(const ZoneDefinition& zoneDefinition) + : m_zone_definition(zoneDefinition), + m_asset_index_in_definition(0u) + { + } + + const ZoneDefinition& m_zone_definition; + unsigned m_asset_index_in_definition; +}; diff --git a/src/ObjLoading/AssetLoading/AssetLoadingContext.h b/src/ObjLoading/AssetLoading/AssetLoadingContext.h deleted file mode 100644 index 18a42596..00000000 --- a/src/ObjLoading/AssetLoading/AssetLoadingContext.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include "IGdtQueryable.h" -#include "IZoneAssetLoaderState.h" -#include "Obj/Gdt/Gdt.h" -#include "SearchPath/ISearchPath.h" -#include "Zone/Zone.h" - -#include -#include -#include - -class AssetLoadingContext final : public IGdtQueryable -{ -public: - AssetLoadingContext(Zone& zone, ISearchPath& rawSearchPath, std::vector gdtFiles); - GdtEntry* GetGdtEntryByGdfAndName(const std::string& gdfName, const std::string& entryName) override; - - template T* GetZoneAssetLoaderState() - { - static_assert(std::is_base_of_v, "T must inherit IZoneAssetLoaderState"); - // T must also have a public default constructor - - const auto foundEntry = m_zone_asset_loader_states.find(typeid(T)); - if (foundEntry != m_zone_asset_loader_states.end()) - return dynamic_cast(foundEntry->second.get()); - - auto newState = std::make_unique(); - newState->SetZone(&m_zone); - auto* newStatePtr = newState.get(); - m_zone_asset_loader_states.emplace(std::make_pair>(typeid(T), std::move(newState))); - return newStatePtr; - } - -private: - void BuildGdtEntryCache(); - -public: - Zone& m_zone; - ISearchPath& m_raw_search_path; - const std::vector m_gdt_files; - std::unordered_map m_ignored_asset_map; - - std::unordered_map> m_entries_by_gdf_and_by_name; - std::unordered_map> m_zone_asset_loader_states; -}; diff --git a/src/ObjLoading/AssetLoading/AssetLoadingManager.cpp b/src/ObjLoading/AssetLoading/AssetLoadingManager.cpp deleted file mode 100644 index b3d0b492..00000000 --- a/src/ObjLoading/AssetLoading/AssetLoadingManager.cpp +++ /dev/null @@ -1,176 +0,0 @@ -#include "AssetLoadingManager.h" - -#include "Utils/StringUtils.h" - -#include -#include -#include - -AssetLoadingManager::AssetLoadingManager(const std::unordered_map>& assetLoadersByType, - AssetLoadingContext& context) - : m_asset_loaders_by_type(assetLoadersByType), - m_context(context), - m_last_dependency_loaded(nullptr) -{ -} - -bool AssetLoadingManager::LoadAssetFromLoader(const asset_type_t assetType, const std::string& assetName) -{ - return LoadDependency(assetType, assetName) != nullptr; -} - -AssetLoadingContext* AssetLoadingManager::GetAssetLoadingContext() const -{ - return &m_context; -} - -XAssetInfoGeneric* AssetLoadingManager::AddAssetInternal(std::unique_ptr xAssetInfo) -{ - const auto assetType = xAssetInfo->m_type; - const auto* pAssetName = xAssetInfo->m_name.c_str(); - - m_last_dependency_loaded = m_context.m_zone.m_pools->AddAsset(std::move(xAssetInfo)); - if (m_last_dependency_loaded == nullptr) - std::cerr << std::format("Failed to add asset of type \"{}\" to pool: \"{}\"\n", *m_context.m_zone.m_pools->GetAssetTypeName(assetType), pAssetName); - - return m_last_dependency_loaded; -} - -XAssetInfoGeneric* AssetLoadingManager::AddAsset(std::unique_ptr xAssetInfo) -{ - xAssetInfo->m_zone = &m_context.m_zone; - return AddAssetInternal(std::move(xAssetInfo)); -} - -XAssetInfoGeneric* AssetLoadingManager::LoadIgnoredDependency(const asset_type_t assetType, const std::string& assetName, IAssetLoader* loader) -{ - auto* alreadyLoadedAsset = m_context.m_zone.m_pools->GetAssetOrAssetReference(assetType, assetName); - if (alreadyLoadedAsset) - return alreadyLoadedAsset; - - auto* linkAsset = loader->CreateEmptyAsset(assetName, m_context.m_zone.GetMemory()); - if (linkAsset) - { - AddAsset(std::make_unique(assetType, assetName, linkAsset)); - auto* lastDependency = m_last_dependency_loaded; - m_last_dependency_loaded = nullptr; - return lastDependency; - } - - auto* existingAsset = loader->LoadFromGlobalAssetPools(assetName); - if (existingAsset) - { - AddAssetInternal(std::make_unique(*existingAsset)); - auto* lastDependency = m_last_dependency_loaded; - m_last_dependency_loaded = nullptr; - return lastDependency; - } - - std::cerr << std::format("Failed to create empty asset \"{}\" for type \"{}\"\n", assetName, *m_context.m_zone.m_pools->GetAssetTypeName(assetType)); - return nullptr; -} - -XAssetInfoGeneric* AssetLoadingManager::LoadAssetDependency(const asset_type_t assetType, const std::string& assetName, const IAssetLoader* loader) -{ - if (loader->CanLoadFromGdt() && !m_context.m_gdt_files.empty() - && loader->LoadFromGdt(assetName, &m_context, m_context.m_zone.GetMemory(), this, &m_context.m_zone)) - { - auto* lastDependency = m_last_dependency_loaded; - m_last_dependency_loaded = nullptr; - return lastDependency; - } - - if (loader->CanLoadFromRaw() && loader->LoadFromRaw(assetName, &m_context.m_raw_search_path, m_context.m_zone.GetMemory(), this, &m_context.m_zone)) - { - auto* lastDependency = m_last_dependency_loaded; - m_last_dependency_loaded = nullptr; - return lastDependency; - } - - auto* existingAsset = loader->LoadFromGlobalAssetPools(assetName); - if (!existingAsset && !assetName.empty() && assetName[0] != ',') - existingAsset = loader->LoadFromGlobalAssetPools(',' + assetName); - - if (existingAsset) - { - std::vector dependencies; - std::vector indirectAssetReferences; - for (const auto* dependency : existingAsset->m_dependencies) - { - auto* newDependency = LoadDependency(dependency->m_type, dependency->m_name); - if (newDependency) - dependencies.push_back(newDependency); - else - return nullptr; - } - - indirectAssetReferences.reserve(existingAsset->m_indirect_asset_references.size()); - for (const auto& indirectAssetReference : existingAsset->m_indirect_asset_references) - indirectAssetReferences.emplace_back(LoadIndirectAssetReference(indirectAssetReference.m_type, indirectAssetReference.m_name)); - - // Make sure any used script string is available in the created zone - // The replacement of the scr_string_t values will be done upon writing - for (const auto scrString : existingAsset->m_used_script_strings) - m_context.m_zone.m_script_strings.AddOrGetScriptString(existingAsset->m_zone->m_script_strings.CValue(scrString)); - - AddAssetInternal(std::make_unique(existingAsset->m_type, - existingAsset->m_name, - existingAsset->m_ptr, - std::move(dependencies), - existingAsset->m_used_script_strings, - std::move(indirectAssetReferences), - existingAsset->m_zone)); - - auto* lastDependency = m_last_dependency_loaded; - m_last_dependency_loaded = nullptr; - return lastDependency; - } - - std::cerr << std::format("Failed to load asset of type \"{}\": \"{}\"\n", *m_context.m_zone.m_pools->GetAssetTypeName(assetType), assetName); - return nullptr; -} - -XAssetInfoGeneric* AssetLoadingManager::LoadDependency(const asset_type_t assetType, const std::string& assetName) -{ - auto* alreadyLoadedAsset = m_context.m_zone.m_pools->GetAssetOrAssetReference(assetType, assetName); - if (alreadyLoadedAsset) - return alreadyLoadedAsset; - - const auto loader = m_asset_loaders_by_type.find(assetType); - if (loader != m_asset_loaders_by_type.end()) - { - const auto ignoreEntry = m_context.m_ignored_asset_map.find(assetName); - if (ignoreEntry != m_context.m_ignored_asset_map.end() && ignoreEntry->second == assetType) - { - const auto linkAssetName = std::format(",{}", assetName); - - return LoadIgnoredDependency(assetType, linkAssetName, loader->second.get()); - } - - return LoadAssetDependency(assetType, assetName, loader->second.get()); - } - - std::cerr << std::format("Failed to find loader for asset type \"{}\"\n", *m_context.m_zone.m_pools->GetAssetTypeName(assetType)); - return nullptr; -} - -IndirectAssetReference AssetLoadingManager::LoadIndirectAssetReference(const asset_type_t assetType, const std::string& assetName) -{ - const auto* alreadyLoadedAsset = m_context.m_zone.m_pools->GetAssetOrAssetReference(assetType, assetName); - if (alreadyLoadedAsset) - return IndirectAssetReference(assetType, assetName); - - const auto ignoreEntry = m_context.m_ignored_asset_map.find(assetName); - if (ignoreEntry != m_context.m_ignored_asset_map.end() && ignoreEntry->second == assetType) - return IndirectAssetReference(assetType, assetName); - - const auto loader = m_asset_loaders_by_type.find(assetType); - if (loader != m_asset_loaders_by_type.end()) - { - LoadAssetDependency(assetType, assetName, loader->second.get()); - return IndirectAssetReference(assetType, assetName); - } - - std::cerr << std::format("Failed to find loader for asset type \"{}\"\n", *m_context.m_zone.m_pools->GetAssetTypeName(assetType)); - return IndirectAssetReference(assetType, assetName); -} diff --git a/src/ObjLoading/AssetLoading/AssetLoadingManager.h b/src/ObjLoading/AssetLoading/AssetLoadingManager.h deleted file mode 100644 index 47e1dcec..00000000 --- a/src/ObjLoading/AssetLoading/AssetLoadingManager.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "AssetLoadingContext.h" -#include "IAssetLoader.h" -#include "IAssetLoadingManager.h" - -#include - -class AssetLoadingManager final : public IAssetLoadingManager -{ -public: - AssetLoadingManager(const std::unordered_map>& assetLoadersByType, AssetLoadingContext& context); - - bool LoadAssetFromLoader(asset_type_t assetType, const std::string& assetName); - - [[nodiscard]] AssetLoadingContext* GetAssetLoadingContext() const override; - - XAssetInfoGeneric* AddAsset(std::unique_ptr xAssetInfo) override; - XAssetInfoGeneric* LoadDependency(asset_type_t assetType, const std::string& assetName) override; - IndirectAssetReference LoadIndirectAssetReference(asset_type_t assetType, const std::string& assetName) override; - -private: - XAssetInfoGeneric* LoadIgnoredDependency(asset_type_t assetType, const std::string& assetName, IAssetLoader* loader); - XAssetInfoGeneric* LoadAssetDependency(asset_type_t assetType, const std::string& assetName, const IAssetLoader* loader); - - XAssetInfoGeneric* AddAssetInternal(std::unique_ptr xAssetInfo); - - const std::unordered_map>& m_asset_loaders_by_type; - AssetLoadingContext& m_context; - XAssetInfoGeneric* m_last_dependency_loaded; -}; diff --git a/src/ObjLoading/AssetLoading/BasicAssetLoader.h b/src/ObjLoading/AssetLoading/BasicAssetLoader.h deleted file mode 100644 index d224fe26..00000000 --- a/src/ObjLoading/AssetLoading/BasicAssetLoader.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once -#include "IAssetLoader.h" -#include "Pool/GlobalAssetPool.h" - -template class BasicAssetLoaderWithoutType : public IAssetLoader -{ -public: - _NODISCARD XAssetInfoGeneric* LoadFromGlobalAssetPools(const std::string& assetName) const override - { - return GlobalAssetPool::GetAssetByName(assetName); - } -}; - -template class BasicAssetLoader : public BasicAssetLoaderWithoutType -{ -public: - static_assert(std::is_base_of_v); - - _NODISCARD asset_type_t GetHandlingAssetType() const override - { - return AssetType::EnumEntry; - } -}; diff --git a/src/ObjLoading/AssetLoading/IAssetLoader.h b/src/ObjLoading/AssetLoading/IAssetLoader.h deleted file mode 100644 index 625c72b5..00000000 --- a/src/ObjLoading/AssetLoading/IAssetLoader.h +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once -#include "IAssetLoadingManager.h" -#include "IGdtQueryable.h" -#include "SearchPath/ISearchPath.h" -#include "Utils/ClassUtils.h" -#include "Zone/ZoneTypes.h" - -#include - -class IAssetLoader -{ -public: - IAssetLoader() = default; - virtual ~IAssetLoader() = default; - IAssetLoader(const IAssetLoader& other) = default; - IAssetLoader(IAssetLoader&& other) noexcept = default; - IAssetLoader& operator=(const IAssetLoader& other) = default; - IAssetLoader& operator=(IAssetLoader&& other) noexcept = default; - - _NODISCARD virtual asset_type_t GetHandlingAssetType() const = 0; - _NODISCARD virtual XAssetInfoGeneric* LoadFromGlobalAssetPools(const std::string& assetName) const = 0; - - _NODISCARD virtual void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) - { - // TODO: Make this pure virtual - return nullptr; - } - - _NODISCARD virtual bool CanLoadFromGdt() const - { - return false; - } - - _NODISCARD virtual bool CanLoadFromRaw() const - { - return false; - } - - virtual bool LoadFromGdt(const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const - { - return false; - } - - virtual bool LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const - { - return false; - } - - virtual void FinalizeAssetsForZone(AssetLoadingContext& context) const - { - // Do nothing by default - } -}; diff --git a/src/ObjLoading/AssetLoading/IAssetLoadingManager.h b/src/ObjLoading/AssetLoading/IAssetLoadingManager.h deleted file mode 100644 index a8c2f64f..00000000 --- a/src/ObjLoading/AssetLoading/IAssetLoadingManager.h +++ /dev/null @@ -1,89 +0,0 @@ -#pragma once -#include "AssetLoadingContext.h" -#include "Game/IAsset.h" -#include "Pool/XAssetInfo.h" -#include "Utils/ClassUtils.h" -#include "Zone/ZoneTypes.h" - -#include - -class IAssetLoadingManager -{ -public: - IAssetLoadingManager() = default; - virtual ~IAssetLoadingManager() = default; - IAssetLoadingManager(const IAssetLoadingManager& other) = default; - IAssetLoadingManager(IAssetLoadingManager&& other) noexcept = default; - IAssetLoadingManager& operator=(const IAssetLoadingManager& other) = default; - IAssetLoadingManager& operator=(IAssetLoadingManager&& other) noexcept = default; - - _NODISCARD virtual AssetLoadingContext* GetAssetLoadingContext() const = 0; - - template XAssetInfo* AddAsset(const std::string& assetName, typename AssetType::Type* asset) - { - static_assert(std::is_base_of_v); - - return static_cast*>(AddAsset(std::make_unique( - AssetType::EnumEntry, assetName, asset, std::vector(), std::vector(), std::vector()))); - } - - template - XAssetInfo* AddAsset(const std::string& assetName, typename AssetType::Type* asset, std::vector dependencies) - { - static_assert(std::is_base_of_v); - - return static_cast*>(AddAsset(std::make_unique( - AssetType::EnumEntry, assetName, asset, std::move(dependencies), std::vector(), std::vector()))); - } - - template - XAssetInfo* AddAsset(const std::string& assetName, - typename AssetType::Type* asset, - std::vector dependencies, - std::vector usedScriptStrings) - { - static_assert(std::is_base_of_v); - - return static_cast*>(AddAsset(std::make_unique( - AssetType::EnumEntry, assetName, asset, std::move(dependencies), std::move(usedScriptStrings), std::vector()))); - } - - template - XAssetInfo* AddAsset(const std::string& assetName, - typename AssetType::Type* asset, - std::vector dependencies, - std::vector usedScriptStrings, - std::vector indirectAssetReferences) - { - static_assert(std::is_base_of_v); - - return static_cast*>(AddAsset(std::make_unique( - AssetType::EnumEntry, assetName, asset, std::move(dependencies), std::move(usedScriptStrings), std::move(indirectAssetReferences)))); - } - - template XAssetInfo* AddAsset(std::unique_ptr> xAssetInfo) - { - static_assert(std::is_base_of_v); - - return static_cast*>(AddAsset(std::unique_ptr(xAssetInfo.release()))); - } - - template XAssetInfo* LoadDependency(const std::string& assetName) - { - static_assert(std::is_base_of_v); - - return static_cast*>(LoadDependency(AssetType::EnumEntry, assetName)); - } - - template IndirectAssetReference LoadIndirectAssetReference(const std::string& assetName) - { - static_assert(std::is_base_of_v); - - return LoadIndirectAssetReference(AssetType::EnumEntry, assetName); - } - -protected: - virtual XAssetInfoGeneric* AddAsset(std::unique_ptr xAssetInfo) = 0; - virtual XAssetInfoGeneric* LoadDependency(asset_type_t assetType, const std::string& assetName) = 0; - virtual IndirectAssetReference LoadIndirectAssetReference(asset_type_t assetType, const std::string& assetName) = 0; -}; diff --git a/src/ObjLoading/AssetLoading/IZoneAssetLoaderState.h b/src/ObjLoading/AssetLoading/IZoneAssetLoaderState.h deleted file mode 100644 index a17ccd51..00000000 --- a/src/ObjLoading/AssetLoading/IZoneAssetLoaderState.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once -#include "Zone/Zone.h" - -class IZoneAssetLoaderState -{ -protected: - IZoneAssetLoaderState() = default; - -public: - virtual ~IZoneAssetLoaderState() = default; - IZoneAssetLoaderState(const IZoneAssetLoaderState& other) = default; - IZoneAssetLoaderState(IZoneAssetLoaderState&& other) noexcept = default; - IZoneAssetLoaderState& operator=(const IZoneAssetLoaderState& other) = default; - IZoneAssetLoaderState& operator=(IZoneAssetLoaderState&& other) noexcept = default; - - virtual void SetZone(Zone* zone) - { - // Do nothing by default - } -}; diff --git a/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderGfxImage.cpp b/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderGfxImage.cpp deleted file mode 100644 index 7daaf720..00000000 --- a/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderGfxImage.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#include "AssetLoaderGfxImage.h" - -#include "Game/IW3/IW3.h" -#include "Image/DdsLoader.h" -#include "Image/IwiTypes.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include -#include -#include - -using namespace IW3; - -void* AssetLoaderGfxImage::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* image = memory->Create(); - memset(image, 0, sizeof(GfxImage)); - image->name = memory->Dup(assetName.c_str()); - return image; -} - -bool AssetLoaderGfxImage::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderGfxImage::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - // Do not load any GfxImages from raw for now that are not loaded - // TODO: Load iwis and add streaming info to asset - if (assetName.empty() || assetName[0] != '*') - return false; - - std::string safeAssetName = assetName; - std::ranges::replace(safeAssetName, '*', '_'); - - const auto file = searchPath->Open(std::format("images/{}.dds", safeAssetName)); - if (!file.IsOpen()) - return false; - - const auto texture = dds::LoadDds(*file.m_stream); - if (!texture) - { - std::cerr << std::format("Failed to load dds file for image asset \"{}\"\n", assetName); - return false; - } - - auto* image = memory->Create(); - image->name = memory->Dup(assetName.c_str()); - image->picmip.platform[0] = 0; - image->picmip.platform[1] = 0; - image->noPicmip = !texture->HasMipMaps(); - image->semantic = TS_FUNCTION; - image->track = 0; - image->cardMemory.platform[0] = 0; - image->cardMemory.platform[1] = 0; - image->width = static_cast(texture->GetWidth()); - image->height = static_cast(texture->GetHeight()); - image->depth = static_cast(texture->GetDepth()); - image->category = IMG_CATEGORY_AUTO_GENERATED; - image->delayLoadPixels = false; - - switch (texture->GetTextureType()) - { - case TextureType::T_2D: - image->mapType = MAPTYPE_2D; - break; - - case TextureType::T_3D: - image->mapType = MAPTYPE_3D; - break; - - case TextureType::T_CUBE: - image->mapType = MAPTYPE_CUBE; - break; - - default: - image->mapType = MAPTYPE_NONE; - break; - } - - const auto mipCount = texture->HasMipMaps() ? texture->GetMipMapCount() : 1; - const auto faceCount = texture->GetFaceCount(); - - size_t dataSize = 0; - for (auto mipLevel = 0; mipLevel < mipCount; mipLevel++) - dataSize += texture->GetSizeOfMipLevel(mipLevel) * faceCount; - - auto* loadDef = static_cast(zone->GetMemory()->AllocRaw(offsetof(GfxImageLoadDef, data) + dataSize)); - image->texture.loadDef = loadDef; - loadDef->levelCount = static_cast(mipCount); - loadDef->flags = 0; - if (!texture->HasMipMaps()) - loadDef->flags |= iwi6::IMG_FLAG_NOMIPMAPS; - if (texture->GetTextureType() == TextureType::T_CUBE) - loadDef->flags |= iwi6::IMG_FLAG_CUBEMAP; - if (texture->GetTextureType() == TextureType::T_3D) - loadDef->flags |= iwi6::IMG_FLAG_VOLMAP; - loadDef->dimensions[0] = image->width; - loadDef->dimensions[1] = image->height; - loadDef->dimensions[2] = image->depth; - loadDef->format = static_cast(texture->GetFormat()->GetD3DFormat()); - loadDef->resourceSize = dataSize; - - char* currentDataBuffer = loadDef->data; - for (auto mipLevel = 0; mipLevel < mipCount; mipLevel++) - { - const auto mipSize = texture->GetSizeOfMipLevel(mipLevel); - - for (auto face = 0; face < faceCount; face++) - { - memcpy(currentDataBuffer, texture->GetBufferForMipLevel(mipLevel, face), mipSize); - currentDataBuffer += mipSize; - } - } - - manager->AddAsset(assetName, image); - - return true; -} diff --git a/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderGfxImage.h b/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderGfxImage.h deleted file mode 100644 index d7f4be3c..00000000 --- a/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderGfxImage.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/IW3/IW3.h" -#include "SearchPath/ISearchPath.h" - -namespace IW3 -{ - class AssetLoaderGfxImage final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW3 diff --git a/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderLocalizeEntry.cpp b/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderLocalizeEntry.cpp deleted file mode 100644 index b71c5cf5..00000000 --- a/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderLocalizeEntry.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "AssetLoaderLocalizeEntry.h" - -#include "Localize/LocalizeCommonAssetLoader.h" - -using namespace IW3; - -XAssetInfoGeneric* AssetLoaderLocalizeEntry::LoadFromGlobalAssetPools(const std::string& assetName) const -{ - return nullptr; -} - -void* AssetLoaderLocalizeEntry::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - return nullptr; -} - -bool AssetLoaderLocalizeEntry::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderLocalizeEntry::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const LocalizeCommonAssetLoader commonLoader( - [memory, manager](const CommonLocalizeEntry& entry) - { - auto* localizeEntry = memory->Create(); - localizeEntry->name = memory->Dup(entry.m_key.c_str()); - localizeEntry->value = memory->Dup(entry.m_value.c_str()); - - manager->AddAsset(entry.m_key, localizeEntry); - }); - - return commonLoader.LoadLocalizeAsset(assetName, searchPath, manager, zone); -} diff --git a/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderLocalizeEntry.h b/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderLocalizeEntry.h deleted file mode 100644 index 3174989d..00000000 --- a/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderLocalizeEntry.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/IW3/IW3.h" -#include "SearchPath/ISearchPath.h" - -namespace IW3 -{ - class AssetLoaderLocalizeEntry final : public BasicAssetLoader - { - public: - _NODISCARD XAssetInfoGeneric* LoadFromGlobalAssetPools(const std::string& assetName) const override; - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW3 diff --git a/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderRawFile.cpp b/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderRawFile.cpp deleted file mode 100644 index c865c06e..00000000 --- a/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderRawFile.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "AssetLoaderRawFile.h" - -#include "Game/IW3/IW3.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW3; - -void* AssetLoaderRawFile::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* rawFile = memory->Create(); - memset(rawFile, 0, sizeof(RawFile)); - rawFile->name = memory->Dup(assetName.c_str()); - return rawFile; -} - -bool AssetLoaderRawFile::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderRawFile::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(assetName); - if (!file.IsOpen()) - return false; - - auto* rawFile = memory->Create(); - rawFile->name = memory->Dup(assetName.c_str()); - rawFile->len = static_cast(file.m_length); - - auto* fileBuffer = memory->Alloc(static_cast(file.m_length + 1)); - file.m_stream->read(fileBuffer, file.m_length); - if (file.m_stream->gcount() != file.m_length) - return false; - fileBuffer[rawFile->len] = '\0'; - - rawFile->buffer = fileBuffer; - manager->AddAsset(assetName, rawFile); - - return true; -} diff --git a/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderRawFile.h b/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderRawFile.h deleted file mode 100644 index 41d1e295..00000000 --- a/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderRawFile.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/IW3/IW3.h" -#include "SearchPath/ISearchPath.h" - -namespace IW3 -{ - class AssetLoaderRawFile final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW3 diff --git a/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderStringTable.cpp b/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderStringTable.cpp deleted file mode 100644 index 972e647f..00000000 --- a/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderStringTable.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "AssetLoaderStringTable.h" - -#include "Csv/CsvStream.h" -#include "Game/IW3/CommonIW3.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" -#include "StringTable/StringTableLoader.h" - -#include - -using namespace IW3; - -void* AssetLoaderStringTable::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* stringTable = memory->Create(); - memset(stringTable, 0, sizeof(StringTable)); - stringTable->name = memory->Dup(assetName.c_str()); - return stringTable; -} - -bool AssetLoaderStringTable::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderStringTable::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(assetName); - if (!file.IsOpen()) - return false; - - string_table::StringTableLoaderV1 loader; - auto* stringTable = loader.LoadFromStream(assetName, *memory, *file.m_stream); - - manager->AddAsset(assetName, stringTable); - - return true; -} diff --git a/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderStringTable.h b/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderStringTable.h deleted file mode 100644 index a8a52387..00000000 --- a/src/ObjLoading/Game/IW3/AssetLoaders/AssetLoaderStringTable.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW3/IW3.h" -#include "SearchPath/ISearchPath.h" - -namespace IW3 -{ - class AssetLoaderStringTable final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW3 diff --git a/src/ObjLoading/Game/IW3/Image/AssetLoaderImageIW3.cpp b/src/ObjLoading/Game/IW3/Image/AssetLoaderImageIW3.cpp new file mode 100644 index 00000000..6f65b5af --- /dev/null +++ b/src/ObjLoading/Game/IW3/Image/AssetLoaderImageIW3.cpp @@ -0,0 +1,131 @@ +#include "AssetLoaderImageIW3.h" + +#include "Game/IW3/IW3.h" +#include "Image/DdsLoader.h" +#include "Image/IwiTypes.h" +#include "Pool/GlobalAssetPool.h" + +#include +#include +#include +#include + +using namespace IW3; + +namespace +{ + class ImageLoader final : public AssetCreator + { + public: + ImageLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + // Do not load any GfxImages from raw for now that are not loaded + // TODO: Load iwis and add streaming info to asset + if (assetName.empty() || assetName[0] != '*') + return AssetCreationResult::NoAction(); + + std::string safeAssetName = assetName; + std::ranges::replace(safeAssetName, '*', '_'); + + const auto file = m_search_path.Open(std::format("images/{}.dds", safeAssetName)); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + const auto texture = dds::LoadDds(*file.m_stream); + if (!texture) + { + std::cerr << std::format("Failed to load dds file for image asset \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + auto* image = m_memory.Alloc(); + image->name = m_memory.Dup(assetName.c_str()); + image->picmip.platform[0] = 0; + image->picmip.platform[1] = 0; + image->noPicmip = !texture->HasMipMaps(); + image->semantic = TS_FUNCTION; + image->track = 0; + image->cardMemory.platform[0] = 0; + image->cardMemory.platform[1] = 0; + image->width = static_cast(texture->GetWidth()); + image->height = static_cast(texture->GetHeight()); + image->depth = static_cast(texture->GetDepth()); + image->category = IMG_CATEGORY_AUTO_GENERATED; + image->delayLoadPixels = false; + + switch (texture->GetTextureType()) + { + case TextureType::T_2D: + image->mapType = MAPTYPE_2D; + break; + + case TextureType::T_3D: + image->mapType = MAPTYPE_3D; + break; + + case TextureType::T_CUBE: + image->mapType = MAPTYPE_CUBE; + break; + + default: + image->mapType = MAPTYPE_NONE; + break; + } + + const auto mipCount = texture->HasMipMaps() ? texture->GetMipMapCount() : 1; + const auto faceCount = texture->GetFaceCount(); + + size_t dataSize = 0; + for (auto mipLevel = 0; mipLevel < mipCount; mipLevel++) + dataSize += texture->GetSizeOfMipLevel(mipLevel) * faceCount; + + auto* loadDef = static_cast(m_memory.AllocRaw(offsetof(GfxImageLoadDef, data) + dataSize)); + image->texture.loadDef = loadDef; + loadDef->levelCount = static_cast(mipCount); + loadDef->flags = 0; + if (!texture->HasMipMaps()) + loadDef->flags |= iwi6::IMG_FLAG_NOMIPMAPS; + if (texture->GetTextureType() == TextureType::T_CUBE) + loadDef->flags |= iwi6::IMG_FLAG_CUBEMAP; + if (texture->GetTextureType() == TextureType::T_3D) + loadDef->flags |= iwi6::IMG_FLAG_VOLMAP; + loadDef->dimensions[0] = image->width; + loadDef->dimensions[1] = image->height; + loadDef->dimensions[2] = image->depth; + loadDef->format = static_cast(texture->GetFormat()->GetD3DFormat()); + loadDef->resourceSize = dataSize; + + char* currentDataBuffer = loadDef->data; + for (auto mipLevel = 0; mipLevel < mipCount; mipLevel++) + { + const auto mipSize = texture->GetSizeOfMipLevel(mipLevel); + + for (auto face = 0; face < faceCount; face++) + { + memcpy(currentDataBuffer, texture->GetBufferForMipLevel(mipLevel, face), mipSize); + currentDataBuffer += mipSize; + } + } + + return AssetCreationResult::Success(context.AddAsset(assetName, image)); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace IW3 +{ + std::unique_ptr> CreateImageLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace IW3 diff --git a/src/ObjLoading/Game/IW3/Image/AssetLoaderImageIW3.h b/src/ObjLoading/Game/IW3/Image/AssetLoaderImageIW3.h new file mode 100644 index 00000000..ce4dbb81 --- /dev/null +++ b/src/ObjLoading/Game/IW3/Image/AssetLoaderImageIW3.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW3/IW3.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW3 +{ + std::unique_ptr> CreateImageLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace IW3 diff --git a/src/ObjLoading/Game/IW3/Localize/AssetLoaderLocalizeIW3.cpp b/src/ObjLoading/Game/IW3/Localize/AssetLoaderLocalizeIW3.cpp new file mode 100644 index 00000000..c7f2572f --- /dev/null +++ b/src/ObjLoading/Game/IW3/Localize/AssetLoaderLocalizeIW3.cpp @@ -0,0 +1,45 @@ +#include "AssetLoaderLocalizeIW3.h" + +#include "Localize/CommonLocalizeLoader.h" + +using namespace IW3; + +namespace +{ + class LocalizeLoader final : public AssetCreator, public CommonLocalizeLoader + { + public: + LocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : CommonLocalizeLoader(searchPath, zone), + m_memory(memory) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + return CreateLocalizeAsset(assetName, context); + } + + protected: + AssetCreationResult CreateAssetFromCommonAsset(const CommonLocalizeEntry& localizeEntry, AssetCreationContext& context) override + + { + auto* asset = m_memory.Alloc(); + asset->name = m_memory.Dup(localizeEntry.m_key.c_str()); + asset->value = m_memory.Dup(localizeEntry.m_value.c_str()); + + return AssetCreationResult::Success(context.AddAsset(localizeEntry.m_key, asset)); + } + + private: + MemoryManager& m_memory; + }; +} // namespace + +namespace IW3 +{ + std::unique_ptr> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + { + return std::make_unique(memory, searchPath, zone); + } +} // namespace IW3 diff --git a/src/ObjLoading/Game/IW3/Localize/AssetLoaderLocalizeIW3.h b/src/ObjLoading/Game/IW3/Localize/AssetLoaderLocalizeIW3.h new file mode 100644 index 00000000..5469d4ca --- /dev/null +++ b/src/ObjLoading/Game/IW3/Localize/AssetLoaderLocalizeIW3.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW3/IW3.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" +#include "Zone/Zone.h" + +#include + +namespace IW3 +{ + std::unique_ptr> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace IW3 diff --git a/src/ObjLoading/Game/IW3/ObjLoaderIW3.cpp b/src/ObjLoading/Game/IW3/ObjLoaderIW3.cpp index 4ea79be1..9d06750a 100644 --- a/src/ObjLoading/Game/IW3/ObjLoaderIW3.cpp +++ b/src/ObjLoading/Game/IW3/ObjLoaderIW3.cpp @@ -1,75 +1,125 @@ #include "ObjLoaderIW3.h" -#include "AssetLoaders/AssetLoaderGfxImage.h" -#include "AssetLoaders/AssetLoaderLocalizeEntry.h" -#include "AssetLoaders/AssetLoaderRawFile.h" -#include "AssetLoading/AssetLoadingManager.h" +#include "Asset/GlobalAssetPoolsLoader.h" #include "Game/IW3/GameIW3.h" +#include "Game/IW3/IW3.h" +#include "Image/AssetLoaderImageIW3.h" +#include "Localize/AssetLoaderLocalizeIW3.h" #include "ObjLoading.h" +#include "RawFile/AssetLoaderRawFileIW3.h" +#include "StringTable/AssetLoaderStringTableIW3.h" + +#include using namespace IW3; -ObjLoader::ObjLoader() -{ -#define REGISTER_ASSET_LOADER(t) \ - { \ - auto l = std::make_unique(); \ - m_asset_loaders_by_type[l->GetHandlingAssetType()] = std::move(l); \ - } - - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(AssetLoaderGfxImage) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(AssetLoaderLocalizeEntry) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(AssetLoaderRawFile) - REGISTER_ASSET_LOADER(BasicAssetLoader) - -#undef REGISTER_ASSET_LOADER -} - -bool ObjLoader::IsMpZone(const Zone& zone) -{ - return zone.m_name.compare(0, 3, "mp_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_mp") == 0; -} - -bool ObjLoader::IsZmZone(const Zone& zone) -{ - return zone.m_name.compare(0, 3, "zm_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_zm") == 0; -} - void ObjLoader::LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const {} void ObjLoader::UnloadContainersOfZone(Zone& zone) const {} -bool ObjLoader::LoadAssetForZone(AssetLoadingContext& context, const asset_type_t assetType, const std::string& assetName) const +namespace { - AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, context); - return assetLoadingManager.LoadAssetFromLoader(assetType, assetName); -} + void ConfigureDefaultCreators(AssetCreatorCollection& collection, Zone& zone) + { + auto& memory = *zone.GetMemory(); -void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext& context) const + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + } + + void ConfigureGlobalAssetPoolsLoaders(AssetCreatorCollection& collection, Zone& zone) + { + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + } + + void ConfigureLoaders(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath) + { + auto& memory = *zone.GetMemory(); + + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateImageLoader(memory, searchPath)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateLocalizeLoader(memory, searchPath, zone)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateRawFileLoader(memory, searchPath)); + collection.AddAssetCreator(CreateStringTableLoader(memory, searchPath)); + } +} // namespace + +void ObjLoader::ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, IGdtQueryable& gdt) const { - for (const auto& [type, loader] : m_asset_loaders_by_type) - loader->FinalizeAssetsForZone(context); + ConfigureDefaultCreators(collection, zone); + ConfigureLoaders(collection, zone, searchPath); + ConfigureGlobalAssetPoolsLoaders(collection, zone); } diff --git a/src/ObjLoading/Game/IW3/ObjLoaderIW3.h b/src/ObjLoading/Game/IW3/ObjLoaderIW3.h index f027ecb4..a11c9d51 100644 --- a/src/ObjLoading/Game/IW3/ObjLoaderIW3.h +++ b/src/ObjLoading/Game/IW3/ObjLoaderIW3.h @@ -1,28 +1,16 @@ #pragma once -#include "AssetLoading/IAssetLoader.h" #include "IObjLoader.h" #include "SearchPath/ISearchPath.h" -#include -#include - namespace IW3 { class ObjLoader final : public IObjLoader { - std::unordered_map> m_asset_loaders_by_type; - - static bool IsMpZone(const Zone& zone); - static bool IsZmZone(const Zone& zone); - public: - ObjLoader(); - void LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const override; void UnloadContainersOfZone(Zone& zone) const override; - bool LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const override; - void FinalizeAssetsForZone(AssetLoadingContext& context) const override; + void ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, IGdtQueryable& gdt) const override; }; } // namespace IW3 diff --git a/src/ObjLoading/Game/IW3/RawFile/AssetLoaderRawFileIW3.cpp b/src/ObjLoading/Game/IW3/RawFile/AssetLoaderRawFileIW3.cpp new file mode 100644 index 00000000..92a19b21 --- /dev/null +++ b/src/ObjLoading/Game/IW3/RawFile/AssetLoaderRawFileIW3.cpp @@ -0,0 +1,53 @@ +#include "AssetLoaderRawFileIW3.h" + +#include "Game/IW3/IW3.h" + +#include + +using namespace IW3; + +namespace +{ + class RawFileLoader final : public AssetCreator + { + public: + RawFileLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto file = m_search_path.Open(assetName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + auto* rawFile = m_memory.Alloc(); + rawFile->name = m_memory.Dup(assetName.c_str()); + rawFile->len = static_cast(file.m_length); + + auto* fileBuffer = m_memory.Alloc(static_cast(file.m_length + 1)); + file.m_stream->read(fileBuffer, file.m_length); + if (file.m_stream->gcount() != file.m_length) + return AssetCreationResult::Failure(); + fileBuffer[rawFile->len] = '\0'; + + rawFile->buffer = fileBuffer; + + return AssetCreationResult::Success(context.AddAsset(assetName, rawFile)); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace IW3 +{ + std::unique_ptr> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace IW3 diff --git a/src/ObjLoading/Game/IW3/RawFile/AssetLoaderRawFileIW3.h b/src/ObjLoading/Game/IW3/RawFile/AssetLoaderRawFileIW3.h new file mode 100644 index 00000000..cddae3ea --- /dev/null +++ b/src/ObjLoading/Game/IW3/RawFile/AssetLoaderRawFileIW3.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW3/IW3.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW3 +{ + std::unique_ptr> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace IW3 diff --git a/src/ObjLoading/Game/IW3/StringTable/AssetLoaderStringTableIW3.cpp b/src/ObjLoading/Game/IW3/StringTable/AssetLoaderStringTableIW3.cpp new file mode 100644 index 00000000..bb7303ec --- /dev/null +++ b/src/ObjLoading/Game/IW3/StringTable/AssetLoaderStringTableIW3.cpp @@ -0,0 +1,47 @@ +#include "AssetLoaderStringTableIW3.h" + +#include "Game/IW3/IW3.h" +#include "StringTable/StringTableLoader.h" + +#include + +using namespace IW3; + +namespace +{ + class StringTableLoader final : public AssetCreator + { + public: + StringTableLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto file = m_search_path.Open(assetName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + string_table::StringTableLoaderV1 loader; + auto* stringTable = loader.LoadFromStream(assetName, m_memory, *file.m_stream); + if (!stringTable) + return AssetCreationResult::Failure(); + + return AssetCreationResult::Success(context.AddAsset(assetName, stringTable)); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace IW3 +{ + std::unique_ptr> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace IW3 diff --git a/src/ObjLoading/Game/IW3/StringTable/AssetLoaderStringTableIW3.h b/src/ObjLoading/Game/IW3/StringTable/AssetLoaderStringTableIW3.h new file mode 100644 index 00000000..76702596 --- /dev/null +++ b/src/ObjLoading/Game/IW3/StringTable/AssetLoaderStringTableIW3.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW3/IW3.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW3 +{ + std::unique_ptr> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace IW3 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderAddonMapEnts.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderAddonMapEnts.cpp deleted file mode 100644 index bc1efe01..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderAddonMapEnts.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderAddonMapEnts.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW4; - -void* AssetLoaderAddonMapEnts::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* addonMapEnts = memory->Create(); - memset(addonMapEnts, 0, sizeof(AddonMapEnts)); - addonMapEnts->name = memory->Dup(assetName.c_str()); - return addonMapEnts; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderAddonMapEnts.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderAddonMapEnts.h deleted file mode 100644 index 119bbd73..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderAddonMapEnts.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderAddonMapEnts final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderClipMap.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderClipMap.cpp deleted file mode 100644 index 874a6ffe..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderClipMap.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "AssetLoaderClipMap.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW4; - -void* AssetLoaderClipMap::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* clipMap = memory->Create(); - memset(clipMap, 0, sizeof(clipMap_t)); - clipMap->name = memory->Dup(assetName.c_str()); - return clipMap; -} - -asset_type_t AssetLoaderClipMapSp::GetHandlingAssetType() const -{ - return ASSET_TYPE_CLIPMAP_SP; -} - -asset_type_t AssetLoaderClipMapMp::GetHandlingAssetType() const -{ - return ASSET_TYPE_CLIPMAP_MP; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderClipMap.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderClipMap.h deleted file mode 100644 index dabf4c80..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderClipMap.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderClipMap : public BasicAssetLoaderWithoutType - { - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; - - class AssetLoaderClipMapSp final : public AssetLoaderClipMap - { - public: - _NODISCARD asset_type_t GetHandlingAssetType() const override; - }; - - class AssetLoaderClipMapMp final : public AssetLoaderClipMap - { - public: - _NODISCARD asset_type_t GetHandlingAssetType() const override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderComWorld.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderComWorld.cpp deleted file mode 100644 index bb373c78..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderComWorld.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderComWorld.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW4; - -void* AssetLoaderComWorld::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* comWorld = memory->Create(); - memset(comWorld, 0, sizeof(ComWorld)); - comWorld->name = memory->Dup(assetName.c_str()); - return comWorld; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderComWorld.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderComWorld.h deleted file mode 100644 index 534ffa72..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderComWorld.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderComWorld final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFont.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFont.cpp deleted file mode 100644 index 4afef3a4..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFont.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderFont.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW4; - -void* AssetLoaderFont::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* font = memory->Create(); - memset(font, 0, sizeof(Font_s)); - font->fontName = memory->Dup(assetName.c_str()); - return font; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFont.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFont.h deleted file mode 100644 index 10175221..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFont.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderFont final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFx.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFx.cpp deleted file mode 100644 index 4bed0ab5..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFx.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderFx.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW4; - -void* AssetLoaderFx::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* fx = memory->Create(); - memset(fx, 0, sizeof(FxEffectDef)); - fx->name = memory->Dup(assetName.c_str()); - return fx; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFx.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFx.h deleted file mode 100644 index 3cddeb71..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFx.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderFx final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFxImpactTable.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFxImpactTable.cpp deleted file mode 100644 index 148e69e0..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFxImpactTable.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderFxImpactTable.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW4; - -void* AssetLoaderFxImpactTable::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* fxImpactTable = memory->Create(); - memset(fxImpactTable, 0, sizeof(FxImpactTable)); - fxImpactTable->name = memory->Dup(assetName.c_str()); - return fxImpactTable; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFxImpactTable.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFxImpactTable.h deleted file mode 100644 index b7ff4c10..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFxImpactTable.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderFxImpactTable final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFxWorld.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFxWorld.cpp deleted file mode 100644 index 70c880db..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFxWorld.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderFxWorld.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW4; - -void* AssetLoaderFxWorld::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* fxWorld = memory->Create(); - memset(fxWorld, 0, sizeof(FxWorld)); - fxWorld->name = memory->Dup(assetName.c_str()); - return fxWorld; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFxWorld.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFxWorld.h deleted file mode 100644 index bbdc1ec6..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderFxWorld.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderFxWorld final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGameWorldMp.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGameWorldMp.cpp deleted file mode 100644 index 93bf930b..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGameWorldMp.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderGameWorldMp.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW4; - -void* AssetLoaderGameWorldMp::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* gameWorld = memory->Create(); - memset(gameWorld, 0, sizeof(GameWorldMp)); - gameWorld->name = memory->Dup(assetName.c_str()); - return gameWorld; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGameWorldMp.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGameWorldMp.h deleted file mode 100644 index 4b9ce827..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGameWorldMp.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderGameWorldMp final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGameWorldSp.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGameWorldSp.cpp deleted file mode 100644 index 331e7c03..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGameWorldSp.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderGameWorldSp.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW4; - -void* AssetLoaderGameWorldSp::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* gameWorld = memory->Create(); - memset(gameWorld, 0, sizeof(GameWorldSp)); - gameWorld->name = memory->Dup(assetName.c_str()); - return gameWorld; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGameWorldSp.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGameWorldSp.h deleted file mode 100644 index f952186e..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGameWorldSp.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderGameWorldSp final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGfxImage.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGfxImage.cpp deleted file mode 100644 index 10d6697c..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGfxImage.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderGfxImage.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW4; - -void* AssetLoaderGfxImage::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* image = memory->Create(); - memset(image, 0, sizeof(GfxImage)); - image->name = memory->Dup(assetName.c_str()); - return image; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGfxImage.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGfxImage.h deleted file mode 100644 index e63c470f..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGfxImage.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderGfxImage final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGfxLightDef.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGfxLightDef.cpp deleted file mode 100644 index 775eb766..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGfxLightDef.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "AssetLoaderGfxLightDef.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include -#include - -using namespace IW4; - -std::string AssetLoaderGfxLightDef::GetAssetFilename(const std::string& assetName) -{ - std::ostringstream ss; - - ss << "lights/" << assetName; - - return ss.str(); -} - -void* AssetLoaderGfxLightDef::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* lightDef = memory->Create(); - memset(lightDef, 0, sizeof(GfxLightDef)); - lightDef->name = memory->Dup(assetName.c_str()); - return lightDef; -} - -bool AssetLoaderGfxLightDef::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderGfxLightDef::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto filename = GetAssetFilename(assetName); - const auto file = searchPath->Open(filename); - if (!file.IsOpen()) - return false; - - const auto imageNameSize = file.m_length - sizeof(char) - sizeof(char); - if (imageNameSize < 0 || imageNameSize > MAX_IMAGE_NAME_SIZE) - return false; - - std::string imageName(static_cast(imageNameSize), '\0'); - - int8_t samplerState; - int8_t lmapLookupStart; - file.m_stream->read(reinterpret_cast(&samplerState), sizeof(int8_t)); - file.m_stream->read(&imageName[0], static_cast(imageNameSize)); - file.m_stream->read(reinterpret_cast(&lmapLookupStart), sizeof(int8_t)); - - auto* imageDependency = manager->LoadDependency(imageName); - - if (!imageDependency) - { - std::cerr << "Could not load GfxLightDef \"" << assetName << "\" due to missing image \"" << imageName << "\"\n"; - return false; - } - - auto* lightDef = memory->Create(); - lightDef->name = memory->Dup(assetName.c_str()); - lightDef->attenuation.samplerState = samplerState; - lightDef->attenuation.image = imageDependency->Asset(); - lightDef->lmapLookupStart = static_cast(static_cast(lmapLookupStart)); - - manager->AddAsset(assetName, lightDef); - - return true; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGfxLightDef.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGfxLightDef.h deleted file mode 100644 index f8fbae58..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGfxLightDef.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderGfxLightDef final : public BasicAssetLoader - { - static constexpr auto MAX_IMAGE_NAME_SIZE = 0x800; - - static std::string GetAssetFilename(const std::string& assetName); - - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGfxWorld.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGfxWorld.cpp deleted file mode 100644 index b31d5112..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGfxWorld.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderGfxWorld.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW4; - -void* AssetLoaderGfxWorld::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* gfxWorld = memory->Create(); - memset(gfxWorld, 0, sizeof(GfxWorld)); - gfxWorld->name = memory->Dup(assetName.c_str()); - return gfxWorld; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGfxWorld.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGfxWorld.h deleted file mode 100644 index 2f87ed12..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderGfxWorld.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderGfxWorld final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderLeaderboard.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderLeaderboard.cpp deleted file mode 100644 index 17952169..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderLeaderboard.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "AssetLoaderLeaderboard.h" - -#include "Game/IW4/IW4.h" -#include "Game/IW4/Leaderboard/JsonLeaderboardDefLoader.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include -#include - -using namespace IW4; - -void* AssetLoaderLeaderboard::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* leaderboard = memory->Create(); - memset(leaderboard, 0, sizeof(LeaderboardDef)); - leaderboard->name = memory->Dup(assetName.c_str()); - return leaderboard; -} - -bool AssetLoaderLeaderboard::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderLeaderboard::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(std::format("leaderboards/{}.json", assetName)); - if (!file.IsOpen()) - return false; - - auto* leaderboardDef = memory->Alloc(); - leaderboardDef->name = memory->Dup(assetName.c_str()); - - if (LoadLeaderboardAsJson(*file.m_stream, *leaderboardDef, memory)) - manager->AddAsset(assetName, leaderboardDef); - else - std::cerr << std::format("Failed to load leaderboard \"{}\"\n", assetName); - - return true; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderLeaderboard.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderLeaderboard.h deleted file mode 100644 index 1d3a224d..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderLeaderboard.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderLeaderboard final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderLoadedSound.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderLoadedSound.cpp deleted file mode 100644 index b94bc60e..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderLoadedSound.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderLoadedSound.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW4; - -void* AssetLoaderLoadedSound::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* loadedSound = memory->Create(); - memset(loadedSound, 0, sizeof(LoadedSound)); - loadedSound->name = memory->Dup(assetName.c_str()); - return loadedSound; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderLoadedSound.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderLoadedSound.h deleted file mode 100644 index 8b166f29..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderLoadedSound.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderLoadedSound final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderLocalizeEntry.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderLocalizeEntry.cpp deleted file mode 100644 index 6d4f596e..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderLocalizeEntry.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "AssetLoaderLocalizeEntry.h" - -#include "Localize/LocalizeCommonAssetLoader.h" - -using namespace IW4; - -XAssetInfoGeneric* AssetLoaderLocalizeEntry::LoadFromGlobalAssetPools(const std::string& assetName) const -{ - return nullptr; -} - -void* AssetLoaderLocalizeEntry::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - return nullptr; -} - -bool AssetLoaderLocalizeEntry::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderLocalizeEntry::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const LocalizeCommonAssetLoader commonLoader( - [memory, manager](const CommonLocalizeEntry& entry) - { - auto* localizeEntry = memory->Create(); - localizeEntry->name = memory->Dup(entry.m_key.c_str()); - localizeEntry->value = memory->Dup(entry.m_value.c_str()); - - manager->AddAsset(entry.m_key, localizeEntry); - }); - - return commonLoader.LoadLocalizeAsset(assetName, searchPath, manager, zone); -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderLocalizeEntry.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderLocalizeEntry.h deleted file mode 100644 index b6964d7e..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderLocalizeEntry.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderLocalizeEntry final : public BasicAssetLoader - { - public: - _NODISCARD XAssetInfoGeneric* LoadFromGlobalAssetPools(const std::string& assetName) const override; - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMapEnts.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMapEnts.cpp deleted file mode 100644 index 012cb0f8..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMapEnts.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderMapEnts.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW4; - -void* AssetLoaderMapEnts::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* mapEnts = memory->Create(); - memset(mapEnts, 0, sizeof(MapEnts)); - mapEnts->name = memory->Dup(assetName.c_str()); - return mapEnts; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMapEnts.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMapEnts.h deleted file mode 100644 index 518e5666..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMapEnts.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderMapEnts final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMaterial.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMaterial.h deleted file mode 100644 index d5642e7c..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMaterial.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderMaterial final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromGdt() const override; - bool LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuDef.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuDef.cpp deleted file mode 100644 index b2fe0500..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuDef.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderMenuDef.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW4; - -void* AssetLoaderMenuDef::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* menu = memory->Create(); - memset(menu, 0, sizeof(menuDef_t)); - menu->window.name = memory->Dup(assetName.c_str()); - return menu; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuDef.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuDef.h deleted file mode 100644 index 35d0910a..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuDef.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderMenuDef final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuList.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuList.cpp deleted file mode 100644 index 276cefc3..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuList.cpp +++ /dev/null @@ -1,233 +0,0 @@ -#include "AssetLoaderMenuList.h" - -#include "Game/IW4/IW4.h" -#include "Game/IW4/Menu/MenuConversionZoneStateIW4.h" -#include "Game/IW4/Menu/MenuConverterIW4.h" -#include "ObjLoading.h" -#include "Parsing/Menu/MenuFileReader.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include - -using namespace IW4; - -namespace IW4 -{ - class MenuLoader - { - public: - static bool ProcessParsedResults(const std::string& fileName, - ISearchPath* searchPath, - MemoryManager* memory, - IAssetLoadingManager* manager, - menu::ParsingResult* parsingResult, - menu::MenuAssetZoneState* zoneState, - MenuConversionZoneState* conversionState, - std::vector& menus, - std::vector& menuListDependencies) - { - const auto menuCount = parsingResult->m_menus.size(); - const auto functionCount = parsingResult->m_functions.size(); - const auto menuLoadCount = parsingResult->m_menus_to_load.size(); - auto totalItemCount = 0u; - for (const auto& menu : parsingResult->m_menus) - totalItemCount += menu->m_items.size(); - - std::cout << "Successfully read menu file \"" << fileName << "\" (" << menuLoadCount << " loads, " << menuCount << " menus, " << functionCount - << " functions, " << totalItemCount << " items)\n"; - - // Add all functions to the zone state to make them available for all menus to be converted - for (auto& function : parsingResult->m_functions) - zoneState->AddFunction(std::move(function)); - - // Prepare a list of all menus of this file - std::vector*> allMenusOfFile; - allMenusOfFile.reserve(parsingResult->m_menus.size()); - - // Convert all menus and add them as assets - for (auto& menu : parsingResult->m_menus) - { - MenuConverter converter(ObjLoading::Configuration.MenuNoOptimization, searchPath, memory, manager); - auto* menuAsset = converter.ConvertMenu(*menu); - if (menuAsset == nullptr) - { - std::cout << "Failed to convert menu file \"" << menu->m_name << "\"\n"; - return false; - } - - menus.push_back(menuAsset); - auto* menuAssetInfo = manager->AddAsset(menu->m_name, menuAsset, std::move(converter.GetDependencies())); - - if (menuAssetInfo) - { - allMenusOfFile.push_back(menuAssetInfo); - menuListDependencies.push_back(menuAssetInfo); - } - - zoneState->AddMenu(std::move(menu)); - } - - // Register this file with all loaded menus - conversionState->AddLoadedFile(fileName, std::move(allMenusOfFile)); - - return true; - } - - static MenuList* CreateMenuListAsset(const std::string& assetName, MemoryManager* memory, const std::vector& menus) - { - auto* menuListAsset = memory->Create(); - menuListAsset->name = memory->Dup(assetName.c_str()); - menuListAsset->menuCount = static_cast(menus.size()); - - if (menuListAsset->menuCount > 0) - { - menuListAsset->menus = memory->Alloc(menuListAsset->menuCount); - for (auto i = 0; i < menuListAsset->menuCount; i++) - menuListAsset->menus[i] = menus[i]; - } - else - menuListAsset->menus = nullptr; - - return menuListAsset; - } - - static std::unique_ptr - ParseMenuFile(const std::string& menuFileName, ISearchPath* searchPath, const menu::MenuAssetZoneState* zoneState) - { - const auto file = searchPath->Open(menuFileName); - if (!file.IsOpen()) - return nullptr; - - menu::MenuFileReader reader(*file.m_stream, - menuFileName, - menu::FeatureLevel::IW4, - [searchPath](const std::string& filename, const std::string& sourceFile) -> std::unique_ptr - { - auto foundFileToInclude = searchPath->Open(filename); - if (!foundFileToInclude.IsOpen() || !foundFileToInclude.m_stream) - return nullptr; - - return std::move(foundFileToInclude.m_stream); - }); - - reader.IncludeZoneState(zoneState); - reader.SetPermissiveMode(ObjLoading::Configuration.MenuPermissiveParsing); - - return reader.ReadMenuFile(); - } - }; -} // namespace IW4 - -void* AssetLoaderMenuList::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* menuList = memory->Create(); - memset(menuList, 0, sizeof(MenuList)); - menuList->name = memory->Dup(assetName.c_str()); - return menuList; -} - -bool AssetLoaderMenuList::CanLoadFromRaw() const -{ - return true; -} - -bool BuildMenuFileQueue(std::deque& menuLoadQueue, - const std::string& menuListAssetName, - ISearchPath* searchPath, - MemoryManager* memory, - IAssetLoadingManager* manager, - menu::MenuAssetZoneState* zoneState, - MenuConversionZoneState* conversionState, - std::vector& menus, - std::vector& menuListDependencies) -{ - const auto alreadyLoadedMenuListFileMenus = conversionState->m_menus_by_filename.find(menuListAssetName); - - if (alreadyLoadedMenuListFileMenus == conversionState->m_menus_by_filename.end()) - { - const auto menuListResult = MenuLoader::ParseMenuFile(menuListAssetName, searchPath, zoneState); - if (menuListResult) - { - MenuLoader::ProcessParsedResults( - menuListAssetName, searchPath, memory, manager, menuListResult.get(), zoneState, conversionState, menus, menuListDependencies); - - for (const auto& menuToLoad : menuListResult->m_menus_to_load) - menuLoadQueue.push_back(menuToLoad); - - zoneState->AddMenusToLoad(menuListAssetName, std::move(menuListResult->m_menus_to_load)); - } - else - return false; - } - - return true; -} - -void LoadMenuFileFromQueue(const std::string& menuFilePath, - ISearchPath* searchPath, - MemoryManager* memory, - IAssetLoadingManager* manager, - menu::MenuAssetZoneState* zoneState, - MenuConversionZoneState* conversionState, - std::vector& menus, - std::vector& menuListDependencies) -{ - const auto alreadyLoadedMenuFile = conversionState->m_menus_by_filename.find(menuFilePath); - if (alreadyLoadedMenuFile != conversionState->m_menus_by_filename.end()) - { - std::cout << "Already loaded \"" << menuFilePath << "\", skipping\n"; - for (auto* menu : alreadyLoadedMenuFile->second) - { - menus.push_back(menu->Asset()); - menuListDependencies.push_back(menu); - } - return; - } - - const auto menuFileResult = MenuLoader::ParseMenuFile(menuFilePath, searchPath, zoneState); - if (menuFileResult) - { - MenuLoader::ProcessParsedResults( - menuFilePath, searchPath, memory, manager, menuFileResult.get(), zoneState, conversionState, menus, menuListDependencies); - if (!menuFileResult->m_menus_to_load.empty()) - std::cout << "WARNING: Menu file has menus to load even though it is not a menu list, ignoring: \"" << menuFilePath << "\"\n"; - } - else - std::cerr << "Could not read menu file \"" << menuFilePath << "\"\n"; -} - -bool AssetLoaderMenuList::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - std::vector menus; - std::vector menuListDependencies; - - auto* zoneState = manager->GetAssetLoadingContext()->GetZoneAssetLoaderState(); - auto* conversionState = manager->GetAssetLoadingContext()->GetZoneAssetLoaderState(); - - std::deque menuLoadQueue; - if (!BuildMenuFileQueue(menuLoadQueue, assetName, searchPath, memory, manager, zoneState, conversionState, menus, menuListDependencies)) - return false; - - while (!menuLoadQueue.empty()) - { - const auto& menuFileToLoad = menuLoadQueue.front(); - - LoadMenuFileFromQueue(menuFileToLoad, searchPath, memory, manager, zoneState, conversionState, menus, menuListDependencies); - - menuLoadQueue.pop_front(); - } - - auto* menuListAsset = MenuLoader::CreateMenuListAsset(assetName, memory, menus); - - if (menuListAsset) - manager->AddAsset(assetName, menuListAsset, menuListDependencies); - - return true; -} - -void AssetLoaderMenuList::FinalizeAssetsForZone(AssetLoadingContext& context) const -{ - context.GetZoneAssetLoaderState()->FinalizeSupportingData(); -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuList.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuList.h deleted file mode 100644 index 61f45486..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuList.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderMenuList final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - void FinalizeAssetsForZone(AssetLoadingContext& context) const override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderPhysCollmap.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderPhysCollmap.cpp deleted file mode 100644 index 805e14aa..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderPhysCollmap.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderPhysCollmap.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW4; - -void* AssetLoaderPhysCollmap::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* collmap = memory->Create(); - memset(collmap, 0, sizeof(PhysCollmap)); - collmap->name = memory->Dup(assetName.c_str()); - return collmap; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderPhysCollmap.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderPhysCollmap.h deleted file mode 100644 index 86cbed6c..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderPhysCollmap.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderPhysCollmap final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderPhysPreset.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderPhysPreset.cpp deleted file mode 100644 index 6f08e0c4..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderPhysPreset.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include "AssetLoaderPhysPreset.h" - -#include "Game/IW4/IW4.h" -#include "Game/IW4/InfoString/InfoStringToStructConverter.h" -#include "Game/IW4/InfoString/PhysPresetFields.h" -#include "Game/IW4/ObjConstantsIW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include -#include - -using namespace IW4; - -namespace IW4 -{ - class InfoStringToPhysPresetConverter final : public InfoStringToStructConverter - { - protected: - bool ConvertExtensionField(const cspField_t& field, const std::string& value) override - { - assert(false); - return false; - } - - public: - InfoStringToPhysPresetConverter(const InfoString& infoString, - PhysPresetInfo* physPreset, - ZoneScriptStrings& zoneScriptStrings, - MemoryManager* memory, - IAssetLoadingManager* manager, - const cspField_t* fields, - const size_t fieldCount) - : InfoStringToStructConverter(infoString, physPreset, zoneScriptStrings, memory, manager, fields, fieldCount) - { - } - }; -} // namespace IW4 - -void AssetLoaderPhysPreset::CopyFromPhysPresetInfo(const PhysPresetInfo* physPresetInfo, PhysPreset* physPreset) -{ - physPreset->mass = std::clamp(physPresetInfo->mass, 1.0f, 2000.0f) * 0.001f; - physPreset->bounce = physPresetInfo->bounce; - - if (physPresetInfo->isFrictionInfinity != 0) - physPreset->friction = std::numeric_limits::infinity(); - else - physPreset->friction = physPresetInfo->friction; - - physPreset->bulletForceScale = physPresetInfo->bulletForceScale; - physPreset->explosiveForceScale = physPresetInfo->explosiveForceScale; - physPreset->sndAliasPrefix = physPresetInfo->sndAliasPrefix; - physPreset->piecesSpreadFraction = physPresetInfo->piecesSpreadFraction; - physPreset->piecesUpwardVelocity = physPresetInfo->piecesUpwardVelocity; - physPreset->tempDefaultToCylinder = physPresetInfo->tempDefaultToCylinder != 0; - physPreset->perSurfaceSndAlias = physPresetInfo->perSurfaceSndAlias != 0; -} - -bool AssetLoaderPhysPreset::LoadFromInfoString( - const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) -{ - const auto presetInfo = std::make_unique(); - memset(presetInfo.get(), 0, sizeof(PhysPresetInfo)); - InfoStringToPhysPresetConverter converter( - infoString, presetInfo.get(), zone->m_script_strings, memory, manager, phys_preset_fields, std::extent_v); - if (!converter.Convert()) - { - std::cout << "Failed to parse phys preset: \"" << assetName << "\"\n"; - return true; - } - - auto* physPreset = memory->Create(); - - CopyFromPhysPresetInfo(presetInfo.get(), physPreset); - physPreset->name = memory->Dup(assetName.c_str()); - - manager->AddAsset(assetName, physPreset, converter.GetDependencies(), converter.GetUsedScriptStrings()); - - return true; -} - -void* AssetLoaderPhysPreset::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* physPreset = memory->Create(); - memset(physPreset, 0, sizeof(PhysPreset)); - physPreset->name = memory->Dup(assetName.c_str()); - return physPreset; -} - -bool AssetLoaderPhysPreset::CanLoadFromGdt() const -{ - return true; -} - -bool AssetLoaderPhysPreset::LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_PHYS_PRESET, assetName); - if (gdtEntry == nullptr) - return false; - - InfoString infoString; - if (!infoString.FromGdtProperties(*gdtEntry)) - { - std::cout << "Failed to read phys preset gdt entry: \"" << assetName << "\"\n"; - return true; - } - - return LoadFromInfoString(infoString, assetName, memory, manager, zone); -} - -bool AssetLoaderPhysPreset::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderPhysPreset::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto fileName = "physic/" + assetName; - const auto file = searchPath->Open(fileName); - if (!file.IsOpen()) - return false; - - InfoString infoString; - if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_PHYS_PRESET, *file.m_stream)) - { - std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n"; - return true; - } - - return LoadFromInfoString(infoString, assetName, memory, manager, zone); -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderPhysPreset.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderPhysPreset.h deleted file mode 100644 index 4d3730bb..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderPhysPreset.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "InfoString/InfoString.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderPhysPreset final : public BasicAssetLoader - { - static void CopyFromPhysPresetInfo(const PhysPresetInfo* physPresetInfo, PhysPreset* physPreset); - - static bool - LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone); - - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromGdt() const override; - bool LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderPixelShader.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderPixelShader.cpp deleted file mode 100644 index e034f6da..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderPixelShader.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "AssetLoaderPixelShader.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include -#include -#include - -using namespace IW4; - -void* AssetLoaderPixelShader::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* pixelShader = memory->Create(); - memset(pixelShader, 0, sizeof(MaterialPixelShader)); - pixelShader->name = memory->Dup(assetName.c_str()); - return pixelShader; -} - -bool AssetLoaderPixelShader::CanLoadFromRaw() const -{ - return true; -} - -std::string AssetLoaderPixelShader::GetFileNameForAsset(const std::string& assetName) -{ - std::ostringstream ss; - ss << "shader_bin/ps_" << assetName << ".cso"; - return ss.str(); -} - -bool AssetLoaderPixelShader::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto fileName = GetFileNameForAsset(assetName); - const auto file = searchPath->Open(fileName); - if (!file.IsOpen()) - return false; - - if (file.m_length % sizeof(uint32_t) != 0) - { - std::cerr << "Invalid pixel shader \"" << assetName << "\": Size must be dividable by " << sizeof(uint32_t) << "\n"; - return false; - } - - auto* pixelShader = memory->Create(); - pixelShader->name = memory->Dup(assetName.c_str()); - pixelShader->prog.loadDef.programSize = static_cast(static_cast(file.m_length) / sizeof(uint32_t)); - pixelShader->prog.loadDef.loadForRenderer = 0; - pixelShader->prog.ps = nullptr; - - auto* fileBuffer = memory->Alloc(pixelShader->prog.loadDef.programSize); - file.m_stream->read(reinterpret_cast(fileBuffer), static_cast(pixelShader->prog.loadDef.programSize) * sizeof(uint32_t)); - if (file.m_stream->gcount() != file.m_length) - return false; - - pixelShader->prog.loadDef.program = fileBuffer; - manager->AddAsset(assetName, pixelShader); - - return true; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderPixelShader.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderPixelShader.h deleted file mode 100644 index 3ac44c5c..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderPixelShader.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -#include - -namespace IW4 -{ - class AssetLoaderPixelShader final : public BasicAssetLoader - { - public: - _NODISCARD static std::string GetFileNameForAsset(const std::string& assetName); - - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderRawFile.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderRawFile.cpp deleted file mode 100644 index 20db51ad..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderRawFile.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "AssetLoaderRawFile.h" - -#include "Game/IW4/IW4.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include -#include -#include - -using namespace IW4; - -void* AssetLoaderRawFile::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* rawFile = memory->Create(); - memset(rawFile, 0, sizeof(RawFile)); - rawFile->name = memory->Dup(assetName.c_str()); - return rawFile; -} - -bool AssetLoaderRawFile::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderRawFile::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(assetName); - if (!file.IsOpen()) - return false; - - const auto uncompressedBuffer = std::make_unique(static_cast(file.m_length)); - file.m_stream->read(uncompressedBuffer.get(), file.m_length); - if (file.m_stream->gcount() != file.m_length) - return false; - - const auto compressionBufferSize = static_cast(file.m_length + COMPRESSED_BUFFER_SIZE_PADDING); - auto* compressedBuffer = memory->Alloc(compressionBufferSize); - - z_stream_s zs{}; - - zs.zalloc = Z_NULL; - zs.zfree = Z_NULL; - zs.opaque = Z_NULL; - zs.avail_in = static_cast(file.m_length); - zs.avail_out = compressionBufferSize; - zs.next_in = reinterpret_cast(uncompressedBuffer.get()); - zs.next_out = reinterpret_cast(compressedBuffer); - - int ret = deflateInit(&zs, Z_DEFAULT_COMPRESSION); - - if (ret != Z_OK) - { - throw std::runtime_error("Initializing deflate failed"); - } - - ret = deflate(&zs, Z_FINISH); - - if (ret != Z_STREAM_END) - { - std::cerr << "Deflate failed for loading rawfile \"" << assetName << "\"\n"; - deflateEnd(&zs); - return false; - } - - const auto compressedSize = compressionBufferSize - zs.avail_out; - - auto* rawFile = memory->Create(); - rawFile->name = memory->Dup(assetName.c_str()); - rawFile->compressedLen = static_cast(compressedSize); - rawFile->len = static_cast(file.m_length); - rawFile->data.compressedBuffer = static_cast(compressedBuffer); - - deflateEnd(&zs); - - manager->AddAsset(assetName, rawFile); - - return true; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderRawFile.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderRawFile.h deleted file mode 100644 index c8b558cc..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderRawFile.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderRawFile final : public BasicAssetLoader - { - static constexpr size_t COMPRESSED_BUFFER_SIZE_PADDING = 64; - - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderSndCurve.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderSndCurve.cpp deleted file mode 100644 index e21d5190..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderSndCurve.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "AssetLoaderSndCurve.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" -#include "Sound/SoundCurveLoader.h" - -#include -#include -#include - -using namespace IW4; - -void* AssetLoaderSndCurve::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* sndCurve = memory->Create(); - memset(sndCurve, 0, sizeof(SndCurve)); - sndCurve->filename = memory->Dup(assetName.c_str()); - return sndCurve; -} - -bool AssetLoaderSndCurve::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderSndCurve::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto sndCurveData = sound_curve::LoadSoundCurve(manager, assetName); - - if (!sndCurveData) - return false; - - if (sndCurveData->knots.size() > std::extent_v) - { - std::cerr << "Failed to load SndCurve \"" << assetName << "\": Too many knots (" << sndCurveData->knots.size() << ")\n"; - return false; - } - - auto* sndCurve = memory->Create(); - sndCurve->filename = memory->Dup(assetName.c_str()); - sndCurve->knotCount = static_cast(sndCurveData->knots.size()); - - for (auto i = 0u; i < std::extent_v; i++) - { - if (i < sndCurveData->knots.size()) - { - const auto& [x, y] = sndCurveData->knots[i]; - sndCurve->knots[i][0] = static_cast(x); - sndCurve->knots[i][1] = static_cast(y); - } - else - { - sndCurve->knots[i][0] = 0; - sndCurve->knots[i][1] = 0; - } - } - - manager->AddAsset(assetName, sndCurve); - - return true; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderSndCurve.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderSndCurve.h deleted file mode 100644 index 1d184ef1..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderSndCurve.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderSndCurve final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderSoundAliasList.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderSoundAliasList.cpp deleted file mode 100644 index 290ba1c9..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderSoundAliasList.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderSoundAliasList.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW4; - -void* AssetLoaderSoundAliasList::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* sndAliasList = memory->Create(); - memset(sndAliasList, 0, sizeof(snd_alias_list_t)); - sndAliasList->aliasName = memory->Dup(assetName.c_str()); - return sndAliasList; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderSoundAliasList.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderSoundAliasList.h deleted file mode 100644 index 86177d8b..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderSoundAliasList.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderSoundAliasList final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderStringTable.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderStringTable.cpp deleted file mode 100644 index 08121661..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderStringTable.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "AssetLoaderStringTable.h" - -#include "Csv/CsvStream.h" -#include "Game/IW4/CommonIW4.h" -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" -#include "StringTable/StringTableLoader.h" - -#include - -using namespace IW4; - -void* AssetLoaderStringTable::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* stringTable = memory->Create(); - memset(stringTable, 0, sizeof(StringTable)); - stringTable->name = memory->Dup(assetName.c_str()); - return stringTable; -} - -bool AssetLoaderStringTable::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderStringTable::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(assetName); - if (!file.IsOpen()) - return false; - - string_table::StringTableLoaderV2 loader; - auto* stringTable = loader.LoadFromStream(assetName, *memory, *file.m_stream); - - manager->AddAsset(assetName, stringTable); - - return true; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderStringTable.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderStringTable.h deleted file mode 100644 index 19fe5caa..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderStringTable.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderStringTable final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderStructuredDataDefSet.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderStructuredDataDefSet.cpp deleted file mode 100644 index ee5c8183..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderStructuredDataDefSet.cpp +++ /dev/null @@ -1,220 +0,0 @@ -#include "AssetLoaderStructuredDataDefSet.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" -#include "StructuredDataDef/StructuredDataDefReader.h" -#include "Utils/Alignment.h" - -#include - -using namespace IW4; - -void* AssetLoaderStructuredDataDefSet::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* structuredDataDefSet = memory->Create(); - memset(structuredDataDefSet, 0, sizeof(StructuredDataDefSet)); - structuredDataDefSet->name = memory->Dup(assetName.c_str()); - return structuredDataDefSet; -} - -bool AssetLoaderStructuredDataDefSet::CanLoadFromRaw() const -{ - return true; -} - -StructuredDataType AssetLoaderStructuredDataDefSet::ConvertType(CommonStructuredDataType inputType) -{ - switch (inputType.m_category) - { - case CommonStructuredDataTypeCategory::INT: - return {DATA_INT, {0}}; - case CommonStructuredDataTypeCategory::BYTE: - return {DATA_BYTE, {0}}; - case CommonStructuredDataTypeCategory::BOOL: - return {DATA_BOOL, {0}}; - case CommonStructuredDataTypeCategory::FLOAT: - return {DATA_FLOAT, {0}}; - case CommonStructuredDataTypeCategory::SHORT: - return {DATA_SHORT, {0}}; - case CommonStructuredDataTypeCategory::STRING: - return {DATA_STRING, {inputType.m_info.string_length}}; - case CommonStructuredDataTypeCategory::ENUM: - return {DATA_ENUM, {inputType.m_info.type_index}}; - case CommonStructuredDataTypeCategory::STRUCT: - return {DATA_STRUCT, {inputType.m_info.type_index}}; - case CommonStructuredDataTypeCategory::INDEXED_ARRAY: - return {DATA_INDEXED_ARRAY, {inputType.m_info.type_index}}; - case CommonStructuredDataTypeCategory::ENUM_ARRAY: - return {DATA_ENUM_ARRAY, {inputType.m_info.type_index}}; - case CommonStructuredDataTypeCategory::UNKNOWN: - default: - assert(false); - return {DATA_INT, {0}}; - } -} - -void AssetLoaderStructuredDataDefSet::ConvertEnum(StructuredDataEnum* outputEnum, CommonStructuredDataEnum* inputEnum, MemoryManager* memory) -{ - outputEnum->entryCount = static_cast(inputEnum->m_entries.size()); - if (inputEnum->m_reserved_entry_count <= 0) - outputEnum->reservedEntryCount = outputEnum->entryCount; - else - outputEnum->reservedEntryCount = inputEnum->m_reserved_entry_count; - - inputEnum->SortEntriesByName(); - if (!inputEnum->m_entries.empty()) - { - outputEnum->entries = memory->Alloc(inputEnum->m_entries.size()); - for (auto entryIndex = 0u; entryIndex < inputEnum->m_entries.size(); entryIndex++) - { - auto& outputEntry = outputEnum->entries[entryIndex]; - const auto& inputEntry = inputEnum->m_entries[entryIndex]; - - outputEntry.string = memory->Dup(inputEntry.m_name.c_str()); - outputEntry.index = static_cast(inputEntry.m_value); - } - } - else - outputEnum->entries = nullptr; -} - -void AssetLoaderStructuredDataDefSet::ConvertStruct(StructuredDataStruct* outputStruct, CommonStructuredDataStruct* inputStruct, MemoryManager* memory) -{ - outputStruct->size = static_cast(inputStruct->m_size_in_byte); - outputStruct->bitOffset = inputStruct->m_bit_offset; - - outputStruct->propertyCount = static_cast(inputStruct->m_properties.size()); - inputStruct->SortPropertiesByName(); - if (!inputStruct->m_properties.empty()) - { - outputStruct->properties = memory->Alloc(inputStruct->m_properties.size()); - for (auto propertyIndex = 0u; propertyIndex < inputStruct->m_properties.size(); propertyIndex++) - { - auto& outputProperty = outputStruct->properties[propertyIndex]; - const auto& inputProperty = inputStruct->m_properties[propertyIndex]; - - outputProperty.name = memory->Dup(inputProperty.m_name.c_str()); - outputProperty.type = ConvertType(inputProperty.m_type); - - if (outputProperty.type.type != DATA_BOOL) - { - assert(inputProperty.m_offset_in_bits % 8 == 0); - outputProperty.offset = inputProperty.m_offset_in_bits / 8; - } - else - outputProperty.offset = inputProperty.m_offset_in_bits; - } - } - else - outputStruct->properties = nullptr; -} - -void AssetLoaderStructuredDataDefSet::ConvertIndexedArray(StructuredDataIndexedArray* outputIndexedArray, - const CommonStructuredDataIndexedArray* inputIndexedArray, - MemoryManager* memory) -{ - outputIndexedArray->arraySize = static_cast(inputIndexedArray->m_element_count); - outputIndexedArray->elementType = ConvertType(inputIndexedArray->m_array_type); - outputIndexedArray->elementSize = utils::Align(inputIndexedArray->m_element_size_in_bits, 8u) / 8u; -} - -void AssetLoaderStructuredDataDefSet::ConvertEnumedArray(StructuredDataEnumedArray* outputEnumedArray, - const CommonStructuredDataEnumedArray* inputEnumedArray, - MemoryManager* memory) -{ - outputEnumedArray->enumIndex = static_cast(inputEnumedArray->m_enum_index); - outputEnumedArray->elementType = ConvertType(inputEnumedArray->m_array_type); - outputEnumedArray->elementSize = utils::Align(inputEnumedArray->m_element_size_in_bits, 8u) / 8u; -} - -void AssetLoaderStructuredDataDefSet::ConvertDef(StructuredDataDef* outputDef, const CommonStructuredDataDef* inputDef, MemoryManager* memory) -{ - outputDef->version = inputDef->m_version; - outputDef->formatChecksum = inputDef->m_checksum; - - outputDef->enumCount = static_cast(inputDef->m_enums.size()); - if (!inputDef->m_enums.empty()) - { - outputDef->enums = memory->Alloc(inputDef->m_enums.size()); - for (auto enumIndex = 0u; enumIndex < inputDef->m_enums.size(); enumIndex++) - ConvertEnum(&outputDef->enums[enumIndex], inputDef->m_enums[enumIndex].get(), memory); - } - else - outputDef->enums = nullptr; - - outputDef->structCount = static_cast(inputDef->m_structs.size()); - if (!inputDef->m_structs.empty()) - { - outputDef->structs = memory->Alloc(inputDef->m_structs.size()); - for (auto structIndex = 0u; structIndex < inputDef->m_structs.size(); structIndex++) - ConvertStruct(&outputDef->structs[structIndex], inputDef->m_structs[structIndex].get(), memory); - } - else - outputDef->structs = nullptr; - - outputDef->indexedArrayCount = static_cast(inputDef->m_indexed_arrays.size()); - if (!inputDef->m_indexed_arrays.empty()) - { - outputDef->indexedArrays = memory->Alloc(inputDef->m_indexed_arrays.size()); - for (auto indexedArrayIndex = 0u; indexedArrayIndex < inputDef->m_indexed_arrays.size(); indexedArrayIndex++) - ConvertIndexedArray(&outputDef->indexedArrays[indexedArrayIndex], &inputDef->m_indexed_arrays[indexedArrayIndex], memory); - } - else - outputDef->indexedArrays = nullptr; - - outputDef->enumedArrayCount = static_cast(inputDef->m_enumed_arrays.size()); - if (!inputDef->m_enumed_arrays.empty()) - { - outputDef->enumedArrays = memory->Alloc(inputDef->m_enumed_arrays.size()); - for (auto enumedArrayIndex = 0u; enumedArrayIndex < inputDef->m_enumed_arrays.size(); enumedArrayIndex++) - ConvertEnumedArray(&outputDef->enumedArrays[enumedArrayIndex], &inputDef->m_enumed_arrays[enumedArrayIndex], memory); - } - else - outputDef->enumedArrays = nullptr; - - outputDef->rootType = ConvertType(inputDef->m_root_type); - outputDef->size = inputDef->m_size_in_byte; -} - -StructuredDataDefSet* AssetLoaderStructuredDataDefSet::ConvertSet(const std::string& assetName, - const std::vector>& defs, - MemoryManager* memory) -{ - auto* set = memory->Create(); - set->name = memory->Dup(assetName.c_str()); - set->defCount = defs.size(); - set->defs = memory->Alloc(defs.size()); - - for (auto defIndex = 0u; defIndex < defs.size(); defIndex++) - ConvertDef(&set->defs[defIndex], defs[defIndex].get(), memory); - - return set; -} - -bool AssetLoaderStructuredDataDefSet::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(assetName); - if (!file.IsOpen()) - return false; - - StructuredDataDefReader reader(*file.m_stream, - assetName, - [searchPath](const std::string& filename, const std::string& sourceFile) -> std::unique_ptr - { - auto foundFileToInclude = searchPath->Open(filename); - if (!foundFileToInclude.IsOpen() || !foundFileToInclude.m_stream) - return nullptr; - - return std::move(foundFileToInclude.m_stream); - }); - - bool readingDefsSuccessful; - const auto defs = reader.ReadStructureDataDefs(readingDefsSuccessful); - - if (readingDefsSuccessful) - manager->AddAsset(assetName, ConvertSet(assetName, defs, memory)); - - return true; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderStructuredDataDefSet.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderStructuredDataDefSet.h deleted file mode 100644 index ef57fc8e..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderStructuredDataDefSet.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" -#include "StructuredDataDef/CommonStructuredDataDef.h" - -namespace IW4 -{ - class AssetLoaderStructuredDataDefSet final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - static StructuredDataType ConvertType(CommonStructuredDataType inputType); - static void ConvertEnum(StructuredDataEnum* outputEnum, CommonStructuredDataEnum* inputEnum, MemoryManager* memory); - static void ConvertStruct(StructuredDataStruct* outputStruct, CommonStructuredDataStruct* inputStruct, MemoryManager* memory); - static void ConvertIndexedArray(StructuredDataIndexedArray* outputIndexedArray, - const CommonStructuredDataIndexedArray* inputIndexedArray, - MemoryManager* memory); - static void - ConvertEnumedArray(StructuredDataEnumedArray* outputEnumedArray, const CommonStructuredDataEnumedArray* inputEnumedArray, MemoryManager* memory); - static void ConvertDef(StructuredDataDef* outputDef, const CommonStructuredDataDef* inputDef, MemoryManager* memory); - static StructuredDataDefSet* - ConvertSet(const std::string& assetName, const std::vector>& defs, MemoryManager* memory); - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.h deleted file mode 100644 index e66a9d67..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" -#include "StateMap/StateMapDefinition.h" -#include "Techset/TechniqueStateMapCache.h" -#include "Techset/TechsetDefinition.h" -#include "Techset/TechsetDefinitionCache.h" - -namespace IW4 -{ - class AssetLoaderTechniqueSet final : public BasicAssetLoader - { - static bool CreateTechsetFromDefinition(const std::string& assetName, - const techset::TechsetDefinition& definition, - ISearchPath* searchPath, - MemoryManager* memory, - IAssetLoadingManager* manager); - - public: - static std::string GetTechsetFileName(const std::string& techsetAssetName); - static std::string GetTechniqueFileName(const std::string& techniqueName); - static std::string GetStateMapFileName(const std::string& stateMapName); - - static techset::TechsetDefinition* - LoadTechsetDefinition(const std::string& assetName, ISearchPath* searchPath, techset::TechsetDefinitionCache* definitionCache); - static const state_map::StateMapDefinition* - LoadStateMapDefinition(const std::string& stateMapName, ISearchPath* searchPath, techset::TechniqueStateMapCache* stateMapCache); - - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTracer.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTracer.cpp deleted file mode 100644 index bbce11b8..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTracer.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderTracer.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW4; - -void* AssetLoaderTracer::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* tracer = memory->Create(); - memset(tracer, 0, sizeof(TracerDef)); - tracer->name = memory->Dup(assetName.c_str()); - return tracer; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTracer.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTracer.h deleted file mode 100644 index c501ad39..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTracer.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderTracer final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVehicle.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVehicle.cpp deleted file mode 100644 index 343bd890..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVehicle.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderVehicle.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW4; - -void* AssetLoaderVehicle::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* vehicle = memory->Create(); - memset(vehicle, 0, sizeof(VehicleDef)); - vehicle->name = memory->Dup(assetName.c_str()); - return vehicle; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVehicle.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVehicle.h deleted file mode 100644 index d260d853..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVehicle.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderVehicle final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVertexDecl.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVertexDecl.cpp deleted file mode 100644 index 8f616e49..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVertexDecl.cpp +++ /dev/null @@ -1,101 +0,0 @@ -#include "AssetLoaderVertexDecl.h" - -#include "Game/IW4/IW4.h" -#include "Game/IW4/TechsetConstantsIW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include - -using namespace IW4; - -void* AssetLoaderVertexDecl::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* vertexDecl = memory->Create(); - memset(vertexDecl, 0, sizeof(MaterialVertexDeclaration)); - vertexDecl->name = memory->Dup(assetName.c_str()); - return vertexDecl; -} - -bool AssetLoaderVertexDecl::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderVertexDecl::NextAbbreviation(const std::string& assetName, std::string& abbreviation, size_t& offset) -{ - if (offset >= assetName.size()) - return false; - - if (offset + 1 < assetName.size() && isdigit(assetName[offset + 1])) - { - abbreviation = std::string(assetName, offset, 2); - offset += 2; - } - else - { - abbreviation = std::string(assetName, offset, 1); - offset += 1; - } - - return true; -} - -bool AssetLoaderVertexDecl::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - MaterialVertexDeclaration decl{}; - - size_t currentOffset = 0u; - - if (!assetName.empty() && assetName[0] == ',') - currentOffset = 1u; - - std::string sourceAbbreviation; - while (NextAbbreviation(assetName, sourceAbbreviation, currentOffset)) - { - if (decl.streamCount >= std::extent_v) - { - std::cout << "Failed to add vertex decl stream. Too many abbreviations: " << assetName << "\n"; - return false; - } - - std::string destinationAbbreviation; - if (!NextAbbreviation(assetName, destinationAbbreviation, currentOffset)) - { - std::cout << "Failed to detect vertex decl destination abbreviation: " << assetName << "\n"; - return false; - } - - const auto foundSourceAbbreviation = std::ranges::find(materialStreamSourceAbbreviation, sourceAbbreviation); - if (foundSourceAbbreviation == std::end(materialStreamSourceAbbreviation)) - { - std::cout << "Unknown vertex decl source abbreviation: " << sourceAbbreviation << "\n"; - return false; - } - - const auto foundDestinationAbbreviation = std::ranges::find(materialStreamDestinationAbbreviation, destinationAbbreviation); - if (foundDestinationAbbreviation == std::end(materialStreamDestinationAbbreviation)) - { - std::cout << "Unknown vertex decl destination abbreviation: " << destinationAbbreviation << "\n"; - return false; - } - - const auto sourceIndex = static_cast(foundSourceAbbreviation - std::begin(materialStreamSourceAbbreviation)); - const auto destinationIndex = - static_cast(foundDestinationAbbreviation - std::begin(materialStreamDestinationAbbreviation)); - - decl.routing.data[decl.streamCount].source = sourceIndex; - decl.routing.data[decl.streamCount].dest = destinationIndex; - decl.hasOptionalSource = decl.hasOptionalSource || sourceIndex >= STREAM_SRC_OPTIONAL_BEGIN; - decl.streamCount++; - } - - decl.name = memory->Dup(assetName.c_str()); - - auto* allocatedDecl = memory->Create(decl); - - manager->AddAsset(assetName, allocatedDecl); - return true; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVertexDecl.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVertexDecl.h deleted file mode 100644 index 939c3a8c..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVertexDecl.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderVertexDecl final : public BasicAssetLoader - { - static bool NextAbbreviation(const std::string& assetName, std::string& abbreviation, size_t& offset); - - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVertexShader.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVertexShader.cpp deleted file mode 100644 index 07df2b0a..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVertexShader.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "AssetLoaderVertexShader.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include -#include -#include - -using namespace IW4; - -void* AssetLoaderVertexShader::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* vertexShader = memory->Create(); - memset(vertexShader, 0, sizeof(MaterialVertexShader)); - vertexShader->name = memory->Dup(assetName.c_str()); - return vertexShader; -} - -bool AssetLoaderVertexShader::CanLoadFromRaw() const -{ - return true; -} - -std::string AssetLoaderVertexShader::GetFileNameForAsset(const std::string& assetName) -{ - std::ostringstream ss; - ss << "shader_bin/vs_" << assetName << ".cso"; - return ss.str(); -} - -bool AssetLoaderVertexShader::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto fileName = GetFileNameForAsset(assetName); - const auto file = searchPath->Open(fileName); - if (!file.IsOpen()) - return false; - - if (file.m_length % sizeof(uint32_t) != 0) - { - std::cerr << "Invalid vertex shader \"" << assetName << "\": Size must be dividable by " << sizeof(uint32_t) << "\n"; - return false; - } - - auto* vertexShader = memory->Create(); - vertexShader->name = memory->Dup(assetName.c_str()); - vertexShader->prog.loadDef.programSize = static_cast(static_cast(file.m_length) / sizeof(uint32_t)); - vertexShader->prog.loadDef.loadForRenderer = 0; - vertexShader->prog.vs = nullptr; - - auto* fileBuffer = memory->Alloc(vertexShader->prog.loadDef.programSize); - file.m_stream->read(reinterpret_cast(fileBuffer), static_cast(vertexShader->prog.loadDef.programSize) * sizeof(uint32_t)); - if (file.m_stream->gcount() != file.m_length) - return false; - - vertexShader->prog.loadDef.program = fileBuffer; - manager->AddAsset(assetName, vertexShader); - - return true; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVertexShader.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVertexShader.h deleted file mode 100644 index 6a72596b..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderVertexShader.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderVertexShader final : public BasicAssetLoader - { - public: - _NODISCARD static std::string GetFileNameForAsset(const std::string& assetName); - - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderWeapon.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderWeapon.h deleted file mode 100644 index 51e69d8c..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderWeapon.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderWeapon final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromGdt() const override; - bool LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderXAnim.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderXAnim.cpp deleted file mode 100644 index 0f7ca8dc..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderXAnim.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderXAnim.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW4; - -void* AssetLoaderXAnim::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* anim = memory->Create(); - memset(anim, 0, sizeof(XAnimParts)); - anim->name = memory->Dup(assetName.c_str()); - return anim; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderXAnim.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderXAnim.h deleted file mode 100644 index a44bbdb7..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderXAnim.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderXAnim final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderXModel.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderXModel.cpp deleted file mode 100644 index b30da93d..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderXModel.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderXModel.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW4; - -void* AssetLoaderXModel::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* model = memory->Create(); - memset(model, 0, sizeof(XModel)); - model->name = memory->Dup(assetName.c_str()); - return model; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderXModel.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderXModel.h deleted file mode 100644 index 50af413d..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderXModel.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderXModel final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderXModelSurfs.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderXModelSurfs.cpp deleted file mode 100644 index 7adf87f9..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderXModelSurfs.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderXModelSurfs.h" - -#include "Game/IW4/IW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW4; - -void* AssetLoaderXModelSurfs::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* modelSurfs = memory->Create(); - memset(modelSurfs, 0, sizeof(XModelSurfs)); - modelSurfs->name = memory->Dup(assetName.c_str()); - return modelSurfs; -} diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderXModelSurfs.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderXModelSurfs.h deleted file mode 100644 index d7751ae3..00000000 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderXModelSurfs.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW4/IW4.h" -#include "SearchPath/ISearchPath.h" - -namespace IW4 -{ - class AssetLoaderXModelSurfs final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/InfoString/InfoStringToStructConverter.cpp b/src/ObjLoading/Game/IW4/InfoString/InfoStringToStructConverter.cpp index 4ac8d81a..112076a7 100644 --- a/src/ObjLoading/Game/IW4/InfoString/InfoStringToStructConverter.cpp +++ b/src/ObjLoading/Game/IW4/InfoString/InfoStringToStructConverter.cpp @@ -1,6 +1,7 @@ #include "InfoStringToStructConverter.h" #include +#include #include using namespace IW4; @@ -8,12 +9,12 @@ using namespace IW4; InfoStringToStructConverter::InfoStringToStructConverter(const InfoString& infoString, void* structure, ZoneScriptStrings& zoneScriptStrings, - MemoryManager* memory, - IAssetLoadingManager* manager, + MemoryManager& memory, + AssetCreationContext& context, + GenericAssetRegistration& registration, const cspField_t* fields, const size_t fieldCount) - : InfoStringToStructConverterBase(infoString, structure, zoneScriptStrings, memory), - m_loading_manager(manager), + : InfoStringToStructConverterBase(infoString, structure, zoneScriptStrings, memory, context, registration), m_fields(fields), m_field_count(fieldCount) { @@ -58,15 +59,15 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons return true; } - auto* fx = m_loading_manager->LoadDependency(value); + auto* fx = m_context.LoadDependency(value); if (fx == nullptr) { - std::cout << "Failed to load fx asset \"" << value << "\"\n"; + std::cerr << std::format("Failed to load fx asset \"{}\"\n", value); return false; } - m_dependencies.emplace(fx); + m_registration.AddDependency(fx); *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = fx->Asset(); return true; @@ -80,15 +81,15 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons return true; } - auto* xmodel = m_loading_manager->LoadDependency(value); + auto* xmodel = m_context.LoadDependency(value); if (xmodel == nullptr) { - std::cout << "Failed to load xmodel asset \"" << value << "\"\n"; + std::cerr << std::format("Failed to load xmodel asset \"{}\"\n", value); return false; } - m_dependencies.emplace(xmodel); + m_registration.AddDependency(xmodel); *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = xmodel->Asset(); return true; @@ -102,15 +103,15 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons return true; } - auto* material = m_loading_manager->LoadDependency(value); + auto* material = m_context.LoadDependency(value); if (material == nullptr) { - std::cout << "Failed to load material asset \"" << value << "\"\n"; + std::cerr << std::format("Failed to load material asset \"{}\"\n", value); return false; } - m_dependencies.emplace(material); + m_registration.AddDependency(material); *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = material->Asset(); return true; @@ -124,15 +125,15 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons return true; } - auto* tracer = m_loading_manager->LoadDependency(value); + auto* tracer = m_context.LoadDependency(value); if (tracer == nullptr) { - std::cout << "Failed to load tracer asset \"" << value << "\"\n"; + std::cerr << std::format("Failed to load tracer asset \"{}\"\n", value); return false; } - m_dependencies.emplace(tracer); + m_registration.AddDependency(tracer); *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = tracer->Asset(); return true; @@ -145,7 +146,7 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons if (endPtr != &value[value.size()]) { - std::cout << "Failed to parse value \"" << value << "\" as mph\n"; + std::cerr << std::format("Failed to parse value \"{}\" as mph\n", value); return false; } @@ -160,15 +161,15 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons return true; } - auto* collmap = m_loading_manager->LoadDependency(value); + auto* collmap = m_context.LoadDependency(value); if (collmap == nullptr) { - std::cout << "Failed to load collmap asset \"" << value << "\"\n"; + std::cerr << std::format("Failed to load collmap asset \"{}\"\n", value); return false; } - m_dependencies.emplace(collmap); + m_registration.AddDependency(collmap); *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = collmap->Asset(); return true; @@ -182,12 +183,12 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons return true; } - auto* name = m_memory->Alloc(); - name->soundName = m_memory->Dup(value.c_str()); + auto* name = m_memory.Alloc(); + name->soundName = m_memory.Dup(value.c_str()); reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset)->name = name; - m_indirect_asset_references.emplace(ASSET_TYPE_SOUND, value); + m_registration.AddIndirectAssetReference(m_context.LoadIndirectAssetReference(value)); return true; } diff --git a/src/ObjLoading/Game/IW4/InfoString/InfoStringToStructConverter.h b/src/ObjLoading/Game/IW4/InfoString/InfoStringToStructConverter.h index 341a1b56..624d63a9 100644 --- a/src/ObjLoading/Game/IW4/InfoString/InfoStringToStructConverter.h +++ b/src/ObjLoading/Game/IW4/InfoString/InfoStringToStructConverter.h @@ -1,5 +1,5 @@ #pragma once -#include "AssetLoading/IAssetLoadingManager.h" + #include "Game/IW4/IW4.h" #include "InfoString/InfoStringToStructConverterBase.h" @@ -7,22 +7,22 @@ namespace IW4 { class InfoStringToStructConverter : public InfoStringToStructConverterBase { - protected: - IAssetLoadingManager* m_loading_manager; - const cspField_t* m_fields; - size_t m_field_count; - - virtual bool ConvertExtensionField(const cspField_t& field, const std::string& value) = 0; - bool ConvertBaseField(const cspField_t& field, const std::string& value); - public: InfoStringToStructConverter(const InfoString& infoString, void* structure, ZoneScriptStrings& zoneScriptStrings, - MemoryManager* memory, - IAssetLoadingManager* manager, + MemoryManager& memory, + AssetCreationContext& context, + GenericAssetRegistration& registration, const cspField_t* fields, size_t fieldCount); bool Convert() override; + + protected: + virtual bool ConvertExtensionField(const cspField_t& field, const std::string& value) = 0; + bool ConvertBaseField(const cspField_t& field, const std::string& value); + + const cspField_t* m_fields; + size_t m_field_count; }; } // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/Leaderboard/LoaderLeaderboardIW4.cpp b/src/ObjLoading/Game/IW4/Leaderboard/LoaderLeaderboardIW4.cpp new file mode 100644 index 00000000..550472dc --- /dev/null +++ b/src/ObjLoading/Game/IW4/Leaderboard/LoaderLeaderboardIW4.cpp @@ -0,0 +1,53 @@ +#include "LoaderLeaderboardIW4.h" + +#include "Game/IW4/IW4.h" +#include "JsonLeaderboardDefLoader.h" + +#include +#include +#include + +using namespace IW4; + +namespace +{ + class LeaderboardLoader final : public AssetCreator + { + public: + LeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto file = m_search_path.Open(std::format("leaderboards/{}.json", assetName)); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + auto* leaderboardDef = m_memory.Alloc(); + leaderboardDef->name = m_memory.Dup(assetName.c_str()); + + if (!LoadLeaderboardAsJson(*file.m_stream, *leaderboardDef, &m_memory)) + { + std::cerr << std::format("Failed to load leaderboard \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + return AssetCreationResult::Success(context.AddAsset(assetName, leaderboardDef)); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace IW4 +{ + std::unique_ptr> CreateLeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/Leaderboard/LoaderLeaderboardIW4.h b/src/ObjLoading/Game/IW4/Leaderboard/LoaderLeaderboardIW4.h new file mode 100644 index 00000000..3f0a86ce --- /dev/null +++ b/src/ObjLoading/Game/IW4/Leaderboard/LoaderLeaderboardIW4.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW4/IW4.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW4 +{ + std::unique_ptr> CreateLeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/LightDef/LoaderLightDefIW4.cpp b/src/ObjLoading/Game/IW4/LightDef/LoaderLightDefIW4.cpp new file mode 100644 index 00000000..0563554e --- /dev/null +++ b/src/ObjLoading/Game/IW4/LightDef/LoaderLightDefIW4.cpp @@ -0,0 +1,80 @@ +#include "LoaderLightDefIW4.h" + +#include "Game/IW4/IW4.h" + +#include +#include +#include + +using namespace IW4; + +namespace +{ + constexpr auto MAX_IMAGE_NAME_SIZE = 0x800; + + class LoaderLightDef final : public AssetCreator + { + public: + LoaderLightDef(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto filename = GetAssetFilename(assetName); + const auto file = m_search_path.Open(filename); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + const auto imageNameSize = file.m_length - sizeof(char) - sizeof(char); + if (imageNameSize < 0 || imageNameSize > MAX_IMAGE_NAME_SIZE) + return AssetCreationResult::Failure(); + + auto* lightDef = m_memory.Alloc(); + lightDef->name = m_memory.Dup(assetName.c_str()); + + AssetRegistration registration(assetName, lightDef); + + std::string imageName(static_cast(imageNameSize), '\0'); + + int8_t samplerState; + int8_t lmapLookupStart; + file.m_stream->read(reinterpret_cast(&samplerState), sizeof(int8_t)); + file.m_stream->read(&imageName[0], static_cast(imageNameSize)); + file.m_stream->read(reinterpret_cast(&lmapLookupStart), sizeof(int8_t)); + + auto* imageDependency = context.LoadDependency(imageName); + if (!imageDependency) + { + std::cerr << std::format("Could not load GfxLightDef \"{}\" due to missing image \"{}\"\n", assetName, imageName); + return AssetCreationResult::Failure(); + } + registration.AddDependency(imageDependency); + + lightDef->attenuation.samplerState = samplerState; + lightDef->attenuation.image = imageDependency->Asset(); + lightDef->lmapLookupStart = static_cast(static_cast(lmapLookupStart)); + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); + } + + private: + std::string GetAssetFilename(const std::string& assetName) + { + return std::format("lights/{}", assetName); + } + + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace IW4 +{ + std::unique_ptr> CreateLightDefLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/LightDef/LoaderLightDefIW4.h b/src/ObjLoading/Game/IW4/LightDef/LoaderLightDefIW4.h new file mode 100644 index 00000000..92eec1bb --- /dev/null +++ b/src/ObjLoading/Game/IW4/LightDef/LoaderLightDefIW4.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW4/IW4.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW4 +{ + std::unique_ptr> CreateLightDefLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/Localize/LoaderLocalizeIW4.cpp b/src/ObjLoading/Game/IW4/Localize/LoaderLocalizeIW4.cpp new file mode 100644 index 00000000..795939ed --- /dev/null +++ b/src/ObjLoading/Game/IW4/Localize/LoaderLocalizeIW4.cpp @@ -0,0 +1,44 @@ +#include "LoaderLocalizeIW4.h" + +#include "Localize/CommonLocalizeLoader.h" + +using namespace IW4; + +namespace +{ + class LocalizeLoader final : public AssetCreator, public CommonLocalizeLoader + { + public: + LocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : CommonLocalizeLoader(searchPath, zone), + m_memory(memory) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + return CreateLocalizeAsset(assetName, context); + } + + protected: + AssetCreationResult CreateAssetFromCommonAsset(const CommonLocalizeEntry& localizeEntry, AssetCreationContext& context) override + { + auto* asset = m_memory.Alloc(); + asset->name = m_memory.Dup(localizeEntry.m_key.c_str()); + asset->value = m_memory.Dup(localizeEntry.m_value.c_str()); + + return AssetCreationResult::Success(context.AddAsset(localizeEntry.m_key, asset)); + } + + private: + MemoryManager& m_memory; + }; +} // namespace + +namespace IW4 +{ + std::unique_ptr> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + { + return std::make_unique(memory, searchPath, zone); + } +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/Localize/LoaderLocalizeIW4.h b/src/ObjLoading/Game/IW4/Localize/LoaderLocalizeIW4.h new file mode 100644 index 00000000..c7ae0d9d --- /dev/null +++ b/src/ObjLoading/Game/IW4/Localize/LoaderLocalizeIW4.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW4/IW4.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" +#include "Zone/Zone.h" + +#include + +namespace IW4 +{ + std::unique_ptr> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMaterial.cpp b/src/ObjLoading/Game/IW4/Material/LoaderMaterialIW4.cpp similarity index 86% rename from src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMaterial.cpp rename to src/ObjLoading/Game/IW4/Material/LoaderMaterialIW4.cpp index 02c81a66..51363e80 100644 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMaterial.cpp +++ b/src/ObjLoading/Game/IW4/Material/LoaderMaterialIW4.cpp @@ -1,26 +1,29 @@ -#include "AssetLoaderMaterial.h" +#include "LoaderMaterialIW4.h" -#include "AssetLoaderTechniqueSet.h" -#include "AssetLoading/AbstractGdtEntryReader.h" #include "Game/IW4/CommonIW4.h" #include "Game/IW4/IW4.h" #include "Game/IW4/MaterialConstantsIW4.h" #include "Game/IW4/ObjConstantsIW4.h" +#include "Game/IW4/Techset/LoaderTechsetIW4.h" #include "Game/IW4/TechsetConstantsIW4.h" +#include "Gdt/AbstractGdtEntryReader.h" #include "ObjLoading.h" #include "Pool/GlobalAssetPool.h" #include "StateMap/StateMapFromTechniqueExtractor.h" #include "StateMap/StateMapHandler.h" #include "Techset/TechniqueFileReader.h" +#include "Techset/TechniqueStateMapCache.h" +#include "Techset/TechsetDefinitionCache.h" #include #include +#include #include #include using namespace IW4; -namespace IW4 +namespace { class SkipMaterialException final : public std::exception { @@ -29,39 +32,33 @@ namespace IW4 class MaterialGdtLoader : AbstractGdtEntryReader { public: - MaterialGdtLoader(const GdtEntry& entry, MemoryManager* memory, ISearchPath* searchPath, IAssetLoadingManager* manager) + MaterialGdtLoader(const GdtEntry& entry, + Material& material, + MemoryManager& memory, + ISearchPath& searchPath, + AssetCreationContext& context, + AssetRegistration& registration) : AbstractGdtEntryReader(entry), + m_material(material), m_memory(memory), m_search_path(searchPath), - m_manager(manager), - m_state_map_cache(manager->GetAssetLoadingContext()->GetZoneAssetLoaderState()), - m_material(nullptr), - m_base_state_bits{} + m_context(context), + m_registration(registration), + m_state_map_cache(context.GetZoneAssetCreationState()), + m_base_state_bits{}, + m_techset_creator(CreateTechsetLoader(memory, searchPath)) { } bool Load() { - m_material = m_memory->Create(); - memset(m_material, 0, sizeof(Material)); - - m_material->info.name = m_memory->Dup(m_entry.m_name.c_str()); material_template(); FinalizeMaterial(); + return true; } - _NODISCARD Material* GetMaterial() const - { - return m_material; - } - - _NODISCARD std::vector GetDependencies() - { - return std::move(m_dependencies); - } - private: void material_template() { @@ -120,11 +117,7 @@ namespace IW4 custom_template(); } else - { - std::ostringstream ss; - ss << "Unknown material type: \"" << materialType << "\""; - throw GdtReadingException(ss.str()); - } + throw GdtReadingException(std::format("Unknown material type: \"{}\"", materialType)); } void mtl_phong_template() @@ -253,7 +246,7 @@ namespace IW4 else throw GdtReadingException("ColorMap may not be blank in particle cloud materials"); - std::cout << "Using particlecloud for \"" << m_material->info.name << "\"\n"; + std::cout << std::format("Using particlecloud for \"{}\"\n", m_material.info.name); } void mtl_tools_template() @@ -332,11 +325,7 @@ namespace IW4 mtl_splatter_template(); } else - { - std::ostringstream ss; - ss << "Unknown custom template: \"" << customTemplate << "\""; - throw GdtReadingException(ss.str()); - } + throw GdtReadingException(std::format("Unknown custom template: \"{}\"", customTemplate)); } void mtl_custom_template() @@ -584,11 +573,7 @@ namespace IW4 const auto sortKeyNum = strtoul(sortKey.c_str(), &endPtr, 10); if (endPtr != &sortKey[sortKey.size()]) - { - std::ostringstream ss; - ss << "Invalid sort value: \"" << sortKey << "\""; - throw GdtReadingException(ss.str()); - } + throw GdtReadingException(std::format("Invalid sort value: \"{}\"", sortKey)); SetSort(static_cast(sortKeyNum)); } @@ -628,11 +613,7 @@ namespace IW4 else if (alphaTest == GDT_ALPHA_TEST_GT0) // TODO: This is not available for IW3 SetAlphaTest(AlphaTest_e::GT0); else - { - std::ostringstream ss; - ss << "Invalid alphatest value: \"" << alphaTest << "\""; - throw GdtReadingException(ss.str()); - } + throw GdtReadingException(std::format("Invalid alphatest value: \"{}\"", alphaTest)); } void blendfunc_template() @@ -682,9 +663,7 @@ namespace IW4 } else { - std::ostringstream ss; - ss << "Invalid blendfunc value: \"" << blendFunc << "\""; - throw GdtReadingException(ss.str()); + throw GdtReadingException(std::format("Invalid blendfunc value: \"{}\"", blendFunc)); } } @@ -740,9 +719,7 @@ namespace IW4 SetDepthWrite(false); else { - std::ostringstream ss; - ss << "Invalid depthWrite blendFunc value: \"" << blendFunc << "\""; - throw GdtReadingException(ss.str()); + throw GdtReadingException(std::format("Invalid depthWrite blendFunc value: \"{}\"", blendFunc)); } } @@ -807,28 +784,21 @@ namespace IW4 void SetTechniqueSet(const std::string& techsetName) { - auto* techset = m_manager->LoadDependency(techsetName); + auto* techset = m_context.LoadDependency(techsetName); if (techset == nullptr) - { - std::ostringstream ss; - ss << "Could not load techset: \"" << techsetName << "\""; - throw GdtReadingException(ss.str()); - } + throw GdtReadingException(std::format("Could not load techset: \"{}\"", techsetName)); - m_dependencies.push_back(techset); - m_material->techniqueSet = techset->Asset(); + m_registration.AddDependency(techset); + m_material.techniqueSet = techset->Asset(); - auto* loadingContext = m_manager->GetAssetLoadingContext(); - auto& searchPath = loadingContext->m_raw_search_path; - auto* definitionCache = loadingContext->GetZoneAssetLoaderState(); + auto& definitionCache = m_context.GetZoneAssetCreationState(); - const auto* techsetDefinition = AssetLoaderTechniqueSet::LoadTechsetDefinition(techsetName, &searchPath, definitionCache); + bool failure = false; + const auto* techsetDefinition = m_techset_creator->LoadTechsetDefinition(techsetName, m_context, failure); if (techsetDefinition == nullptr) { - std::ostringstream ss; - ss << "Could not find techset definition for: \"" << techsetName << "\""; - throw GdtReadingException(ss.str()); + throw GdtReadingException(std::format("Could not find techset definition for: \"{}\"", techsetName)); } SetTechniqueSetStateBits(techsetDefinition); @@ -852,17 +822,17 @@ namespace IW4 if (foundStateBits != m_state_bits.end()) { - m_material->stateBitsEntry[i] = static_cast(foundStateBits - m_state_bits.begin()); + m_material.stateBitsEntry[i] = static_cast(foundStateBits - m_state_bits.begin()); } else { - m_material->stateBitsEntry[i] = static_cast(m_state_bits.size()); + m_material.stateBitsEntry[i] = static_cast(m_state_bits.size()); m_state_bits.push_back(stateBitsForTechnique); } } else { - m_material->stateBitsEntry[i] = std::numeric_limits::max(); + m_material.stateBitsEntry[i] = std::numeric_limits::max(); } } } @@ -885,12 +855,12 @@ namespace IW4 _NODISCARD const state_map::StateMapDefinition* GetStateMapForTechnique(const std::string& techniqueName) const { - const auto* preloadedStateMap = m_state_map_cache->GetStateMapForTechnique(techniqueName); + const auto* preloadedStateMap = m_state_map_cache.GetStateMapForTechnique(techniqueName); if (preloadedStateMap) return preloadedStateMap; - const auto techniqueFileName = AssetLoaderTechniqueSet::GetTechniqueFileName(techniqueName); - const auto file = m_search_path->Open(techniqueFileName); + const auto techniqueFileName = GetTechniqueFileName(techniqueName); + const auto file = m_search_path.Open(techniqueFileName); if (!file.IsOpen()) return nullptr; @@ -898,13 +868,13 @@ namespace IW4 const techset::TechniqueFileReader reader(*file.m_stream, techniqueFileName, &extractor); if (!reader.ReadTechniqueDefinition()) { - m_state_map_cache->SetTechniqueUsesStateMap(techniqueName, nullptr); + m_state_map_cache.SetTechniqueUsesStateMap(techniqueName, nullptr); return nullptr; } const auto stateMapName = extractor.RetrieveStateMap(); - const auto* loadedStateMap = AssetLoaderTechniqueSet::LoadStateMapDefinition(stateMapName, m_search_path, m_state_map_cache); - m_state_map_cache->SetTechniqueUsesStateMap(techniqueName, loadedStateMap); + const auto* loadedStateMap = m_techset_creator->LoadStateMapDefinition(stateMapName, m_context); + m_state_map_cache.SetTechniqueUsesStateMap(techniqueName, loadedStateMap); return loadedStateMap; } @@ -924,18 +894,18 @@ namespace IW4 std::string tempName; if (techsetDefinition->GetTechniqueByIndex(TECHNIQUE_LIT, tempName)) { - if (m_material->info.sortKey >= SORTKEY_TRANS_START) - m_material->cameraRegion = CAMERA_REGION_LIT_TRANS; + if (m_material.info.sortKey >= SORTKEY_TRANS_START) + m_material.cameraRegion = CAMERA_REGION_LIT_TRANS; else - m_material->cameraRegion = CAMERA_REGION_LIT_OPAQUE; + m_material.cameraRegion = CAMERA_REGION_LIT_OPAQUE; } else if (techsetDefinition->GetTechniqueByIndex(TECHNIQUE_EMISSIVE, tempName)) { - m_material->cameraRegion = CAMERA_REGION_EMISSIVE; + m_material.cameraRegion = CAMERA_REGION_EMISSIVE; } else { - m_material->cameraRegion = CAMERA_REGION_NONE; + m_material.cameraRegion = CAMERA_REGION_NONE; } } @@ -993,16 +963,12 @@ namespace IW4 break; } - auto* image = m_manager->LoadDependency(textureName); + auto* image = m_context.LoadDependency(textureName); if (image == nullptr) - { - std::ostringstream ss; - ss << "Could not load image: \"" << textureName << "\""; - throw GdtReadingException(ss.str()); - } + throw GdtReadingException(std::format("Could not load image: \"{}\"", textureName)); - m_dependencies.push_back(image); + m_registration.AddDependency(image); textureDef.u.image = image->Asset(); m_textures.push_back(textureDef); @@ -1023,13 +989,13 @@ namespace IW4 void SetSort(const unsigned char sort) const { - m_material->info.sortKey = sort; + m_material.info.sortKey = sort; } void SetTextureAtlas(const unsigned char rowCount, const unsigned char columnCount) const { - m_material->info.textureAtlasRowCount = rowCount; - m_material->info.textureAtlasColumnCount = columnCount; + m_material.info.textureAtlasRowCount = rowCount; + m_material.info.textureAtlasColumnCount = columnCount; } void SetAlphaTest(const AlphaTest_e alphaTest) @@ -1054,9 +1020,7 @@ namespace IW4 case AlphaTest_e::UNKNOWN: default: - std::ostringstream ss; - ss << "Unknown alphatest value: \"" << static_cast(alphaTest) << "\""; - throw GdtReadingException(ss.str()); + throw GdtReadingException(std::format("Unknown alphatest value: \"{}\"", static_cast(alphaTest))); } } @@ -1113,9 +1077,7 @@ namespace IW4 if (colorWriteRed != colorWriteGreen || colorWriteRed != colorWriteBlue) { - std::ostringstream ss; - ss << "Invalid ColorWrite values: values for rgb must match"; - throw GdtReadingException(ss.str()); + throw GdtReadingException("Invalid ColorWrite values: values for rgb must match"); } m_base_state_bits.loadBits[0] &= ~GFXS0_COLORWRITE_MASK; @@ -1286,38 +1248,38 @@ namespace IW4 { if (!m_textures.empty()) { - m_material->textureTable = m_memory->Alloc(m_textures.size()); - m_material->textureCount = static_cast(m_textures.size()); - memcpy(m_material->textureTable, m_textures.data(), sizeof(MaterialTextureDef) * m_textures.size()); + m_material.textureTable = m_memory.Alloc(m_textures.size()); + m_material.textureCount = static_cast(m_textures.size()); + std::memcpy(m_material.textureTable, m_textures.data(), sizeof(MaterialTextureDef) * m_textures.size()); } else { - m_material->textureTable = nullptr; - m_material->textureCount = 0u; + m_material.textureTable = nullptr; + m_material.textureCount = 0u; } if (!m_constants.empty()) { - m_material->constantTable = m_memory->Alloc(m_constants.size()); - m_material->constantCount = static_cast(m_constants.size()); - memcpy(m_material->constantTable, m_constants.data(), sizeof(MaterialConstantDef) * m_constants.size()); + m_material.constantTable = m_memory.Alloc(m_constants.size()); + m_material.constantCount = static_cast(m_constants.size()); + std::memcpy(m_material.constantTable, m_constants.data(), sizeof(MaterialConstantDef) * m_constants.size()); } else { - m_material->constantTable = nullptr; - m_material->constantCount = 0u; + m_material.constantTable = nullptr; + m_material.constantCount = 0u; } if (!m_state_bits.empty()) { - m_material->stateBitsTable = m_memory->Alloc(m_state_bits.size()); - m_material->stateBitsCount = static_cast(m_state_bits.size()); - memcpy(m_material->stateBitsTable, m_state_bits.data(), sizeof(GfxStateBits) * m_state_bits.size()); + m_material.stateBitsTable = m_memory.Alloc(m_state_bits.size()); + m_material.stateBitsCount = static_cast(m_state_bits.size()); + std::memcpy(m_material.stateBitsTable, m_state_bits.data(), sizeof(GfxStateBits) * m_state_bits.size()); } else { - m_material->stateBitsTable = nullptr; - m_material->stateBitsCount = 0u; + m_material.stateBitsTable = nullptr; + m_material.stateBitsCount = 0u; } } @@ -1330,9 +1292,7 @@ namespace IW4 return i; } - std::ostringstream ss; - ss << "Unknown " << propertyName << " value: \"" << value << "\""; - throw GdtReadingException(ss.str()); + throw GdtReadingException(std::format("Unknown {} value: \"{}\"", propertyName, value)); } template T ReadEnumProperty(const std::string& propertyName, const char** validValuesArray, const size_t validValuesArraySize) const @@ -1340,59 +1300,74 @@ namespace IW4 return static_cast(GetIndexForString(propertyName, ReadStringProperty(propertyName), validValuesArray, validValuesArraySize)); } - MemoryManager* m_memory; - ISearchPath* m_search_path; - IAssetLoadingManager* m_manager; - techset::TechniqueStateMapCache* m_state_map_cache; - std::unordered_map m_state_bits_per_state_map; - std::vector m_dependencies; + Material& m_material; + MemoryManager& m_memory; + ISearchPath& m_search_path; + AssetCreationContext& m_context; + AssetRegistration& m_registration; + + techset::TechniqueStateMapCache& m_state_map_cache; + std::unordered_map m_state_bits_per_state_map; - Material* m_material; GfxStateBits m_base_state_bits; std::vector m_state_bits; std::vector m_textures; std::vector m_constants; + + std::unique_ptr m_techset_creator; }; -} // namespace IW4 -void* AssetLoaderMaterial::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* material = memory->Create(); - memset(material, 0, sizeof(Material)); - material->info.name = memory->Dup(assetName.c_str()); - return material; -} - -bool AssetLoaderMaterial::CanLoadFromGdt() const -{ - return true; -} - -bool AssetLoaderMaterial::LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto* entry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_MATERIAL, assetName); - if (!entry) - return false; - - MaterialGdtLoader loader(*entry, memory, &manager->GetAssetLoadingContext()->m_raw_search_path, manager); - - try + class MaterialLoader final : public AssetCreator { - if (loader.Load()) + public: + MaterialLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt) + : m_memory(memory), + m_search_path(m_search_path), + m_gdt(gdt) { - manager->AddAsset(assetName, loader.GetMaterial(), loader.GetDependencies()); } - } - catch (const SkipMaterialException&) - { - return false; - } - catch (const GdtReadingException& e) - { - std::cerr << "Error while trying to load material from gdt: " << e.what() << " @ GdtEntry \"" << entry->m_name << "\"\n"; - return false; - } - return true; -} + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto* entry = m_gdt.GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_MATERIAL, assetName); + if (!entry) + return AssetCreationResult::NoAction(); + + auto* material = m_memory.Alloc(); + material->info.name = m_memory.Dup(assetName.c_str()); + + AssetRegistration registration(assetName, material); + + MaterialGdtLoader loader(*entry, *material, m_memory, m_search_path, context, registration); + + try + { + if (loader.Load()) + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); + } + catch (const SkipMaterialException&) + { + return AssetCreationResult::NoAction(); + } + catch (const GdtReadingException& e) + { + std::cerr << std::format("Error while trying to load material from gdt: {} @ GdtEntry \"{}\"\n", e.what(), entry->m_name); + } + + return AssetCreationResult::Failure(); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + IGdtQueryable& m_gdt; + }; +} // namespace + +namespace IW4 +{ + std::unique_ptr> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt) + { + return std::make_unique(memory, searchPath, gdt); + } +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/Material/LoaderMaterialIW4.h b/src/ObjLoading/Game/IW4/Material/LoaderMaterialIW4.h new file mode 100644 index 00000000..04b975e0 --- /dev/null +++ b/src/ObjLoading/Game/IW4/Material/LoaderMaterialIW4.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW4/IW4.h" +#include "Gdt/IGdtQueryable.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +namespace IW4 +{ + std::unique_ptr> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt); +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/Menu/LoaderMenuListIW4.cpp b/src/ObjLoading/Game/IW4/Menu/LoaderMenuListIW4.cpp new file mode 100644 index 00000000..6dc661d9 --- /dev/null +++ b/src/ObjLoading/Game/IW4/Menu/LoaderMenuListIW4.cpp @@ -0,0 +1,220 @@ +#include "LoaderMenuListIW4.h" + +#include "Game/IW4/IW4.h" +#include "Game/IW4/Menu/MenuConversionZoneStateIW4.h" +#include "Game/IW4/Menu/MenuConverterIW4.h" +#include "ObjLoading.h" +#include "Parsing/Menu/MenuFileReader.h" + +#include +#include +#include + +using namespace IW4; + +namespace +{ + class MenuListLoader final : public AssetCreator + { + public: + MenuListLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + std::vector menus; + AssetRegistration registration(assetName); + + auto& zoneState = context.GetZoneAssetCreationState(); + auto& conversionState = context.GetZoneAssetCreationState(); + + std::deque menuLoadQueue; + const auto alreadyLoadedMenuListFileMenus = conversionState.m_menus_by_filename.find(assetName); + + if (alreadyLoadedMenuListFileMenus == conversionState.m_menus_by_filename.end()) + { + const auto file = m_search_path.Open(assetName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + const auto menuListResult = ParseMenuFile(*file.m_stream, assetName, zoneState); + if (menuListResult) + { + ProcessParsedResults(assetName, context, *menuListResult, zoneState, conversionState, menus, registration); + + for (const auto& menuToLoad : menuListResult->m_menus_to_load) + menuLoadQueue.emplace_back(menuToLoad); + + zoneState.AddMenusToLoad(assetName, std::move(menuListResult->m_menus_to_load)); + } + else + return AssetCreationResult::Failure(); + } + + while (!menuLoadQueue.empty()) + { + const auto& menuFileToLoad = menuLoadQueue.front(); + + LoadMenuFileFromQueue(menuFileToLoad, context, zoneState, conversionState, menus, registration); + + menuLoadQueue.pop_front(); + } + + auto* menuListAsset = m_memory.Create(); + menuListAsset->name = m_memory.Dup(assetName.c_str()); + registration.SetAsset(menuListAsset); + + CreateMenuListAsset(*menuListAsset, menus); + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); + } + + void FinalizeZone(AssetCreationContext& context) override + { + context.GetZoneAssetCreationState().FinalizeSupportingData(); + } + + private: + bool LoadMenuFileFromQueue(const std::string& menuFilePath, + AssetCreationContext& context, + menu::MenuAssetZoneState& zoneState, + MenuConversionZoneState& conversionState, + std::vector& menus, + AssetRegistration& registration) + { + const auto alreadyLoadedMenuFile = conversionState.m_menus_by_filename.find(menuFilePath); + if (alreadyLoadedMenuFile != conversionState.m_menus_by_filename.end()) + { + std::cout << std::format("Already loaded \"{}\", skipping\n", menuFilePath); + for (auto* menu : alreadyLoadedMenuFile->second) + { + menus.emplace_back(menu->Asset()); + registration.AddDependency(menu); + } + return true; + } + + const auto file = m_search_path.Open(menuFilePath); + if (!file.IsOpen()) + { + std::cerr << std::format("Could not open menu file \"{}\"\n", menuFilePath); + return false; + } + + const auto menuFileResult = ParseMenuFile(*file.m_stream, menuFilePath, zoneState); + if (menuFileResult) + { + ProcessParsedResults(menuFilePath, context, *menuFileResult, zoneState, conversionState, menus, registration); + if (!menuFileResult->m_menus_to_load.empty()) + std::cout << std::format("WARNING: Menu file has menus to load even though it is not a menu list, ignoring: \"{}\"\n", menuFilePath); + + return true; + } + else + std::cerr << std::format("Could not read menu file \"{}\"\n", menuFilePath); + + return false; + } + + bool ProcessParsedResults(const std::string& fileName, + AssetCreationContext& context, + menu::ParsingResult& parsingResult, + menu::MenuAssetZoneState& zoneState, + MenuConversionZoneState& conversionState, + std::vector& menus, + AssetRegistration& registration) + { + const auto menuCount = parsingResult.m_menus.size(); + const auto functionCount = parsingResult.m_functions.size(); + const auto menuLoadCount = parsingResult.m_menus_to_load.size(); + auto totalItemCount = 0u; + for (const auto& menu : parsingResult.m_menus) + totalItemCount += menu->m_items.size(); + + std::cout << std::format("Successfully read menu file \"{}\" ({} loads, {} menus, {} functions, {} items)\n", + fileName, + menuLoadCount, + menuCount, + functionCount, + totalItemCount); + + // Add all functions to the zone state to make them available for all menus to be converted + for (auto& function : parsingResult.m_functions) + zoneState.AddFunction(std::move(function)); + + // Prepare a list of all menus of this file + std::vector*> allMenusOfFile; + allMenusOfFile.reserve(parsingResult.m_menus.size()); + + // Convert all menus and add them as assets + for (auto& commonMenu : parsingResult.m_menus) + { + auto converter = IMenuConverter::Create(ObjLoading::Configuration.MenuNoOptimization, m_search_path, m_memory, context); + + auto* menuAsset = m_memory.Alloc(); + AssetRegistration menuRegistration(commonMenu->m_name, menuAsset); + + converter->ConvertMenu(*commonMenu, *menuAsset, menuRegistration); + if (menuAsset == nullptr) + { + std::cerr << std::format("Failed to convert menu file \"{}\"\n", commonMenu->m_name); + return false; + } + + menus.emplace_back(menuAsset); + auto* menuAssetInfo = context.AddAsset(std::move(menuRegistration)); + + if (menuAssetInfo) + { + allMenusOfFile.emplace_back(menuAssetInfo); + registration.AddDependency(menuAssetInfo); + } + + zoneState.AddMenu(std::move(commonMenu)); + } + + // Register this file with all loaded menus + conversionState.AddLoadedFile(fileName, std::move(allMenusOfFile)); + + return true; + } + + void CreateMenuListAsset(MenuList& menuList, const std::vector& menus) + { + menuList.menuCount = static_cast(menus.size()); + + if (menuList.menuCount > 0) + { + menuList.menus = m_memory.Alloc(menuList.menuCount); + for (auto i = 0; i < menuList.menuCount; i++) + menuList.menus[i] = menus[i]; + } + else + menuList.menus = nullptr; + } + + std::unique_ptr ParseMenuFile(std::istream& stream, const std::string& menuFileName, const menu::MenuAssetZoneState& zoneState) + { + menu::MenuFileReader reader(stream, menuFileName, menu::FeatureLevel::IW4, m_search_path); + + reader.IncludeZoneState(zoneState); + reader.SetPermissiveMode(ObjLoading::Configuration.MenuPermissiveParsing); + + return reader.ReadMenuFile(); + } + + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace IW4 +{ + std::unique_ptr> CreateMenuListLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/Menu/LoaderMenuListIW4.h b/src/ObjLoading/Game/IW4/Menu/LoaderMenuListIW4.h new file mode 100644 index 00000000..6a1d0499 --- /dev/null +++ b/src/ObjLoading/Game/IW4/Menu/LoaderMenuListIW4.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW4/IW4.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW4 +{ + std::unique_ptr> CreateMenuListLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/Menu/MenuConversionZoneStateIW4.cpp b/src/ObjLoading/Game/IW4/Menu/MenuConversionZoneStateIW4.cpp index 3574894f..5bded2c4 100644 --- a/src/ObjLoading/Game/IW4/Menu/MenuConversionZoneStateIW4.cpp +++ b/src/ObjLoading/Game/IW4/Menu/MenuConversionZoneStateIW4.cpp @@ -10,11 +10,11 @@ MenuConversionZoneState::MenuConversionZoneState() { } -void MenuConversionZoneState::SetZone(Zone* zone) +void MenuConversionZoneState::Inject(ZoneAssetCreationInjection& inject) { - auto* memory = zone->GetMemory(); + auto* memory = inject.m_zone.GetMemory(); - m_zone = zone; + m_zone = &inject.m_zone; m_supporting_data = memory->Create(); memset(m_supporting_data, 0, sizeof(ExpressionSupportingData)); } diff --git a/src/ObjLoading/Game/IW4/Menu/MenuConversionZoneStateIW4.h b/src/ObjLoading/Game/IW4/Menu/MenuConversionZoneStateIW4.h index 0978a6cc..5c383604 100644 --- a/src/ObjLoading/Game/IW4/Menu/MenuConversionZoneStateIW4.h +++ b/src/ObjLoading/Game/IW4/Menu/MenuConversionZoneStateIW4.h @@ -1,13 +1,13 @@ #pragma once -#include "AssetLoading/IZoneAssetLoaderState.h" +#include "Asset/IZoneAssetCreationState.h" #include "Game/IW4/IW4.h" #include namespace IW4 { - class MenuConversionZoneState final : public IZoneAssetLoaderState + class MenuConversionZoneState final : public IZoneAssetCreationState { Zone* m_zone; std::vector m_functions; @@ -24,7 +24,7 @@ namespace IW4 ExpressionSupportingData* m_supporting_data; MenuConversionZoneState(); - void SetZone(Zone* zone) override; + void Inject(ZoneAssetCreationInjection& inject) override; Statement_s* FindFunction(const std::string& functionName); diff --git a/src/ObjLoading/Game/IW4/Menu/MenuConverterIW4.cpp b/src/ObjLoading/Game/IW4/Menu/MenuConverterIW4.cpp index 4c27dbd5..bc07ad53 100644 --- a/src/ObjLoading/Game/IW4/Menu/MenuConverterIW4.cpp +++ b/src/ObjLoading/Game/IW4/Menu/MenuConverterIW4.cpp @@ -16,19 +16,17 @@ #include #include +#include #include using namespace IW4; using namespace menu; -namespace IW4 +namespace { - class MenuConverterImpl : public AbstractMenuConverter + class MenuConverter : public AbstractMenuConverter, public IMenuConverter { - MenuConversionZoneState* m_conversion_zone_state; - MenuAssetZoneState* m_parsing_zone_state; - - _NODISCARD static rectDef_s ConvertRectDef(const CommonRect& rect) + [[nodiscard]] static rectDef_s ConvertRectDef(const CommonRect& rect) { return rectDef_s{ static_cast(rect.x), @@ -40,7 +38,7 @@ namespace IW4 }; } - _NODISCARD static rectDef_s ConvertRectDefRelativeTo(const CommonRect& rect, const CommonRect& rectRelativeTo) + [[nodiscard]] static rectDef_s ConvertRectDefRelativeTo(const CommonRect& rect, const CommonRect& rectRelativeTo) { return rectDef_s{ static_cast(rectRelativeTo.x + rect.x), @@ -78,26 +76,26 @@ namespace IW4 return input; } - _NODISCARD Material* ConvertMaterial(const std::string& materialName, const CommonMenuDef* menu, const CommonItemDef* item = nullptr) const + [[nodiscard]] Material* ConvertMaterial(const std::string& materialName, const CommonMenuDef* menu, const CommonItemDef* item = nullptr) const { if (materialName.empty()) return nullptr; - auto* materialDependency = m_manager->LoadDependency(materialName); + auto* materialDependency = m_context.LoadDependency(materialName); if (!materialDependency) - throw MenuConversionException("Failed to load material \"" + materialName + "\"", menu, item); + throw MenuConversionException(std::format("Failed to load material \"{}\"", materialName), menu, item); return materialDependency->Asset(); } - _NODISCARD snd_alias_list_t* ConvertSound(const std::string& soundName, const CommonMenuDef* menu, const CommonItemDef* item = nullptr) const + [[nodiscard]] snd_alias_list_t* ConvertSound(const std::string& soundName, const CommonMenuDef* menu, const CommonItemDef* item = nullptr) const { if (soundName.empty()) return nullptr; - auto* soundDependency = m_manager->LoadDependency(soundName); + auto* soundDependency = m_context.LoadDependency(soundName); if (!soundDependency) - throw MenuConversionException("Failed to load sound \"" + soundName + "\"", menu, item); + throw MenuConversionException(std::format("Failed to load sound \"{}\"", soundName), menu, item); return soundDependency->Asset(); } @@ -127,7 +125,7 @@ namespace IW4 staticDvarIndexEntry.type = EET_OPERAND; staticDvarIndexEntry.data.operand.dataType = VAL_INT; staticDvarIndexEntry.data.operand.internals.intVal = - static_cast(m_conversion_zone_state->AddStaticDvar(*staticDvarNameExpressionValue.m_string_value)); + static_cast(m_conversion_zone_state.AddStaticDvar(*staticDvarNameExpressionValue.m_string_value)); entries.emplace_back(staticDvarIndexEntry); expressionEntry parenRight{}; @@ -135,7 +133,7 @@ namespace IW4 parenRight.data.op = OP_RIGHTPAREN; entries.emplace_back(parenRight); - gameStatement->supportingData = m_conversion_zone_state->m_supporting_data; + gameStatement->supportingData = m_conversion_zone_state.m_supporting_data; return true; } @@ -208,18 +206,18 @@ namespace IW4 std::string lowerCaseFunctionName(functionCall->m_function_name); utils::MakeStringLowerCase(lowerCaseFunctionName); - Statement_s* functionStatement = m_conversion_zone_state->FindFunction(lowerCaseFunctionName); + Statement_s* functionStatement = m_conversion_zone_state.FindFunction(lowerCaseFunctionName); if (functionStatement == nullptr) { // Function was not converted yet: Convert it now - const auto foundCommonFunction = m_parsing_zone_state->m_functions_by_name.find(lowerCaseFunctionName); + const auto foundCommonFunction = m_parsing_zone_state.m_functions_by_name.find(lowerCaseFunctionName); - if (foundCommonFunction == m_parsing_zone_state->m_functions_by_name.end()) + if (foundCommonFunction == m_parsing_zone_state.m_functions_by_name.end()) throw MenuConversionException("Failed to find definition for custom function \"" + functionCall->m_function_name + "\"", menu, item); functionStatement = ConvertExpression(foundCommonFunction->second->m_value.get(), menu, item); - functionStatement = m_conversion_zone_state->AddFunction(foundCommonFunction->second->m_name, functionStatement); + functionStatement = m_conversion_zone_state.AddFunction(foundCommonFunction->second->m_name, functionStatement); } expressionEntry functionEntry{}; @@ -229,7 +227,7 @@ namespace IW4 entries.emplace_back(functionEntry); // Statement uses custom function so it needs supporting data - gameStatement->supportingData = m_conversion_zone_state->m_supporting_data; + gameStatement->supportingData = m_conversion_zone_state.m_supporting_data; } constexpr static expressionOperatorType_e UNARY_OPERATION_MAPPING[static_cast(SimpleUnaryOperationId::COUNT)]{ @@ -363,7 +361,7 @@ namespace IW4 else if (expressionValue->m_type == SimpleExpressionValue::Type::STRING) { entry.data.operand.dataType = VAL_STRING; - entry.data.operand.internals.stringVal.string = m_conversion_zone_state->AddString(*expressionValue->m_string_value); + entry.data.operand.internals.stringVal.string = m_conversion_zone_state.AddString(*expressionValue->m_string_value); } entries.emplace_back(entry); @@ -416,7 +414,7 @@ namespace IW4 if (!expression) return nullptr; - auto* statement = m_memory->Create(); + auto* statement = m_memory.Alloc(); statement->lastResult = Operand{}; statement->lastExecuteTime = 0; statement->supportingData = nullptr; // Supporting data is set upon using it @@ -424,8 +422,8 @@ namespace IW4 std::vector expressionEntries; ConvertExpressionEntry(statement, expressionEntries, expression, menu, item); - auto* outputExpressionEntries = m_memory->Alloc(expressionEntries.size()); - memcpy(outputExpressionEntries, expressionEntries.data(), sizeof(expressionEntry) * expressionEntries.size()); + auto* outputExpressionEntries = m_memory.Alloc(expressionEntries.size()); + std::memcpy(outputExpressionEntries, expressionEntries.data(), sizeof(expressionEntry) * expressionEntries.size()); statement->entries = outputExpressionEntries; statement->numEntries = static_cast(expressionEntries.size()); @@ -433,10 +431,10 @@ namespace IW4 return statement; } - _NODISCARD Statement_s* ConvertOrApplyStatement(float& staticValue, - const ISimpleExpression* expression, - const CommonMenuDef* menu, - const CommonItemDef* item = nullptr) const + [[nodiscard]] Statement_s* ConvertOrApplyStatement(float& staticValue, + const ISimpleExpression* expression, + const CommonMenuDef* menu, + const CommonItemDef* item = nullptr) const { if (m_disable_optimizations) return ConvertExpression(expression, menu, item); @@ -464,10 +462,10 @@ namespace IW4 return ConvertExpression(expression, menu, item); } - _NODISCARD Statement_s* ConvertOrApplyStatement(const char*& staticValue, - const ISimpleExpression* expression, - const CommonMenuDef* menu, - const CommonItemDef* item = nullptr) const + [[nodiscard]] Statement_s* ConvertOrApplyStatement(const char*& staticValue, + const ISimpleExpression* expression, + const CommonMenuDef* menu, + const CommonItemDef* item = nullptr) const { if (m_disable_optimizations) return ConvertExpression(expression, menu, item); @@ -481,7 +479,7 @@ namespace IW4 switch (value.m_type) { case SimpleExpressionValue::Type::STRING: - staticValue = m_memory->Dup(value.m_string_value->c_str()); + staticValue = m_memory.Dup(value.m_string_value->c_str()); break; case SimpleExpressionValue::Type::DOUBLE: @@ -494,10 +492,10 @@ namespace IW4 return ConvertExpression(expression, menu, item); } - _NODISCARD Statement_s* ConvertOrApplyStatement(Material*& staticValue, - const ISimpleExpression* expression, - const CommonMenuDef* menu, - const CommonItemDef* item = nullptr) const + [[nodiscard]] Statement_s* ConvertOrApplyStatement(Material*& staticValue, + const ISimpleExpression* expression, + const CommonMenuDef* menu, + const CommonItemDef* item = nullptr) const { if (m_disable_optimizations) return ConvertExpression(expression, menu, item); @@ -524,10 +522,10 @@ namespace IW4 return ConvertExpression(expression, menu, item); } - _NODISCARD Statement_s* ConvertVisibleExpression(windowDef_t* window, - const ISimpleExpression* expression, - const CommonMenuDef* commonMenu, - const CommonItemDef* commonItem = nullptr) const + [[nodiscard]] Statement_s* ConvertVisibleExpression(windowDef_t* window, + const ISimpleExpression* expression, + const CommonMenuDef* commonMenu, + const CommonItemDef* commonItem = nullptr) const { if (expression == nullptr) return nullptr; @@ -558,7 +556,7 @@ namespace IW4 return ConvertExpression(expression, commonMenu, commonItem); } - _NODISCARD static EventType SetLocalVarTypeToEventType(const SetLocalVarType setLocalVarType) + [[nodiscard]] static EventType SetLocalVarTypeToEventType(const SetLocalVarType setLocalVarType) { switch (setLocalVarType) { @@ -586,16 +584,16 @@ namespace IW4 if (!setLocalVar) return; - auto* outputHandler = m_memory->Alloc(); - auto* outputSetLocalVar = m_memory->Alloc(); + auto* outputHandler = m_memory.Alloc(); + auto* outputSetLocalVar = m_memory.Alloc(); outputHandler->eventType = SetLocalVarTypeToEventType(setLocalVar->m_type); outputHandler->eventData.setLocalVarData = outputSetLocalVar; - outputSetLocalVar->localVarName = m_memory->Dup(setLocalVar->m_var_name.c_str()); + outputSetLocalVar->localVarName = m_memory.Dup(setLocalVar->m_var_name.c_str()); outputSetLocalVar->expression = ConvertExpression(setLocalVar->m_value.get(), menu, item); - elements.push_back(outputHandler); + elements.emplace_back(outputHandler); } void ConvertEventHandlerScript(std::vector& elements, const CommonEventHandlerScript* script) const @@ -604,11 +602,11 @@ namespace IW4 if (!script) return; - auto* outputHandler = m_memory->Create(); + auto* outputHandler = m_memory.Alloc(); outputHandler->eventType = EVENT_UNCONDITIONAL; - outputHandler->eventData.unconditionalScript = m_memory->Dup(script->m_script.c_str()); + outputHandler->eventData.unconditionalScript = m_memory.Dup(script->m_script.c_str()); - elements.push_back(outputHandler); + elements.emplace_back(outputHandler); } void ConvertEventHandlerCondition(std::vector& elements, @@ -631,8 +629,8 @@ namespace IW4 } else { - auto* outputHandler = m_memory->Alloc(); - auto* outputCondition = m_memory->Alloc(); + auto* outputHandler = m_memory.Alloc(); + auto* outputCondition = m_memory.Alloc(); outputHandler->eventType = EVENT_IF; outputHandler->eventData.conditionalScript = outputCondition; @@ -644,7 +642,7 @@ namespace IW4 if (condition->m_else_elements) { - auto* outputElseHandler = m_memory->Create(); + auto* outputElseHandler = m_memory.Alloc(); outputElseHandler->eventType = EVENT_ELSE; outputElseHandler->eventData.elseScript = ConvertEventHandlerSet(condition->m_else_elements.get(), menu, item); @@ -687,7 +685,7 @@ namespace IW4 ConvertEventHandler(elements, element.get(), menu, item); } - _NODISCARD MenuEventHandlerSet* + [[nodiscard]] MenuEventHandlerSet* ConvertEventHandlerSet(const CommonEventHandlerSet* eventHandlerSet, const CommonMenuDef* menu, const CommonItemDef* item = nullptr) const { if (!eventHandlerSet) @@ -699,8 +697,8 @@ namespace IW4 if (elements.empty()) return nullptr; - auto* outputSet = m_memory->Alloc(); - auto* outputElements = m_memory->Alloc(elements.size()); + auto* outputSet = m_memory.Alloc(); + auto* outputElements = m_memory.Alloc(elements.size()); memcpy(outputElements, elements.data(), sizeof(void*) * elements.size()); outputSet->eventHandlerCount = static_cast(elements.size()); @@ -709,15 +707,15 @@ namespace IW4 return outputSet; } - _NODISCARD ItemKeyHandler* ConvertKeyHandler(const std::multimap>& keyHandlers, - const CommonMenuDef* menu, - const CommonItemDef* item = nullptr) const + [[nodiscard]] ItemKeyHandler* ConvertKeyHandler(const std::multimap>& keyHandlers, + const CommonMenuDef* menu, + const CommonItemDef* item = nullptr) const { if (keyHandlers.empty()) return nullptr; const auto keyHandlerCount = keyHandlers.size(); - auto* output = m_memory->Alloc(keyHandlerCount); + auto* output = m_memory.Alloc(keyHandlerCount); auto currentKeyHandler = keyHandlers.cbegin(); for (auto i = 0u; i < keyHandlerCount; i++) { @@ -829,7 +827,7 @@ namespace IW4 if (floatExpressionCount <= 0) return nullptr; - auto* floatExpressions = m_memory->Alloc(floatExpressionCount); + auto* floatExpressions = m_memory.Alloc(floatExpressionCount); auto floatExpressionIndex = 0; for (const auto& [expression, expressionIsStatic, target, staticValue, staticValueArraySize, dynamicFlagsToSet] : locations) { @@ -846,7 +844,7 @@ namespace IW4 return floatExpressions; } - _NODISCARD const char* CreateEnableDvarString(const std::vector& stringElements) const + [[nodiscard]] const char* CreateEnableDvarString(const std::vector& stringElements) const { std::ostringstream ss; @@ -855,10 +853,10 @@ namespace IW4 ss << "\"" << element << "\" "; } - return m_memory->Dup(ss.str().c_str()); + return m_memory.Dup(ss.str().c_str()); } - _NODISCARD const char* ConvertEnableDvar(const CommonItemDef& commonItem, int& dvarFlags) const + [[nodiscard]] const char* ConvertEnableDvar(const CommonItemDef& commonItem, int& dvarFlags) const { dvarFlags = 0; @@ -895,15 +893,15 @@ namespace IW4 return nullptr; } - _NODISCARD listBoxDef_s* ConvertListBoxFeatures(itemDef_s* item, - CommonItemFeaturesListBox* commonListBox, - const CommonMenuDef& parentMenu, - const CommonItemDef& commonItem) const + [[nodiscard]] listBoxDef_s* ConvertListBoxFeatures(itemDef_s* item, + CommonItemFeaturesListBox* commonListBox, + const CommonMenuDef& parentMenu, + const CommonItemDef& commonItem) const { if (commonListBox == nullptr) return nullptr; - auto* listBox = m_memory->Alloc(); + auto* listBox = m_memory.Alloc(); listBox->notselectable = commonListBox->m_not_selectable ? 1 : 0; listBox->noScrollBars = commonListBox->m_no_scrollbars ? 1 : 0; listBox->usePaging = commonListBox->m_use_paging ? 1 : 0; @@ -930,15 +928,15 @@ namespace IW4 return listBox; } - _NODISCARD editFieldDef_s* ConvertEditFieldFeatures(itemDef_s* item, - CommonItemFeaturesEditField* commonEditField, - const CommonMenuDef& parentMenu, - const CommonItemDef& commonItem) const + [[nodiscard]] editFieldDef_s* ConvertEditFieldFeatures(itemDef_s* item, + CommonItemFeaturesEditField* commonEditField, + const CommonMenuDef& parentMenu, + const CommonItemDef& commonItem) const { if (commonEditField == nullptr) return nullptr; - auto* editField = m_memory->Alloc(); + auto* editField = m_memory.Alloc(); editField->defVal = static_cast(commonEditField->m_def_val); editField->minVal = static_cast(commonEditField->m_min_val); editField->maxVal = static_cast(commonEditField->m_max_val); @@ -950,15 +948,15 @@ namespace IW4 return editField; } - _NODISCARD multiDef_s* ConvertMultiValueFeatures(itemDef_s* item, - CommonItemFeaturesMultiValue* commonMultiValue, - const CommonMenuDef& parentMenu, - const CommonItemDef& commonItem) const + [[nodiscard]] multiDef_s* ConvertMultiValueFeatures(itemDef_s* item, + CommonItemFeaturesMultiValue* commonMultiValue, + const CommonMenuDef& parentMenu, + const CommonItemDef& commonItem) const { if (commonMultiValue == nullptr) return nullptr; - auto* multiValue = m_memory->Alloc(); + auto* multiValue = m_memory.Alloc(); multiValue->count = static_cast(std::min(std::extent_v, commonMultiValue->m_step_names.size())); multiValue->strDef = !commonMultiValue->m_string_values.empty() ? 1 : 0; @@ -981,15 +979,15 @@ namespace IW4 return multiValue; } - _NODISCARD newsTickerDef_s* ConvertNewsTickerFeatures(itemDef_s* item, - CommonItemFeaturesNewsTicker* commonNewsTicker, - const CommonMenuDef& parentMenu, - const CommonItemDef& commonItem) const + [[nodiscard]] newsTickerDef_s* ConvertNewsTickerFeatures(itemDef_s* item, + CommonItemFeaturesNewsTicker* commonNewsTicker, + const CommonMenuDef& parentMenu, + const CommonItemDef& commonItem) const { if (commonNewsTicker == nullptr) return nullptr; - auto* newsTicker = m_memory->Alloc(); + auto* newsTicker = m_memory.Alloc(); newsTicker->spacing = commonNewsTicker->m_spacing; newsTicker->speed = commonNewsTicker->m_speed; newsTicker->feedId = commonNewsTicker->m_news_feed_id; @@ -997,10 +995,9 @@ namespace IW4 return newsTicker; } - _NODISCARD itemDef_s* ConvertItem(const CommonMenuDef& parentMenu, const CommonItemDef& commonItem) const + [[nodiscard]] itemDef_s* ConvertItem(const CommonMenuDef& parentMenu, const CommonItemDef& commonItem) const { - auto* item = m_memory->Create(); - memset(item, 0, sizeof(itemDef_s)); + auto* item = m_memory.Alloc(); item->window.name = ConvertString(commonItem.m_name); item->text = ConvertString(commonItem.m_text); @@ -1087,7 +1084,7 @@ namespace IW4 case CommonItemFeatureType::NONE: default: if (item->type == ITEM_TYPE_TEXT_SCROLL) - item->typeData.scroll = m_memory->Alloc(); + item->typeData.scroll = m_memory.Alloc(); break; } @@ -1103,7 +1100,7 @@ namespace IW4 return nullptr; } - auto* items = m_memory->Alloc(commonMenu.m_items.size()); + auto* items = m_memory.Alloc(commonMenu.m_items.size()); for (auto i = 0u; i < commonMenu.m_items.size(); i++) items[i] = ConvertItem(commonMenu, *commonMenu.m_items[i]); @@ -1113,98 +1110,73 @@ namespace IW4 } public: - MenuConverterImpl(const bool disableOptimizations, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) - : AbstractMenuConverter(disableOptimizations, searchPath, memory, manager), - m_conversion_zone_state(manager->GetAssetLoadingContext()->GetZoneAssetLoaderState()), - m_parsing_zone_state(manager->GetAssetLoadingContext()->GetZoneAssetLoaderState()) + MenuConverter(const bool disableOptimizations, ISearchPath& searchPath, MemoryManager& memory, AssetCreationContext& context) + : AbstractMenuConverter(disableOptimizations, searchPath, memory, context), + m_conversion_zone_state(context.GetZoneAssetCreationState()), + m_parsing_zone_state(context.GetZoneAssetCreationState()) { - assert(m_conversion_zone_state); - assert(m_parsing_zone_state); } - _NODISCARD menuDef_t* ConvertMenu(const CommonMenuDef& commonMenu) const + void ConvertMenu(const menu::CommonMenuDef& commonMenu, menuDef_t& menu, AssetRegistration& registration) override { - auto* menu = m_memory->Create(); - memset(menu, 0, sizeof(menuDef_t)); - - menu->window.name = m_memory->Dup(commonMenu.m_name.c_str()); - menu->fullScreen = commonMenu.m_full_screen; - ApplyFlag(menu->window.staticFlags, commonMenu.m_screen_space, WINDOW_FLAG_SCREEN_SPACE); - ApplyFlag(menu->window.staticFlags, commonMenu.m_decoration, WINDOW_FLAG_DECORATION); - menu->window.rect = ConvertRectDef(commonMenu.m_rect); - menu->window.style = commonMenu.m_style; - menu->window.border = commonMenu.m_border; - menu->window.borderSize = static_cast(commonMenu.m_border_size); - ConvertColor(menu->window.backColor, commonMenu.m_back_color); - ConvertColor(menu->window.foreColor, commonMenu.m_fore_color); - ConvertColor(menu->window.borderColor, commonMenu.m_border_color); - ConvertColor(menu->focusColor, commonMenu.m_focus_color); - menu->window.background = ConvertMaterial(commonMenu.m_background, &commonMenu); - menu->window.ownerDraw = commonMenu.m_owner_draw; - menu->window.ownerDrawFlags = commonMenu.m_owner_draw_flags; - ApplyFlag(menu->window.staticFlags, commonMenu.m_out_of_bounds_click, WINDOW_FLAG_OUT_OF_BOUNDS_CLICK); - menu->soundName = ConvertString(commonMenu.m_sound_loop); - ApplyFlag(menu->window.staticFlags, commonMenu.m_popup, WINDOW_FLAG_POPUP); - menu->fadeClamp = static_cast(commonMenu.m_fade_clamp); - menu->fadeCycle = commonMenu.m_fade_cycle; - menu->fadeAmount = static_cast(commonMenu.m_fade_amount); - menu->fadeInAmount = static_cast(commonMenu.m_fade_in_amount); - menu->blurRadius = static_cast(commonMenu.m_blur_radius); - ApplyFlag(menu->window.staticFlags, commonMenu.m_legacy_split_screen_scale, WINDOW_FLAG_LEGACY_SPLIT_SCREEN_SCALE); - ApplyFlag(menu->window.staticFlags, commonMenu.m_hidden_during_scope, WINDOW_FLAG_HIDDEN_DURING_SCOPE); - ApplyFlag(menu->window.staticFlags, commonMenu.m_hidden_during_flashbang, WINDOW_FLAG_HIDDEN_DURING_FLASH_BANG); - ApplyFlag(menu->window.staticFlags, commonMenu.m_hidden_during_ui, WINDOW_FLAG_HIDDEN_DURING_UI); - menu->allowedBinding = ConvertString(commonMenu.m_allowed_binding); - ApplyFlag(menu->window.staticFlags, commonMenu.m_text_only_focus, WINDOW_FLAG_TEXT_ONLY_FOCUS); - menu->visibleExp = ConvertVisibleExpression(&menu->window, commonMenu.m_visible_expression.get(), &commonMenu); - menu->rectXExp = ConvertOrApplyStatement(menu->window.rect.x, commonMenu.m_rect_x_exp.get(), &commonMenu); - menu->rectYExp = ConvertOrApplyStatement(menu->window.rect.y, commonMenu.m_rect_y_exp.get(), &commonMenu); - menu->rectWExp = ConvertOrApplyStatement(menu->window.rect.w, commonMenu.m_rect_w_exp.get(), &commonMenu); - menu->rectHExp = ConvertOrApplyStatement(menu->window.rect.h, commonMenu.m_rect_h_exp.get(), &commonMenu); - menu->openSoundExp = ConvertExpression(commonMenu.m_open_sound_exp.get(), &commonMenu); - menu->closeSoundExp = ConvertExpression(commonMenu.m_close_sound_exp.get(), &commonMenu); - menu->onOpen = ConvertEventHandlerSet(commonMenu.m_on_open.get(), &commonMenu); - menu->onClose = ConvertEventHandlerSet(commonMenu.m_on_close.get(), &commonMenu); - menu->onCloseRequest = ConvertEventHandlerSet(commonMenu.m_on_request_close.get(), &commonMenu); - menu->onESC = ConvertEventHandlerSet(commonMenu.m_on_esc.get(), &commonMenu); - menu->onKey = ConvertKeyHandler(commonMenu.m_key_handlers, &commonMenu); - menu->items = ConvertMenuItems(commonMenu, menu->itemCount); - menu->expressionData = m_conversion_zone_state->m_supporting_data; - - return menu; + try + { + menu.window.name = m_memory.Dup(commonMenu.m_name.c_str()); + menu.fullScreen = commonMenu.m_full_screen; + ApplyFlag(menu.window.staticFlags, commonMenu.m_screen_space, WINDOW_FLAG_SCREEN_SPACE); + ApplyFlag(menu.window.staticFlags, commonMenu.m_decoration, WINDOW_FLAG_DECORATION); + menu.window.rect = ConvertRectDef(commonMenu.m_rect); + menu.window.style = commonMenu.m_style; + menu.window.border = commonMenu.m_border; + menu.window.borderSize = static_cast(commonMenu.m_border_size); + ConvertColor(menu.window.backColor, commonMenu.m_back_color); + ConvertColor(menu.window.foreColor, commonMenu.m_fore_color); + ConvertColor(menu.window.borderColor, commonMenu.m_border_color); + ConvertColor(menu.focusColor, commonMenu.m_focus_color); + menu.window.background = ConvertMaterial(commonMenu.m_background, &commonMenu); + menu.window.ownerDraw = commonMenu.m_owner_draw; + menu.window.ownerDrawFlags = commonMenu.m_owner_draw_flags; + ApplyFlag(menu.window.staticFlags, commonMenu.m_out_of_bounds_click, WINDOW_FLAG_OUT_OF_BOUNDS_CLICK); + menu.soundName = ConvertString(commonMenu.m_sound_loop); + ApplyFlag(menu.window.staticFlags, commonMenu.m_popup, WINDOW_FLAG_POPUP); + menu.fadeClamp = static_cast(commonMenu.m_fade_clamp); + menu.fadeCycle = commonMenu.m_fade_cycle; + menu.fadeAmount = static_cast(commonMenu.m_fade_amount); + menu.fadeInAmount = static_cast(commonMenu.m_fade_in_amount); + menu.blurRadius = static_cast(commonMenu.m_blur_radius); + ApplyFlag(menu.window.staticFlags, commonMenu.m_legacy_split_screen_scale, WINDOW_FLAG_LEGACY_SPLIT_SCREEN_SCALE); + ApplyFlag(menu.window.staticFlags, commonMenu.m_hidden_during_scope, WINDOW_FLAG_HIDDEN_DURING_SCOPE); + ApplyFlag(menu.window.staticFlags, commonMenu.m_hidden_during_flashbang, WINDOW_FLAG_HIDDEN_DURING_FLASH_BANG); + ApplyFlag(menu.window.staticFlags, commonMenu.m_hidden_during_ui, WINDOW_FLAG_HIDDEN_DURING_UI); + menu.allowedBinding = ConvertString(commonMenu.m_allowed_binding); + ApplyFlag(menu.window.staticFlags, commonMenu.m_text_only_focus, WINDOW_FLAG_TEXT_ONLY_FOCUS); + menu.visibleExp = ConvertVisibleExpression(&menu.window, commonMenu.m_visible_expression.get(), &commonMenu); + menu.rectXExp = ConvertOrApplyStatement(menu.window.rect.x, commonMenu.m_rect_x_exp.get(), &commonMenu); + menu.rectYExp = ConvertOrApplyStatement(menu.window.rect.y, commonMenu.m_rect_y_exp.get(), &commonMenu); + menu.rectWExp = ConvertOrApplyStatement(menu.window.rect.w, commonMenu.m_rect_w_exp.get(), &commonMenu); + menu.rectHExp = ConvertOrApplyStatement(menu.window.rect.h, commonMenu.m_rect_h_exp.get(), &commonMenu); + menu.openSoundExp = ConvertExpression(commonMenu.m_open_sound_exp.get(), &commonMenu); + menu.closeSoundExp = ConvertExpression(commonMenu.m_close_sound_exp.get(), &commonMenu); + menu.onOpen = ConvertEventHandlerSet(commonMenu.m_on_open.get(), &commonMenu); + menu.onClose = ConvertEventHandlerSet(commonMenu.m_on_close.get(), &commonMenu); + menu.onCloseRequest = ConvertEventHandlerSet(commonMenu.m_on_request_close.get(), &commonMenu); + menu.onESC = ConvertEventHandlerSet(commonMenu.m_on_esc.get(), &commonMenu); + menu.onKey = ConvertKeyHandler(commonMenu.m_key_handlers, &commonMenu); + menu.items = ConvertMenuItems(commonMenu, menu.itemCount); + menu.expressionData = m_conversion_zone_state.m_supporting_data; + } + catch (const MenuConversionException& e) + { + PrintConversionExceptionDetails(e); + } } - std::vector m_dependencies; + MenuConversionZoneState& m_conversion_zone_state; + MenuAssetZoneState& m_parsing_zone_state; }; -} // namespace IW4 +} // namespace -MenuConverter::MenuConverter(const bool disableOptimizations, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) - : m_disable_optimizations(disableOptimizations), - m_search_path(searchPath), - m_memory(memory), - m_manager(manager) +std::unique_ptr IMenuConverter::Create(bool disableOptimizations, ISearchPath& searchPath, MemoryManager& memory, AssetCreationContext& context) { -} - -std::vector& MenuConverter::GetDependencies() -{ - return m_dependencies; -} - -menuDef_t* MenuConverter::ConvertMenu(const CommonMenuDef& commonMenu) -{ - MenuConverterImpl impl(m_disable_optimizations, m_search_path, m_memory, m_manager); - - try - { - auto* result = impl.ConvertMenu(commonMenu); - m_dependencies = std::move(impl.m_dependencies); - return result; - } - catch (const MenuConversionException& e) - { - MenuConverterImpl::PrintConversionExceptionDetails(e); - } - - return nullptr; + return std::make_unique(disableOptimizations, searchPath, memory, context); } diff --git a/src/ObjLoading/Game/IW4/Menu/MenuConverterIW4.h b/src/ObjLoading/Game/IW4/Menu/MenuConverterIW4.h index ffe6f40b..234cedb5 100644 --- a/src/ObjLoading/Game/IW4/Menu/MenuConverterIW4.h +++ b/src/ObjLoading/Game/IW4/Menu/MenuConverterIW4.h @@ -1,26 +1,21 @@ #pragma once -#include "AssetLoading/IAssetLoadingManager.h" +#include "Asset/AssetCreationContext.h" #include "Game/IW4/IW4.h" #include "Parsing/Menu/Domain/CommonMenuDef.h" #include "SearchPath/ISearchPath.h" -#include "Utils/ClassUtils.h" #include "Utils/MemoryManager.h" namespace IW4 { - class MenuConverter + class IMenuConverter { - bool m_disable_optimizations; - ISearchPath* m_search_path; - MemoryManager* m_memory; - IAssetLoadingManager* m_manager; - std::vector m_dependencies; - public: - MenuConverter(bool disableOptimizations, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager); + IMenuConverter() = default; + virtual ~IMenuConverter() = default; - std::vector& GetDependencies(); - _NODISCARD menuDef_t* ConvertMenu(const menu::CommonMenuDef& commonMenu); + virtual void ConvertMenu(const menu::CommonMenuDef& commonMenu, menuDef_t& menu, AssetRegistration& registration) = 0; + + static std::unique_ptr Create(bool disableOptimizations, ISearchPath& searchPath, MemoryManager& memory, AssetCreationContext& context); }; } // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/ObjLoaderIW4.cpp b/src/ObjLoading/Game/IW4/ObjLoaderIW4.cpp index 0960b737..7710fb8a 100644 --- a/src/ObjLoading/Game/IW4/ObjLoaderIW4.cpp +++ b/src/ObjLoading/Game/IW4/ObjLoaderIW4.cpp @@ -1,119 +1,170 @@ #include "ObjLoaderIW4.h" -#include "AssetLoaders/AssetLoaderAddonMapEnts.h" -#include "AssetLoaders/AssetLoaderClipMap.h" -#include "AssetLoaders/AssetLoaderComWorld.h" -#include "AssetLoaders/AssetLoaderFont.h" -#include "AssetLoaders/AssetLoaderFx.h" -#include "AssetLoaders/AssetLoaderFxImpactTable.h" -#include "AssetLoaders/AssetLoaderFxWorld.h" -#include "AssetLoaders/AssetLoaderGameWorldMp.h" -#include "AssetLoaders/AssetLoaderGameWorldSp.h" -#include "AssetLoaders/AssetLoaderGfxImage.h" -#include "AssetLoaders/AssetLoaderGfxLightDef.h" -#include "AssetLoaders/AssetLoaderGfxWorld.h" -#include "AssetLoaders/AssetLoaderLeaderboard.h" -#include "AssetLoaders/AssetLoaderLoadedSound.h" -#include "AssetLoaders/AssetLoaderLocalizeEntry.h" -#include "AssetLoaders/AssetLoaderMapEnts.h" -#include "AssetLoaders/AssetLoaderMaterial.h" -#include "AssetLoaders/AssetLoaderMenuDef.h" -#include "AssetLoaders/AssetLoaderMenuList.h" -#include "AssetLoaders/AssetLoaderPhysCollmap.h" -#include "AssetLoaders/AssetLoaderPhysPreset.h" -#include "AssetLoaders/AssetLoaderPixelShader.h" -#include "AssetLoaders/AssetLoaderRawFile.h" -#include "AssetLoaders/AssetLoaderSndCurve.h" -#include "AssetLoaders/AssetLoaderSoundAliasList.h" -#include "AssetLoaders/AssetLoaderStringTable.h" -#include "AssetLoaders/AssetLoaderStructuredDataDefSet.h" -#include "AssetLoaders/AssetLoaderTechniqueSet.h" -#include "AssetLoaders/AssetLoaderTracer.h" -#include "AssetLoaders/AssetLoaderVehicle.h" -#include "AssetLoaders/AssetLoaderVertexDecl.h" -#include "AssetLoaders/AssetLoaderVertexShader.h" -#include "AssetLoaders/AssetLoaderWeapon.h" -#include "AssetLoaders/AssetLoaderXAnim.h" -#include "AssetLoaders/AssetLoaderXModel.h" -#include "AssetLoaders/AssetLoaderXModelSurfs.h" -#include "AssetLoading/AssetLoadingManager.h" +#include "Asset/GlobalAssetPoolsLoader.h" #include "Game/IW4/GameIW4.h" -#include "Image/IwiLoader.h" -#include "ObjContainer/IPak/IPak.h" +#include "Game/IW4/IW4.h" +#include "Leaderboard/LoaderLeaderboardIW4.h" +#include "LightDef/LoaderLightDefIW4.h" +#include "Localize/LoaderLocalizeIW4.h" +#include "Material/LoaderMaterialIW4.h" +#include "Menu/LoaderMenuListIW4.h" +#include "ObjLoading.h" +#include "PhysPreset/GdtLoaderPhysPresetIW4.h" +#include "PhysPreset/RawLoaderPhysPresetIW4.h" +#include "RawFile/LoaderRawFileIW4.h" +#include "Shader/LoaderPixelShaderIW4.h" +#include "Shader/LoaderVertexShaderIW4.h" +#include "Sound/LoaderSoundCurveIW4.h" +#include "StringTable/LoaderStringTableIW4.h" +#include "StructuredDataDef/LoaderStructuredDataDefIW4.h" +#include "Techset/LoaderTechsetIW4.h" +#include "Techset/LoaderVertexDeclIW4.h" +#include "Weapon/GdtLoaderWeaponIW4.h" +#include "Weapon/RawLoaderWeaponIW4.h" + +#include using namespace IW4; -ObjLoader::ObjLoader() -{ -#define REGISTER_ASSET_LOADER(t) \ - { \ - auto l = std::make_unique(); \ - m_asset_loaders_by_type[l->GetHandlingAssetType()] = std::move(l); \ - } - - REGISTER_ASSET_LOADER(AssetLoaderPhysPreset) - REGISTER_ASSET_LOADER(AssetLoaderPhysCollmap) - REGISTER_ASSET_LOADER(AssetLoaderXAnim) - REGISTER_ASSET_LOADER(AssetLoaderXModelSurfs) - REGISTER_ASSET_LOADER(AssetLoaderXModel) - REGISTER_ASSET_LOADER(AssetLoaderMaterial) - REGISTER_ASSET_LOADER(AssetLoaderPixelShader) - REGISTER_ASSET_LOADER(AssetLoaderVertexShader) - REGISTER_ASSET_LOADER(AssetLoaderVertexDecl) - REGISTER_ASSET_LOADER(AssetLoaderTechniqueSet) - REGISTER_ASSET_LOADER(AssetLoaderGfxImage) - REGISTER_ASSET_LOADER(AssetLoaderSoundAliasList) - REGISTER_ASSET_LOADER(AssetLoaderSndCurve) - REGISTER_ASSET_LOADER(AssetLoaderLoadedSound) - REGISTER_ASSET_LOADER(AssetLoaderClipMapSp) - REGISTER_ASSET_LOADER(AssetLoaderClipMapMp) - REGISTER_ASSET_LOADER(AssetLoaderComWorld) - REGISTER_ASSET_LOADER(AssetLoaderGameWorldSp) - REGISTER_ASSET_LOADER(AssetLoaderGameWorldMp) - REGISTER_ASSET_LOADER(AssetLoaderMapEnts) - REGISTER_ASSET_LOADER(AssetLoaderFxWorld) - REGISTER_ASSET_LOADER(AssetLoaderGfxWorld) - REGISTER_ASSET_LOADER(AssetLoaderGfxLightDef) - REGISTER_ASSET_LOADER(AssetLoaderFont) - REGISTER_ASSET_LOADER(AssetLoaderMenuList) - REGISTER_ASSET_LOADER(AssetLoaderMenuDef) - REGISTER_ASSET_LOADER(AssetLoaderLocalizeEntry) - REGISTER_ASSET_LOADER(AssetLoaderWeapon) - REGISTER_ASSET_LOADER(AssetLoaderFx) - REGISTER_ASSET_LOADER(AssetLoaderFxImpactTable) - REGISTER_ASSET_LOADER(AssetLoaderRawFile) - REGISTER_ASSET_LOADER(AssetLoaderStringTable) - REGISTER_ASSET_LOADER(AssetLoaderLeaderboard) - REGISTER_ASSET_LOADER(AssetLoaderStructuredDataDefSet) - REGISTER_ASSET_LOADER(AssetLoaderTracer) - REGISTER_ASSET_LOADER(AssetLoaderVehicle) - REGISTER_ASSET_LOADER(AssetLoaderAddonMapEnts) - -#undef REGISTER_ASSET_LOADER -} - -bool ObjLoader::IsMpZone(const Zone& zone) -{ - return zone.m_name.compare(0, 3, "mp_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_mp") == 0; -} - -bool ObjLoader::IsZmZone(const Zone& zone) -{ - return zone.m_name.compare(0, 3, "zm_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_zm") == 0; -} - void ObjLoader::LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const {} void ObjLoader::UnloadContainersOfZone(Zone& zone) const {} -bool ObjLoader::LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const +namespace { - AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, context); - return assetLoadingManager.LoadAssetFromLoader(assetType, assetName); -} + void ConfigureDefaultCreators(AssetCreatorCollection& collection, Zone& zone) + { + auto& memory = *zone.GetMemory(); -void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext& context) const + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + } + + void ConfigureGlobalAssetPoolsLoaders(AssetCreatorCollection& collection, Zone& zone) + { + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + } + + void ConfigureLoaders(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, IGdtQueryable& gdt) + { + auto& memory = *zone.GetMemory(); + + collection.AddAssetCreator(std::make_unique(memory, searchPath, zone)); + collection.AddAssetCreator(std::make_unique(memory, gdt, zone)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateMaterialLoader(memory, searchPath, gdt)); + collection.AddAssetCreator(CreatePixelShaderLoader(memory, searchPath)); + collection.AddAssetCreator(CreateVertexShaderLoader(memory, searchPath)); + collection.AddAssetCreator(CreateVertexDeclLoader(memory)); + collection.AddAssetCreator(CreateTechsetLoader(memory, searchPath)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateSoundCurveLoader(memory, searchPath)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateLightDefLoader(memory, searchPath)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateMenuListLoader(memory, searchPath)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateLocalizeLoader(memory, searchPath, zone)); + collection.AddAssetCreator(CreateRawWeaponLoader(memory, searchPath, zone)); + collection.AddAssetCreator(CreateGdtWeaponLoader(memory, searchPath, gdt, zone)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateRawFileLoader(memory, searchPath)); + collection.AddAssetCreator(CreateStringTableLoader(memory, searchPath)); + collection.AddAssetCreator(CreateLeaderboardLoader(memory, searchPath)); + collection.AddAssetCreator(CreateStructuredDataDefLoader(memory, searchPath)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + } +} // namespace + +void ObjLoader::ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, IGdtQueryable& gdt) const { - for (const auto& [type, loader] : m_asset_loaders_by_type) - loader->FinalizeAssetsForZone(context); + ConfigureDefaultCreators(collection, zone); + ConfigureLoaders(collection, zone, searchPath, gdt); + ConfigureGlobalAssetPoolsLoaders(collection, zone); } diff --git a/src/ObjLoading/Game/IW4/ObjLoaderIW4.h b/src/ObjLoading/Game/IW4/ObjLoaderIW4.h index ab4e10b3..4d080914 100644 --- a/src/ObjLoading/Game/IW4/ObjLoaderIW4.h +++ b/src/ObjLoading/Game/IW4/ObjLoaderIW4.h @@ -1,29 +1,17 @@ #pragma once -#include "AssetLoading/IAssetLoader.h" #include "IObjLoader.h" #include "SearchPath/ISearchPath.h" - -#include -#include +#include "Zone/Zone.h" namespace IW4 { class ObjLoader final : public IObjLoader { public: - ObjLoader(); - void LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const override; void UnloadContainersOfZone(Zone& zone) const override; - bool LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const override; - void FinalizeAssetsForZone(AssetLoadingContext& context) const override; - - private: - static bool IsMpZone(const Zone& zone); - static bool IsZmZone(const Zone& zone); - - std::unordered_map> m_asset_loaders_by_type; + void ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, IGdtQueryable& gdt) const override; }; } // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/PhysPreset/GdtLoaderPhysPresetIW4.cpp b/src/ObjLoading/Game/IW4/PhysPreset/GdtLoaderPhysPresetIW4.cpp new file mode 100644 index 00000000..afd65d70 --- /dev/null +++ b/src/ObjLoading/Game/IW4/PhysPreset/GdtLoaderPhysPresetIW4.cpp @@ -0,0 +1,35 @@ +#include "GdtLoaderPhysPresetIW4.h" + +#include "Game/IW4/IW4.h" +#include "Game/IW4/ObjConstantsIW4.h" +#include "InfoString/InfoString.h" +#include "InfoStringLoaderPhysPresetIW4.h" + +#include +#include + +using namespace IW4; + +GdtLoaderPhysPreset::GdtLoaderPhysPreset(MemoryManager& memory, IGdtQueryable& gdt, Zone& zone) + : m_memory(memory), + m_gdt(gdt), + m_zone(zone) +{ +} + +AssetCreationResult GdtLoaderPhysPreset::CreateAsset(const std::string& assetName, AssetCreationContext& context) +{ + auto* gdtEntry = m_gdt.GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_PHYS_PRESET, assetName); + if (gdtEntry == nullptr) + return AssetCreationResult::NoAction(); + + InfoString infoString; + if (!infoString.FromGdtProperties(*gdtEntry)) + { + std::cerr << std::format("Failed to read phys preset gdt entry: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + InfoStringLoaderPhysPreset infoStringLoader(m_memory, m_zone); + return infoStringLoader.CreateAsset(assetName, infoString, context); +} diff --git a/src/ObjLoading/Game/IW4/PhysPreset/GdtLoaderPhysPresetIW4.h b/src/ObjLoading/Game/IW4/PhysPreset/GdtLoaderPhysPresetIW4.h new file mode 100644 index 00000000..59b65bc1 --- /dev/null +++ b/src/ObjLoading/Game/IW4/PhysPreset/GdtLoaderPhysPresetIW4.h @@ -0,0 +1,22 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW4/IW4.h" +#include "Gdt/IGdtQueryable.h" +#include "Utils/MemoryManager.h" + +namespace IW4 +{ + class GdtLoaderPhysPreset final : public AssetCreator + { + public: + GdtLoaderPhysPreset(MemoryManager& memory, IGdtQueryable& gdt, Zone& zone); + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override; + + private: + MemoryManager& m_memory; + IGdtQueryable& m_gdt; + Zone& m_zone; + }; +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/PhysPreset/InfoStringLoaderPhysPresetIW4.cpp b/src/ObjLoading/Game/IW4/PhysPreset/InfoStringLoaderPhysPresetIW4.cpp new file mode 100644 index 00000000..25c8cc89 --- /dev/null +++ b/src/ObjLoading/Game/IW4/PhysPreset/InfoStringLoaderPhysPresetIW4.cpp @@ -0,0 +1,87 @@ +#include "InfoStringLoaderPhysPresetIW4.h" + +#include "Game/IW4/IW4.h" +#include "Game/IW4/InfoString/InfoStringToStructConverter.h" +#include "Game/IW4/PhysPreset/PhysPresetFields.h" + +#include +#include +#include +#include +#include +#include + +using namespace IW4; + +namespace +{ + class InfoStringToPhysPresetConverter final : public InfoStringToStructConverter + { + public: + InfoStringToPhysPresetConverter(const InfoString& infoString, + void* structure, + ZoneScriptStrings& zoneScriptStrings, + MemoryManager& memory, + AssetCreationContext& context, + GenericAssetRegistration& registration, + const cspField_t* fields, + size_t fieldCount) + : InfoStringToStructConverter(infoString, structure, zoneScriptStrings, memory, context, registration, fields, fieldCount) + { + } + + protected: + bool ConvertExtensionField(const cspField_t& field, const std::string& value) override + { + assert(false); + return false; + } + }; + + void CopyFromPhysPresetInfo(const PhysPresetInfo& physPresetInfo, PhysPreset& physPreset) + { + physPreset.mass = std::clamp(physPresetInfo.mass, 1.0f, 2000.0f) * 0.001f; + physPreset.bounce = physPresetInfo.bounce; + + if (physPresetInfo.isFrictionInfinity != 0) + physPreset.friction = std::numeric_limits::infinity(); + else + physPreset.friction = physPresetInfo.friction; + + physPreset.bulletForceScale = physPresetInfo.bulletForceScale; + physPreset.explosiveForceScale = physPresetInfo.explosiveForceScale; + physPreset.sndAliasPrefix = physPresetInfo.sndAliasPrefix; + physPreset.piecesSpreadFraction = physPresetInfo.piecesSpreadFraction; + physPreset.piecesUpwardVelocity = physPresetInfo.piecesUpwardVelocity; + physPreset.tempDefaultToCylinder = physPresetInfo.tempDefaultToCylinder != 0; + physPreset.perSurfaceSndAlias = physPresetInfo.perSurfaceSndAlias != 0; + } +} // namespace + +InfoStringLoaderPhysPreset::InfoStringLoaderPhysPreset(MemoryManager& memory, Zone& zone) + : m_memory(memory), + m_zone(zone) +{ +} + +AssetCreationResult InfoStringLoaderPhysPreset::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) +{ + PhysPresetInfo presetInfo; + std::memset(&presetInfo, 0, sizeof(presetInfo)); + + auto* physPreset = m_memory.Alloc(); + AssetRegistration registration(assetName, physPreset); + + InfoStringToPhysPresetConverter converter( + infoString, &presetInfo, m_zone.m_script_strings, m_memory, context, registration, phys_preset_fields, std::extent_v); + if (!converter.Convert()) + { + std::cerr << std::format("Failed to parse phys preset: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + CopyFromPhysPresetInfo(presetInfo, *physPreset); + physPreset->name = m_memory.Dup(assetName.c_str()); + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); +} diff --git a/src/ObjLoading/Game/IW4/PhysPreset/InfoStringLoaderPhysPresetIW4.h b/src/ObjLoading/Game/IW4/PhysPreset/InfoStringLoaderPhysPresetIW4.h new file mode 100644 index 00000000..0ca1cede --- /dev/null +++ b/src/ObjLoading/Game/IW4/PhysPreset/InfoStringLoaderPhysPresetIW4.h @@ -0,0 +1,20 @@ +#pragma once + +#include "Asset/AssetCreationContext.h" +#include "Asset/AssetCreationResult.h" +#include "InfoString/InfoString.h" + +namespace IW4 +{ + class InfoStringLoaderPhysPreset + { + public: + InfoStringLoaderPhysPreset(MemoryManager& memory, Zone& zone); + + AssetCreationResult CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context); + + private: + MemoryManager& m_memory; + Zone& m_zone; + }; +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/PhysPreset/RawLoaderPhysPresetIW4.cpp b/src/ObjLoading/Game/IW4/PhysPreset/RawLoaderPhysPresetIW4.cpp new file mode 100644 index 00000000..ada031ac --- /dev/null +++ b/src/ObjLoading/Game/IW4/PhysPreset/RawLoaderPhysPresetIW4.cpp @@ -0,0 +1,36 @@ +#include "RawLoaderPhysPresetIW4.h" + +#include "Game/IW4/IW4.h" +#include "Game/IW4/ObjConstantsIW4.h" +#include "InfoString/InfoString.h" +#include "InfoStringLoaderPhysPresetIW4.h" + +#include +#include + +using namespace IW4; + +RawLoaderPhysPreset::RawLoaderPhysPreset(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_memory(memory), + m_search_path(searchPath), + m_zone(zone) +{ +} + +AssetCreationResult RawLoaderPhysPreset::CreateAsset(const std::string& assetName, AssetCreationContext& context) +{ + const auto fileName = std::format("physic/{}", assetName); + const auto file = m_search_path.Open(fileName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + InfoString infoString; + if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_PHYS_PRESET, *file.m_stream)) + { + std::cerr << std::format("Could not parse as info string file: \"{}\"\n", fileName); + return AssetCreationResult::Failure(); + } + + InfoStringLoaderPhysPreset infoStringLoader(m_memory, m_zone); + return infoStringLoader.CreateAsset(assetName, infoString, context); +} diff --git a/src/ObjLoading/Game/IW4/PhysPreset/RawLoaderPhysPresetIW4.h b/src/ObjLoading/Game/IW4/PhysPreset/RawLoaderPhysPresetIW4.h new file mode 100644 index 00000000..1c3dd841 --- /dev/null +++ b/src/ObjLoading/Game/IW4/PhysPreset/RawLoaderPhysPresetIW4.h @@ -0,0 +1,22 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW4/IW4.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +namespace IW4 +{ + class RawLoaderPhysPreset final : public AssetCreator + { + public: + RawLoaderPhysPreset(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override; + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + Zone& m_zone; + }; +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/RawFile/LoaderRawFileIW4.cpp b/src/ObjLoading/Game/IW4/RawFile/LoaderRawFileIW4.cpp new file mode 100644 index 00000000..f4b788ad --- /dev/null +++ b/src/ObjLoading/Game/IW4/RawFile/LoaderRawFileIW4.cpp @@ -0,0 +1,91 @@ +#include "LoaderRawFileIW4.h" + +#include "Game/IW4/IW4.h" + +#include +#include +#include +#include +#include + +using namespace IW4; + +namespace +{ + constexpr size_t COMPRESSED_BUFFER_SIZE_PADDING = 64u; + + class RawFileLoader final : public AssetCreator + { + public: + RawFileLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto file = m_search_path.Open(assetName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + const auto uncompressedBuffer = std::make_unique(static_cast(file.m_length)); + file.m_stream->read(uncompressedBuffer.get(), file.m_length); + if (file.m_stream->gcount() != file.m_length) + return AssetCreationResult::Failure(); + + const auto compressionBufferSize = static_cast(file.m_length + COMPRESSED_BUFFER_SIZE_PADDING); + auto* compressedBuffer = m_memory.Alloc(compressionBufferSize); + + z_stream_s zs{}; + + zs.zalloc = Z_NULL; + zs.zfree = Z_NULL; + zs.opaque = Z_NULL; + zs.avail_in = static_cast(file.m_length); + zs.avail_out = compressionBufferSize; + zs.next_in = reinterpret_cast(uncompressedBuffer.get()); + zs.next_out = reinterpret_cast(compressedBuffer); + + int ret = deflateInit(&zs, Z_DEFAULT_COMPRESSION); + + if (ret != Z_OK) + { + throw std::runtime_error("Initializing deflate failed"); + } + + ret = deflate(&zs, Z_FINISH); + + if (ret != Z_STREAM_END) + { + std::cerr << std::format("Deflate failed for loading rawfile \"{}\"\n", assetName); + deflateEnd(&zs); + return AssetCreationResult::Failure(); + } + + const auto compressedSize = compressionBufferSize - zs.avail_out; + + auto* rawFile = m_memory.Alloc(); + rawFile->name = m_memory.Dup(assetName.c_str()); + rawFile->compressedLen = static_cast(compressedSize); + rawFile->len = static_cast(file.m_length); + rawFile->data.compressedBuffer = static_cast(compressedBuffer); + + deflateEnd(&zs); + + return AssetCreationResult::Success(context.AddAsset(assetName, rawFile)); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace IW4 +{ + std::unique_ptr> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/RawFile/LoaderRawFileIW4.h b/src/ObjLoading/Game/IW4/RawFile/LoaderRawFileIW4.h new file mode 100644 index 00000000..e8163342 --- /dev/null +++ b/src/ObjLoading/Game/IW4/RawFile/LoaderRawFileIW4.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW4/IW4.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW4 +{ + std::unique_ptr> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/Shader/LoaderPixelShaderIW4.cpp b/src/ObjLoading/Game/IW4/Shader/LoaderPixelShaderIW4.cpp new file mode 100644 index 00000000..670e6879 --- /dev/null +++ b/src/ObjLoading/Game/IW4/Shader/LoaderPixelShaderIW4.cpp @@ -0,0 +1,67 @@ +#include "LoaderPixelShaderIW4.h" + +#include "Game/IW4/IW4.h" + +#include +#include +#include + +using namespace IW4; + +namespace +{ + class PixelShaderLoader final : public AssetCreator + { + public: + PixelShaderLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto fileName = GetPixelShaderFileName(assetName); + const auto file = m_search_path.Open(fileName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + if (file.m_length % sizeof(uint32_t) != 0) + { + std::cerr << std::format("Invalid pixel shader \"{}\": Size must be dividable by {}\n", assetName, sizeof(uint32_t)); + return AssetCreationResult::Failure(); + } + + auto* pixelShader = m_memory.Alloc(); + pixelShader->name = m_memory.Dup(assetName.c_str()); + pixelShader->prog.loadDef.programSize = static_cast(static_cast(file.m_length) / sizeof(uint32_t)); + pixelShader->prog.loadDef.loadForRenderer = 0; + pixelShader->prog.ps = nullptr; + + auto* fileBuffer = m_memory.Alloc(pixelShader->prog.loadDef.programSize); + file.m_stream->read(reinterpret_cast(fileBuffer), static_cast(pixelShader->prog.loadDef.programSize) * sizeof(uint32_t)); + if (file.m_stream->gcount() != file.m_length) + return AssetCreationResult::Failure(); + + pixelShader->prog.loadDef.program = fileBuffer; + return AssetCreationResult::Success(context.AddAsset(assetName, pixelShader)); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace IW4 +{ + std::string GetPixelShaderFileName(const std::string& pixelShaderAssetName) + { + return std::format("shader_bin/ps_{}.cso", pixelShaderAssetName); + } + + std::unique_ptr> CreatePixelShaderLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/Shader/LoaderPixelShaderIW4.h b/src/ObjLoading/Game/IW4/Shader/LoaderPixelShaderIW4.h new file mode 100644 index 00000000..d29d29ba --- /dev/null +++ b/src/ObjLoading/Game/IW4/Shader/LoaderPixelShaderIW4.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW4/IW4.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW4 +{ + [[nodiscard]] std::string GetPixelShaderFileName(const std::string& pixelShaderAssetName); + + std::unique_ptr> CreatePixelShaderLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/Shader/LoaderVertexShaderIW4.cpp b/src/ObjLoading/Game/IW4/Shader/LoaderVertexShaderIW4.cpp new file mode 100644 index 00000000..6c1dd5bb --- /dev/null +++ b/src/ObjLoading/Game/IW4/Shader/LoaderVertexShaderIW4.cpp @@ -0,0 +1,67 @@ +#include "LoaderVertexShaderIW4.h" + +#include "Game/IW4/IW4.h" + +#include +#include +#include + +using namespace IW4; + +namespace +{ + class VertexShaderLoader final : public AssetCreator + { + public: + VertexShaderLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto fileName = GetVertexShaderFileName(assetName); + const auto file = m_search_path.Open(fileName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + if (file.m_length % sizeof(uint32_t) != 0) + { + std::cerr << std::format("Invalid vertex shader \"{}\": Size must be dividable by {}\n", assetName, sizeof(uint32_t)); + return AssetCreationResult::Failure(); + } + + auto* vertexShader = m_memory.Alloc(); + vertexShader->name = m_memory.Dup(assetName.c_str()); + vertexShader->prog.loadDef.programSize = static_cast(static_cast(file.m_length) / sizeof(uint32_t)); + vertexShader->prog.loadDef.loadForRenderer = 0; + vertexShader->prog.vs = nullptr; + + auto* fileBuffer = m_memory.Alloc(vertexShader->prog.loadDef.programSize); + file.m_stream->read(reinterpret_cast(fileBuffer), static_cast(vertexShader->prog.loadDef.programSize) * sizeof(uint32_t)); + if (file.m_stream->gcount() != file.m_length) + return AssetCreationResult::Failure(); + + vertexShader->prog.loadDef.program = fileBuffer; + return AssetCreationResult::Success(context.AddAsset(assetName, vertexShader)); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace IW4 +{ + std::string GetVertexShaderFileName(const std::string& vertexShaderAssetName) + { + return std::format("shader_bin/vs_{}.cso", vertexShaderAssetName); + } + + std::unique_ptr> CreateVertexShaderLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/Shader/LoaderVertexShaderIW4.h b/src/ObjLoading/Game/IW4/Shader/LoaderVertexShaderIW4.h new file mode 100644 index 00000000..e8139af0 --- /dev/null +++ b/src/ObjLoading/Game/IW4/Shader/LoaderVertexShaderIW4.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW4/IW4.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW4 +{ + [[nodiscard]] std::string GetVertexShaderFileName(const std::string& vertexShaderAssetName); + + std::unique_ptr> CreateVertexShaderLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/Sound/LoaderSoundCurveIW4.cpp b/src/ObjLoading/Game/IW4/Sound/LoaderSoundCurveIW4.cpp new file mode 100644 index 00000000..5f760754 --- /dev/null +++ b/src/ObjLoading/Game/IW4/Sound/LoaderSoundCurveIW4.cpp @@ -0,0 +1,78 @@ +#include "LoaderSoundCurveIW4.h" + +#include "Game/IW4/IW4.h" +#include "ObjLoading.h" +#include "Parsing/Graph2D/Graph2DReader.h" +#include "Pool/GlobalAssetPool.h" + +#include +#include +#include +#include + +using namespace IW4; + +namespace +{ + class LoaderSoundCurve final : public AssetCreator + { + public: + LoaderSoundCurve(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto fileName = std::format("soundaliases/{}.vfcurve", assetName); + const auto file = m_search_path.Open(fileName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + const auto sndCurveData = graph2d::Read("sound curve", "SNDCURVE", *file.m_stream, fileName, assetName); + + if (!sndCurveData) + return AssetCreationResult::Failure(); + + if (sndCurveData->knots.size() > std::extent_v) + { + std::cerr << std::format("Failed to load SndCurve \"{}\": Too many knots ({})\n", assetName, sndCurveData->knots.size()); + return AssetCreationResult::Failure(); + } + + auto* sndCurve = m_memory.Alloc(); + sndCurve->filename = m_memory.Dup(assetName.c_str()); + sndCurve->knotCount = static_cast(sndCurveData->knots.size()); + + for (auto i = 0u; i < std::extent_v; i++) + { + if (i < sndCurveData->knots.size()) + { + const auto& [x, y] = sndCurveData->knots[i]; + sndCurve->knots[i][0] = static_cast(x); + sndCurve->knots[i][1] = static_cast(y); + } + else + { + sndCurve->knots[i][0] = 0; + sndCurve->knots[i][1] = 0; + } + } + + return AssetCreationResult::Success(context.AddAsset(assetName, sndCurve)); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace IW4 +{ + std::unique_ptr> CreateSoundCurveLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/Sound/LoaderSoundCurveIW4.h b/src/ObjLoading/Game/IW4/Sound/LoaderSoundCurveIW4.h new file mode 100644 index 00000000..19f1bb3c --- /dev/null +++ b/src/ObjLoading/Game/IW4/Sound/LoaderSoundCurveIW4.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW4/IW4.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW4 +{ + std::unique_ptr> CreateSoundCurveLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/StringTable/LoaderStringTableIW4.cpp b/src/ObjLoading/Game/IW4/StringTable/LoaderStringTableIW4.cpp new file mode 100644 index 00000000..d4530772 --- /dev/null +++ b/src/ObjLoading/Game/IW4/StringTable/LoaderStringTableIW4.cpp @@ -0,0 +1,47 @@ +#include "LoaderStringTableIW4.h" + +#include "Csv/CsvStream.h" +#include "Game/IW4/CommonIW4.h" +#include "Game/IW4/IW4.h" +#include "StringTable/StringTableLoader.h" + +using namespace IW4; + +namespace +{ + class LoaderStringTable final : public AssetCreator + { + public: + LoaderStringTable(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto file = m_search_path.Open(assetName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + string_table::StringTableLoaderV2 loader; + auto* stringTable = loader.LoadFromStream(assetName, m_memory, *file.m_stream); + if (!stringTable) + return AssetCreationResult::Failure(); + + return AssetCreationResult::Success(context.AddAsset(assetName, stringTable)); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace IW4 +{ + std::unique_ptr> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/StringTable/LoaderStringTableIW4.h b/src/ObjLoading/Game/IW4/StringTable/LoaderStringTableIW4.h new file mode 100644 index 00000000..c9cbd55f --- /dev/null +++ b/src/ObjLoading/Game/IW4/StringTable/LoaderStringTableIW4.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW4/IW4.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW4 +{ + std::unique_ptr> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/StructuredDataDef/LoaderStructuredDataDefIW4.cpp b/src/ObjLoading/Game/IW4/StructuredDataDef/LoaderStructuredDataDefIW4.cpp new file mode 100644 index 00000000..1e74175c --- /dev/null +++ b/src/ObjLoading/Game/IW4/StructuredDataDef/LoaderStructuredDataDefIW4.cpp @@ -0,0 +1,216 @@ +#include "LoaderStructuredDataDefIW4.h" + +#include "Game/IW4/IW4.h" +#include "StructuredDataDef/StructuredDataDefReader.h" +#include "Utils/Alignment.h" + +#include +#include + +using namespace IW4; + +namespace +{ + class StructuredDataDefLoader final : public AssetCreator + { + public: + StructuredDataDefLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto file = m_search_path.Open(assetName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + StructuredDataDefReader reader(*file.m_stream, assetName, m_search_path); + + bool readingDefsSuccessful; + const auto defs = reader.ReadStructureDataDefs(readingDefsSuccessful); + + if (!readingDefsSuccessful) + return AssetCreationResult::Failure(); + + return AssetCreationResult::Success(context.AddAsset(assetName, ConvertSet(assetName, defs))); + } + + private: + StructuredDataType ConvertType(CommonStructuredDataType inputType) + { + switch (inputType.m_category) + { + case CommonStructuredDataTypeCategory::INT: + return {DATA_INT, {0}}; + case CommonStructuredDataTypeCategory::BYTE: + return {DATA_BYTE, {0}}; + case CommonStructuredDataTypeCategory::BOOL: + return {DATA_BOOL, {0}}; + case CommonStructuredDataTypeCategory::FLOAT: + return {DATA_FLOAT, {0}}; + case CommonStructuredDataTypeCategory::SHORT: + return {DATA_SHORT, {0}}; + case CommonStructuredDataTypeCategory::STRING: + return {DATA_STRING, {inputType.m_info.string_length}}; + case CommonStructuredDataTypeCategory::ENUM: + return {DATA_ENUM, {inputType.m_info.type_index}}; + case CommonStructuredDataTypeCategory::STRUCT: + return {DATA_STRUCT, {inputType.m_info.type_index}}; + case CommonStructuredDataTypeCategory::INDEXED_ARRAY: + return {DATA_INDEXED_ARRAY, {inputType.m_info.type_index}}; + case CommonStructuredDataTypeCategory::ENUM_ARRAY: + return {DATA_ENUM_ARRAY, {inputType.m_info.type_index}}; + case CommonStructuredDataTypeCategory::UNKNOWN: + default: + assert(false); + return {DATA_INT, {0}}; + } + } + + void ConvertEnum(CommonStructuredDataEnum& inputEnum, StructuredDataEnum& outputEnum) + { + outputEnum.entryCount = static_cast(inputEnum.m_entries.size()); + if (inputEnum.m_reserved_entry_count <= 0) + outputEnum.reservedEntryCount = outputEnum.entryCount; + else + outputEnum.reservedEntryCount = inputEnum.m_reserved_entry_count; + + inputEnum.SortEntriesByName(); + if (!inputEnum.m_entries.empty()) + { + outputEnum.entries = m_memory.Alloc(inputEnum.m_entries.size()); + for (auto entryIndex = 0u; entryIndex < inputEnum.m_entries.size(); entryIndex++) + { + auto& outputEntry = outputEnum.entries[entryIndex]; + const auto& inputEntry = inputEnum.m_entries[entryIndex]; + + outputEntry.string = m_memory.Dup(inputEntry.m_name.c_str()); + outputEntry.index = static_cast(inputEntry.m_value); + } + } + else + outputEnum.entries = nullptr; + } + + void ConvertStruct(CommonStructuredDataStruct& inputStruct, StructuredDataStruct& outputStruct) + { + outputStruct.size = static_cast(inputStruct.m_size_in_byte); + outputStruct.bitOffset = inputStruct.m_bit_offset; + + outputStruct.propertyCount = static_cast(inputStruct.m_properties.size()); + inputStruct.SortPropertiesByName(); + if (!inputStruct.m_properties.empty()) + { + outputStruct.properties = m_memory.Alloc(inputStruct.m_properties.size()); + for (auto propertyIndex = 0u; propertyIndex < inputStruct.m_properties.size(); propertyIndex++) + { + auto& outputProperty = outputStruct.properties[propertyIndex]; + const auto& inputProperty = inputStruct.m_properties[propertyIndex]; + + outputProperty.name = m_memory.Dup(inputProperty.m_name.c_str()); + outputProperty.type = ConvertType(inputProperty.m_type); + + if (outputProperty.type.type != DATA_BOOL) + { + assert(inputProperty.m_offset_in_bits % 8 == 0); + outputProperty.offset = inputProperty.m_offset_in_bits / 8; + } + else + outputProperty.offset = inputProperty.m_offset_in_bits; + } + } + else + outputStruct.properties = nullptr; + } + + void ConvertIndexedArray(const CommonStructuredDataIndexedArray& inputIndexedArray, StructuredDataIndexedArray& outputIndexedArray) + { + outputIndexedArray.arraySize = static_cast(inputIndexedArray.m_element_count); + outputIndexedArray.elementType = ConvertType(inputIndexedArray.m_array_type); + outputIndexedArray.elementSize = utils::Align(inputIndexedArray.m_element_size_in_bits, 8u) / 8u; + } + + void ConvertEnumedArray(const CommonStructuredDataEnumedArray& inputEnumedArray, StructuredDataEnumedArray& outputEnumedArray) + { + outputEnumedArray.enumIndex = static_cast(inputEnumedArray.m_enum_index); + outputEnumedArray.elementType = ConvertType(inputEnumedArray.m_array_type); + outputEnumedArray.elementSize = utils::Align(inputEnumedArray.m_element_size_in_bits, 8u) / 8u; + } + + void ConvertDef(const CommonStructuredDataDef& inputDef, StructuredDataDef& outputDef) + { + outputDef.version = inputDef.m_version; + outputDef.formatChecksum = inputDef.m_checksum; + + outputDef.enumCount = static_cast(inputDef.m_enums.size()); + if (!inputDef.m_enums.empty()) + { + outputDef.enums = m_memory.Alloc(inputDef.m_enums.size()); + for (auto enumIndex = 0u; enumIndex < inputDef.m_enums.size(); enumIndex++) + ConvertEnum(*inputDef.m_enums[enumIndex], outputDef.enums[enumIndex]); + } + else + outputDef.enums = nullptr; + + outputDef.structCount = static_cast(inputDef.m_structs.size()); + if (!inputDef.m_structs.empty()) + { + outputDef.structs = m_memory.Alloc(inputDef.m_structs.size()); + for (auto structIndex = 0u; structIndex < inputDef.m_structs.size(); structIndex++) + ConvertStruct(*inputDef.m_structs[structIndex], outputDef.structs[structIndex]); + } + else + outputDef.structs = nullptr; + + outputDef.indexedArrayCount = static_cast(inputDef.m_indexed_arrays.size()); + if (!inputDef.m_indexed_arrays.empty()) + { + outputDef.indexedArrays = m_memory.Alloc(inputDef.m_indexed_arrays.size()); + for (auto indexedArrayIndex = 0u; indexedArrayIndex < inputDef.m_indexed_arrays.size(); indexedArrayIndex++) + ConvertIndexedArray(inputDef.m_indexed_arrays[indexedArrayIndex], outputDef.indexedArrays[indexedArrayIndex]); + } + else + outputDef.indexedArrays = nullptr; + + outputDef.enumedArrayCount = static_cast(inputDef.m_enumed_arrays.size()); + if (!inputDef.m_enumed_arrays.empty()) + { + outputDef.enumedArrays = m_memory.Alloc(inputDef.m_enumed_arrays.size()); + for (auto enumedArrayIndex = 0u; enumedArrayIndex < inputDef.m_enumed_arrays.size(); enumedArrayIndex++) + ConvertEnumedArray(inputDef.m_enumed_arrays[enumedArrayIndex], outputDef.enumedArrays[enumedArrayIndex]); + } + else + outputDef.enumedArrays = nullptr; + + outputDef.rootType = ConvertType(inputDef.m_root_type); + outputDef.size = inputDef.m_size_in_byte; + } + + StructuredDataDefSet* ConvertSet(const std::string& assetName, const std::vector>& commonDefs) + { + auto* set = m_memory.Alloc(); + set->name = m_memory.Dup(assetName.c_str()); + + set->defCount = commonDefs.size(); + set->defs = m_memory.Alloc(commonDefs.size()); + + for (auto defIndex = 0u; defIndex < commonDefs.size(); defIndex++) + ConvertDef(*commonDefs[defIndex], set->defs[defIndex]); + + return set; + } + + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace IW4 +{ + std::unique_ptr> CreateStructuredDataDefLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/StructuredDataDef/LoaderStructuredDataDefIW4.h b/src/ObjLoading/Game/IW4/StructuredDataDef/LoaderStructuredDataDefIW4.h new file mode 100644 index 00000000..22d40f09 --- /dev/null +++ b/src/ObjLoading/Game/IW4/StructuredDataDef/LoaderStructuredDataDefIW4.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW4/IW4.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW4 +{ + std::unique_ptr> CreateStructuredDataDefLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp b/src/ObjLoading/Game/IW4/Techset/LoaderTechsetIW4.cpp similarity index 85% rename from src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp rename to src/ObjLoading/Game/IW4/Techset/LoaderTechsetIW4.cpp index c7b330ec..8362dc3e 100644 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp +++ b/src/ObjLoading/Game/IW4/Techset/LoaderTechsetIW4.cpp @@ -1,11 +1,9 @@ -#include "AssetLoaderTechniqueSet.h" +#include "LoaderTechsetIW4.h" -#include "AssetLoaderPixelShader.h" -#include "AssetLoaderVertexShader.h" #include "Game/IW4/IW4.h" +#include "Game/IW4/Shader/LoaderPixelShaderIW4.h" +#include "Game/IW4/Shader/LoaderVertexShaderIW4.h" #include "Game/IW4/TechsetConstantsIW4.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" #include "Shader/D3D9ShaderAnalyser.h" #include "StateMap/StateMapReader.h" #include "Techset/TechniqueFileReader.h" @@ -13,10 +11,13 @@ #include "Techset/TechsetDefinitionCache.h" #include "Techset/TechsetFileReader.h" #include "Utils/Alignment.h" -#include "Utils/ClassUtils.h" +#include +#include #include +#include #include +#include #include #include #include @@ -25,7 +26,7 @@ using namespace IW4; using namespace std::string_literals; -namespace IW4 +namespace { class LoadedTechnique { @@ -40,15 +41,11 @@ namespace IW4 } }; - class TechniqueZoneLoadingState final : public IZoneAssetLoaderState + class TechniqueZoneLoadingState final : public IZoneAssetCreationState { public: typedef const float (*literal_t)[4]; - private: - std::unordered_map> m_loaded_techniques; - std::map m_allocated_literals; - public: _NODISCARD const LoadedTechnique* FindLoadedTechnique(const std::string& techniqueName) const { @@ -65,14 +62,14 @@ namespace IW4 .first->second.get(); } - literal_t GetAllocatedLiteral(MemoryManager* memory, techset::ShaderArgumentLiteralSource source) + literal_t GetAllocatedLiteral(MemoryManager& memory, techset::ShaderArgumentLiteralSource source) { const auto& existingEntry = m_allocated_literals.find(source); if (existingEntry != m_allocated_literals.end()) return existingEntry->second; - auto* newLiteral = memory->Alloc(); + auto* newLiteral = memory.Alloc(); (*newLiteral)[0] = source.m_value[0]; (*newLiteral)[1] = source.m_value[1]; (*newLiteral)[2] = source.m_value[2]; @@ -81,20 +78,24 @@ namespace IW4 return newLiteral; } + + private: + std::unordered_map> m_loaded_techniques; + std::map m_allocated_literals; }; - class ShaderInfoFromFileSystemCacheState final : public IZoneAssetLoaderState + class ShaderInfoFromFileSystemCacheState final : public IZoneAssetCreationState { std::unordered_map> m_cached_shader_info; public: - _NODISCARD const d3d9::ShaderInfo* LoadShaderInfoFromDisk(ISearchPath* searchPath, const std::string& fileName) + [[nodiscard]] const d3d9::ShaderInfo* LoadShaderInfoFromDisk(ISearchPath& searchPath, const std::string& fileName) { const auto cachedShaderInfo = m_cached_shader_info.find(fileName); if (cachedShaderInfo != m_cached_shader_info.end()) return cachedShaderInfo->second.get(); - const auto file = searchPath->Open(fileName); + const auto file = searchPath.Open(fileName); if (!file.IsOpen()) return nullptr; @@ -102,7 +103,7 @@ namespace IW4 if (shaderSize % sizeof(uint32_t) != 0) { - std::cerr << "Invalid shader \"" << fileName << "\": Size must be dividable by " << sizeof(uint32_t) << "\n"; + std::cerr << std::format("Invalid shader \"{}\": Size must be dividable by {}\n", fileName, sizeof(uint32_t)); return nullptr; } @@ -121,14 +122,6 @@ namespace IW4 class TechniqueCreator final : public techset::ITechniqueDefinitionAcceptor { - const std::string& m_technique_name; - ISearchPath* const m_search_path; - MemoryManager* const m_memory; - IAssetLoadingManager* const m_manager; - TechniqueZoneLoadingState* const m_zone_state; - techset::TechniqueStateMapCache* const m_state_map_cache; - ShaderInfoFromFileSystemCacheState* const m_shader_info_cache; - public: class PassShaderArgument { @@ -206,20 +199,16 @@ namespace IW4 std::vector m_passes; std::vector m_dependencies; - TechniqueCreator(const std::string& techniqueName, - ISearchPath* searchPath, - MemoryManager* memory, - IAssetLoadingManager* manager, - TechniqueZoneLoadingState* zoneState, - ShaderInfoFromFileSystemCacheState* shaderInfoCache, - techset::TechniqueStateMapCache* stateMapCache) + TechniqueCreator( + const std::string& techniqueName, ISearchPath& searchPath, MemoryManager& memory, AssetCreationContext& context, ITechsetCreator* techsetCreator) : m_technique_name(techniqueName), m_search_path(searchPath), m_memory(memory), - m_manager(manager), - m_zone_state(zoneState), - m_state_map_cache(stateMapCache), - m_shader_info_cache(shaderInfoCache) + m_context(context), + m_zone_state(context.GetZoneAssetCreationState()), + m_state_map_cache(context.GetZoneAssetCreationState()), + m_shader_info_cache(context.GetZoneAssetCreationState()), + m_techset_creator(techsetCreator) { } @@ -391,7 +380,7 @@ namespace IW4 ss << materialStreamSourceAbbreviation[stream.source] << materialStreamDestinationAbbreviation[stream.dest]; } - pass.m_vertex_decl_asset = m_manager->LoadDependency(ss.str()); + pass.m_vertex_decl_asset = m_context.LoadDependency(ss.str()); } bool AcceptEndPass(std::string& errorMessage) override @@ -426,17 +415,17 @@ namespace IW4 bool AcceptStateMap(const std::string& stateMapName, std::string& errorMessage) override { - const auto* stateMap = AssetLoaderTechniqueSet::LoadStateMapDefinition(stateMapName, m_search_path, m_state_map_cache); + const auto* stateMap = m_techset_creator->LoadStateMapDefinition(stateMapName, m_context); if (!stateMap) { std::ostringstream ss; - ss << "Failed to load specified state map \"" << stateMapName << "\""; + ss << std::format("Failed to load specified state map \"{}\"", stateMapName); errorMessage = ss.str(); return false; } - m_state_map_cache->SetTechniqueUsesStateMap(m_technique_name, stateMap); + m_state_map_cache.SetTechniqueUsesStateMap(m_technique_name, stateMap); return true; } @@ -461,12 +450,10 @@ namespace IW4 bool AcceptVertexShader(const std::string& vertexShaderName, std::string& errorMessage) override { - auto* vertexShaderDependency = m_manager->LoadDependency(vertexShaderName); + auto* vertexShaderDependency = m_context.LoadDependency(vertexShaderName); if (vertexShaderDependency == nullptr) { - std::ostringstream ss; - ss << "Failed to load specified shader \"" << vertexShaderName << "\""; - errorMessage = ss.str(); + errorMessage = std::format("Failed to load specified shader \"{}\"", vertexShaderName); return false; } @@ -476,8 +463,7 @@ namespace IW4 if (pass.m_vertex_shader->Asset()->name && pass.m_vertex_shader->Asset()->name[0] == ',') { - pass.m_vertex_shader_info = - m_shader_info_cache->LoadShaderInfoFromDisk(m_search_path, AssetLoaderVertexShader::GetFileNameForAsset(vertexShaderName)); + pass.m_vertex_shader_info = m_shader_info_cache.LoadShaderInfoFromDisk(m_search_path, GetVertexShaderFileName(vertexShaderName)); } else { @@ -488,9 +474,7 @@ namespace IW4 if (!pass.m_vertex_shader_info) { - std::ostringstream ss; - ss << "No shader info for shader \"" << vertexShaderName << "\""; - errorMessage = ss.str(); + errorMessage = std::format("No shader info for shader \"{}\"", vertexShaderName); return false; } @@ -501,12 +485,10 @@ namespace IW4 bool AcceptPixelShader(const std::string& pixelShaderName, std::string& errorMessage) override { - auto* pixelShaderDependency = m_manager->LoadDependency(pixelShaderName); + auto* pixelShaderDependency = m_context.LoadDependency(pixelShaderName); if (pixelShaderDependency == nullptr) { - std::ostringstream ss; - ss << "Failed to load specified shader \"" << pixelShaderName << "\""; - errorMessage = ss.str(); + errorMessage = std::format("Failed to load specified shader \"{}\"", pixelShaderName); return false; } @@ -516,8 +498,7 @@ namespace IW4 if (pass.m_pixel_shader->Asset()->name && pass.m_pixel_shader->Asset()->name[0] == ',') { - pass.m_pixel_shader_info = - m_shader_info_cache->LoadShaderInfoFromDisk(m_search_path, AssetLoaderPixelShader::GetFileNameForAsset(pixelShaderName)); + pass.m_pixel_shader_info = m_shader_info_cache.LoadShaderInfoFromDisk(m_search_path, GetPixelShaderFileName(pixelShaderName)); } else { @@ -528,9 +509,7 @@ namespace IW4 if (!pass.m_pixel_shader_info) { - std::ostringstream ss; - ss << "No shader info for shader \"" << pixelShaderName << "\""; - errorMessage = ss.str(); + errorMessage = std::format("No shader info for shader \"{}\"", pixelShaderName); return false; } @@ -922,7 +901,7 @@ namespace IW4 } argument.dest = static_cast(shaderConstant.m_register_index + registerOffset); - argument.u.literalConst = m_zone_state->GetAllocatedLiteral(m_memory, source); + argument.u.literalConst = m_zone_state.GetAllocatedLiteral(m_memory, source); pass.m_arguments.emplace_back(argument); if (shader == techset::ShaderSelector::VERTEX_SHADER) @@ -1036,17 +1015,45 @@ namespace IW4 pass.m_vertex_decl.streamCount++; return true; } + + private: + const std::string& m_technique_name; + ISearchPath& m_search_path; + MemoryManager& m_memory; + AssetCreationContext& m_context; + TechniqueZoneLoadingState& m_zone_state; + techset::TechniqueStateMapCache& m_state_map_cache; + ShaderInfoFromFileSystemCacheState& m_shader_info_cache; + ITechsetCreator* m_techset_creator; }; class TechniqueLoader { - ISearchPath* m_search_path; - MemoryManager* m_memory; - IAssetLoadingManager* m_manager; - TechniqueZoneLoadingState* m_zone_state; - ShaderInfoFromFileSystemCacheState* m_shader_info_cache; - techset::TechniqueStateMapCache* m_state_map_cache; + public: + TechniqueLoader(ISearchPath& searchPath, MemoryManager& memory, AssetCreationContext& context, ITechsetCreator* techsetCreator) + : m_search_path(searchPath), + m_memory(memory), + m_context(context), + m_zone_state(context.GetZoneAssetCreationState()), + m_techset_creator(techsetCreator) + { + } + _NODISCARD const LoadedTechnique* LoadMaterialTechnique(const std::string& techniqueName) const + { + auto* technique = m_zone_state.FindLoadedTechnique(techniqueName); + if (technique) + return technique; + + std::vector dependencies; + auto* techniqueFromRaw = LoadTechniqueFromRaw(techniqueName, dependencies); + if (techniqueFromRaw == nullptr) + return nullptr; + + return m_zone_state.AddLoadedTechnique(techniqueName, techniqueFromRaw, dependencies); + } + + private: static void UpdateTechniqueFlags(MaterialTechnique& technique) { // This is stupid but that's what the game does for zprepass for sure @@ -1159,7 +1166,7 @@ namespace IW4 out.pixelShader = in.m_pixel_shader->Asset(); out.vertexDecl = in.m_vertex_decl_asset->Asset(); - out.args = m_memory->Alloc(in.m_arguments.size()); + out.args = m_memory.Alloc(in.m_arguments.size()); size_t perObjArgCount = 0u; size_t perPrimArgCount = 0u; @@ -1220,8 +1227,8 @@ namespace IW4 { assert(!passes.empty()); const auto techniqueSize = sizeof(MaterialTechnique) + (passes.size() - 1u) * sizeof(MaterialPass); - auto* technique = static_cast(m_memory->AllocRaw(techniqueSize)); - technique->name = m_memory->Dup(techniqueName.c_str()); + auto* technique = static_cast(m_memory.AllocRaw(techniqueSize)); + technique->name = m_memory.Dup(techniqueName.c_str()); technique->passCount = static_cast(passes.size()); UpdateTechniqueFlags(*technique); @@ -1234,12 +1241,12 @@ namespace IW4 MaterialTechnique* LoadTechniqueFromRaw(const std::string& techniqueName, std::vector& dependencies) const { - const auto techniqueFileName = AssetLoaderTechniqueSet::GetTechniqueFileName(techniqueName); - const auto file = m_search_path->Open(techniqueFileName); + const auto techniqueFileName = GetTechniqueFileName(techniqueName); + const auto file = m_search_path.Open(techniqueFileName); if (!file.IsOpen()) return nullptr; - TechniqueCreator creator(techniqueName, m_search_path, m_memory, m_manager, m_zone_state, m_shader_info_cache, m_state_map_cache); + TechniqueCreator creator(techniqueName, m_search_path, m_memory, m_context, m_techset_creator); const techset::TechniqueFileReader reader(*file.m_stream, techniqueFileName, &creator); if (!reader.ReadTechniqueDefinition()) return nullptr; @@ -1247,150 +1254,139 @@ namespace IW4 return ConvertTechnique(techniqueName, creator.m_passes, dependencies); } + ISearchPath& m_search_path; + MemoryManager& m_memory; + AssetCreationContext& m_context; + TechniqueZoneLoadingState& m_zone_state; + ITechsetCreator* m_techset_creator; + }; + + class TechsetLoader final : public ITechsetCreator + { public: - TechniqueLoader(ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) - : m_search_path(searchPath), - m_memory(memory), - m_manager(manager), - m_zone_state(manager->GetAssetLoadingContext()->GetZoneAssetLoaderState()), - m_shader_info_cache(manager->GetAssetLoadingContext()->GetZoneAssetLoaderState()), - m_state_map_cache(manager->GetAssetLoadingContext()->GetZoneAssetLoaderState()) + TechsetLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) { } - _NODISCARD const LoadedTechnique* LoadMaterialTechnique(const std::string& techniqueName) const + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - auto* technique = m_zone_state->FindLoadedTechnique(techniqueName); - if (technique) - return technique; + bool failure = false; + const auto* techsetDefinition = LoadTechsetDefinition(assetName, context, failure); + if (!techsetDefinition) + return failure ? AssetCreationResult::Failure() : AssetCreationResult::NoAction(); - std::vector dependencies; - auto* techniqueFromRaw = LoadTechniqueFromRaw(techniqueName, dependencies); - if (techniqueFromRaw == nullptr) + return CreateTechsetFromDefinition(assetName, *techsetDefinition, context); + } + + private: + AssetCreationResult + CreateTechsetFromDefinition(const std::string& assetName, const techset::TechsetDefinition& definition, AssetCreationContext& context) + { + auto* techset = m_memory.Alloc(); + techset->name = m_memory.Dup(assetName.c_str()); + + AssetRegistration registration(assetName, techset); + + const TechniqueLoader techniqueLoader(m_search_path, m_memory, context, this); + for (auto i = 0u; i < std::extent_v; i++) + { + std::string techniqueName; + if (definition.GetTechniqueByIndex(i, techniqueName)) + { + auto* technique = techniqueLoader.LoadMaterialTechnique(techniqueName); + + if (!technique) + return AssetCreationResult::Failure(); + + for (auto* techniqueDependency : technique->m_dependencies) + registration.AddDependency(techniqueDependency); + + techset->techniques[i] = technique->m_technique; + } + } + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); + } + + techset::TechsetDefinition* LoadTechsetDefinition(const std::string& assetName, AssetCreationContext& context, bool& failure) override + { + failure = false; + auto& definitionCache = context.GetZoneAssetCreationState(); + auto* cachedTechsetDefinition = definitionCache.GetCachedTechsetDefinition(assetName); + if (cachedTechsetDefinition) + return cachedTechsetDefinition; + + const auto techsetFileName = GetTechsetFileName(assetName); + const auto file = m_search_path.Open(techsetFileName); + if (!file.IsOpen()) return nullptr; - return m_zone_state->AddLoadedTechnique(techniqueName, techniqueFromRaw, dependencies); + const techset::TechsetFileReader reader(*file.m_stream, techsetFileName, techniqueTypeNames, std::extent_v); + auto techsetDefinition = reader.ReadTechsetDefinition(); + if (!techsetDefinition) + { + failure = true; + return nullptr; + } + + auto* techsetDefinitionPtr = techsetDefinition.get(); + + definitionCache.AddTechsetDefinitionToCache(assetName, std::move(techsetDefinition)); + + return techsetDefinitionPtr; } - }; -} // namespace IW4 -void* AssetLoaderTechniqueSet::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* techset = memory->Create(); - memset(techset, 0, sizeof(MaterialTechniqueSet)); - techset->name = memory->Dup(assetName.c_str()); - return techset; -} - -std::string AssetLoaderTechniqueSet::GetTechsetFileName(const std::string& techsetAssetName) -{ - std::ostringstream ss; - ss << "techsets/" << techsetAssetName << ".techset"; - return ss.str(); -} - -std::string AssetLoaderTechniqueSet::GetTechniqueFileName(const std::string& techniqueName) -{ - std::ostringstream ss; - ss << "techniques/" << techniqueName << ".tech"; - return ss.str(); -} - -std::string AssetLoaderTechniqueSet::GetStateMapFileName(const std::string& stateMapName) -{ - std::ostringstream ss; - ss << "statemaps/" << stateMapName << ".sm"; - return ss.str(); -} - -bool AssetLoaderTechniqueSet::CreateTechsetFromDefinition( - const std::string& assetName, const techset::TechsetDefinition& definition, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) -{ - auto* techset = memory->Create(); - memset(techset, 0, sizeof(MaterialTechniqueSet)); - techset->name = memory->Dup(assetName.c_str()); - - const TechniqueLoader techniqueLoader(searchPath, memory, manager); - std::set dependencies; - for (auto i = 0u; i < std::extent_v; i++) - { - std::string techniqueName; - if (definition.GetTechniqueByIndex(i, techniqueName)) + const state_map::StateMapDefinition* LoadStateMapDefinition(const std::string& stateMapName, AssetCreationContext& context) override { - auto* technique = techniqueLoader.LoadMaterialTechnique(techniqueName); + auto& stateMapCache = context.GetZoneAssetCreationState(); + auto* cachedStateMap = stateMapCache.GetCachedStateMap(stateMapName); + if (cachedStateMap) + return cachedStateMap; - if (!technique) - return false; + const auto stateMapFileName = GetStateMapFileName(stateMapName); + const auto file = m_search_path.Open(stateMapFileName); + if (!file.IsOpen()) + return nullptr; - for (auto* techniqueDependency : technique->m_dependencies) - dependencies.emplace(techniqueDependency); + const state_map::StateMapReader reader(*file.m_stream, stateMapFileName, stateMapName, stateMapLayout); + auto stateMapDefinition = reader.ReadStateMapDefinition(); + if (!stateMapDefinition) + return nullptr; - techset->techniques[i] = technique->m_technique; + const auto* stateMapDefinitionPtr = stateMapDefinition.get(); + + stateMapCache.AddStateMapToCache(std::move(stateMapDefinition)); + + return stateMapDefinitionPtr; } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace IW4 +{ + std::string GetTechsetFileName(const std::string& techsetAssetName) + { + return std::format("techsets/{}.techset", techsetAssetName); } - manager->AddAsset(assetName, techset, std::vector(dependencies.begin(), dependencies.end())); + std::string GetTechniqueFileName(const std::string& techniqueName) + { + return std::format("techniques/{}.tech", techniqueName); + } - return true; -} + std::string GetStateMapFileName(const std::string& stateMapName) + { + return std::format("statemaps/{}.sm", stateMapName); + } -techset::TechsetDefinition* - AssetLoaderTechniqueSet::LoadTechsetDefinition(const std::string& assetName, ISearchPath* searchPath, techset::TechsetDefinitionCache* definitionCache) -{ - auto* cachedTechsetDefinition = definitionCache->GetCachedTechsetDefinition(assetName); - if (cachedTechsetDefinition) - return cachedTechsetDefinition; - - const auto techsetFileName = GetTechsetFileName(assetName); - const auto file = searchPath->Open(techsetFileName); - if (!file.IsOpen()) - return nullptr; - - const techset::TechsetFileReader reader(*file.m_stream, techsetFileName, techniqueTypeNames, std::extent_v); - auto techsetDefinition = reader.ReadTechsetDefinition(); - auto* techsetDefinitionPtr = techsetDefinition.get(); - - definitionCache->AddTechsetDefinitionToCache(assetName, std::move(techsetDefinition)); - - return techsetDefinitionPtr; -} - -const state_map::StateMapDefinition* - AssetLoaderTechniqueSet::LoadStateMapDefinition(const std::string& stateMapName, ISearchPath* searchPath, techset::TechniqueStateMapCache* stateMapCache) -{ - auto* cachedStateMap = stateMapCache->GetCachedStateMap(stateMapName); - if (cachedStateMap) - return cachedStateMap; - - const auto stateMapFileName = GetStateMapFileName(stateMapName); - const auto file = searchPath->Open(stateMapFileName); - if (!file.IsOpen()) - return nullptr; - - const state_map::StateMapReader reader(*file.m_stream, stateMapFileName, stateMapName, stateMapLayout); - auto stateMapDefinition = reader.ReadStateMapDefinition(); - if (!stateMapDefinition) - return nullptr; - - const auto* stateMapDefinitionPtr = stateMapDefinition.get(); - - stateMapCache->AddStateMapToCache(std::move(stateMapDefinition)); - - return stateMapDefinitionPtr; -} - -bool AssetLoaderTechniqueSet::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderTechniqueSet::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - auto* definitionCache = manager->GetAssetLoadingContext()->GetZoneAssetLoaderState(); - const auto* techsetDefinition = LoadTechsetDefinition(assetName, searchPath, definitionCache); - if (techsetDefinition) - return CreateTechsetFromDefinition(assetName, *techsetDefinition, searchPath, memory, manager); - - return false; -} + std::unique_ptr CreateTechsetLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/Techset/LoaderTechsetIW4.h b/src/ObjLoading/Game/IW4/Techset/LoaderTechsetIW4.h new file mode 100644 index 00000000..2f246031 --- /dev/null +++ b/src/ObjLoading/Game/IW4/Techset/LoaderTechsetIW4.h @@ -0,0 +1,30 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW4/IW4.h" +#include "SearchPath/ISearchPath.h" +#include "StateMap/StateMapDefinition.h" +#include "Techset/TechsetDefinition.h" +#include "Utils/MemoryManager.h" + +#include +#include + +namespace IW4 +{ + [[nodiscard]] std::string GetTechsetFileName(const std::string& techsetAssetName); + [[nodiscard]] std::string GetTechniqueFileName(const std::string& techniqueName); + [[nodiscard]] std::string GetStateMapFileName(const std::string& stateMapName); + + class ITechsetCreator : public AssetCreator + { + public: + ITechsetCreator() = default; + virtual ~ITechsetCreator() = default; + + virtual techset::TechsetDefinition* LoadTechsetDefinition(const std::string& assetName, AssetCreationContext& context, bool& failure) = 0; + virtual const state_map::StateMapDefinition* LoadStateMapDefinition(const std::string& stateMapName, AssetCreationContext& context) = 0; + }; + + std::unique_ptr CreateTechsetLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/Techset/LoaderVertexDeclIW4.cpp b/src/ObjLoading/Game/IW4/Techset/LoaderVertexDeclIW4.cpp new file mode 100644 index 00000000..64071166 --- /dev/null +++ b/src/ObjLoading/Game/IW4/Techset/LoaderVertexDeclIW4.cpp @@ -0,0 +1,101 @@ +#include "LoaderVertexDeclIW4.h" + +#include "Game/IW4/IW4.h" +#include "Game/IW4/TechsetConstantsIW4.h" + +#include +#include +#include + +using namespace IW4; + +namespace +{ + class LoaderVertexDecl final : public AssetCreator + { + public: + LoaderVertexDecl(MemoryManager& memory) + : m_memory(memory) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + auto* decl = m_memory.Alloc(); + decl->name = m_memory.Dup(assetName.c_str()); + + size_t currentOffset = 0u; + + std::string sourceAbbreviation; + while (NextAbbreviation(assetName, sourceAbbreviation, currentOffset)) + { + if (decl->streamCount >= std::extent_v) + { + std::cerr << std::format("Failed to add vertex decl stream. Too many abbreviations: {}\n", assetName); + return AssetCreationResult::Failure(); + } + + std::string destinationAbbreviation; + if (!NextAbbreviation(assetName, destinationAbbreviation, currentOffset)) + { + std::cerr << std::format("Failed to detect vertex decl destination abbreviation: {}\n", assetName); + return AssetCreationResult::Failure(); + } + + const auto foundSourceAbbreviation = std::ranges::find(materialStreamSourceAbbreviation, sourceAbbreviation); + if (foundSourceAbbreviation == std::end(materialStreamSourceAbbreviation)) + { + std::cerr << std::format("Unknown vertex decl source abbreviation: {}\n", sourceAbbreviation); + return AssetCreationResult::Failure(); + } + + const auto foundDestinationAbbreviation = std::ranges::find(materialStreamDestinationAbbreviation, destinationAbbreviation); + if (foundDestinationAbbreviation == std::end(materialStreamDestinationAbbreviation)) + { + std::cerr << std::format("Unknown vertex decl destination abbreviation: {}\n", destinationAbbreviation); + return AssetCreationResult::Failure(); + } + + const auto sourceIndex = static_cast(foundSourceAbbreviation - std::begin(materialStreamSourceAbbreviation)); + const auto destinationIndex = + static_cast(foundDestinationAbbreviation - std::begin(materialStreamDestinationAbbreviation)); + + decl->routing.data[decl->streamCount].source = sourceIndex; + decl->routing.data[decl->streamCount].dest = destinationIndex; + decl->hasOptionalSource = decl->hasOptionalSource || sourceIndex >= STREAM_SRC_OPTIONAL_BEGIN; + decl->streamCount++; + } + + return AssetCreationResult::Success(context.AddAsset(assetName, decl)); + } + + static bool NextAbbreviation(const std::string& assetName, std::string& abbreviation, size_t& offset) + { + if (offset >= assetName.size()) + return false; + + if (offset + 1 < assetName.size() && isdigit(assetName[offset + 1])) + { + abbreviation = std::string(assetName, offset, 2); + offset += 2; + } + else + { + abbreviation = std::string(assetName, offset, 1); + offset += 1; + } + + return true; + } + + MemoryManager& m_memory; + }; +} // namespace + +namespace IW4 +{ + std::unique_ptr> CreateVertexDeclLoader(MemoryManager& memory) + { + return std::make_unique(memory); + } +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/Techset/LoaderVertexDeclIW4.h b/src/ObjLoading/Game/IW4/Techset/LoaderVertexDeclIW4.h new file mode 100644 index 00000000..d4bd1b68 --- /dev/null +++ b/src/ObjLoading/Game/IW4/Techset/LoaderVertexDeclIW4.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW4/IW4.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW4 +{ + std::unique_ptr> CreateVertexDeclLoader(MemoryManager& memory); +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/Weapon/GdtLoaderWeaponIW4.cpp b/src/ObjLoading/Game/IW4/Weapon/GdtLoaderWeaponIW4.cpp new file mode 100644 index 00000000..9b585add --- /dev/null +++ b/src/ObjLoading/Game/IW4/Weapon/GdtLoaderWeaponIW4.cpp @@ -0,0 +1,53 @@ +#include "GdtLoaderWeaponIW4.h" + +#include "Game/IW4/IW4.h" +#include "Game/IW4/ObjConstantsIW4.h" +#include "InfoString/InfoString.h" +#include "InfoStringLoaderWeaponIW4.h" + +#include +#include +#include + +using namespace IW4; + +namespace +{ + class GdtLoaderWeapon final : public AssetCreator + { + public: + GdtLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + : m_gdt(gdt), + m_info_string_loader(memory, searchPath, zone) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto* gdtEntry = m_gdt.GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_WEAPON, assetName); + if (gdtEntry == nullptr) + return AssetCreationResult::NoAction(); + + InfoString infoString; + if (!infoString.FromGdtProperties(*gdtEntry)) + { + std::cerr << std::format("Failed to read weapon gdt entry: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + return m_info_string_loader.CreateAsset(assetName, infoString, context); + } + + private: + IGdtQueryable& m_gdt; + InfoStringLoaderWeapon m_info_string_loader; + }; +} // namespace + +namespace IW4 +{ + std::unique_ptr> CreateGdtWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + { + return std::make_unique(memory, searchPath, gdt, zone); + } +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/Weapon/GdtLoaderWeaponIW4.h b/src/ObjLoading/Game/IW4/Weapon/GdtLoaderWeaponIW4.h new file mode 100644 index 00000000..44a699b8 --- /dev/null +++ b/src/ObjLoading/Game/IW4/Weapon/GdtLoaderWeaponIW4.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW4/IW4.h" +#include "Gdt/IGdtQueryable.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW4 +{ + std::unique_ptr> CreateGdtWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderWeapon.cpp b/src/ObjLoading/Game/IW4/Weapon/InfoStringLoaderWeaponIW4.cpp similarity index 67% rename from src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderWeapon.cpp rename to src/ObjLoading/Game/IW4/Weapon/InfoStringLoaderWeaponIW4.cpp index b46bc66e..5434043a 100644 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderWeapon.cpp +++ b/src/ObjLoading/Game/IW4/Weapon/InfoStringLoaderWeaponIW4.cpp @@ -1,19 +1,16 @@ -#include "AssetLoaderWeapon.h" +#include "InfoStringLoaderWeaponIW4.h" #include "Game/IW4/IW4.h" #include "Game/IW4/InfoString/EnumStrings.h" #include "Game/IW4/InfoString/InfoStringToStructConverter.h" -#include "Game/IW4/InfoString/WeaponFields.h" -#include "Game/IW4/ObjConstantsIW4.h" -#include "InfoString/InfoString.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" -#include "Utils/StringUtils.h" +#include "Game/IW4/Weapon/WeaponFields.h" #include "Weapon/AccuracyGraphLoader.h" +#include #include #include #include +#include using namespace IW4; @@ -32,7 +29,7 @@ namespace if (valueArray.size() > std::extent_v) { - std::cerr << "Cannot have more than " << std::extent_v << " hide tags!\n"; + std::cerr << std::format("Cannot have more than {} hide tags!\n", std::extent_v); return false; } @@ -40,7 +37,7 @@ namespace if (valueArray.size() < std::extent_v) { - m_used_script_string_list.emplace(m_zone_script_strings.AddOrGetScriptString(nullptr)); + m_registration.AddScriptString(m_zone_script_strings.AddOrGetScriptString(nullptr)); } auto currentHideTag = 0u; @@ -50,7 +47,7 @@ namespace const auto scrString = !currentValue.empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue) : m_zone_script_strings.AddOrGetScriptString(nullptr); hideTags[currentHideTag] = scrString; - m_used_script_string_list.emplace(scrString); + m_registration.AddScriptString(scrString); } for (; currentHideTag < std::extent_v; currentHideTag++) @@ -71,13 +68,13 @@ namespace } assert(std::extent_v == SURF_TYPE_NUM); - *bounceSound = m_memory->Alloc(SURF_TYPE_NUM); + *bounceSound = m_memory.Alloc(SURF_TYPE_NUM); for (auto i = 0u; i < SURF_TYPE_NUM; i++) { const auto currentBounceSound = value + bounceSoundSuffixes[i]; - (*bounceSound)[i].name = m_memory->Alloc(); - (*bounceSound)[i].name->soundName = m_memory->Dup(currentBounceSound.c_str()); + (*bounceSound)[i].name = m_memory.Alloc(); + (*bounceSound)[i].name->soundName = m_memory.Dup(currentBounceSound.c_str()); } return true; @@ -88,14 +85,14 @@ namespace std::vector> pairs; if (!ParseAsArray(value, pairs)) { - std::cerr << "Failed to parse notetrack" << mapName << "map as pairs\n"; + std::cerr << std::format("Failed to parse notetrack{}map as pairs\n", mapName); return false; } if (pairs.size() > std::extent_v) { - std::cerr << "Cannot have more than " << std::extent_v << " notetrack" << mapName - << "map entries!\n"; + std::cerr << std::format( + "Cannot have more than {} notetrack{}map entries!\n", std::extent_v, mapName); return false; } @@ -105,7 +102,7 @@ namespace if (pairs.size() < keyAndValueCount) { - m_used_script_string_list.emplace(m_zone_script_strings.AddOrGetScriptString(nullptr)); + m_registration.AddScriptString(m_zone_script_strings.AddOrGetScriptString(nullptr)); } for (; currentEntryNum < pairs.size(); currentEntryNum++) @@ -117,10 +114,10 @@ namespace : m_zone_script_strings.AddOrGetScriptString(nullptr); keys[currentEntryNum] = keyScriptString; - m_used_script_string_list.emplace(keyScriptString); + m_registration.AddScriptString(keyScriptString); values[currentEntryNum] = valueScriptString; - m_used_script_string_list.emplace(valueScriptString); + m_registration.AddScriptString(valueScriptString); } for (; currentEntryNum < keyAndValueCount; currentEntryNum++) @@ -138,7 +135,7 @@ namespace if (ConvertString(value, field.iOffset)) { if (!value.empty()) - m_indirect_asset_references.emplace(m_loading_manager->LoadIndirectAssetReference(value)); + m_registration.AddIndirectAssetReference(m_context.LoadIndirectAssetReference(value)); return true; } @@ -229,40 +226,41 @@ namespace public: InfoStringToWeaponConverter(const InfoString& infoString, - WeaponFullDef* weaponFullDef, + WeaponFullDef& weaponFullDef, ZoneScriptStrings& zoneScriptStrings, - MemoryManager* memory, - IAssetLoadingManager* manager, + MemoryManager& memory, + AssetCreationContext& context, + AssetRegistration& registration, const cspField_t* fields, const size_t fieldCount) - : InfoStringToStructConverter(infoString, weaponFullDef, zoneScriptStrings, memory, manager, fields, fieldCount) + : InfoStringToStructConverter(infoString, &weaponFullDef, zoneScriptStrings, memory, context, registration, fields, fieldCount) { } }; - void InitWeaponFullDef(WeaponFullDef* weapon) + void InitWeaponFullDef(WeaponFullDef& weapon) { - weapon->weapCompleteDef.weapDef = &weapon->weapDef; - weapon->weapCompleteDef.hideTags = weapon->hideTags; - weapon->weapCompleteDef.szXAnims = weapon->szXAnims; - weapon->weapDef.gunXModel = weapon->gunXModel; - weapon->weapDef.szXAnimsRightHanded = weapon->szXAnimsRightHanded; - weapon->weapDef.szXAnimsLeftHanded = weapon->szXAnimsLeftHanded; - weapon->weapDef.notetrackSoundMapKeys = weapon->notetrackSoundMapKeys; - weapon->weapDef.notetrackSoundMapValues = weapon->notetrackSoundMapValues; - weapon->weapDef.notetrackRumbleMapKeys = weapon->notetrackRumbleMapKeys; - weapon->weapDef.notetrackRumbleMapValues = weapon->notetrackRumbleMapValues; - weapon->weapDef.worldModel = weapon->worldModel; - weapon->weapDef.parallelBounce = weapon->parallelBounce; - weapon->weapDef.perpendicularBounce = weapon->perpendicularBounce; - weapon->weapDef.locationDamageMultipliers = weapon->locationDamageMultipliers; + weapon.weapCompleteDef.weapDef = &weapon.weapDef; + weapon.weapCompleteDef.hideTags = weapon.hideTags; + weapon.weapCompleteDef.szXAnims = weapon.szXAnims; + weapon.weapDef.gunXModel = weapon.gunXModel; + weapon.weapDef.szXAnimsRightHanded = weapon.szXAnimsRightHanded; + weapon.weapDef.szXAnimsLeftHanded = weapon.szXAnimsLeftHanded; + weapon.weapDef.notetrackSoundMapKeys = weapon.notetrackSoundMapKeys; + weapon.weapDef.notetrackSoundMapValues = weapon.notetrackSoundMapValues; + weapon.weapDef.notetrackRumbleMapKeys = weapon.notetrackRumbleMapKeys; + weapon.weapDef.notetrackRumbleMapValues = weapon.notetrackRumbleMapValues; + weapon.weapDef.worldModel = weapon.worldModel; + weapon.weapDef.parallelBounce = weapon.parallelBounce; + weapon.weapDef.perpendicularBounce = weapon.perpendicularBounce; + weapon.weapDef.locationDamageMultipliers = weapon.locationDamageMultipliers; for (const auto& field : weapon_fields) { if (field.iFieldType != CSPFT_STRING) continue; - *reinterpret_cast(reinterpret_cast(weapon) + field.iOffset) = ""; + *reinterpret_cast(reinterpret_cast(&weapon) + field.iOffset) = ""; } } @@ -313,10 +311,10 @@ namespace } } - void CalculateWeaponFields(WeaponFullDef* weapon, MemoryManager* memory) + void CalculateWeaponFields(WeaponFullDef& weapon, MemoryManager& memory) { - auto& weaponCompleteDef = weapon->weapCompleteDef; - auto& weaponDef = weapon->weapDef; + auto& weaponCompleteDef = weapon.weapCompleteDef; + auto& weaponDef = weapon.weapDef; if (!weaponDef.viewLastShotEjectEffect) weaponDef.viewLastShotEjectEffect = weaponDef.viewShellEjectEffect; @@ -376,10 +374,10 @@ namespace uint16_t& originalGraphKnotCount, vec2_t*& graphKnots, uint16_t& graphKnotCount, - MemoryManager* memory) + MemoryManager& memory) { originalGraphKnotCount = static_cast(graph.knots.size()); - originalGraphKnots = memory->Alloc(originalGraphKnotCount); + originalGraphKnots = memory.Alloc(originalGraphKnotCount); for (auto i = 0u; i < originalGraphKnotCount; i++) { @@ -392,116 +390,69 @@ namespace graphKnotCount = originalGraphKnotCount; } - bool LoadAccuracyGraphs(WeaponFullDef* weaponFullDef, MemoryManager* memory, const IAssetLoadingManager* manager) + bool LoadAccuracyGraphs(WeaponFullDef& weaponFullDef, MemoryManager& memory, ISearchPath& searchPath, AssetCreationContext& context) { - auto* accuracyGraphLoader = manager->GetAssetLoadingContext()->GetZoneAssetLoaderState(); + auto& accuracyGraphLoader = context.GetZoneAssetCreationState(); - if (weaponFullDef->weapDef.aiVsAiAccuracyGraphName && weaponFullDef->weapDef.aiVsAiAccuracyGraphName[0]) + if (weaponFullDef.weapDef.aiVsAiAccuracyGraphName && weaponFullDef.weapDef.aiVsAiAccuracyGraphName[0]) { - const auto* graph = accuracyGraphLoader->LoadAiVsAiGraph(manager, weaponFullDef->weapDef.aiVsAiAccuracyGraphName); + const auto* graph = accuracyGraphLoader.LoadAiVsAiGraph(searchPath, weaponFullDef.weapDef.aiVsAiAccuracyGraphName); if (!graph) return false; ConvertAccuracyGraph(*graph, - weaponFullDef->weapDef.originalAiVsAiAccuracyGraphKnots, - weaponFullDef->weapDef.originalAiVsAiAccuracyGraphKnotCount, - weaponFullDef->weapCompleteDef.aiVsAiAccuracyGraphKnots, - weaponFullDef->weapCompleteDef.aiVsAiAccuracyGraphKnotCount, + weaponFullDef.weapDef.originalAiVsAiAccuracyGraphKnots, + weaponFullDef.weapDef.originalAiVsAiAccuracyGraphKnotCount, + weaponFullDef.weapCompleteDef.aiVsAiAccuracyGraphKnots, + weaponFullDef.weapCompleteDef.aiVsAiAccuracyGraphKnotCount, memory); } - if (weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName && weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName[0]) + if (weaponFullDef.weapDef.aiVsPlayerAccuracyGraphName && weaponFullDef.weapDef.aiVsPlayerAccuracyGraphName[0]) { - const auto* graph = accuracyGraphLoader->LoadAiVsPlayerGraph(manager, weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName); + const auto* graph = accuracyGraphLoader.LoadAiVsPlayerGraph(searchPath, weaponFullDef.weapDef.aiVsPlayerAccuracyGraphName); if (!graph) return false; ConvertAccuracyGraph(*graph, - weaponFullDef->weapDef.originalAiVsPlayerAccuracyGraphKnots, - weaponFullDef->weapDef.originalAiVsPlayerAccuracyGraphKnotCount, - weaponFullDef->weapCompleteDef.aiVsPlayerAccuracyGraphKnots, - weaponFullDef->weapCompleteDef.aiVsPlayerAccuracyGraphKnotCount, + weaponFullDef.weapDef.originalAiVsPlayerAccuracyGraphKnots, + weaponFullDef.weapDef.originalAiVsPlayerAccuracyGraphKnotCount, + weaponFullDef.weapCompleteDef.aiVsPlayerAccuracyGraphKnots, + weaponFullDef.weapCompleteDef.aiVsPlayerAccuracyGraphKnotCount, memory); } return true; } - - bool LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) - { - auto* weaponFullDef = memory->Create(); - memset(weaponFullDef, 0, sizeof(WeaponFullDef)); - InitWeaponFullDef(weaponFullDef); - weaponFullDef->weapCompleteDef.szInternalName = memory->Dup(assetName.c_str()); - - InfoStringToWeaponConverter converter( - infoString, weaponFullDef, zone->m_script_strings, memory, manager, weapon_fields, std::extent_v); - if (!converter.Convert()) - { - std::cerr << "Failed to parse weapon: \"" << assetName << "\"\n"; - return true; - } - - CalculateWeaponFields(weaponFullDef, memory); - - LoadAccuracyGraphs(weaponFullDef, memory, manager); - - manager->AddAsset( - assetName, &weaponFullDef->weapCompleteDef, converter.GetDependencies(), converter.GetUsedScriptStrings(), converter.GetIndirectAssetReferences()); - - return true; - } } // namespace -void* AssetLoaderWeapon::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) +InfoStringLoaderWeapon::InfoStringLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_memory(memory), + m_search_path(searchPath), + m_zone(zone) { - auto* weapon = memory->Create(); - memset(weapon, 0, sizeof(WeaponCompleteDef)); - weapon->szInternalName = memory->Dup(assetName.c_str()); - return weapon; } -bool AssetLoaderWeapon::CanLoadFromGdt() const +AssetCreationResult InfoStringLoaderWeapon::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) { - return true; -} + auto* weaponFullDef = m_memory.Alloc(); -bool AssetLoaderWeapon::LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_WEAPON, assetName); - if (gdtEntry == nullptr) - return false; + InitWeaponFullDef(*weaponFullDef); + weaponFullDef->weapCompleteDef.szInternalName = m_memory.Dup(assetName.c_str()); - InfoString infoString; - if (!infoString.FromGdtProperties(*gdtEntry)) + AssetRegistration registration(assetName, &weaponFullDef->weapCompleteDef); + + InfoStringToWeaponConverter converter( + infoString, *weaponFullDef, m_zone.m_script_strings, m_memory, context, registration, weapon_fields, std::extent_v); + if (!converter.Convert()) { - std::cerr << "Failed to read weapon gdt entry: \"" << assetName << "\"\n"; - return true; + std::cerr << std::format("Failed to parse weapon: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); } - return LoadFromInfoString(infoString, assetName, memory, manager, zone); -} - -bool AssetLoaderWeapon::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderWeapon::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto fileName = "weapons/" + assetName; - const auto file = searchPath->Open(fileName); - if (!file.IsOpen()) - return false; - - InfoString infoString; - if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_WEAPON, *file.m_stream)) - { - std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n"; - return true; - } - - return LoadFromInfoString(infoString, assetName, memory, manager, zone); + CalculateWeaponFields(*weaponFullDef, m_memory); + + LoadAccuracyGraphs(*weaponFullDef, m_memory, m_search_path, context); + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); } diff --git a/src/ObjLoading/Game/IW4/Weapon/InfoStringLoaderWeaponIW4.h b/src/ObjLoading/Game/IW4/Weapon/InfoStringLoaderWeaponIW4.h new file mode 100644 index 00000000..59204d85 --- /dev/null +++ b/src/ObjLoading/Game/IW4/Weapon/InfoStringLoaderWeaponIW4.h @@ -0,0 +1,21 @@ +#pragma once + +#include "Asset/AssetCreationContext.h" +#include "Asset/AssetCreationResult.h" +#include "InfoString/InfoString.h" + +namespace IW4 +{ + class InfoStringLoaderWeapon + { + public: + InfoStringLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); + + AssetCreationResult CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context); + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + Zone& m_zone; + }; +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/Weapon/RawLoaderWeaponIW4.cpp b/src/ObjLoading/Game/IW4/Weapon/RawLoaderWeaponIW4.cpp new file mode 100644 index 00000000..a1b7b656 --- /dev/null +++ b/src/ObjLoading/Game/IW4/Weapon/RawLoaderWeaponIW4.cpp @@ -0,0 +1,54 @@ +#include "RawLoaderWeaponIW4.h" + +#include "Game/IW4/IW4.h" +#include "Game/IW4/ObjConstantsIW4.h" +#include "InfoString/InfoString.h" +#include "InfoStringLoaderWeaponIW4.h" + +#include +#include +#include + +using namespace IW4; + +namespace +{ + class RawLoaderWeapon final : public AssetCreator + { + public: + RawLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_search_path(searchPath), + m_info_string_loader(memory, searchPath, zone) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto fileName = std::format("weapons/{}", assetName); + const auto file = m_search_path.Open(fileName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + InfoString infoString; + if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_WEAPON, *file.m_stream)) + { + std::cerr << std::format("Could not parse as info string file: \"{}\"\n", fileName); + return AssetCreationResult::Failure(); + } + + return m_info_string_loader.CreateAsset(assetName, infoString, context); + } + + private: + ISearchPath& m_search_path; + InfoStringLoaderWeapon m_info_string_loader; + }; +} // namespace + +namespace IW4 +{ + std::unique_ptr> CreateRawWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + { + return std::make_unique(memory, searchPath, zone); + } +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/Weapon/RawLoaderWeaponIW4.h b/src/ObjLoading/Game/IW4/Weapon/RawLoaderWeaponIW4.h new file mode 100644 index 00000000..786d7ce3 --- /dev/null +++ b/src/ObjLoading/Game/IW4/Weapon/RawLoaderWeaponIW4.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW4/IW4.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW4 +{ + std::unique_ptr> CreateRawWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace IW4 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderAddonMapEnts.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderAddonMapEnts.cpp deleted file mode 100644 index c3109c50..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderAddonMapEnts.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderAddonMapEnts.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderAddonMapEnts::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* addonMapEnts = memory->Create(); - memset(addonMapEnts, 0, sizeof(AddonMapEnts)); - addonMapEnts->name = memory->Dup(assetName.c_str()); - return addonMapEnts; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderAddonMapEnts.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderAddonMapEnts.h deleted file mode 100644 index a1b308ac..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderAddonMapEnts.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderAddonMapEnts final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderClipMap.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderClipMap.cpp deleted file mode 100644 index 3f0e93b0..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderClipMap.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderClipMap.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderClipMap::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* clipMap = memory->Create(); - memset(clipMap, 0, sizeof(clipMap_t)); - clipMap->name = memory->Dup(assetName.c_str()); - return clipMap; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderClipMap.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderClipMap.h deleted file mode 100644 index 8b4d0d75..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderClipMap.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderClipMap : public BasicAssetLoader - { - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderComWorld.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderComWorld.cpp deleted file mode 100644 index 6cb25175..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderComWorld.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderComWorld.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderComWorld::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* comWorld = memory->Create(); - memset(comWorld, 0, sizeof(ComWorld)); - comWorld->name = memory->Dup(assetName.c_str()); - return comWorld; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderComWorld.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderComWorld.h deleted file mode 100644 index a491a99f..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderComWorld.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderComWorld final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFont.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFont.cpp deleted file mode 100644 index 121d92dc..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFont.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderFont.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderFont::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* font = memory->Create(); - memset(font, 0, sizeof(Font_s)); - font->fontName = memory->Dup(assetName.c_str()); - return font; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFont.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFont.h deleted file mode 100644 index ff08dd9f..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFont.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderFont final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFx.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFx.cpp deleted file mode 100644 index 613ec05f..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFx.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderFx.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderFx::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* fx = memory->Create(); - memset(fx, 0, sizeof(FxEffectDef)); - fx->name = memory->Dup(assetName.c_str()); - return fx; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFx.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFx.h deleted file mode 100644 index 1040158d..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFx.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderFx final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFxImpactTable.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFxImpactTable.cpp deleted file mode 100644 index f6a4c7bf..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFxImpactTable.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderFxImpactTable.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderFxImpactTable::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* fxImpactTable = memory->Create(); - memset(fxImpactTable, 0, sizeof(FxImpactTable)); - fxImpactTable->name = memory->Dup(assetName.c_str()); - return fxImpactTable; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFxImpactTable.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFxImpactTable.h deleted file mode 100644 index 577fe178..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFxImpactTable.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderFxImpactTable final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFxWorld.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFxWorld.cpp deleted file mode 100644 index 45b83494..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFxWorld.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderFxWorld.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderFxWorld::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* fxWorld = memory->Create(); - memset(fxWorld, 0, sizeof(FxWorld)); - fxWorld->name = memory->Dup(assetName.c_str()); - return fxWorld; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFxWorld.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFxWorld.h deleted file mode 100644 index 5e7005af..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderFxWorld.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderFxWorld final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGfxImage.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGfxImage.cpp deleted file mode 100644 index e6a1948e..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGfxImage.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "AssetLoaderGfxImage.h" - -#include "Game/IW5/IW5.h" -#include "Image/IwiLoader.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include -#include -#include - -using namespace IW5; - -void* AssetLoaderGfxImage::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} - -bool AssetLoaderGfxImage::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderGfxImage::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto fileName = std::format("images/{}.iwi", assetName); - const auto file = searchPath->Open(fileName); - if (!file.IsOpen()) - return false; - - const auto fileSize = static_cast(file.m_length); - const auto fileData = std::make_unique(fileSize); - file.m_stream->read(fileData.get(), fileSize); - - std::istringstream ss(std::string(fileData.get(), fileSize)); - const auto texture = iwi::LoadIwi(ss); - if (!texture) - { - std::cerr << std::format("Failed to load texture from: {}\n", fileName); - return false; - } - - auto* image = memory->Create(); - memset(image, 0, sizeof(GfxImage)); - - image->name = memory->Dup(assetName.c_str()); - image->noPicmip = !texture->HasMipMaps(); - image->width = static_cast(texture->GetWidth()); - image->height = static_cast(texture->GetHeight()); - image->depth = static_cast(texture->GetDepth()); - - image->texture.loadDef = memory->Alloc(); - - manager->AddAsset(assetName, image); - - return true; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGfxImage.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGfxImage.h deleted file mode 100644 index 7f2bec24..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGfxImage.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderGfxImage final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGfxLightDef.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGfxLightDef.cpp deleted file mode 100644 index d2bf64d3..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGfxLightDef.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderGfxLightDef.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderGfxLightDef::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* lightDef = memory->Create(); - memset(lightDef, 0, sizeof(GfxLightDef)); - lightDef->name = memory->Dup(assetName.c_str()); - return lightDef; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGfxLightDef.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGfxLightDef.h deleted file mode 100644 index 7bb44a97..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGfxLightDef.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderGfxLightDef final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGfxWorld.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGfxWorld.cpp deleted file mode 100644 index 40775533..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGfxWorld.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderGfxWorld.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderGfxWorld::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* gfxWorld = memory->Create(); - memset(gfxWorld, 0, sizeof(GfxWorld)); - gfxWorld->name = memory->Dup(assetName.c_str()); - return gfxWorld; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGfxWorld.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGfxWorld.h deleted file mode 100644 index d967cc06..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGfxWorld.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderGfxWorld final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGlassWorld.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGlassWorld.cpp deleted file mode 100644 index 418a844b..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGlassWorld.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderGlassWorld.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderGlassWorld::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* glassWorld = memory->Create(); - memset(glassWorld, 0, sizeof(GlassWorld)); - glassWorld->name = memory->Dup(assetName.c_str()); - return glassWorld; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGlassWorld.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGlassWorld.h deleted file mode 100644 index 6fb2162b..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderGlassWorld.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderGlassWorld final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderLeaderboard.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderLeaderboard.cpp deleted file mode 100644 index 25b25e48..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderLeaderboard.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "AssetLoaderLeaderboard.h" - -#include "Game/IW5/IW5.h" -#include "Game/IW5/Leaderboard/JsonLeaderboardDefLoader.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include -#include - -using namespace IW5; - -void* AssetLoaderLeaderboard::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* leaderboard = memory->Create(); - memset(leaderboard, 0, sizeof(LeaderboardDef)); - leaderboard->name = memory->Dup(assetName.c_str()); - return leaderboard; -} - -bool AssetLoaderLeaderboard::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderLeaderboard::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(std::format("leaderboards/{}.json", assetName)); - if (!file.IsOpen()) - return false; - - auto* leaderboardDef = memory->Alloc(); - leaderboardDef->name = memory->Dup(assetName.c_str()); - - if (LoadLeaderboardAsJson(*file.m_stream, *leaderboardDef, memory)) - manager->AddAsset(assetName, leaderboardDef); - else - std::cerr << std::format("Failed to load leaderboard \"{}\"\n", assetName); - - return true; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderLeaderboard.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderLeaderboard.h deleted file mode 100644 index 50c7cf72..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderLeaderboard.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderLeaderboard final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderLoadedSound.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderLoadedSound.cpp deleted file mode 100644 index 26a1106d..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderLoadedSound.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderLoadedSound.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderLoadedSound::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* loadedSound = memory->Create(); - memset(loadedSound, 0, sizeof(LoadedSound)); - loadedSound->name = memory->Dup(assetName.c_str()); - return loadedSound; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderLoadedSound.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderLoadedSound.h deleted file mode 100644 index cf6f0ca0..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderLoadedSound.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderLoadedSound final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderLocalizeEntry.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderLocalizeEntry.cpp deleted file mode 100644 index 94f9a42e..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderLocalizeEntry.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "AssetLoaderLocalizeEntry.h" - -#include "Localize/LocalizeCommonAssetLoader.h" - -using namespace IW5; - -XAssetInfoGeneric* AssetLoaderLocalizeEntry::LoadFromGlobalAssetPools(const std::string& assetName) const -{ - return nullptr; -} - -void* AssetLoaderLocalizeEntry::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - return nullptr; -} - -bool AssetLoaderLocalizeEntry::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderLocalizeEntry::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const LocalizeCommonAssetLoader commonLoader( - [memory, manager](const CommonLocalizeEntry& entry) - { - auto* localizeEntry = memory->Create(); - localizeEntry->name = memory->Dup(entry.m_key.c_str()); - localizeEntry->value = memory->Dup(entry.m_value.c_str()); - - manager->AddAsset(entry.m_key, localizeEntry); - }); - - return commonLoader.LoadLocalizeAsset(assetName, searchPath, manager, zone); -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderLocalizeEntry.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderLocalizeEntry.h deleted file mode 100644 index 5d8d7e92..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderLocalizeEntry.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderLocalizeEntry final : public BasicAssetLoader - { - public: - _NODISCARD XAssetInfoGeneric* LoadFromGlobalAssetPools(const std::string& assetName) const override; - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMapEnts.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMapEnts.cpp deleted file mode 100644 index 07f7781e..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMapEnts.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderMapEnts.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderMapEnts::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* mapEnts = memory->Create(); - memset(mapEnts, 0, sizeof(MapEnts)); - mapEnts->name = memory->Dup(assetName.c_str()); - return mapEnts; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMapEnts.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMapEnts.h deleted file mode 100644 index 783d475a..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMapEnts.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderMapEnts final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMaterial.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMaterial.cpp deleted file mode 100644 index 13170e20..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMaterial.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "AssetLoaderMaterial.h" - -#include "Game/IW5/IW5.h" -#include "Game/IW5/Material/JsonMaterialLoader.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include -#include - -using namespace IW5; - -void* AssetLoaderMaterial::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->info.name = memory->Dup(assetName.c_str()); - return asset; -} - -bool AssetLoaderMaterial::CanLoadFromRaw() const -{ - return true; -} - -std::string AssetLoaderMaterial::GetFileNameForAsset(const std::string& assetName) -{ - std::string sanitizedFileName(assetName); - if (sanitizedFileName[0] == '*') - { - std::ranges::replace(sanitizedFileName, '*', '_'); - const auto parenthesisPos = sanitizedFileName.find('('); - if (parenthesisPos != std::string::npos) - sanitizedFileName.erase(parenthesisPos); - sanitizedFileName = "generated/" + sanitizedFileName; - } - - return std::format("materials/{}.json", sanitizedFileName); -} - -bool AssetLoaderMaterial::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(GetFileNameForAsset(assetName)); - if (!file.IsOpen()) - return false; - - auto* material = memory->Alloc(); - material->info.name = memory->Dup(assetName.c_str()); - - std::vector dependencies; - if (LoadMaterialAsJson(*file.m_stream, *material, memory, manager, dependencies)) - manager->AddAsset(assetName, material, std::move(dependencies)); - else - std::cerr << std::format("Failed to load material \"{}\"\n", assetName); - - return true; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMaterial.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMaterial.h deleted file mode 100644 index f9f45d71..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMaterial.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderMaterial final : public BasicAssetLoader - { - static std::string GetFileNameForAsset(const std::string& assetName); - - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMenuDef.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMenuDef.cpp deleted file mode 100644 index dbbddba7..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMenuDef.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderMenuDef.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderMenuDef::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* menu = memory->Create(); - memset(menu, 0, sizeof(menuDef_t)); - menu->window.name = memory->Dup(assetName.c_str()); - return menu; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMenuDef.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMenuDef.h deleted file mode 100644 index 24764024..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMenuDef.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderMenuDef final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMenuList.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMenuList.cpp deleted file mode 100644 index ce698821..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMenuList.cpp +++ /dev/null @@ -1,233 +0,0 @@ -#include "AssetLoaderMenuList.h" - -#include "Game/IW5/IW5.h" -#include "Game/IW5/Menu/MenuConversionZoneStateIW5.h" -#include "Game/IW5/Menu/MenuConverterIW5.h" -#include "ObjLoading.h" -#include "Parsing/Menu/MenuFileReader.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include - -using namespace IW5; - -namespace IW5 -{ - class MenuLoader - { - public: - static bool ProcessParsedResults(const std::string& fileName, - ISearchPath* searchPath, - MemoryManager* memory, - IAssetLoadingManager* manager, - menu::ParsingResult* parsingResult, - menu::MenuAssetZoneState* zoneState, - MenuConversionZoneState* conversionState, - std::vector& menus, - std::vector& menuListDependencies) - { - const auto menuCount = parsingResult->m_menus.size(); - const auto functionCount = parsingResult->m_functions.size(); - const auto menuLoadCount = parsingResult->m_menus_to_load.size(); - auto totalItemCount = 0u; - for (const auto& menu : parsingResult->m_menus) - totalItemCount += menu->m_items.size(); - - std::cout << "Successfully read menu file \"" << fileName << "\" (" << menuLoadCount << " loads, " << menuCount << " menus, " << functionCount - << " functions, " << totalItemCount << " items)\n"; - - // Add all functions to the zone state to make them available for all menus to be converted - for (auto& function : parsingResult->m_functions) - zoneState->AddFunction(std::move(function)); - - // Prepare a list of all menus of this file - std::vector*> allMenusOfFile; - allMenusOfFile.reserve(parsingResult->m_menus.size()); - - // Convert all menus and add them as assets - for (auto& menu : parsingResult->m_menus) - { - MenuConverter converter(ObjLoading::Configuration.MenuNoOptimization, searchPath, memory, manager); - auto* menuAsset = converter.ConvertMenu(*menu); - if (menuAsset == nullptr) - { - std::cout << "Failed to convert menu file \"" << menu->m_name << "\"\n"; - return false; - } - - menus.push_back(menuAsset); - auto* menuAssetInfo = manager->AddAsset(menu->m_name, menuAsset, std::move(converter.GetDependencies())); - - if (menuAssetInfo) - { - allMenusOfFile.push_back(menuAssetInfo); - menuListDependencies.push_back(menuAssetInfo); - } - - zoneState->AddMenu(std::move(menu)); - } - - // Register this file with all loaded menus - conversionState->AddLoadedFile(fileName, std::move(allMenusOfFile)); - - return true; - } - - static MenuList* CreateMenuListAsset(const std::string& assetName, MemoryManager* memory, const std::vector& menus) - { - auto* menuListAsset = memory->Create(); - menuListAsset->name = memory->Dup(assetName.c_str()); - menuListAsset->menuCount = static_cast(menus.size()); - - if (menuListAsset->menuCount > 0) - { - menuListAsset->menus = memory->Alloc(menuListAsset->menuCount); - for (auto i = 0; i < menuListAsset->menuCount; i++) - menuListAsset->menus[i] = menus[i]; - } - else - menuListAsset->menus = nullptr; - - return menuListAsset; - } - - static std::unique_ptr - ParseMenuFile(const std::string& menuFileName, ISearchPath* searchPath, const menu::MenuAssetZoneState* zoneState) - { - const auto file = searchPath->Open(menuFileName); - if (!file.IsOpen()) - return nullptr; - - menu::MenuFileReader reader(*file.m_stream, - menuFileName, - menu::FeatureLevel::IW5, - [searchPath](const std::string& filename, const std::string& sourceFile) -> std::unique_ptr - { - auto foundFileToInclude = searchPath->Open(filename); - if (!foundFileToInclude.IsOpen() || !foundFileToInclude.m_stream) - return nullptr; - - return std::move(foundFileToInclude.m_stream); - }); - - reader.IncludeZoneState(zoneState); - reader.SetPermissiveMode(ObjLoading::Configuration.MenuPermissiveParsing); - - return reader.ReadMenuFile(); - } - }; -} // namespace IW5 - -void* AssetLoaderMenuList::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* menuList = memory->Create(); - memset(menuList, 0, sizeof(MenuList)); - menuList->name = memory->Dup(assetName.c_str()); - return menuList; -} - -bool AssetLoaderMenuList::CanLoadFromRaw() const -{ - return true; -} - -bool BuildMenuFileQueue(std::deque& menuLoadQueue, - const std::string& menuListAssetName, - ISearchPath* searchPath, - MemoryManager* memory, - IAssetLoadingManager* manager, - menu::MenuAssetZoneState* zoneState, - MenuConversionZoneState* conversionState, - std::vector& menus, - std::vector& menuListDependencies) -{ - const auto alreadyLoadedMenuListFileMenus = conversionState->m_menus_by_filename.find(menuListAssetName); - - if (alreadyLoadedMenuListFileMenus == conversionState->m_menus_by_filename.end()) - { - const auto menuListResult = MenuLoader::ParseMenuFile(menuListAssetName, searchPath, zoneState); - if (menuListResult) - { - MenuLoader::ProcessParsedResults( - menuListAssetName, searchPath, memory, manager, menuListResult.get(), zoneState, conversionState, menus, menuListDependencies); - - for (const auto& menuToLoad : menuListResult->m_menus_to_load) - menuLoadQueue.push_back(menuToLoad); - - zoneState->AddMenusToLoad(menuListAssetName, std::move(menuListResult->m_menus_to_load)); - } - else - return false; - } - - return true; -} - -void LoadMenuFileFromQueue(const std::string& menuFilePath, - ISearchPath* searchPath, - MemoryManager* memory, - IAssetLoadingManager* manager, - menu::MenuAssetZoneState* zoneState, - MenuConversionZoneState* conversionState, - std::vector& menus, - std::vector& menuListDependencies) -{ - const auto alreadyLoadedMenuFile = conversionState->m_menus_by_filename.find(menuFilePath); - if (alreadyLoadedMenuFile != conversionState->m_menus_by_filename.end()) - { - std::cout << "Already loaded \"" << menuFilePath << "\", skipping\n"; - for (auto* menu : alreadyLoadedMenuFile->second) - { - menus.push_back(menu->Asset()); - menuListDependencies.push_back(menu); - } - return; - } - - const auto menuFileResult = MenuLoader::ParseMenuFile(menuFilePath, searchPath, zoneState); - if (menuFileResult) - { - MenuLoader::ProcessParsedResults( - menuFilePath, searchPath, memory, manager, menuFileResult.get(), zoneState, conversionState, menus, menuListDependencies); - if (!menuFileResult->m_menus_to_load.empty()) - std::cout << "WARNING: Menu file has menus to load even though it is not a menu list, ignoring: \"" << menuFilePath << "\"\n"; - } - else - std::cerr << "Could not read menu file \"" << menuFilePath << "\"\n"; -} - -bool AssetLoaderMenuList::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - std::vector menus; - std::vector menuListDependencies; - - auto* zoneState = manager->GetAssetLoadingContext()->GetZoneAssetLoaderState(); - auto* conversionState = manager->GetAssetLoadingContext()->GetZoneAssetLoaderState(); - - std::deque menuLoadQueue; - if (!BuildMenuFileQueue(menuLoadQueue, assetName, searchPath, memory, manager, zoneState, conversionState, menus, menuListDependencies)) - return false; - - while (!menuLoadQueue.empty()) - { - const auto& menuFileToLoad = menuLoadQueue.front(); - - LoadMenuFileFromQueue(menuFileToLoad, searchPath, memory, manager, zoneState, conversionState, menus, menuListDependencies); - - menuLoadQueue.pop_front(); - } - - auto* menuListAsset = MenuLoader::CreateMenuListAsset(assetName, memory, menus); - - if (menuListAsset) - manager->AddAsset(assetName, menuListAsset, menuListDependencies); - - return true; -} - -void AssetLoaderMenuList::FinalizeAssetsForZone(AssetLoadingContext& context) const -{ - context.GetZoneAssetLoaderState()->FinalizeSupportingData(); -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMenuList.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMenuList.h deleted file mode 100644 index 00f42417..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMenuList.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderMenuList final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - void FinalizeAssetsForZone(AssetLoadingContext& context) const override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPathData.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPathData.cpp deleted file mode 100644 index e9959372..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPathData.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderPathData.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderPathData::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* pathData = memory->Create(); - memset(pathData, 0, sizeof(PathData)); - pathData->name = memory->Dup(assetName.c_str()); - return pathData; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPathData.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPathData.h deleted file mode 100644 index 700b0baf..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPathData.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderPathData final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPhysCollmap.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPhysCollmap.cpp deleted file mode 100644 index 544ad3ea..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPhysCollmap.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderPhysCollmap.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderPhysCollmap::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* collmap = memory->Create(); - memset(collmap, 0, sizeof(PhysCollmap)); - collmap->name = memory->Dup(assetName.c_str()); - return collmap; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPhysCollmap.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPhysCollmap.h deleted file mode 100644 index 08d76909..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPhysCollmap.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderPhysCollmap final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPhysPreset.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPhysPreset.cpp deleted file mode 100644 index ecfa646b..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPhysPreset.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderPhysPreset.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderPhysPreset::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* physPreset = memory->Create(); - memset(physPreset, 0, sizeof(PhysPreset)); - physPreset->name = memory->Dup(assetName.c_str()); - return physPreset; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPhysPreset.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPhysPreset.h deleted file mode 100644 index 59abe996..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPhysPreset.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderPhysPreset final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPixelShader.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPixelShader.cpp deleted file mode 100644 index 787118a7..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPixelShader.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderPixelShader.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderPixelShader::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* pixelShader = memory->Create(); - memset(pixelShader, 0, sizeof(MaterialPixelShader)); - pixelShader->name = memory->Dup(assetName.c_str()); - return pixelShader; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPixelShader.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPixelShader.h deleted file mode 100644 index 47bc4253..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderPixelShader.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderPixelShader final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderRawFile.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderRawFile.cpp deleted file mode 100644 index b1a9a0a7..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderRawFile.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "AssetLoaderRawFile.h" - -#include "Game/IW5/IW5.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include -#include -#include - -using namespace IW5; - -void* AssetLoaderRawFile::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* rawFile = memory->Create(); - memset(rawFile, 0, sizeof(RawFile)); - rawFile->name = memory->Dup(assetName.c_str()); - return rawFile; -} - -bool AssetLoaderRawFile::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderRawFile::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(assetName); - if (!file.IsOpen()) - return false; - - const auto uncompressedBuffer = std::make_unique(static_cast(file.m_length)); - file.m_stream->read(uncompressedBuffer.get(), file.m_length); - if (file.m_stream->gcount() != file.m_length) - return false; - - const auto compressionBufferSize = static_cast(file.m_length + COMPRESSED_BUFFER_SIZE_PADDING); - auto* compressedBuffer = memory->Alloc(compressionBufferSize); - - z_stream_s zs{}; - - zs.zalloc = Z_NULL; - zs.zfree = Z_NULL; - zs.opaque = Z_NULL; - zs.avail_in = static_cast(file.m_length); - zs.avail_out = compressionBufferSize; - zs.next_in = reinterpret_cast(uncompressedBuffer.get()); - zs.next_out = reinterpret_cast(compressedBuffer); - - int ret = deflateInit(&zs, Z_DEFAULT_COMPRESSION); - - if (ret != Z_OK) - { - throw std::runtime_error("Initializing deflate failed"); - } - - ret = deflate(&zs, Z_FINISH); - - if (ret != Z_STREAM_END) - { - std::cerr << "Deflate failed for loading rawfile \"" << assetName << "\"\n"; - deflateEnd(&zs); - return false; - } - - const auto compressedSize = compressionBufferSize - zs.avail_out; - - auto* rawFile = memory->Create(); - rawFile->name = memory->Dup(assetName.c_str()); - rawFile->compressedLen = static_cast(compressedSize); - rawFile->len = static_cast(file.m_length); - rawFile->buffer = static_cast(compressedBuffer); - - deflateEnd(&zs); - - manager->AddAsset(assetName, rawFile); - - return true; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderRawFile.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderRawFile.h deleted file mode 100644 index 94d235ef..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderRawFile.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderRawFile final : public BasicAssetLoader - { - static constexpr size_t COMPRESSED_BUFFER_SIZE_PADDING = 64; - - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderScriptFile.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderScriptFile.cpp deleted file mode 100644 index 84d4a8bb..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderScriptFile.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "AssetLoaderScriptFile.h" - -#include "Game/IW5/IW5.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include -#include - -using namespace IW5; - -void* AssetLoaderScriptFile::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* scriptFile = memory->Create(); - memset(scriptFile, 0, sizeof(ScriptFile)); - scriptFile->name = memory->Dup(assetName.c_str()); - return scriptFile; -} - -bool AssetLoaderScriptFile::CanLoadFromRaw() const -{ - return true; -} - -// See https://github.com/xensik/gsc-tool#file-format for an in-depth explanation about the .gscbin format -bool AssetLoaderScriptFile::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(assetName + ".gscbin"); - if (!file.IsOpen()) - return false; - - const auto fileBuffer = std::make_unique(static_cast(file.m_length)); - file.m_stream->read(fileBuffer.get(), file.m_length); - if (file.m_stream->gcount() != file.m_length) - return false; - - auto* scriptFile = memory->Create(); - scriptFile->name = memory->Dup(assetName.c_str()); - - // Retrieve data from the buffer - size_t offset = 0; - - // Read past the name pointer, we will use the one from assetName - offset += strlen(fileBuffer.get()) + 1; - - memcpy(&scriptFile->compressedLen, fileBuffer.get() + offset, sizeof(scriptFile->compressedLen)); - offset += sizeof(scriptFile->compressedLen); - - memcpy(&scriptFile->len, fileBuffer.get() + offset, sizeof(scriptFile->len)); - offset += sizeof(scriptFile->len); - - memcpy(&scriptFile->bytecodeLen, fileBuffer.get() + offset, sizeof(scriptFile->bytecodeLen)); - offset += sizeof(scriptFile->bytecodeLen); - - if (scriptFile->compressedLen <= 0 || scriptFile->bytecodeLen <= 0) - { - std::cerr << "Error: Invalid length of the buffers in " << assetName << " specified\n"; - return false; - } - - if (offset + (scriptFile->compressedLen + scriptFile->bytecodeLen) > file.m_length) - { - std::cerr << "Error: Specified length in " << assetName << " GSC BIN structure exceeds the actual file size\n"; - return false; - } - - scriptFile->buffer = memory->Alloc(scriptFile->compressedLen); - memcpy(const_cast(scriptFile->buffer), fileBuffer.get() + offset, scriptFile->compressedLen); - offset += scriptFile->compressedLen; - - scriptFile->bytecode = memory->Alloc(scriptFile->bytecodeLen); - memcpy(scriptFile->bytecode, fileBuffer.get() + offset, scriptFile->bytecodeLen); - - manager->AddAsset(assetName, scriptFile); - - return true; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderScriptFile.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderScriptFile.h deleted file mode 100644 index 3cb47778..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderScriptFile.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderScriptFile final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderSoundAliasList.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderSoundAliasList.cpp deleted file mode 100644 index 0a581719..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderSoundAliasList.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderSoundAliasList.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderSoundAliasList::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* sndAliasList = memory->Create(); - memset(sndAliasList, 0, sizeof(snd_alias_list_t)); - sndAliasList->aliasName = memory->Dup(assetName.c_str()); - return sndAliasList; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderSoundAliasList.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderSoundAliasList.h deleted file mode 100644 index 7301d230..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderSoundAliasList.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderSoundAliasList final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderSoundCurve.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderSoundCurve.cpp deleted file mode 100644 index 5d786501..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderSoundCurve.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderSoundCurve.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderSoundCurve::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* sndCurve = memory->Create(); - memset(sndCurve, 0, sizeof(SndCurve)); - sndCurve->filename = memory->Dup(assetName.c_str()); - return sndCurve; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderSoundCurve.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderSoundCurve.h deleted file mode 100644 index 15ced190..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderSoundCurve.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderSoundCurve final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderStringTable.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderStringTable.cpp deleted file mode 100644 index c91eceb9..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderStringTable.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "AssetLoaderStringTable.h" - -#include "Csv/CsvStream.h" -#include "Game/IW5/CommonIW5.h" -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" -#include "StringTable/StringTableLoader.h" - -#include - -using namespace IW5; - -void* AssetLoaderStringTable::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* stringTable = memory->Create(); - memset(stringTable, 0, sizeof(StringTable)); - stringTable->name = memory->Dup(assetName.c_str()); - return stringTable; -} - -bool AssetLoaderStringTable::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderStringTable::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(assetName); - if (!file.IsOpen()) - return false; - - string_table::StringTableLoaderV2 loader; - auto* stringTable = loader.LoadFromStream(assetName, *memory, *file.m_stream); - - manager->AddAsset(assetName, stringTable); - - return true; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderStringTable.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderStringTable.h deleted file mode 100644 index 80d1ce74..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderStringTable.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderStringTable final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderStructuredDataDef.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderStructuredDataDef.cpp deleted file mode 100644 index bc52d984..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderStructuredDataDef.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderStructuredDataDef.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderStructuredDataDef::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* structuredDataDefSet = memory->Create(); - memset(structuredDataDefSet, 0, sizeof(StructuredDataDefSet)); - structuredDataDefSet->name = memory->Dup(assetName.c_str()); - return structuredDataDefSet; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderStructuredDataDef.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderStructuredDataDef.h deleted file mode 100644 index 901d589e..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderStructuredDataDef.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderStructuredDataDef final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderSurfaceFxTable.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderSurfaceFxTable.cpp deleted file mode 100644 index 82cfd398..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderSurfaceFxTable.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderSurfaceFxTable.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderSurfaceFxTable::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* surfaceFxTable = memory->Create(); - memset(surfaceFxTable, 0, sizeof(SurfaceFxTable)); - surfaceFxTable->name = memory->Dup(assetName.c_str()); - return surfaceFxTable; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderSurfaceFxTable.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderSurfaceFxTable.h deleted file mode 100644 index 7ddda89c..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderSurfaceFxTable.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderSurfaceFxTable final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderTechniqueSet.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderTechniqueSet.cpp deleted file mode 100644 index 81aae5d7..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderTechniqueSet.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderTechniqueSet.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderTechniqueSet::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* techniqueSet = memory->Create(); - memset(techniqueSet, 0, sizeof(MaterialTechniqueSet)); - techniqueSet->name = memory->Dup(assetName.c_str()); - return techniqueSet; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderTechniqueSet.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderTechniqueSet.h deleted file mode 100644 index 9a280bd9..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderTechniqueSet.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderTechniqueSet final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderTracerDef.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderTracerDef.cpp deleted file mode 100644 index 91bf73f6..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderTracerDef.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderTracerDef.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderTracerDef::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* tracerDef = memory->Create(); - memset(tracerDef, 0, sizeof(TracerDef)); - tracerDef->name = memory->Dup(assetName.c_str()); - return tracerDef; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderTracerDef.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderTracerDef.h deleted file mode 100644 index 7233dc28..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderTracerDef.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderTracerDef final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVehicleDef.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVehicleDef.cpp deleted file mode 100644 index f60fca54..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVehicleDef.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderVehicleDef.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderVehicleDef::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* vehicleDef = memory->Create(); - memset(vehicleDef, 0, sizeof(VehicleDef)); - vehicleDef->name = memory->Dup(assetName.c_str()); - return vehicleDef; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVehicleDef.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVehicleDef.h deleted file mode 100644 index f17a38a2..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVehicleDef.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderVehicleDef final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVehicleTrack.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVehicleTrack.cpp deleted file mode 100644 index 4db1cb43..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVehicleTrack.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderVehicleTrack.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderVehicleTrack::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* vehicleTrack = memory->Create(); - memset(vehicleTrack, 0, sizeof(VehicleTrack)); - vehicleTrack->name = memory->Dup(assetName.c_str()); - return vehicleTrack; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVehicleTrack.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVehicleTrack.h deleted file mode 100644 index 66d171e5..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVehicleTrack.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderVehicleTrack final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVertexDecl.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVertexDecl.cpp deleted file mode 100644 index 96be5b97..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVertexDecl.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderVertexDecl.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderVertexDecl::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* vertexDecl = memory->Create(); - memset(vertexDecl, 0, sizeof(MaterialVertexDeclaration)); - vertexDecl->name = memory->Dup(assetName.c_str()); - return vertexDecl; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVertexDecl.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVertexDecl.h deleted file mode 100644 index 2e8d7685..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVertexDecl.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderVertexDecl final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVertexShader.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVertexShader.cpp deleted file mode 100644 index 267f1c76..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVertexShader.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderVertexShader.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderVertexShader::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* vertexShader = memory->Create(); - memset(vertexShader, 0, sizeof(MaterialVertexShader)); - vertexShader->name = memory->Dup(assetName.c_str()); - return vertexShader; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVertexShader.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVertexShader.h deleted file mode 100644 index dde8ba8d..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderVertexShader.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderVertexShader final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderWeapon.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderWeapon.h deleted file mode 100644 index 67495344..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderWeapon.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderWeapon final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromGdt() const override; - bool LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderWeaponAttachment.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderWeaponAttachment.cpp deleted file mode 100644 index 0d04b56d..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderWeaponAttachment.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "AssetLoaderWeaponAttachment.h" - -#include "Game/IW5/IW5.h" -#include "Game/IW5/Weapon/JsonWeaponAttachmentLoader.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include -#include - -using namespace IW5; - -void* AssetLoaderWeaponAttachment::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* attachment = memory->Create(); - memset(attachment, 0, sizeof(WeaponAttachment)); - attachment->szInternalName = memory->Dup(assetName.c_str()); - - return attachment; -} - -bool AssetLoaderWeaponAttachment::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderWeaponAttachment::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(std::format("attachment/{}.json", assetName)); - if (!file.IsOpen()) - return false; - - auto* attachment = memory->Alloc(); - attachment->szInternalName = memory->Dup(assetName.c_str()); - - std::vector dependencies; - std::vector indirectAssetReferences; - if (LoadWeaponAttachmentAsJson(*file.m_stream, *attachment, memory, manager, dependencies, indirectAssetReferences)) - manager->AddAsset(assetName, attachment, std::move(dependencies), std::vector(), std::move(indirectAssetReferences)); - else - std::cerr << "Failed to load attachment \"" << assetName << "\"\n"; - - return true; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderWeaponAttachment.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderWeaponAttachment.h deleted file mode 100644 index 72173e19..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderWeaponAttachment.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderWeaponAttachment final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderXAnim.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderXAnim.cpp deleted file mode 100644 index 0f0cc5e8..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderXAnim.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderXAnim.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderXAnim::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* anim = memory->Create(); - memset(anim, 0, sizeof(XAnimParts)); - anim->name = memory->Dup(assetName.c_str()); - return anim; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderXAnim.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderXAnim.h deleted file mode 100644 index 16bf60a3..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderXAnim.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderXAnim final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderXModel.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderXModel.cpp deleted file mode 100644 index 4f7f9629..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderXModel.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "AssetLoaderXModel.h" - -#include "Game/IW5/IW5.h" -#include "Game/IW5/XModel/XModelLoaderIW5.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include -#include - -using namespace IW5; - -void* AssetLoaderXModel::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} - -bool AssetLoaderXModel::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderXModel::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(std::format("xmodel/{}.json", assetName)); - if (!file.IsOpen()) - return false; - - auto* xmodel = memory->Alloc(); - xmodel->name = memory->Dup(assetName.c_str()); - - std::vector dependencies; - if (LoadXModel(*file.m_stream, *xmodel, memory, manager, dependencies)) - { - manager->AddAsset(assetName, xmodel, std::move(dependencies)); - } - else - { - std::cerr << std::format("Failed to load xmodel \"{}\"\n", assetName); - return false; - } - - return true; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderXModel.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderXModel.h deleted file mode 100644 index 3bee159f..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderXModel.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderXModel final : public BasicAssetLoader - { - static std::string GetFileNameForAsset(const std::string& assetName); - - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderXModelSurfs.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderXModelSurfs.cpp deleted file mode 100644 index 11952da7..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderXModelSurfs.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "AssetLoaderXModelSurfs.h" - -#include "Game/IW5/IW5.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace IW5; - -void* AssetLoaderXModelSurfs::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* modelSurfs = memory->Create(); - memset(modelSurfs, 0, sizeof(XModelSurfs)); - modelSurfs->name = memory->Dup(assetName.c_str()); - return modelSurfs; -} diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderXModelSurfs.h b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderXModelSurfs.h deleted file mode 100644 index 2487afbe..00000000 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderXModelSurfs.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/IW5/IW5.h" -#include "SearchPath/ISearchPath.h" - -namespace IW5 -{ - class AssetLoaderXModelSurfs final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Image/LoaderImageIW5.cpp b/src/ObjLoading/Game/IW5/Image/LoaderImageIW5.cpp new file mode 100644 index 00000000..f30d27e4 --- /dev/null +++ b/src/ObjLoading/Game/IW5/Image/LoaderImageIW5.cpp @@ -0,0 +1,69 @@ +#include "LoaderImageIW5.h" + +#include "Game/IW5/IW5.h" +#include "Image/IwiLoader.h" + +#include +#include +#include +#include + +using namespace IW5; + +namespace +{ + constexpr auto MAX_IMAGE_NAME_SIZE = 0x800; + + class ImageLoader final : public AssetCreator + { + public: + ImageLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto fileName = std::format("images/{}.iwi", assetName); + const auto file = m_search_path.Open(fileName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + const auto fileSize = static_cast(file.m_length); + const auto fileData = std::make_unique(fileSize); + file.m_stream->read(fileData.get(), fileSize); + + std::istringstream ss(std::string(fileData.get(), fileSize)); + const auto texture = iwi::LoadIwi(ss); + if (!texture) + { + std::cerr << std::format("Failed to load texture from: {}\n", fileName); + return AssetCreationResult::Failure(); + } + + auto* image = m_memory.Alloc(); + image->name = m_memory.Dup(assetName.c_str()); + image->noPicmip = !texture->HasMipMaps(); + image->width = static_cast(texture->GetWidth()); + image->height = static_cast(texture->GetHeight()); + image->depth = static_cast(texture->GetDepth()); + + image->texture.loadDef = m_memory.Alloc(); + + return AssetCreationResult::Success(context.AddAsset(assetName, image)); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace IW5 +{ + std::unique_ptr> CreateImageLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Image/LoaderImageIW5.h b/src/ObjLoading/Game/IW5/Image/LoaderImageIW5.h new file mode 100644 index 00000000..66609137 --- /dev/null +++ b/src/ObjLoading/Game/IW5/Image/LoaderImageIW5.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW5/IW5.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW5 +{ + std::unique_ptr> CreateImageLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/InfoString/InfoStringToStructConverter.cpp b/src/ObjLoading/Game/IW5/InfoString/InfoStringToStructConverter.cpp index 4d312202..63be576b 100644 --- a/src/ObjLoading/Game/IW5/InfoString/InfoStringToStructConverter.cpp +++ b/src/ObjLoading/Game/IW5/InfoString/InfoStringToStructConverter.cpp @@ -1,6 +1,7 @@ #include "InfoStringToStructConverter.h" #include +#include #include using namespace IW5; @@ -8,12 +9,12 @@ using namespace IW5; InfoStringToStructConverter::InfoStringToStructConverter(const InfoString& infoString, void* structure, ZoneScriptStrings& zoneScriptStrings, - MemoryManager* memory, - IAssetLoadingManager* manager, + MemoryManager& memory, + AssetCreationContext& context, + GenericAssetRegistration& registration, const cspField_t* fields, const size_t fieldCount) - : InfoStringToStructConverterBase(infoString, structure, zoneScriptStrings, memory), - m_loading_manager(manager), + : InfoStringToStructConverterBase(infoString, structure, zoneScriptStrings, memory, context, registration), m_fields(fields), m_field_count(fieldCount) { @@ -58,15 +59,15 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons return true; } - auto* fx = m_loading_manager->LoadDependency(value); + auto* fx = m_context.LoadDependency(value); if (fx == nullptr) { - std::cout << "Failed to load fx asset \"" << value << "\"\n"; + std::cerr << std::format("Failed to load fx asset \"{}\"\n", value); return false; } - m_dependencies.emplace(fx); + m_registration.AddDependency(fx); *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = fx->Asset(); return true; @@ -80,15 +81,15 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons return true; } - auto* xmodel = m_loading_manager->LoadDependency(value); + auto* xmodel = m_context.LoadDependency(value); if (xmodel == nullptr) { - std::cout << "Failed to load xmodel asset \"" << value << "\"\n"; + std::cerr << std::format("Failed to load xmodel asset \"{}\"\n", value); return false; } - m_dependencies.emplace(xmodel); + m_registration.AddDependency(xmodel); *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = xmodel->Asset(); return true; @@ -102,15 +103,15 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons return true; } - auto* material = m_loading_manager->LoadDependency(value); + auto* material = m_context.LoadDependency(value); if (material == nullptr) { - std::cout << "Failed to load material asset \"" << value << "\"\n"; + std::cerr << std::format("Failed to load material asset \"{}\"\n", value); return false; } - m_dependencies.emplace(material); + m_registration.AddDependency(material); *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = material->Asset(); return true; @@ -124,15 +125,15 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons return true; } - auto* tracer = m_loading_manager->LoadDependency(value); + auto* tracer = m_context.LoadDependency(value); if (tracer == nullptr) { - std::cout << "Failed to load tracer asset \"" << value << "\"\n"; + std::cerr << std::format("Failed to load tracer asset \"{}\"\n", value); return false; } - m_dependencies.emplace(tracer); + m_registration.AddDependency(tracer); *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = tracer->Asset(); return true; @@ -160,15 +161,15 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons return true; } - auto* collmap = m_loading_manager->LoadDependency(value); + auto* collmap = m_context.LoadDependency(value); if (collmap == nullptr) { - std::cout << "Failed to load collmap asset \"" << value << "\"\n"; + std::cerr << std::format("Failed to load collmap asset \"{}\"\n", value); return false; } - m_dependencies.emplace(collmap); + m_registration.AddDependency(collmap); *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = collmap->Asset(); return true; @@ -182,12 +183,12 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons return true; } - auto* name = m_memory->Alloc(); - name->soundName = m_memory->Dup(value.c_str()); + auto* name = m_memory.Alloc(); + name->soundName = m_memory.Dup(value.c_str()); reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset)->name = name; - m_indirect_asset_references.emplace(ASSET_TYPE_SOUND, value); + m_registration.AddIndirectAssetReference(m_context.LoadIndirectAssetReference(value)); return true; } diff --git a/src/ObjLoading/Game/IW5/InfoString/InfoStringToStructConverter.h b/src/ObjLoading/Game/IW5/InfoString/InfoStringToStructConverter.h index f2026e18..7e415486 100644 --- a/src/ObjLoading/Game/IW5/InfoString/InfoStringToStructConverter.h +++ b/src/ObjLoading/Game/IW5/InfoString/InfoStringToStructConverter.h @@ -1,5 +1,5 @@ #pragma once -#include "AssetLoading/IAssetLoadingManager.h" + #include "Game/IW5/IW5.h" #include "InfoString/InfoStringToStructConverterBase.h" @@ -7,24 +7,22 @@ namespace IW5 { class InfoStringToStructConverter : public InfoStringToStructConverterBase { - protected: - IAssetLoadingManager* m_loading_manager; - const cspField_t* m_fields; - size_t m_field_count; - - static bool GetHashValue(const std::string& value, unsigned int& hash); - - virtual bool ConvertExtensionField(const cspField_t& field, const std::string& value) = 0; - bool ConvertBaseField(const cspField_t& field, const std::string& value); - public: InfoStringToStructConverter(const InfoString& infoString, void* structure, ZoneScriptStrings& zoneScriptStrings, - MemoryManager* memory, - IAssetLoadingManager* manager, + MemoryManager& memory, + AssetCreationContext& context, + GenericAssetRegistration& registration, const cspField_t* fields, size_t fieldCount); bool Convert() override; + + protected: + virtual bool ConvertExtensionField(const cspField_t& field, const std::string& value) = 0; + bool ConvertBaseField(const cspField_t& field, const std::string& value); + + const cspField_t* m_fields; + size_t m_field_count; }; } // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Leaderboard/JsonLeaderboardDefLoader.cpp b/src/ObjLoading/Game/IW5/Leaderboard/JsonLeaderboardDefLoader.cpp index 092a510d..5c896d66 100644 --- a/src/ObjLoading/Game/IW5/Leaderboard/JsonLeaderboardDefLoader.cpp +++ b/src/ObjLoading/Game/IW5/Leaderboard/JsonLeaderboardDefLoader.cpp @@ -122,9 +122,9 @@ namespace namespace IW5 { - bool LoadLeaderboardAsJson(std::istream& stream, LeaderboardDef& leaderboard, MemoryManager* memory) + bool LoadLeaderboardAsJson(std::istream& stream, LeaderboardDef& leaderboard, MemoryManager& memory) { - const JsonLoader loader(stream, *memory); + const JsonLoader loader(stream, memory); return loader.Load(leaderboard); } diff --git a/src/ObjLoading/Game/IW5/Leaderboard/JsonLeaderboardDefLoader.h b/src/ObjLoading/Game/IW5/Leaderboard/JsonLeaderboardDefLoader.h index 1dc020b6..753a5db3 100644 --- a/src/ObjLoading/Game/IW5/Leaderboard/JsonLeaderboardDefLoader.h +++ b/src/ObjLoading/Game/IW5/Leaderboard/JsonLeaderboardDefLoader.h @@ -7,5 +7,5 @@ namespace IW5 { - bool LoadLeaderboardAsJson(std::istream& stream, LeaderboardDef& leaderboard, MemoryManager* memory); + bool LoadLeaderboardAsJson(std::istream& stream, LeaderboardDef& leaderboard, MemoryManager& memory); } // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Leaderboard/LoaderLeaderboardIW5.cpp b/src/ObjLoading/Game/IW5/Leaderboard/LoaderLeaderboardIW5.cpp new file mode 100644 index 00000000..c18ed86b --- /dev/null +++ b/src/ObjLoading/Game/IW5/Leaderboard/LoaderLeaderboardIW5.cpp @@ -0,0 +1,53 @@ +#include "LoaderLeaderboardIW5.h" + +#include "Game/IW5/IW5.h" +#include "JsonLeaderboardDefLoader.h" + +#include +#include +#include + +using namespace IW5; + +namespace +{ + class LeaderboardLoader final : public AssetCreator + { + public: + LeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto file = m_search_path.Open(std::format("leaderboards/{}.json", assetName)); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + auto* leaderboardDef = m_memory.Alloc(); + leaderboardDef->name = m_memory.Dup(assetName.c_str()); + + if (!LoadLeaderboardAsJson(*file.m_stream, *leaderboardDef, m_memory)) + { + std::cerr << std::format("Failed to load leaderboard \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + return AssetCreationResult::Success(context.AddAsset(assetName, leaderboardDef)); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace IW5 +{ + std::unique_ptr> CreateLeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Leaderboard/LoaderLeaderboardIW5.h b/src/ObjLoading/Game/IW5/Leaderboard/LoaderLeaderboardIW5.h new file mode 100644 index 00000000..6c144840 --- /dev/null +++ b/src/ObjLoading/Game/IW5/Leaderboard/LoaderLeaderboardIW5.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW5/IW5.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW5 +{ + std::unique_ptr> CreateLeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Localize/LoaderLocalizeIW5.cpp b/src/ObjLoading/Game/IW5/Localize/LoaderLocalizeIW5.cpp new file mode 100644 index 00000000..a531c42f --- /dev/null +++ b/src/ObjLoading/Game/IW5/Localize/LoaderLocalizeIW5.cpp @@ -0,0 +1,44 @@ +#include "LoaderLocalizeIW5.h" + +#include "Localize/CommonLocalizeLoader.h" + +using namespace IW5; + +namespace +{ + class LocalizeLoader final : public AssetCreator, public CommonLocalizeLoader + { + public: + LocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : CommonLocalizeLoader(searchPath, zone), + m_memory(memory) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + return CreateLocalizeAsset(assetName, context); + } + + protected: + AssetCreationResult CreateAssetFromCommonAsset(const CommonLocalizeEntry& localizeEntry, AssetCreationContext& context) override + { + auto* asset = m_memory.Alloc(); + asset->name = m_memory.Dup(localizeEntry.m_key.c_str()); + asset->value = m_memory.Dup(localizeEntry.m_value.c_str()); + + return AssetCreationResult::Success(context.AddAsset(localizeEntry.m_key, asset)); + } + + private: + MemoryManager& m_memory; + }; +} // namespace + +namespace IW5 +{ + std::unique_ptr> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + { + return std::make_unique(memory, searchPath, zone); + } +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Localize/LoaderLocalizeIW5.h b/src/ObjLoading/Game/IW5/Localize/LoaderLocalizeIW5.h new file mode 100644 index 00000000..6c47a8d1 --- /dev/null +++ b/src/ObjLoading/Game/IW5/Localize/LoaderLocalizeIW5.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW5/IW5.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" +#include "Zone/Zone.h" + +#include + +namespace IW5 +{ + std::unique_ptr> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Material/JsonMaterialLoader.cpp b/src/ObjLoading/Game/IW5/Material/JsonMaterialLoader.cpp index a567e9dd..3742f848 100644 --- a/src/ObjLoading/Game/IW5/Material/JsonMaterialLoader.cpp +++ b/src/ObjLoading/Game/IW5/Material/JsonMaterialLoader.cpp @@ -16,12 +16,11 @@ namespace class JsonLoader { public: - JsonLoader(std::istream& stream, MemoryManager& memory, IAssetLoadingManager& manager, std::vector& dependencies) + JsonLoader(std::istream& stream, MemoryManager& memory, AssetCreationContext& context, AssetRegistration& registration) : m_stream(stream), m_memory(memory), - m_manager(manager), - m_dependencies(dependencies) - + m_context(context), + m_registration(registration) { } @@ -159,13 +158,13 @@ namespace textureDef.semantic = jTexture.semantic; - auto* imageAsset = m_manager.LoadDependency(jTexture.image); + auto* imageAsset = m_context.LoadDependency(jTexture.image); if (!imageAsset) { PrintError(material, std::format("Could not find textureDef image: {}", jTexture.image)); return false; } - m_dependencies.push_back(imageAsset); + m_registration.AddDependency(imageAsset); if (jTexture.water) { @@ -365,13 +364,13 @@ namespace material.stateFlags = static_cast(jMaterial.stateFlags); material.cameraRegion = jMaterial.cameraRegion; - auto* techniqueSet = m_manager.LoadDependency(jMaterial.techniqueSet); + auto* techniqueSet = m_context.LoadDependency(jMaterial.techniqueSet); if (!techniqueSet) { PrintError(material, "Could not find technique set"); return false; } - m_dependencies.push_back(techniqueSet); + m_registration.AddDependency(techniqueSet); material.techniqueSet = techniqueSet->Asset(); if (!jMaterial.textures.empty()) @@ -430,17 +429,17 @@ namespace std::istream& m_stream; MemoryManager& m_memory; - IAssetLoadingManager& m_manager; - std::vector& m_dependencies; + AssetCreationContext& m_context; + AssetRegistration& m_registration; }; } // namespace namespace IW5 { bool LoadMaterialAsJson( - std::istream& stream, Material& material, MemoryManager* memory, IAssetLoadingManager* manager, std::vector& dependencies) + std::istream& stream, Material& material, MemoryManager& memory, AssetCreationContext& context, AssetRegistration& registration) { - const JsonLoader loader(stream, *memory, *manager, dependencies); + const JsonLoader loader(stream, memory, context, registration); return loader.Load(material); } diff --git a/src/ObjLoading/Game/IW5/Material/JsonMaterialLoader.h b/src/ObjLoading/Game/IW5/Material/JsonMaterialLoader.h index b498852d..6b2b5b74 100644 --- a/src/ObjLoading/Game/IW5/Material/JsonMaterialLoader.h +++ b/src/ObjLoading/Game/IW5/Material/JsonMaterialLoader.h @@ -1,6 +1,7 @@ #pragma once -#include "AssetLoading/IAssetLoadingManager.h" +#include "Asset/AssetCreationContext.h" +#include "Asset/AssetRegistration.h" #include "Game/IW5/IW5.h" #include "Utils/MemoryManager.h" @@ -9,5 +10,5 @@ namespace IW5 { bool LoadMaterialAsJson( - std::istream& stream, Material& material, MemoryManager* memory, IAssetLoadingManager* manager, std::vector& dependencies); + std::istream& stream, Material& material, MemoryManager& memory, AssetCreationContext& context, AssetRegistration& registration); } // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Material/LoaderMaterialIW5.cpp b/src/ObjLoading/Game/IW5/Material/LoaderMaterialIW5.cpp new file mode 100644 index 00000000..96f5af0e --- /dev/null +++ b/src/ObjLoading/Game/IW5/Material/LoaderMaterialIW5.cpp @@ -0,0 +1,70 @@ +#include "LoaderMaterialIW5.h" + +#include "Game/IW5/IW5.h" +#include "JsonMaterialLoader.h" + +#include +#include +#include +#include + +using namespace IW5; + +namespace +{ + class MaterialLoader final : public AssetCreator + { + public: + MaterialLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto file = m_search_path.Open(GetFileNameForAsset(assetName)); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + auto* material = m_memory.Alloc(); + material->info.name = m_memory.Dup(assetName.c_str()); + + AssetRegistration registration(assetName, material); + if (!LoadMaterialAsJson(*file.m_stream, *material, m_memory, context, registration)) + { + std::cerr << std::format("Failed to load material \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); + } + + private: + std::string GetFileNameForAsset(const std::string& assetName) + { + std::string sanitizedFileName(assetName); + if (sanitizedFileName[0] == '*') + { + std::ranges::replace(sanitizedFileName, '*', '_'); + const auto parenthesisPos = sanitizedFileName.find('('); + if (parenthesisPos != std::string::npos) + sanitizedFileName.erase(parenthesisPos); + sanitizedFileName = std::format("generated/{}", sanitizedFileName); + } + + return std::format("materials/{}.json", sanitizedFileName); + } + + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace IW5 +{ + std::unique_ptr> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Material/LoaderMaterialIW5.h b/src/ObjLoading/Game/IW5/Material/LoaderMaterialIW5.h new file mode 100644 index 00000000..5488c1a7 --- /dev/null +++ b/src/ObjLoading/Game/IW5/Material/LoaderMaterialIW5.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW5/IW5.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW5 +{ + std::unique_ptr> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Menu/LoaderMenuListIW5.cpp b/src/ObjLoading/Game/IW5/Menu/LoaderMenuListIW5.cpp new file mode 100644 index 00000000..e4058d18 --- /dev/null +++ b/src/ObjLoading/Game/IW5/Menu/LoaderMenuListIW5.cpp @@ -0,0 +1,220 @@ +#include "LoaderMenuListIW5.h" + +#include "Game/IW5/IW5.h" +#include "Game/IW5/Menu/MenuConversionZoneStateIW5.h" +#include "Game/IW5/Menu/MenuConverterIW5.h" +#include "ObjLoading.h" +#include "Parsing/Menu/MenuFileReader.h" + +#include +#include +#include + +using namespace IW5; + +namespace +{ + class MenuListLoader final : public AssetCreator + { + public: + MenuListLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + std::vector menus; + AssetRegistration registration(assetName); + + auto& zoneState = context.GetZoneAssetCreationState(); + auto& conversionState = context.GetZoneAssetCreationState(); + + std::deque menuLoadQueue; + const auto alreadyLoadedMenuListFileMenus = conversionState.m_menus_by_filename.find(assetName); + + if (alreadyLoadedMenuListFileMenus == conversionState.m_menus_by_filename.end()) + { + const auto file = m_search_path.Open(assetName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + const auto menuListResult = ParseMenuFile(*file.m_stream, assetName, zoneState); + if (menuListResult) + { + ProcessParsedResults(assetName, context, *menuListResult, zoneState, conversionState, menus, registration); + + for (const auto& menuToLoad : menuListResult->m_menus_to_load) + menuLoadQueue.emplace_back(menuToLoad); + + zoneState.AddMenusToLoad(assetName, std::move(menuListResult->m_menus_to_load)); + } + else + return AssetCreationResult::Failure(); + } + + while (!menuLoadQueue.empty()) + { + const auto& menuFileToLoad = menuLoadQueue.front(); + + LoadMenuFileFromQueue(menuFileToLoad, context, zoneState, conversionState, menus, registration); + + menuLoadQueue.pop_front(); + } + + auto* menuListAsset = m_memory.Create(); + menuListAsset->name = m_memory.Dup(assetName.c_str()); + registration.SetAsset(menuListAsset); + + CreateMenuListAsset(*menuListAsset, menus); + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); + } + + void FinalizeZone(AssetCreationContext& context) override + { + context.GetZoneAssetCreationState().FinalizeSupportingData(); + } + + private: + bool LoadMenuFileFromQueue(const std::string& menuFilePath, + AssetCreationContext& context, + menu::MenuAssetZoneState& zoneState, + MenuConversionZoneState& conversionState, + std::vector& menus, + AssetRegistration& registration) + { + const auto alreadyLoadedMenuFile = conversionState.m_menus_by_filename.find(menuFilePath); + if (alreadyLoadedMenuFile != conversionState.m_menus_by_filename.end()) + { + std::cout << std::format("Already loaded \"{}\", skipping\n", menuFilePath); + for (auto* menu : alreadyLoadedMenuFile->second) + { + menus.emplace_back(menu->Asset()); + registration.AddDependency(menu); + } + return true; + } + + const auto file = m_search_path.Open(menuFilePath); + if (!file.IsOpen()) + { + std::cerr << std::format("Could not open menu file \"{}\"\n", menuFilePath); + return false; + } + + const auto menuFileResult = ParseMenuFile(*file.m_stream, menuFilePath, zoneState); + if (menuFileResult) + { + ProcessParsedResults(menuFilePath, context, *menuFileResult, zoneState, conversionState, menus, registration); + if (!menuFileResult->m_menus_to_load.empty()) + std::cout << std::format("WARNING: Menu file has menus to load even though it is not a menu list, ignoring: \"{}\"\n", menuFilePath); + + return true; + } + else + std::cerr << std::format("Could not read menu file \"{}\"\n", menuFilePath); + + return false; + } + + bool ProcessParsedResults(const std::string& fileName, + AssetCreationContext& context, + menu::ParsingResult& parsingResult, + menu::MenuAssetZoneState& zoneState, + MenuConversionZoneState& conversionState, + std::vector& menus, + AssetRegistration& registration) + { + const auto menuCount = parsingResult.m_menus.size(); + const auto functionCount = parsingResult.m_functions.size(); + const auto menuLoadCount = parsingResult.m_menus_to_load.size(); + auto totalItemCount = 0u; + for (const auto& menu : parsingResult.m_menus) + totalItemCount += menu->m_items.size(); + + std::cout << std::format("Successfully read menu file \"{}\" ({} loads, {} menus, {} functions, {} items)\n", + fileName, + menuLoadCount, + menuCount, + functionCount, + totalItemCount); + + // Add all functions to the zone state to make them available for all menus to be converted + for (auto& function : parsingResult.m_functions) + zoneState.AddFunction(std::move(function)); + + // Prepare a list of all menus of this file + std::vector*> allMenusOfFile; + allMenusOfFile.reserve(parsingResult.m_menus.size()); + + // Convert all menus and add them as assets + for (auto& commonMenu : parsingResult.m_menus) + { + auto converter = IMenuConverter::Create(ObjLoading::Configuration.MenuNoOptimization, m_search_path, m_memory, context); + + auto* menuAsset = m_memory.Alloc(); + AssetRegistration menuRegistration(commonMenu->m_name, menuAsset); + + converter->ConvertMenu(*commonMenu, *menuAsset, menuRegistration); + if (menuAsset == nullptr) + { + std::cerr << std::format("Failed to convert menu file \"{}\"\n", commonMenu->m_name); + return false; + } + + menus.emplace_back(menuAsset); + auto* menuAssetInfo = context.AddAsset(std::move(menuRegistration)); + + if (menuAssetInfo) + { + allMenusOfFile.emplace_back(menuAssetInfo); + registration.AddDependency(menuAssetInfo); + } + + zoneState.AddMenu(std::move(commonMenu)); + } + + // Register this file with all loaded menus + conversionState.AddLoadedFile(fileName, std::move(allMenusOfFile)); + + return true; + } + + void CreateMenuListAsset(MenuList& menuList, const std::vector& menus) + { + menuList.menuCount = static_cast(menus.size()); + + if (menuList.menuCount > 0) + { + menuList.menus = m_memory.Alloc(menuList.menuCount); + for (auto i = 0; i < menuList.menuCount; i++) + menuList.menus[i] = menus[i]; + } + else + menuList.menus = nullptr; + } + + std::unique_ptr ParseMenuFile(std::istream& stream, const std::string& menuFileName, const menu::MenuAssetZoneState& zoneState) + { + menu::MenuFileReader reader(stream, menuFileName, menu::FeatureLevel::IW5, m_search_path); + + reader.IncludeZoneState(zoneState); + reader.SetPermissiveMode(ObjLoading::Configuration.MenuPermissiveParsing); + + return reader.ReadMenuFile(); + } + + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace IW5 +{ + std::unique_ptr> CreateMenuListLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Menu/LoaderMenuListIW5.h b/src/ObjLoading/Game/IW5/Menu/LoaderMenuListIW5.h new file mode 100644 index 00000000..823161b8 --- /dev/null +++ b/src/ObjLoading/Game/IW5/Menu/LoaderMenuListIW5.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW5/IW5.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW5 +{ + std::unique_ptr> CreateMenuListLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Menu/MenuConversionZoneStateIW5.cpp b/src/ObjLoading/Game/IW5/Menu/MenuConversionZoneStateIW5.cpp index d6867359..89f23c85 100644 --- a/src/ObjLoading/Game/IW5/Menu/MenuConversionZoneStateIW5.cpp +++ b/src/ObjLoading/Game/IW5/Menu/MenuConversionZoneStateIW5.cpp @@ -10,11 +10,11 @@ MenuConversionZoneState::MenuConversionZoneState() { } -void MenuConversionZoneState::SetZone(Zone* zone) +void MenuConversionZoneState::Inject(ZoneAssetCreationInjection& inject) { - auto* memory = zone->GetMemory(); + auto* memory = inject.m_zone.GetMemory(); - m_zone = zone; + m_zone = &inject.m_zone; m_supporting_data = memory->Create(); memset(m_supporting_data, 0, sizeof(ExpressionSupportingData)); } diff --git a/src/ObjLoading/Game/IW5/Menu/MenuConversionZoneStateIW5.h b/src/ObjLoading/Game/IW5/Menu/MenuConversionZoneStateIW5.h index 214a6f6e..849300dd 100644 --- a/src/ObjLoading/Game/IW5/Menu/MenuConversionZoneStateIW5.h +++ b/src/ObjLoading/Game/IW5/Menu/MenuConversionZoneStateIW5.h @@ -1,13 +1,13 @@ #pragma once -#include "AssetLoading/IZoneAssetLoaderState.h" +#include "Asset/IZoneAssetCreationState.h" #include "Game/IW5/IW5.h" #include namespace IW5 { - class MenuConversionZoneState final : public IZoneAssetLoaderState + class MenuConversionZoneState final : public IZoneAssetCreationState { Zone* m_zone; std::vector m_functions; @@ -24,7 +24,7 @@ namespace IW5 ExpressionSupportingData* m_supporting_data; MenuConversionZoneState(); - void SetZone(Zone* zone) override; + void Inject(ZoneAssetCreationInjection& inject) override; Statement_s* FindFunction(const std::string& functionName); diff --git a/src/ObjLoading/Game/IW5/Menu/MenuConverterIW5.cpp b/src/ObjLoading/Game/IW5/Menu/MenuConverterIW5.cpp index e36a7b37..b4bfc9a8 100644 --- a/src/ObjLoading/Game/IW5/Menu/MenuConverterIW5.cpp +++ b/src/ObjLoading/Game/IW5/Menu/MenuConverterIW5.cpp @@ -16,18 +16,16 @@ #include #include +#include #include using namespace IW5; using namespace menu; -namespace IW5 +namespace { - class MenuConverterImpl : public AbstractMenuConverter + class MenuConverter final : public AbstractMenuConverter, public IMenuConverter { - MenuConversionZoneState* m_conversion_zone_state; - MenuAssetZoneState* m_parsing_zone_state; - _NODISCARD static rectDef_s ConvertRectDef(const CommonRect& rect) { return rectDef_s{ @@ -78,26 +76,26 @@ namespace IW5 return input; } - _NODISCARD Material* ConvertMaterial(const std::string& materialName, const CommonMenuDef* menu, const CommonItemDef* item = nullptr) const + [[nodiscard]] Material* ConvertMaterial(const std::string& materialName, const CommonMenuDef* menu, const CommonItemDef* item = nullptr) const { if (materialName.empty()) return nullptr; - auto* materialDependency = m_manager->LoadDependency(materialName); + auto* materialDependency = m_context.LoadDependency(materialName); if (!materialDependency) - throw MenuConversionException("Failed to load material \"" + materialName + "\"", menu, item); + throw MenuConversionException(std::format("Failed to load material \"{}\"", materialName), menu, item); return materialDependency->Asset(); } - _NODISCARD snd_alias_list_t* ConvertSound(const std::string& soundName, const CommonMenuDef* menu, const CommonItemDef* item = nullptr) const + [[nodiscard]] snd_alias_list_t* ConvertSound(const std::string& soundName, const CommonMenuDef* menu, const CommonItemDef* item = nullptr) const { if (soundName.empty()) return nullptr; - auto* soundDependency = m_manager->LoadDependency(soundName); + auto* soundDependency = m_context.LoadDependency(soundName); if (!soundDependency) - throw MenuConversionException("Failed to load sound \"" + soundName + "\"", menu, item); + throw MenuConversionException(std::format("Failed to load sound \"{}\"", soundName), menu, item); return soundDependency->Asset(); } @@ -127,7 +125,7 @@ namespace IW5 staticDvarIndexEntry.type = EET_OPERAND; staticDvarIndexEntry.data.operand.dataType = VAL_INT; staticDvarIndexEntry.data.operand.internals.intVal = - static_cast(m_conversion_zone_state->AddStaticDvar(*staticDvarNameExpressionValue.m_string_value)); + static_cast(m_conversion_zone_state.AddStaticDvar(*staticDvarNameExpressionValue.m_string_value)); entries.emplace_back(staticDvarIndexEntry); expressionEntry parenRight{}; @@ -135,7 +133,7 @@ namespace IW5 parenRight.data.op = OP_RIGHTPAREN; entries.emplace_back(parenRight); - gameStatement->supportingData = m_conversion_zone_state->m_supporting_data; + gameStatement->supportingData = m_conversion_zone_state.m_supporting_data; return true; } @@ -208,18 +206,18 @@ namespace IW5 std::string lowerCaseFunctionName(functionCall->m_function_name); utils::MakeStringLowerCase(lowerCaseFunctionName); - Statement_s* functionStatement = m_conversion_zone_state->FindFunction(lowerCaseFunctionName); + Statement_s* functionStatement = m_conversion_zone_state.FindFunction(lowerCaseFunctionName); if (functionStatement == nullptr) { // Function was not converted yet: Convert it now - const auto foundCommonFunction = m_parsing_zone_state->m_functions_by_name.find(lowerCaseFunctionName); + const auto foundCommonFunction = m_parsing_zone_state.m_functions_by_name.find(lowerCaseFunctionName); - if (foundCommonFunction == m_parsing_zone_state->m_functions_by_name.end()) + if (foundCommonFunction == m_parsing_zone_state.m_functions_by_name.end()) throw MenuConversionException("Failed to find definition for custom function \"" + functionCall->m_function_name + "\"", menu, item); functionStatement = ConvertExpression(foundCommonFunction->second->m_value.get(), menu, item); - functionStatement = m_conversion_zone_state->AddFunction(lowerCaseFunctionName, functionStatement); + functionStatement = m_conversion_zone_state.AddFunction(lowerCaseFunctionName, functionStatement); } expressionEntry functionEntry{}; @@ -229,7 +227,7 @@ namespace IW5 entries.emplace_back(functionEntry); // Statement uses custom function so it needs supporting data - gameStatement->supportingData = m_conversion_zone_state->m_supporting_data; + gameStatement->supportingData = m_conversion_zone_state.m_supporting_data; } constexpr static expressionOperatorType_e UNARY_OPERATION_MAPPING[static_cast(SimpleUnaryOperationId::COUNT)]{ @@ -363,7 +361,7 @@ namespace IW5 else if (expressionValue->m_type == SimpleExpressionValue::Type::STRING) { entry.data.operand.dataType = VAL_STRING; - entry.data.operand.internals.stringVal.string = m_conversion_zone_state->AddString(*expressionValue->m_string_value); + entry.data.operand.internals.stringVal.string = m_conversion_zone_state.AddString(*expressionValue->m_string_value); } entries.emplace_back(entry); @@ -416,7 +414,7 @@ namespace IW5 if (!expression) return nullptr; - auto* statement = m_memory->Create(); + auto* statement = m_memory.Alloc(); for (auto& result : statement->persistentState.lastResult) result = Operand{}; for (auto& lastExecutionTime : statement->persistentState.lastExecuteTime) @@ -426,8 +424,8 @@ namespace IW5 std::vector expressionEntries; ConvertExpressionEntry(statement, expressionEntries, expression, menu, item); - auto* outputExpressionEntries = m_memory->Alloc(expressionEntries.size()); - memcpy(outputExpressionEntries, expressionEntries.data(), sizeof(expressionEntry) * expressionEntries.size()); + auto* outputExpressionEntries = m_memory.Alloc(expressionEntries.size()); + std::memcpy(outputExpressionEntries, expressionEntries.data(), sizeof(expressionEntry) * expressionEntries.size()); statement->entries = outputExpressionEntries; statement->numEntries = static_cast(expressionEntries.size()); @@ -435,10 +433,10 @@ namespace IW5 return statement; } - _NODISCARD Statement_s* ConvertOrApplyStatement(float& staticValue, - const ISimpleExpression* expression, - const CommonMenuDef* menu, - const CommonItemDef* item = nullptr) const + [[nodiscard]] Statement_s* ConvertOrApplyStatement(float& staticValue, + const ISimpleExpression* expression, + const CommonMenuDef* menu, + const CommonItemDef* item = nullptr) const { if (m_disable_optimizations) return ConvertExpression(expression, menu, item); @@ -466,10 +464,10 @@ namespace IW5 return ConvertExpression(expression, menu, item); } - _NODISCARD Statement_s* ConvertOrApplyStatement(const char*& staticValue, - const ISimpleExpression* expression, - const CommonMenuDef* menu, - const CommonItemDef* item = nullptr) const + [[nodiscard]] Statement_s* ConvertOrApplyStatement(const char*& staticValue, + const ISimpleExpression* expression, + const CommonMenuDef* menu, + const CommonItemDef* item = nullptr) const { if (m_disable_optimizations) return ConvertExpression(expression, menu, item); @@ -483,7 +481,7 @@ namespace IW5 switch (value.m_type) { case SimpleExpressionValue::Type::STRING: - staticValue = m_memory->Dup(value.m_string_value->c_str()); + staticValue = m_memory.Dup(value.m_string_value->c_str()); break; case SimpleExpressionValue::Type::DOUBLE: @@ -496,10 +494,10 @@ namespace IW5 return ConvertExpression(expression, menu, item); } - _NODISCARD Statement_s* ConvertOrApplyStatement(Material*& staticValue, - const ISimpleExpression* expression, - const CommonMenuDef* menu, - const CommonItemDef* item = nullptr) const + [[nodiscard]] Statement_s* ConvertOrApplyStatement(Material*& staticValue, + const ISimpleExpression* expression, + const CommonMenuDef* menu, + const CommonItemDef* item = nullptr) const { if (m_disable_optimizations) return ConvertExpression(expression, menu, item); @@ -526,10 +524,10 @@ namespace IW5 return ConvertExpression(expression, menu, item); } - _NODISCARD Statement_s* ConvertVisibleExpression(windowDef_t* window, - const ISimpleExpression* expression, - const CommonMenuDef* commonMenu, - const CommonItemDef* commonItem = nullptr) const + [[nodiscard]] Statement_s* ConvertVisibleExpression(windowDef_t* window, + const ISimpleExpression* expression, + const CommonMenuDef* commonMenu, + const CommonItemDef* commonItem = nullptr) const { if (expression == nullptr) return nullptr; @@ -560,7 +558,7 @@ namespace IW5 return ConvertExpression(expression, commonMenu, commonItem); } - _NODISCARD static EventType SetLocalVarTypeToEventType(const SetLocalVarType setLocalVarType) + [[nodiscard]] static EventType SetLocalVarTypeToEventType(const SetLocalVarType setLocalVarType) { switch (setLocalVarType) { @@ -588,16 +586,16 @@ namespace IW5 if (!setLocalVar) return; - auto* outputHandler = m_memory->Alloc(); - auto* outputSetLocalVar = m_memory->Alloc(); + auto* outputHandler = m_memory.Alloc(); + auto* outputSetLocalVar = m_memory.Alloc(); outputHandler->eventType = SetLocalVarTypeToEventType(setLocalVar->m_type); outputHandler->eventData.setLocalVarData = outputSetLocalVar; - outputSetLocalVar->localVarName = m_memory->Dup(setLocalVar->m_var_name.c_str()); + outputSetLocalVar->localVarName = m_memory.Dup(setLocalVar->m_var_name.c_str()); outputSetLocalVar->expression = ConvertExpression(setLocalVar->m_value.get(), menu, item); - elements.push_back(outputHandler); + elements.emplace_back(outputHandler); } void ConvertEventHandlerScript(std::vector& elements, const CommonEventHandlerScript* script) const @@ -606,11 +604,11 @@ namespace IW5 if (!script) return; - auto* outputHandler = m_memory->Create(); + auto* outputHandler = m_memory.Alloc(); outputHandler->eventType = EVENT_UNCONDITIONAL; - outputHandler->eventData.unconditionalScript = m_memory->Dup(script->m_script.c_str()); + outputHandler->eventData.unconditionalScript = m_memory.Dup(script->m_script.c_str()); - elements.push_back(outputHandler); + elements.emplace_back(outputHandler); } void ConvertEventHandlerCondition(std::vector& elements, @@ -633,8 +631,8 @@ namespace IW5 } else { - auto* outputHandler = m_memory->Alloc(); - auto* outputCondition = m_memory->Alloc(); + auto* outputHandler = m_memory.Alloc(); + auto* outputCondition = m_memory.Alloc(); outputHandler->eventType = EVENT_IF; outputHandler->eventData.conditionalScript = outputCondition; @@ -646,7 +644,7 @@ namespace IW5 if (condition->m_else_elements) { - auto* outputElseHandler = m_memory->Create(); + auto* outputElseHandler = m_memory.Alloc(); outputElseHandler->eventType = EVENT_ELSE; outputElseHandler->eventData.elseScript = ConvertEventHandlerSet(condition->m_else_elements.get(), menu, item); @@ -689,7 +687,7 @@ namespace IW5 ConvertEventHandler(elements, element.get(), menu, item); } - _NODISCARD MenuEventHandlerSet* + [[nodiscard]] MenuEventHandlerSet* ConvertEventHandlerSet(const CommonEventHandlerSet* eventHandlerSet, const CommonMenuDef* menu, const CommonItemDef* item = nullptr) const { if (!eventHandlerSet) @@ -701,9 +699,9 @@ namespace IW5 if (elements.empty()) return nullptr; - auto* outputSet = m_memory->Alloc(); - auto* outputElements = m_memory->Alloc(elements.size()); - memcpy(outputElements, elements.data(), sizeof(void*) * elements.size()); + auto* outputSet = m_memory.Alloc(); + auto* outputElements = m_memory.Alloc(elements.size()); + std::memcpy(outputElements, elements.data(), sizeof(void*) * elements.size()); outputSet->eventHandlerCount = static_cast(elements.size()); outputSet->eventHandlers = outputElements; @@ -711,15 +709,15 @@ namespace IW5 return outputSet; } - _NODISCARD ItemKeyHandler* ConvertKeyHandler(const std::multimap>& keyHandlers, - const CommonMenuDef* menu, - const CommonItemDef* item = nullptr) const + [[nodiscard]] ItemKeyHandler* ConvertKeyHandler(const std::multimap>& keyHandlers, + const CommonMenuDef* menu, + const CommonItemDef* item = nullptr) const { if (keyHandlers.empty()) return nullptr; const auto keyHandlerCount = keyHandlers.size(); - auto* output = m_memory->Alloc(keyHandlerCount); + auto* output = m_memory.Alloc(keyHandlerCount); auto currentKeyHandler = keyHandlers.cbegin(); for (auto i = 0u; i < keyHandlerCount; i++) { @@ -831,7 +829,7 @@ namespace IW5 if (floatExpressionCount <= 0) return nullptr; - auto* floatExpressions = m_memory->Alloc(floatExpressionCount); + auto* floatExpressions = m_memory.Alloc(floatExpressionCount); auto floatExpressionIndex = 0; for (const auto& [expression, expressionIsStatic, target, staticValue, staticValueArraySize, dynamicFlagsToSet] : locations) { @@ -848,7 +846,7 @@ namespace IW5 return floatExpressions; } - _NODISCARD const char* CreateEnableDvarString(const std::vector& stringElements) const + [[nodiscard]] const char* CreateEnableDvarString(const std::vector& stringElements) const { std::ostringstream ss; @@ -857,10 +855,10 @@ namespace IW5 ss << "\"" << element << "\" "; } - return m_memory->Dup(ss.str().c_str()); + return m_memory.Dup(ss.str().c_str()); } - _NODISCARD const char* ConvertEnableDvar(const CommonItemDef& commonItem, int& dvarFlags) const + [[nodiscard]] const char* ConvertEnableDvar(const CommonItemDef& commonItem, int& dvarFlags) const { dvarFlags = 0; @@ -897,15 +895,15 @@ namespace IW5 return nullptr; } - _NODISCARD listBoxDef_s* ConvertListBoxFeatures(itemDef_s* item, - CommonItemFeaturesListBox* commonListBox, - const CommonMenuDef& parentMenu, - const CommonItemDef& commonItem) const + [[nodiscard]] listBoxDef_s* ConvertListBoxFeatures(itemDef_s* item, + CommonItemFeaturesListBox* commonListBox, + const CommonMenuDef& parentMenu, + const CommonItemDef& commonItem) const { if (commonListBox == nullptr) return nullptr; - auto* listBox = m_memory->Alloc(); + auto* listBox = m_memory.Alloc(); listBox->notselectable = commonListBox->m_not_selectable ? 1 : 0; listBox->noScrollBars = commonListBox->m_no_scrollbars ? 1 : 0; listBox->usePaging = commonListBox->m_use_paging ? 1 : 0; @@ -935,15 +933,15 @@ namespace IW5 return listBox; } - _NODISCARD editFieldDef_s* ConvertEditFieldFeatures(itemDef_s* item, - CommonItemFeaturesEditField* commonEditField, - const CommonMenuDef& parentMenu, - const CommonItemDef& commonItem) const + [[nodiscard]] editFieldDef_s* ConvertEditFieldFeatures(itemDef_s* item, + CommonItemFeaturesEditField* commonEditField, + const CommonMenuDef& parentMenu, + const CommonItemDef& commonItem) const { if (commonEditField == nullptr) return nullptr; - auto* editField = m_memory->Alloc(); + auto* editField = m_memory.Alloc(); editField->stepVal = static_cast(commonEditField->m_def_val); editField->minVal = static_cast(commonEditField->m_min_val); editField->maxVal = static_cast(commonEditField->m_max_val); @@ -955,15 +953,15 @@ namespace IW5 return editField; } - _NODISCARD multiDef_s* ConvertMultiValueFeatures(itemDef_s* item, - CommonItemFeaturesMultiValue* commonMultiValue, - const CommonMenuDef& parentMenu, - const CommonItemDef& commonItem) const + [[nodiscard]] multiDef_s* ConvertMultiValueFeatures(itemDef_s* item, + CommonItemFeaturesMultiValue* commonMultiValue, + const CommonMenuDef& parentMenu, + const CommonItemDef& commonItem) const { if (commonMultiValue == nullptr) return nullptr; - auto* multiValue = m_memory->Alloc(); + auto* multiValue = m_memory.Alloc(); multiValue->count = static_cast(std::min(std::extent_v, commonMultiValue->m_step_names.size())); multiValue->strDef = !commonMultiValue->m_string_values.empty() ? 1 : 0; @@ -986,15 +984,15 @@ namespace IW5 return multiValue; } - _NODISCARD newsTickerDef_s* ConvertNewsTickerFeatures(itemDef_s* item, - CommonItemFeaturesNewsTicker* commonNewsTicker, - const CommonMenuDef& parentMenu, - const CommonItemDef& commonItem) const + [[nodiscard]] newsTickerDef_s* ConvertNewsTickerFeatures(itemDef_s* item, + CommonItemFeaturesNewsTicker* commonNewsTicker, + const CommonMenuDef& parentMenu, + const CommonItemDef& commonItem) const { if (commonNewsTicker == nullptr) return nullptr; - auto* newsTicker = m_memory->Alloc(); + auto* newsTicker = m_memory.Alloc(); newsTicker->spacing = commonNewsTicker->m_spacing; newsTicker->speed = commonNewsTicker->m_speed; newsTicker->feedId = commonNewsTicker->m_news_feed_id; @@ -1002,9 +1000,9 @@ namespace IW5 return newsTicker; } - _NODISCARD itemDef_s* ConvertItem(const CommonMenuDef& parentMenu, const CommonItemDef& commonItem) const + [[nodiscard]] itemDef_s* ConvertItem(const CommonMenuDef& parentMenu, const CommonItemDef& commonItem) const { - auto* item = m_memory->Create(); + auto* item = m_memory.Alloc(); memset(item, 0, sizeof(itemDef_s)); item->window.name = ConvertString(commonItem.m_name); @@ -1094,7 +1092,7 @@ namespace IW5 case CommonItemFeatureType::NONE: default: if (item->type == ITEM_TYPE_TEXT_SCROLL) - item->typeData.scroll = m_memory->Alloc(); + item->typeData.scroll = m_memory.Alloc(); break; } @@ -1110,7 +1108,7 @@ namespace IW5 return nullptr; } - auto* items = m_memory->Alloc(commonMenu.m_items.size()); + auto* items = m_memory.Alloc(commonMenu.m_items.size()); for (auto i = 0u; i < commonMenu.m_items.size(); i++) items[i] = ConvertItem(commonMenu, *commonMenu.m_items[i]); @@ -1120,101 +1118,77 @@ namespace IW5 } public: - MenuConverterImpl(const bool disableOptimizations, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) - : AbstractMenuConverter(disableOptimizations, searchPath, memory, manager), - m_conversion_zone_state(manager->GetAssetLoadingContext()->GetZoneAssetLoaderState()), - m_parsing_zone_state(manager->GetAssetLoadingContext()->GetZoneAssetLoaderState()) + MenuConverter(const bool disableOptimizations, ISearchPath& searchPath, MemoryManager& memory, AssetCreationContext& context) + : AbstractMenuConverter(disableOptimizations, searchPath, memory, context), + m_conversion_zone_state(context.GetZoneAssetCreationState()), + m_parsing_zone_state(context.GetZoneAssetCreationState()) { - assert(m_conversion_zone_state); - assert(m_parsing_zone_state); } - _NODISCARD menuDef_t* ConvertMenu(const CommonMenuDef& commonMenu) const + void ConvertMenu(const menu::CommonMenuDef& commonMenu, menuDef_t& menu, AssetRegistration& registration) override { - auto* menu = m_memory->Create(); - auto* menuData = m_memory->Create(); - memset(menu, 0, sizeof(menuDef_t)); + try + { + auto* menuData = m_memory.Alloc(); - menu->data = menuData; - menu->window.name = m_memory->Dup(commonMenu.m_name.c_str()); - menuData->fullScreen = commonMenu.m_full_screen; - ApplyFlag(menu->window.staticFlags, commonMenu.m_screen_space, WINDOW_FLAG_SCREEN_SPACE); - ApplyFlag(menu->window.staticFlags, commonMenu.m_decoration, WINDOW_FLAG_DECORATION); - menu->window.rect = ConvertRectDef(commonMenu.m_rect); - menu->window.style = commonMenu.m_style; - menu->window.border = commonMenu.m_border; - menu->window.borderSize = static_cast(commonMenu.m_border_size); - ConvertColor(menu->window.backColor, commonMenu.m_back_color); - ConvertColor(menu->window.foreColor, commonMenu.m_fore_color); - ConvertColor(menu->window.borderColor, commonMenu.m_border_color); - ConvertColor(menuData->focusColor, commonMenu.m_focus_color); - menu->window.background = ConvertMaterial(commonMenu.m_background, &commonMenu); - menu->window.ownerDraw = commonMenu.m_owner_draw; - menu->window.ownerDrawFlags = commonMenu.m_owner_draw_flags; - ApplyFlag(menu->window.staticFlags, commonMenu.m_out_of_bounds_click, WINDOW_FLAG_OUT_OF_BOUNDS_CLICK); - menuData->soundName = ConvertString(commonMenu.m_sound_loop); - ApplyFlag(menu->window.staticFlags, commonMenu.m_popup, WINDOW_FLAG_POPUP); - menuData->fadeClamp = static_cast(commonMenu.m_fade_clamp); - menuData->fadeCycle = commonMenu.m_fade_cycle; - menuData->fadeAmount = static_cast(commonMenu.m_fade_amount); - menuData->fadeInAmount = static_cast(commonMenu.m_fade_in_amount); - menuData->blurRadius = static_cast(commonMenu.m_blur_radius); - ApplyFlag(menu->window.staticFlags, commonMenu.m_legacy_split_screen_scale, WINDOW_FLAG_LEGACY_SPLIT_SCREEN_SCALE); - ApplyFlag(menu->window.staticFlags, commonMenu.m_hidden_during_scope, WINDOW_FLAG_HIDDEN_DURING_SCOPE); - ApplyFlag(menu->window.staticFlags, commonMenu.m_hidden_during_flashbang, WINDOW_FLAG_HIDDEN_DURING_FLASH_BANG); - ApplyFlag(menu->window.staticFlags, commonMenu.m_hidden_during_ui, WINDOW_FLAG_HIDDEN_DURING_UI); - menuData->allowedBinding = ConvertString(commonMenu.m_allowed_binding); - ApplyFlag(menu->window.staticFlags, commonMenu.m_text_only_focus, WINDOW_FLAG_TEXT_ONLY_FOCUS); - menuData->visibleExp = ConvertVisibleExpression(&menu->window, commonMenu.m_visible_expression.get(), &commonMenu); - menuData->rectXExp = ConvertOrApplyStatement(menu->window.rect.x, commonMenu.m_rect_x_exp.get(), &commonMenu); - menuData->rectYExp = ConvertOrApplyStatement(menu->window.rect.y, commonMenu.m_rect_y_exp.get(), &commonMenu); - menuData->rectWExp = ConvertOrApplyStatement(menu->window.rect.w, commonMenu.m_rect_w_exp.get(), &commonMenu); - menuData->rectHExp = ConvertOrApplyStatement(menu->window.rect.h, commonMenu.m_rect_h_exp.get(), &commonMenu); - menuData->openSoundExp = ConvertExpression(commonMenu.m_open_sound_exp.get(), &commonMenu); - menuData->closeSoundExp = ConvertExpression(commonMenu.m_close_sound_exp.get(), &commonMenu); - menuData->onOpen = ConvertEventHandlerSet(commonMenu.m_on_open.get(), &commonMenu); - menuData->onClose = ConvertEventHandlerSet(commonMenu.m_on_close.get(), &commonMenu); - menuData->onCloseRequest = ConvertEventHandlerSet(commonMenu.m_on_request_close.get(), &commonMenu); - menuData->onESC = ConvertEventHandlerSet(commonMenu.m_on_esc.get(), &commonMenu); - menuData->onFocusDueToClose = ConvertEventHandlerSet(commonMenu.m_on_focus_due_to_close.get(), &commonMenu); - menuData->onKey = ConvertKeyHandler(commonMenu.m_key_handlers, &commonMenu); - menu->items = ConvertMenuItems(commonMenu, menu->itemCount); - menuData->expressionData = m_conversion_zone_state->m_supporting_data; - - return menu; + menu.data = menuData; + menu.window.name = m_memory.Dup(commonMenu.m_name.c_str()); + menuData->fullScreen = commonMenu.m_full_screen; + ApplyFlag(menu.window.staticFlags, commonMenu.m_screen_space, WINDOW_FLAG_SCREEN_SPACE); + ApplyFlag(menu.window.staticFlags, commonMenu.m_decoration, WINDOW_FLAG_DECORATION); + menu.window.rect = ConvertRectDef(commonMenu.m_rect); + menu.window.style = commonMenu.m_style; + menu.window.border = commonMenu.m_border; + menu.window.borderSize = static_cast(commonMenu.m_border_size); + ConvertColor(menu.window.backColor, commonMenu.m_back_color); + ConvertColor(menu.window.foreColor, commonMenu.m_fore_color); + ConvertColor(menu.window.borderColor, commonMenu.m_border_color); + ConvertColor(menuData->focusColor, commonMenu.m_focus_color); + menu.window.background = ConvertMaterial(commonMenu.m_background, &commonMenu); + menu.window.ownerDraw = commonMenu.m_owner_draw; + menu.window.ownerDrawFlags = commonMenu.m_owner_draw_flags; + ApplyFlag(menu.window.staticFlags, commonMenu.m_out_of_bounds_click, WINDOW_FLAG_OUT_OF_BOUNDS_CLICK); + menuData->soundName = ConvertString(commonMenu.m_sound_loop); + ApplyFlag(menu.window.staticFlags, commonMenu.m_popup, WINDOW_FLAG_POPUP); + menuData->fadeClamp = static_cast(commonMenu.m_fade_clamp); + menuData->fadeCycle = commonMenu.m_fade_cycle; + menuData->fadeAmount = static_cast(commonMenu.m_fade_amount); + menuData->fadeInAmount = static_cast(commonMenu.m_fade_in_amount); + menuData->blurRadius = static_cast(commonMenu.m_blur_radius); + ApplyFlag(menu.window.staticFlags, commonMenu.m_legacy_split_screen_scale, WINDOW_FLAG_LEGACY_SPLIT_SCREEN_SCALE); + ApplyFlag(menu.window.staticFlags, commonMenu.m_hidden_during_scope, WINDOW_FLAG_HIDDEN_DURING_SCOPE); + ApplyFlag(menu.window.staticFlags, commonMenu.m_hidden_during_flashbang, WINDOW_FLAG_HIDDEN_DURING_FLASH_BANG); + ApplyFlag(menu.window.staticFlags, commonMenu.m_hidden_during_ui, WINDOW_FLAG_HIDDEN_DURING_UI); + menuData->allowedBinding = ConvertString(commonMenu.m_allowed_binding); + ApplyFlag(menu.window.staticFlags, commonMenu.m_text_only_focus, WINDOW_FLAG_TEXT_ONLY_FOCUS); + menuData->visibleExp = ConvertVisibleExpression(&menu.window, commonMenu.m_visible_expression.get(), &commonMenu); + menuData->rectXExp = ConvertOrApplyStatement(menu.window.rect.x, commonMenu.m_rect_x_exp.get(), &commonMenu); + menuData->rectYExp = ConvertOrApplyStatement(menu.window.rect.y, commonMenu.m_rect_y_exp.get(), &commonMenu); + menuData->rectWExp = ConvertOrApplyStatement(menu.window.rect.w, commonMenu.m_rect_w_exp.get(), &commonMenu); + menuData->rectHExp = ConvertOrApplyStatement(menu.window.rect.h, commonMenu.m_rect_h_exp.get(), &commonMenu); + menuData->openSoundExp = ConvertExpression(commonMenu.m_open_sound_exp.get(), &commonMenu); + menuData->closeSoundExp = ConvertExpression(commonMenu.m_close_sound_exp.get(), &commonMenu); + menuData->onOpen = ConvertEventHandlerSet(commonMenu.m_on_open.get(), &commonMenu); + menuData->onClose = ConvertEventHandlerSet(commonMenu.m_on_close.get(), &commonMenu); + menuData->onCloseRequest = ConvertEventHandlerSet(commonMenu.m_on_request_close.get(), &commonMenu); + menuData->onESC = ConvertEventHandlerSet(commonMenu.m_on_esc.get(), &commonMenu); + menuData->onFocusDueToClose = ConvertEventHandlerSet(commonMenu.m_on_focus_due_to_close.get(), &commonMenu); + menuData->onKey = ConvertKeyHandler(commonMenu.m_key_handlers, &commonMenu); + menu.items = ConvertMenuItems(commonMenu, menu.itemCount); + menuData->expressionData = m_conversion_zone_state.m_supporting_data; + } + catch (const MenuConversionException& e) + { + PrintConversionExceptionDetails(e); + } } - std::vector m_dependencies; + MenuConversionZoneState& m_conversion_zone_state; + MenuAssetZoneState& m_parsing_zone_state; }; -} // namespace IW5 +} // namespace -MenuConverter::MenuConverter(const bool disableOptimizations, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) - : m_disable_optimizations(disableOptimizations), - m_search_path(searchPath), - m_memory(memory), - m_manager(manager) +std::unique_ptr IMenuConverter::Create(bool disableOptimizations, ISearchPath& searchPath, MemoryManager& memory, AssetCreationContext& context) { -} - -std::vector& MenuConverter::GetDependencies() -{ - return m_dependencies; -} - -menuDef_t* MenuConverter::ConvertMenu(const CommonMenuDef& commonMenu) -{ - MenuConverterImpl impl(m_disable_optimizations, m_search_path, m_memory, m_manager); - - try - { - auto* result = impl.ConvertMenu(commonMenu); - m_dependencies = std::move(impl.m_dependencies); - return result; - } - catch (const MenuConversionException& e) - { - MenuConverterImpl::PrintConversionExceptionDetails(e); - } - - return nullptr; + return std::make_unique(disableOptimizations, searchPath, memory, context); } diff --git a/src/ObjLoading/Game/IW5/Menu/MenuConverterIW5.h b/src/ObjLoading/Game/IW5/Menu/MenuConverterIW5.h index 52381782..2f112270 100644 --- a/src/ObjLoading/Game/IW5/Menu/MenuConverterIW5.h +++ b/src/ObjLoading/Game/IW5/Menu/MenuConverterIW5.h @@ -1,26 +1,21 @@ #pragma once -#include "AssetLoading/IAssetLoadingManager.h" +#include "Asset/AssetCreationContext.h" #include "Game/IW5/IW5.h" #include "Parsing/Menu/Domain/CommonMenuDef.h" #include "SearchPath/ISearchPath.h" -#include "Utils/ClassUtils.h" #include "Utils/MemoryManager.h" namespace IW5 { - class MenuConverter + class IMenuConverter { - bool m_disable_optimizations; - ISearchPath* m_search_path; - MemoryManager* m_memory; - IAssetLoadingManager* m_manager; - std::vector m_dependencies; - public: - MenuConverter(bool disableOptimizations, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager); + IMenuConverter() = default; + virtual ~IMenuConverter() = default; - std::vector& GetDependencies(); - _NODISCARD menuDef_t* ConvertMenu(const menu::CommonMenuDef& commonMenu); + virtual void ConvertMenu(const menu::CommonMenuDef& commonMenu, menuDef_t& menu, AssetRegistration& registration) = 0; + + static std::unique_ptr Create(bool disableOptimizations, ISearchPath& searchPath, MemoryManager& memory, AssetCreationContext& context); }; } // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/ObjLoaderIW5.cpp b/src/ObjLoading/Game/IW5/ObjLoaderIW5.cpp index de35f87a..49aad040 100644 --- a/src/ObjLoading/Game/IW5/ObjLoaderIW5.cpp +++ b/src/ObjLoading/Game/IW5/ObjLoaderIW5.cpp @@ -1,126 +1,173 @@ #include "ObjLoaderIW5.h" -#include "AssetLoaders/AssetLoaderAddonMapEnts.h" -#include "AssetLoaders/AssetLoaderClipMap.h" -#include "AssetLoaders/AssetLoaderComWorld.h" -#include "AssetLoaders/AssetLoaderFont.h" -#include "AssetLoaders/AssetLoaderFx.h" -#include "AssetLoaders/AssetLoaderFxImpactTable.h" -#include "AssetLoaders/AssetLoaderFxWorld.h" -#include "AssetLoaders/AssetLoaderGfxImage.h" -#include "AssetLoaders/AssetLoaderGfxLightDef.h" -#include "AssetLoaders/AssetLoaderGfxWorld.h" -#include "AssetLoaders/AssetLoaderGlassWorld.h" -#include "AssetLoaders/AssetLoaderLeaderboard.h" -#include "AssetLoaders/AssetLoaderLoadedSound.h" -#include "AssetLoaders/AssetLoaderLocalizeEntry.h" -#include "AssetLoaders/AssetLoaderMapEnts.h" -#include "AssetLoaders/AssetLoaderMaterial.h" -#include "AssetLoaders/AssetLoaderMenuDef.h" -#include "AssetLoaders/AssetLoaderMenuList.h" -#include "AssetLoaders/AssetLoaderPathData.h" -#include "AssetLoaders/AssetLoaderPhysCollmap.h" -#include "AssetLoaders/AssetLoaderPhysPreset.h" -#include "AssetLoaders/AssetLoaderPixelShader.h" -#include "AssetLoaders/AssetLoaderRawFile.h" -#include "AssetLoaders/AssetLoaderScriptFile.h" -#include "AssetLoaders/AssetLoaderSoundAliasList.h" -#include "AssetLoaders/AssetLoaderSoundCurve.h" -#include "AssetLoaders/AssetLoaderStringTable.h" -#include "AssetLoaders/AssetLoaderStructuredDataDef.h" -#include "AssetLoaders/AssetLoaderSurfaceFxTable.h" -#include "AssetLoaders/AssetLoaderTechniqueSet.h" -#include "AssetLoaders/AssetLoaderTracerDef.h" -#include "AssetLoaders/AssetLoaderVehicleDef.h" -#include "AssetLoaders/AssetLoaderVehicleTrack.h" -#include "AssetLoaders/AssetLoaderVertexDecl.h" -#include "AssetLoaders/AssetLoaderVertexShader.h" -#include "AssetLoaders/AssetLoaderWeapon.h" -#include "AssetLoaders/AssetLoaderWeaponAttachment.h" -#include "AssetLoaders/AssetLoaderXAnim.h" -#include "AssetLoaders/AssetLoaderXModel.h" -#include "AssetLoaders/AssetLoaderXModelSurfs.h" -#include "AssetLoading/AssetLoadingManager.h" +#include "Asset/GlobalAssetPoolsLoader.h" #include "Game/IW5/GameIW5.h" -#include "Image/IwiLoader.h" -#include "ObjContainer/IPak/IPak.h" +#include "Game/IW5/IW5.h" +#include "Game/IW5/XModel/LoaderXModelIW5.h" +#include "Image/LoaderImageIW5.h" +#include "Leaderboard/LoaderLeaderboardIW5.h" +#include "Localize/LoaderLocalizeIW5.h" +#include "Material/LoaderMaterialIW5.h" +#include "Menu/LoaderMenuListIW5.h" +#include "ObjLoading.h" +#include "RawFile/LoaderRawFileIW5.h" +#include "Script/LoaderScriptFileIW5.h" +#include "StringTable/LoaderStringTableIW5.h" +#include "Weapon/GdtLoaderWeaponIW5.h" +#include "Weapon/LoaderAttachmentIW5.h" +#include "Weapon/RawLoaderWeaponIW5.h" + +#include using namespace IW5; -ObjLoader::ObjLoader() -{ -#define REGISTER_ASSET_LOADER(t) \ - { \ - auto l = std::make_unique(); \ - m_asset_loaders_by_type[l->GetHandlingAssetType()] = std::move(l); \ - } - - REGISTER_ASSET_LOADER(AssetLoaderPhysPreset) - REGISTER_ASSET_LOADER(AssetLoaderPhysCollmap) - REGISTER_ASSET_LOADER(AssetLoaderXAnim) - REGISTER_ASSET_LOADER(AssetLoaderXModelSurfs) - REGISTER_ASSET_LOADER(AssetLoaderXModel) - REGISTER_ASSET_LOADER(AssetLoaderMaterial) - REGISTER_ASSET_LOADER(AssetLoaderPixelShader) - REGISTER_ASSET_LOADER(AssetLoaderVertexShader) - REGISTER_ASSET_LOADER(AssetLoaderVertexDecl) - REGISTER_ASSET_LOADER(AssetLoaderTechniqueSet) - REGISTER_ASSET_LOADER(AssetLoaderGfxImage) - REGISTER_ASSET_LOADER(AssetLoaderSoundAliasList) - REGISTER_ASSET_LOADER(AssetLoaderSoundCurve) - REGISTER_ASSET_LOADER(AssetLoaderLoadedSound) - REGISTER_ASSET_LOADER(AssetLoaderClipMap) - REGISTER_ASSET_LOADER(AssetLoaderComWorld) - REGISTER_ASSET_LOADER(AssetLoaderGlassWorld) - REGISTER_ASSET_LOADER(AssetLoaderPathData) - REGISTER_ASSET_LOADER(AssetLoaderVehicleTrack) - REGISTER_ASSET_LOADER(AssetLoaderMapEnts) - REGISTER_ASSET_LOADER(AssetLoaderFxWorld) - REGISTER_ASSET_LOADER(AssetLoaderGfxWorld) - REGISTER_ASSET_LOADER(AssetLoaderGfxLightDef) - REGISTER_ASSET_LOADER(AssetLoaderFont) - REGISTER_ASSET_LOADER(AssetLoaderMenuList) - REGISTER_ASSET_LOADER(AssetLoaderMenuDef) - REGISTER_ASSET_LOADER(AssetLoaderLocalizeEntry) - REGISTER_ASSET_LOADER(AssetLoaderWeaponAttachment) - REGISTER_ASSET_LOADER(AssetLoaderWeapon) - REGISTER_ASSET_LOADER(AssetLoaderFx) - REGISTER_ASSET_LOADER(AssetLoaderFxImpactTable) - REGISTER_ASSET_LOADER(AssetLoaderSurfaceFxTable) - REGISTER_ASSET_LOADER(AssetLoaderRawFile) - REGISTER_ASSET_LOADER(AssetLoaderScriptFile) - REGISTER_ASSET_LOADER(AssetLoaderStringTable) - REGISTER_ASSET_LOADER(AssetLoaderLeaderboard) - REGISTER_ASSET_LOADER(AssetLoaderStructuredDataDef) - REGISTER_ASSET_LOADER(AssetLoaderTracerDef) - REGISTER_ASSET_LOADER(AssetLoaderVehicleDef) - REGISTER_ASSET_LOADER(AssetLoaderAddonMapEnts) - -#undef REGISTER_ASSET_LOADER -} - -bool ObjLoader::IsMpZone(const Zone& zone) -{ - return zone.m_name.compare(0, 3, "mp_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_mp") == 0; -} - -bool ObjLoader::IsZmZone(const Zone& zone) -{ - return zone.m_name.compare(0, 3, "zm_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_zm") == 0; -} - void ObjLoader::LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const {} void ObjLoader::UnloadContainersOfZone(Zone& zone) const {} -bool ObjLoader::LoadAssetForZone(AssetLoadingContext& context, const asset_type_t assetType, const std::string& assetName) const +namespace { - AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, context); - return assetLoadingManager.LoadAssetFromLoader(assetType, assetName); -} + void ConfigureDefaultCreators(AssetCreatorCollection& collection, Zone& zone) + { + auto& memory = *zone.GetMemory(); -void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext& context) const + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + } + + void ConfigureGlobalAssetPoolsLoaders(AssetCreatorCollection& collection, Zone& zone) + { + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + } + + void ConfigureLoaders(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, IGdtQueryable& gdt) + { + auto& memory = *zone.GetMemory(); + + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateXModelLoader(memory, searchPath, zone)); + collection.AddAssetCreator(CreateMaterialLoader(memory, searchPath)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateImageLoader(memory, searchPath)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateMenuListLoader(memory, searchPath)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateLocalizeLoader(memory, searchPath, zone)); + collection.AddAssetCreator(CreateAttachmentLoader(memory, searchPath)); + collection.AddAssetCreator(CreateRawWeaponLoader(memory, searchPath, zone)); + collection.AddAssetCreator(CreateGdtWeaponLoader(memory, searchPath, gdt, zone)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateRawFileLoader(memory, searchPath)); + collection.AddAssetCreator(CreateScriptLoader(memory, searchPath)); + collection.AddAssetCreator(CreateStringTableLoader(memory, searchPath)); + collection.AddAssetCreator(CreateLeaderboardLoader(memory, searchPath)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + } +} // namespace + +void ObjLoader::ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, IGdtQueryable& gdt) const { - for (const auto& [type, loader] : m_asset_loaders_by_type) - loader->FinalizeAssetsForZone(context); + ConfigureDefaultCreators(collection, zone); + ConfigureLoaders(collection, zone, searchPath, gdt); + ConfigureGlobalAssetPoolsLoaders(collection, zone); } diff --git a/src/ObjLoading/Game/IW5/ObjLoaderIW5.h b/src/ObjLoading/Game/IW5/ObjLoaderIW5.h index 2b259032..2b882ecb 100644 --- a/src/ObjLoading/Game/IW5/ObjLoaderIW5.h +++ b/src/ObjLoading/Game/IW5/ObjLoaderIW5.h @@ -1,29 +1,16 @@ #pragma once -#include "AssetLoading/IAssetLoader.h" #include "IObjLoader.h" #include "SearchPath/ISearchPath.h" -#include -#include - namespace IW5 { class ObjLoader final : public IObjLoader { public: - ObjLoader(); - void LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const override; void UnloadContainersOfZone(Zone& zone) const override; - bool LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const override; - void FinalizeAssetsForZone(AssetLoadingContext& context) const override; - - private: - static bool IsMpZone(const Zone& zone); - static bool IsZmZone(const Zone& zone); - - std::unordered_map> m_asset_loaders_by_type; + void ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, IGdtQueryable& gdt) const override; }; } // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/RawFile/LoaderRawFileIW5.cpp b/src/ObjLoading/Game/IW5/RawFile/LoaderRawFileIW5.cpp new file mode 100644 index 00000000..05e2ca8f --- /dev/null +++ b/src/ObjLoading/Game/IW5/RawFile/LoaderRawFileIW5.cpp @@ -0,0 +1,90 @@ +#include "LoaderRawFileIW5.h" + +#include "Game/IW5/IW5.h" +#include "Pool/GlobalAssetPool.h" + +#include +#include +#include +#include +#include + +using namespace IW5; + +namespace +{ + constexpr size_t COMPRESSED_BUFFER_SIZE_PADDING = 64; + + class RawFileLoader final : public AssetCreator + { + public: + RawFileLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto file = m_search_path.Open(assetName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + const auto uncompressedBuffer = std::make_unique(static_cast(file.m_length)); + file.m_stream->read(uncompressedBuffer.get(), file.m_length); + if (file.m_stream->gcount() != file.m_length) + return AssetCreationResult::Failure(); + + const auto compressionBufferSize = static_cast(file.m_length + COMPRESSED_BUFFER_SIZE_PADDING); + auto* compressedBuffer = m_memory.Alloc(compressionBufferSize); + + z_stream_s zs{}; + + zs.zalloc = Z_NULL; + zs.zfree = Z_NULL; + zs.opaque = Z_NULL; + zs.avail_in = static_cast(file.m_length); + zs.avail_out = compressionBufferSize; + zs.next_in = reinterpret_cast(uncompressedBuffer.get()); + zs.next_out = reinterpret_cast(compressedBuffer); + + int ret = deflateInit(&zs, Z_DEFAULT_COMPRESSION); + + if (ret != Z_OK) + throw std::runtime_error("Initializing deflate failed"); + + ret = deflate(&zs, Z_FINISH); + + if (ret != Z_STREAM_END) + { + std::cerr << std::format("Deflate failed for loading rawfile \"{}\"\n", assetName); + deflateEnd(&zs); + return AssetCreationResult::Failure(); + } + + const auto compressedSize = compressionBufferSize - zs.avail_out; + + auto* rawFile = m_memory.Alloc(); + rawFile->name = m_memory.Dup(assetName.c_str()); + rawFile->compressedLen = static_cast(compressedSize); + rawFile->len = static_cast(file.m_length); + rawFile->buffer = static_cast(compressedBuffer); + + deflateEnd(&zs); + + return AssetCreationResult::Success(context.AddAsset(assetName, rawFile)); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace IW5 +{ + std::unique_ptr> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/RawFile/LoaderRawFileIW5.h b/src/ObjLoading/Game/IW5/RawFile/LoaderRawFileIW5.h new file mode 100644 index 00000000..3099146e --- /dev/null +++ b/src/ObjLoading/Game/IW5/RawFile/LoaderRawFileIW5.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW5/IW5.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW5 +{ + std::unique_ptr> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Script/LoaderScriptFileIW5.cpp b/src/ObjLoading/Game/IW5/Script/LoaderScriptFileIW5.cpp new file mode 100644 index 00000000..df9bdc2d --- /dev/null +++ b/src/ObjLoading/Game/IW5/Script/LoaderScriptFileIW5.cpp @@ -0,0 +1,88 @@ +#include "LoaderScriptFileIW5.h" + +#include "Game/IW5/IW5.h" +#include "Pool/GlobalAssetPool.h" + +#include +#include +#include +#include + +using namespace IW5; + +namespace +{ + class ScriptLoader final : public AssetCreator + { + public: + ScriptLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + // See https://github.com/xensik/gsc-tool#file-format for an in-depth explanation about the .gscbin format + const auto file = m_search_path.Open(std::format("{}.gscbin", assetName)); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + const auto fileBuffer = std::make_unique(static_cast(file.m_length)); + file.m_stream->read(fileBuffer.get(), file.m_length); + if (file.m_stream->gcount() != file.m_length) + return AssetCreationResult::Failure(); + + auto* scriptFile = m_memory.Alloc(); + scriptFile->name = m_memory.Dup(assetName.c_str()); + + // Retrieve data from the buffer + size_t offset = 0; + + // Read past the name pointer, we will use the one from assetName + offset += strlen(fileBuffer.get()) + 1; + + std::memcpy(&scriptFile->compressedLen, fileBuffer.get() + offset, sizeof(scriptFile->compressedLen)); + offset += sizeof(scriptFile->compressedLen); + + std::memcpy(&scriptFile->len, fileBuffer.get() + offset, sizeof(scriptFile->len)); + offset += sizeof(scriptFile->len); + + std::memcpy(&scriptFile->bytecodeLen, fileBuffer.get() + offset, sizeof(scriptFile->bytecodeLen)); + offset += sizeof(scriptFile->bytecodeLen); + + if (scriptFile->compressedLen <= 0 || scriptFile->bytecodeLen <= 0) + { + std::cerr << std::format("Error: Invalid length of the buffers in {} specified\n", assetName); + return AssetCreationResult::Failure(); + } + + if (offset + (scriptFile->compressedLen + scriptFile->bytecodeLen) > file.m_length) + { + std::cerr << std::format("Error: Specified length in {} GSC BIN structure exceeds the actual file size\n", assetName); + return AssetCreationResult::Failure(); + } + + scriptFile->buffer = m_memory.Alloc(scriptFile->compressedLen); + std::memcpy(const_cast(scriptFile->buffer), fileBuffer.get() + offset, scriptFile->compressedLen); + offset += scriptFile->compressedLen; + + scriptFile->bytecode = m_memory.Alloc(scriptFile->bytecodeLen); + std::memcpy(scriptFile->bytecode, fileBuffer.get() + offset, scriptFile->bytecodeLen); + + return AssetCreationResult::Success(context.AddAsset(assetName, scriptFile)); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace IW5 +{ + std::unique_ptr> CreateScriptLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Script/LoaderScriptFileIW5.h b/src/ObjLoading/Game/IW5/Script/LoaderScriptFileIW5.h new file mode 100644 index 00000000..457a0957 --- /dev/null +++ b/src/ObjLoading/Game/IW5/Script/LoaderScriptFileIW5.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW5/IW5.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW5 +{ + std::unique_ptr> CreateScriptLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/StringTable/LoaderStringTableIW5.cpp b/src/ObjLoading/Game/IW5/StringTable/LoaderStringTableIW5.cpp new file mode 100644 index 00000000..2ca18723 --- /dev/null +++ b/src/ObjLoading/Game/IW5/StringTable/LoaderStringTableIW5.cpp @@ -0,0 +1,49 @@ +#include "LoaderStringTableIW5.h" + +#include "Csv/CsvStream.h" +#include "Game/IW5/CommonIW5.h" +#include "Game/IW5/IW5.h" +#include "ObjLoading.h" +#include "Pool/GlobalAssetPool.h" +#include "StringTable/StringTableLoader.h" + +#include + +using namespace IW5; + +namespace +{ + class StringTableLoader final : public AssetCreator + { + public: + StringTableLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto file = m_search_path.Open(assetName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + string_table::StringTableLoaderV2 loader; + auto* stringTable = loader.LoadFromStream(assetName, m_memory, *file.m_stream); + + return AssetCreationResult::Success(context.AddAsset(assetName, stringTable)); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace IW5 +{ + std::unique_ptr> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/StringTable/LoaderStringTableIW5.h b/src/ObjLoading/Game/IW5/StringTable/LoaderStringTableIW5.h new file mode 100644 index 00000000..e07bf9c7 --- /dev/null +++ b/src/ObjLoading/Game/IW5/StringTable/LoaderStringTableIW5.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW5/IW5.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW5 +{ + std::unique_ptr> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Weapon/GdtLoaderWeaponIW5.cpp b/src/ObjLoading/Game/IW5/Weapon/GdtLoaderWeaponIW5.cpp new file mode 100644 index 00000000..03897a0d --- /dev/null +++ b/src/ObjLoading/Game/IW5/Weapon/GdtLoaderWeaponIW5.cpp @@ -0,0 +1,53 @@ +#include "GdtLoaderWeaponIW5.h" + +#include "Game/IW5/IW5.h" +#include "Game/IW5/ObjConstantsIW5.h" +#include "InfoString/InfoString.h" +#include "InfoStringLoaderWeaponIW5.h" + +#include +#include +#include + +using namespace IW5; + +namespace +{ + class GdtLoaderWeapon final : public AssetCreator + { + public: + GdtLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + : m_gdt(gdt), + m_info_string_loader(memory, searchPath, zone) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto* gdtEntry = m_gdt.GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_WEAPON, assetName); + if (gdtEntry == nullptr) + return AssetCreationResult::NoAction(); + + InfoString infoString; + if (!infoString.FromGdtProperties(*gdtEntry)) + { + std::cerr << std::format("Failed to read weapon gdt entry: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + return m_info_string_loader.CreateAsset(assetName, infoString, context); + } + + private: + IGdtQueryable& m_gdt; + InfoStringLoaderWeapon m_info_string_loader; + }; +} // namespace + +namespace IW5 +{ + std::unique_ptr> CreateGdtWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + { + return std::make_unique(memory, searchPath, gdt, zone); + } +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Weapon/GdtLoaderWeaponIW5.h b/src/ObjLoading/Game/IW5/Weapon/GdtLoaderWeaponIW5.h new file mode 100644 index 00000000..0e86b336 --- /dev/null +++ b/src/ObjLoading/Game/IW5/Weapon/GdtLoaderWeaponIW5.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW5/IW5.h" +#include "Gdt/IGdtQueryable.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW5 +{ + std::unique_ptr> CreateGdtWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderWeapon.cpp b/src/ObjLoading/Game/IW5/Weapon/InfoStringLoaderWeaponIW5.cpp similarity index 70% rename from src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderWeapon.cpp rename to src/ObjLoading/Game/IW5/Weapon/InfoStringLoaderWeaponIW5.cpp index 19713878..39310e5a 100644 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderWeapon.cpp +++ b/src/ObjLoading/Game/IW5/Weapon/InfoStringLoaderWeaponIW5.cpp @@ -1,18 +1,15 @@ -#include "AssetLoaderWeapon.h" +#include "InfoStringLoaderWeaponIW5.h" #include "Game/IW5/IW5.h" #include "Game/IW5/InfoString/InfoStringToStructConverter.h" -#include "Game/IW5/InfoString/WeaponFields.h" -#include "Game/IW5/ObjConstantsIW5.h" -#include "InfoString/InfoString.h" -#include "ObjLoading.h" -#include "Pool/GlobalAssetPool.h" -#include "Utils/StringUtils.h" +#include "Game/IW5/Weapon/WeaponFields.h" #include "Weapon/AccuracyGraphLoader.h" +#include #include #include #include +#include using namespace IW5; @@ -31,7 +28,7 @@ namespace if (valueArray.size() > std::extent_v) { - std::cerr << "Cannot have more than " << std::extent_v << " hide tags!\n"; + std::cerr << std::format("Cannot have more than {} hide tags!\n", std::extent_v); return false; } @@ -39,7 +36,7 @@ namespace if (valueArray.size() < std::extent_v) { - m_used_script_string_list.emplace(m_zone_script_strings.AddOrGetScriptString(nullptr)); + m_registration.AddScriptString(m_zone_script_strings.AddOrGetScriptString(nullptr)); } auto currentHideTag = 0u; @@ -49,7 +46,7 @@ namespace const auto scrString = !currentValue.empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue) : m_zone_script_strings.AddOrGetScriptString(nullptr); hideTags[currentHideTag] = scrString; - m_used_script_string_list.emplace(scrString); + m_registration.AddScriptString(scrString); } for (; currentHideTag < std::extent_v; currentHideTag++) @@ -60,7 +57,7 @@ namespace return true; } - _NODISCARD bool ConvertPerSurfaceTypeSound(const cspField_t& field, const std::string& value) const + [[nodiscard]] bool ConvertPerSurfaceTypeSound(const cspField_t& field, const std::string& value) const { auto** perSurfaceTypeSound = reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset); if (value.empty()) @@ -69,31 +66,31 @@ namespace return true; } - *perSurfaceTypeSound = m_memory->Alloc(SURF_TYPE_COUNT); + *perSurfaceTypeSound = m_memory.Alloc(SURF_TYPE_COUNT); for (auto i = 0u; i < SURF_TYPE_COUNT; i++) { const auto currentPerSurfaceTypeSound = value + surfaceTypeSoundSuffixes[i]; - (*perSurfaceTypeSound)[i].name = m_memory->Alloc(); - (*perSurfaceTypeSound)[i].name->soundName = m_memory->Dup(currentPerSurfaceTypeSound.c_str()); + (*perSurfaceTypeSound)[i].name = m_memory.Alloc(); + (*perSurfaceTypeSound)[i].name->soundName = m_memory.Dup(currentPerSurfaceTypeSound.c_str()); } return true; } - _NODISCARD bool ConvertNoteTrackMap(const cspField_t& field, const std::string& value, const char* mapName, const size_t keyAndValueCount) + [[nodiscard]] bool ConvertNoteTrackMap(const cspField_t& field, const std::string& value, const char* mapName, const size_t keyAndValueCount) { std::vector> pairs; if (!ParseAsArray(value, pairs)) { - std::cerr << "Failed to parse notetrack" << mapName << "map as pairs\n"; + std::cerr << std::format("Failed to parse notetrack{}map as pairs\n", mapName); return false; } if (pairs.size() > std::extent_v) { - std::cerr << "Cannot have more than " << std::extent_v << " notetrack" << mapName - << "map entries!\n"; + std::cerr << std::format( + "Cannot have more than {} notetrack{}map entries!\n", std::extent_v, mapName); return false; } @@ -103,7 +100,7 @@ namespace if (pairs.size() < keyAndValueCount) { - m_used_script_string_list.emplace(m_zone_script_strings.AddOrGetScriptString(nullptr)); + m_registration.AddScriptString(m_zone_script_strings.AddOrGetScriptString(nullptr)); } for (; currentEntryNum < pairs.size(); currentEntryNum++) @@ -115,10 +112,10 @@ namespace : m_zone_script_strings.AddOrGetScriptString(nullptr); keys[currentEntryNum] = keyScriptString; - m_used_script_string_list.emplace(keyScriptString); + m_registration.AddScriptString(keyScriptString); values[currentEntryNum] = valueScriptString; - m_used_script_string_list.emplace(valueScriptString); + m_registration.AddScriptString(valueScriptString); } for (; currentEntryNum < keyAndValueCount; currentEntryNum++) @@ -136,7 +133,7 @@ namespace if (ConvertString(value, field.iOffset)) { if (!value.empty()) - m_indirect_asset_references.emplace(m_loading_manager->LoadIndirectAssetReference(value)); + m_registration.AddIndirectAssetReference(m_context.LoadIndirectAssetReference(value)); return true; } @@ -158,41 +155,41 @@ namespace auto currentOther = 0u; for (const auto& attachmentName : valueArray) { - auto* attachmentInfo = m_loading_manager->LoadDependency(attachmentName); + auto* attachmentInfo = m_context.LoadDependency(attachmentName); if (!attachmentInfo) return false; - m_dependencies.emplace(attachmentInfo); + m_registration.AddDependency(attachmentInfo); auto* attachment = attachmentInfo->Asset(); if (attachment->type == ATTACHMENT_SCOPE) { if (currentScope >= std::extent_v) { - std::cerr << "Cannot have more than " << std::extent_v << " scopes\n"; + std::cerr << std::format("Cannot have more than {} scopes\n", std::extent_v); return false; } - m_weapon->scopes[currentScope++] = attachment; + m_weapon.scopes[currentScope++] = attachment; } else if (attachment->type == ATTACHMENT_UNDERBARREL) { if (currentUnderBarrel >= std::extent_v) { - std::cerr << "Cannot have more than " << std::extent_v << " under barrels\n"; + std::cerr << std::format("Cannot have more than {} under barrels\n", std::extent_v); return false; } - m_weapon->underBarrels[currentUnderBarrel++] = attachment; + m_weapon.underBarrels[currentUnderBarrel++] = attachment; } else if (attachment->type == ATTACHMENT_OTHER) { if (currentOther >= std::extent_v) { - std::cerr << "Cannot have more than " << std::extent_v << " other attachments\n"; + std::cerr << std::format("Cannot have more than {} other attachments\n", std::extent_v); return false; } - m_weapon->others[currentOther++] = attachment; + m_weapon.others[currentOther++] = attachment; } } @@ -208,7 +205,7 @@ namespace return false; } - auto* animOverrides = m_memory->Alloc(valueArray.size()); + auto* animOverrides = m_memory.Alloc(valueArray.size()); auto i = 0u; for (const auto& overrideValues : valueArray) @@ -234,8 +231,8 @@ namespace return false; } - m_weapon->weapCompleteDef.animOverrides = animOverrides; - m_weapon->weapCompleteDef.numAnimOverrides = valueArray.size(); + m_weapon.weapCompleteDef.animOverrides = animOverrides; + m_weapon.weapCompleteDef.numAnimOverrides = valueArray.size(); return true; } @@ -249,7 +246,7 @@ namespace return false; } - auto* soundOverrides = m_memory->Alloc(valueArray.size()); + auto* soundOverrides = m_memory.Alloc(valueArray.size()); auto i = 0u; for (const auto& overrideValues : valueArray) @@ -269,8 +266,8 @@ namespace ParseSoundAlias(overrideValues[4], soundOverride.altmodeSound); } - m_weapon->weapCompleteDef.soundOverrides = soundOverrides; - m_weapon->weapCompleteDef.numSoundOverrides = valueArray.size(); + m_weapon.weapCompleteDef.soundOverrides = soundOverrides; + m_weapon.weapCompleteDef.numSoundOverrides = valueArray.size(); return true; } @@ -284,7 +281,7 @@ namespace return false; } - auto* fxOverrides = m_memory->Alloc(valueArray.size()); + auto* fxOverrides = m_memory.Alloc(valueArray.size()); auto i = 0u; for (const auto& overrideValues : valueArray) @@ -307,8 +304,8 @@ namespace return false; } - m_weapon->weapCompleteDef.fxOverrides = fxOverrides; - m_weapon->weapCompleteDef.numFxOverrides = valueArray.size(); + m_weapon.weapCompleteDef.fxOverrides = fxOverrides; + m_weapon.weapCompleteDef.numFxOverrides = valueArray.size(); return true; } @@ -322,7 +319,7 @@ namespace return false; } - auto* reloadOverrides = m_memory->Alloc(valueArray.size()); + auto* reloadOverrides = m_memory.Alloc(valueArray.size()); auto i = 0u; for (const auto& overrideValues : valueArray) @@ -341,8 +338,8 @@ namespace return false; } - m_weapon->weapCompleteDef.reloadOverrides = reloadOverrides; - m_weapon->weapCompleteDef.numReloadStateTimerOverrides = valueArray.size(); + m_weapon.weapCompleteDef.reloadOverrides = reloadOverrides; + m_weapon.weapCompleteDef.numReloadStateTimerOverrides = valueArray.size(); return true; } @@ -373,15 +370,15 @@ namespace if (!ParseSingleWeaponAttachment(overrideValues[0], currentOverride.attachment)) return false; - currentOverride.notetrackSoundMapKeys = m_memory->Alloc(24u); - currentOverride.notetrackSoundMapValues = m_memory->Alloc(24u); + currentOverride.notetrackSoundMapKeys = m_memory.Alloc(24u); + currentOverride.notetrackSoundMapValues = m_memory.Alloc(24u); lastAttachment = overrideValues[0]; currentOverrideKeyOffset = 0u; } if (currentOverrideKeyOffset >= 24u) { - std::cerr << "Cannot have more than " << 24u << " note track overrides per attachment\n"; + std::cerr << std::format("Cannot have more than {} note track overrides per attachment\n", 24u); return false; } @@ -393,9 +390,9 @@ namespace if (currentOverrideKeyOffset > 0u) overrideVector.emplace_back(currentOverride); - m_weapon->weapCompleteDef.notetrackOverrides = m_memory->Alloc(overrideVector.size()); - memcpy(m_weapon->weapCompleteDef.notetrackOverrides, overrideVector.data(), sizeof(NoteTrackToSoundEntry) * overrideVector.size()); - m_weapon->weapCompleteDef.numNotetrackOverrides = overrideVector.size(); + m_weapon.weapCompleteDef.notetrackOverrides = m_memory.Alloc(overrideVector.size()); + memcpy(m_weapon.weapCompleteDef.notetrackOverrides, overrideVector.data(), sizeof(NoteTrackToSoundEntry) * overrideVector.size()); + m_weapon.weapCompleteDef.numNotetrackOverrides = overrideVector.size(); return true; } @@ -408,7 +405,7 @@ namespace for (auto i = 0u; i < std::extent_v; i++) { - const auto* scope = m_weapon->scopes[i]; + const auto* scope = m_weapon.scopes[i]; if (scope && scope->szInternalName && value == scope->szInternalName) { attachment.scope = static_cast(i + 1); @@ -418,7 +415,7 @@ namespace for (auto i = 0u; i < std::extent_v; i++) { - const auto* underBarrel = m_weapon->underBarrels[i]; + const auto* underBarrel = m_weapon.underBarrels[i]; if (underBarrel && underBarrel->szInternalName && value == underBarrel->szInternalName) { attachment.underBarrel = static_cast(i + 1); @@ -428,7 +425,7 @@ namespace for (auto i = 0u; i < std::extent_v; i++) { - const auto* other = m_weapon->others[i]; + const auto* other = m_weapon.others[i]; if (other && other->szInternalName && value == other->szInternalName) { attachment.other = static_cast(1u << i); @@ -436,7 +433,7 @@ namespace } } - std::cerr << "Weapon does not have attachment \"" << value << "\"\n"; + std::cerr << std::format("Weapon does not have attachment \"{}\"\n", value); return false; } @@ -448,8 +445,8 @@ namespace return; } - animName = m_memory->Dup(value.c_str()); - m_indirect_asset_references.emplace(m_loading_manager->LoadIndirectAssetReference(value)); + animName = m_memory.Dup(value.c_str()); + m_registration.AddIndirectAssetReference(m_context.LoadIndirectAssetReference(value)); } void ParseSoundAlias(const std::string& value, SndAliasCustom& soundAlias) @@ -460,9 +457,9 @@ namespace return; } - soundAlias.name = m_memory->Alloc(); - soundAlias.name->soundName = m_memory->Dup(value.c_str()); - m_indirect_asset_references.emplace(m_loading_manager->LoadIndirectAssetReference(value)); + soundAlias.name = m_memory.Alloc(); + soundAlias.name->soundName = m_memory.Dup(value.c_str()); + m_registration.AddIndirectAssetReference(m_context.LoadIndirectAssetReference(value)); } bool ParseFxEffectDef(const std::string& value, FxEffectDef*& fx) @@ -473,15 +470,15 @@ namespace return true; } - auto* fxInfo = m_loading_manager->LoadDependency(value); + auto* fxInfo = m_context.LoadDependency(value); if (!fxInfo) { - std::cerr << "Failed to load fx for override \"" << value << "\"\n"; + std::cerr << std::format("Failed to load fx for override \"{}\"\n", value); return false; } fx = fxInfo->Asset(); - m_dependencies.emplace(fxInfo); + m_registration.AddDependency(fxInfo); return true; } @@ -497,7 +494,7 @@ namespace } } - std::cerr << "Unknown anim file \"" << value << "\"\n"; + std::cerr << std::format("Unknown anim file \"{}\"\n", value); return false; } @@ -512,7 +509,7 @@ namespace } } - std::cerr << "Unknown sound type \"" << value << "\"\n"; + std::cerr << std::format("Unknown sound type \"{}\"\n", value); return false; } @@ -527,7 +524,7 @@ namespace } } - std::cerr << "Unknown fx type \"" << value << "\"\n"; + std::cerr << std::format("Unknown fx type \"{}\"\n", value); return false; } @@ -538,7 +535,7 @@ namespace if (size != value.size()) { - std::cerr << "Invalid int value: \"" << value << "\"\n"; + std::cerr << std::format("Invalid int value: \"{}\"\n", value); return false; } @@ -548,7 +545,7 @@ namespace void ParseScriptString(const std::string& value, ScriptString& out) { out = m_zone_script_strings.AddOrGetScriptString(value); - m_used_script_string_list.emplace(out); + m_registration.AddScriptString(out); } protected: @@ -652,47 +649,48 @@ namespace public: InfoStringToWeaponConverter(const InfoString& infoString, - WeaponFullDef* weaponFullDef, + WeaponFullDef& weaponFullDef, ZoneScriptStrings& zoneScriptStrings, - MemoryManager* memory, - IAssetLoadingManager* manager, + MemoryManager& memory, + AssetCreationContext& context, + AssetRegistration& registration, const cspField_t* fields, const size_t fieldCount) - : InfoStringToStructConverter(infoString, weaponFullDef, zoneScriptStrings, memory, manager, fields, fieldCount) + : InfoStringToStructConverter(infoString, &weaponFullDef, zoneScriptStrings, memory, context, registration, fields, fieldCount), + m_weapon(weaponFullDef) { - m_weapon = weaponFullDef; } private: - WeaponFullDef* m_weapon; + WeaponFullDef& m_weapon; }; - void InitWeaponFullDef(WeaponFullDef* weapon) + void InitWeaponFullDef(WeaponFullDef& weapon) { - weapon->weapCompleteDef.weapDef = &weapon->weapDef; - weapon->weapCompleteDef.hideTags = weapon->hideTags; - weapon->weapCompleteDef.szXAnims = weapon->szXAnims; - weapon->weapCompleteDef.scopes = weapon->scopes; - weapon->weapCompleteDef.underBarrels = weapon->underBarrels; - weapon->weapCompleteDef.others = weapon->others; - weapon->weapDef.gunXModel = weapon->gunXModel; - weapon->weapDef.szXAnimsRightHanded = weapon->szXAnimsRightHanded; - weapon->weapDef.szXAnimsLeftHanded = weapon->szXAnimsLeftHanded; - weapon->weapDef.notetrackSoundMapKeys = weapon->notetrackSoundMapKeys; - weapon->weapDef.notetrackSoundMapValues = weapon->notetrackSoundMapValues; - weapon->weapDef.notetrackRumbleMapKeys = weapon->notetrackRumbleMapKeys; - weapon->weapDef.notetrackRumbleMapValues = weapon->notetrackRumbleMapValues; - weapon->weapDef.worldModel = weapon->worldModel; - weapon->weapDef.parallelBounce = weapon->parallelBounce; - weapon->weapDef.perpendicularBounce = weapon->perpendicularBounce; - weapon->weapDef.locationDamageMultipliers = weapon->locationDamageMultipliers; + weapon.weapCompleteDef.weapDef = &weapon.weapDef; + weapon.weapCompleteDef.hideTags = weapon.hideTags; + weapon.weapCompleteDef.szXAnims = weapon.szXAnims; + weapon.weapCompleteDef.scopes = weapon.scopes; + weapon.weapCompleteDef.underBarrels = weapon.underBarrels; + weapon.weapCompleteDef.others = weapon.others; + weapon.weapDef.gunXModel = weapon.gunXModel; + weapon.weapDef.szXAnimsRightHanded = weapon.szXAnimsRightHanded; + weapon.weapDef.szXAnimsLeftHanded = weapon.szXAnimsLeftHanded; + weapon.weapDef.notetrackSoundMapKeys = weapon.notetrackSoundMapKeys; + weapon.weapDef.notetrackSoundMapValues = weapon.notetrackSoundMapValues; + weapon.weapDef.notetrackRumbleMapKeys = weapon.notetrackRumbleMapKeys; + weapon.weapDef.notetrackRumbleMapValues = weapon.notetrackRumbleMapValues; + weapon.weapDef.worldModel = weapon.worldModel; + weapon.weapDef.parallelBounce = weapon.parallelBounce; + weapon.weapDef.perpendicularBounce = weapon.perpendicularBounce; + weapon.weapDef.locationDamageMultipliers = weapon.locationDamageMultipliers; for (const auto& field : weapon_fields) { if (field.iFieldType != CSPFT_STRING) continue; - *reinterpret_cast(reinterpret_cast(weapon) + field.iOffset) = ""; + *reinterpret_cast(reinterpret_cast(&weapon) + field.iOffset) = ""; } } @@ -743,10 +741,10 @@ namespace } } - void CalculateWeaponFields(WeaponFullDef* weapon, MemoryManager* memory) + void CalculateWeaponFields(WeaponFullDef& weapon, MemoryManager& memory) { - auto& weaponCompleteDef = weapon->weapCompleteDef; - auto& weaponDef = weapon->weapDef; + auto& weaponCompleteDef = weapon.weapCompleteDef; + auto& weaponDef = weapon.weapDef; if (!weaponDef.viewLastShotEjectEffect) weaponDef.viewLastShotEjectEffect = weaponDef.viewShellEjectEffect; @@ -806,10 +804,10 @@ namespace uint16_t& originalGraphKnotCount, vec2_t*& graphKnots, uint16_t& graphKnotCount, - MemoryManager* memory) + MemoryManager& memory) { originalGraphKnotCount = static_cast(graph.knots.size()); - originalGraphKnots = memory->Alloc(originalGraphKnotCount); + originalGraphKnots = memory.Alloc(originalGraphKnotCount); for (auto i = 0u; i < originalGraphKnotCount; i++) { @@ -822,116 +820,69 @@ namespace graphKnotCount = originalGraphKnotCount; } - bool LoadAccuracyGraphs(WeaponFullDef* weaponFullDef, MemoryManager* memory, const IAssetLoadingManager* manager) + bool LoadAccuracyGraphs(WeaponFullDef& weaponFullDef, MemoryManager& memory, ISearchPath& searchPath, AssetCreationContext& context) { - auto* accuracyGraphLoader = manager->GetAssetLoadingContext()->GetZoneAssetLoaderState(); + auto& accuracyGraphLoader = context.GetZoneAssetCreationState(); - if (weaponFullDef->weapDef.aiVsAiAccuracyGraphName && weaponFullDef->weapDef.aiVsAiAccuracyGraphName[0]) + if (weaponFullDef.weapDef.aiVsAiAccuracyGraphName && weaponFullDef.weapDef.aiVsAiAccuracyGraphName[0]) { - const auto* graph = accuracyGraphLoader->LoadAiVsAiGraph(manager, weaponFullDef->weapDef.aiVsAiAccuracyGraphName); + const auto* graph = accuracyGraphLoader.LoadAiVsAiGraph(searchPath, weaponFullDef.weapDef.aiVsAiAccuracyGraphName); if (!graph) return false; ConvertAccuracyGraph(*graph, - weaponFullDef->weapDef.originalAiVsAiAccuracyGraphKnots, - weaponFullDef->weapDef.originalAiVsAiAccuracyGraphKnotCount, - weaponFullDef->weapCompleteDef.aiVsAiAccuracyGraphKnots, - weaponFullDef->weapCompleteDef.aiVsAiAccuracyGraphKnotCount, + weaponFullDef.weapDef.originalAiVsAiAccuracyGraphKnots, + weaponFullDef.weapDef.originalAiVsAiAccuracyGraphKnotCount, + weaponFullDef.weapCompleteDef.aiVsAiAccuracyGraphKnots, + weaponFullDef.weapCompleteDef.aiVsAiAccuracyGraphKnotCount, memory); } - if (weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName && weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName[0]) + if (weaponFullDef.weapDef.aiVsPlayerAccuracyGraphName && weaponFullDef.weapDef.aiVsPlayerAccuracyGraphName[0]) { - const auto* graph = accuracyGraphLoader->LoadAiVsPlayerGraph(manager, weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName); + const auto* graph = accuracyGraphLoader.LoadAiVsPlayerGraph(searchPath, weaponFullDef.weapDef.aiVsPlayerAccuracyGraphName); if (!graph) return false; ConvertAccuracyGraph(*graph, - weaponFullDef->weapDef.originalAiVsPlayerAccuracyGraphKnots, - weaponFullDef->weapDef.originalAiVsPlayerAccuracyGraphKnotCount, - weaponFullDef->weapCompleteDef.aiVsPlayerAccuracyGraphKnots, - weaponFullDef->weapCompleteDef.aiVsPlayerAccuracyGraphKnotCount, + weaponFullDef.weapDef.originalAiVsPlayerAccuracyGraphKnots, + weaponFullDef.weapDef.originalAiVsPlayerAccuracyGraphKnotCount, + weaponFullDef.weapCompleteDef.aiVsPlayerAccuracyGraphKnots, + weaponFullDef.weapCompleteDef.aiVsPlayerAccuracyGraphKnotCount, memory); } return true; } - - bool LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) - { - auto* weaponFullDef = memory->Create(); - memset(weaponFullDef, 0, sizeof(WeaponFullDef)); - InitWeaponFullDef(weaponFullDef); - weaponFullDef->weapCompleteDef.szInternalName = memory->Dup(assetName.c_str()); - - InfoStringToWeaponConverter converter( - infoString, weaponFullDef, zone->m_script_strings, memory, manager, weapon_fields, std::extent_v); - if (!converter.Convert()) - { - std::cerr << "Failed to parse weapon: \"" << assetName << "\"\n"; - return true; - } - - CalculateWeaponFields(weaponFullDef, memory); - - LoadAccuracyGraphs(weaponFullDef, memory, manager); - - manager->AddAsset( - assetName, &weaponFullDef->weapCompleteDef, converter.GetDependencies(), converter.GetUsedScriptStrings(), converter.GetIndirectAssetReferences()); - - return true; - } } // namespace -void* AssetLoaderWeapon::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) +InfoStringLoaderWeapon::InfoStringLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_memory(memory), + m_search_path(searchPath), + m_zone(zone) { - auto* weapon = memory->Create(); - memset(weapon, 0, sizeof(WeaponCompleteDef)); - weapon->szInternalName = memory->Dup(assetName.c_str()); - return weapon; } -bool AssetLoaderWeapon::CanLoadFromGdt() const +AssetCreationResult InfoStringLoaderWeapon::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) { - return true; -} + auto* weaponFullDef = m_memory.Alloc(); -bool AssetLoaderWeapon::LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_WEAPON, assetName); - if (gdtEntry == nullptr) - return false; + InitWeaponFullDef(*weaponFullDef); + weaponFullDef->weapCompleteDef.szInternalName = m_memory.Dup(assetName.c_str()); - InfoString infoString; - if (!infoString.FromGdtProperties(*gdtEntry)) + AssetRegistration registration(assetName, &weaponFullDef->weapCompleteDef); + + InfoStringToWeaponConverter converter( + infoString, *weaponFullDef, m_zone.m_script_strings, m_memory, context, registration, weapon_fields, std::extent_v); + if (!converter.Convert()) { - std::cerr << "Failed to read weapon gdt entry: \"" << assetName << "\"\n"; - return true; + std::cerr << std::format("Failed to parse weapon: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); } - return LoadFromInfoString(infoString, assetName, memory, manager, zone); -} - -bool AssetLoaderWeapon::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderWeapon::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto fileName = std::format("weapons/{}", assetName); - const auto file = searchPath->Open(fileName); - if (!file.IsOpen()) - return false; - - InfoString infoString; - if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_WEAPON, *file.m_stream)) - { - std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n"; - return true; - } - - return LoadFromInfoString(infoString, assetName, memory, manager, zone); + CalculateWeaponFields(*weaponFullDef, m_memory); + + LoadAccuracyGraphs(*weaponFullDef, m_memory, m_search_path, context); + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); } diff --git a/src/ObjLoading/Game/IW5/Weapon/InfoStringLoaderWeaponIW5.h b/src/ObjLoading/Game/IW5/Weapon/InfoStringLoaderWeaponIW5.h new file mode 100644 index 00000000..06d6e076 --- /dev/null +++ b/src/ObjLoading/Game/IW5/Weapon/InfoStringLoaderWeaponIW5.h @@ -0,0 +1,21 @@ +#pragma once + +#include "Asset/AssetCreationContext.h" +#include "Asset/AssetCreationResult.h" +#include "InfoString/InfoString.h" + +namespace IW5 +{ + class InfoStringLoaderWeapon + { + public: + InfoStringLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); + + AssetCreationResult CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context); + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + Zone& m_zone; + }; +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Weapon/JsonWeaponAttachmentLoader.cpp b/src/ObjLoading/Game/IW5/Weapon/JsonWeaponAttachmentLoader.cpp index 71a77664..f6ef081e 100644 --- a/src/ObjLoading/Game/IW5/Weapon/JsonWeaponAttachmentLoader.cpp +++ b/src/ObjLoading/Game/IW5/Weapon/JsonWeaponAttachmentLoader.cpp @@ -15,16 +15,11 @@ namespace class JsonLoader { public: - JsonLoader(std::istream& stream, - MemoryManager& memory, - IAssetLoadingManager& manager, - std::vector& dependencies, - std::vector& indirectAssetReferences) + JsonLoader(std::istream& stream, MemoryManager& memory, AssetCreationContext& context, AssetRegistration& registration) : m_stream(stream), m_memory(memory), - m_manager(manager), - m_dependencies(dependencies), - m_indirect_asset_references(indirectAssetReferences) + m_context(context), + m_registration(registration) { } @@ -129,13 +124,13 @@ namespace bool CreateTracerFromJson(const std::string& assetName, TracerDef*& tracerPtr, const WeaponAttachment& attachment) const { - auto* tracer = m_manager.LoadDependency(assetName); + auto* tracer = m_context.LoadDependency(assetName); if (!tracer) { PrintError(attachment, std::format("Could not find tracer {}", assetName)); return false; } - m_dependencies.push_back(tracer); + m_registration.AddDependency(tracer); tracerPtr = tracer->Asset(); return true; @@ -143,13 +138,13 @@ namespace bool CreateMaterialFromJson(const std::string& assetName, Material*& materialPtr, const WeaponAttachment& attachment) const { - auto* material = m_manager.LoadDependency(assetName); + auto* material = m_context.LoadDependency(assetName); if (!material) { PrintError(attachment, std::format("Could not find material {}", assetName)); return false; } - m_dependencies.push_back(material); + m_registration.AddDependency(material); materialPtr = material->Asset(); return true; @@ -157,13 +152,13 @@ namespace bool CreateFxFromJson(const std::string& assetName, FxEffectDef*& fxPtr, const WeaponAttachment& attachment) const { - auto* fx = m_manager.LoadDependency(assetName); + auto* fx = m_context.LoadDependency(assetName); if (!fx) { PrintError(attachment, std::format("Could not find fx {}", assetName)); return false; } - m_dependencies.push_back(fx); + m_registration.AddDependency(fx); fxPtr = fx->Asset(); return true; @@ -171,8 +166,7 @@ namespace bool CreateSoundFromJson(const std::string& assetName, SndAliasCustom& sndAliasCustom, const WeaponAttachment& attachment) const { - auto sound = m_manager.LoadIndirectAssetReference(assetName); - m_indirect_asset_references.push_back(std::move(sound)); + m_registration.AddIndirectAssetReference(m_context.LoadIndirectAssetReference(assetName)); sndAliasCustom.name = m_memory.Alloc(); sndAliasCustom.name->soundName = m_memory.Dup(assetName.c_str()); @@ -181,13 +175,13 @@ namespace bool CreateXModelFromJson(const std::string& assetName, XModel*& xmodelPtr, const WeaponAttachment& attachment) const { - auto* xmodel = m_manager.LoadDependency(assetName); + auto* xmodel = m_context.LoadDependency(assetName); if (!xmodel) { PrintError(attachment, std::format("Could not find xmodel {}", assetName)); return false; } - m_dependencies.push_back(xmodel); + m_registration.AddDependency(xmodel); xmodelPtr = xmodel->Asset(); return true; @@ -631,9 +625,8 @@ namespace std::istream& m_stream; MemoryManager& m_memory; - IAssetLoadingManager& m_manager; - std::vector& m_dependencies; - std::vector& m_indirect_asset_references; + AssetCreationContext& m_context; + AssetRegistration& m_registration; }; } // namespace @@ -641,12 +634,11 @@ namespace IW5 { bool LoadWeaponAttachmentAsJson(std::istream& stream, WeaponAttachment& attachment, - MemoryManager* memory, - IAssetLoadingManager* manager, - std::vector& dependencies, - std::vector& indirectAssetReferences) + MemoryManager& memory, + AssetCreationContext& context, + AssetRegistration& registration) { - const JsonLoader loader(stream, *memory, *manager, dependencies, indirectAssetReferences); + const JsonLoader loader(stream, memory, context, registration); return loader.Load(attachment); } diff --git a/src/ObjLoading/Game/IW5/Weapon/JsonWeaponAttachmentLoader.h b/src/ObjLoading/Game/IW5/Weapon/JsonWeaponAttachmentLoader.h index 8bf8df8b..5b9d7b06 100644 --- a/src/ObjLoading/Game/IW5/Weapon/JsonWeaponAttachmentLoader.h +++ b/src/ObjLoading/Game/IW5/Weapon/JsonWeaponAttachmentLoader.h @@ -1,6 +1,7 @@ #pragma once -#include "AssetLoading/IAssetLoadingManager.h" +#include "Asset/AssetCreationContext.h" +#include "Asset/AssetRegistration.h" #include "Game/IW5/IW5.h" #include "Utils/MemoryManager.h" @@ -10,8 +11,7 @@ namespace IW5 { bool LoadWeaponAttachmentAsJson(std::istream& stream, WeaponAttachment& attachment, - MemoryManager* memory, - IAssetLoadingManager* manager, - std::vector& dependencies, - std::vector& indirectAssetReferences); + MemoryManager& memory, + AssetCreationContext& context, + AssetRegistration& registration); } // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Weapon/LoaderAttachmentIW5.cpp b/src/ObjLoading/Game/IW5/Weapon/LoaderAttachmentIW5.cpp new file mode 100644 index 00000000..ac7197c1 --- /dev/null +++ b/src/ObjLoading/Game/IW5/Weapon/LoaderAttachmentIW5.cpp @@ -0,0 +1,54 @@ +#include "LoaderAttachmentIW5.h" + +#include "Game/IW5/IW5.h" +#include "JsonWeaponAttachmentLoader.h" + +#include +#include +#include + +using namespace IW5; + +namespace +{ + class AttachmentLoader final : public AssetCreator + { + public: + AttachmentLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto file = m_search_path.Open(std::format("attachment/{}.json", assetName)); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + auto* attachment = m_memory.Alloc(); + attachment->szInternalName = m_memory.Dup(assetName.c_str()); + + AssetRegistration registration(assetName, attachment); + if (!LoadWeaponAttachmentAsJson(*file.m_stream, *attachment, m_memory, context, registration)) + { + std::cerr << std::format("Failed to load attachment \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace IW5 +{ + std::unique_ptr> CreateAttachmentLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Weapon/LoaderAttachmentIW5.h b/src/ObjLoading/Game/IW5/Weapon/LoaderAttachmentIW5.h new file mode 100644 index 00000000..ec43ff96 --- /dev/null +++ b/src/ObjLoading/Game/IW5/Weapon/LoaderAttachmentIW5.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW5/IW5.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW5 +{ + std::unique_ptr> CreateAttachmentLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Weapon/RawLoaderWeaponIW5.cpp b/src/ObjLoading/Game/IW5/Weapon/RawLoaderWeaponIW5.cpp new file mode 100644 index 00000000..642efa2e --- /dev/null +++ b/src/ObjLoading/Game/IW5/Weapon/RawLoaderWeaponIW5.cpp @@ -0,0 +1,54 @@ +#include "RawLoaderWeaponIW5.h" + +#include "Game/IW5/IW5.h" +#include "Game/IW5/ObjConstantsIW5.h" +#include "InfoString/InfoString.h" +#include "InfoStringLoaderWeaponIW5.h" + +#include +#include +#include + +using namespace IW5; + +namespace +{ + class RawLoaderWeapon final : public AssetCreator + { + public: + RawLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_search_path(searchPath), + m_info_string_loader(memory, searchPath, zone) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto fileName = std::format("weapons/{}", assetName); + const auto file = m_search_path.Open(fileName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + InfoString infoString; + if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_WEAPON, *file.m_stream)) + { + std::cerr << std::format("Could not parse as info string file: \"{}\"\n", fileName); + return AssetCreationResult::Failure(); + } + + return m_info_string_loader.CreateAsset(assetName, infoString, context); + } + + private: + ISearchPath& m_search_path; + InfoStringLoaderWeapon m_info_string_loader; + }; +} // namespace + +namespace IW5 +{ + std::unique_ptr> CreateRawWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + { + return std::make_unique(memory, searchPath, zone); + } +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Weapon/RawLoaderWeaponIW5.h b/src/ObjLoading/Game/IW5/Weapon/RawLoaderWeaponIW5.h new file mode 100644 index 00000000..d5df5fcf --- /dev/null +++ b/src/ObjLoading/Game/IW5/Weapon/RawLoaderWeaponIW5.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/IW5/IW5.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace IW5 +{ + std::unique_ptr> CreateRawWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/XModel/LoaderXModelIW5asdf.cpp b/src/ObjLoading/Game/IW5/XModel/LoaderXModelIW5asdf.cpp new file mode 100644 index 00000000..973d59f3 --- /dev/null +++ b/src/ObjLoading/Game/IW5/XModel/LoaderXModelIW5asdf.cpp @@ -0,0 +1,55 @@ +// #include "LoaderXModelIW5.h" + +// #include "Game/IW5/IW5.h" +// #include "Game/IW5/XModel/XModelLoaderIW5.h" +// #include "Pool/GlobalAssetPool.h" + +// #include +// #include +// #include + +// using namespace IW5; + +// namespace +// { +// class XModelLoader final : public AssetCreator +// { +// public: +// XModelLoader(MemoryManager& memory, ISearchPath& searchPath) +// : m_memory(memory), +// m_search_path(searchPath) +// { +// } + +// AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override +// { +// const auto file = m_search_path.Open(std::format("xmodel/{}.json", assetName)); +// if (!file.IsOpen()) +// return AssetCreationResult::NoAction(); + +// auto* xmodel = m_memory.Alloc(); +// xmodel->name = m_memory.Dup(assetName.c_str()); + +// AssetRegistration registration(assetName, xmodel); +// if (!LoadXModel(*file.m_stream, *xmodel, m_memory, context, registration)) +// { +// std::cerr << std::format("Failed to load xmodel \"{}\"\n", assetName); +// return AssetCreationResult::Failure(); +// } + +// return AssetCreationResult::Success(context.AddAsset(std::move(registration))); +// } + +// private: +// MemoryManager& m_memory; +// ISearchPath& m_search_path; +// }; +// } // namespace + +// namespace IW5 +// { +// std::unique_ptr> CreateXModelLoader(MemoryManager& memory, ISearchPath& searchPath) +// { +// return std::make_unique(memory, searchPath); +// } +// } // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/XModel/LoaderXModelIW5asdf.h b/src/ObjLoading/Game/IW5/XModel/LoaderXModelIW5asdf.h new file mode 100644 index 00000000..3d656f21 --- /dev/null +++ b/src/ObjLoading/Game/IW5/XModel/LoaderXModelIW5asdf.h @@ -0,0 +1,13 @@ +// #pragma once + +// #include "Asset/IAssetCreator.h" +// #include "Game/IW5/IW5.h" +// #include "SearchPath/ISearchPath.h" +// #include "Utils/MemoryManager.h" + +// #include + +// namespace IW5 +// { +// std::unique_ptr> CreateXModelLoader(MemoryManager& memory, ISearchPath& searchPath); +// } // namespace IW5 diff --git a/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderLocalizeEntry.cpp b/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderLocalizeEntry.cpp deleted file mode 100644 index 720af58a..00000000 --- a/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderLocalizeEntry.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "AssetLoaderLocalizeEntry.h" - -#include "Localize/LocalizeCommonAssetLoader.h" - -using namespace T5; - -XAssetInfoGeneric* AssetLoaderLocalizeEntry::LoadFromGlobalAssetPools(const std::string& assetName) const -{ - return nullptr; -} - -void* AssetLoaderLocalizeEntry::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - return nullptr; -} - -bool AssetLoaderLocalizeEntry::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderLocalizeEntry::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const LocalizeCommonAssetLoader commonLoader( - [memory, manager](const CommonLocalizeEntry& entry) - { - auto* localizeEntry = memory->Create(); - localizeEntry->name = memory->Dup(entry.m_key.c_str()); - localizeEntry->value = memory->Dup(entry.m_value.c_str()); - - manager->AddAsset(entry.m_key, localizeEntry); - }); - - return commonLoader.LoadLocalizeAsset(assetName, searchPath, manager, zone); -} diff --git a/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderLocalizeEntry.h b/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderLocalizeEntry.h deleted file mode 100644 index 3033df86..00000000 --- a/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderLocalizeEntry.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T5/T5.h" -#include "SearchPath/ISearchPath.h" - -namespace T5 -{ - class AssetLoaderLocalizeEntry final : public BasicAssetLoader - { - public: - _NODISCARD XAssetInfoGeneric* LoadFromGlobalAssetPools(const std::string& assetName) const override; - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T5 diff --git a/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderRawFile.cpp b/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderRawFile.cpp deleted file mode 100644 index 53a5ae1a..00000000 --- a/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderRawFile.cpp +++ /dev/null @@ -1,116 +0,0 @@ -#include "AssetLoaderRawFile.h" - -#include "Game/T5/T5.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include -#include -#include - -using namespace T5; - -namespace fs = std::filesystem; - -void* AssetLoaderRawFile::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* rawFile = memory->Create(); - memset(rawFile, 0, sizeof(RawFile)); - rawFile->name = memory->Dup(assetName.c_str()); - return rawFile; -} - -bool AssetLoaderRawFile::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderRawFile::LoadGsc( - const SearchPathOpenFile& file, const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) -{ - const auto uncompressedBuffer = std::make_unique(static_cast(file.m_length + 1)); - file.m_stream->read(uncompressedBuffer.get(), file.m_length); - if (file.m_stream->gcount() != file.m_length) - return false; - uncompressedBuffer[static_cast(file.m_length)] = '\0'; - - const auto compressionBufferSize = static_cast(file.m_length + 1 + sizeof(uint32_t) + sizeof(uint32_t) + COMPRESSED_BUFFER_SIZE_PADDING); - auto* compressedBuffer = memory->Alloc(compressionBufferSize); - - z_stream_s zs{}; - - zs.zalloc = Z_NULL; - zs.zfree = Z_NULL; - zs.opaque = Z_NULL; - zs.avail_in = static_cast(file.m_length + 1); - zs.avail_out = compressionBufferSize; - zs.next_in = reinterpret_cast(uncompressedBuffer.get()); - zs.next_out = reinterpret_cast(&compressedBuffer[sizeof(uint32_t) + sizeof(uint32_t)]); - - int ret = deflateInit(&zs, Z_DEFAULT_COMPRESSION); - - if (ret != Z_OK) - { - throw std::runtime_error("Initializing deflate failed"); - } - - ret = deflate(&zs, Z_FINISH); - - if (ret != Z_STREAM_END) - { - std::cerr << "Deflate failed for loading gsc file \"" << assetName << "\"\n"; - deflateEnd(&zs); - return false; - } - - const auto compressedSize = compressionBufferSize - zs.avail_out; - - reinterpret_cast(compressedBuffer)[0] = static_cast(file.m_length + 1); // outLen - reinterpret_cast(compressedBuffer)[1] = compressedSize; // inLen - - auto* rawFile = memory->Create(); - rawFile->name = memory->Dup(assetName.c_str()); - rawFile->len = static_cast(compressedSize + sizeof(uint32_t) + sizeof(uint32_t)); - rawFile->buffer = static_cast(compressedBuffer); - - deflateEnd(&zs); - - manager->AddAsset(assetName, rawFile); - - return true; -} - -bool AssetLoaderRawFile::LoadDefault( - const SearchPathOpenFile& file, const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) -{ - auto* rawFile = memory->Create(); - rawFile->name = memory->Dup(assetName.c_str()); - rawFile->len = static_cast(file.m_length); - - auto* fileBuffer = memory->Alloc(static_cast(file.m_length + 1)); - file.m_stream->read(fileBuffer, file.m_length); - if (file.m_stream->gcount() != file.m_length) - return false; - fileBuffer[rawFile->len] = '\0'; - - rawFile->buffer = fileBuffer; - manager->AddAsset(assetName, rawFile); - - return true; -} - -bool AssetLoaderRawFile::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(assetName); - if (!file.IsOpen()) - return false; - - const fs::path rawFilePath(assetName); - const auto extension = rawFilePath.extension().string(); - - if (extension == ".gsc" || extension == ".csc") - return LoadGsc(file, assetName, searchPath, memory, manager); - - return LoadDefault(file, assetName, searchPath, memory, manager); -} diff --git a/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderRawFile.h b/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderRawFile.h deleted file mode 100644 index 54bc33a7..00000000 --- a/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderRawFile.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T5/T5.h" -#include "SearchPath/ISearchPath.h" - -namespace T5 -{ - class AssetLoaderRawFile final : public BasicAssetLoader - { - static constexpr size_t COMPRESSED_BUFFER_SIZE_PADDING = 64; - - static bool LoadGsc( - const SearchPathOpenFile& file, const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager); - static bool LoadDefault( - const SearchPathOpenFile& file, const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager); - - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T5 diff --git a/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderStringTable.cpp b/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderStringTable.cpp deleted file mode 100644 index 3d06701e..00000000 --- a/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderStringTable.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "AssetLoaderStringTable.h" - -#include "Csv/CsvStream.h" -#include "Game/T5/CommonT5.h" -#include "Game/T5/T5.h" -#include "Pool/GlobalAssetPool.h" -#include "StringTable/StringTableLoader.h" - -#include - -using namespace T5; - -void* AssetLoaderStringTable::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* stringTable = memory->Create(); - memset(stringTable, 0, sizeof(StringTable)); - stringTable->name = memory->Dup(assetName.c_str()); - return stringTable; -} - -bool AssetLoaderStringTable::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderStringTable::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(assetName); - if (!file.IsOpen()) - return false; - - string_table::StringTableLoaderV3 loader; - auto* stringTable = loader.LoadFromStream(assetName, *memory, *file.m_stream); - - manager->AddAsset(assetName, stringTable); - - return true; -} diff --git a/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderStringTable.h b/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderStringTable.h deleted file mode 100644 index fc90f9a8..00000000 --- a/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderStringTable.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T5/T5.h" -#include "SearchPath/ISearchPath.h" - -namespace T5 -{ - class AssetLoaderStringTable final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T5 diff --git a/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderWeapon.cpp b/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderWeapon.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderWeapon.h b/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderWeapon.h deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderXModel.cpp b/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderXModel.cpp deleted file mode 100644 index 22dee30f..00000000 --- a/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderXModel.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "AssetLoaderXModel.h" - -#include "Game/T5/T5.h" -#include "Game/T5/XModel/XModelLoaderT5.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include -#include - -using namespace T5; - -void* AssetLoaderXModel::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} - -bool AssetLoaderXModel::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderXModel::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(std::format("xmodel/{}.json", assetName)); - if (!file.IsOpen()) - return false; - - auto* xmodel = memory->Alloc(); - xmodel->name = memory->Dup(assetName.c_str()); - - std::vector dependencies; - if (LoadXModel(*file.m_stream, *xmodel, memory, manager, dependencies)) - { - manager->AddAsset(assetName, xmodel, std::move(dependencies)); - } - else - { - std::cerr << std::format("Failed to load xmodel \"{}\"\n", assetName); - return false; - } - - return true; -} diff --git a/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderXModel.h b/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderXModel.h deleted file mode 100644 index 4a669630..00000000 --- a/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderXModel.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T5/T5.h" -#include "SearchPath/ISearchPath.h" - -namespace T5 -{ - class AssetLoaderXModel final : public BasicAssetLoader - { - static std::string GetFileNameForAsset(const std::string& assetName); - - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T5 diff --git a/src/ObjLoading/Game/T5/InfoString/InfoStringToStructConverter.cpp b/src/ObjLoading/Game/T5/InfoString/InfoStringToStructConverter.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ObjLoading/Game/T5/InfoString/InfoStringToStructConverter.h b/src/ObjLoading/Game/T5/InfoString/InfoStringToStructConverter.h deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ObjLoading/Game/T5/Localize/LoaderLocalizeT5.cpp b/src/ObjLoading/Game/T5/Localize/LoaderLocalizeT5.cpp new file mode 100644 index 00000000..175b71fb --- /dev/null +++ b/src/ObjLoading/Game/T5/Localize/LoaderLocalizeT5.cpp @@ -0,0 +1,44 @@ +#include "LoaderLocalizeT5.h" + +#include "Localize/CommonLocalizeLoader.h" + +using namespace T5; + +namespace +{ + class LocalizeLoader final : public AssetCreator, public CommonLocalizeLoader + { + public: + LocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : CommonLocalizeLoader(searchPath, zone), + m_memory(memory) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + return CreateLocalizeAsset(assetName, context); + } + + protected: + AssetCreationResult CreateAssetFromCommonAsset(const CommonLocalizeEntry& localizeEntry, AssetCreationContext& context) override + { + auto* asset = m_memory.Alloc(); + asset->name = m_memory.Dup(localizeEntry.m_key.c_str()); + asset->value = m_memory.Dup(localizeEntry.m_value.c_str()); + + return AssetCreationResult::Success(context.AddAsset(localizeEntry.m_key, asset)); + } + + private: + MemoryManager& m_memory; + }; +} // namespace + +namespace T5 +{ + std::unique_ptr> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + { + return std::make_unique(memory, searchPath, zone); + } +} // namespace T5 diff --git a/src/ObjLoading/Game/T5/Localize/LoaderLocalizeT5.h b/src/ObjLoading/Game/T5/Localize/LoaderLocalizeT5.h new file mode 100644 index 00000000..fd71deb5 --- /dev/null +++ b/src/ObjLoading/Game/T5/Localize/LoaderLocalizeT5.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T5/T5.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" +#include "Zone/Zone.h" + +#include + +namespace T5 +{ + std::unique_ptr> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace T5 diff --git a/src/ObjLoading/Game/T5/ObjLoaderT5.cpp b/src/ObjLoading/Game/T5/ObjLoaderT5.cpp index 3ec02cf4..5308111e 100644 --- a/src/ObjLoading/Game/T5/ObjLoaderT5.cpp +++ b/src/ObjLoading/Game/T5/ObjLoaderT5.cpp @@ -1,83 +1,143 @@ #include "ObjLoaderT5.h" -#include "AssetLoaders/AssetLoaderLocalizeEntry.h" -#include "AssetLoaders/AssetLoaderRawFile.h" -#include "AssetLoaders/AssetLoaderStringTable.h" -#include "AssetLoaders/AssetLoaderXModel.h" -#include "AssetLoading/AssetLoadingManager.h" +#include "Asset/GlobalAssetPoolsLoader.h" #include "Game/T5/GameT5.h" -#include "Image/IwiLoader.h" -#include "ObjContainer/IPak/IPak.h" +#include "Game/T5/T5.h" +#include "Game/T5/XModel/LoaderXModelT5.h" +#include "Localize/LoaderLocalizeT5.h" +#include "ObjLoading.h" +#include "RawFile/LoaderRawFileT5.h" +#include "StringTable/LoaderStringTableT5.h" + +#include using namespace T5; -ObjLoader::ObjLoader() -{ -#define REGISTER_ASSET_LOADER(t) \ - { \ - auto l = std::make_unique(); \ - m_asset_loaders_by_type[l->GetHandlingAssetType()] = std::move(l); \ - } - - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(AssetLoaderXModel) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(AssetLoaderLocalizeEntry) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(AssetLoaderRawFile) - REGISTER_ASSET_LOADER(AssetLoaderStringTable) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - REGISTER_ASSET_LOADER(BasicAssetLoader) - -#undef REGISTER_ASSET_LOADER -} - -bool ObjLoader::IsMpZone(const Zone& zone) -{ - return zone.m_name.compare(0, 3, "mp_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_mp") == 0; -} - -bool ObjLoader::IsZmZone(const Zone& zone) -{ - return zone.m_name.compare(0, 3, "zm_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_zm") == 0; -} - void ObjLoader::LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const {} void ObjLoader::UnloadContainersOfZone(Zone& zone) const {} -bool ObjLoader::LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const +namespace { - AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, context); - return assetLoadingManager.LoadAssetFromLoader(assetType, assetName); -} + void ConfigureDefaultCreators(AssetCreatorCollection& collection, Zone& zone) + { + auto& memory = *zone.GetMemory(); -void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext& context) const + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + // AssetImpactFx has no name and cannot be default constructed + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + // AssetEmblemSet has no name and cannot be default constructed + } + + void ConfigureGlobalAssetPoolsLoaders(AssetCreatorCollection& collection, Zone& zone) + { + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + } + + void ConfigureLoaders(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath) + { + auto& memory = *zone.GetMemory(); + + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateXModelLoader(memory, searchPath, zone)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateLocalizeLoader(memory, searchPath, zone)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateRawFileLoader(memory, searchPath)); + collection.AddAssetCreator(CreateStringTableLoader(memory, searchPath)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + } +} // namespace + +void ObjLoader::ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, IGdtQueryable& gdt) const { - for (const auto& [type, loader] : m_asset_loaders_by_type) - loader->FinalizeAssetsForZone(context); + ConfigureDefaultCreators(collection, zone); + ConfigureLoaders(collection, zone, searchPath); + ConfigureGlobalAssetPoolsLoaders(collection, zone); } diff --git a/src/ObjLoading/Game/T5/ObjLoaderT5.h b/src/ObjLoading/Game/T5/ObjLoaderT5.h index 4ede43c4..99fc99c8 100644 --- a/src/ObjLoading/Game/T5/ObjLoaderT5.h +++ b/src/ObjLoading/Game/T5/ObjLoaderT5.h @@ -1,29 +1,16 @@ #pragma once -#include "AssetLoading/IAssetLoader.h" #include "IObjLoader.h" #include "SearchPath/ISearchPath.h" -#include -#include - namespace T5 { class ObjLoader final : public IObjLoader { public: - ObjLoader(); - void LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const override; void UnloadContainersOfZone(Zone& zone) const override; - bool LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const override; - void FinalizeAssetsForZone(AssetLoadingContext& context) const override; - - private: - static bool IsMpZone(const Zone& zone); - static bool IsZmZone(const Zone& zone); - - std::unordered_map> m_asset_loaders_by_type; + void ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, IGdtQueryable& gdt) const override; }; } // namespace T5 diff --git a/src/ObjLoading/Game/T5/RawFile/LoaderRawFileT5.cpp b/src/ObjLoading/Game/T5/RawFile/LoaderRawFileT5.cpp new file mode 100644 index 00000000..4ffa79db --- /dev/null +++ b/src/ObjLoading/Game/T5/RawFile/LoaderRawFileT5.cpp @@ -0,0 +1,123 @@ +#include "LoaderRawFileT5.h" + +#include "Game/T5/T5.h" + +#include +#include +#include +#include +#include + +using namespace T5; +namespace fs = std::filesystem; + +namespace +{ + constexpr size_t COMPRESSED_BUFFER_SIZE_PADDING = 64; + + class RawFileLoader final : public AssetCreator + { + public: + RawFileLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto file = m_search_path.Open(assetName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + const fs::path rawFilePath(assetName); + const auto extension = rawFilePath.extension().string(); + + if (extension == ".gsc" || extension == ".csc") + return LoadGsc(file, assetName, context); + + return LoadDefault(file, assetName, context); + } + + private: + AssetCreationResult LoadGsc(const SearchPathOpenFile& file, const std::string& assetName, AssetCreationContext& context) + { + const auto uncompressedBuffer = std::make_unique(static_cast(file.m_length + 1)); + + file.m_stream->read(uncompressedBuffer.get(), file.m_length); + if (file.m_stream->gcount() != file.m_length) + return AssetCreationResult::Failure(); + + uncompressedBuffer[static_cast(file.m_length)] = '\0'; + + const auto compressionBufferSize = static_cast(file.m_length + 1 + sizeof(uint32_t) + sizeof(uint32_t) + COMPRESSED_BUFFER_SIZE_PADDING); + auto* compressedBuffer = m_memory.Alloc(compressionBufferSize); + + z_stream_s zs{}; + zs.zalloc = Z_NULL; + zs.zfree = Z_NULL; + zs.opaque = Z_NULL; + zs.avail_in = static_cast(file.m_length + 1); + zs.avail_out = compressionBufferSize; + zs.next_in = reinterpret_cast(uncompressedBuffer.get()); + zs.next_out = reinterpret_cast(&compressedBuffer[sizeof(uint32_t) + sizeof(uint32_t)]); + + int ret = deflateInit(&zs, Z_DEFAULT_COMPRESSION); + + if (ret != Z_OK) + throw std::runtime_error("Initializing deflate failed"); + + ret = deflate(&zs, Z_FINISH); + + if (ret != Z_STREAM_END) + { + std::cerr << std::format("Deflate failed for loading gsc file \"{}\"\n", assetName); + deflateEnd(&zs); + return AssetCreationResult::Failure(); + } + + const auto compressedSize = compressionBufferSize - zs.avail_out; + + reinterpret_cast(compressedBuffer)[0] = static_cast(file.m_length + 1); // outLen + reinterpret_cast(compressedBuffer)[1] = compressedSize; // inLen + + auto* rawFile = m_memory.Alloc(); + rawFile->name = m_memory.Dup(assetName.c_str()); + rawFile->len = static_cast(compressedSize + sizeof(uint32_t) + sizeof(uint32_t)); + rawFile->buffer = static_cast(compressedBuffer); + + deflateEnd(&zs); + + return AssetCreationResult::Success(context.AddAsset(assetName, rawFile)); + } + + AssetCreationResult LoadDefault(const SearchPathOpenFile& file, const std::string& assetName, AssetCreationContext& context) + { + auto* rawFile = m_memory.Alloc(); + rawFile->name = m_memory.Dup(assetName.c_str()); + rawFile->len = static_cast(file.m_length); + + auto* fileBuffer = m_memory.Alloc(static_cast(file.m_length + 1)); + + file.m_stream->read(fileBuffer, file.m_length); + if (file.m_stream->gcount() != file.m_length) + return AssetCreationResult::Failure(); + + fileBuffer[rawFile->len] = '\0'; + rawFile->buffer = fileBuffer; + + return AssetCreationResult::Success(context.AddAsset(assetName, rawFile)); + } + + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace T5 +{ + std::unique_ptr> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace T5 diff --git a/src/ObjLoading/Game/T5/RawFile/LoaderRawFileT5.h b/src/ObjLoading/Game/T5/RawFile/LoaderRawFileT5.h new file mode 100644 index 00000000..42e83ed3 --- /dev/null +++ b/src/ObjLoading/Game/T5/RawFile/LoaderRawFileT5.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T5/T5.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T5 +{ + std::unique_ptr> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace T5 diff --git a/src/ObjLoading/Game/T5/StringTable/LoaderStringTableT5.cpp b/src/ObjLoading/Game/T5/StringTable/LoaderStringTableT5.cpp new file mode 100644 index 00000000..f50b423a --- /dev/null +++ b/src/ObjLoading/Game/T5/StringTable/LoaderStringTableT5.cpp @@ -0,0 +1,46 @@ +#include "LoaderStringTableT5.h" + +#include "Game/T5/CommonT5.h" +#include "Game/T5/T5.h" +#include "StringTable/StringTableLoader.h" + +#include + +using namespace T5; + +namespace +{ + class StringTableLoader final : public AssetCreator + { + public: + StringTableLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto file = m_search_path.Open(assetName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + string_table::StringTableLoaderV3 loader; + auto* stringTable = loader.LoadFromStream(assetName, m_memory, *file.m_stream); + + return AssetCreationResult::Success(context.AddAsset(assetName, stringTable)); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace T5 +{ + std::unique_ptr> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace T5 diff --git a/src/ObjLoading/Game/T5/StringTable/LoaderStringTableT5.h b/src/ObjLoading/Game/T5/StringTable/LoaderStringTableT5.h new file mode 100644 index 00000000..3479639b --- /dev/null +++ b/src/ObjLoading/Game/T5/StringTable/LoaderStringTableT5.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T5/T5.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T5 +{ + std::unique_ptr> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace T5 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderAddonMapEnts.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderAddonMapEnts.cpp deleted file mode 100644 index cb51edca..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderAddonMapEnts.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderAddonMapEnts.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderAddonMapEnts::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderAddonMapEnts.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderAddonMapEnts.h deleted file mode 100644 index 1f7f0ae9..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderAddonMapEnts.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderAddonMapEnts final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderClipMap.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderClipMap.cpp deleted file mode 100644 index 16d161e3..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderClipMap.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "AssetLoaderClipMap.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderClipMapBase::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} - -asset_type_t AssetLoaderClipMap::GetHandlingAssetType() const -{ - return ASSET_TYPE_CLIPMAP; -} - -asset_type_t AssetLoaderClipMapPvs::GetHandlingAssetType() const -{ - return ASSET_TYPE_CLIPMAP_PVS; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderClipMap.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderClipMap.h deleted file mode 100644 index fbe0145b..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderClipMap.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderClipMapBase : public BasicAssetLoaderWithoutType - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; - - class AssetLoaderClipMap final : public AssetLoaderClipMapBase - { - public: - [[nodiscard]] asset_type_t GetHandlingAssetType() const override; - }; - - class AssetLoaderClipMapPvs final : public AssetLoaderClipMapBase - { - public: - [[nodiscard]] asset_type_t GetHandlingAssetType() const override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderComWorld.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderComWorld.cpp deleted file mode 100644 index db595fa5..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderComWorld.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderComWorld.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderComWorld::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderComWorld.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderComWorld.h deleted file mode 100644 index 7a8879b0..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderComWorld.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderComWorld final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderDDL.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderDDL.cpp deleted file mode 100644 index 9dfe415a..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderDDL.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderDDL.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderDDL::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderDDL.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderDDL.h deleted file mode 100644 index fa63756a..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderDDL.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderDDL final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderDestructibleDef.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderDestructibleDef.cpp deleted file mode 100644 index 95162e2e..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderDestructibleDef.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderDestructibleDef.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderDestructibleDef::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderDestructibleDef.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderDestructibleDef.h deleted file mode 100644 index 67bc6e10..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderDestructibleDef.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderDestructibleDef final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderEmblemSet.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderEmblemSet.cpp deleted file mode 100644 index a6c99892..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderEmblemSet.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderEmblemSet.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderEmblemSet::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - // Asset does not have a name - // So this cannot be an asset reference - return nullptr; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderEmblemSet.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderEmblemSet.h deleted file mode 100644 index e28fd74b..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderEmblemSet.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderEmblemSet final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFont.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFont.cpp deleted file mode 100644 index af8fd342..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFont.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderFont.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderFont::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->fontName = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFont.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFont.h deleted file mode 100644 index 50826ebd..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFont.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderFont final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFontIcon.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFontIcon.cpp deleted file mode 100644 index e89d739c..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFontIcon.cpp +++ /dev/null @@ -1,270 +0,0 @@ -#include "AssetLoaderFontIcon.h" - -#include "Csv/CsvStream.h" -#include "Game/T6/CommonT6.h" -#include "Game/T6/T6.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include -#include - -using namespace T6; - -void* AssetLoaderFontIcon::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} - -bool AssetLoaderFontIcon::CanLoadFromRaw() const -{ - return true; -} - -std::string AssetLoaderFontIcon::ErrorPrefix(const std::string& assetName, const unsigned rowIndex) -{ - std::ostringstream str; - str << "FontIcon \"" << assetName << "\" Row " << rowIndex << ": "; - return str.str(); -} - -void AssetLoaderFontIcon::PreprocessRow(std::vector& row) -{ - for (auto& cell : row) - { - for (auto c : cell) - { - if (isspace(c)) - continue; - if (c == '#') - cell = ""; - break; - } - } -} - -bool AssetLoaderFontIcon::RowIsEmpty(const std::vector& row) -{ - return std::ranges::all_of(row, - [](const std::string& cell) - { - return cell.empty(); - }); -} - -bool AssetLoaderFontIcon::ParseInt(int& value, const std::string& str) -{ - char* endPtr; - value = strtol(str.c_str(), &endPtr, 0); - if (endPtr != &str[str.size()]) - return false; - return true; -} - -bool AssetLoaderFontIcon::ParseFloat(float& value, const std::string& str) -{ - char* endPtr; - value = strtof(str.c_str(), &endPtr); - if (endPtr != &str[str.size()]) - return false; - return true; -} - -bool AssetLoaderFontIcon::ParseHashStr(int& value, const std::string& str) -{ - if (!str.empty() && str[0] == '@' && str.size() > 1) - { - char* endPtr; - value = strtol(&str[1], &endPtr, 16); - - if (endPtr != &str[str.size()]) - return false; - } - else - { - value = Common::Com_HashString(str.c_str()); - } - - return true; -} - -bool AssetLoaderFontIcon::ReadIconRow(const std::vector& row, - FontIconEntry& icon, - const std::string& assetName, - const unsigned rowIndex, - MemoryManager* memory, - IAssetLoadingManager* manager, - std::vector& dependencies) -{ - if (row.size() < COL_COUNT_ICON) - { - std::cout << ErrorPrefix(assetName, rowIndex) << "Column count lower than min column count for entries (" << COL_COUNT_ICON << ")\n"; - return false; - } - - if (!ParseInt(icon.fontIconSize, row[ROW_ICON_SIZE])) - { - std::cout << ErrorPrefix(assetName, rowIndex) << "Failed to parse size\n"; - return false; - } - - if (!ParseFloat(icon.xScale, row[ROW_ICON_XSCALE]) || !ParseFloat(icon.yScale, row[ROW_ICON_YSCALE])) - { - std::cout << ErrorPrefix(assetName, rowIndex) << "Failed to parse scale\n"; - return false; - } - - auto* materialDependency = manager->LoadDependency(row[ROW_ICON_MATERIAL]); - if (materialDependency == nullptr) - { - std::cout << ErrorPrefix(assetName, rowIndex) << "Failed to load material \"" << row[ROW_ICON_MATERIAL] << "\"\n"; - return false; - } - - icon.fontIconMaterialHandle = materialDependency->Asset(); - icon.fontIconName.string = memory->Dup(row[ROW_ICON_NAME].c_str()); - icon.fontIconName.hash = Common::Com_HashString(icon.fontIconName.string); - - return true; -} - -bool AssetLoaderFontIcon::ReadAliasRow(const std::vector& row, - FontIconAlias& alias, - const std::string& assetName, - const unsigned rowIndex, - MemoryManager* memory, - IAssetLoadingManager* manager) -{ - if (row.size() < COL_COUNT_ALIAS) - { - std::cout << ErrorPrefix(assetName, rowIndex) << "Column count lower than min column count for aliases (" << COL_COUNT_ALIAS << ")\n"; - return false; - } - - if (!ParseHashStr(alias.aliasHash, row[ROW_ALIAS_NAME])) - { - std::cout << ErrorPrefix(assetName, rowIndex) << "Failed to parse alias \"" << row[ROW_ALIAS_NAME] << "\"\n"; - return false; - } - - if (!ParseHashStr(alias.buttonHash, row[ROW_ALIAS_BUTTON])) - { - std::cout << ErrorPrefix(assetName, rowIndex) << "Failed to parse button \"" << row[ROW_ALIAS_BUTTON] << "\"\n"; - return false; - } - - return true; -} - -bool AssetLoaderFontIcon::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(assetName); - if (!file.IsOpen()) - return false; - - auto* fontIcon = memory->Create(); - fontIcon->name = memory->Dup(assetName.c_str()); - - const CsvInputStream csv(*file.m_stream); - std::vector dependencies; - std::vector currentRow; - std::vector entries; - std::vector aliases; - auto currentRowIndex = 0u; - - while (csv.NextRow(currentRow)) - { - currentRowIndex++; - PreprocessRow(currentRow); - - if (RowIsEmpty(currentRow)) - continue; - - if (currentRow.size() < COL_COUNT_MIN) - { - std::cout << ErrorPrefix(assetName, currentRowIndex) << "Column count lower than min column count (" << COL_COUNT_MIN << ")\n"; - return true; - } - - int index; - if (!ParseInt(index, currentRow[ROW_INDEX]) || index < 0) - { - std::cout << ErrorPrefix(assetName, currentRowIndex) << "Failed to parse index\n"; - return true; - } - - if (currentRow[ROW_TYPE] == VALUE_TYPE_ICON) - { - FontIconEntry icon{}; - if (!ReadIconRow(currentRow, icon, assetName, currentRowIndex, memory, manager, dependencies)) - return true; - - if (static_cast(index) == entries.size()) - { - entries.push_back(icon); - } - else if (static_cast(index) > entries.size()) - { - entries.reserve(index + 1); - entries[index] = icon; - } - else - { - entries[index] = icon; - } - } - else if (currentRow[ROW_TYPE] == VALUE_TYPE_ALIAS) - { - FontIconAlias alias{}; - if (!ReadAliasRow(currentRow, alias, assetName, currentRowIndex, memory, manager)) - return true; - - if (static_cast(index) == aliases.size()) - { - aliases.push_back(alias); - } - else if (static_cast(index) > aliases.size()) - { - aliases.reserve(index + 1); - aliases[index] = alias; - } - else - { - aliases[index] = alias; - } - } - else - { - std::cout << ErrorPrefix(assetName, currentRowIndex) << "Unknown row type \"" << currentRow[ROW_TYPE] << "\"\n"; - return true; - } - } - - fontIcon->numEntries = entries.size(); - fontIcon->numAliasEntries = aliases.size(); - - if (fontIcon->numEntries > 0) - { - fontIcon->fontIconEntry = memory->Alloc(fontIcon->numEntries); - for (auto i = 0u; i < entries.size(); i++) - fontIcon->fontIconEntry[i] = entries[i]; - } - else - fontIcon->fontIconEntry = nullptr; - - if (fontIcon->numAliasEntries > 0) - { - fontIcon->fontIconAlias = memory->Alloc(fontIcon->numAliasEntries); - for (auto i = 0u; i < aliases.size(); i++) - fontIcon->fontIconAlias[i] = aliases[i]; - } - else - fontIcon->fontIconAlias = nullptr; - - manager->AddAsset(assetName, fontIcon); - - return true; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFontIcon.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFontIcon.h deleted file mode 100644 index 7f78f0ee..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFontIcon.h +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -#include -#include -#include - -namespace T6 -{ - class AssetLoaderFontIcon final : public BasicAssetLoader - { - static constexpr unsigned ROW_INDEX = 0; - static constexpr unsigned ROW_TYPE = 1; - - static constexpr unsigned ROW_ICON_NAME = 2; - static constexpr unsigned ROW_ICON_MATERIAL = 3; - static constexpr unsigned ROW_ICON_SIZE = 4; - static constexpr unsigned ROW_ICON_XSCALE = 5; - static constexpr unsigned ROW_ICON_YSCALE = 6; - - static constexpr unsigned ROW_ALIAS_NAME = 2; - static constexpr unsigned ROW_ALIAS_BUTTON = 3; - - static constexpr const char* VALUE_TYPE_ICON = "icon"; - static constexpr const char* VALUE_TYPE_ALIAS = "alias"; - - static constexpr unsigned COL_COUNT_ICON = 7; - static constexpr unsigned COL_COUNT_ALIAS = 4; - static constexpr unsigned COL_COUNT_MIN = std::min(COL_COUNT_ICON, COL_COUNT_ALIAS); - - static std::string ErrorPrefix(const std::string& assetName, unsigned rowIndex); - static void PreprocessRow(std::vector& row); - static bool RowIsEmpty(const std::vector& row); - - static bool ParseInt(int& value, const std::string& str); - static bool ParseFloat(float& value, const std::string& str); - static bool ParseHashStr(int& value, const std::string& str); - - static bool ReadIconRow(const std::vector& row, - FontIconEntry& icon, - const std::string& assetName, - unsigned rowIndex, - MemoryManager* memory, - IAssetLoadingManager* manager, - std::vector& dependencies); - static bool ReadAliasRow(const std::vector& row, - FontIconAlias& alias, - const std::string& assetName, - unsigned rowIndex, - MemoryManager* memory, - IAssetLoadingManager* manager); - - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFootstepFxTable.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFootstepFxTable.cpp deleted file mode 100644 index e2ca8f02..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFootstepFxTable.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderFootstepFxTable.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderFootstepFxTable::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFootstepFxTable.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFootstepFxTable.h deleted file mode 100644 index 141ddf9c..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFootstepFxTable.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderFootstepFxTable final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFootstepTable.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFootstepTable.cpp deleted file mode 100644 index 8dcd8534..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFootstepTable.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderFootstepTable.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderFootstepTable::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFootstepTable.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFootstepTable.h deleted file mode 100644 index 66c00426..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFootstepTable.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderFootstepTable final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFx.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFx.cpp deleted file mode 100644 index b20d5d6e..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFx.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderFx.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderFx::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFx.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFx.h deleted file mode 100644 index ba190b4a..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderFx.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderFx final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGameWorldMp.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGameWorldMp.cpp deleted file mode 100644 index a09751f9..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGameWorldMp.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderGameWorldMp.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderGameWorldMp::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGameWorldMp.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGameWorldMp.h deleted file mode 100644 index 092ea981..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGameWorldMp.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderGameWorldMp final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGameWorldSp.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGameWorldSp.cpp deleted file mode 100644 index f69f7bbe..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGameWorldSp.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderGameWorldSp.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderGameWorldSp::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGameWorldSp.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGameWorldSp.h deleted file mode 100644 index bfd3ac1b..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGameWorldSp.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderGameWorldSp final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGfxImage.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGfxImage.cpp deleted file mode 100644 index 5c47dceb..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGfxImage.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "AssetLoaderGfxImage.h" - -#include "Game/T6/CommonT6.h" -#include "Game/T6/T6.h" -#include "Image/IwiLoader.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include -#include -#include -#include - -using namespace T6; - -void* AssetLoaderGfxImage::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} - -bool AssetLoaderGfxImage::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderGfxImage::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto fileName = std::format("images/{}.iwi", assetName); - const auto file = searchPath->Open(fileName); - if (!file.IsOpen()) - return false; - - const auto fileSize = static_cast(file.m_length); - const auto fileData = std::make_unique(fileSize); - file.m_stream->read(fileData.get(), fileSize); - const auto dataHash = static_cast(crc32(0u, reinterpret_cast(fileData.get()), fileSize)); - - std::istringstream ss(std::string(fileData.get(), fileSize)); - const auto texture = iwi::LoadIwi(ss); - if (!texture) - { - std::cerr << std::format("Failed to load texture from: {}\n", fileName); - return false; - } - - auto* image = memory->Create(); - memset(image, 0, sizeof(GfxImage)); - - image->name = memory->Dup(assetName.c_str()); - image->hash = Common::R_HashString(image->name, 0); - image->delayLoadPixels = true; - - image->noPicmip = !texture->HasMipMaps(); - image->width = static_cast(texture->GetWidth()); - image->height = static_cast(texture->GetHeight()); - image->depth = static_cast(texture->GetDepth()); - - image->streaming = 1; - image->streamedParts[0].levelCount = 1; - image->streamedParts[0].levelSize = static_cast(fileSize); - image->streamedParts[0].hash = dataHash & 0x1FFFFFFF; - image->streamedPartCount = 1; - - manager->AddAsset(assetName, image); - - return true; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGfxImage.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGfxImage.h deleted file mode 100644 index c88788bd..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGfxImage.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderGfxImage final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGfxLightDef.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGfxLightDef.cpp deleted file mode 100644 index a46bef80..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGfxLightDef.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderGfxLightDef.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderGfxLightDef::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGfxLightDef.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGfxLightDef.h deleted file mode 100644 index dd8c88c3..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGfxLightDef.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderGfxLightDef final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGfxWorld.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGfxWorld.cpp deleted file mode 100644 index 6243579b..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGfxWorld.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderGfxWorld.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderGfxWorld::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGfxWorld.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGfxWorld.h deleted file mode 100644 index 3653ff15..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGfxWorld.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderGfxWorld final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGlasses.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGlasses.cpp deleted file mode 100644 index dd1e5ef5..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGlasses.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderGlasses.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderGlasses::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGlasses.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGlasses.h deleted file mode 100644 index c8deb7e4..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderGlasses.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderGlasses final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderImpactFx.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderImpactFx.cpp deleted file mode 100644 index e9478c0f..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderImpactFx.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderImpactFx.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderImpactFx::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderImpactFx.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderImpactFx.h deleted file mode 100644 index 779ee741..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderImpactFx.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderImpactFx final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderLeaderboard.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderLeaderboard.cpp deleted file mode 100644 index 8db736f2..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderLeaderboard.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "AssetLoaderLeaderboard.h" - -#include "Game/T6/CommonT6.h" -#include "Game/T6/Leaderboard/JsonLeaderboardDefLoader.h" -#include "Game/T6/T6.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include -#include - -using namespace T6; - -void* AssetLoaderLeaderboard::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} - -bool AssetLoaderLeaderboard::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderLeaderboard::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(std::format("leaderboards/{}.json", assetName)); - if (!file.IsOpen()) - return false; - - auto* leaderboardDef = memory->Alloc(); - leaderboardDef->name = memory->Dup(assetName.c_str()); - - if (LoadLeaderboardAsJson(*file.m_stream, *leaderboardDef, memory)) - manager->AddAsset(assetName, leaderboardDef); - else - std::cerr << std::format("Failed to load leaderboard \"{}\"\n", assetName); - - return true; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderLeaderboard.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderLeaderboard.h deleted file mode 100644 index 13c3e2a2..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderLeaderboard.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderLeaderboard final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderLocalizeEntry.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderLocalizeEntry.cpp deleted file mode 100644 index b90d5eb7..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderLocalizeEntry.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "AssetLoaderLocalizeEntry.h" - -#include "Localize/LocalizeCommonAssetLoader.h" - -using namespace T6; - -XAssetInfoGeneric* AssetLoaderLocalizeEntry::LoadFromGlobalAssetPools(const std::string& assetName) const -{ - return nullptr; -} - -void* AssetLoaderLocalizeEntry::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - return nullptr; -} - -bool AssetLoaderLocalizeEntry::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderLocalizeEntry::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const LocalizeCommonAssetLoader commonLoader( - [memory, manager](const CommonLocalizeEntry& entry) - { - auto* localizeEntry = memory->Create(); - localizeEntry->name = memory->Dup(entry.m_key.c_str()); - localizeEntry->value = memory->Dup(entry.m_value.c_str()); - - manager->AddAsset(entry.m_key, localizeEntry); - }); - - return commonLoader.LoadLocalizeAsset(assetName, searchPath, manager, zone); -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderLocalizeEntry.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderLocalizeEntry.h deleted file mode 100644 index 62b218ac..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderLocalizeEntry.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderLocalizeEntry final : public BasicAssetLoader - { - public: - _NODISCARD XAssetInfoGeneric* LoadFromGlobalAssetPools(const std::string& assetName) const override; - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMapEnts.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMapEnts.cpp deleted file mode 100644 index ed2c3a2f..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMapEnts.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderMapEnts.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderMapEnts::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMapEnts.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMapEnts.h deleted file mode 100644 index 59ce1a65..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMapEnts.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderMapEnts final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMaterial.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMaterial.cpp deleted file mode 100644 index 8bfbe12b..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMaterial.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "AssetLoaderMaterial.h" - -#include "Game/T6/Material/JsonMaterialLoader.h" -#include "Game/T6/T6.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include -#include - -using namespace T6; - -void* AssetLoaderMaterial::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->info.name = memory->Dup(assetName.c_str()); - return asset; -} - -bool AssetLoaderMaterial::CanLoadFromRaw() const -{ - return true; -} - -std::string AssetLoaderMaterial::GetFileNameForAsset(const std::string& assetName) -{ - std::string sanitizedFileName(assetName); - if (sanitizedFileName[0] == '*') - { - std::ranges::replace(sanitizedFileName, '*', '_'); - const auto parenthesisPos = sanitizedFileName.find('('); - if (parenthesisPos != std::string::npos) - sanitizedFileName.erase(parenthesisPos); - sanitizedFileName = "generated/" + sanitizedFileName; - } - - return std::format("materials/{}.json", sanitizedFileName); -} - -bool AssetLoaderMaterial::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(GetFileNameForAsset(assetName)); - if (!file.IsOpen()) - return false; - - auto* material = memory->Alloc(); - material->info.name = memory->Dup(assetName.c_str()); - - std::vector dependencies; - if (LoadMaterialAsJson(*file.m_stream, *material, memory, manager, dependencies)) - manager->AddAsset(assetName, material, std::move(dependencies)); - else - std::cerr << "Failed to load material \"" << assetName << "\"\n"; - - return true; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMaterial.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMaterial.h deleted file mode 100644 index 6ed4075e..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMaterial.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderMaterial final : public BasicAssetLoader - { - static std::string GetFileNameForAsset(const std::string& assetName); - - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMemoryBlock.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMemoryBlock.cpp deleted file mode 100644 index c07acc51..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMemoryBlock.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderMemoryBlock.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderMemoryBlock::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMemoryBlock.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMemoryBlock.h deleted file mode 100644 index 055703ce..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMemoryBlock.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderMemoryBlock final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMenu.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMenu.cpp deleted file mode 100644 index dd90466e..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMenu.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderMenu.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderMenu::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->window.name = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMenu.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMenu.h deleted file mode 100644 index 372b1de7..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMenu.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderMenu final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMenuList.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMenuList.cpp deleted file mode 100644 index 71f1bdd3..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMenuList.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderMenuList.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderMenuList::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMenuList.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMenuList.h deleted file mode 100644 index a786e7a2..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderMenuList.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderMenuList final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderPhysConstraints.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderPhysConstraints.cpp deleted file mode 100644 index 22433770..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderPhysConstraints.cpp +++ /dev/null @@ -1,153 +0,0 @@ -#include "AssetLoaderPhysConstraints.h" - -#include "Game/T6/InfoString/EnumStrings.h" -#include "Game/T6/InfoString/InfoStringToStructConverter.h" -#include "Game/T6/InfoString/PhysConstraintsFields.h" -#include "Game/T6/ObjConstantsT6.h" -#include "Game/T6/T6.h" -#include "InfoString/InfoString.h" - -#include -#include -#include - -using namespace T6; - -namespace T6 -{ - class InfoStringToPhysConstraintsConverter final : public InfoStringToStructConverter - { - protected: - bool ConvertExtensionField(const cspField_t& field, const std::string& value) override - { - switch (static_cast(field.iFieldType)) - { - case CFT_TYPE: - return ConvertEnumInt(field.szName, value, field.iOffset, s_constraintTypeNames, std::extent_v); - - default: - assert(false); - return false; - } - } - - public: - InfoStringToPhysConstraintsConverter(const InfoString& infoString, - PhysConstraints* physConstraints, - ZoneScriptStrings& zoneScriptStrings, - MemoryManager* memory, - IAssetLoadingManager* manager, - const cspField_t* fields, - const size_t fieldCount) - : InfoStringToStructConverter(infoString, physConstraints, zoneScriptStrings, memory, manager, fields, fieldCount) - { - } - }; -} // namespace T6 - -void AssetLoaderPhysConstraints::CalculatePhysConstraintsFields(PhysConstraints* physConstraints, Zone* zone) -{ - for (auto& constraint : physConstraints->data) - { - constraint.targetname = zone->m_script_strings.AddOrGetScriptString(""); - constraint.target_ent1 = zone->m_script_strings.AddOrGetScriptString(""); - constraint.target_ent2 = zone->m_script_strings.AddOrGetScriptString(""); - constraint.attach_point_type1 = ATTACH_POINT_BONE; - constraint.attach_point_type2 = ATTACH_POINT_BONE; - constraint.target_bone1 = ""; - constraint.target_bone2 = ""; - } - - // count - { - auto foundEnd = false; - for (auto i = 0u; i < std::extent_v; i++) - { - if (physConstraints->data[i].type == CONSTRAINT_NONE) - { - foundEnd = true; - physConstraints->count = i; - break; - } - } - - if (!foundEnd) - physConstraints->count = std::extent_v; - } -} - -bool AssetLoaderPhysConstraints::LoadFromInfoString( - const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) -{ - auto* physConstraints = memory->Create(); - memset(physConstraints, 0, sizeof(PhysConstraints)); - - InfoStringToPhysConstraintsConverter converter( - infoString, physConstraints, zone->m_script_strings, memory, manager, phys_constraints_fields, std::extent_v); - if (!converter.Convert()) - { - std::cout << "Failed to parse phys constraints: \"" << assetName << "\"\n"; - return true; - } - - CalculatePhysConstraintsFields(physConstraints, zone); - physConstraints->name = memory->Dup(assetName.c_str()); - - auto scrStrings = converter.GetUsedScriptStrings(); - scrStrings.push_back(zone->m_script_strings.AddOrGetScriptString("")); - manager->AddAsset(assetName, physConstraints, converter.GetDependencies(), scrStrings); - - return true; -} - -void* AssetLoaderPhysConstraints::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} - -bool AssetLoaderPhysConstraints::CanLoadFromGdt() const -{ - return true; -} - -bool AssetLoaderPhysConstraints::LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_PHYS_CONSTRAINTS, assetName); - if (gdtEntry == nullptr) - return false; - - InfoString infoString; - if (!infoString.FromGdtProperties(*gdtEntry)) - { - std::cout << "Failed to read phys constraints gdt entry: \"" << assetName << "\"\n"; - return true; - } - - return LoadFromInfoString(infoString, assetName, memory, manager, zone); -} - -bool AssetLoaderPhysConstraints::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderPhysConstraints::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto fileName = "physconstraints/" + assetName; - const auto file = searchPath->Open(fileName); - if (!file.IsOpen()) - return false; - - InfoString infoString; - if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_PHYS_CONSTRAINTS, *file.m_stream)) - { - std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n"; - return true; - } - - return LoadFromInfoString(infoString, assetName, memory, manager, zone); -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderPhysConstraints.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderPhysConstraints.h deleted file mode 100644 index c8b54e75..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderPhysConstraints.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T6/T6.h" -#include "InfoString/InfoString.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderPhysConstraints final : public BasicAssetLoader - { - static void CalculatePhysConstraintsFields(PhysConstraints* physConstraints, Zone* zone); - - static bool - LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone); - - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromGdt() const override; - bool LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderPhysPreset.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderPhysPreset.cpp deleted file mode 100644 index e5fb21a1..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderPhysPreset.cpp +++ /dev/null @@ -1,136 +0,0 @@ -#include "AssetLoaderPhysPreset.h" - -#include "Game/T6/InfoString/InfoStringToStructConverter.h" -#include "Game/T6/InfoString/PhysPresetFields.h" -#include "Game/T6/ObjConstantsT6.h" -#include "Game/T6/T6.h" -#include "InfoString/InfoString.h" - -#include -#include -#include -#include -#include - -using namespace T6; - -namespace T6 -{ - class InfoStringToPhysPresetConverter final : public InfoStringToStructConverter - { - protected: - bool ConvertExtensionField(const cspField_t& field, const std::string& value) override - { - assert(false); - return false; - } - - public: - InfoStringToPhysPresetConverter(const InfoString& infoString, - PhysPresetInfo* physPreset, - ZoneScriptStrings& zoneScriptStrings, - MemoryManager* memory, - IAssetLoadingManager* manager, - const cspField_t* fields, - const size_t fieldCount) - : InfoStringToStructConverter(infoString, physPreset, zoneScriptStrings, memory, manager, fields, fieldCount) - { - } - }; -} // namespace T6 - -void AssetLoaderPhysPreset::CopyFromPhysPresetInfo(const PhysPresetInfo* physPresetInfo, PhysPreset* physPreset) -{ - physPreset->mass = std::clamp(physPresetInfo->mass, 1.0f, 2000.0f) * 0.001f; - physPreset->bounce = physPresetInfo->bounce; - - if (physPresetInfo->isFrictionInfinity != 0) - physPreset->friction = std::numeric_limits::infinity(); - else - physPreset->friction = physPresetInfo->friction; - - physPreset->bulletForceScale = physPresetInfo->bulletForceScale; - physPreset->explosiveForceScale = physPresetInfo->explosiveForceScale; - physPreset->piecesSpreadFraction = physPresetInfo->piecesSpreadFraction; - physPreset->piecesUpwardVelocity = physPresetInfo->piecesUpwardVelocity; - physPreset->canFloat = physPresetInfo->canFloat; - physPreset->gravityScale = std::clamp(physPresetInfo->gravityScale, 0.01f, 10.0f); - physPreset->centerOfMassOffset = physPresetInfo->centerOfMassOffset; - physPreset->buoyancyBoxMin = physPresetInfo->buoyancyBoxMin; - physPreset->buoyancyBoxMax = physPresetInfo->buoyancyBoxMax; -} - -bool AssetLoaderPhysPreset::LoadFromInfoString( - const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) -{ - const auto presetInfo = std::make_unique(); - memset(presetInfo.get(), 0, sizeof(PhysPresetInfo)); - InfoStringToPhysPresetConverter converter( - infoString, presetInfo.get(), zone->m_script_strings, memory, manager, phys_preset_fields, std::extent_v); - if (!converter.Convert()) - { - std::cout << "Failed to parse phys preset: \"" << assetName << "\"\n"; - return true; - } - - auto* physPreset = memory->Create(); - - CopyFromPhysPresetInfo(presetInfo.get(), physPreset); - physPreset->name = memory->Dup(assetName.c_str()); - - manager->AddAsset(assetName, physPreset, converter.GetDependencies(), converter.GetUsedScriptStrings()); - - return true; -} - -void* AssetLoaderPhysPreset::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} - -bool AssetLoaderPhysPreset::CanLoadFromGdt() const -{ - return true; -} - -bool AssetLoaderPhysPreset::LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_PHYS_PRESET, assetName); - if (gdtEntry == nullptr) - return false; - - InfoString infoString; - if (!infoString.FromGdtProperties(*gdtEntry)) - { - std::cout << "Failed to read phys preset gdt entry: \"" << assetName << "\"\n"; - return true; - } - - return LoadFromInfoString(infoString, assetName, memory, manager, zone); -} - -bool AssetLoaderPhysPreset::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderPhysPreset::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto fileName = "physic/" + assetName; - const auto file = searchPath->Open(fileName); - if (!file.IsOpen()) - return false; - - InfoString infoString; - if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_PHYS_PRESET, *file.m_stream)) - { - std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n"; - return true; - } - - return LoadFromInfoString(infoString, assetName, memory, manager, zone); -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderPhysPreset.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderPhysPreset.h deleted file mode 100644 index a0c6db0b..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderPhysPreset.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T6/T6.h" -#include "InfoString/InfoString.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderPhysPreset final : public BasicAssetLoader - { - static void CopyFromPhysPresetInfo(const PhysPresetInfo* physPresetInfo, PhysPreset* physPreset); - - static bool - LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone); - - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromGdt() const override; - bool LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderQdb.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderQdb.cpp deleted file mode 100644 index 514878ff..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderQdb.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "AssetLoaderQdb.h" - -#include "Game/T6/T6.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace T6; - -void* AssetLoaderQdb::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} - -bool AssetLoaderQdb::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderQdb::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(assetName); - if (!file.IsOpen()) - return false; - - auto* qdb = memory->Create(); - qdb->name = memory->Dup(assetName.c_str()); - qdb->len = static_cast(file.m_length); - - auto* fileBuffer = memory->Alloc(static_cast(file.m_length + 1)); - file.m_stream->read(fileBuffer, file.m_length); - if (file.m_stream->gcount() != file.m_length) - return false; - fileBuffer[qdb->len] = '\0'; - - qdb->buffer = static_cast(fileBuffer); - manager->AddAsset(assetName, qdb); - - return true; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderQdb.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderQdb.h deleted file mode 100644 index ad5f2e13..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderQdb.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderQdb final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderRawFile.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderRawFile.cpp deleted file mode 100644 index f279574a..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderRawFile.cpp +++ /dev/null @@ -1,114 +0,0 @@ -#include "AssetLoaderRawFile.h" - -#include "Game/T6/T6.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include -#include -#include -#include - -using namespace T6; - -namespace fs = std::filesystem; - -void* AssetLoaderRawFile::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} - -bool AssetLoaderRawFile::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderRawFile::LoadAnimtree( - const SearchPathOpenFile& file, const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) -{ - const auto uncompressedBuffer = std::make_unique(static_cast(file.m_length)); - file.m_stream->read(uncompressedBuffer.get(), file.m_length); - if (file.m_stream->gcount() != file.m_length) - return false; - - const auto compressionBufferSize = static_cast(file.m_length + sizeof(uint32_t) + COMPRESSED_BUFFER_SIZE_PADDING); - auto* compressedBuffer = memory->Alloc(compressionBufferSize); - - z_stream_s zs{}; - - zs.zalloc = Z_NULL; - zs.zfree = Z_NULL; - zs.opaque = Z_NULL; - zs.avail_in = static_cast(file.m_length); - zs.avail_out = compressionBufferSize; - zs.next_in = reinterpret_cast(uncompressedBuffer.get()); - zs.next_out = reinterpret_cast(&compressedBuffer[sizeof(uint32_t)]); - - int ret = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -DEF_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); - - if (ret != Z_OK) - { - throw std::runtime_error("Initializing deflate failed"); - } - - ret = deflate(&zs, Z_FINISH); - - if (ret != Z_STREAM_END) - { - std::cerr << "Deflate failed for loading animtree file \"" << assetName << "\"\n"; - deflateEnd(&zs); - return false; - } - - const auto compressedSize = compressionBufferSize + sizeof(uint32_t) - zs.avail_out; - - reinterpret_cast(compressedBuffer)[0] = static_cast(file.m_length); // outLen - - auto* rawFile = memory->Create(); - rawFile->name = memory->Dup(assetName.c_str()); - rawFile->len = static_cast(compressedSize); - rawFile->buffer = static_cast(compressedBuffer); - - deflateEnd(&zs); - - manager->AddAsset(assetName, rawFile); - - return true; -} - -bool AssetLoaderRawFile::LoadDefault( - const SearchPathOpenFile& file, const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) -{ - auto* rawFile = memory->Create(); - rawFile->name = memory->Dup(assetName.c_str()); - rawFile->len = static_cast(file.m_length); - - auto* fileBuffer = memory->Alloc(static_cast(file.m_length + 1)); - file.m_stream->read(fileBuffer, file.m_length); - if (file.m_stream->gcount() != file.m_length) - return false; - fileBuffer[rawFile->len] = '\0'; - - rawFile->buffer = static_cast(fileBuffer); - manager->AddAsset(assetName, rawFile); - - return true; -} - -bool AssetLoaderRawFile::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(assetName); - if (!file.IsOpen()) - return false; - - const fs::path rawFilePath(assetName); - const auto extension = rawFilePath.extension().string(); - - if (extension == ".atr") - return LoadAnimtree(file, assetName, searchPath, memory, manager); - - return LoadDefault(file, assetName, searchPath, memory, manager); -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderRawFile.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderRawFile.h deleted file mode 100644 index 2e4a5412..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderRawFile.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderRawFile final : public BasicAssetLoader - { - static constexpr size_t COMPRESSED_BUFFER_SIZE_PADDING = 64; - - static bool LoadAnimtree( - const SearchPathOpenFile& file, const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager); - static bool LoadDefault( - const SearchPathOpenFile& file, const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager); - - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderScriptParseTree.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderScriptParseTree.cpp deleted file mode 100644 index c2ed0069..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderScriptParseTree.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "AssetLoaderScriptParseTree.h" - -#include "Game/T6/T6.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace T6; - -void* AssetLoaderScriptParseTree::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} - -bool AssetLoaderScriptParseTree::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderScriptParseTree::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(assetName); - if (!file.IsOpen()) - return false; - - auto* scriptParseTree = memory->Create(); - scriptParseTree->name = memory->Dup(assetName.c_str()); - scriptParseTree->len = static_cast(file.m_length); - - auto* fileBuffer = memory->Alloc(static_cast(file.m_length + 1)); - file.m_stream->read(fileBuffer, file.m_length); - if (file.m_stream->gcount() != file.m_length) - return false; - fileBuffer[scriptParseTree->len] = '\0'; - - scriptParseTree->buffer = static_cast(fileBuffer); - manager->AddAsset(assetName, scriptParseTree); - - return true; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderScriptParseTree.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderScriptParseTree.h deleted file mode 100644 index 2d4ea3e2..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderScriptParseTree.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderScriptParseTree final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSkinnedVerts.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSkinnedVerts.cpp deleted file mode 100644 index 89565253..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSkinnedVerts.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderSkinnedVerts.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderSkinnedVerts::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSkinnedVerts.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSkinnedVerts.h deleted file mode 100644 index 2d96097c..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSkinnedVerts.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderSkinnedVerts final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSlug.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSlug.cpp deleted file mode 100644 index 49f6a8d6..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSlug.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "AssetLoaderSlug.h" - -#include "Game/T6/T6.h" -#include "Pool/GlobalAssetPool.h" - -#include - -using namespace T6; - -void* AssetLoaderSlug::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} - -bool AssetLoaderSlug::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderSlug::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(assetName); - if (!file.IsOpen()) - return false; - - auto* slug = memory->Create(); - slug->name = memory->Dup(assetName.c_str()); - slug->len = static_cast(file.m_length); - - auto* fileBuffer = memory->Alloc(static_cast(file.m_length + 1)); - file.m_stream->read(fileBuffer, file.m_length); - if (file.m_stream->gcount() != file.m_length) - return false; - fileBuffer[slug->len] = '\0'; - - slug->buffer = static_cast(fileBuffer); - manager->AddAsset(assetName, slug); - - return true; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSlug.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSlug.h deleted file mode 100644 index 375a48ba..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSlug.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderSlug final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSoundBank.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSoundBank.h deleted file mode 100644 index 2327467e..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSoundBank.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderSoundBank final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSoundDriverGlobals.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSoundDriverGlobals.cpp deleted file mode 100644 index ff897a85..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSoundDriverGlobals.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderSoundDriverGlobals.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderSoundDriverGlobals::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSoundDriverGlobals.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSoundDriverGlobals.h deleted file mode 100644 index de2863c9..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSoundDriverGlobals.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderSoundDriverGlobals final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSoundPatch.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSoundPatch.cpp deleted file mode 100644 index 9594fc40..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSoundPatch.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderSoundPatch.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderSoundPatch::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSoundPatch.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSoundPatch.h deleted file mode 100644 index 02db1c40..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSoundPatch.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderSoundPatch final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderStringTable.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderStringTable.cpp deleted file mode 100644 index e4a0321d..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderStringTable.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "AssetLoaderStringTable.h" - -#include "Csv/CsvStream.h" -#include "Game/T6/CommonT6.h" -#include "Game/T6/T6.h" -#include "Pool/GlobalAssetPool.h" -#include "StringTable/StringTableLoader.h" - -#include - -using namespace T6; - -void* AssetLoaderStringTable::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} - -bool AssetLoaderStringTable::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderStringTable::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(assetName); - if (!file.IsOpen()) - return false; - - string_table::StringTableLoaderV3 loader; - auto* stringTable = loader.LoadFromStream(assetName, *memory, *file.m_stream); - - manager->AddAsset(assetName, stringTable); - - return true; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderStringTable.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderStringTable.h deleted file mode 100644 index 2d9b3bc0..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderStringTable.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderStringTable final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderTechniqueSet.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderTechniqueSet.cpp deleted file mode 100644 index bf4bf380..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderTechniqueSet.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderTechniqueSet.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderTechniqueSet::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderTechniqueSet.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderTechniqueSet.h deleted file mode 100644 index c9b8b6b7..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderTechniqueSet.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderTechniqueSet final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderTracer.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderTracer.cpp deleted file mode 100644 index 7ac19a8c..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderTracer.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include "AssetLoaderTracer.h" - -#include "Game/T6/InfoString/EnumStrings.h" -#include "Game/T6/InfoString/InfoStringToStructConverter.h" -#include "Game/T6/InfoString/TracerFields.h" -#include "Game/T6/ObjConstantsT6.h" -#include "Game/T6/T6.h" -#include "InfoString/InfoString.h" - -#include -#include -#include - -using namespace T6; - -namespace T6 -{ - class InfoStringToTracerConverter final : public InfoStringToStructConverter - { - protected: - bool ConvertExtensionField(const cspField_t& field, const std::string& value) override - { - switch (static_cast(field.iFieldType)) - { - case TFT_TRACERTYPE: - return ConvertEnumInt(field.szName, value, field.iOffset, tracerTypeNames, std::extent_v); - - case TFT_NUM_FIELD_TYPES: - default: - assert(false); - return false; - } - } - - public: - InfoStringToTracerConverter(const InfoString& infoString, - TracerDef* tracer, - ZoneScriptStrings& zoneScriptStrings, - MemoryManager* memory, - IAssetLoadingManager* manager, - const cspField_t* fields, - const size_t fieldCount) - : InfoStringToStructConverter(infoString, tracer, zoneScriptStrings, memory, manager, fields, fieldCount) - { - } - }; -} // namespace T6 - -bool AssetLoaderTracer::LoadFromInfoString( - const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) -{ - auto* tracer = memory->Create(); - memset(tracer, 0, sizeof(TracerDef)); - - InfoStringToTracerConverter converter(infoString, tracer, zone->m_script_strings, memory, manager, tracer_fields, std::extent_v); - if (!converter.Convert()) - { - std::cout << "Failed to parse tracer: \"" << assetName << "\"\n"; - return true; - } - - tracer->name = memory->Dup(assetName.c_str()); - - manager->AddAsset(assetName, tracer, converter.GetDependencies(), converter.GetUsedScriptStrings()); - - return true; -} - -void* AssetLoaderTracer::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} - -bool AssetLoaderTracer::CanLoadFromGdt() const -{ - return true; -} - -bool AssetLoaderTracer::LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_TRACER, assetName); - if (gdtEntry == nullptr) - return false; - - InfoString infoString; - if (!infoString.FromGdtProperties(*gdtEntry)) - { - std::cout << "Failed to read tracer gdt entry: \"" << assetName << "\"\n"; - return true; - } - - return LoadFromInfoString(infoString, assetName, memory, manager, zone); -} - -bool AssetLoaderTracer::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderTracer::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto fileName = "tracer/" + assetName; - const auto file = searchPath->Open(fileName); - if (!file.IsOpen()) - return false; - - InfoString infoString; - if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_TRACER, *file.m_stream)) - { - std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n"; - return true; - } - - return LoadFromInfoString(infoString, assetName, memory, manager, zone); -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderTracer.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderTracer.h deleted file mode 100644 index ea650439..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderTracer.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T6/T6.h" -#include "InfoString/InfoString.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderTracer final : public BasicAssetLoader - { - static bool - LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone); - - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromGdt() const override; - bool LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderVehicle.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderVehicle.h deleted file mode 100644 index aaa6ccda..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderVehicle.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T6/T6.h" -#include "InfoString/InfoString.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderVehicle final : public BasicAssetLoader - { - static bool - LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone); - - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromGdt() const override; - bool LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeapon.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeapon.cpp deleted file mode 100644 index 6fad7e7e..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeapon.cpp +++ /dev/null @@ -1,683 +0,0 @@ -#include "AssetLoaderWeapon.h" - -#include "AssetLoaderWeaponAttachmentUnique.h" -#include "Game/T6/InfoString/EnumStrings.h" -#include "Game/T6/InfoString/InfoStringToStructConverter.h" -#include "Game/T6/InfoString/WeaponFields.h" -#include "Game/T6/ObjConstantsT6.h" -#include "Game/T6/T6.h" -#include "InfoString/InfoString.h" -#include "Utils/ClassUtils.h" -#include "Utils/StringUtils.h" -#include "Weapon/AccuracyGraphLoader.h" - -#include -#include -#include - -using namespace T6; - -namespace T6 -{ - class InfoStringToWeaponConverter final : public InfoStringToStructConverter - { - bool ConvertHideTags(const cspField_t& field, const std::string& value) - { - std::vector valueArray; - if (!ParseAsArray(value, valueArray)) - { - std::cerr << "Failed to parse hide tags as array\n"; - return false; - } - - if (valueArray.size() > std::extent_v) - { - std::cerr << "Cannot have more than " << std::extent_v << " hide tags!\n"; - return false; - } - - auto* hideTags = reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset); - - if (valueArray.size() < std::extent_v) - { - m_used_script_string_list.emplace(m_zone_script_strings.AddOrGetScriptString(nullptr)); - } - - auto currentHideTag = 0u; - for (; currentHideTag < valueArray.size(); currentHideTag++) - { - const auto& currentValue = valueArray[currentHideTag]; - const auto scrString = - !currentValue.empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue) : m_zone_script_strings.AddOrGetScriptString(nullptr); - hideTags[currentHideTag] = scrString; - m_used_script_string_list.emplace(scrString); - } - - for (; currentHideTag < std::extent_v; currentHideTag++) - { - hideTags[currentHideTag] = m_zone_script_strings.GetScriptString(nullptr); - } - - return true; - } - - _NODISCARD bool ConvertBounceSounds(const cspField_t& field, const std::string& value) const - { - auto*** bounceSound = reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset); - if (value.empty()) - { - *bounceSound = nullptr; - return true; - } - - assert(std::extent_v == SURF_TYPE_NUM); - *bounceSound = m_memory->Alloc(SURF_TYPE_NUM); - for (auto i = 0u; i < SURF_TYPE_NUM; i++) - { - const auto currentBounceSound = value + bounceSoundSuffixes[i]; - (*bounceSound)[i] = m_memory->Dup(currentBounceSound.c_str()); - } - return true; - } - - _NODISCARD bool ConvertNotetrackSoundMap(const cspField_t& field, const std::string& value) - { - std::vector> pairs; - if (!ParseAsArray(value, pairs)) - { - std::cerr << "Failed to parse notetracksoundmap as pairs\n"; - return false; - } - - if (pairs.size() > std::extent_v) - { - std::cerr << "Cannot have more than " << std::extent_v << " notetracksoundmap entries!\n"; - return false; - } - - auto* keys = reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset); - auto* values = &keys[std::extent_v]; - auto currentEntryNum = 0u; - - if (pairs.size() < std::extent_v) - { - m_used_script_string_list.emplace(m_zone_script_strings.AddOrGetScriptString(nullptr)); - } - - for (; currentEntryNum < pairs.size(); currentEntryNum++) - { - const auto& currentValue = pairs[currentEntryNum]; - const auto keyScriptString = !currentValue[0].empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue[0]) - : m_zone_script_strings.AddOrGetScriptString(nullptr); - const auto valueScriptString = !currentValue[1].empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue[1]) - : m_zone_script_strings.AddOrGetScriptString(nullptr); - - keys[currentEntryNum] = keyScriptString; - m_used_script_string_list.emplace(keyScriptString); - - values[currentEntryNum] = valueScriptString; - m_used_script_string_list.emplace(valueScriptString); - } - - for (; currentEntryNum < std::extent_v; currentEntryNum++) - { - const auto emptyScr = m_zone_script_strings.GetScriptString(nullptr); - keys[currentEntryNum] = emptyScr; - values[currentEntryNum] = emptyScr; - } - - return true; - } - - _NODISCARD bool ConvertWeaponCamo(const cspField_t& field, const std::string& value) - { - if (value.empty()) - { - *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = nullptr; - return true; - } - - auto* camo = m_loading_manager->LoadDependency(value); - - if (camo == nullptr) - { - std::cerr << "Failed to load camo asset \"" << value << "\"\n"; - return false; - } - - m_dependencies.emplace(camo); - *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = camo->Asset(); - - return true; - } - - _NODISCARD bool ConvertAttachments(const cspField_t& field, const std::string& value) - { - std::vector valueArray; - if (!ParseAsArray(value, valueArray)) - { - std::cerr << "Failed to parse attachments as array\n"; - return false; - } - - auto** attachments = reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset); - - for (const auto& attachmentName : valueArray) - { - auto* attachmentAssetInfo = m_loading_manager->LoadDependency(attachmentName); - if (attachmentAssetInfo == nullptr) - { - std::cerr << "Failed to load attachment asset \"" << attachmentName << "\"\n"; - return false; - } - - auto* attachmentAsset = attachmentAssetInfo->Asset(); - - if (static_cast(attachmentAsset->attachmentType) >= ATTACHMENT_TYPE_COUNT) - { - std::cerr << "Invalid attachment type " << attachmentAsset->attachmentType << " for attachment asset \"" << attachmentName << "\"\n"; - return false; - } - - if (attachments[attachmentAsset->attachmentType] != nullptr) - { - std::cerr << "Already loaded attachment with same type " << attachmentAsset->attachmentType << ": \"" - << attachments[attachmentAsset->attachmentType]->szInternalName << "\", \"" << attachmentName << "\"\n"; - return false; - } - - attachments[attachmentAsset->attachmentType] = attachmentAsset; - m_dependencies.emplace(attachmentAssetInfo); - } - - return true; - } - - _NODISCARD static bool HasMoreThanOneAttachmentSetInMask(const int mask) - { - // Check if int has more than 1 bit set - return (mask & (mask - 1)) != 0; - } - - _NODISCARD bool ConvertAttachmentUniques(const cspField_t& field, const std::string& value) - { - std::vector valueArray; - if (!ParseAsArray(value, valueArray)) - { - std::cerr << "Failed to parse attachment uniques as array\n"; - return false; - } - - auto** attachmentUniques = reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset); - auto attachmentCombinationIndex = std::extent_v; - - for (const auto& attachmentUniqueName : valueArray) - { - auto* attachmentUniqueAssetInfo = m_loading_manager->LoadDependency(attachmentUniqueName); - if (attachmentUniqueAssetInfo == nullptr) - { - std::cerr << "Failed to load attachment unique asset \"" << attachmentUniqueName << "\"\n"; - return false; - } - - auto* attachmentUniqueAsset = attachmentUniqueAssetInfo->Asset(); - - if (HasMoreThanOneAttachmentSetInMask(attachmentUniqueAsset->combinedAttachmentTypeMask)) - { - if (attachmentCombinationIndex >= std::extent_v) - { - std::cerr << "Cannot have more than " - << (std::extent_v - std::extent_v) - << " combined attachment attachment unique entries!\n"; - return false; - } - - attachmentUniques[attachmentCombinationIndex++] = attachmentUniqueAsset; - m_dependencies.emplace(attachmentUniqueAssetInfo); - } - else - { - if (static_cast(attachmentUniqueAsset->attachmentType) >= ATTACHMENT_TYPE_COUNT) - { - std::cerr << "Invalid attachment type " << attachmentUniqueAsset->attachmentType << " for attachment unique asset \"" - << attachmentUniqueName << "\"\n"; - return false; - } - - if (attachmentUniques[attachmentUniqueAsset->attachmentType] != nullptr) - { - std::cerr << "Already loaded attachment unique with same type " << attachmentUniqueAsset->attachmentType << ": \"" - << attachmentUniques[attachmentUniqueAsset->attachmentType]->szInternalName << "\", \"" << attachmentUniqueName << "\"\n"; - return false; - } - - attachmentUniques[attachmentUniqueAsset->attachmentType] = attachmentUniqueAsset; - m_dependencies.emplace(attachmentUniqueAssetInfo); - } - } - - return true; - } - - bool ConvertAnimName(const cspField_t& field, const std::string& value) - { - if (ConvertString(value, field.iOffset)) - { - if (!value.empty()) - m_indirect_asset_references.emplace(m_loading_manager->LoadIndirectAssetReference(value)); - - return true; - } - - return false; - } - - protected: - bool ConvertExtensionField(const cspField_t& field, const std::string& value) override - { - switch (static_cast(field.iFieldType)) - { - case WFT_WEAPONTYPE: - return ConvertEnumInt(field.szName, value, field.iOffset, szWeapTypeNames, std::extent_v); - - case WFT_WEAPONCLASS: - return ConvertEnumInt(field.szName, value, field.iOffset, szWeapClassNames, std::extent_v); - - case WFT_OVERLAYRETICLE: - return ConvertEnumInt(field.szName, value, field.iOffset, szWeapOverlayReticleNames, std::extent_v); - - case WFT_PENETRATE_TYPE: - return ConvertEnumInt(field.szName, value, field.iOffset, penetrateTypeNames, std::extent_v); - - case WFT_IMPACT_TYPE: - return ConvertEnumInt(field.szName, value, field.iOffset, impactTypeNames, std::extent_v); - - case WFT_STANCE: - return ConvertEnumInt(field.szName, value, field.iOffset, szWeapStanceNames, std::extent_v); - - case WFT_PROJ_EXPLOSION: - return ConvertEnumInt(field.szName, value, field.iOffset, szProjectileExplosionNames, std::extent_v); - - case WFT_OFFHAND_CLASS: - return ConvertEnumInt(field.szName, value, field.iOffset, offhandClassNames, std::extent_v); - - case WFT_OFFHAND_SLOT: - return ConvertEnumInt(field.szName, value, field.iOffset, offhandSlotNames, std::extent_v); - - case WFT_ANIMTYPE: - return ConvertEnumInt(field.szName, value, field.iOffset, playerAnimTypeNames, std::extent_v); - - case WFT_ACTIVE_RETICLE_TYPE: - return ConvertEnumInt(field.szName, value, field.iOffset, activeReticleNames, std::extent_v); - - case WFT_GUIDED_MISSILE_TYPE: - return ConvertEnumInt(field.szName, value, field.iOffset, guidedMissileNames, std::extent_v); - - case WFT_BOUNCE_SOUND: - return ConvertBounceSounds(field, value); - - case WFT_STICKINESS: - return ConvertEnumInt(field.szName, value, field.iOffset, stickinessNames, std::extent_v); - - case WFT_ROTATETYPE: - return ConvertEnumInt(field.szName, value, field.iOffset, rotateTypeNames, std::extent_v); - - case WFT_OVERLAYINTERFACE: - return ConvertEnumInt(field.szName, value, field.iOffset, overlayInterfaceNames, std::extent_v); - - case WFT_INVENTORYTYPE: - return ConvertEnumInt(field.szName, value, field.iOffset, szWeapInventoryTypeNames, std::extent_v); - - case WFT_FIRETYPE: - return ConvertEnumInt(field.szName, value, field.iOffset, szWeapFireTypeNames, std::extent_v); - - case WFT_CLIPTYPE: - return ConvertEnumInt(field.szName, value, field.iOffset, szWeapClipTypeNames, std::extent_v); - - case WFT_AMMOCOUNTER_CLIPTYPE: - return ConvertEnumInt(field.szName, value, field.iOffset, ammoCounterClipNames, std::extent_v); - - case WFT_ICONRATIO_HUD: - case WFT_ICONRATIO_AMMOCOUNTER: - case WFT_ICONRATIO_KILL: - case WFT_ICONRATIO_DPAD: - case WFT_ICONRATIO_INDICATOR: - return ConvertEnumInt(field.szName, value, field.iOffset, weapIconRatioNames, std::extent_v); - - case WFT_BARRELTYPE: - return ConvertEnumInt(field.szName, value, field.iOffset, barrelTypeNames, std::extent_v); - - case WFT_HIDETAGS: - return ConvertHideTags(field, value); - - case WFT_EXPLOSION_TAG: - return ConvertScriptString(value, field.iOffset); - - case WFT_NOTETRACKSOUNDMAP: - return ConvertNotetrackSoundMap(field, value); - - case WFT_WEAPON_CAMO: - return ConvertWeaponCamo(field, value); - - case WFT_ATTACHMENTS: - return ConvertAttachments(field, value); - - case WFT_ATTACHMENT_UNIQUES: - return ConvertAttachmentUniques(field, value); - - case WFT_ANIM_NAME: - return ConvertAnimName(field, value); - - default: - assert(false); - return false; - } - } - - public: - InfoStringToWeaponConverter(const InfoString& infoString, - WeaponFullDef* weaponFullDef, - ZoneScriptStrings& zoneScriptStrings, - MemoryManager* memory, - IAssetLoadingManager* manager, - const cspField_t* fields, - const size_t fieldCount) - : InfoStringToStructConverter(infoString, weaponFullDef, zoneScriptStrings, memory, manager, fields, fieldCount) - { - } - }; - - void ConvertAccuracyGraph( - const GenericGraph2D& graph, vec2_t*& originalGraphKnots, int& originalGraphKnotCount, vec2_t*& graphKnots, int& graphKnotCount, MemoryManager* memory) - { - originalGraphKnotCount = static_cast(graph.knots.size()); - originalGraphKnots = memory->Alloc(originalGraphKnotCount); - - for (auto i = 0; i < originalGraphKnotCount; i++) - { - const auto& commonKnot = graph.knots[i]; - originalGraphKnots[i].x = static_cast(commonKnot.x); - originalGraphKnots[i].y = static_cast(commonKnot.y); - } - - graphKnots = originalGraphKnots; - graphKnotCount = originalGraphKnotCount; - } - - bool LoadAccuracyGraphs(WeaponFullDef* weaponFullDef, MemoryManager* memory, const IAssetLoadingManager* manager) - { - auto* accuracyGraphLoader = manager->GetAssetLoadingContext()->GetZoneAssetLoaderState(); - - if (weaponFullDef->weapDef.aiVsAiAccuracyGraphName && weaponFullDef->weapDef.aiVsAiAccuracyGraphName[0]) - { - const auto* graph = accuracyGraphLoader->LoadAiVsAiGraph(manager, weaponFullDef->weapDef.aiVsAiAccuracyGraphName); - if (!graph) - return false; - - ConvertAccuracyGraph(*graph, - weaponFullDef->weapDef.originalAiVsAiAccuracyGraphKnots, - weaponFullDef->weapDef.originalAiVsAiAccuracyGraphKnotCount, - weaponFullDef->weapDef.aiVsAiAccuracyGraphKnots, - weaponFullDef->weapDef.aiVsAiAccuracyGraphKnotCount, - memory); - } - - if (weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName && weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName[0]) - { - const auto* graph = accuracyGraphLoader->LoadAiVsPlayerGraph(manager, weaponFullDef->weapDef.aiVsPlayerAccuracyGraphName); - if (!graph) - return false; - - ConvertAccuracyGraph(*graph, - weaponFullDef->weapDef.originalAiVsPlayerAccuracyGraphKnots, - weaponFullDef->weapDef.originalAiVsPlayerAccuracyGraphKnotCount, - weaponFullDef->weapDef.aiVsPlayerAccuracyGraphKnots, - weaponFullDef->weapDef.aiVsPlayerAccuracyGraphKnotCount, - memory); - } - - return true; - } -} // namespace T6 - -void AssetLoaderWeapon::LinkWeaponFullDefSubStructs(WeaponFullDef* weapon) -{ - weapon->weapVariantDef.weapDef = &weapon->weapDef; - weapon->weapVariantDef.attachments = weapon->attachments; - weapon->weapVariantDef.attachmentUniques = weapon->attachmentUniques; - weapon->weapDef.gunXModel = weapon->gunXModel; - weapon->weapVariantDef.szXAnims = weapon->szXAnims; - weapon->weapVariantDef.hideTags = weapon->hideTags; - weapon->weapDef.notetrackSoundMapKeys = weapon->notetrackSoundMapKeys; - weapon->weapDef.notetrackSoundMapValues = weapon->notetrackSoundMapValues; - weapon->weapDef.worldModel = weapon->worldModel; - weapon->weapVariantDef.attachViewModel = weapon->attachViewModel; - weapon->weapVariantDef.attachWorldModel = weapon->attachWorldModel; - weapon->weapVariantDef.attachViewModelTag = weapon->attachViewModelTag; - weapon->weapVariantDef.attachWorldModelTag = weapon->attachWorldModelTag; - weapon->weapDef.parallelBounce = weapon->parallelBounce; - weapon->weapDef.perpendicularBounce = weapon->perpendicularBounce; - weapon->weapDef.locationDamageMultipliers = weapon->locationDamageMultipliers; -} - -void AssetLoaderWeapon::CalculateWeaponFields(WeaponFullDef* weapon) -{ - // iAttachments - weapon->weapVariantDef.iAttachments = 0; - for (auto i = 1u; i < sizeof(WeaponVariantDef::iAttachments) * 8; i++) // Bit for default attachment always 0 - { - if (weapon->attachments[i]) - weapon->weapVariantDef.iAttachments |= 1 << i; - } - - if (weapon->weapVariantDef.iAdsTransInTime <= 0) - weapon->weapVariantDef.fOOPosAnimLength[0] = 0.0033333334f; - else - weapon->weapVariantDef.fOOPosAnimLength[0] = 1.0f / static_cast(weapon->weapVariantDef.iAdsTransInTime); - - if (weapon->weapVariantDef.iAdsTransOutTime <= 0) - weapon->weapVariantDef.fOOPosAnimLength[1] = 0.0020000001f; - else - weapon->weapVariantDef.fOOPosAnimLength[1] = 1.0f / static_cast(weapon->weapVariantDef.iAdsTransOutTime); -} - -bool AssetLoaderWeapon::IsStringOverride(const char* baseString, const char* overrideString) -{ - if (overrideString == nullptr || overrideString[0] == '\0') - return false; - - if (baseString == nullptr || baseString[0] == '\0') - return true; - - return strcmp(baseString, overrideString) != 0; -} - -bool AssetLoaderWeapon::IsFxOverride(const FxEffectDef* baseEffect, const FxEffectDef* overrideEffect) -{ - if (overrideEffect == nullptr) - return false; - - if (baseEffect == nullptr) - return true; - - return strcmp(baseEffect->name, overrideEffect->name) != 0; -} - -void AssetLoaderWeapon::HandleSoundOverride(WeaponAttachmentUnique* attachmentUnique, - const char* snd1, - const char* snd2, - const eAttachmentOverrideSounds sndOverrideIndex) -{ - if (IsStringOverride(snd1, snd2)) - attachmentUnique->soundOverrides |= 1 << static_cast(sndOverrideIndex); -} - -void AssetLoaderWeapon::HandleFxOverride(WeaponAttachmentUnique* attachmentUnique, - const FxEffectDef* effect1, - const FxEffectDef* effect2, - const eAttachmentOverrideEffects fxOverrideIndex) -{ - if (IsFxOverride(effect1, effect2)) - attachmentUnique->effectOverrides |= 1 << static_cast(fxOverrideIndex); -} - -void AssetLoaderWeapon::CalculateAttachmentFields(const WeaponFullDef* weapon, unsigned attachmentIndex, WeaponAttachmentUnique* attachmentUnique) -{ - for (auto& val : attachmentUnique->animationOverrides) - val = 0; - - for (auto animIndex = 0u; animIndex < std::extent_v; animIndex++) - { - if (IsStringOverride(weapon->szXAnims[animIndex], attachmentUnique->szXAnims[animIndex])) - attachmentUnique->animationOverrides[animIndex / 32] |= 1 << (animIndex % 32); - } - - attachmentUnique->soundOverrides = 0; - HandleSoundOverride(attachmentUnique, weapon->weapDef.fireSound, attachmentUnique->fireSound, ATTACHMENT_OVERRIDE_SOUND_FIRE); - HandleSoundOverride(attachmentUnique, weapon->weapDef.fireSoundPlayer, attachmentUnique->fireSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_PLAYER); - HandleSoundOverride(attachmentUnique, weapon->weapDef.fireLoopSound, attachmentUnique->fireLoopSound, ATTACHMENT_OVERRIDE_SOUND_FIRE_LOOP); - HandleSoundOverride( - attachmentUnique, weapon->weapDef.fireLoopSoundPlayer, attachmentUnique->fireLoopSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_LOOP_PLAYER); - HandleSoundOverride(attachmentUnique, weapon->weapDef.fireLoopEndSound, attachmentUnique->fireLoopEndSound, ATTACHMENT_OVERRIDE_SOUND_FIRE_LOOP_END); - HandleSoundOverride( - attachmentUnique, weapon->weapDef.fireLoopEndSoundPlayer, attachmentUnique->fireLoopEndSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_LOOP_END_PLAYER); - HandleSoundOverride(attachmentUnique, weapon->weapDef.fireStartSound, attachmentUnique->fireStartSound, ATTACHMENT_OVERRIDE_SOUND_FIRE_START); - HandleSoundOverride(attachmentUnique, weapon->weapDef.fireStopSound, attachmentUnique->fireStopSound, ATTACHMENT_OVERRIDE_SOUND_FIRE_STOP); - HandleSoundOverride( - attachmentUnique, weapon->weapDef.fireStartSoundPlayer, attachmentUnique->fireStartSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_START_PLAYER); - HandleSoundOverride( - attachmentUnique, weapon->weapDef.fireStopSoundPlayer, attachmentUnique->fireStopSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_STOP_PLAYER); - HandleSoundOverride(attachmentUnique, weapon->weapDef.fireLastSound, attachmentUnique->fireLastSound, ATTACHMENT_OVERRIDE_SOUND_FIRE_LAST); - HandleSoundOverride( - attachmentUnique, weapon->weapDef.fireLastSoundPlayer, attachmentUnique->fireLastSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_LAST_PLAYER); - - attachmentUnique->effectOverrides = 0; - HandleFxOverride(attachmentUnique, weapon->weapDef.viewFlashEffect, attachmentUnique->viewFlashEffect, ATTACHMENT_OVERRIDE_EFFECT_VIEW_FLASH); - HandleFxOverride(attachmentUnique, weapon->weapDef.worldFlashEffect, attachmentUnique->worldFlashEffect, ATTACHMENT_OVERRIDE_EFFECT_WORLD_FLASH); - - attachmentUnique->childLink = 0; - if (attachmentUnique->combinedAttachmentTypeMask == 0) - { - WeaponAttachmentUnique* lastSibling = nullptr; - for (auto attachmentUniqueIndex = std::extent_v; - attachmentUniqueIndex < std::extent_v; - attachmentUniqueIndex++) - { - if (weapon->attachmentUniques[attachmentUniqueIndex] != nullptr - && weapon->attachmentUniques[attachmentUniqueIndex]->combinedAttachmentTypeMask & (1 << static_cast(attachmentUnique->attachmentType)) - && weapon->attachmentUniques[attachmentUniqueIndex]->attachmentType != attachmentUnique->attachmentType) - { - std::vector attachments; - if (AssetLoaderWeaponAttachmentUnique::ExtractAttachmentsFromAssetName(weapon->attachmentUniques[attachmentUniqueIndex]->szInternalName, - attachments) - && attachments.front() == attachmentUnique->attachmentType) - { - if (lastSibling == nullptr) - { - attachmentUnique->childLink = attachmentUniqueIndex; - lastSibling = weapon->attachmentUniques[attachmentUniqueIndex]; - } - else - { - lastSibling->siblingLink = attachmentUniqueIndex; - lastSibling = weapon->attachmentUniques[attachmentUniqueIndex]; - } - } - } - } - } -} - -void AssetLoaderWeapon::CalculateAttachmentFields(const WeaponFullDef* weapon) -{ - for (auto attachmentUniqueIndex = 0u; attachmentUniqueIndex < std::extent_v; attachmentUniqueIndex++) - { - if (weapon->attachmentUniques[attachmentUniqueIndex] == nullptr) - continue; - - CalculateAttachmentFields(weapon, attachmentUniqueIndex, weapon->attachmentUniques[attachmentUniqueIndex]); - } -} - -bool AssetLoaderWeapon::LoadFromInfoString( - const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) -{ - auto* weaponFullDef = memory->Create(); - memset(weaponFullDef, 0, sizeof(WeaponFullDef)); - LinkWeaponFullDefSubStructs(weaponFullDef); - - InfoStringToWeaponConverter converter( - infoString, weaponFullDef, zone->m_script_strings, memory, manager, weapon_fields, std::extent_v); - if (!converter.Convert()) - { - std::cerr << "Failed to parse weapon: \"" << assetName << "\"\n"; - return true; - } - - weaponFullDef->weapVariantDef.szInternalName = memory->Dup(assetName.c_str()); - - // TODO: Load flametable - CalculateWeaponFields(weaponFullDef); - CalculateAttachmentFields(weaponFullDef); - - LoadAccuracyGraphs(weaponFullDef, memory, manager); - - manager->AddAsset( - assetName, &weaponFullDef->weapVariantDef, converter.GetDependencies(), converter.GetUsedScriptStrings(), converter.GetIndirectAssetReferences()); - - return true; -} - -void* AssetLoaderWeapon::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* weaponFullDef = memory->Alloc(); - LinkWeaponFullDefSubStructs(weaponFullDef); - CalculateWeaponFields(weaponFullDef); - weaponFullDef->weapVariantDef.szInternalName = memory->Dup(assetName.c_str()); - return weaponFullDef; -} - -bool AssetLoaderWeapon::CanLoadFromGdt() const -{ - return true; -} - -bool AssetLoaderWeapon::LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_WEAPON, assetName); - if (gdtEntry == nullptr) - return false; - - InfoString infoString; - if (!infoString.FromGdtProperties(*gdtEntry)) - { - std::cerr << "Failed to read weapon gdt entry: \"" << assetName << "\"\n"; - return true; - } - - return LoadFromInfoString(infoString, assetName, memory, manager, zone); -} - -bool AssetLoaderWeapon::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderWeapon::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto fileName = "weapons/" + assetName; - const auto file = searchPath->Open(fileName); - if (!file.IsOpen()) - return false; - - InfoString infoString; - if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_WEAPON, *file.m_stream)) - { - std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n"; - return true; - } - - return LoadFromInfoString(infoString, assetName, memory, manager, zone); -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeapon.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeapon.h deleted file mode 100644 index 9a9cb4fc..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeapon.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T6/T6.h" -#include "InfoString/InfoString.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderWeapon final : public BasicAssetLoader - { - static void LinkWeaponFullDefSubStructs(WeaponFullDef* weapon); - - static bool IsStringOverride(const char* baseString, const char* overrideString); - static bool IsFxOverride(const FxEffectDef* baseEffect, const FxEffectDef* overrideEffect); - static void - HandleSoundOverride(WeaponAttachmentUnique* attachmentUnique, const char* snd1, const char* snd2, eAttachmentOverrideSounds sndOverrideIndex); - static void HandleFxOverride(WeaponAttachmentUnique* attachmentUnique, - const FxEffectDef* effect1, - const FxEffectDef* effect2, - eAttachmentOverrideEffects fxOverrideIndex); - - static void CalculateWeaponFields(WeaponFullDef* weapon); - static void CalculateAttachmentFields(const WeaponFullDef* weapon, unsigned attachmentIndex, WeaponAttachmentUnique* attachmentUnique); - static void CalculateAttachmentFields(const WeaponFullDef* weapon); - - static bool - LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone); - - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromGdt() const override; - bool LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeaponAttachment.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeaponAttachment.cpp deleted file mode 100644 index 46ce62f9..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeaponAttachment.cpp +++ /dev/null @@ -1,172 +0,0 @@ -#include "AssetLoaderWeaponAttachment.h" - -#include "Game/T6/InfoString/EnumStrings.h" -#include "Game/T6/InfoString/InfoStringToStructConverter.h" -#include "Game/T6/InfoString/WeaponAttachmentFields.h" -#include "Game/T6/ObjConstantsT6.h" -#include "Game/T6/T6.h" -#include "InfoString/InfoString.h" - -#include -#include -#include - -using namespace T6; - -namespace T6 -{ - eAttachmentPoint attachmentPointByAttachmentTable[]{ - ATTACHMENT_POINT_NONE, // none - ATTACHMENT_POINT_TOP, // acog - ATTACHMENT_POINT_TRIGGER, // dualclip - ATTACHMENT_POINT_TOP, // dualoptic - ATTACHMENT_POINT_BOTTOM, // dw - ATTACHMENT_POINT_MUZZLE, // extbarrel - ATTACHMENT_POINT_TRIGGER, // extclip - ATTACHMENT_POINT_TRIGGER, // extramags - ATTACHMENT_POINT_GUNPERK, // fastads - ATTACHMENT_POINT_TOP, // fastreload - ATTACHMENT_POINT_TRIGGER, // fmj - ATTACHMENT_POINT_BOTTOM, // gl - ATTACHMENT_POINT_BOTTOM, // grip - ATTACHMENT_POINT_TOP, // holo - ATTACHMENT_POINT_BOTTOM, // ir - ATTACHMENT_POINT_BOTTOM, // is - ATTACHMENT_POINT_GUNPERK, // longbreath - ATTACHMENT_POINT_BOTTOM, // mk - ATTACHMENT_POINT_TOP, // mms - ATTACHMENT_POINT_TOP, // rangefinder - ATTACHMENT_POINT_TOP, // reflex - ATTACHMENT_POINT_MUZZLE, // rf - ATTACHMENT_POINT_BOTTOM, // sf - ATTACHMENT_POINT_MUZZLE, // silencer - ATTACHMENT_POINT_TRIGGER, // stackfire - ATTACHMENT_POINT_GUNPERK, // stalker - ATTACHMENT_POINT_GUNPERK, // steadyaim - ATTACHMENT_POINT_GUNPERK, // swayreduc - ATTACHMENT_POINT_TOP, // tacknife - ATTACHMENT_POINT_TOP, // vzoom - }; - - static_assert(std::extent_v == ATTACHMENT_TYPE_COUNT); - - class InfoStringToWeaponAttachmentConverter final : public InfoStringToStructConverter - { - protected: - bool ConvertExtensionField(const cspField_t& field, const std::string& value) override - { - switch (static_cast(field.iFieldType)) - { - case AFT_ATTACHMENTTYPE: - return ConvertEnumInt(field.szName, value, field.iOffset, szAttachmentTypeNames, std::extent_v); - - case AFT_PENETRATE_TYPE: - return ConvertEnumInt(field.szName, value, field.iOffset, penetrateTypeNames, std::extent_v); - - case AFT_FIRETYPE: - return ConvertEnumInt(field.szName, value, field.iOffset, szWeapFireTypeNames, std::extent_v); - - default: - assert(false); - return false; - } - } - - public: - InfoStringToWeaponAttachmentConverter(const InfoString& infoString, - WeaponAttachment* weaponAttachment, - ZoneScriptStrings& zoneScriptStrings, - MemoryManager* memory, - IAssetLoadingManager* manager, - const cspField_t* fields, - const size_t fieldCount) - : InfoStringToStructConverter(infoString, weaponAttachment, zoneScriptStrings, memory, manager, fields, fieldCount) - { - } - }; -} // namespace T6 - -void AssetLoaderWeaponAttachment::CalculateAttachmentFields(WeaponAttachment* attachment) -{ - // attachmentPoint - if (static_cast(attachment->attachmentType) < ATTACHMENT_TYPE_COUNT) - { - attachment->attachmentPoint = attachmentPointByAttachmentTable[attachment->attachmentType]; - } -} - -bool AssetLoaderWeaponAttachment::LoadFromInfoString( - const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) -{ - auto* attachment = memory->Create(); - memset(attachment, 0, sizeof(WeaponAttachment)); - - InfoStringToWeaponAttachmentConverter converter( - infoString, attachment, zone->m_script_strings, memory, manager, attachment_fields, std::extent_v); - if (!converter.Convert()) - { - std::cerr << "Failed to parse attachment: \"" << assetName << "\"\n"; - return true; - } - - CalculateAttachmentFields(attachment); - attachment->szInternalName = memory->Dup(assetName.c_str()); - - manager->AddAsset( - assetName, attachment, converter.GetDependencies(), converter.GetUsedScriptStrings(), converter.GetIndirectAssetReferences()); - - return true; -} - -void* AssetLoaderWeaponAttachment::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* attachment = memory->Alloc(); - CalculateAttachmentFields(attachment); - attachment->szInternalName = memory->Dup(assetName.c_str()); - return attachment; -} - -bool AssetLoaderWeaponAttachment::CanLoadFromGdt() const -{ - return true; -} - -bool AssetLoaderWeaponAttachment::LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_WEAPON_ATTACHMENT, assetName); - if (gdtEntry == nullptr) - return false; - - InfoString infoString; - if (!infoString.FromGdtProperties(*gdtEntry)) - { - std::cerr << "Failed to read attachment gdt entry: \"" << assetName << "\"\n"; - return true; - } - - return LoadFromInfoString(infoString, assetName, memory, manager, zone); -} - -bool AssetLoaderWeaponAttachment::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderWeaponAttachment::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto fileName = "attachment/" + assetName; - const auto file = searchPath->Open(fileName); - if (!file.IsOpen()) - return false; - - InfoString infoString; - if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_WEAPON_ATTACHMENT, *file.m_stream)) - { - std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n"; - return true; - } - - return LoadFromInfoString(infoString, assetName, memory, manager, zone); -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeaponAttachment.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeaponAttachment.h deleted file mode 100644 index 9c03b87b..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeaponAttachment.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T6/T6.h" -#include "InfoString/InfoString.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderWeaponAttachment final : public BasicAssetLoader - { - static void CalculateAttachmentFields(WeaponAttachment* attachment); - - static bool - LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone); - - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromGdt() const override; - bool LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeaponAttachmentUnique.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeaponAttachmentUnique.cpp deleted file mode 100644 index 885576d1..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeaponAttachmentUnique.cpp +++ /dev/null @@ -1,292 +0,0 @@ -#include "AssetLoaderWeaponAttachmentUnique.h" - -#include "Game/T6/InfoString/EnumStrings.h" -#include "Game/T6/InfoString/InfoStringToStructConverter.h" -#include "Game/T6/InfoString/WeaponAttachmentUniqueFields.h" -#include "Game/T6/ObjConstantsT6.h" -#include "Game/T6/T6.h" -#include "InfoString/InfoString.h" -#include "Utils/ClassUtils.h" - -#include -#include -#include - -using namespace T6; - -namespace T6 -{ - class InfoStringToWeaponAttachmentUniqueConverter final : public InfoStringToStructConverter - { - bool ConvertHideTags(const cspField_t& field, const std::string& value) - { - std::vector valueArray; - if (!ParseAsArray(value, valueArray)) - { - std::cerr << "Failed to parse hide tags as array\n"; - return false; - } - - if (valueArray.size() > std::extent_v) - { - std::cerr << "Cannot have more than " << std::extent_v << " hide tags!\n"; - return false; - } - - auto* hideTags = reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset); - - if (valueArray.size() < std::extent_v) - { - m_used_script_string_list.emplace(m_zone_script_strings.AddOrGetScriptString(nullptr)); - } - - auto currentHideTag = 0u; - for (; currentHideTag < valueArray.size(); currentHideTag++) - { - const auto& currentValue = valueArray[currentHideTag]; - const auto scrString = - !currentValue.empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue) : m_zone_script_strings.AddOrGetScriptString(nullptr); - hideTags[currentHideTag] = scrString; - m_used_script_string_list.emplace(scrString); - } - - for (; currentHideTag < std::extent_v; currentHideTag++) - { - hideTags[currentHideTag] = m_zone_script_strings.GetScriptString(nullptr); - } - - return true; - } - - _NODISCARD bool ConvertWeaponCamo(const cspField_t& field, const std::string& value) - { - if (value.empty()) - { - *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = nullptr; - return true; - } - - auto* camo = m_loading_manager->LoadDependency(value); - - if (camo == nullptr) - { - std::cerr << "Failed to load camo asset \"" << value << "\"\n"; - return false; - } - - m_dependencies.emplace(camo); - *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = camo->Asset(); - - return true; - } - - bool ConvertAnimName(const cspField_t& field, const std::string& value) - { - if (ConvertString(value, field.iOffset)) - { - if (!value.empty()) - m_indirect_asset_references.emplace(m_loading_manager->LoadIndirectAssetReference(value)); - - return true; - } - - return false; - } - - protected: - bool ConvertExtensionField(const cspField_t& field, const std::string& value) override - { - switch (static_cast(field.iFieldType)) - { - case AUFT_ATTACHMENTTYPE: - return ConvertEnumInt(field.szName, value, field.iOffset, szAttachmentTypeNames, std::extent_v); - - case AUFT_HIDETAGS: - return ConvertHideTags(field, value); - - case AUFT_OVERLAYRETICLE: - return ConvertEnumInt(field.szName, value, field.iOffset, szWeapOverlayReticleNames, std::extent_v); - - case AUFT_CAMO: - return ConvertWeaponCamo(field, value); - - case AUFT_ANIM_NAME: - return ConvertAnimName(field, value); - - default: - assert(false); - return false; - } - } - - public: - InfoStringToWeaponAttachmentUniqueConverter(const InfoString& infoString, - WeaponAttachmentUniqueFull* attachmentUniqueFull, - ZoneScriptStrings& zoneScriptStrings, - MemoryManager* memory, - IAssetLoadingManager* manager, - const cspField_t* fields, - const size_t fieldCount) - : InfoStringToStructConverter(infoString, attachmentUniqueFull, zoneScriptStrings, memory, manager, fields, fieldCount) - { - } - }; -} // namespace T6 - -bool AssetLoaderWeaponAttachmentUnique::ExtractAttachmentsFromAssetName(const std::string& assetName, std::vector& attachmentList) -{ - std::vector parts; - - auto attachCount = 1u; - auto partStart = 0u; - for (auto ci = 0u; ci < assetName.size(); ci++) - { - if (assetName[ci] == '_') - { - parts.emplace_back(assetName, partStart, ci - partStart); - partStart = ci + 1; - } - else if (assetName[ci] == '+') - { - attachCount++; - parts.emplace_back(assetName, partStart, ci - partStart); - partStart = ci + 1; - } - } - - if (partStart < assetName.size()) - parts.emplace_back(assetName, partStart, assetName.size() - partStart); - - for (auto attachPartOffset = parts.size() - attachCount; attachPartOffset < parts.size(); attachPartOffset++) - { - auto& specifiedAttachName = parts[attachPartOffset]; - - for (auto& c : specifiedAttachName) - c = static_cast(tolower(c)); - - auto foundAttachment = false; - for (auto attachIndex = 0u; attachIndex < std::extent_v; attachIndex++) - { - if (specifiedAttachName == szAttachmentTypeNames[attachIndex]) - { - attachmentList.push_back(static_cast(attachIndex)); - foundAttachment = true; - break; - } - } - - if (!foundAttachment) - return false; - } - - return true; -} - -void AssetLoaderWeaponAttachmentUnique::LinkAttachmentUniqueFullSubStructs(WeaponAttachmentUniqueFull* attachmentUnique) -{ - attachmentUnique->attachment.hideTags = attachmentUnique->hideTags; - attachmentUnique->attachment.szXAnims = attachmentUnique->szXAnims; - attachmentUnique->attachment.locationDamageMultipliers = attachmentUnique->locationDamageMultipliers; -} - -bool AssetLoaderWeaponAttachmentUnique::CalculateAttachmentUniqueFields(const std::string& assetName, WeaponAttachmentUniqueFull* attachmentUnique) -{ - // combinedAttachmentTypeMask - std::vector attachmentsFromName; - if (!ExtractAttachmentsFromAssetName(assetName, attachmentsFromName)) - { - std::cerr << "Failed to determine attachments from attachment unique name \"" << assetName << "\"\n"; - return false; - } - - if (attachmentsFromName.size() > 1) - { - for (const auto attachment : attachmentsFromName) - { - attachmentUnique->attachment.combinedAttachmentTypeMask |= 1 << attachment; - } - } - - return true; -} - -bool AssetLoaderWeaponAttachmentUnique::LoadFromInfoString( - const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) -{ - - auto* attachmentUniqueFull = memory->Create(); - memset(attachmentUniqueFull, 0, sizeof(WeaponAttachmentUniqueFull)); - LinkAttachmentUniqueFullSubStructs(attachmentUniqueFull); - - InfoStringToWeaponAttachmentUniqueConverter converter( - infoString, attachmentUniqueFull, zone->m_script_strings, memory, manager, attachment_unique_fields, std::extent_v); - if (!converter.Convert()) - { - std::cerr << "Failed to parse attachment unique: \"" << assetName << "\"\n"; - return true; - } - - if (!CalculateAttachmentUniqueFields(assetName, attachmentUniqueFull)) - return true; - - attachmentUniqueFull->attachment.szInternalName = memory->Dup(assetName.c_str()); - - manager->AddAsset( - assetName, &attachmentUniqueFull->attachment, converter.GetDependencies(), converter.GetUsedScriptStrings(), converter.GetIndirectAssetReferences()); - - return true; -} - -void* AssetLoaderWeaponAttachmentUnique::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* attachmentUniqueFull = memory->Alloc(); - LinkAttachmentUniqueFullSubStructs(attachmentUniqueFull); - CalculateAttachmentUniqueFields(assetName, attachmentUniqueFull); - attachmentUniqueFull->attachment.szInternalName = memory->Dup(assetName.c_str()); - return attachmentUniqueFull; -} - -bool AssetLoaderWeaponAttachmentUnique::CanLoadFromGdt() const -{ - return true; -} - -bool AssetLoaderWeaponAttachmentUnique::LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_WEAPON_ATTACHMENT_UNIQUE, assetName); - if (gdtEntry == nullptr) - return false; - - InfoString infoString; - if (!infoString.FromGdtProperties(*gdtEntry)) - { - std::cerr << "Failed to read attachment unique gdt entry: \"" << assetName << "\"\n"; - return true; - } - - return LoadFromInfoString(infoString, assetName, memory, manager, zone); -} - -bool AssetLoaderWeaponAttachmentUnique::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderWeaponAttachmentUnique::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto fileName = "attachmentunique/" + assetName; - const auto file = searchPath->Open(fileName); - if (!file.IsOpen()) - return false; - - InfoString infoString; - if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_WEAPON_ATTACHMENT_UNIQUE, *file.m_stream)) - { - std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n"; - return true; - } - - return LoadFromInfoString(infoString, assetName, memory, manager, zone); -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeaponAttachmentUnique.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeaponAttachmentUnique.h deleted file mode 100644 index 23f5548d..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeaponAttachmentUnique.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T6/T6.h" -#include "InfoString/InfoString.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderWeaponAttachmentUnique final : public BasicAssetLoader - { - static void LinkAttachmentUniqueFullSubStructs(WeaponAttachmentUniqueFull* attachmentUnique); - static bool CalculateAttachmentUniqueFields(const std::string& assetName, WeaponAttachmentUniqueFull* attachmentUnique); - - static bool - LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone); - - public: - static bool ExtractAttachmentsFromAssetName(const std::string& assetName, std::vector& attachmentList); - - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromGdt() const override; - bool LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeaponCamo.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeaponCamo.cpp deleted file mode 100644 index 671ecbb8..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeaponCamo.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "AssetLoaderWeaponCamo.h" - -#include "Game/T6/T6.h" -#include "Game/T6/WeaponCamo/JsonWeaponCamoLoader.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include -#include - -using namespace T6; - -void* AssetLoaderWeaponCamo::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} - -bool AssetLoaderWeaponCamo::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderWeaponCamo::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto fileName = std::format("camo/{}.json", assetName); - const auto file = searchPath->Open(fileName); - if (!file.IsOpen()) - return false; - - auto* weaponCamo = memory->Alloc(); - weaponCamo->name = memory->Dup(assetName.c_str()); - - std::vector dependencies; - if (LoadWeaponCamoAsJson(*file.m_stream, *weaponCamo, memory, manager, dependencies)) - manager->AddAsset(assetName, weaponCamo, std::move(dependencies)); - else - std::cerr << "Failed to load weapon camo \"" << assetName << "\"\n"; - - return true; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeaponCamo.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeaponCamo.h deleted file mode 100644 index bd8a75c6..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderWeaponCamo.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderWeaponCamo final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderXAnim.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderXAnim.cpp deleted file mode 100644 index 9e2516a0..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderXAnim.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderXAnim.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderXAnim::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderXAnim.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderXAnim.h deleted file mode 100644 index 3e270ac6..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderXAnim.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderXAnim final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderXGlobals.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderXGlobals.cpp deleted file mode 100644 index e1c2b937..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderXGlobals.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "AssetLoaderXGlobals.h" - -#include "Game/T6/T6.h" -#include "ObjLoading.h" - -using namespace T6; - -void* AssetLoaderXGlobals::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderXGlobals.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderXGlobals.h deleted file mode 100644 index c510101b..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderXGlobals.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "AssetLoading/BasicAssetLoader.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderXGlobals final : public BasicAssetLoader - { - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderXModel.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderXModel.cpp deleted file mode 100644 index 28dfcc01..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderXModel.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "AssetLoaderXModel.h" - -#include "Game/T6/T6.h" -#include "Game/T6/XModel/XModelLoaderT6.h" -#include "Pool/GlobalAssetPool.h" - -#include -#include -#include - -using namespace T6; - -void* AssetLoaderXModel::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} - -bool AssetLoaderXModel::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderXModel::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto file = searchPath->Open(std::format("xmodel/{}.json", assetName)); - if (!file.IsOpen()) - return false; - - auto* xmodel = memory->Alloc(); - xmodel->name = memory->Dup(assetName.c_str()); - - std::vector dependencies; - if (LoadXModel(*file.m_stream, *xmodel, memory, manager, dependencies)) - { - manager->AddAsset(assetName, xmodel, std::move(dependencies)); - } - else - { - std::cerr << std::format("Failed to load xmodel \"{}\"\n", assetName); - return false; - } - - return true; -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderXModel.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderXModel.h deleted file mode 100644 index 8a39a8dc..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderXModel.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T6/T6.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderXModel final : public BasicAssetLoader - { - static std::string GetFileNameForAsset(const std::string& assetName); - - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderZBarrier.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderZBarrier.cpp deleted file mode 100644 index c8cf1fda..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderZBarrier.cpp +++ /dev/null @@ -1,133 +0,0 @@ -#include "AssetLoaderZBarrier.h" - -#include "Game/T6/InfoString/InfoStringToStructConverter.h" -#include "Game/T6/InfoString/ZBarrierFields.h" -#include "Game/T6/ObjConstantsT6.h" -#include "Game/T6/T6.h" -#include "InfoString/InfoString.h" - -#include -#include -#include - -using namespace T6; - -namespace T6 -{ - class InfoStringToZBarrierConverter final : public InfoStringToStructConverter - { - protected: - bool ConvertExtensionField(const cspField_t& field, const std::string& value) override - { - assert(false); - return false; - } - - public: - InfoStringToZBarrierConverter(const InfoString& infoString, - ZBarrierDef* zbarrier, - ZoneScriptStrings& zoneScriptStrings, - MemoryManager* memory, - IAssetLoadingManager* manager, - const cspField_t* fields, - const size_t fieldCount) - : InfoStringToStructConverter(infoString, zbarrier, zoneScriptStrings, memory, manager, fields, fieldCount) - { - } - }; -} // namespace T6 - -void AssetLoaderZBarrier::CalculateZBarrierFields(ZBarrierDef* zbarrier) -{ - // numBoardsInBarrier - { - auto foundEnd = false; - for (auto i = 0u; i < std::extent_v; i++) - { - if (zbarrier->boards[i].pBoardModel == nullptr) - { - foundEnd = true; - zbarrier->numBoardsInBarrier = i; - break; - } - } - - if (!foundEnd) - zbarrier->numBoardsInBarrier = std::extent_v; - } -} - -bool AssetLoaderZBarrier::LoadFromInfoString( - const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) -{ - auto* zbarrier = memory->Create(); - memset(zbarrier, 0, sizeof(ZBarrierDef)); - - InfoStringToZBarrierConverter converter( - infoString, zbarrier, zone->m_script_strings, memory, manager, zbarrier_fields, std::extent_v); - if (!converter.Convert()) - { - std::cout << "Failed to parse zbarrier: \"" << assetName << "\"\n"; - return true; - } - - CalculateZBarrierFields(zbarrier); - zbarrier->name = memory->Dup(assetName.c_str()); - - manager->AddAsset(assetName, zbarrier, converter.GetDependencies(), converter.GetUsedScriptStrings()); - - return true; -} - -void* AssetLoaderZBarrier::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* zbarrier = memory->Alloc(); - CalculateZBarrierFields(zbarrier); - zbarrier->name = memory->Dup(assetName.c_str()); - return zbarrier; -} - -bool AssetLoaderZBarrier::CanLoadFromGdt() const -{ - return true; -} - -bool AssetLoaderZBarrier::LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_ZBARRIER, assetName); - if (gdtEntry == nullptr) - return false; - - InfoString infoString; - if (!infoString.FromGdtProperties(*gdtEntry)) - { - std::cout << "Failed to read zbarrier gdt entry: \"" << assetName << "\"\n"; - return true; - } - - return LoadFromInfoString(infoString, assetName, memory, manager, zone); -} - -bool AssetLoaderZBarrier::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderZBarrier::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto fileName = "zbarrier/" + assetName; - const auto file = searchPath->Open(fileName); - if (!file.IsOpen()) - return false; - - InfoString infoString; - if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_ZBARRIER, *file.m_stream)) - { - std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n"; - return true; - } - - return LoadFromInfoString(infoString, assetName, memory, manager, zone); -} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderZBarrier.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderZBarrier.h deleted file mode 100644 index 77e23b17..00000000 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderZBarrier.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include "AssetLoading/BasicAssetLoader.h" -#include "AssetLoading/IAssetLoadingManager.h" -#include "Game/T6/T6.h" -#include "InfoString/InfoString.h" -#include "SearchPath/ISearchPath.h" - -namespace T6 -{ - class AssetLoaderZBarrier final : public BasicAssetLoader - { - static void CalculateZBarrierFields(ZBarrierDef* zbarrier); - - static bool - LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone); - - public: - _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; - _NODISCARD bool CanLoadFromGdt() const override; - bool LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - _NODISCARD bool CanLoadFromRaw() const override; - bool - LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; - }; -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/FontIcon/LoaderFontIconT6.cpp b/src/ObjLoading/Game/T6/FontIcon/LoaderFontIconT6.cpp new file mode 100644 index 00000000..bcdfb938 --- /dev/null +++ b/src/ObjLoading/Game/T6/FontIcon/LoaderFontIconT6.cpp @@ -0,0 +1,292 @@ +#include "LoaderFontIconT6.h" + +#include "Csv/CsvStream.h" +#include "Game/T6/CommonT6.h" +#include "Game/T6/T6.h" + +#include +#include +#include +#include + +using namespace T6; + +namespace +{ + constexpr unsigned ROW_INDEX = 0; + constexpr unsigned ROW_TYPE = 1; + + constexpr unsigned ROW_ICON_NAME = 2; + constexpr unsigned ROW_ICON_MATERIAL = 3; + constexpr unsigned ROW_ICON_SIZE = 4; + constexpr unsigned ROW_ICON_XSCALE = 5; + constexpr unsigned ROW_ICON_YSCALE = 6; + + constexpr unsigned ROW_ALIAS_NAME = 2; + constexpr unsigned ROW_ALIAS_BUTTON = 3; + + constexpr const char* VALUE_TYPE_ICON = "icon"; + constexpr const char* VALUE_TYPE_ALIAS = "alias"; + + constexpr unsigned COL_COUNT_ICON = 7; + constexpr unsigned COL_COUNT_ALIAS = 4; + constexpr unsigned COL_COUNT_MIN = std::min(COL_COUNT_ICON, COL_COUNT_ALIAS); + + class FontIconLoader final : public AssetCreator + { + public: + FontIconLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto file = m_search_path.Open(assetName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + auto* fontIcon = m_memory.Alloc(); + fontIcon->name = m_memory.Dup(assetName.c_str()); + AssetRegistration registration(assetName, fontIcon); + + const CsvInputStream csv(*file.m_stream); + std::vector currentRow; + std::vector entries; + std::vector aliases; + auto currentRowIndex = 0u; + + while (csv.NextRow(currentRow)) + { + currentRowIndex++; + PreprocessRow(currentRow); + + if (RowIsEmpty(currentRow)) + continue; + + if (currentRow.size() < COL_COUNT_MIN) + { + std::cerr << std::format("{} Column count lower than min column count ({})\n", ErrorPrefix(assetName, currentRowIndex), COL_COUNT_MIN); + return AssetCreationResult::Failure(); + } + + int index; + if (!ParseInt(index, currentRow[ROW_INDEX]) || index < 0) + { + std::cerr << std::format("{} Failed to parse index\n", ErrorPrefix(assetName, currentRowIndex)); + return AssetCreationResult::Failure(); + } + + if (currentRow[ROW_TYPE] == VALUE_TYPE_ICON) + { + FontIconEntry icon{}; + if (!ReadIconRow(currentRow, icon, assetName, currentRowIndex, context, registration)) + return AssetCreationResult::Failure(); + + if (static_cast(index) == entries.size()) + { + entries.push_back(icon); + } + else if (static_cast(index) > entries.size()) + { + entries.reserve(index + 1); + entries[index] = icon; + } + else + { + entries[index] = icon; + } + } + else if (currentRow[ROW_TYPE] == VALUE_TYPE_ALIAS) + { + FontIconAlias alias{}; + if (!ReadAliasRow(currentRow, alias, assetName, currentRowIndex, context)) + return AssetCreationResult::Failure(); + + if (static_cast(index) == aliases.size()) + { + aliases.push_back(alias); + } + else if (static_cast(index) > aliases.size()) + { + aliases.reserve(index + 1); + aliases[index] = alias; + } + else + { + aliases[index] = alias; + } + } + else + { + std::cerr << std::format("{} Unknown row type \"{}\"\n", ErrorPrefix(assetName, currentRowIndex), currentRow[ROW_TYPE]); + return AssetCreationResult::Failure(); + } + } + + fontIcon->numEntries = entries.size(); + fontIcon->numAliasEntries = aliases.size(); + + if (fontIcon->numEntries > 0) + { + fontIcon->fontIconEntry = m_memory.Alloc(fontIcon->numEntries); + for (auto i = 0u; i < entries.size(); i++) + fontIcon->fontIconEntry[i] = entries[i]; + } + else + fontIcon->fontIconEntry = nullptr; + + if (fontIcon->numAliasEntries > 0) + { + fontIcon->fontIconAlias = m_memory.Alloc(fontIcon->numAliasEntries); + for (auto i = 0u; i < aliases.size(); i++) + fontIcon->fontIconAlias[i] = aliases[i]; + } + else + fontIcon->fontIconAlias = nullptr; + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); + } + + private: + static std::string ErrorPrefix(const std::string& assetName, const unsigned rowIndex) + { + return std::format("FontIcon \"{}\" Row {}:", assetName, rowIndex); + } + + static void PreprocessRow(std::vector& row) + { + for (auto& cell : row) + { + for (auto c : cell) + { + if (isspace(c)) + continue; + if (c == '#') + cell = ""; + break; + } + } + } + + static bool RowIsEmpty(const std::vector& row) + { + return std::ranges::all_of(row, + [](const std::string& cell) + { + return cell.empty(); + }); + } + + static bool ParseInt(int& value, const std::string& str) + { + char* endPtr; + value = strtol(str.c_str(), &endPtr, 0); + if (endPtr != &str[str.size()]) + return false; + return true; + } + + static bool ParseFloat(float& value, const std::string& str) + { + char* endPtr; + value = strtof(str.c_str(), &endPtr); + if (endPtr != &str[str.size()]) + return false; + return true; + } + + static bool ParseHashStr(int& value, const std::string& str) + { + if (!str.empty() && str[0] == '@' && str.size() > 1) + { + char* endPtr; + value = strtol(&str[1], &endPtr, 16); + + if (endPtr != &str[str.size()]) + return false; + } + else + { + value = Common::Com_HashString(str.c_str()); + } + + return true; + } + + bool ReadIconRow(const std::vector& row, + FontIconEntry& icon, + const std::string& assetName, + const unsigned rowIndex, + AssetCreationContext& context, + AssetRegistration& registration) + { + if (row.size() < COL_COUNT_ICON) + { + std::cerr << std::format("{} Column count lower than min column count for entries ({})\n", ErrorPrefix(assetName, rowIndex), COL_COUNT_ICON); + return false; + } + + if (!ParseInt(icon.fontIconSize, row[ROW_ICON_SIZE])) + { + std::cerr << std::format("{} Failed to parse size\n", ErrorPrefix(assetName, rowIndex)); + return false; + } + + if (!ParseFloat(icon.xScale, row[ROW_ICON_XSCALE]) || !ParseFloat(icon.yScale, row[ROW_ICON_YSCALE])) + { + std::cerr << std::format("{} Failed to parse scale\n", ErrorPrefix(assetName, rowIndex)); + return false; + } + + auto* materialDependency = context.LoadDependency(row[ROW_ICON_MATERIAL]); + if (materialDependency == nullptr) + { + std::cerr << std::format("{} Failed to load material \"{}\"\n", ErrorPrefix(assetName, rowIndex), row[ROW_ICON_MATERIAL]); + return false; + } + + icon.fontIconMaterialHandle = materialDependency->Asset(); + icon.fontIconName.string = m_memory.Dup(row[ROW_ICON_NAME].c_str()); + icon.fontIconName.hash = Common::Com_HashString(icon.fontIconName.string); + + return true; + } + + bool ReadAliasRow( + const std::vector& row, FontIconAlias& alias, const std::string& assetName, const unsigned rowIndex, AssetCreationContext& context) + { + if (row.size() < COL_COUNT_ALIAS) + { + std::cerr << std::format("{} Column count lower than min column count for aliases ({})\n", ErrorPrefix(assetName, rowIndex), COL_COUNT_ALIAS); + return false; + } + + if (!ParseHashStr(alias.aliasHash, row[ROW_ALIAS_NAME])) + { + std::cerr << std::format("{} Failed to parse alias \"{}\"\n", ErrorPrefix(assetName, rowIndex), row[ROW_ALIAS_NAME]); + return false; + } + + if (!ParseHashStr(alias.buttonHash, row[ROW_ALIAS_BUTTON])) + { + std::cerr << std::format("{} Failed to parse button \"{}\"\n", ErrorPrefix(assetName, rowIndex), row[ROW_ALIAS_BUTTON]); + return false; + } + + return true; + } + + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateFontIconLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/FontIcon/LoaderFontIconT6.h b/src/ObjLoading/Game/T6/FontIcon/LoaderFontIconT6.h new file mode 100644 index 00000000..e9f658e8 --- /dev/null +++ b/src/ObjLoading/Game/T6/FontIcon/LoaderFontIconT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateFontIconLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Image/LoaderImageT6.cpp b/src/ObjLoading/Game/T6/Image/LoaderImageT6.cpp new file mode 100644 index 00000000..76e74131 --- /dev/null +++ b/src/ObjLoading/Game/T6/Image/LoaderImageT6.cpp @@ -0,0 +1,77 @@ +#include "LoaderImageT6.h" + +#include "Game/T6/CommonT6.h" +#include "Game/T6/T6.h" +#include "Image/IwiLoader.h" + +#include +#include +#include +#include +#include + +using namespace T6; + +namespace +{ + class ImageLoader final : public AssetCreator + { + public: + ImageLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto fileName = std::format("images/{}.iwi", assetName); + const auto file = m_search_path.Open(fileName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + const auto fileSize = static_cast(file.m_length); + const auto fileData = std::make_unique(fileSize); + file.m_stream->read(fileData.get(), fileSize); + const auto dataHash = static_cast(crc32(0u, reinterpret_cast(fileData.get()), fileSize)); + + std::istringstream ss(std::string(fileData.get(), fileSize)); + const auto texture = iwi::LoadIwi(ss); + if (!texture) + { + std::cerr << std::format("Failed to load texture from: {}\n", fileName); + return AssetCreationResult::Failure(); + } + + auto* image = m_memory.Alloc(); + image->name = m_memory.Dup(assetName.c_str()); + image->hash = Common::R_HashString(image->name, 0); + image->delayLoadPixels = true; + + image->noPicmip = !texture->HasMipMaps(); + image->width = static_cast(texture->GetWidth()); + image->height = static_cast(texture->GetHeight()); + image->depth = static_cast(texture->GetDepth()); + + image->streaming = 1; + image->streamedParts[0].levelCount = 1; + image->streamedParts[0].levelSize = static_cast(fileSize); + image->streamedParts[0].hash = dataHash & 0x1FFFFFFF; + image->streamedPartCount = 1; + + return AssetCreationResult::Success(context.AddAsset(assetName, image)); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateImageLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Image/LoaderImageT6.h b/src/ObjLoading/Game/T6/Image/LoaderImageT6.h new file mode 100644 index 00000000..6c1bfb1f --- /dev/null +++ b/src/ObjLoading/Game/T6/Image/LoaderImageT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateImageLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/InfoString/InfoStringToStructConverter.cpp b/src/ObjLoading/Game/T6/InfoString/InfoStringToStructConverter.cpp index 6866a586..d7fd2678 100644 --- a/src/ObjLoading/Game/T6/InfoString/InfoStringToStructConverter.cpp +++ b/src/ObjLoading/Game/T6/InfoString/InfoStringToStructConverter.cpp @@ -7,33 +7,36 @@ using namespace T6; +namespace +{ + bool GetHashValue(const std::string& value, unsigned& hash) + { + if (!value.empty() && value[0] == '@') + { + char* endPtr; + hash = strtoul(&value[1], &endPtr, 16); + return endPtr == &value[value.size()]; + } + + hash = Common::Com_HashString(value.c_str()); + return true; + } +} // namespace + InfoStringToStructConverter::InfoStringToStructConverter(const InfoString& infoString, void* structure, ZoneScriptStrings& zoneScriptStrings, - MemoryManager* memory, - IAssetLoadingManager* manager, + MemoryManager& memory, + AssetCreationContext& context, + GenericAssetRegistration& registration, const cspField_t* fields, const size_t fieldCount) - : InfoStringToStructConverterBase(infoString, structure, zoneScriptStrings, memory), - m_loading_manager(manager), + : InfoStringToStructConverterBase(infoString, structure, zoneScriptStrings, memory, context, registration), m_fields(fields), m_field_count(fieldCount) { } -bool InfoStringToStructConverter::GetHashValue(const std::string& value, unsigned& hash) -{ - if (!value.empty() && value[0] == '@') - { - char* endPtr; - hash = strtoul(&value[1], &endPtr, 16); - return endPtr == &value[value.size()]; - } - - hash = Common::Com_HashString(value.c_str()); - return true; -} - bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, const std::string& value) { switch (static_cast(field.iFieldType)) @@ -76,15 +79,15 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons return true; } - auto* fx = m_loading_manager->LoadDependency(value); + auto* fx = m_context.LoadDependency(value); if (fx == nullptr) { - std::cout << "Failed to load fx asset \"" << value << "\"\n"; + std::cerr << std::format("Failed to load fx asset \"{}\"\n", value); return false; } - m_dependencies.emplace(fx); + m_registration.AddDependency(fx); *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = fx->Asset(); return true; @@ -98,15 +101,15 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons return true; } - auto* xmodel = m_loading_manager->LoadDependency(value); + auto* xmodel = m_context.LoadDependency(value); if (xmodel == nullptr) { - std::cout << "Failed to load xmodel asset \"" << value << "\"\n"; + std::cerr << std::format("Failed to load xmodel asset \"{}\"\n", value); return false; } - m_dependencies.emplace(xmodel); + m_registration.AddDependency(xmodel); *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = xmodel->Asset(); return true; @@ -121,15 +124,15 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons return true; } - auto* material = m_loading_manager->LoadDependency(value); + auto* material = m_context.LoadDependency(value); if (material == nullptr) { - std::cout << "Failed to load material asset \"" << value << "\"\n"; + std::cerr << std::format("Failed to load material asset \"{}\"\n", value); return false; } - m_dependencies.emplace(material); + m_registration.AddDependency(material); *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = material->Asset(); return true; @@ -143,15 +146,15 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons return true; } - auto* physPreset = m_loading_manager->LoadDependency(value); + auto* physPreset = m_context.LoadDependency(value); if (physPreset == nullptr) { - std::cout << "Failed to load physpreset asset \"" << value << "\"\n"; + std::cerr << std::format("Failed to load physpreset asset \"{}\"\n", value); return false; } - m_dependencies.emplace(physPreset); + m_registration.AddDependency(physPreset); *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = physPreset->Asset(); return true; @@ -168,15 +171,15 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons return true; } - auto* tracer = m_loading_manager->LoadDependency(value); + auto* tracer = m_context.LoadDependency(value); if (tracer == nullptr) { - std::cout << "Failed to load tracer asset \"" << value << "\"\n"; + std::cerr << std::format("Failed to load tracer asset \"{}\"\n", value); return false; } - m_dependencies.emplace(tracer); + m_registration.AddDependency(tracer); *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = tracer->Asset(); return true; @@ -187,7 +190,7 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons unsigned int soundAliasHash; if (!GetHashValue(value, soundAliasHash)) { - std::cout << "Failed to parse value \"" << value << "\" as hash\n"; + std::cerr << std::format("Failed to parse value \"{}\" as hash\n", value); return false; } diff --git a/src/ObjLoading/Game/T6/InfoString/InfoStringToStructConverter.h b/src/ObjLoading/Game/T6/InfoString/InfoStringToStructConverter.h index 5adb8cf0..6a2b3ddf 100644 --- a/src/ObjLoading/Game/T6/InfoString/InfoStringToStructConverter.h +++ b/src/ObjLoading/Game/T6/InfoString/InfoStringToStructConverter.h @@ -1,5 +1,5 @@ #pragma once -#include "AssetLoading/IAssetLoadingManager.h" + #include "Game/T6/T6.h" #include "InfoString/InfoStringToStructConverterBase.h" @@ -7,24 +7,22 @@ namespace T6 { class InfoStringToStructConverter : public InfoStringToStructConverterBase { - protected: - IAssetLoadingManager* m_loading_manager; - const cspField_t* m_fields; - size_t m_field_count; - - static bool GetHashValue(const std::string& value, unsigned int& hash); - - virtual bool ConvertExtensionField(const cspField_t& field, const std::string& value) = 0; - bool ConvertBaseField(const cspField_t& field, const std::string& value); - public: InfoStringToStructConverter(const InfoString& infoString, void* structure, ZoneScriptStrings& zoneScriptStrings, - MemoryManager* memory, - IAssetLoadingManager* manager, + MemoryManager& memory, + AssetCreationContext& context, + GenericAssetRegistration& registration, const cspField_t* fields, size_t fieldCount); bool Convert() override; + + protected: + virtual bool ConvertExtensionField(const cspField_t& field, const std::string& value) = 0; + bool ConvertBaseField(const cspField_t& field, const std::string& value); + + const cspField_t* m_fields; + size_t m_field_count; }; } // namespace T6 diff --git a/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp b/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp index 1fb1d400..6e8686c3 100644 --- a/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp +++ b/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp @@ -1,4 +1,3 @@ - #include "JsonLeaderboardDefLoader.h" #include "Game/T6/CommonT6.h" @@ -129,9 +128,9 @@ namespace namespace T6 { - bool LoadLeaderboardAsJson(std::istream& stream, LeaderboardDef& leaderboard, MemoryManager* memory) + bool LoadLeaderboardAsJson(std::istream& stream, LeaderboardDef& leaderboard, MemoryManager& memory) { - const JsonLoader loader(stream, *memory); + const JsonLoader loader(stream, memory); return loader.Load(leaderboard); } } // namespace T6 diff --git a/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.h b/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.h index 9c145ae5..6145d04d 100644 --- a/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.h +++ b/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.h @@ -7,5 +7,5 @@ namespace T6 { - bool LoadLeaderboardAsJson(std::istream& stream, LeaderboardDef& leaderboard, MemoryManager* memory); + bool LoadLeaderboardAsJson(std::istream& stream, LeaderboardDef& leaderboard, MemoryManager& memory); } // namespace T6 diff --git a/src/ObjLoading/Game/T6/Leaderboard/LoaderLeaderboardT6.cpp b/src/ObjLoading/Game/T6/Leaderboard/LoaderLeaderboardT6.cpp new file mode 100644 index 00000000..ae08c020 --- /dev/null +++ b/src/ObjLoading/Game/T6/Leaderboard/LoaderLeaderboardT6.cpp @@ -0,0 +1,54 @@ +#include "LoaderLeaderboardT6.h" + +#include "Game/T6/CommonT6.h" +#include "Game/T6/T6.h" +#include "JsonLeaderboardDefLoader.h" + +#include +#include +#include + +using namespace T6; + +namespace +{ + class LeaderboardLoader final : public AssetCreator + { + public: + LeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto file = m_search_path.Open(std::format("leaderboards/{}.json", assetName)); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + auto* leaderboardDef = m_memory.Alloc(); + leaderboardDef->name = m_memory.Dup(assetName.c_str()); + + if (!LoadLeaderboardAsJson(*file.m_stream, *leaderboardDef, m_memory)) + { + std::cerr << std::format("Failed to load leaderboard \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + return AssetCreationResult::Success(context.AddAsset(assetName, leaderboardDef)); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateLeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Leaderboard/LoaderLeaderboardT6.h b/src/ObjLoading/Game/T6/Leaderboard/LoaderLeaderboardT6.h new file mode 100644 index 00000000..df060b90 --- /dev/null +++ b/src/ObjLoading/Game/T6/Leaderboard/LoaderLeaderboardT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateLeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Localize/LoaderLocalizeT6.cpp b/src/ObjLoading/Game/T6/Localize/LoaderLocalizeT6.cpp new file mode 100644 index 00000000..c4a3b77d --- /dev/null +++ b/src/ObjLoading/Game/T6/Localize/LoaderLocalizeT6.cpp @@ -0,0 +1,44 @@ +#include "LoaderLocalizeT6.h" + +#include "Localize/CommonLocalizeLoader.h" + +using namespace T6; + +namespace +{ + class LocalizeLoader final : public AssetCreator, public CommonLocalizeLoader + { + public: + LocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : CommonLocalizeLoader(searchPath, zone), + m_memory(memory) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + return CreateLocalizeAsset(assetName, context); + } + + protected: + AssetCreationResult CreateAssetFromCommonAsset(const CommonLocalizeEntry& localizeEntry, AssetCreationContext& context) override + { + auto* asset = m_memory.Alloc(); + asset->name = m_memory.Dup(localizeEntry.m_key.c_str()); + asset->value = m_memory.Dup(localizeEntry.m_value.c_str()); + + return AssetCreationResult::Success(context.AddAsset(localizeEntry.m_key, asset)); + } + + private: + MemoryManager& m_memory; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + { + return std::make_unique(memory, searchPath, zone); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Localize/LoaderLocalizeT6.h b/src/ObjLoading/Game/T6/Localize/LoaderLocalizeT6.h new file mode 100644 index 00000000..991f53b1 --- /dev/null +++ b/src/ObjLoading/Game/T6/Localize/LoaderLocalizeT6.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" +#include "Zone/Zone.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Material/JsonMaterialLoader.cpp b/src/ObjLoading/Game/T6/Material/JsonMaterialLoader.cpp index 09517f39..aa3be869 100644 --- a/src/ObjLoading/Game/T6/Material/JsonMaterialLoader.cpp +++ b/src/ObjLoading/Game/T6/Material/JsonMaterialLoader.cpp @@ -15,11 +15,11 @@ namespace class JsonLoader { public: - JsonLoader(std::istream& stream, MemoryManager& memory, IAssetLoadingManager& manager, std::vector& dependencies) + JsonLoader(std::istream& stream, MemoryManager& memory, AssetCreationContext& context, AssetRegistration& registration) : m_stream(stream), m_memory(memory), - m_manager(manager), - m_dependencies(dependencies) + m_context(context), + m_registration(registration) { } @@ -35,7 +35,7 @@ namespace if (type != "material" || version != 1u) { - std::cerr << "Tried to load material \"" << material.info.name << "\" but did not find expected type material of version 1\n"; + std::cerr << std::format("Tried to load material \"{}\" but did not find expected type material of version 1\n", material.info.name); return false; } @@ -55,7 +55,7 @@ namespace private: static void PrintError(const Material& material, const std::string& message) { - std::cerr << "Cannot load material \"" << material.info.name << "\": " << message << "\n"; + std::cerr << std::format("Cannot load material \"{}\": {}\n", material.info.name, message); } static bool CreateGameFlagsFromJson(const JsonMaterial& jMaterial, unsigned& gameFlags) @@ -108,13 +108,13 @@ namespace textureDef.semantic = jTexture.semantic; textureDef.isMatureContent = jTexture.isMatureContent; - auto* image = m_manager.LoadDependency(jTexture.image); + auto* image = m_context.LoadDependency(jTexture.image); if (!image) { PrintError(material, std::format("Could not find textureDef image: {}", jTexture.image)); return false; } - m_dependencies.push_back(image); + m_registration.AddDependency(image); textureDef.image = image->Asset(); return true; @@ -284,13 +284,13 @@ namespace material.cameraRegion = jMaterial.cameraRegion; material.probeMipBits = jMaterial.probeMipBits; - auto* techniqueSet = m_manager.LoadDependency(jMaterial.techniqueSet); + auto* techniqueSet = m_context.LoadDependency(jMaterial.techniqueSet); if (!techniqueSet) { PrintError(material, "Could not find technique set"); return false; } - m_dependencies.push_back(techniqueSet); + m_registration.AddDependency(techniqueSet); material.techniqueSet = techniqueSet->Asset(); if (!jMaterial.textures.empty()) @@ -346,13 +346,13 @@ namespace if (jMaterial.thermalMaterial) { - auto* thermalMaterial = m_manager.LoadDependency(jMaterial.thermalMaterial.value()); + auto* thermalMaterial = m_context.LoadDependency(jMaterial.thermalMaterial.value()); if (!thermalMaterial) { PrintError(material, "Could not find thermal material"); return false; } - m_dependencies.push_back(thermalMaterial); + m_registration.AddDependency(thermalMaterial); material.thermalMaterial = thermalMaterial->Asset(); } else @@ -365,17 +365,17 @@ namespace std::istream& m_stream; MemoryManager& m_memory; - IAssetLoadingManager& m_manager; - std::vector& m_dependencies; + AssetCreationContext& m_context; + AssetRegistration& m_registration; }; } // namespace namespace T6 { bool LoadMaterialAsJson( - std::istream& stream, Material& material, MemoryManager* memory, IAssetLoadingManager* manager, std::vector& dependencies) + std::istream& stream, Material& material, MemoryManager& memory, AssetCreationContext& context, AssetRegistration& registration) { - const JsonLoader loader(stream, *memory, *manager, dependencies); + const JsonLoader loader(stream, memory, context, registration); return loader.Load(material); } diff --git a/src/ObjLoading/Game/T6/Material/JsonMaterialLoader.h b/src/ObjLoading/Game/T6/Material/JsonMaterialLoader.h index 5e502e90..0356ed0e 100644 --- a/src/ObjLoading/Game/T6/Material/JsonMaterialLoader.h +++ b/src/ObjLoading/Game/T6/Material/JsonMaterialLoader.h @@ -1,6 +1,7 @@ #pragma once -#include "AssetLoading/IAssetLoadingManager.h" +#include "Asset/AssetCreationContext.h" +#include "Asset/AssetRegistration.h" #include "Game/T6/T6.h" #include "Utils/MemoryManager.h" @@ -9,5 +10,5 @@ namespace T6 { bool LoadMaterialAsJson( - std::istream& stream, Material& material, MemoryManager* memory, IAssetLoadingManager* manager, std::vector& dependencies); + std::istream& stream, Material& material, MemoryManager& memory, AssetCreationContext& context, AssetRegistration& registration); } // namespace T6 diff --git a/src/ObjLoading/Game/T6/Material/LoaderMaterialT6.cpp b/src/ObjLoading/Game/T6/Material/LoaderMaterialT6.cpp new file mode 100644 index 00000000..08add739 --- /dev/null +++ b/src/ObjLoading/Game/T6/Material/LoaderMaterialT6.cpp @@ -0,0 +1,70 @@ +#include "LoaderMaterialT6.h" + +#include "Game/T6/Material/JsonMaterialLoader.h" +#include "Game/T6/T6.h" + +#include +#include +#include +#include + +using namespace T6; + +namespace +{ + class MaterialLoader final : public AssetCreator + { + public: + MaterialLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto file = m_search_path.Open(GetFileNameForAsset(assetName)); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + auto* material = m_memory.Alloc(); + material->info.name = m_memory.Dup(assetName.c_str()); + + AssetRegistration registration(assetName, material); + if (!LoadMaterialAsJson(*file.m_stream, *material, m_memory, context, registration)) + { + std::cerr << std::format("Failed to load material \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); + } + + private: + static std::string GetFileNameForAsset(const std::string& assetName) + { + std::string sanitizedFileName(assetName); + if (sanitizedFileName[0] == '*') + { + std::ranges::replace(sanitizedFileName, '*', '_'); + const auto parenthesisPos = sanitizedFileName.find('('); + if (parenthesisPos != std::string::npos) + sanitizedFileName.erase(parenthesisPos); + sanitizedFileName = "generated/" + sanitizedFileName; + } + + return std::format("materials/{}.json", sanitizedFileName); + } + + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Material/LoaderMaterialT6.h b/src/ObjLoading/Game/T6/Material/LoaderMaterialT6.h new file mode 100644 index 00000000..22cd78dc --- /dev/null +++ b/src/ObjLoading/Game/T6/Material/LoaderMaterialT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/ObjLoaderT6.cpp b/src/ObjLoading/Game/T6/ObjLoaderT6.cpp index 99d48000..cbce8c48 100644 --- a/src/ObjLoading/Game/T6/ObjLoaderT6.cpp +++ b/src/ObjLoading/Game/T6/ObjLoaderT6.cpp @@ -1,130 +1,54 @@ #include "ObjLoaderT6.h" -#include "AssetLoaders/AssetLoaderAddonMapEnts.h" -#include "AssetLoaders/AssetLoaderClipMap.h" -#include "AssetLoaders/AssetLoaderComWorld.h" -#include "AssetLoaders/AssetLoaderDDL.h" -#include "AssetLoaders/AssetLoaderDestructibleDef.h" -#include "AssetLoaders/AssetLoaderEmblemSet.h" -#include "AssetLoaders/AssetLoaderFont.h" -#include "AssetLoaders/AssetLoaderFontIcon.h" -#include "AssetLoaders/AssetLoaderFootstepFxTable.h" -#include "AssetLoaders/AssetLoaderFootstepTable.h" -#include "AssetLoaders/AssetLoaderFx.h" -#include "AssetLoaders/AssetLoaderGameWorldMp.h" -#include "AssetLoaders/AssetLoaderGameWorldSp.h" -#include "AssetLoaders/AssetLoaderGfxImage.h" -#include "AssetLoaders/AssetLoaderGfxLightDef.h" -#include "AssetLoaders/AssetLoaderGfxWorld.h" -#include "AssetLoaders/AssetLoaderGlasses.h" -#include "AssetLoaders/AssetLoaderImpactFx.h" -#include "AssetLoaders/AssetLoaderLeaderboard.h" -#include "AssetLoaders/AssetLoaderLocalizeEntry.h" -#include "AssetLoaders/AssetLoaderMapEnts.h" -#include "AssetLoaders/AssetLoaderMaterial.h" -#include "AssetLoaders/AssetLoaderMemoryBlock.h" -#include "AssetLoaders/AssetLoaderMenu.h" -#include "AssetLoaders/AssetLoaderMenuList.h" -#include "AssetLoaders/AssetLoaderPhysConstraints.h" -#include "AssetLoaders/AssetLoaderPhysPreset.h" -#include "AssetLoaders/AssetLoaderQdb.h" -#include "AssetLoaders/AssetLoaderRawFile.h" -#include "AssetLoaders/AssetLoaderScriptParseTree.h" -#include "AssetLoaders/AssetLoaderSkinnedVerts.h" -#include "AssetLoaders/AssetLoaderSlug.h" -#include "AssetLoaders/AssetLoaderSoundBank.h" -#include "AssetLoaders/AssetLoaderSoundDriverGlobals.h" -#include "AssetLoaders/AssetLoaderSoundPatch.h" -#include "AssetLoaders/AssetLoaderStringTable.h" -#include "AssetLoaders/AssetLoaderTechniqueSet.h" -#include "AssetLoaders/AssetLoaderTracer.h" -#include "AssetLoaders/AssetLoaderVehicle.h" -#include "AssetLoaders/AssetLoaderWeapon.h" -#include "AssetLoaders/AssetLoaderWeaponAttachment.h" -#include "AssetLoaders/AssetLoaderWeaponAttachmentUnique.h" -#include "AssetLoaders/AssetLoaderWeaponCamo.h" -#include "AssetLoaders/AssetLoaderXAnim.h" -#include "AssetLoaders/AssetLoaderXGlobals.h" -#include "AssetLoaders/AssetLoaderXModel.h" -#include "AssetLoaders/AssetLoaderZBarrier.h" -#include "AssetLoading/AssetLoadingManager.h" +#include "Asset/GlobalAssetPoolsLoader.h" +#include "FontIcon/LoaderFontIconT6.h" #include "Game/T6/CommonT6.h" #include "Game/T6/GameAssetPoolT6.h" #include "Game/T6/GameT6.h" +#include "Game/T6/T6.h" +#include "Game/T6/XModel/LoaderXModelT6.h" #include "Image/Dx12TextureLoader.h" #include "Image/IwiLoader.h" #include "Image/IwiTypes.h" +#include "Image/LoaderImageT6.h" #include "Image/Texture.h" +#include "Leaderboard/LoaderLeaderboardT6.h" +#include "Localize/LoaderLocalizeT6.h" +#include "Material/LoaderMaterialT6.h" #include "ObjContainer/IPak/IPak.h" #include "ObjLoading.h" +#include "PhysConstraints/GdtLoaderPhysConstraintsT6.h" +#include "PhysConstraints/RawLoaderPhysConstraintsT6.h" +#include "PhysPreset/GdtLoaderPhysPresetT6.h" +#include "PhysPreset/RawLoaderPhysPresetT6.h" +#include "Qdb/LoaderQdbT6.h" +#include "RawFile/LoaderRawFileT6.h" +#include "Script/LoaderScriptT6.h" +#include "Slug/LoaderSlugT6.h" +#include "Sound/LoaderSoundBankT6.h" +#include "StringTable/LoaderStringTableT6.h" +#include "Tracer/GdtLoaderTracerT6.h" +#include "Tracer/RawLoaderTracerT6.h" +#include "Vehicle/GdtLoaderVehicleT6.h" +#include "Vehicle/RawLoaderVehicleT6.h" +#include "Weapon/GdtLoaderAttachmentT6.h" +#include "Weapon/GdtLoaderAttachmentUniqueT6.h" +#include "Weapon/GdtLoaderWeaponT6.h" +#include "Weapon/LoaderWeaponCamoT6.h" +#include "Weapon/RawLoaderAttachmentT6.h" +#include "Weapon/RawLoaderAttachmentUniqueT6.h" +#include "Weapon/RawLoaderWeaponT6.h" +#include "ZBarrier/GdtLoaderZBarrierT6.h" +#include "ZBarrier/RawLoaderZBarrierT6.h" #include +#include namespace T6 { constexpr auto IPAK_READ_HASH = Common::Com_HashKey("ipak_read", 64); constexpr auto GLOBAL_HASH = Common::Com_HashKey("GLOBAL", 64); - ObjLoader::ObjLoader() - { -#define REGISTER_ASSET_LOADER(t) \ - { \ - auto l = std::make_unique(); \ - m_asset_loaders_by_type[l->GetHandlingAssetType()] = std::move(l); \ - } - - REGISTER_ASSET_LOADER(AssetLoaderPhysPreset) - REGISTER_ASSET_LOADER(AssetLoaderPhysConstraints) - REGISTER_ASSET_LOADER(AssetLoaderDestructibleDef) - REGISTER_ASSET_LOADER(AssetLoaderXAnim) - REGISTER_ASSET_LOADER(AssetLoaderXModel) - REGISTER_ASSET_LOADER(AssetLoaderMaterial) - REGISTER_ASSET_LOADER(AssetLoaderTechniqueSet) - REGISTER_ASSET_LOADER(AssetLoaderGfxImage) - REGISTER_ASSET_LOADER(AssetLoaderSoundBank) - REGISTER_ASSET_LOADER(AssetLoaderSoundPatch) - REGISTER_ASSET_LOADER(AssetLoaderClipMap) - REGISTER_ASSET_LOADER(AssetLoaderClipMapPvs) - REGISTER_ASSET_LOADER(AssetLoaderComWorld) - REGISTER_ASSET_LOADER(AssetLoaderGameWorldSp) - REGISTER_ASSET_LOADER(AssetLoaderGameWorldMp) - REGISTER_ASSET_LOADER(AssetLoaderMapEnts) - REGISTER_ASSET_LOADER(AssetLoaderGfxWorld) - REGISTER_ASSET_LOADER(AssetLoaderGfxLightDef) - REGISTER_ASSET_LOADER(AssetLoaderFont) - REGISTER_ASSET_LOADER(AssetLoaderFontIcon) - REGISTER_ASSET_LOADER(AssetLoaderMenuList) - REGISTER_ASSET_LOADER(AssetLoaderMenu) - REGISTER_ASSET_LOADER(AssetLoaderLocalizeEntry) - REGISTER_ASSET_LOADER(AssetLoaderWeapon) - REGISTER_ASSET_LOADER(AssetLoaderWeaponAttachment) - REGISTER_ASSET_LOADER(AssetLoaderWeaponAttachmentUnique) - REGISTER_ASSET_LOADER(AssetLoaderWeaponCamo) - REGISTER_ASSET_LOADER(AssetLoaderSoundDriverGlobals) - REGISTER_ASSET_LOADER(AssetLoaderFx) - REGISTER_ASSET_LOADER(AssetLoaderImpactFx) - REGISTER_ASSET_LOADER(AssetLoaderRawFile) - REGISTER_ASSET_LOADER(AssetLoaderStringTable) - REGISTER_ASSET_LOADER(AssetLoaderLeaderboard) - REGISTER_ASSET_LOADER(AssetLoaderXGlobals) - REGISTER_ASSET_LOADER(AssetLoaderDDL) - REGISTER_ASSET_LOADER(AssetLoaderGlasses) - REGISTER_ASSET_LOADER(AssetLoaderEmblemSet) - REGISTER_ASSET_LOADER(AssetLoaderScriptParseTree) - REGISTER_ASSET_LOADER(AssetLoaderVehicle) - REGISTER_ASSET_LOADER(AssetLoaderMemoryBlock) - REGISTER_ASSET_LOADER(AssetLoaderAddonMapEnts) - REGISTER_ASSET_LOADER(AssetLoaderTracer) - REGISTER_ASSET_LOADER(AssetLoaderSkinnedVerts) - REGISTER_ASSET_LOADER(AssetLoaderQdb) - REGISTER_ASSET_LOADER(AssetLoaderSlug) - REGISTER_ASSET_LOADER(AssetLoaderFootstepTable) - REGISTER_ASSET_LOADER(AssetLoaderFootstepFxTable) - REGISTER_ASSET_LOADER(AssetLoaderZBarrier) - -#undef REGISTER_ASSET_LOADER - } - bool ObjLoader::VerifySoundBankChecksum(const SoundBank& soundBank, const SndRuntimeAssetBank& sndRuntimeAssetBank) { SoundAssetBankChecksum checksum{}; @@ -328,7 +252,7 @@ namespace T6 for (auto* keyValuePairsEntry : *assetPoolT6->m_key_value_pairs) { const auto* keyValuePairs = keyValuePairsEntry->Asset(); - for (auto variableIndex = 0; variableIndex < keyValuePairs->numVariables; variableIndex++) + for (auto variableIndex = 0u; variableIndex < keyValuePairs->numVariables; variableIndex++) { auto* variable = &keyValuePairs->keyValuePairs[variableIndex]; @@ -356,15 +280,180 @@ namespace T6 IPak::Repository.RemoveContainerReferences(&zone); } - bool ObjLoader::LoadAssetForZone(AssetLoadingContext& context, const asset_type_t assetType, const std::string& assetName) const + namespace { - AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, context); - return assetLoadingManager.LoadAssetFromLoader(assetType, assetName); - } + void ConfigureDefaultCreators(AssetCreatorCollection& collection, Zone& zone) + { + auto& memory = *zone.GetMemory(); - void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext& context) const + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + // AssetImpactFx has no name and cannot be default constructed + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + // AssetEmblemSet has no name and cannot be default constructed + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + collection.AddDefaultAssetCreator(std::make_unique>(memory)); + } + + void ConfigureGlobalAssetPoolsLoaders(AssetCreatorCollection& collection, Zone& zone) + { + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + collection.AddAssetCreator(std::make_unique>(zone)); + } + + void ConfigureLoaders(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, IGdtQueryable& gdt) + { + auto& memory = *zone.GetMemory(); + + collection.AddAssetCreator(CreateRawPhysPresetLoader(memory, searchPath, zone)); + collection.AddAssetCreator(CreateGdtPhysPresetLoader(memory, searchPath, gdt, zone)); + collection.AddAssetCreator(CreateRawPhysConstraintsLoader(memory, searchPath, zone)); + collection.AddAssetCreator(CreateGdtPhysConstraintsLoader(memory, searchPath, gdt, zone)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateXModelLoader(memory, searchPath, zone)); + collection.AddAssetCreator(CreateMaterialLoader(memory, searchPath)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateImageLoader(memory, searchPath)); + collection.AddAssetCreator(CreateSoundBankLoader(memory, searchPath)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateFontIconLoader(memory, searchPath)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateLocalizeLoader(memory, searchPath, zone)); + collection.AddAssetCreator(CreateRawWeaponLoader(memory, searchPath, zone)); + collection.AddAssetCreator(CreateGdtWeaponLoader(memory, searchPath, gdt, zone)); + collection.AddAssetCreator(CreateRawAttachmentLoader(memory, searchPath, zone)); + collection.AddAssetCreator(CreateGdtAttachmentLoader(memory, searchPath, gdt, zone)); + collection.AddAssetCreator(CreateRawAttachmentUniqueLoader(memory, searchPath, zone)); + collection.AddAssetCreator(CreateGdtAttachmentUniqueLoader(memory, searchPath, gdt, zone)); + collection.AddAssetCreator(CreateWeaponCamoLoader(memory, searchPath)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateRawFileLoader(memory, searchPath)); + collection.AddAssetCreator(CreateStringTableLoader(memory, searchPath)); + collection.AddAssetCreator(CreateLeaderboardLoader(memory, searchPath)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateScriptLoader(memory, searchPath)); + collection.AddAssetCreator(CreateRawVehicleLoader(memory, searchPath, zone)); + collection.AddAssetCreator(CreateGdtVehicleLoader(memory, searchPath, gdt, zone)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateQdbLoader(memory, searchPath)); + collection.AddAssetCreator(CreateSlugLoader(memory, searchPath)); + // collection.AddAssetCreator(std::make_unique(memory)); + // collection.AddAssetCreator(std::make_unique(memory)); + collection.AddAssetCreator(CreateRawZBarrierLoader(memory, searchPath, zone)); + collection.AddAssetCreator(CreateGdtZBarrierLoader(memory, searchPath, gdt, zone)); + } + } // namespace + + void ObjLoader::ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, IGdtQueryable& gdt) const { - for (const auto& [type, loader] : m_asset_loaders_by_type) - loader->FinalizeAssetsForZone(context); + ConfigureDefaultCreators(collection, zone); + ConfigureLoaders(collection, zone, searchPath, gdt); + ConfigureGlobalAssetPoolsLoaders(collection, zone); } } // namespace T6 diff --git a/src/ObjLoading/Game/T6/ObjLoaderT6.h b/src/ObjLoading/Game/T6/ObjLoaderT6.h index 3e9aa741..6e210b85 100644 --- a/src/ObjLoading/Game/T6/ObjLoaderT6.h +++ b/src/ObjLoading/Game/T6/ObjLoaderT6.h @@ -1,6 +1,5 @@ #pragma once -#include "AssetLoading/IAssetLoader.h" #include "Game/T6/T6.h" #include "IObjLoader.h" #include "ObjContainer/SoundBank/SoundBank.h" @@ -10,20 +9,16 @@ #include #include #include -#include namespace T6 { class ObjLoader final : public IObjLoader { public: - ObjLoader(); - void LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const override; void UnloadContainersOfZone(Zone& zone) const override; - bool LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const override; - void FinalizeAssetsForZone(AssetLoadingContext& context) const override; + void ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, IGdtQueryable& gdt) const override; private: static bool VerifySoundBankChecksum(const SoundBank& soundBank, const SndRuntimeAssetBank& sndRuntimeAssetBank); @@ -41,7 +36,5 @@ namespace T6 static bool IsMpZone(const Zone& zone); static bool IsZmZone(const Zone& zone); - - std::unordered_map> m_asset_loaders_by_type; }; } // namespace T6 diff --git a/src/ObjLoading/Game/T6/PhysConstraints/GdtLoaderPhysConstraintsT6.cpp b/src/ObjLoading/Game/T6/PhysConstraints/GdtLoaderPhysConstraintsT6.cpp new file mode 100644 index 00000000..d6c35c5d --- /dev/null +++ b/src/ObjLoading/Game/T6/PhysConstraints/GdtLoaderPhysConstraintsT6.cpp @@ -0,0 +1,54 @@ +#include "GdtLoaderPhysConstraintsT6.h" + +#include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" +#include "InfoStringLoaderPhysConstraintsT6.h" + +#include +#include +#include + +using namespace T6; + +namespace +{ + class GdtLoaderPhysConstraints final : public AssetCreator + { + public: + GdtLoaderPhysConstraints(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + : m_gdt(gdt), + m_info_string_loader(memory, searchPath, zone) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto* gdtEntry = m_gdt.GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_WEAPON, assetName); + if (gdtEntry == nullptr) + return AssetCreationResult::NoAction(); + + InfoString infoString; + if (!infoString.FromGdtProperties(*gdtEntry)) + { + std::cerr << std::format("Failed to read phys constraints gdt entry: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + return m_info_string_loader.CreateAsset(assetName, infoString, context); + } + + private: + IGdtQueryable& m_gdt; + InfoStringLoaderPhysConstraints m_info_string_loader; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> + CreateGdtPhysConstraintsLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + { + return std::make_unique(memory, searchPath, gdt, zone); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/PhysConstraints/GdtLoaderPhysConstraintsT6.h b/src/ObjLoading/Game/T6/PhysConstraints/GdtLoaderPhysConstraintsT6.h new file mode 100644 index 00000000..45b70188 --- /dev/null +++ b/src/ObjLoading/Game/T6/PhysConstraints/GdtLoaderPhysConstraintsT6.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "Gdt/IGdtQueryable.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> + CreateGdtPhysConstraintsLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/PhysConstraints/InfoStringLoaderPhysConstraintsT6.cpp b/src/ObjLoading/Game/T6/PhysConstraints/InfoStringLoaderPhysConstraintsT6.cpp new file mode 100644 index 00000000..ab29df7e --- /dev/null +++ b/src/ObjLoading/Game/T6/PhysConstraints/InfoStringLoaderPhysConstraintsT6.cpp @@ -0,0 +1,110 @@ +#include "InfoStringLoaderPhysConstraintsT6.h" + +#include "Game/T6/InfoString/InfoStringToStructConverter.h" +#include "Game/T6/PhysConstraints/PhysConstraintsFields.h" +#include "Game/T6/T6.h" + +#include +#include +#include +#include +#include + +using namespace T6; + +namespace +{ + class InfoStringToPhysConstraintsConverter final : public InfoStringToStructConverter + { + protected: + bool ConvertExtensionField(const cspField_t& field, const std::string& value) override + { + switch (static_cast(field.iFieldType)) + { + case CFT_TYPE: + return ConvertEnumInt(field.szName, value, field.iOffset, s_constraintTypeNames, std::extent_v); + + default: + assert(false); + return false; + } + } + + public: + InfoStringToPhysConstraintsConverter(const InfoString& infoString, + PhysConstraints& physConstraints, + ZoneScriptStrings& zoneScriptStrings, + MemoryManager& memory, + AssetCreationContext& context, + AssetRegistration& registration, + const cspField_t* fields, + const size_t fieldCount) + : InfoStringToStructConverter(infoString, &physConstraints, zoneScriptStrings, memory, context, registration, fields, fieldCount) + { + } + }; + + void CalculatePhysConstraintsFields(PhysConstraints& physConstraints, ZoneScriptStrings& scriptStrings) + { + for (auto& constraint : physConstraints.data) + { + constraint.targetname = scriptStrings.AddOrGetScriptString(""); + constraint.target_ent1 = scriptStrings.AddOrGetScriptString(""); + constraint.target_ent2 = scriptStrings.AddOrGetScriptString(""); + constraint.attach_point_type1 = ATTACH_POINT_BONE; + constraint.attach_point_type2 = ATTACH_POINT_BONE; + constraint.target_bone1 = ""; + constraint.target_bone2 = ""; + } + + // count + { + auto foundEnd = false; + for (auto i = 0u; i < std::extent_v; i++) + { + if (physConstraints.data[i].type == CONSTRAINT_NONE) + { + foundEnd = true; + physConstraints.count = i; + break; + } + } + + if (!foundEnd) + physConstraints.count = std::extent_v; + } + } +} // namespace + +InfoStringLoaderPhysConstraints::InfoStringLoaderPhysConstraints(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_memory(memory), + m_search_path(searchPath), + m_zone(zone) +{ +} + +AssetCreationResult InfoStringLoaderPhysConstraints::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) +{ + auto* physConstraints = m_memory.Alloc(); + physConstraints->name = m_memory.Dup(assetName.c_str()); + + AssetRegistration registration(assetName, physConstraints); + InfoStringToPhysConstraintsConverter converter(infoString, + *physConstraints, + m_zone.m_script_strings, + m_memory, + context, + registration, + phys_constraints_fields, + std::extent_v); + if (!converter.Convert()) + { + std::cerr << std::format("Failed to parse phys constraints: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + CalculatePhysConstraintsFields(*physConstraints, m_zone.m_script_strings); + registration.AddScriptString(m_zone.m_script_strings.AddOrGetScriptString("")); + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); +} diff --git a/src/ObjLoading/Game/T6/PhysConstraints/InfoStringLoaderPhysConstraintsT6.h b/src/ObjLoading/Game/T6/PhysConstraints/InfoStringLoaderPhysConstraintsT6.h new file mode 100644 index 00000000..dbebb186 --- /dev/null +++ b/src/ObjLoading/Game/T6/PhysConstraints/InfoStringLoaderPhysConstraintsT6.h @@ -0,0 +1,21 @@ +#pragma once + +#include "Asset/AssetCreationContext.h" +#include "Asset/AssetCreationResult.h" +#include "InfoString/InfoString.h" + +namespace T6 +{ + class InfoStringLoaderPhysConstraints + { + public: + InfoStringLoaderPhysConstraints(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); + + AssetCreationResult CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context); + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + Zone& m_zone; + }; +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/PhysConstraints/RawLoaderPhysConstraintsT6.cpp b/src/ObjLoading/Game/T6/PhysConstraints/RawLoaderPhysConstraintsT6.cpp new file mode 100644 index 00000000..607a3c82 --- /dev/null +++ b/src/ObjLoading/Game/T6/PhysConstraints/RawLoaderPhysConstraintsT6.cpp @@ -0,0 +1,54 @@ +#include "RawLoaderPhysConstraintsT6.h" + +#include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" +#include "InfoStringLoaderPhysConstraintsT6.h" + +#include +#include +#include + +using namespace T6; + +namespace +{ + class RawLoaderPhysConstraints final : public AssetCreator + { + public: + RawLoaderPhysConstraints(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_search_path(searchPath), + m_info_string_loader(memory, searchPath, zone) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto fileName = std::format("physconstraints/{}", assetName); + const auto file = m_search_path.Open(fileName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + InfoString infoString; + if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_PHYS_CONSTRAINTS, *file.m_stream)) + { + std::cerr << std::format("Could not parse as info string file: \"{}\"\n", fileName); + return AssetCreationResult::Failure(); + } + + return m_info_string_loader.CreateAsset(assetName, infoString, context); + } + + private: + ISearchPath& m_search_path; + InfoStringLoaderPhysConstraints m_info_string_loader; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateRawPhysConstraintsLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + { + return std::make_unique(memory, searchPath, zone); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/PhysConstraints/RawLoaderPhysConstraintsT6.h b/src/ObjLoading/Game/T6/PhysConstraints/RawLoaderPhysConstraintsT6.h new file mode 100644 index 00000000..dc88bc45 --- /dev/null +++ b/src/ObjLoading/Game/T6/PhysConstraints/RawLoaderPhysConstraintsT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateRawPhysConstraintsLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/PhysPreset/GdtLoaderPhysPresetT6.cpp b/src/ObjLoading/Game/T6/PhysPreset/GdtLoaderPhysPresetT6.cpp new file mode 100644 index 00000000..9d7f179f --- /dev/null +++ b/src/ObjLoading/Game/T6/PhysPreset/GdtLoaderPhysPresetT6.cpp @@ -0,0 +1,53 @@ +#include "GdtLoaderPhysPresetT6.h" + +#include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" +#include "InfoStringLoaderPhysPresetT6.h" + +#include +#include +#include + +using namespace T6; + +namespace +{ + class GdtLoaderPhysPreset final : public AssetCreator + { + public: + GdtLoaderPhysPreset(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + : m_gdt(gdt), + m_info_string_loader(memory, searchPath, zone) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto* gdtEntry = m_gdt.GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_WEAPON, assetName); + if (gdtEntry == nullptr) + return AssetCreationResult::NoAction(); + + InfoString infoString; + if (!infoString.FromGdtProperties(*gdtEntry)) + { + std::cerr << std::format("Failed to read phys preset gdt entry: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + return m_info_string_loader.CreateAsset(assetName, infoString, context); + } + + private: + IGdtQueryable& m_gdt; + InfoStringLoaderPhysPreset m_info_string_loader; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateGdtPhysPresetLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + { + return std::make_unique(memory, searchPath, gdt, zone); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/PhysPreset/GdtLoaderPhysPresetT6.h b/src/ObjLoading/Game/T6/PhysPreset/GdtLoaderPhysPresetT6.h new file mode 100644 index 00000000..c2fdbe8d --- /dev/null +++ b/src/ObjLoading/Game/T6/PhysPreset/GdtLoaderPhysPresetT6.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "Gdt/IGdtQueryable.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateGdtPhysPresetLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/PhysPreset/InfoStringLoaderPhysPresetT6.cpp b/src/ObjLoading/Game/T6/PhysPreset/InfoStringLoaderPhysPresetT6.cpp new file mode 100644 index 00000000..fbd2b9d2 --- /dev/null +++ b/src/ObjLoading/Game/T6/PhysPreset/InfoStringLoaderPhysPresetT6.cpp @@ -0,0 +1,90 @@ +#include "InfoStringLoaderPhysPresetT6.h" + +#include "Game/T6/InfoString/InfoStringToStructConverter.h" +#include "Game/T6/PhysPreset/PhysPresetFields.h" +#include "Game/T6/T6.h" + +#include +#include +#include +#include +#include +#include + +using namespace T6; + +namespace +{ + class InfoStringToPhysPresetConverter final : public InfoStringToStructConverter + { + protected: + bool ConvertExtensionField(const cspField_t& field, const std::string& value) override + { + assert(false); + return false; + } + + public: + InfoStringToPhysPresetConverter(const InfoString& infoString, + PhysPresetInfo& physPreset, + ZoneScriptStrings& zoneScriptStrings, + MemoryManager& memory, + AssetCreationContext& context, + AssetRegistration& registration, + const cspField_t* fields, + const size_t fieldCount) + : InfoStringToStructConverter(infoString, &physPreset, zoneScriptStrings, memory, context, registration, fields, fieldCount) + { + } + }; + + void CopyFromPhysPresetInfo(const PhysPresetInfo& physPresetInfo, PhysPreset& physPreset) + { + physPreset.mass = std::clamp(physPresetInfo.mass, 1.0f, 2000.0f) * 0.001f; + physPreset.bounce = physPresetInfo.bounce; + + if (physPresetInfo.isFrictionInfinity != 0) + physPreset.friction = std::numeric_limits::infinity(); + else + physPreset.friction = physPresetInfo.friction; + + physPreset.bulletForceScale = physPresetInfo.bulletForceScale; + physPreset.explosiveForceScale = physPresetInfo.explosiveForceScale; + physPreset.piecesSpreadFraction = physPresetInfo.piecesSpreadFraction; + physPreset.piecesUpwardVelocity = physPresetInfo.piecesUpwardVelocity; + physPreset.canFloat = physPresetInfo.canFloat; + physPreset.gravityScale = std::clamp(physPresetInfo.gravityScale, 0.01f, 10.0f); + physPreset.centerOfMassOffset = physPresetInfo.centerOfMassOffset; + physPreset.buoyancyBoxMin = physPresetInfo.buoyancyBoxMin; + physPreset.buoyancyBoxMax = physPresetInfo.buoyancyBoxMax; + } +} // namespace + +InfoStringLoaderPhysPreset::InfoStringLoaderPhysPreset(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_memory(memory), + m_search_path(searchPath), + m_zone(zone) +{ +} + +AssetCreationResult InfoStringLoaderPhysPreset::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) +{ + auto* physPreset = m_memory.Alloc(); + physPreset->name = m_memory.Dup(assetName.c_str()); + + AssetRegistration registration(assetName, physPreset); + + PhysPresetInfo physPresetInfo; + memset(&physPresetInfo, 0, sizeof(physPresetInfo)); + InfoStringToPhysPresetConverter converter( + infoString, physPresetInfo, m_zone.m_script_strings, m_memory, context, registration, phys_preset_fields, std::extent_v); + if (!converter.Convert()) + { + std::cerr << std::format("Failed to parse phys preset: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + CopyFromPhysPresetInfo(physPresetInfo, *physPreset); + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); +} diff --git a/src/ObjLoading/Game/T6/PhysPreset/InfoStringLoaderPhysPresetT6.h b/src/ObjLoading/Game/T6/PhysPreset/InfoStringLoaderPhysPresetT6.h new file mode 100644 index 00000000..3e214d60 --- /dev/null +++ b/src/ObjLoading/Game/T6/PhysPreset/InfoStringLoaderPhysPresetT6.h @@ -0,0 +1,21 @@ +#pragma once + +#include "Asset/AssetCreationContext.h" +#include "Asset/AssetCreationResult.h" +#include "InfoString/InfoString.h" + +namespace T6 +{ + class InfoStringLoaderPhysPreset + { + public: + InfoStringLoaderPhysPreset(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); + + AssetCreationResult CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context); + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + Zone& m_zone; + }; +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/PhysPreset/RawLoaderPhysPresetT6.cpp b/src/ObjLoading/Game/T6/PhysPreset/RawLoaderPhysPresetT6.cpp new file mode 100644 index 00000000..4fe78db8 --- /dev/null +++ b/src/ObjLoading/Game/T6/PhysPreset/RawLoaderPhysPresetT6.cpp @@ -0,0 +1,54 @@ +#include "RawLoaderPhysPresetT6.h" + +#include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" +#include "InfoStringLoaderPhysPresetT6.h" + +#include +#include +#include + +using namespace T6; + +namespace +{ + class RawLoaderPhysPreset final : public AssetCreator + { + public: + RawLoaderPhysPreset(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_search_path(searchPath), + m_info_string_loader(memory, searchPath, zone) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto fileName = std::format("physic/{}", assetName); + const auto file = m_search_path.Open(fileName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + InfoString infoString; + if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_PHYS_PRESET, *file.m_stream)) + { + std::cerr << std::format("Could not parse as info string file: \"{}\"\n", fileName); + return AssetCreationResult::Failure(); + } + + return m_info_string_loader.CreateAsset(assetName, infoString, context); + } + + private: + ISearchPath& m_search_path; + InfoStringLoaderPhysPreset m_info_string_loader; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateRawPhysPresetLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + { + return std::make_unique(memory, searchPath, zone); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/PhysPreset/RawLoaderPhysPresetT6.h b/src/ObjLoading/Game/T6/PhysPreset/RawLoaderPhysPresetT6.h new file mode 100644 index 00000000..44070d9b --- /dev/null +++ b/src/ObjLoading/Game/T6/PhysPreset/RawLoaderPhysPresetT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateRawPhysPresetLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Qdb/LoaderQdbT6.cpp b/src/ObjLoading/Game/T6/Qdb/LoaderQdbT6.cpp new file mode 100644 index 00000000..e00e88ac --- /dev/null +++ b/src/ObjLoading/Game/T6/Qdb/LoaderQdbT6.cpp @@ -0,0 +1,53 @@ +#include "LoaderQdbT6.h" + +#include "Game/T6/T6.h" + +#include + +using namespace T6; + +namespace +{ + class QdbLoader final : public AssetCreator + { + public: + QdbLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto file = m_search_path.Open(assetName); + if (!file.IsOpen()) + return AssetCreationResult::Failure(); + + auto* qdb = m_memory.Alloc(); + qdb->name = m_memory.Dup(assetName.c_str()); + qdb->len = static_cast(file.m_length); + + auto* fileBuffer = m_memory.Alloc(static_cast(file.m_length + 1)); + file.m_stream->read(fileBuffer, file.m_length); + if (file.m_stream->gcount() != file.m_length) + return AssetCreationResult::Failure(); + fileBuffer[qdb->len] = '\0'; + + qdb->buffer = static_cast(fileBuffer); + + return AssetCreationResult::Success(context.AddAsset(assetName, qdb)); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateQdbLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Qdb/LoaderQdbT6.h b/src/ObjLoading/Game/T6/Qdb/LoaderQdbT6.h new file mode 100644 index 00000000..a8d5f9c9 --- /dev/null +++ b/src/ObjLoading/Game/T6/Qdb/LoaderQdbT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateQdbLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/RawFile/LoaderRawFileT6.cpp b/src/ObjLoading/Game/T6/RawFile/LoaderRawFileT6.cpp new file mode 100644 index 00000000..5e92aebc --- /dev/null +++ b/src/ObjLoading/Game/T6/RawFile/LoaderRawFileT6.cpp @@ -0,0 +1,123 @@ +#include "LoaderRawFileT6.h" + +#include "Game/T6/T6.h" +#include "Pool/GlobalAssetPool.h" + +#include +#include +#include +#include +#include +#include + +using namespace T6; +namespace fs = std::filesystem; + +namespace +{ + constexpr size_t COMPRESSED_BUFFER_SIZE_PADDING = 64; + + class RawFileLoader final : public AssetCreator + { + public: + RawFileLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto file = m_search_path.Open(assetName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + const fs::path rawFilePath(assetName); + const auto extension = rawFilePath.extension().string(); + + if (extension == ".atr") + return LoadAnimtree(file, assetName, context); + + return LoadDefault(file, assetName, context); + } + + private: + AssetCreationResult LoadAnimtree(const SearchPathOpenFile& file, const std::string& assetName, AssetCreationContext& context) + { + const auto uncompressedBuffer = std::make_unique(static_cast(file.m_length)); + file.m_stream->read(uncompressedBuffer.get(), file.m_length); + if (file.m_stream->gcount() != file.m_length) + return AssetCreationResult::Failure(); + + const auto compressionBufferSize = static_cast(file.m_length + sizeof(uint32_t) + COMPRESSED_BUFFER_SIZE_PADDING); + auto* compressedBuffer = m_memory.Alloc(compressionBufferSize); + + z_stream_s zs{}; + + zs.zalloc = Z_NULL; + zs.zfree = Z_NULL; + zs.opaque = Z_NULL; + zs.avail_in = static_cast(file.m_length); + zs.avail_out = compressionBufferSize; + zs.next_in = reinterpret_cast(uncompressedBuffer.get()); + zs.next_out = reinterpret_cast(&compressedBuffer[sizeof(uint32_t)]); + + int ret = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -DEF_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); + + if (ret != Z_OK) + { + throw std::runtime_error("Initializing deflate failed"); + } + + ret = deflate(&zs, Z_FINISH); + + if (ret != Z_STREAM_END) + { + std::cerr << std::format("Deflate failed for loading animtree file \"{}\"\n", assetName); + deflateEnd(&zs); + return AssetCreationResult::Failure(); + } + + const auto compressedSize = compressionBufferSize + sizeof(uint32_t) - zs.avail_out; + + reinterpret_cast(compressedBuffer)[0] = static_cast(file.m_length); // outLen + + auto* rawFile = m_memory.Alloc(); + rawFile->name = m_memory.Dup(assetName.c_str()); + rawFile->len = static_cast(compressedSize); + rawFile->buffer = static_cast(compressedBuffer); + + deflateEnd(&zs); + + return AssetCreationResult::Success(context.AddAsset(assetName, rawFile)); + } + + AssetCreationResult LoadDefault(const SearchPathOpenFile& file, const std::string& assetName, AssetCreationContext& context) + { + auto* rawFile = m_memory.Alloc(); + rawFile->name = m_memory.Dup(assetName.c_str()); + rawFile->len = static_cast(file.m_length); + + auto* fileBuffer = m_memory.Alloc(static_cast(file.m_length + 1)); + file.m_stream->read(fileBuffer, file.m_length); + if (file.m_stream->gcount() != file.m_length) + return AssetCreationResult::Failure(); + fileBuffer[rawFile->len] = '\0'; + + rawFile->buffer = static_cast(fileBuffer); + + return AssetCreationResult::Success(context.AddAsset(assetName, rawFile)); + } + + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/RawFile/LoaderRawFileT6.h b/src/ObjLoading/Game/T6/RawFile/LoaderRawFileT6.h new file mode 100644 index 00000000..db44f9a5 --- /dev/null +++ b/src/ObjLoading/Game/T6/RawFile/LoaderRawFileT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Script/LoaderScriptT6.cpp b/src/ObjLoading/Game/T6/Script/LoaderScriptT6.cpp new file mode 100644 index 00000000..5d30b473 --- /dev/null +++ b/src/ObjLoading/Game/T6/Script/LoaderScriptT6.cpp @@ -0,0 +1,53 @@ +#include "LoaderScriptT6.h" + +#include "Game/T6/T6.h" + +#include + +using namespace T6; + +namespace +{ + class ScriptLoader final : public AssetCreator + { + public: + ScriptLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto file = m_search_path.Open(assetName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + auto* scriptParseTree = m_memory.Alloc(); + scriptParseTree->name = m_memory.Dup(assetName.c_str()); + scriptParseTree->len = static_cast(file.m_length); + + auto* fileBuffer = m_memory.Alloc(static_cast(file.m_length + 1)); + file.m_stream->read(fileBuffer, file.m_length); + if (file.m_stream->gcount() != file.m_length) + return AssetCreationResult::Failure(); + fileBuffer[scriptParseTree->len] = '\0'; + + scriptParseTree->buffer = static_cast(fileBuffer); + + return AssetCreationResult::Success(context.AddAsset(assetName, scriptParseTree)); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateScriptLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Script/LoaderScriptT6.h b/src/ObjLoading/Game/T6/Script/LoaderScriptT6.h new file mode 100644 index 00000000..754da2ec --- /dev/null +++ b/src/ObjLoading/Game/T6/Script/LoaderScriptT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateScriptLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Slug/LoaderSlugT6.cpp b/src/ObjLoading/Game/T6/Slug/LoaderSlugT6.cpp new file mode 100644 index 00000000..f527a521 --- /dev/null +++ b/src/ObjLoading/Game/T6/Slug/LoaderSlugT6.cpp @@ -0,0 +1,53 @@ +#include "LoaderSlugT6.h" + +#include "Game/T6/T6.h" + +#include + +using namespace T6; + +namespace +{ + class SlugLoader final : public AssetCreator + { + public: + SlugLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto file = m_search_path.Open(assetName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + auto* slug = m_memory.Alloc(); + slug->name = m_memory.Dup(assetName.c_str()); + slug->len = static_cast(file.m_length); + + auto* fileBuffer = m_memory.Alloc(static_cast(file.m_length + 1)); + file.m_stream->read(fileBuffer, file.m_length); + if (file.m_stream->gcount() != file.m_length) + return AssetCreationResult::Failure(); + fileBuffer[slug->len] = '\0'; + + slug->buffer = static_cast(fileBuffer); + + return AssetCreationResult::Success(context.AddAsset(assetName, slug)); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateSlugLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Slug/LoaderSlugT6.h b/src/ObjLoading/Game/T6/Slug/LoaderSlugT6.h new file mode 100644 index 00000000..49da9e84 --- /dev/null +++ b/src/ObjLoading/Game/T6/Slug/LoaderSlugT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateSlugLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSoundBank.cpp b/src/ObjLoading/Game/T6/Sound/LoaderSoundBankT6.cpp similarity index 85% rename from src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSoundBank.cpp rename to src/ObjLoading/Game/T6/Sound/LoaderSoundBankT6.cpp index f42fe26e..aab25cb4 100644 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderSoundBank.cpp +++ b/src/ObjLoading/Game/T6/Sound/LoaderSoundBankT6.cpp @@ -1,4 +1,4 @@ -#include "AssetLoaderSoundBank.h" +#include "LoaderSoundBankT6.h" #include "Csv/CsvHeaderRow.h" #include "Csv/CsvStream.h" @@ -859,7 +859,7 @@ namespace return true; } - bool LoadSoundDuckList(ISearchPath* searchPath, MemoryManager& memory, SndBank* sndBank, const SearchPathOpenFile& file) + bool LoadSoundDuckList(ISearchPath& searchPath, MemoryManager& memory, SndBank* sndBank, const SearchPathOpenFile& file) { const CsvInputStream csv(*file.m_stream); CsvHeaderRow headerRow; @@ -879,7 +879,7 @@ namespace if (name.empty()) return false; - const auto duckFile = searchPath->Open(std::format("soundbank/ducks/{}.duk", name)); + const auto duckFile = searchPath.Open(std::format("soundbank/ducks/{}.duk", name)); if (!duckFile.IsOpen()) { std::cerr << std::format("Unable to find .duk file for {} in ducklist for sound bank {}\n", name, sndBank->name); @@ -930,151 +930,159 @@ namespace return true; } + + class SoundBankLoader final : public AssetCreator + { + public: + SoundBankLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + if (assetName.find('.') == std::string::npos) + { + std::cerr << "A language must be specific in the sound bank asset name! (Ex: mpl_common.all)\n"; + return AssetCreationResult::Failure(); + } + + const auto aliasFile = m_search_path.Open(std::format("soundbank/{}.aliases.csv", assetName)); + if (!aliasFile.IsOpen()) + return AssetCreationResult::NoAction(); + + auto* sndBank = m_memory.Alloc(); + sndBank->name = m_memory.Dup(assetName.c_str()); + + const auto sndBankLocalization = utils::StringSplit(assetName, '.'); + + unsigned loadedEntryCount = 0u, streamedEntryCount = 0u; + if (!LoadSoundAliasList(m_memory, sndBank, aliasFile, loadedEntryCount, streamedEntryCount)) + return AssetCreationResult::Failure(); + + if (!LoadSoundAliasIndexList(m_memory, sndBank)) + return AssetCreationResult::Failure(); + + const auto radverbFile = m_search_path.Open(std::format("soundbank/{}.reverbs.csv", assetName)); + if (radverbFile.IsOpen()) + { + if (!LoadSoundRadverbs(m_memory, sndBank, radverbFile)) + { + std::cerr << std::format("Sound bank reverbs file for {} is invalid\n", assetName); + return AssetCreationResult::Failure(); + } + } + + const auto duckListFile = m_search_path.Open(std::format("soundbank/{}.ducklist.csv", assetName)); + if (duckListFile.IsOpen()) + { + if (!LoadSoundDuckList(m_search_path, m_memory, sndBank, duckListFile)) + { + std::cerr << std::format("Sound bank ducklist file for {} is invalid\n", assetName); + return AssetCreationResult::Failure(); + } + } + + std::unique_ptr sablStream, sabsStream; + std::unique_ptr sablWriter, sabsWriter; + + if (loadedEntryCount > 0) + { + sndBank->loadAssetBank.zone = m_memory.Dup(sndBankLocalization.at(0).c_str()); + sndBank->loadAssetBank.language = m_memory.Dup(sndBankLocalization.at(1).c_str()); + memset(sndBank->loadAssetBank.linkTimeChecksum, 0xCC, 16); + + sndBank->loadedAssets.loadedCount = 0; + sndBank->loadedAssets.zone = m_memory.Dup(sndBankLocalization.at(0).c_str()); + sndBank->loadedAssets.language = m_memory.Dup(sndBankLocalization.at(1).c_str()); + sndBank->loadedAssets.entryCount = loadedEntryCount; + sndBank->loadedAssets.entries = m_memory.Alloc(loadedEntryCount); + + sndBank->runtimeAssetLoad = true; + + const auto sablName = std::format("{}.sabl", assetName); + sablStream = OpenSoundBankOutputFile(sablName); + if (sablStream) + sablWriter = SoundBankWriter::Create(sablName, *sablStream, m_search_path); + } + + if (streamedEntryCount > 0) + { + sndBank->streamAssetBank.zone = m_memory.Dup(sndBankLocalization.at(0).c_str()); + sndBank->streamAssetBank.language = m_memory.Dup(sndBankLocalization.at(1).c_str()); + memset(sndBank->streamAssetBank.linkTimeChecksum, 0xCC, 16); + + const auto sabsName = std::format("{}.sabs", assetName); + sabsStream = OpenSoundBankOutputFile(sabsName); + if (sabsStream) + sabsWriter = SoundBankWriter::Create(sabsName, *sabsStream, m_search_path); + } + + // add aliases to the correct sound bank writer + for (auto i = 0u; i < sndBank->aliasCount; i++) + { + const auto* aliasList = &sndBank->alias[i]; + for (auto j = 0; j < aliasList->count; j++) + { + const auto* alias = &aliasList->head[j]; + + if (alias->assetFileName && alias->assetId) + { + if (sabsWriter && alias->flags.loadType == SA_STREAMED) + sabsWriter->AddSound(GetSoundFilePath(alias), alias->assetId, alias->flags.looping, true); + else if (sablWriter) + sablWriter->AddSound(GetSoundFilePath(alias), alias->assetId, alias->flags.looping); + } + } + } + + // write the output linked sound bank + if (sablWriter) + { + size_t dataSize = 0u; + const auto result = sablWriter->Write(dataSize); + sablStream->close(); + + if (result) + { + sndBank->loadedAssets.dataSize = dataSize; + sndBank->loadedAssets.data = m_memory.Alloc(dataSize); + } + else + { + std::cerr << std::format("Loaded sound bank for {} failed to generate. Please check your build files.\n", assetName); + return AssetCreationResult::Failure(); + } + } + + // write the output streamed sound bank + if (sabsWriter) + { + size_t dataSize = 0u; + const auto result = sabsWriter->Write(dataSize); + sabsStream->close(); + + if (!result) + { + std::cerr << std::format("Streamed sound bank for {} failed to generate. Please check your build files.\n", assetName); + return AssetCreationResult::Failure(); + } + } + + return AssetCreationResult::Success(context.AddAsset(assetName, sndBank)); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; } // namespace -void* AssetLoaderSoundBank::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) +namespace T6 { - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} - -bool AssetLoaderSoundBank::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderSoundBank::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - if (assetName.find('.') == std::string::npos) + std::unique_ptr> CreateSoundBankLoader(MemoryManager& memory, ISearchPath& searchPath) { - std::cerr << "A language must be specific in the sound bank asset name! (Ex: mpl_common.all)\n"; - return false; + return std::make_unique(memory, searchPath); } - - const auto aliasFile = searchPath->Open(std::format("soundbank/{}.aliases.csv", assetName)); - if (!aliasFile.IsOpen()) - return false; - - auto* sndBank = memory->Alloc(); - - sndBank->name = memory->Dup(assetName.c_str()); - const auto sndBankLocalization = utils::StringSplit(assetName, '.'); - - unsigned loadedEntryCount = 0u, streamedEntryCount = 0u; - if (!LoadSoundAliasList(*memory, sndBank, aliasFile, loadedEntryCount, streamedEntryCount)) - return false; - - if (!LoadSoundAliasIndexList(*memory, sndBank)) - return false; - - const auto radverbFile = searchPath->Open(std::format("soundbank/{}.reverbs.csv", assetName)); - if (radverbFile.IsOpen()) - { - if (!LoadSoundRadverbs(*memory, sndBank, radverbFile)) - { - std::cerr << std::format("Sound bank reverbs file for {} is invalid\n", assetName); - return false; - } - } - - const auto duckListFile = searchPath->Open(std::format("soundbank/{}.ducklist.csv", assetName)); - if (duckListFile.IsOpen()) - { - if (!LoadSoundDuckList(searchPath, *memory, sndBank, duckListFile)) - { - std::cerr << std::format("Sound bank ducklist file for {} is invalid\n", assetName); - return false; - } - } - - std::unique_ptr sablStream, sabsStream; - std::unique_ptr sablWriter, sabsWriter; - - if (loadedEntryCount > 0) - { - sndBank->loadAssetBank.zone = memory->Dup(sndBankLocalization.at(0).c_str()); - sndBank->loadAssetBank.language = memory->Dup(sndBankLocalization.at(1).c_str()); - memset(sndBank->loadAssetBank.linkTimeChecksum, 0xCC, 16); - - sndBank->loadedAssets.loadedCount = 0; - sndBank->loadedAssets.zone = memory->Dup(sndBankLocalization.at(0).c_str()); - sndBank->loadedAssets.language = memory->Dup(sndBankLocalization.at(1).c_str()); - sndBank->loadedAssets.entryCount = loadedEntryCount; - sndBank->loadedAssets.entries = memory->Alloc(loadedEntryCount); - - sndBank->runtimeAssetLoad = true; - - const auto sablName = std::format("{}.sabl", assetName); - sablStream = OpenSoundBankOutputFile(sablName); - if (sablStream) - sablWriter = SoundBankWriter::Create(sablName, *sablStream, searchPath); - } - - if (streamedEntryCount > 0) - { - sndBank->streamAssetBank.zone = memory->Dup(sndBankLocalization.at(0).c_str()); - sndBank->streamAssetBank.language = memory->Dup(sndBankLocalization.at(1).c_str()); - memset(sndBank->streamAssetBank.linkTimeChecksum, 0xCC, 16); - - const auto sabsName = std::format("{}.sabs", assetName); - sabsStream = OpenSoundBankOutputFile(sabsName); - if (sabsStream) - sabsWriter = SoundBankWriter::Create(sabsName, *sabsStream, searchPath); - } - - // add aliases to the correct sound bank writer - for (auto i = 0u; i < sndBank->aliasCount; i++) - { - const auto* aliasList = &sndBank->alias[i]; - for (auto j = 0; j < aliasList->count; j++) - { - const auto* alias = &aliasList->head[j]; - - if (alias->assetFileName && alias->assetId) - { - if (sabsWriter && alias->flags.loadType == SA_STREAMED) - sabsWriter->AddSound(GetSoundFilePath(alias), alias->assetId, alias->flags.looping, true); - else if (sablWriter) - sablWriter->AddSound(GetSoundFilePath(alias), alias->assetId, alias->flags.looping); - } - } - } - - // write the output linked sound bank - if (sablWriter) - { - size_t dataSize = 0u; - const auto result = sablWriter->Write(dataSize); - sablStream->close(); - - if (result) - { - sndBank->loadedAssets.dataSize = dataSize; - sndBank->loadedAssets.data = memory->Alloc(dataSize); - } - else - { - std::cerr << std::format("Loaded sound bank for {} failed to generate. Please check your build files.\n", assetName); - return false; - } - } - - // write the output streamed sound bank - if (sabsWriter) - { - size_t dataSize = 0u; - const auto result = sabsWriter->Write(dataSize); - sabsStream->close(); - - if (!result) - { - std::cerr << std::format("Streamed sound bank for {} failed to generate. Please check your build files.\n", assetName); - return false; - } - } - - manager->AddAsset(assetName, sndBank); - return true; -} +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Sound/LoaderSoundBankT6.h b/src/ObjLoading/Game/T6/Sound/LoaderSoundBankT6.h new file mode 100644 index 00000000..6e99e962 --- /dev/null +++ b/src/ObjLoading/Game/T6/Sound/LoaderSoundBankT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateSoundBankLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/StringTable/LoaderStringTableT6.cpp b/src/ObjLoading/Game/T6/StringTable/LoaderStringTableT6.cpp new file mode 100644 index 00000000..d9560241 --- /dev/null +++ b/src/ObjLoading/Game/T6/StringTable/LoaderStringTableT6.cpp @@ -0,0 +1,47 @@ +#include "LoaderStringTableT6.h" + +#include "Csv/CsvStream.h" +#include "Game/T6/CommonT6.h" +#include "Game/T6/T6.h" +#include "StringTable/StringTableLoader.h" + +#include + +using namespace T6; + +namespace +{ + class StringTableLoader final : public AssetCreator + { + public: + StringTableLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto file = m_search_path.Open(assetName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + string_table::StringTableLoaderV3 loader; + auto* stringTable = loader.LoadFromStream(assetName, m_memory, *file.m_stream); + + return AssetCreationResult::Success(context.AddAsset(assetName, stringTable)); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/StringTable/LoaderStringTableT6.h b/src/ObjLoading/Game/T6/StringTable/LoaderStringTableT6.h new file mode 100644 index 00000000..7db144c6 --- /dev/null +++ b/src/ObjLoading/Game/T6/StringTable/LoaderStringTableT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Tracer/GdtLoaderTracerT6.cpp b/src/ObjLoading/Game/T6/Tracer/GdtLoaderTracerT6.cpp new file mode 100644 index 00000000..ee7376ed --- /dev/null +++ b/src/ObjLoading/Game/T6/Tracer/GdtLoaderTracerT6.cpp @@ -0,0 +1,53 @@ +#include "GdtLoaderTracerT6.h" + +#include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" +#include "InfoStringLoaderTracerT6.h" + +#include +#include +#include + +using namespace T6; + +namespace +{ + class GdtLoaderTracer final : public AssetCreator + { + public: + GdtLoaderTracer(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + : m_gdt(gdt), + m_info_string_loader(memory, searchPath, zone) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto* gdtEntry = m_gdt.GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_TRACER, assetName); + if (gdtEntry == nullptr) + return AssetCreationResult::NoAction(); + + InfoString infoString; + if (!infoString.FromGdtProperties(*gdtEntry)) + { + std::cerr << std::format("Failed to read tracer gdt entry: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + return m_info_string_loader.CreateAsset(assetName, infoString, context); + } + + private: + IGdtQueryable& m_gdt; + InfoStringLoaderTracer m_info_string_loader; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateGdtTracerLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + { + return std::make_unique(memory, searchPath, gdt, zone); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Tracer/GdtLoaderTracerT6.h b/src/ObjLoading/Game/T6/Tracer/GdtLoaderTracerT6.h new file mode 100644 index 00000000..d3059ce3 --- /dev/null +++ b/src/ObjLoading/Game/T6/Tracer/GdtLoaderTracerT6.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "Gdt/IGdtQueryable.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateGdtTracerLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Tracer/InfoStringLoaderTracerT6.cpp b/src/ObjLoading/Game/T6/Tracer/InfoStringLoaderTracerT6.cpp new file mode 100644 index 00000000..00c21757 --- /dev/null +++ b/src/ObjLoading/Game/T6/Tracer/InfoStringLoaderTracerT6.cpp @@ -0,0 +1,72 @@ +#include "InfoStringLoaderTracerT6.h" + +#include "Game/T6/InfoString/InfoStringToStructConverter.h" +#include "Game/T6/T6.h" +#include "Game/T6/Tracer/TracerFields.h" + +#include +#include +#include +#include +#include + +using namespace T6; + +namespace +{ + class InfoStringToTracerConverter final : public InfoStringToStructConverter + { + protected: + bool ConvertExtensionField(const cspField_t& field, const std::string& value) override + { + switch (static_cast(field.iFieldType)) + { + case TFT_TRACERTYPE: + return ConvertEnumInt(field.szName, value, field.iOffset, tracerTypeNames, std::extent_v); + + case TFT_NUM_FIELD_TYPES: + default: + assert(false); + return false; + } + } + + public: + InfoStringToTracerConverter(const InfoString& infoString, + TracerDef& tracer, + ZoneScriptStrings& zoneScriptStrings, + MemoryManager& memory, + AssetCreationContext& context, + AssetRegistration& registration, + const cspField_t* fields, + const size_t fieldCount) + : InfoStringToStructConverter(infoString, &tracer, zoneScriptStrings, memory, context, registration, fields, fieldCount) + { + } + }; +} // namespace + +InfoStringLoaderTracer::InfoStringLoaderTracer(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_memory(memory), + m_search_path(searchPath), + m_zone(zone) +{ +} + +AssetCreationResult InfoStringLoaderTracer::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) +{ + auto* tracer = m_memory.Alloc(); + tracer->name = m_memory.Dup(assetName.c_str()); + + AssetRegistration registration(assetName, tracer); + + InfoStringToTracerConverter converter( + infoString, *tracer, m_zone.m_script_strings, m_memory, context, registration, tracer_fields, std::extent_v); + if (!converter.Convert()) + { + std::cerr << std::format("Failed to parse tracer: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); +} diff --git a/src/ObjLoading/Game/T6/Tracer/InfoStringLoaderTracerT6.h b/src/ObjLoading/Game/T6/Tracer/InfoStringLoaderTracerT6.h new file mode 100644 index 00000000..141c8216 --- /dev/null +++ b/src/ObjLoading/Game/T6/Tracer/InfoStringLoaderTracerT6.h @@ -0,0 +1,21 @@ +#pragma once + +#include "Asset/AssetCreationContext.h" +#include "Asset/AssetCreationResult.h" +#include "InfoString/InfoString.h" + +namespace T6 +{ + class InfoStringLoaderTracer + { + public: + InfoStringLoaderTracer(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); + + AssetCreationResult CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context); + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + Zone& m_zone; + }; +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Tracer/RawLoaderTracerT6.cpp b/src/ObjLoading/Game/T6/Tracer/RawLoaderTracerT6.cpp new file mode 100644 index 00000000..16eb7ea9 --- /dev/null +++ b/src/ObjLoading/Game/T6/Tracer/RawLoaderTracerT6.cpp @@ -0,0 +1,54 @@ +#include "RawLoaderTracerT6.h" + +#include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" +#include "InfoStringLoaderTracerT6.h" + +#include +#include +#include + +using namespace T6; + +namespace +{ + class RawLoaderTracer final : public AssetCreator + { + public: + RawLoaderTracer(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_search_path(searchPath), + m_info_string_loader(memory, searchPath, zone) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto fileName = std::format("tracer/{}", assetName); + const auto file = m_search_path.Open(fileName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + InfoString infoString; + if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_TRACER, *file.m_stream)) + { + std::cerr << std::format("Could not parse as info string file: \"{}\"\n", fileName); + return AssetCreationResult::Failure(); + } + + return m_info_string_loader.CreateAsset(assetName, infoString, context); + } + + private: + ISearchPath& m_search_path; + InfoStringLoaderTracer m_info_string_loader; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateRawTracerLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + { + return std::make_unique(memory, searchPath, zone); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Tracer/RawLoaderTracerT6.h b/src/ObjLoading/Game/T6/Tracer/RawLoaderTracerT6.h new file mode 100644 index 00000000..a41e74c2 --- /dev/null +++ b/src/ObjLoading/Game/T6/Tracer/RawLoaderTracerT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateRawTracerLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Vehicle/GdtLoaderVehicleT6.cpp b/src/ObjLoading/Game/T6/Vehicle/GdtLoaderVehicleT6.cpp new file mode 100644 index 00000000..7b224773 --- /dev/null +++ b/src/ObjLoading/Game/T6/Vehicle/GdtLoaderVehicleT6.cpp @@ -0,0 +1,53 @@ +#include "GdtLoaderVehicleT6.h" + +#include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" +#include "InfoStringLoaderVehicleT6.h" + +#include +#include +#include + +using namespace T6; + +namespace +{ + class GdtLoaderVehicle final : public AssetCreator + { + public: + GdtLoaderVehicle(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + : m_gdt(gdt), + m_info_string_loader(memory, searchPath, zone) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto* gdtEntry = m_gdt.GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_VEHICLE, assetName); + if (gdtEntry == nullptr) + return AssetCreationResult::NoAction(); + + InfoString infoString; + if (!infoString.FromGdtProperties(*gdtEntry)) + { + std::cerr << std::format("Failed to read vehicle gdt entry: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + return m_info_string_loader.CreateAsset(assetName, infoString, context); + } + + private: + IGdtQueryable& m_gdt; + InfoStringLoaderVehicle m_info_string_loader; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateGdtVehicleLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + { + return std::make_unique(memory, searchPath, gdt, zone); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Vehicle/GdtLoaderVehicleT6.h b/src/ObjLoading/Game/T6/Vehicle/GdtLoaderVehicleT6.h new file mode 100644 index 00000000..fee2a56d --- /dev/null +++ b/src/ObjLoading/Game/T6/Vehicle/GdtLoaderVehicleT6.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "Gdt/IGdtQueryable.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateGdtVehicleLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderVehicle.cpp b/src/ObjLoading/Game/T6/Vehicle/InfoStringLoaderVehicleT6.cpp similarity index 50% rename from src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderVehicle.cpp rename to src/ObjLoading/Game/T6/Vehicle/InfoStringLoaderVehicleT6.cpp index 2b36b60c..4999f0bb 100644 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderVehicle.cpp +++ b/src/ObjLoading/Game/T6/Vehicle/InfoStringLoaderVehicleT6.cpp @@ -1,19 +1,18 @@ -#include "AssetLoaderVehicle.h" +#include "InfoStringLoaderVehicleT6.h" -#include "Game/T6/InfoString/EnumStrings.h" #include "Game/T6/InfoString/InfoStringToStructConverter.h" -#include "Game/T6/InfoString/VehicleFields.h" -#include "Game/T6/ObjConstantsT6.h" #include "Game/T6/T6.h" -#include "InfoString/InfoString.h" -#include "Pool/GlobalAssetPool.h" +#include "Game/T6/Vehicle/VehicleFields.h" +#include #include +#include #include +#include using namespace T6; -namespace T6 +namespace { class InfoStringToVehicleConverter final : public InfoStringToStructConverter { @@ -38,7 +37,7 @@ namespace T6 if (endPtr != &value[value.size()]) { - std::cout << "Failed to parse value \"" << value << "\" as mph\n"; + std::cerr << std::format("Failed to parse value \"{}\" as mph\n", value); return false; } @@ -52,7 +51,7 @@ namespace T6 if (endPtr != &value[value.size()]) { - std::cout << "Failed to parse value \"" << value << "\" as pounds\n"; + std::cerr << std::format("Failed to parse value \"{}\" as pounds\n", value); return false; } @@ -80,14 +79,13 @@ namespace T6 } *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = TEAM_BAD; - std::cout << "Failed to parse value \"" << value << "\" as team\n"; + std::cerr << std::format("Failed to parse value \"{}\" as team\n", value); return false; } case VFT_KEY_BINDING: case VFT_GRAPH: case VFT_WIIUCONTROLOVERRIDE: - case VFT_NUM: default: assert(false); return false; @@ -96,87 +94,40 @@ namespace T6 public: InfoStringToVehicleConverter(const InfoString& infoString, - VehicleDef* vehicleDef, + VehicleDef& vehicleDef, ZoneScriptStrings& zoneScriptStrings, - MemoryManager* memory, - IAssetLoadingManager* manager, + MemoryManager& memory, + AssetCreationContext& context, + AssetRegistration& registration, const cspField_t* fields, const size_t fieldCount) - : InfoStringToStructConverter(infoString, vehicleDef, zoneScriptStrings, memory, manager, fields, fieldCount) + : InfoStringToStructConverter(infoString, &vehicleDef, zoneScriptStrings, memory, context, registration, fields, fieldCount) { } }; -} // namespace T6 +} // namespace -bool AssetLoaderVehicle::LoadFromInfoString( - const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) +InfoStringLoaderVehicle::InfoStringLoaderVehicle(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_memory(memory), + m_search_path(searchPath), + m_zone(zone) { - auto* vehicleDef = memory->Create(); - memset(vehicleDef, 0, sizeof(VehicleDef)); +} + +AssetCreationResult InfoStringLoaderVehicle::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) +{ + auto* vehicleDef = m_memory.Alloc(); + vehicleDef->name = m_memory.Dup(assetName.c_str()); + + AssetRegistration registration(assetName, vehicleDef); InfoStringToVehicleConverter converter( - infoString, vehicleDef, zone->m_script_strings, memory, manager, vehicle_fields, std::extent_v); + infoString, *vehicleDef, m_zone.m_script_strings, m_memory, context, registration, vehicle_fields, std::extent_v); if (!converter.Convert()) { - std::cout << "Failed to parse vehicle: \"" << assetName << "\"\n"; - return true; + std::cerr << std::format("Failed to parse vehicle: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); } - vehicleDef->name = memory->Dup(assetName.c_str()); - - manager->AddAsset(assetName, vehicleDef, converter.GetDependencies(), converter.GetUsedScriptStrings()); - - return true; -} - -void* AssetLoaderVehicle::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) -{ - auto* asset = memory->Alloc(); - asset->name = memory->Dup(assetName.c_str()); - return asset; -} - -bool AssetLoaderVehicle::CanLoadFromGdt() const -{ - return true; -} - -bool AssetLoaderVehicle::LoadFromGdt( - const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_VEHICLE, assetName); - if (gdtEntry == nullptr) - return false; - - InfoString infoString; - if (!infoString.FromGdtProperties(*gdtEntry)) - { - std::cout << "Failed to read vehicle gdt entry: \"" << assetName << "\"\n"; - return true; - } - - return LoadFromInfoString(infoString, assetName, memory, manager, zone); -} - -bool AssetLoaderVehicle::CanLoadFromRaw() const -{ - return true; -} - -bool AssetLoaderVehicle::LoadFromRaw( - const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const -{ - const auto fileName = "vehicles/" + assetName; - const auto file = searchPath->Open(fileName); - if (!file.IsOpen()) - return false; - - InfoString infoString; - if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_VEHICLE, *file.m_stream)) - { - std::cerr << "Could not parse as info string file: \"" << fileName << "\"\n"; - return true; - } - - return LoadFromInfoString(infoString, assetName, memory, manager, zone); + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); } diff --git a/src/ObjLoading/Game/T6/Vehicle/InfoStringLoaderVehicleT6.h b/src/ObjLoading/Game/T6/Vehicle/InfoStringLoaderVehicleT6.h new file mode 100644 index 00000000..9aed730e --- /dev/null +++ b/src/ObjLoading/Game/T6/Vehicle/InfoStringLoaderVehicleT6.h @@ -0,0 +1,21 @@ +#pragma once + +#include "Asset/AssetCreationContext.h" +#include "Asset/AssetCreationResult.h" +#include "InfoString/InfoString.h" + +namespace T6 +{ + class InfoStringLoaderVehicle + { + public: + InfoStringLoaderVehicle(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); + + AssetCreationResult CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context); + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + Zone& m_zone; + }; +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Vehicle/RawLoaderVehicleT6.cpp b/src/ObjLoading/Game/T6/Vehicle/RawLoaderVehicleT6.cpp new file mode 100644 index 00000000..68a8299e --- /dev/null +++ b/src/ObjLoading/Game/T6/Vehicle/RawLoaderVehicleT6.cpp @@ -0,0 +1,54 @@ +#include "RawLoaderVehicleT6.h" + +#include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" +#include "InfoStringLoaderVehicleT6.h" + +#include +#include +#include + +using namespace T6; + +namespace +{ + class RawLoaderVehicle final : public AssetCreator + { + public: + RawLoaderVehicle(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_search_path(searchPath), + m_info_string_loader(memory, searchPath, zone) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto fileName = std::format("vehicles/{}", assetName); + const auto file = m_search_path.Open(fileName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + InfoString infoString; + if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_VEHICLE, *file.m_stream)) + { + std::cerr << std::format("Could not parse as info string file: \"{}\"\n", fileName); + return AssetCreationResult::Failure(); + } + + return m_info_string_loader.CreateAsset(assetName, infoString, context); + } + + private: + ISearchPath& m_search_path; + InfoStringLoaderVehicle m_info_string_loader; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateRawVehicleLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + { + return std::make_unique(memory, searchPath, zone); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Vehicle/RawLoaderVehicleT6.h b/src/ObjLoading/Game/T6/Vehicle/RawLoaderVehicleT6.h new file mode 100644 index 00000000..e88d6909 --- /dev/null +++ b/src/ObjLoading/Game/T6/Vehicle/RawLoaderVehicleT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateRawVehicleLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Weapon/GdtLoaderAttachmentT6.cpp b/src/ObjLoading/Game/T6/Weapon/GdtLoaderAttachmentT6.cpp new file mode 100644 index 00000000..ceecfd7f --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/GdtLoaderAttachmentT6.cpp @@ -0,0 +1,53 @@ +#include "GdtLoaderAttachmentT6.h" + +#include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" +#include "InfoStringLoaderAttachmentT6.h" + +#include +#include +#include + +using namespace T6; + +namespace +{ + class GdtLoaderAttachment final : public AssetCreator + { + public: + GdtLoaderAttachment(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + : m_gdt(gdt), + m_info_string_loader(memory, searchPath, zone) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto* gdtEntry = m_gdt.GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_WEAPON_ATTACHMENT, assetName); + if (gdtEntry == nullptr) + return AssetCreationResult::NoAction(); + + InfoString infoString; + if (!infoString.FromGdtProperties(*gdtEntry)) + { + std::cerr << std::format("Failed to read attachment gdt entry: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + return m_info_string_loader.CreateAsset(assetName, infoString, context); + } + + private: + IGdtQueryable& m_gdt; + InfoStringLoaderAttachment m_info_string_loader; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateGdtAttachmentLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + { + return std::make_unique(memory, searchPath, gdt, zone); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Weapon/GdtLoaderAttachmentT6.h b/src/ObjLoading/Game/T6/Weapon/GdtLoaderAttachmentT6.h new file mode 100644 index 00000000..6455b204 --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/GdtLoaderAttachmentT6.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "Gdt/IGdtQueryable.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateGdtAttachmentLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Weapon/GdtLoaderAttachmentUniqueT6.cpp b/src/ObjLoading/Game/T6/Weapon/GdtLoaderAttachmentUniqueT6.cpp new file mode 100644 index 00000000..ab53d947 --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/GdtLoaderAttachmentUniqueT6.cpp @@ -0,0 +1,54 @@ +#include "GdtLoaderAttachmentUniqueT6.h" + +#include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" +#include "InfoStringLoaderAttachmentUniqueT6.h" + +#include +#include +#include + +using namespace T6; + +namespace +{ + class GdtLoaderAttachmentUnique final : public AssetCreator + { + public: + GdtLoaderAttachmentUnique(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + : m_gdt(gdt), + m_info_string_loader(memory, searchPath, zone) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto* gdtEntry = m_gdt.GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_WEAPON_ATTACHMENT_UNIQUE, assetName); + if (gdtEntry == nullptr) + return AssetCreationResult::NoAction(); + + InfoString infoString; + if (!infoString.FromGdtProperties(*gdtEntry)) + { + std::cerr << std::format("Failed to read attachment unique gdt entry: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + return m_info_string_loader.CreateAsset(assetName, infoString, context); + } + + private: + IGdtQueryable& m_gdt; + InfoStringLoaderAttachmentUnique m_info_string_loader; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> + CreateGdtAttachmentUniqueLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + { + return std::make_unique(memory, searchPath, gdt, zone); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Weapon/GdtLoaderAttachmentUniqueT6.h b/src/ObjLoading/Game/T6/Weapon/GdtLoaderAttachmentUniqueT6.h new file mode 100644 index 00000000..3e39221d --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/GdtLoaderAttachmentUniqueT6.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "Gdt/IGdtQueryable.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> + CreateGdtAttachmentUniqueLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Weapon/GdtLoaderWeaponT6.cpp b/src/ObjLoading/Game/T6/Weapon/GdtLoaderWeaponT6.cpp new file mode 100644 index 00000000..702213dd --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/GdtLoaderWeaponT6.cpp @@ -0,0 +1,53 @@ +#include "GdtLoaderWeaponT6.h" + +#include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" +#include "InfoStringLoaderWeaponT6.h" + +#include +#include +#include + +using namespace T6; + +namespace +{ + class GdtLoaderWeapon final : public AssetCreator + { + public: + GdtLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + : m_gdt(gdt), + m_info_string_loader(memory, searchPath, zone) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto* gdtEntry = m_gdt.GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_WEAPON, assetName); + if (gdtEntry == nullptr) + return AssetCreationResult::NoAction(); + + InfoString infoString; + if (!infoString.FromGdtProperties(*gdtEntry)) + { + std::cerr << std::format("Failed to read weapon gdt entry: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + return m_info_string_loader.CreateAsset(assetName, infoString, context); + } + + private: + IGdtQueryable& m_gdt; + InfoStringLoaderWeapon m_info_string_loader; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateGdtWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + { + return std::make_unique(memory, searchPath, gdt, zone); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Weapon/GdtLoaderWeaponT6.h b/src/ObjLoading/Game/T6/Weapon/GdtLoaderWeaponT6.h new file mode 100644 index 00000000..fdb1882b --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/GdtLoaderWeaponT6.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "Gdt/IGdtQueryable.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateGdtWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentT6.cpp b/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentT6.cpp new file mode 100644 index 00000000..83f71735 --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentT6.cpp @@ -0,0 +1,121 @@ +#include "InfoStringLoaderAttachmentT6.h" + +#include "Game/T6/InfoString/InfoStringToStructConverter.h" +#include "Game/T6/T6.h" +#include "Game/T6/Weapon/AttachmentFields.h" +#include "Game/T6/Weapon/WeaponStrings.h" + +#include +#include +#include +#include +#include + +using namespace T6; + +namespace +{ + eAttachmentPoint attachmentPointByAttachmentTable[]{ + ATTACHMENT_POINT_NONE, // none + ATTACHMENT_POINT_TOP, // acog + ATTACHMENT_POINT_TRIGGER, // dualclip + ATTACHMENT_POINT_TOP, // dualoptic + ATTACHMENT_POINT_BOTTOM, // dw + ATTACHMENT_POINT_MUZZLE, // extbarrel + ATTACHMENT_POINT_TRIGGER, // extclip + ATTACHMENT_POINT_TRIGGER, // extramags + ATTACHMENT_POINT_GUNPERK, // fastads + ATTACHMENT_POINT_TOP, // fastreload + ATTACHMENT_POINT_TRIGGER, // fmj + ATTACHMENT_POINT_BOTTOM, // gl + ATTACHMENT_POINT_BOTTOM, // grip + ATTACHMENT_POINT_TOP, // holo + ATTACHMENT_POINT_BOTTOM, // ir + ATTACHMENT_POINT_BOTTOM, // is + ATTACHMENT_POINT_GUNPERK, // longbreath + ATTACHMENT_POINT_BOTTOM, // mk + ATTACHMENT_POINT_TOP, // mms + ATTACHMENT_POINT_TOP, // rangefinder + ATTACHMENT_POINT_TOP, // reflex + ATTACHMENT_POINT_MUZZLE, // rf + ATTACHMENT_POINT_BOTTOM, // sf + ATTACHMENT_POINT_MUZZLE, // silencer + ATTACHMENT_POINT_TRIGGER, // stackfire + ATTACHMENT_POINT_GUNPERK, // stalker + ATTACHMENT_POINT_GUNPERK, // steadyaim + ATTACHMENT_POINT_GUNPERK, // swayreduc + ATTACHMENT_POINT_TOP, // tacknife + ATTACHMENT_POINT_TOP, // vzoom + }; + static_assert(std::extent_v == ATTACHMENT_TYPE_COUNT); + + class InfoStringToAttachmentConverter final : public InfoStringToStructConverter + { + protected: + bool ConvertExtensionField(const cspField_t& field, const std::string& value) override + { + switch (static_cast(field.iFieldType)) + { + case AFT_ATTACHMENTTYPE: + return ConvertEnumInt(field.szName, value, field.iOffset, szAttachmentTypeNames, std::extent_v); + + case AFT_PENETRATE_TYPE: + return ConvertEnumInt(field.szName, value, field.iOffset, penetrateTypeNames, std::extent_v); + + case AFT_FIRETYPE: + return ConvertEnumInt(field.szName, value, field.iOffset, szWeapFireTypeNames, std::extent_v); + + default: + assert(false); + return false; + } + } + + public: + InfoStringToAttachmentConverter(const InfoString& infoString, + WeaponAttachment& attachment, + ZoneScriptStrings& zoneScriptStrings, + MemoryManager& memory, + AssetCreationContext& context, + AssetRegistration& registration, + const cspField_t* fields, + const size_t fieldCount) + : InfoStringToStructConverter(infoString, &attachment, zoneScriptStrings, memory, context, registration, fields, fieldCount) + { + } + }; + + void CalculateAttachmentFields(WeaponAttachment& attachment) + { + assert(static_cast(attachment.attachmentType) < ATTACHMENT_TYPE_COUNT); + if (static_cast(attachment.attachmentType) < ATTACHMENT_TYPE_COUNT) + attachment.attachmentPoint = attachmentPointByAttachmentTable[attachment.attachmentType]; + } +} // namespace + +InfoStringLoaderAttachment::InfoStringLoaderAttachment(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_memory(memory), + m_search_path(searchPath), + m_zone(zone) +{ +} + +AssetCreationResult InfoStringLoaderAttachment::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) +{ + auto* attachment = m_memory.Alloc(); + attachment->szInternalName = m_memory.Dup(assetName.c_str()); + + AssetRegistration registration(assetName, attachment); + + InfoStringToAttachmentConverter converter( + infoString, *attachment, m_zone.m_script_strings, m_memory, context, registration, attachment_fields, std::extent_v); + if (!converter.Convert()) + { + std::cerr << std::format("Failed to parse attachment: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + CalculateAttachmentFields(*attachment); + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); +} diff --git a/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentT6.h b/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentT6.h new file mode 100644 index 00000000..fc6d020d --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentT6.h @@ -0,0 +1,21 @@ +#pragma once + +#include "Asset/AssetCreationContext.h" +#include "Asset/AssetCreationResult.h" +#include "InfoString/InfoString.h" + +namespace T6 +{ + class InfoStringLoaderAttachment + { + public: + InfoStringLoaderAttachment(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); + + AssetCreationResult CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context); + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + Zone& m_zone; + }; +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentUniqueT6.cpp b/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentUniqueT6.cpp new file mode 100644 index 00000000..8172eddb --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentUniqueT6.cpp @@ -0,0 +1,242 @@ +#include "InfoStringLoaderAttachmentUniqueT6.h" + +#include "Game/T6/InfoString/InfoStringToStructConverter.h" +#include "Game/T6/T6.h" +#include "Game/T6/Weapon/AttachmentUniqueFields.h" +#include "Game/T6/Weapon/WeaponStrings.h" + +#include +#include +#include +#include +#include + +using namespace T6; + +namespace +{ + class InfoStringToAttachmentUniqueConverter final : public InfoStringToStructConverter + { + protected: + bool ConvertExtensionField(const cspField_t& field, const std::string& value) override + { + switch (static_cast(field.iFieldType)) + { + case AUFT_ATTACHMENTTYPE: + return ConvertEnumInt(field.szName, value, field.iOffset, szAttachmentTypeNames, std::extent_v); + + case AUFT_HIDETAGS: + return ConvertHideTags(field, value); + + case AUFT_OVERLAYRETICLE: + return ConvertEnumInt(field.szName, value, field.iOffset, szWeapOverlayReticleNames, std::extent_v); + + case AUFT_CAMO: + return ConvertWeaponCamo(field, value); + + case AUFT_ANIM_NAME: + return ConvertAnimName(field, value); + + default: + assert(false); + return false; + } + } + + bool ConvertHideTags(const cspField_t& field, const std::string& value) + { + std::vector valueArray; + if (!ParseAsArray(value, valueArray)) + { + std::cerr << "Failed to parse hide tags as array\n"; + return false; + } + + if (valueArray.size() > std::extent_v) + { + std::cerr << std::format("Cannot have more than {} hide tags!\n", std::extent_v); + return false; + } + + auto* hideTags = reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset); + + if (valueArray.size() < std::extent_v) + m_registration.AddScriptString(m_zone_script_strings.AddOrGetScriptString(nullptr)); + + auto currentHideTag = 0u; + for (; currentHideTag < valueArray.size(); currentHideTag++) + { + const auto& currentValue = valueArray[currentHideTag]; + const auto scrString = + !currentValue.empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue) : m_zone_script_strings.AddOrGetScriptString(nullptr); + hideTags[currentHideTag] = scrString; + m_registration.AddScriptString(scrString); + } + + for (; currentHideTag < std::extent_v; currentHideTag++) + { + hideTags[currentHideTag] = m_zone_script_strings.GetScriptString(nullptr); + } + + return true; + } + + [[nodiscard]] bool ConvertWeaponCamo(const cspField_t& field, const std::string& value) + { + if (value.empty()) + { + *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = nullptr; + return true; + } + + auto* camo = m_context.LoadDependency(value); + + if (camo == nullptr) + { + std::cerr << std::format("Failed to load camo asset \"{}\"\n", value); + return false; + } + + m_registration.AddDependency(camo); + *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = camo->Asset(); + + return true; + } + + bool ConvertAnimName(const cspField_t& field, const std::string& value) + { + if (ConvertString(value, field.iOffset)) + { + if (!value.empty()) + m_registration.AddIndirectAssetReference(m_context.LoadIndirectAssetReference(value)); + + return true; + } + + return false; + } + + public: + InfoStringToAttachmentUniqueConverter(const InfoString& infoString, + WeaponAttachmentUniqueFull& attachmentUniqueFull, + ZoneScriptStrings& zoneScriptStrings, + MemoryManager& memory, + AssetCreationContext& context, + AssetRegistration& registration, + const cspField_t* fields, + const size_t fieldCount) + : InfoStringToStructConverter(infoString, &attachmentUniqueFull, zoneScriptStrings, memory, context, registration, fields, fieldCount) + { + } + }; + + void LinkAttachmentUniqueFullSubStructs(WeaponAttachmentUniqueFull& attachmentUnique) + { + attachmentUnique.attachment.hideTags = attachmentUnique.hideTags; + attachmentUnique.attachment.szXAnims = attachmentUnique.szXAnims; + attachmentUnique.attachment.locationDamageMultipliers = attachmentUnique.locationDamageMultipliers; + } + + bool CalculateAttachmentUniqueFields(const std::string& assetName, WeaponAttachmentUniqueFull& attachmentUnique) + { + // combinedAttachmentTypeMask + std::vector attachmentsFromName; + if (!InfoStringLoaderAttachmentUnique::ExtractAttachmentsFromAssetName(assetName, attachmentsFromName)) + { + std::cerr << std::format("Failed to determine attachments from attachment unique name \"{}\"\n", assetName); + return false; + } + + if (attachmentsFromName.size() > 1) + { + for (const auto attachment : attachmentsFromName) + { + attachmentUnique.attachment.combinedAttachmentTypeMask |= 1 << attachment; + } + } + + return true; + } +} // namespace + +bool InfoStringLoaderAttachmentUnique::ExtractAttachmentsFromAssetName(const std::string& assetName, std::vector& attachmentList) +{ + std::vector parts; + + auto attachCount = 1u; + auto partStart = 0u; + for (auto ci = 0u; ci < assetName.size(); ci++) + { + if (assetName[ci] == '_') + { + parts.emplace_back(assetName, partStart, ci - partStart); + partStart = ci + 1; + } + else if (assetName[ci] == '+') + { + attachCount++; + parts.emplace_back(assetName, partStart, ci - partStart); + partStart = ci + 1; + } + } + + if (partStart < assetName.size()) + parts.emplace_back(assetName, partStart, assetName.size() - partStart); + + for (auto attachPartOffset = parts.size() - attachCount; attachPartOffset < parts.size(); attachPartOffset++) + { + auto& specifiedAttachName = parts[attachPartOffset]; + + for (auto& c : specifiedAttachName) + c = static_cast(tolower(c)); + + auto foundAttachment = false; + for (auto attachIndex = 0u; attachIndex < std::extent_v; attachIndex++) + { + if (specifiedAttachName == szAttachmentTypeNames[attachIndex]) + { + attachmentList.push_back(static_cast(attachIndex)); + foundAttachment = true; + break; + } + } + + if (!foundAttachment) + return false; + } + + return true; +} + +InfoStringLoaderAttachmentUnique::InfoStringLoaderAttachmentUnique(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_memory(memory), + m_search_path(searchPath), + m_zone(zone) +{ +} + +AssetCreationResult InfoStringLoaderAttachmentUnique::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) +{ + auto* attachmentUniqueFull = m_memory.Alloc(); + attachmentUniqueFull->attachment.szInternalName = m_memory.Dup(assetName.c_str()); + + LinkAttachmentUniqueFullSubStructs(*attachmentUniqueFull); + + AssetRegistration registration(assetName, &attachmentUniqueFull->attachment); + + InfoStringToAttachmentUniqueConverter converter(infoString, + *attachmentUniqueFull, + m_zone.m_script_strings, + m_memory, + context, + registration, + attachment_unique_fields, + std::extent_v); + if (!converter.Convert()) + { + std::cerr << std::format("Failed to parse attachment unique: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); +} diff --git a/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentUniqueT6.h b/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentUniqueT6.h new file mode 100644 index 00000000..3ff89621 --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentUniqueT6.h @@ -0,0 +1,26 @@ +#pragma once + +#include "Asset/AssetCreationContext.h" +#include "Asset/AssetCreationResult.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" + +#include + +namespace T6 +{ + class InfoStringLoaderAttachmentUnique + { + public: + InfoStringLoaderAttachmentUnique(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); + + AssetCreationResult CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context); + + static bool ExtractAttachmentsFromAssetName(const std::string& assetName, std::vector& attachmentList); + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + Zone& m_zone; + }; +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderWeaponT6.cpp b/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderWeaponT6.cpp new file mode 100644 index 00000000..d71ab521 --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderWeaponT6.cpp @@ -0,0 +1,633 @@ +#include "InfoStringLoaderWeaponT6.h" + +#include "Game/T6/InfoString/InfoStringToStructConverter.h" +#include "Game/T6/T6.h" +#include "Game/T6/Weapon/WeaponFields.h" +#include "Game/T6/Weapon/WeaponStrings.h" +#include "InfoStringLoaderAttachmentUniqueT6.h" +#include "Weapon/AccuracyGraphLoader.h" + +#include +#include +#include +#include +#include + +using namespace T6; + +namespace +{ + class InfoStringToWeaponConverter final : public InfoStringToStructConverter + { + protected: + bool ConvertExtensionField(const cspField_t& field, const std::string& value) override + { + switch (static_cast(field.iFieldType)) + { + case WFT_WEAPONTYPE: + return ConvertEnumInt(field.szName, value, field.iOffset, szWeapTypeNames, std::extent_v); + + case WFT_WEAPONCLASS: + return ConvertEnumInt(field.szName, value, field.iOffset, szWeapClassNames, std::extent_v); + + case WFT_OVERLAYRETICLE: + return ConvertEnumInt(field.szName, value, field.iOffset, szWeapOverlayReticleNames, std::extent_v); + + case WFT_PENETRATE_TYPE: + return ConvertEnumInt(field.szName, value, field.iOffset, penetrateTypeNames, std::extent_v); + + case WFT_IMPACT_TYPE: + return ConvertEnumInt(field.szName, value, field.iOffset, impactTypeNames, std::extent_v); + + case WFT_STANCE: + return ConvertEnumInt(field.szName, value, field.iOffset, szWeapStanceNames, std::extent_v); + + case WFT_PROJ_EXPLOSION: + return ConvertEnumInt(field.szName, value, field.iOffset, szProjectileExplosionNames, std::extent_v); + + case WFT_OFFHAND_CLASS: + return ConvertEnumInt(field.szName, value, field.iOffset, offhandClassNames, std::extent_v); + + case WFT_OFFHAND_SLOT: + return ConvertEnumInt(field.szName, value, field.iOffset, offhandSlotNames, std::extent_v); + + case WFT_ANIMTYPE: + return ConvertEnumInt(field.szName, value, field.iOffset, playerAnimTypeNames, std::extent_v); + + case WFT_ACTIVE_RETICLE_TYPE: + return ConvertEnumInt(field.szName, value, field.iOffset, activeReticleNames, std::extent_v); + + case WFT_GUIDED_MISSILE_TYPE: + return ConvertEnumInt(field.szName, value, field.iOffset, guidedMissileNames, std::extent_v); + + case WFT_BOUNCE_SOUND: + return ConvertBounceSounds(field, value); + + case WFT_STICKINESS: + return ConvertEnumInt(field.szName, value, field.iOffset, stickinessNames, std::extent_v); + + case WFT_ROTATETYPE: + return ConvertEnumInt(field.szName, value, field.iOffset, rotateTypeNames, std::extent_v); + + case WFT_OVERLAYINTERFACE: + return ConvertEnumInt(field.szName, value, field.iOffset, overlayInterfaceNames, std::extent_v); + + case WFT_INVENTORYTYPE: + return ConvertEnumInt(field.szName, value, field.iOffset, szWeapInventoryTypeNames, std::extent_v); + + case WFT_FIRETYPE: + return ConvertEnumInt(field.szName, value, field.iOffset, szWeapFireTypeNames, std::extent_v); + + case WFT_CLIPTYPE: + return ConvertEnumInt(field.szName, value, field.iOffset, szWeapClipTypeNames, std::extent_v); + + case WFT_AMMOCOUNTER_CLIPTYPE: + return ConvertEnumInt(field.szName, value, field.iOffset, ammoCounterClipNames, std::extent_v); + + case WFT_ICONRATIO_HUD: + case WFT_ICONRATIO_AMMOCOUNTER: + case WFT_ICONRATIO_KILL: + case WFT_ICONRATIO_DPAD: + case WFT_ICONRATIO_INDICATOR: + return ConvertEnumInt(field.szName, value, field.iOffset, weapIconRatioNames, std::extent_v); + + case WFT_BARRELTYPE: + return ConvertEnumInt(field.szName, value, field.iOffset, barrelTypeNames, std::extent_v); + + case WFT_HIDETAGS: + return ConvertHideTags(field, value); + + case WFT_EXPLOSION_TAG: + return ConvertScriptString(value, field.iOffset); + + case WFT_NOTETRACKSOUNDMAP: + return ConvertNotetrackSoundMap(field, value); + + case WFT_WEAPON_CAMO: + return ConvertWeaponCamo(field, value); + + case WFT_ATTACHMENTS: + return ConvertAttachments(field, value); + + case WFT_ATTACHMENT_UNIQUES: + return ConvertAttachmentUniques(field, value); + + case WFT_ANIM_NAME: + return ConvertAnimName(field, value); + + default: + assert(false); + return false; + } + } + + bool ConvertHideTags(const cspField_t& field, const std::string& value) + { + std::vector valueArray; + if (!ParseAsArray(value, valueArray)) + { + std::cerr << "Failed to parse hide tags as array\n"; + return false; + } + + if (valueArray.size() > std::extent_v) + { + std::cerr << std::format("Cannot have more than {} hide tags!\n", std::extent_v); + return false; + } + + auto* hideTags = reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset); + + if (valueArray.size() < std::extent_v) + m_registration.AddScriptString(m_zone_script_strings.AddOrGetScriptString(nullptr)); + + auto currentHideTag = 0u; + for (; currentHideTag < valueArray.size(); currentHideTag++) + { + const auto& currentValue = valueArray[currentHideTag]; + const auto scrString = + !currentValue.empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue) : m_zone_script_strings.AddOrGetScriptString(nullptr); + hideTags[currentHideTag] = scrString; + m_registration.AddScriptString(scrString); + } + + for (; currentHideTag < std::extent_v; currentHideTag++) + { + hideTags[currentHideTag] = m_zone_script_strings.GetScriptString(nullptr); + } + + return true; + } + + _NODISCARD bool ConvertBounceSounds(const cspField_t& field, const std::string& value) const + { + auto*** bounceSound = reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset); + if (value.empty()) + { + *bounceSound = nullptr; + return true; + } + + assert(std::extent_v == SURF_TYPE_NUM); + *bounceSound = m_memory.Alloc(SURF_TYPE_NUM); + for (auto i = 0u; i < SURF_TYPE_NUM; i++) + { + const auto currentBounceSound = value + bounceSoundSuffixes[i]; + (*bounceSound)[i] = m_memory.Dup(currentBounceSound.c_str()); + } + return true; + } + + _NODISCARD bool ConvertNotetrackSoundMap(const cspField_t& field, const std::string& value) + { + std::vector> pairs; + if (!ParseAsArray(value, pairs)) + { + std::cerr << "Failed to parse notetracksoundmap as pairs\n"; + return false; + } + + if (pairs.size() > std::extent_v) + { + std::cerr << "Cannot have more than " << std::extent_v << " notetracksoundmap entries!\n"; + return false; + } + + auto* keys = reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset); + auto* values = &keys[std::extent_v]; + auto currentEntryNum = 0u; + + if (pairs.size() < std::extent_v) + { + m_registration.AddScriptString(m_zone_script_strings.AddOrGetScriptString(nullptr)); + } + + for (; currentEntryNum < pairs.size(); currentEntryNum++) + { + const auto& currentValue = pairs[currentEntryNum]; + const auto keyScriptString = !currentValue[0].empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue[0]) + : m_zone_script_strings.AddOrGetScriptString(nullptr); + const auto valueScriptString = !currentValue[1].empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue[1]) + : m_zone_script_strings.AddOrGetScriptString(nullptr); + + keys[currentEntryNum] = keyScriptString; + m_registration.AddScriptString(keyScriptString); + + values[currentEntryNum] = valueScriptString; + m_registration.AddScriptString(valueScriptString); + } + + for (; currentEntryNum < std::extent_v; currentEntryNum++) + { + const auto emptyScr = m_zone_script_strings.GetScriptString(nullptr); + keys[currentEntryNum] = emptyScr; + values[currentEntryNum] = emptyScr; + } + + return true; + } + + _NODISCARD bool ConvertWeaponCamo(const cspField_t& field, const std::string& value) + { + if (value.empty()) + { + *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = nullptr; + return true; + } + + auto* camo = m_context.LoadDependency(value); + + if (camo == nullptr) + { + std::cerr << std::format("Failed to load camo asset \"{}\"\n", value); + return false; + } + + m_registration.AddDependency(camo); + *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset) = camo->Asset(); + + return true; + } + + _NODISCARD bool ConvertAttachments(const cspField_t& field, const std::string& value) + { + std::vector valueArray; + if (!ParseAsArray(value, valueArray)) + { + std::cerr << "Failed to parse attachments as array\n"; + return false; + } + + auto** attachments = reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset); + + for (const auto& attachmentName : valueArray) + { + auto* attachmentAssetInfo = m_context.LoadDependency(attachmentName); + if (attachmentAssetInfo == nullptr) + { + std::cerr << std::format("Failed to load attachment asset \"{}\"\n", attachmentName); + return false; + } + + auto* attachmentAsset = attachmentAssetInfo->Asset(); + + if (static_cast(attachmentAsset->attachmentType) >= ATTACHMENT_TYPE_COUNT) + { + std::cerr << std::format( + "Invalid attachment type {} for attachment asset \"{}\"\n", static_cast(attachmentAsset->attachmentType), attachmentName); + return false; + } + + if (attachments[attachmentAsset->attachmentType] != nullptr) + { + std::cerr << std::format("Already loaded attachment with same type {}: \"{}\", \"{}\"\n", + static_cast(attachmentAsset->attachmentType), + attachments[attachmentAsset->attachmentType]->szInternalName, + attachmentName); + return false; + } + + attachments[attachmentAsset->attachmentType] = attachmentAsset; + m_registration.AddDependency(attachmentAssetInfo); + } + + return true; + } + + _NODISCARD static bool HasMoreThanOneAttachmentSetInMask(const int mask) + { + // Check if int has more than 1 bit set + return (mask & (mask - 1)) != 0; + } + + _NODISCARD bool ConvertAttachmentUniques(const cspField_t& field, const std::string& value) + { + std::vector valueArray; + if (!ParseAsArray(value, valueArray)) + { + std::cerr << "Failed to parse attachment uniques as array\n"; + return false; + } + + auto** attachmentUniques = reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset); + auto attachmentCombinationIndex = std::extent_v; + + for (const auto& attachmentUniqueName : valueArray) + { + auto* attachmentUniqueAssetInfo = m_context.LoadDependency(attachmentUniqueName); + if (attachmentUniqueAssetInfo == nullptr) + { + std::cerr << std::format("Failed to load attachment unique asset \"{}\"\n", attachmentUniqueName); + return false; + } + + auto* attachmentUniqueAsset = attachmentUniqueAssetInfo->Asset(); + + if (HasMoreThanOneAttachmentSetInMask(attachmentUniqueAsset->combinedAttachmentTypeMask)) + { + if (attachmentCombinationIndex >= std::extent_v) + { + std::cerr << std::format( + "Cannot have more than {} combined attachment attachment unique entries!\n", + (std::extent_v - std::extent_v)); + return false; + } + + attachmentUniques[attachmentCombinationIndex++] = attachmentUniqueAsset; + m_registration.AddDependency(attachmentUniqueAssetInfo); + } + else + { + if (static_cast(attachmentUniqueAsset->attachmentType) >= ATTACHMENT_TYPE_COUNT) + { + std::cerr << std::format("Invalid attachment type {} for attachment unique asset \"{}\"\n", + static_cast(attachmentUniqueAsset->attachmentType), + attachmentUniqueName); + return false; + } + + if (attachmentUniques[attachmentUniqueAsset->attachmentType] != nullptr) + { + std::cerr << std::format("Already loaded attachment unique with same type {}: \"{}\", \"{}\"\n", + static_cast(attachmentUniqueAsset->attachmentType), + attachmentUniques[attachmentUniqueAsset->attachmentType]->szInternalName, + attachmentUniqueName); + return false; + } + + attachmentUniques[attachmentUniqueAsset->attachmentType] = attachmentUniqueAsset; + m_registration.AddDependency(attachmentUniqueAssetInfo); + } + } + + return true; + } + + bool ConvertAnimName(const cspField_t& field, const std::string& value) + { + if (ConvertString(value, field.iOffset)) + { + if (!value.empty()) + m_registration.AddIndirectAssetReference(m_context.LoadIndirectAssetReference(value)); + + return true; + } + + return false; + } + + public: + InfoStringToWeaponConverter(const InfoString& infoString, + WeaponFullDef& weaponFullDef, + ZoneScriptStrings& zoneScriptStrings, + MemoryManager& memory, + AssetCreationContext& context, + AssetRegistration& registration, + const cspField_t* fields, + const size_t fieldCount) + : InfoStringToStructConverter(infoString, &weaponFullDef, zoneScriptStrings, memory, context, registration, fields, fieldCount) + { + } + }; + + void ConvertAccuracyGraph( + const GenericGraph2D& graph, vec2_t*& originalGraphKnots, int& originalGraphKnotCount, vec2_t*& graphKnots, int& graphKnotCount, MemoryManager& memory) + { + originalGraphKnotCount = static_cast(graph.knots.size()); + originalGraphKnots = memory.Alloc(originalGraphKnotCount); + + for (auto i = 0; i < originalGraphKnotCount; i++) + { + const auto& commonKnot = graph.knots[i]; + originalGraphKnots[i].x = static_cast(commonKnot.x); + originalGraphKnots[i].y = static_cast(commonKnot.y); + } + + graphKnots = originalGraphKnots; + graphKnotCount = originalGraphKnotCount; + } + + bool LoadAccuracyGraphs(WeaponFullDef& weaponFullDef, MemoryManager& memory, ISearchPath& searchPath, AssetCreationContext& context) + { + auto& accuracyGraphLoader = context.GetZoneAssetCreationState(); + + if (weaponFullDef.weapDef.aiVsAiAccuracyGraphName && weaponFullDef.weapDef.aiVsAiAccuracyGraphName[0]) + { + const auto* graph = accuracyGraphLoader.LoadAiVsAiGraph(searchPath, weaponFullDef.weapDef.aiVsAiAccuracyGraphName); + if (!graph) + return false; + + ConvertAccuracyGraph(*graph, + weaponFullDef.weapDef.originalAiVsAiAccuracyGraphKnots, + weaponFullDef.weapDef.originalAiVsAiAccuracyGraphKnotCount, + weaponFullDef.weapDef.aiVsAiAccuracyGraphKnots, + weaponFullDef.weapDef.aiVsAiAccuracyGraphKnotCount, + memory); + } + + if (weaponFullDef.weapDef.aiVsPlayerAccuracyGraphName && weaponFullDef.weapDef.aiVsPlayerAccuracyGraphName[0]) + { + const auto* graph = accuracyGraphLoader.LoadAiVsPlayerGraph(searchPath, weaponFullDef.weapDef.aiVsPlayerAccuracyGraphName); + if (!graph) + return false; + + ConvertAccuracyGraph(*graph, + weaponFullDef.weapDef.originalAiVsPlayerAccuracyGraphKnots, + weaponFullDef.weapDef.originalAiVsPlayerAccuracyGraphKnotCount, + weaponFullDef.weapDef.aiVsPlayerAccuracyGraphKnots, + weaponFullDef.weapDef.aiVsPlayerAccuracyGraphKnotCount, + memory); + } + + return true; + } + + void LinkWeaponFullDefSubStructs(WeaponFullDef& weapon) + { + weapon.weapVariantDef.weapDef = &weapon.weapDef; + weapon.weapVariantDef.attachments = weapon.attachments; + weapon.weapVariantDef.attachmentUniques = weapon.attachmentUniques; + weapon.weapDef.gunXModel = weapon.gunXModel; + weapon.weapVariantDef.szXAnims = weapon.szXAnims; + weapon.weapVariantDef.hideTags = weapon.hideTags; + weapon.weapDef.notetrackSoundMapKeys = weapon.notetrackSoundMapKeys; + weapon.weapDef.notetrackSoundMapValues = weapon.notetrackSoundMapValues; + weapon.weapDef.worldModel = weapon.worldModel; + weapon.weapVariantDef.attachViewModel = weapon.attachViewModel; + weapon.weapVariantDef.attachWorldModel = weapon.attachWorldModel; + weapon.weapVariantDef.attachViewModelTag = weapon.attachViewModelTag; + weapon.weapVariantDef.attachWorldModelTag = weapon.attachWorldModelTag; + weapon.weapDef.parallelBounce = weapon.parallelBounce; + weapon.weapDef.perpendicularBounce = weapon.perpendicularBounce; + weapon.weapDef.locationDamageMultipliers = weapon.locationDamageMultipliers; + } + + void CalculateWeaponFields(WeaponFullDef& weapon) + { + // iAttachments + weapon.weapVariantDef.iAttachments = 0; + for (auto i = 1u; i < sizeof(WeaponVariantDef::iAttachments) * 8; i++) // Bit for default attachment always 0 + { + if (weapon.attachments[i]) + weapon.weapVariantDef.iAttachments |= 1 << i; + } + + if (weapon.weapVariantDef.iAdsTransInTime <= 0) + weapon.weapVariantDef.fOOPosAnimLength[0] = 0.0033333334f; + else + weapon.weapVariantDef.fOOPosAnimLength[0] = 1.0f / static_cast(weapon.weapVariantDef.iAdsTransInTime); + + if (weapon.weapVariantDef.iAdsTransOutTime <= 0) + weapon.weapVariantDef.fOOPosAnimLength[1] = 0.0020000001f; + else + weapon.weapVariantDef.fOOPosAnimLength[1] = 1.0f / static_cast(weapon.weapVariantDef.iAdsTransOutTime); + } + + bool IsStringOverride(const char* baseString, const char* overrideString) + { + if (overrideString == nullptr || overrideString[0] == '\0') + return false; + + if (baseString == nullptr || baseString[0] == '\0') + return true; + + return strcmp(baseString, overrideString) != 0; + } + + bool IsFxOverride(const FxEffectDef* baseEffect, const FxEffectDef* overrideEffect) + { + if (overrideEffect == nullptr) + return false; + + if (baseEffect == nullptr) + return true; + + return strcmp(baseEffect->name, overrideEffect->name) != 0; + } + + void HandleSoundOverride(WeaponAttachmentUnique& attachmentUnique, const char* snd1, const char* snd2, const eAttachmentOverrideSounds sndOverrideIndex) + { + if (IsStringOverride(snd1, snd2)) + attachmentUnique.soundOverrides |= 1 << static_cast(sndOverrideIndex); + } + + void HandleFxOverride(WeaponAttachmentUnique& attachmentUnique, + const FxEffectDef* effect1, + const FxEffectDef* effect2, + const eAttachmentOverrideEffects fxOverrideIndex) + { + if (IsFxOverride(effect1, effect2)) + attachmentUnique.effectOverrides |= 1 << static_cast(fxOverrideIndex); + } + + void CalculateAttachmentFields(const WeaponFullDef& weapon, unsigned attachmentIndex, WeaponAttachmentUnique& attachmentUnique) + { + for (auto& val : attachmentUnique.animationOverrides) + val = 0; + + for (auto animIndex = 0u; animIndex < std::extent_v; animIndex++) + { + if (IsStringOverride(weapon.szXAnims[animIndex], attachmentUnique.szXAnims[animIndex])) + attachmentUnique.animationOverrides[animIndex / 32] |= 1 << (animIndex % 32); + } + + attachmentUnique.soundOverrides = 0; + HandleSoundOverride(attachmentUnique, weapon.weapDef.fireSound, attachmentUnique.fireSound, ATTACHMENT_OVERRIDE_SOUND_FIRE); + HandleSoundOverride(attachmentUnique, weapon.weapDef.fireSoundPlayer, attachmentUnique.fireSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_PLAYER); + HandleSoundOverride(attachmentUnique, weapon.weapDef.fireLoopSound, attachmentUnique.fireLoopSound, ATTACHMENT_OVERRIDE_SOUND_FIRE_LOOP); + HandleSoundOverride( + attachmentUnique, weapon.weapDef.fireLoopSoundPlayer, attachmentUnique.fireLoopSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_LOOP_PLAYER); + HandleSoundOverride(attachmentUnique, weapon.weapDef.fireLoopEndSound, attachmentUnique.fireLoopEndSound, ATTACHMENT_OVERRIDE_SOUND_FIRE_LOOP_END); + HandleSoundOverride( + attachmentUnique, weapon.weapDef.fireLoopEndSoundPlayer, attachmentUnique.fireLoopEndSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_LOOP_END_PLAYER); + HandleSoundOverride(attachmentUnique, weapon.weapDef.fireStartSound, attachmentUnique.fireStartSound, ATTACHMENT_OVERRIDE_SOUND_FIRE_START); + HandleSoundOverride(attachmentUnique, weapon.weapDef.fireStopSound, attachmentUnique.fireStopSound, ATTACHMENT_OVERRIDE_SOUND_FIRE_STOP); + HandleSoundOverride( + attachmentUnique, weapon.weapDef.fireStartSoundPlayer, attachmentUnique.fireStartSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_START_PLAYER); + HandleSoundOverride( + attachmentUnique, weapon.weapDef.fireStopSoundPlayer, attachmentUnique.fireStopSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_STOP_PLAYER); + HandleSoundOverride(attachmentUnique, weapon.weapDef.fireLastSound, attachmentUnique.fireLastSound, ATTACHMENT_OVERRIDE_SOUND_FIRE_LAST); + HandleSoundOverride( + attachmentUnique, weapon.weapDef.fireLastSoundPlayer, attachmentUnique.fireLastSoundPlayer, ATTACHMENT_OVERRIDE_SOUND_FIRE_LAST_PLAYER); + + attachmentUnique.effectOverrides = 0; + HandleFxOverride(attachmentUnique, weapon.weapDef.viewFlashEffect, attachmentUnique.viewFlashEffect, ATTACHMENT_OVERRIDE_EFFECT_VIEW_FLASH); + HandleFxOverride(attachmentUnique, weapon.weapDef.worldFlashEffect, attachmentUnique.worldFlashEffect, ATTACHMENT_OVERRIDE_EFFECT_WORLD_FLASH); + + attachmentUnique.childLink = 0; + if (attachmentUnique.combinedAttachmentTypeMask == 0) + { + WeaponAttachmentUnique* lastSibling = nullptr; + for (auto attachmentUniqueIndex = std::extent_v; + attachmentUniqueIndex < std::extent_v; + attachmentUniqueIndex++) + { + if (weapon.attachmentUniques[attachmentUniqueIndex] != nullptr + && weapon.attachmentUniques[attachmentUniqueIndex]->combinedAttachmentTypeMask + & (1 << static_cast(attachmentUnique.attachmentType)) + && weapon.attachmentUniques[attachmentUniqueIndex]->attachmentType != attachmentUnique.attachmentType) + { + std::vector attachments; + if (InfoStringLoaderAttachmentUnique::ExtractAttachmentsFromAssetName(weapon.attachmentUniques[attachmentUniqueIndex]->szInternalName, + attachments) + && attachments.front() == attachmentUnique.attachmentType) + { + if (lastSibling == nullptr) + { + attachmentUnique.childLink = attachmentUniqueIndex; + lastSibling = weapon.attachmentUniques[attachmentUniqueIndex]; + } + else + { + lastSibling->siblingLink = attachmentUniqueIndex; + lastSibling = weapon.attachmentUniques[attachmentUniqueIndex]; + } + } + } + } + } + } + + void CalculateAttachmentFields(const WeaponFullDef& weapon) + { + for (auto attachmentUniqueIndex = 0u; attachmentUniqueIndex < std::extent_v; attachmentUniqueIndex++) + { + if (weapon.attachmentUniques[attachmentUniqueIndex] == nullptr) + continue; + + CalculateAttachmentFields(weapon, attachmentUniqueIndex, *weapon.attachmentUniques[attachmentUniqueIndex]); + } + } +} // namespace + +InfoStringLoaderWeapon::InfoStringLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_memory(memory), + m_search_path(searchPath), + m_zone(zone) +{ +} + +AssetCreationResult InfoStringLoaderWeapon::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) +{ + auto* weaponFullDef = m_memory.Alloc(); + weaponFullDef->weapVariantDef.szInternalName = m_memory.Dup(assetName.c_str()); + + LinkWeaponFullDefSubStructs(*weaponFullDef); + + AssetRegistration registration(assetName, &weaponFullDef->weapVariantDef); + + InfoStringToWeaponConverter converter( + infoString, *weaponFullDef, m_zone.m_script_strings, m_memory, context, registration, weapon_fields, std::extent_v); + if (!converter.Convert()) + { + std::cerr << std::format("Failed to parse weapon: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + CalculateWeaponFields(*weaponFullDef); + CalculateAttachmentFields(*weaponFullDef); + + LoadAccuracyGraphs(*weaponFullDef, m_memory, m_search_path, context); + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); +} diff --git a/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderWeaponT6.h b/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderWeaponT6.h new file mode 100644 index 00000000..f745963a --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderWeaponT6.h @@ -0,0 +1,21 @@ +#pragma once + +#include "Asset/AssetCreationContext.h" +#include "Asset/AssetCreationResult.h" +#include "InfoString/InfoString.h" + +namespace T6 +{ + class InfoStringLoaderWeapon + { + public: + InfoStringLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); + + AssetCreationResult CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context); + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + Zone& m_zone; + }; +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/WeaponCamo/JsonWeaponCamoLoader.cpp b/src/ObjLoading/Game/T6/Weapon/JsonWeaponCamoLoaderT6.cpp similarity index 86% rename from src/ObjLoading/Game/T6/WeaponCamo/JsonWeaponCamoLoader.cpp rename to src/ObjLoading/Game/T6/Weapon/JsonWeaponCamoLoaderT6.cpp index 3c8a4c60..b98df329 100644 --- a/src/ObjLoading/Game/T6/WeaponCamo/JsonWeaponCamoLoader.cpp +++ b/src/ObjLoading/Game/T6/Weapon/JsonWeaponCamoLoaderT6.cpp @@ -1,4 +1,4 @@ -#include "JsonWeaponCamoLoader.h" +#include "JsonWeaponCamoLoaderT6.h" #include "Game/T6/CommonT6.h" #include "Game/T6/Json/JsonWeaponCamo.h" @@ -15,11 +15,11 @@ namespace class JsonLoader { public: - JsonLoader(std::istream& stream, MemoryManager& memory, IAssetLoadingManager& manager, std::vector& dependencies) + JsonLoader(std::istream& stream, MemoryManager& memory, AssetCreationContext& context, AssetRegistration& registration) : m_stream(stream), m_memory(memory), - m_manager(manager), - m_dependencies(dependencies) + m_context(context), + m_registration(registration) { } @@ -35,7 +35,7 @@ namespace if (type != "weaponCamo" || version != 1u) { - std::cerr << "Tried to load weapon camo \"" << weaponCamo.name << "\" but did not find expected type weaponCamo of version 1\n"; + std::cerr << std::format("Tried to load weapon camo \"{}\" but did not find expected type weaponCamo of version {}\n", weaponCamo.name, 1u); return false; } @@ -62,25 +62,25 @@ namespace { if (jWeaponCamoSet.solidCamoImage) { - auto* image = m_manager.LoadDependency(jWeaponCamoSet.solidCamoImage.value()); + auto* image = m_context.LoadDependency(jWeaponCamoSet.solidCamoImage.value()); if (!image) { PrintError(weaponCamo, "Could not find solidCamoImage"); return false; } - m_dependencies.push_back(image); + m_registration.AddDependency(image); weaponCamoSet.solidCamoImage = image->Asset(); } if (jWeaponCamoSet.patternCamoImage) { - auto* image = m_manager.LoadDependency(jWeaponCamoSet.patternCamoImage.value()); + auto* image = m_context.LoadDependency(jWeaponCamoSet.patternCamoImage.value()); if (!image) { PrintError(weaponCamo, "Could not find patternCamoImage"); return false; } - m_dependencies.push_back(image); + m_registration.AddDependency(image); weaponCamoSet.patternCamoImage = image->Asset(); } @@ -111,8 +111,8 @@ namespace for (auto i = 0u; i < weaponCamoMaterial.numBaseMaterials; i++) { const auto& materialOverride = jWeaponCamoMaterial.materialOverrides[i]; - auto* baseMaterial = m_manager.LoadDependency(materialOverride.baseMaterial); - auto* camoMaterial = m_manager.LoadDependency(materialOverride.camoMaterial); + auto* baseMaterial = m_context.LoadDependency(materialOverride.baseMaterial); + auto* camoMaterial = m_context.LoadDependency(materialOverride.camoMaterial); if (!baseMaterial) { @@ -126,8 +126,8 @@ namespace return false; } - m_dependencies.push_back(baseMaterial); - m_dependencies.push_back(camoMaterial); + m_registration.AddDependency(baseMaterial); + m_registration.AddDependency(camoMaterial); weaponCamoMaterial.baseMaterials[i] = baseMaterial->Asset(); weaponCamoMaterial.camoMaterials[i] = camoMaterial->Asset(); @@ -173,25 +173,25 @@ namespace { if (jWeaponCamo.solidBaseImage) { - auto* image = m_manager.LoadDependency(jWeaponCamo.solidBaseImage.value()); + auto* image = m_context.LoadDependency(jWeaponCamo.solidBaseImage.value()); if (!image) { PrintError(weaponCamo, "Could not find solidBaseImage"); return false; } - m_dependencies.push_back(image); + m_registration.AddDependency(image); weaponCamo.solidBaseImage = image->Asset(); } if (jWeaponCamo.patternBaseImage) { - auto* image = m_manager.LoadDependency(jWeaponCamo.patternBaseImage.value()); + auto* image = m_context.LoadDependency(jWeaponCamo.patternBaseImage.value()); if (!image) { PrintError(weaponCamo, "Could not find patternBaseImage"); return false; } - m_dependencies.push_back(image); + m_registration.AddDependency(image); weaponCamo.patternBaseImage = image->Asset(); } @@ -234,17 +234,17 @@ namespace std::istream& m_stream; MemoryManager& m_memory; - IAssetLoadingManager& m_manager; - std::vector& m_dependencies; + AssetCreationContext& m_context; + AssetRegistration& m_registration; }; } // namespace namespace T6 { bool LoadWeaponCamoAsJson( - std::istream& stream, WeaponCamo& weaponCamo, MemoryManager* memory, IAssetLoadingManager* manager, std::vector& dependencies) + std::istream& stream, WeaponCamo& weaponCamo, MemoryManager& memory, AssetCreationContext& context, AssetRegistration& registration) { - const JsonLoader loader(stream, *memory, *manager, dependencies); + const JsonLoader loader(stream, memory, context, registration); return loader.Load(weaponCamo); } diff --git a/src/ObjLoading/Game/T6/WeaponCamo/JsonWeaponCamoLoader.h b/src/ObjLoading/Game/T6/Weapon/JsonWeaponCamoLoaderT6.h similarity index 56% rename from src/ObjLoading/Game/T6/WeaponCamo/JsonWeaponCamoLoader.h rename to src/ObjLoading/Game/T6/Weapon/JsonWeaponCamoLoaderT6.h index b0fc78bb..6f5aea17 100644 --- a/src/ObjLoading/Game/T6/WeaponCamo/JsonWeaponCamoLoader.h +++ b/src/ObjLoading/Game/T6/Weapon/JsonWeaponCamoLoaderT6.h @@ -1,6 +1,7 @@ #pragma once -#include "AssetLoading/IAssetLoadingManager.h" +#include "Asset/AssetCreationContext.h" +#include "Asset/AssetRegistration.h" #include "Game/T6/T6.h" #include "Utils/MemoryManager.h" @@ -9,5 +10,5 @@ namespace T6 { bool LoadWeaponCamoAsJson( - std::istream& stream, WeaponCamo& weaponCamo, MemoryManager* memory, IAssetLoadingManager* manager, std::vector& dependencies); + std::istream& stream, WeaponCamo& weaponCamo, MemoryManager& memory, AssetCreationContext& context, AssetRegistration& registration); } // namespace T6 diff --git a/src/ObjLoading/Game/T6/Weapon/LoaderWeaponCamoT6.cpp b/src/ObjLoading/Game/T6/Weapon/LoaderWeaponCamoT6.cpp new file mode 100644 index 00000000..c3409ac8 --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/LoaderWeaponCamoT6.cpp @@ -0,0 +1,55 @@ +#include "LoaderWeaponCamoT6.h" + +#include "Game/T6/T6.h" +#include "JsonWeaponCamoLoaderT6.h" +#include "Pool/GlobalAssetPool.h" + +#include +#include +#include + +using namespace T6; + +namespace +{ + class WeaponCamoLoader final : public AssetCreator + { + public: + WeaponCamoLoader(MemoryManager& memory, ISearchPath& searchPath) + : m_memory(memory), + m_search_path(searchPath) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto file = m_search_path.Open(std::format("camo/{}.json", assetName)); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + auto* weaponCamo = m_memory.Alloc(); + weaponCamo->name = m_memory.Dup(assetName.c_str()); + + AssetRegistration registration(assetName, weaponCamo); + if (!LoadWeaponCamoAsJson(*file.m_stream, *weaponCamo, m_memory, context, registration)) + { + std::cerr << std::format("Failed to load weapon camo \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); + } + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateWeaponCamoLoader(MemoryManager& memory, ISearchPath& searchPath) + { + return std::make_unique(memory, searchPath); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Weapon/LoaderWeaponCamoT6.h b/src/ObjLoading/Game/T6/Weapon/LoaderWeaponCamoT6.h new file mode 100644 index 00000000..b5270fba --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/LoaderWeaponCamoT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateWeaponCamoLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Weapon/RawLoaderAttachmentT6.cpp b/src/ObjLoading/Game/T6/Weapon/RawLoaderAttachmentT6.cpp new file mode 100644 index 00000000..bf318b2d --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/RawLoaderAttachmentT6.cpp @@ -0,0 +1,54 @@ +#include "RawLoaderAttachmentT6.h" + +#include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" +#include "InfoStringLoaderAttachmentT6.h" + +#include +#include +#include + +using namespace T6; + +namespace +{ + class RawLoaderAttachment final : public AssetCreator + { + public: + RawLoaderAttachment(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_search_path(searchPath), + m_info_string_loader(memory, searchPath, zone) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto fileName = std::format("attachment/{}", assetName); + const auto file = m_search_path.Open(fileName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + InfoString infoString; + if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_WEAPON_ATTACHMENT, *file.m_stream)) + { + std::cerr << std::format("Could not parse as info string file: \"{}\"\n", fileName); + return AssetCreationResult::Failure(); + } + + return m_info_string_loader.CreateAsset(assetName, infoString, context); + } + + private: + ISearchPath& m_search_path; + InfoStringLoaderAttachment m_info_string_loader; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateRawAttachmentLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + { + return std::make_unique(memory, searchPath, zone); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Weapon/RawLoaderAttachmentT6.h b/src/ObjLoading/Game/T6/Weapon/RawLoaderAttachmentT6.h new file mode 100644 index 00000000..d83631d1 --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/RawLoaderAttachmentT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateRawAttachmentLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Weapon/RawLoaderAttachmentUniqueT6.cpp b/src/ObjLoading/Game/T6/Weapon/RawLoaderAttachmentUniqueT6.cpp new file mode 100644 index 00000000..f3af0c30 --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/RawLoaderAttachmentUniqueT6.cpp @@ -0,0 +1,54 @@ +#include "RawLoaderAttachmentUniqueT6.h" + +#include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" +#include "InfoStringLoaderAttachmentUniqueT6.h" + +#include +#include +#include + +using namespace T6; + +namespace +{ + class RawLoaderAttachmentUnique final : public AssetCreator + { + public: + RawLoaderAttachmentUnique(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_search_path(searchPath), + m_info_string_loader(memory, searchPath, zone) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto fileName = std::format("attachmentunique/{}", assetName); + const auto file = m_search_path.Open(fileName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + InfoString infoString; + if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_WEAPON_ATTACHMENT_UNIQUE, *file.m_stream)) + { + std::cerr << std::format("Could not parse as info string file: \"{}\"\n", fileName); + return AssetCreationResult::Failure(); + } + + return m_info_string_loader.CreateAsset(assetName, infoString, context); + } + + private: + ISearchPath& m_search_path; + InfoStringLoaderAttachmentUnique m_info_string_loader; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateRawAttachmentUniqueLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + { + return std::make_unique(memory, searchPath, zone); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Weapon/RawLoaderAttachmentUniqueT6.h b/src/ObjLoading/Game/T6/Weapon/RawLoaderAttachmentUniqueT6.h new file mode 100644 index 00000000..47b66237 --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/RawLoaderAttachmentUniqueT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateRawAttachmentUniqueLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Weapon/RawLoaderWeaponT6.cpp b/src/ObjLoading/Game/T6/Weapon/RawLoaderWeaponT6.cpp new file mode 100644 index 00000000..36cbcd48 --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/RawLoaderWeaponT6.cpp @@ -0,0 +1,54 @@ +#include "RawLoaderWeaponT6.h" + +#include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" +#include "InfoStringLoaderWeaponT6.h" + +#include +#include +#include + +using namespace T6; + +namespace +{ + class RawLoaderWeapon final : public AssetCreator + { + public: + RawLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_search_path(searchPath), + m_info_string_loader(memory, searchPath, zone) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto fileName = std::format("weapons/{}", assetName); + const auto file = m_search_path.Open(fileName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + InfoString infoString; + if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_WEAPON, *file.m_stream)) + { + std::cerr << std::format("Could not parse as info string file: \"{}\"\n", fileName); + return AssetCreationResult::Failure(); + } + + return m_info_string_loader.CreateAsset(assetName, infoString, context); + } + + private: + ISearchPath& m_search_path; + InfoStringLoaderWeapon m_info_string_loader; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateRawWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + { + return std::make_unique(memory, searchPath, zone); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Weapon/RawLoaderWeaponT6.h b/src/ObjLoading/Game/T6/Weapon/RawLoaderWeaponT6.h new file mode 100644 index 00000000..8eedbb71 --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/RawLoaderWeaponT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateRawWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/ZBarrier/GdtLoaderZBarrierT6.cpp b/src/ObjLoading/Game/T6/ZBarrier/GdtLoaderZBarrierT6.cpp new file mode 100644 index 00000000..cba149e6 --- /dev/null +++ b/src/ObjLoading/Game/T6/ZBarrier/GdtLoaderZBarrierT6.cpp @@ -0,0 +1,53 @@ +#include "GdtLoaderZBarrierT6.h" + +#include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" +#include "InfoStringLoaderZBarrierT6.h" + +#include +#include +#include + +using namespace T6; + +namespace +{ + class GdtLoaderZBarrier final : public AssetCreator + { + public: + GdtLoaderZBarrier(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + : m_gdt(gdt), + m_info_string_loader(memory, searchPath, zone) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto* gdtEntry = m_gdt.GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_ZBARRIER, assetName); + if (gdtEntry == nullptr) + return AssetCreationResult::NoAction(); + + InfoString infoString; + if (!infoString.FromGdtProperties(*gdtEntry)) + { + std::cerr << std::format("Failed to read zbarrier gdt entry: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + return m_info_string_loader.CreateAsset(assetName, infoString, context); + } + + private: + IGdtQueryable& m_gdt; + InfoStringLoaderZBarrier m_info_string_loader; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateGdtZBarrierLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + { + return std::make_unique(memory, searchPath, gdt, zone); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/ZBarrier/GdtLoaderZBarrierT6.h b/src/ObjLoading/Game/T6/ZBarrier/GdtLoaderZBarrierT6.h new file mode 100644 index 00000000..af3796b9 --- /dev/null +++ b/src/ObjLoading/Game/T6/ZBarrier/GdtLoaderZBarrierT6.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "Gdt/IGdtQueryable.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateGdtZBarrierLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/ZBarrier/InfoStringLoaderZBarrierT6.cpp b/src/ObjLoading/Game/T6/ZBarrier/InfoStringLoaderZBarrierT6.cpp new file mode 100644 index 00000000..23c460b9 --- /dev/null +++ b/src/ObjLoading/Game/T6/ZBarrier/InfoStringLoaderZBarrierT6.cpp @@ -0,0 +1,83 @@ +#include "InfoStringLoaderZBarrierT6.h" + +#include "Game/T6/InfoString/InfoStringToStructConverter.h" +#include "Game/T6/T6.h" +#include "Game/T6/ZBarrier/ZBarrierFields.h" + +#include +#include +#include +#include +#include + +using namespace T6; + +namespace +{ + class InfoStringToZBarrierConverter final : public InfoStringToStructConverter + { + protected: + bool ConvertExtensionField(const cspField_t& field, const std::string& value) override + { + assert(false); + return false; + } + + public: + InfoStringToZBarrierConverter(const InfoString& infoString, + ZBarrierDef& zbarrier, + ZoneScriptStrings& zoneScriptStrings, + MemoryManager& memory, + AssetCreationContext& context, + AssetRegistration& registration, + const cspField_t* fields, + const size_t fieldCount) + : InfoStringToStructConverter(infoString, &zbarrier, zoneScriptStrings, memory, context, registration, fields, fieldCount) + { + } + }; + + void CalculateZBarrierFields(ZBarrierDef& zbarrier) + { + auto foundEnd = false; + for (auto i = 0u; i < std::extent_v; i++) + { + if (zbarrier.boards[i].pBoardModel == nullptr) + { + foundEnd = true; + zbarrier.numBoardsInBarrier = i; + break; + } + } + + if (!foundEnd) + zbarrier.numBoardsInBarrier = std::extent_v; + } +} // namespace + +InfoStringLoaderZBarrier::InfoStringLoaderZBarrier(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_memory(memory), + m_search_path(searchPath), + m_zone(zone) +{ +} + +AssetCreationResult InfoStringLoaderZBarrier::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) +{ + auto* zbarrier = m_memory.Alloc(); + zbarrier->name = m_memory.Dup(assetName.c_str()); + + AssetRegistration registration(assetName, zbarrier); + + InfoStringToZBarrierConverter converter( + infoString, *zbarrier, m_zone.m_script_strings, m_memory, context, registration, zbarrier_fields, std::extent_v); + if (!converter.Convert()) + { + std::cerr << std::format("Failed to parse zbarrier: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + CalculateZBarrierFields(*zbarrier); + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); +} diff --git a/src/ObjLoading/Game/T6/ZBarrier/InfoStringLoaderZBarrierT6.h b/src/ObjLoading/Game/T6/ZBarrier/InfoStringLoaderZBarrierT6.h new file mode 100644 index 00000000..5a70ec28 --- /dev/null +++ b/src/ObjLoading/Game/T6/ZBarrier/InfoStringLoaderZBarrierT6.h @@ -0,0 +1,21 @@ +#pragma once + +#include "Asset/AssetCreationContext.h" +#include "Asset/AssetCreationResult.h" +#include "InfoString/InfoString.h" + +namespace T6 +{ + class InfoStringLoaderZBarrier + { + public: + InfoStringLoaderZBarrier(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); + + AssetCreationResult CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context); + + private: + MemoryManager& m_memory; + ISearchPath& m_search_path; + Zone& m_zone; + }; +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/ZBarrier/RawLoaderZBarrierT6.cpp b/src/ObjLoading/Game/T6/ZBarrier/RawLoaderZBarrierT6.cpp new file mode 100644 index 00000000..0a7d56d0 --- /dev/null +++ b/src/ObjLoading/Game/T6/ZBarrier/RawLoaderZBarrierT6.cpp @@ -0,0 +1,54 @@ +#include "RawLoaderZBarrierT6.h" + +#include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" +#include "InfoStringLoaderZBarrierT6.h" + +#include +#include +#include + +using namespace T6; + +namespace +{ + class RawLoaderZBarrier final : public AssetCreator + { + public: + RawLoaderZBarrier(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_search_path(searchPath), + m_info_string_loader(memory, searchPath, zone) + { + } + + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto fileName = std::format("zbarrier/{}", assetName); + const auto file = m_search_path.Open(fileName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + InfoString infoString; + if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_ZBARRIER, *file.m_stream)) + { + std::cerr << std::format("Could not parse as info string file: \"{}\"\n", fileName); + return AssetCreationResult::Failure(); + } + + return m_info_string_loader.CreateAsset(assetName, infoString, context); + } + + private: + ISearchPath& m_search_path; + InfoStringLoaderZBarrier m_info_string_loader; + }; +} // namespace + +namespace T6 +{ + std::unique_ptr> CreateRawZBarrierLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + { + return std::make_unique(memory, searchPath, zone); + } +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/ZBarrier/RawLoaderZBarrierT6.h b/src/ObjLoading/Game/T6/ZBarrier/RawLoaderZBarrierT6.h new file mode 100644 index 00000000..007b2306 --- /dev/null +++ b/src/ObjLoading/Game/T6/ZBarrier/RawLoaderZBarrierT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Game/T6/T6.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace T6 +{ + std::unique_ptr> CreateRawZBarrierLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace T6 diff --git a/src/ObjLoading/AssetLoading/AbstractGdtEntryReader.cpp b/src/ObjLoading/Gdt/AbstractGdtEntryReader.cpp similarity index 100% rename from src/ObjLoading/AssetLoading/AbstractGdtEntryReader.cpp rename to src/ObjLoading/Gdt/AbstractGdtEntryReader.cpp diff --git a/src/ObjLoading/AssetLoading/AbstractGdtEntryReader.h b/src/ObjLoading/Gdt/AbstractGdtEntryReader.h similarity index 100% rename from src/ObjLoading/AssetLoading/AbstractGdtEntryReader.h rename to src/ObjLoading/Gdt/AbstractGdtEntryReader.h diff --git a/src/ObjLoading/AssetLoading/AssetLoadingContext.cpp b/src/ObjLoading/Gdt/GdtLookup.cpp similarity index 55% rename from src/ObjLoading/AssetLoading/AssetLoadingContext.cpp rename to src/ObjLoading/Gdt/GdtLookup.cpp index 26480fd9..9cd66ed9 100644 --- a/src/ObjLoading/AssetLoading/AssetLoadingContext.cpp +++ b/src/ObjLoading/Gdt/GdtLookup.cpp @@ -1,16 +1,10 @@ -#include "AssetLoadingContext.h" +#include "GdtLookup.h" -AssetLoadingContext::AssetLoadingContext(Zone& zone, ISearchPath& rawSearchPath, std::vector gdtFiles) - : m_zone(zone), - m_raw_search_path(rawSearchPath), - m_gdt_files(std::move(gdtFiles)) +void GdtLookup::Initialize(const std::vector& gdtFiles) { - BuildGdtEntryCache(); -} + m_entries_by_gdf_and_by_name.clear(); -void AssetLoadingContext::BuildGdtEntryCache() -{ - for (const auto* gdt : m_gdt_files) + for (const auto* gdt : gdtFiles) { for (const auto& entry : gdt->m_entries) { @@ -18,15 +12,15 @@ void AssetLoadingContext::BuildGdtEntryCache() if (gdfMapEntry == m_entries_by_gdf_and_by_name.end()) { std::unordered_map entryMap; - entryMap.emplace(std::make_pair(entry->m_name, entry.get())); - m_entries_by_gdf_and_by_name.emplace(std::make_pair(entry->m_gdf_name, std::move(entryMap))); + entryMap.emplace(entry->m_name, entry.get()); + m_entries_by_gdf_and_by_name.emplace(entry->m_gdf_name, std::move(entryMap)); } else { auto entryMapEntry = gdfMapEntry->second.find(entry->m_name); if (entryMapEntry == gdfMapEntry->second.end()) - gdfMapEntry->second.emplace(std::make_pair(entry->m_name, entry.get())); + gdfMapEntry->second.emplace(entry->m_name, entry.get()); else entryMapEntry->second = entry.get(); } @@ -34,7 +28,7 @@ void AssetLoadingContext::BuildGdtEntryCache() } } -GdtEntry* AssetLoadingContext::GetGdtEntryByGdfAndName(const std::string& gdfName, const std::string& entryName) +GdtEntry* GdtLookup::GetGdtEntryByGdfAndName(const std::string& gdfName, const std::string& entryName) { const auto foundGdtMap = m_entries_by_gdf_and_by_name.find(gdfName); diff --git a/src/ObjLoading/Gdt/GdtLookup.h b/src/ObjLoading/Gdt/GdtLookup.h new file mode 100644 index 00000000..c7d073f1 --- /dev/null +++ b/src/ObjLoading/Gdt/GdtLookup.h @@ -0,0 +1,18 @@ +#pragma once + +#include "IGdtQueryable.h" +#include "Obj/Gdt/Gdt.h" + +#include +#include +#include + +class GdtLookup : public IGdtQueryable +{ +public: + void Initialize(const std::vector& gdtFiles); + GdtEntry* GetGdtEntryByGdfAndName(const std::string& gdfName, const std::string& entryName) override; + +private: + std::unordered_map> m_entries_by_gdf_and_by_name; +}; diff --git a/src/ObjLoading/AssetLoading/IGdtQueryable.h b/src/ObjLoading/Gdt/IGdtQueryable.h similarity index 99% rename from src/ObjLoading/AssetLoading/IGdtQueryable.h rename to src/ObjLoading/Gdt/IGdtQueryable.h index 09b034e5..9bf22856 100644 --- a/src/ObjLoading/AssetLoading/IGdtQueryable.h +++ b/src/ObjLoading/Gdt/IGdtQueryable.h @@ -1,4 +1,5 @@ #pragma once + #include "Obj/Gdt/GdtEntry.h" #include diff --git a/src/ObjLoading/IObjLoader.h b/src/ObjLoading/IObjLoader.h index 9302b943..b534cac6 100644 --- a/src/ObjLoading/IObjLoader.h +++ b/src/ObjLoading/IObjLoader.h @@ -1,6 +1,7 @@ #pragma once -#include "AssetLoading/AssetLoadingContext.h" +#include "Asset/AssetCreatorCollection.h" +#include "Gdt/IGdtQueryable.h" #include "SearchPath/ISearchPath.h" #include "Zone/Zone.h" @@ -27,8 +28,7 @@ public: */ virtual void UnloadContainersOfZone(Zone& zone) const = 0; - virtual bool LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const = 0; - virtual void FinalizeAssetsForZone(AssetLoadingContext& context) const = 0; + virtual void ConfigureCreatorCollection(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, IGdtQueryable& gdt) const = 0; static const IObjLoader* GetObjLoaderForGame(GameId game); }; diff --git a/src/ObjLoading/InfoString/InfoStringToStructConverterBase.cpp b/src/ObjLoading/InfoString/InfoStringToStructConverterBase.cpp index a2686ddf..33e6dd60 100644 --- a/src/ObjLoading/InfoString/InfoStringToStructConverterBase.cpp +++ b/src/ObjLoading/InfoString/InfoStringToStructConverterBase.cpp @@ -1,17 +1,22 @@ #include "InfoStringToStructConverterBase.h" #include +#include #include #include InfoStringToStructConverterBase::InfoStringToStructConverterBase(const InfoString& infoString, void* structure, ZoneScriptStrings& zoneScriptStrings, - MemoryManager* memory) + MemoryManager& memory, + AssetCreationContext& context, + GenericAssetRegistration& registration) : m_info_string(infoString), + m_structure(structure), m_zone_script_strings(zoneScriptStrings), m_memory(memory), - m_structure(structure) + m_context(context), + m_registration(registration) { } @@ -44,7 +49,7 @@ bool InfoStringToStructConverterBase::ParseAsArray(const std::string& value, std bool InfoStringToStructConverterBase::ConvertString(const std::string& value, const size_t offset) { - *reinterpret_cast(reinterpret_cast(m_structure) + offset) = m_memory->Dup(value.c_str()); + *reinterpret_cast(reinterpret_cast(m_structure) + offset) = m_memory.Dup(value.c_str()); return true; } @@ -61,7 +66,7 @@ bool InfoStringToStructConverterBase::ConvertInt(const std::string& value, const if (endPtr != &value[value.size()]) { - std::cout << "Failed to parse value \"" << value << "\" as int\n"; + std::cerr << std::format("Failed to parse value \"{}\" as int\n", value); return false; } @@ -75,7 +80,7 @@ bool InfoStringToStructConverterBase::ConvertUint(const std::string& value, cons if (endPtr != &value[value.size()]) { - std::cout << "Failed to parse value \"" << value << "\" as uint\n"; + std::cerr << std::format("Failed to parse value \"{}\" as uint\n", value); return false; } @@ -90,7 +95,7 @@ bool InfoStringToStructConverterBase::ConvertBool(const std::string& value, cons *reinterpret_cast(reinterpret_cast(m_structure) + offset) = intValue != 0; if (endPtr != &value[value.size()]) { - std::cout << "Failed to parse value \"" << value << "\" as bool\n"; + std::cerr << std::format("Failed to parse value \"{}\" as bool\n", value); return false; } @@ -105,7 +110,7 @@ bool InfoStringToStructConverterBase::ConvertQBoolean(const std::string& value, *reinterpret_cast(reinterpret_cast(m_structure) + offset) = intValue != 0 ? 1 : 0; if (endPtr != &value[value.size()]) { - std::cout << "Failed to parse value \"" << value << "\" as qboolean\n"; + std::cerr << std::format("Failed to parse value \"{}\" as qboolean\n", value); return false; } @@ -119,7 +124,7 @@ bool InfoStringToStructConverterBase::ConvertFloat(const std::string& value, con if (endPtr != &value[value.size()]) { - std::cout << "Failed to parse value \"" << value << "\" as float\n"; + std::cerr << std::format("Failed to parse value \"{}\" as float\n", value); return false; } @@ -133,7 +138,7 @@ bool InfoStringToStructConverterBase::ConvertMilliseconds(const std::string& val if (endPtr != &value[value.size()]) { - std::cout << "Failed to parse value \"" << value << "\" as milliseconds\n"; + std::cerr << std::format("Failed to parse value \"{}\" as milliseconds\n", value); return false; } @@ -143,7 +148,7 @@ bool InfoStringToStructConverterBase::ConvertMilliseconds(const std::string& val bool InfoStringToStructConverterBase::ConvertScriptString(const std::string& value, const size_t offset) { auto scrStrValue = m_zone_script_strings.AddOrGetScriptString(value); - m_used_script_string_list.emplace(scrStrValue); + m_registration.AddScriptString(scrStrValue); *reinterpret_cast(reinterpret_cast(m_structure) + offset) = scrStrValue; return true; @@ -176,39 +181,3 @@ bool InfoStringToStructConverterBase::ConvertEnumInt( return false; } - -std::vector InfoStringToStructConverterBase::GetUsedScriptStrings() const -{ - std::vector scrStringList; - scrStringList.reserve(m_used_script_string_list.size()); - for (auto scrStr : m_used_script_string_list) - { - scrStringList.push_back(scrStr); - } - - return scrStringList; -} - -std::vector InfoStringToStructConverterBase::GetDependencies() const -{ - std::vector dependencyList; - dependencyList.reserve(m_dependencies.size()); - for (auto* dependency : m_dependencies) - { - dependencyList.push_back(dependency); - } - - return dependencyList; -} - -std::vector InfoStringToStructConverterBase::GetIndirectAssetReferences() const -{ - std::vector indirectAssetReferences; - indirectAssetReferences.reserve(m_indirect_asset_references.size()); - for (auto& assetReference : m_indirect_asset_references) - { - indirectAssetReferences.emplace_back(assetReference); - } - - return indirectAssetReferences; -} diff --git a/src/ObjLoading/InfoString/InfoStringToStructConverterBase.h b/src/ObjLoading/InfoString/InfoStringToStructConverterBase.h index cc9be478..af065f0f 100644 --- a/src/ObjLoading/InfoString/InfoStringToStructConverterBase.h +++ b/src/ObjLoading/InfoString/InfoStringToStructConverterBase.h @@ -1,5 +1,7 @@ #pragma once +#include "Asset/AssetCreationContext.h" +#include "Asset/AssetRegistration.h" #include "InfoString/InfoString.h" #include "Pool/XAssetInfo.h" #include "Utils/ClassUtils.h" @@ -7,6 +9,7 @@ #include "Zone/ZoneScriptStrings.h" #include +#include #include #include #include @@ -14,15 +17,22 @@ class InfoStringToStructConverterBase { -protected: - const InfoString& m_info_string; - ZoneScriptStrings& m_zone_script_strings; - std::unordered_set m_used_script_string_list; - std::unordered_set m_dependencies; - std::unordered_set m_indirect_asset_references; - MemoryManager* m_memory; - void* m_structure; +public: + InfoStringToStructConverterBase(const InfoString& infoString, + void* structure, + ZoneScriptStrings& zoneScriptStrings, + MemoryManager& memory, + AssetCreationContext& context, + GenericAssetRegistration& registration); + virtual ~InfoStringToStructConverterBase() = default; + InfoStringToStructConverterBase(const InfoStringToStructConverterBase& other) = delete; + InfoStringToStructConverterBase(InfoStringToStructConverterBase&& other) noexcept = delete; + InfoStringToStructConverterBase& operator=(const InfoStringToStructConverterBase& other) = delete; + InfoStringToStructConverterBase& operator=(InfoStringToStructConverterBase&& other) noexcept = delete; + virtual bool Convert() = 0; + +protected: static bool ParseAsArray(const std::string& value, std::vector& valueArray); template static bool ParseAsArray(const std::string& value, std::vector>& valueArray) @@ -79,7 +89,7 @@ protected: const auto isLastEntry = currentEntryOffset >= (ARRAY_SIZE - 1); if (isNextEntrySeparator != isLastEntry) { - std::cout << "Expected " << ARRAY_SIZE << " values but got new line\n"; + std::cerr << std::format("Expected {} values but got new line\n", ARRAY_SIZE); return false; } @@ -94,7 +104,7 @@ protected: if (currentEntryOffset > 0) { - std::cout << "Expected " << ARRAY_SIZE << " values but got new line\n"; + std::cerr << std::format("Expected {} values but got new line\n", ARRAY_SIZE); return false; } @@ -112,16 +122,10 @@ protected: bool ConvertScriptString(const std::string& value, size_t offset); bool ConvertEnumInt(const std::string& fieldName, const std::string& value, size_t offset, const char** enumValues, size_t enumSize); -public: - InfoStringToStructConverterBase(const InfoString& infoString, void* structure, ZoneScriptStrings& zoneScriptStrings, MemoryManager* memory); - virtual ~InfoStringToStructConverterBase() = default; - InfoStringToStructConverterBase(const InfoStringToStructConverterBase& other) = delete; - InfoStringToStructConverterBase(InfoStringToStructConverterBase&& other) noexcept = delete; - InfoStringToStructConverterBase& operator=(const InfoStringToStructConverterBase& other) = delete; - InfoStringToStructConverterBase& operator=(InfoStringToStructConverterBase&& other) noexcept = delete; - - virtual bool Convert() = 0; - _NODISCARD std::vector GetUsedScriptStrings() const; - _NODISCARD std::vector GetDependencies() const; - _NODISCARD std::vector GetIndirectAssetReferences() const; + const InfoString& m_info_string; + void* m_structure; + ZoneScriptStrings& m_zone_script_strings; + MemoryManager& m_memory; + AssetCreationContext& m_context; + GenericAssetRegistration& m_registration; }; diff --git a/src/ObjLoading/Localize/CommonLocalizeLoader.cpp b/src/ObjLoading/Localize/CommonLocalizeLoader.cpp new file mode 100644 index 00000000..d5071e12 --- /dev/null +++ b/src/ObjLoading/Localize/CommonLocalizeLoader.cpp @@ -0,0 +1,52 @@ +#include "CommonLocalizeLoader.h" + +#include "Localize/LocalizeCommon.h" +#include "Localize/Parsing/LocalizeFileReader.h" + +#include + +CommonLocalizeLoader::CommonLocalizeLoader(ISearchPath& searchPath, Zone& zone) + : m_search_path(searchPath), + m_zone(zone) +{ +} + +std::string CommonLocalizeLoader::GetFileName(const std::string& assetName) const +{ + return std::format("{}/localizedstrings/{}.str", LocalizeCommon::GetNameOfLanguage(m_zone.m_language), assetName); +} + +AssetCreationResult CommonLocalizeLoader::CreateLocalizeAsset(const std::string& assetName, AssetCreationContext& context) +{ + std::string fileName = GetFileName(assetName); + + const auto file = m_search_path.Open(fileName); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + LocalizeFileReader reader(*file.m_stream, assetName, m_zone.m_language, *this); + + std::vector localizeEntries; + if (!reader.ReadLocalizeFile(localizeEntries)) + return AssetCreationResult::Failure(); + + auto lastResult = AssetCreationResult::Failure(); + for (const auto& entry : localizeEntries) + { + lastResult = CreateAssetFromCommonAsset(entry, context); + if (!lastResult.HasBeenSuccessful()) + return lastResult; + } + + return lastResult; +} + +bool CommonLocalizeLoader::CheckLocalizeEntryForDuplicates(const std::string& key) +{ + const auto existingEntry = m_keys.find(key); + if (existingEntry != m_keys.end()) + return false; + + m_keys.emplace(key); + return true; +} diff --git a/src/ObjLoading/Localize/CommonLocalizeLoader.h b/src/ObjLoading/Localize/CommonLocalizeLoader.h new file mode 100644 index 00000000..b6cc6c43 --- /dev/null +++ b/src/ObjLoading/Localize/CommonLocalizeLoader.h @@ -0,0 +1,31 @@ +#pragma once + +#include "Asset/IAssetCreator.h" +#include "Localize/CommonLocalizeEntry.h" +#include "Localize/Parsing/ILocalizeFileDuplicationChecker.h" +#include "SearchPath/ISearchPath.h" +#include "Zone/Zone.h" + +#include +#include + +class CommonLocalizeLoader : ILocalizeFileDuplicationChecker +{ +public: + CommonLocalizeLoader(ISearchPath& searchPath, Zone& zone); + + AssetCreationResult CreateLocalizeAsset(const std::string& assetName, AssetCreationContext& context); + +protected: + virtual AssetCreationResult CreateAssetFromCommonAsset(const CommonLocalizeEntry& localizeEntry, AssetCreationContext& context) = 0; + +private: + std::string GetFileName(const std::string& assetName) const; + + bool CheckLocalizeEntryForDuplicates(const std::string& key) override; + + ISearchPath& m_search_path; + Zone& m_zone; + + std::unordered_set m_keys; +}; diff --git a/src/ObjLoading/Localize/LocalizeCommonAssetLoader.cpp b/src/ObjLoading/Localize/LocalizeCommonAssetLoader.cpp deleted file mode 100644 index bbfd8bd3..00000000 --- a/src/ObjLoading/Localize/LocalizeCommonAssetLoader.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "LocalizeCommonAssetLoader.h" - -#include "Localize/LocalizeCommon.h" -#include "Localize/LocalizeReadingZoneState.h" -#include "Localize/Parsing/LocalizeFileReader.h" - -#include - -LocalizeCommonAssetLoader::LocalizeCommonAssetLoader(std::function entryCallback) - : m_entry_callback(std::move(entryCallback)) -{ -} - -std::string LocalizeCommonAssetLoader::GetFileName(const std::string& assetName, Zone* zone) const -{ - std::ostringstream ss; - ss << LocalizeCommon::GetNameOfLanguage(zone->m_language) << "/localizedstrings/" << assetName << ".str"; - return ss.str(); -} - -bool LocalizeCommonAssetLoader::LoadLocalizeAsset(const std::string& assetName, ISearchPath* searchPath, IAssetLoadingManager* manager, Zone* zone) const -{ - std::string fileName = GetFileName(assetName, zone); - - const auto file = searchPath->Open(fileName); - if (!file.IsOpen()) - return false; - - auto* zoneState = manager->GetAssetLoadingContext()->GetZoneAssetLoaderState(); - LocalizeFileReader reader(*file.m_stream, assetName, zone->m_language, zoneState); - - std::vector localizeEntries; - if (!reader.ReadLocalizeFile(localizeEntries)) - return false; - - for (const auto& entry : localizeEntries) - { - m_entry_callback(entry); - } - - return true; -} diff --git a/src/ObjLoading/Localize/LocalizeCommonAssetLoader.h b/src/ObjLoading/Localize/LocalizeCommonAssetLoader.h deleted file mode 100644 index 0955b630..00000000 --- a/src/ObjLoading/Localize/LocalizeCommonAssetLoader.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "AssetLoading/IAssetLoadingManager.h" -#include "Localize/CommonLocalizeEntry.h" -#include "SearchPath/ISearchPath.h" -#include "Zone/Zone.h" - -#include -#include - -class LocalizeCommonAssetLoader -{ -public: - explicit LocalizeCommonAssetLoader(std::function entryCallback); - - bool LoadLocalizeAsset(const std::string& assetName, ISearchPath* searchPath, IAssetLoadingManager* manager, Zone* zone) const; - -private: - std::string GetFileName(const std::string& assetName, Zone* zone) const; - - std::function m_entry_callback; -}; diff --git a/src/ObjLoading/Localize/LocalizeReadingZoneState.cpp b/src/ObjLoading/Localize/LocalizeReadingZoneState.cpp deleted file mode 100644 index 652c5ba9..00000000 --- a/src/ObjLoading/Localize/LocalizeReadingZoneState.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "LocalizeReadingZoneState.h" - -bool LocalizeReadingZoneState::DoLocalizeEntryDuplicateCheck(const std::string& key) -{ - const auto existingEntry = m_keys.find(key); - if (existingEntry != m_keys.end()) - return false; - - m_keys.emplace(key); - return true; -} diff --git a/src/ObjLoading/Localize/LocalizeReadingZoneState.h b/src/ObjLoading/Localize/Parsing/ILocalizeFileDuplicationChecker.h similarity index 51% rename from src/ObjLoading/Localize/LocalizeReadingZoneState.h rename to src/ObjLoading/Localize/Parsing/ILocalizeFileDuplicationChecker.h index 6350e138..d7c7f6c2 100644 --- a/src/ObjLoading/Localize/LocalizeReadingZoneState.h +++ b/src/ObjLoading/Localize/Parsing/ILocalizeFileDuplicationChecker.h @@ -1,13 +1,12 @@ #pragma once -#include "AssetLoading/IZoneAssetLoaderState.h" - #include -#include -class LocalizeReadingZoneState final : public IZoneAssetLoaderState +class ILocalizeFileDuplicationChecker { public: + virtual ~ILocalizeFileDuplicationChecker() = default; + /** * Checks whether a localize key was already added. * Inserts key if it was not added yet. @@ -15,8 +14,5 @@ public: * \param key The key to check * \returns \c true if key was not duplicated yet, \c false otherwise */ - bool DoLocalizeEntryDuplicateCheck(const std::string& key); - -private: - std::unordered_set m_keys; + virtual bool CheckLocalizeEntryForDuplicates(const std::string& key) = 0; }; diff --git a/src/ObjLoading/Localize/Parsing/LocalizeFileParser.cpp b/src/ObjLoading/Localize/Parsing/LocalizeFileParser.cpp index 35958c06..fb484dfa 100644 --- a/src/ObjLoading/Localize/Parsing/LocalizeFileParser.cpp +++ b/src/ObjLoading/Localize/Parsing/LocalizeFileParser.cpp @@ -8,8 +8,8 @@ #include "Sequence/SequenceLocalizeFileReference.h" #include "Sequence/SequenceLocalizeFileVersion.h" -LocalizeFileParser::LocalizeFileParser(SimpleLexer* lexer, GameLanguage language, LocalizeReadingZoneState* zoneState) - : AbstractParser(lexer, std::make_unique(language, zoneState)) +LocalizeFileParser::LocalizeFileParser(SimpleLexer* lexer, GameLanguage language, ILocalizeFileDuplicationChecker& duplicationChecker) + : AbstractParser(lexer, std::make_unique(language, duplicationChecker)) { } diff --git a/src/ObjLoading/Localize/Parsing/LocalizeFileParser.h b/src/ObjLoading/Localize/Parsing/LocalizeFileParser.h index 20b5b39b..8ce6517d 100644 --- a/src/ObjLoading/Localize/Parsing/LocalizeFileParser.h +++ b/src/ObjLoading/Localize/Parsing/LocalizeFileParser.h @@ -12,6 +12,6 @@ protected: const std::vector& GetTestsForState() override; public: - LocalizeFileParser(SimpleLexer* lexer, GameLanguage language, LocalizeReadingZoneState* zoneState); + LocalizeFileParser(SimpleLexer* lexer, GameLanguage language, ILocalizeFileDuplicationChecker& duplicationChecker); std::vector GetParsedValues(); }; diff --git a/src/ObjLoading/Localize/Parsing/LocalizeFileParserState.cpp b/src/ObjLoading/Localize/Parsing/LocalizeFileParserState.cpp index 0a52c5f8..d7464268 100644 --- a/src/ObjLoading/Localize/Parsing/LocalizeFileParserState.cpp +++ b/src/ObjLoading/Localize/Parsing/LocalizeFileParserState.cpp @@ -3,10 +3,10 @@ #include "Localize/LocalizeCommon.h" #include "Utils/StringUtils.h" -LocalizeFileParserState::LocalizeFileParserState(const GameLanguage language, LocalizeReadingZoneState* zoneState) +LocalizeFileParserState::LocalizeFileParserState(const GameLanguage language, ILocalizeFileDuplicationChecker& duplicationChecker) : m_end(false), m_language(language), - m_zone_state(zoneState) + m_duplication_checker(duplicationChecker) { m_language_name_caps = LocalizeCommon::GetNameOfLanguage(m_language); utils::MakeStringUpperCase(m_language_name_caps); diff --git a/src/ObjLoading/Localize/Parsing/LocalizeFileParserState.h b/src/ObjLoading/Localize/Parsing/LocalizeFileParserState.h index bee910d7..df931972 100644 --- a/src/ObjLoading/Localize/Parsing/LocalizeFileParserState.h +++ b/src/ObjLoading/Localize/Parsing/LocalizeFileParserState.h @@ -1,8 +1,8 @@ #pragma once #include "Game/GameLanguage.h" +#include "ILocalizeFileDuplicationChecker.h" #include "Localize/CommonLocalizeEntry.h" -#include "Localize/LocalizeReadingZoneState.h" #include #include @@ -10,16 +10,16 @@ class LocalizeFileParserState { public: + LocalizeFileParserState(GameLanguage language, ILocalizeFileDuplicationChecker& duplicationChecker); + bool m_end; std::vector m_entries; GameLanguage m_language; - LocalizeReadingZoneState* m_zone_state; + ILocalizeFileDuplicationChecker& m_duplication_checker; std::string m_language_name_caps; std::string m_current_reference; std::unordered_set m_current_reference_languages; - - LocalizeFileParserState(GameLanguage language, LocalizeReadingZoneState* zoneState); }; diff --git a/src/ObjLoading/Localize/Parsing/LocalizeFileReader.cpp b/src/ObjLoading/Localize/Parsing/LocalizeFileReader.cpp index b50c53b0..76a231b6 100644 --- a/src/ObjLoading/Localize/Parsing/LocalizeFileReader.cpp +++ b/src/ObjLoading/Localize/Parsing/LocalizeFileReader.cpp @@ -4,11 +4,11 @@ #include "Parsing/Impl/CommentRemovingStreamProxy.h" #include "Parsing/Impl/ParserSingleInputStream.h" -LocalizeFileReader::LocalizeFileReader(std::istream& stream, std::string fileName, GameLanguage language, LocalizeReadingZoneState* zoneState) +LocalizeFileReader::LocalizeFileReader(std::istream& stream, std::string fileName, GameLanguage language, ILocalizeFileDuplicationChecker& duplicationChecker) : m_file_name(std::move(fileName)), m_stream(nullptr), m_language(language), - m_zone_state(zoneState) + m_duplication_checker(duplicationChecker) { OpenBaseStream(stream); SetupStreamProxies(); @@ -38,7 +38,7 @@ bool LocalizeFileReader::ReadLocalizeFile(std::vector& entr lexerConfig.m_read_floating_point_numbers = false; const auto lexer = std::make_unique(m_stream, std::move(lexerConfig)); - const auto parser = std::make_unique(lexer.get(), m_language, m_zone_state); + const auto parser = std::make_unique(lexer.get(), m_language, m_duplication_checker); if (parser->Parse()) { diff --git a/src/ObjLoading/Localize/Parsing/LocalizeFileReader.h b/src/ObjLoading/Localize/Parsing/LocalizeFileReader.h index 1abb4d60..9028041b 100644 --- a/src/ObjLoading/Localize/Parsing/LocalizeFileReader.h +++ b/src/ObjLoading/Localize/Parsing/LocalizeFileReader.h @@ -1,8 +1,8 @@ #pragma once #include "Game/GameLanguage.h" +#include "ILocalizeFileDuplicationChecker.h" #include "Localize/CommonLocalizeEntry.h" -#include "Localize/LocalizeReadingZoneState.h" #include "Parsing/IParserLineStream.h" #include @@ -16,13 +16,13 @@ class LocalizeFileReader IParserLineStream* m_stream; std::vector> m_open_streams; GameLanguage m_language; - LocalizeReadingZoneState* m_zone_state; + ILocalizeFileDuplicationChecker& m_duplication_checker; bool OpenBaseStream(std::istream& stream); void SetupStreamProxies(); public: - LocalizeFileReader(std::istream& stream, std::string fileName, GameLanguage language, LocalizeReadingZoneState* zoneState); + LocalizeFileReader(std::istream& stream, std::string fileName, GameLanguage language, ILocalizeFileDuplicationChecker& duplicationChecker); bool ReadLocalizeFile(std::vector& entries); }; diff --git a/src/ObjLoading/Localize/Parsing/Sequence/SequenceLocalizeFileLanguageValue.cpp b/src/ObjLoading/Localize/Parsing/Sequence/SequenceLocalizeFileLanguageValue.cpp index fbf8110b..60102949 100644 --- a/src/ObjLoading/Localize/Parsing/Sequence/SequenceLocalizeFileLanguageValue.cpp +++ b/src/ObjLoading/Localize/Parsing/Sequence/SequenceLocalizeFileLanguageValue.cpp @@ -33,7 +33,7 @@ void SequenceLocalizeFileLanguageValue::ProcessMatch(LocalizeFileParserState* st if (langName == state->m_language_name_caps) { const auto& currentReference = state->m_current_reference; - if (!state->m_zone_state->DoLocalizeEntryDuplicateCheck(currentReference)) + if (!state->m_duplication_checker.CheckLocalizeEntryForDuplicates(currentReference)) { std::cout << "Localize: a value for reference \"" << currentReference << "\" was already defined\n"; } diff --git a/src/ObjLoading/Menu/AbstractMenuConverter.cpp b/src/ObjLoading/Menu/AbstractMenuConverter.cpp index 0b05d76f..86c4c6b6 100644 --- a/src/ObjLoading/Menu/AbstractMenuConverter.cpp +++ b/src/ObjLoading/Menu/AbstractMenuConverter.cpp @@ -1,35 +1,29 @@ #include "AbstractMenuConverter.h" +#include #include using namespace menu; -AbstractMenuConverter::AbstractMenuConverter(const bool disableOptimizations, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) +AbstractMenuConverter::AbstractMenuConverter(const bool disableOptimizations, ISearchPath& searchPath, MemoryManager& memory, AssetCreationContext& context) : m_disable_optimizations(disableOptimizations), m_search_path(searchPath), m_memory(memory), - m_manager(manager) + m_context(context) { } void AbstractMenuConverter::PrintConversionExceptionDetails(const MenuConversionException& e) { - std::cout << "ERROR while converting menu:\n"; - std::cout << " Menu: " << e.m_menu->m_name << "\n"; + std::cerr << "ERROR while converting menu:\n"; + std::cerr << std::format(" Menu: {}\n", e.m_menu->m_name); if (e.m_item) { - std::cout << "Item: "; - - if (!e.m_item->m_name.empty()) - { - std::cout << e.m_item->m_name << "\n"; - } - - std::cout << "\n"; + std::cerr << std::format("Item: {}\n", e.m_item->m_name); } - std::cout << " Message: " << e.m_message << "\n"; + std::cerr << std::format(" Message: {}\n", e.m_message); } const char* AbstractMenuConverter::ConvertString(const std::string& str) const @@ -37,5 +31,5 @@ const char* AbstractMenuConverter::ConvertString(const std::string& str) const if (str.empty()) return nullptr; - return m_memory->Dup(str.c_str()); + return m_memory.Dup(str.c_str()); } diff --git a/src/ObjLoading/Menu/AbstractMenuConverter.h b/src/ObjLoading/Menu/AbstractMenuConverter.h index 442e1054..1db72896 100644 --- a/src/ObjLoading/Menu/AbstractMenuConverter.h +++ b/src/ObjLoading/Menu/AbstractMenuConverter.h @@ -1,6 +1,6 @@ #pragma once -#include "AssetLoading/IAssetLoadingManager.h" +#include "Asset/AssetCreationContext.h" #include "MenuConversionException.h" #include "SearchPath/ISearchPath.h" #include "Utils/ClassUtils.h" @@ -11,16 +11,14 @@ namespace menu class AbstractMenuConverter { protected: - bool m_disable_optimizations; - ISearchPath* m_search_path; - MemoryManager* m_memory; - IAssetLoadingManager* m_manager; - - AbstractMenuConverter(bool disableOptimizations, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager); + AbstractMenuConverter(bool disableOptimizations, ISearchPath& searchPath, MemoryManager& memory, AssetCreationContext& context); _NODISCARD const char* ConvertString(const std::string& str) const; - - public: static void PrintConversionExceptionDetails(const MenuConversionException& e); + + bool m_disable_optimizations; + ISearchPath& m_search_path; + MemoryManager& m_memory; + AssetCreationContext& m_context; }; } // namespace menu diff --git a/src/ObjLoading/ObjContainer/IWD/IWD.cpp b/src/ObjLoading/ObjContainer/IWD/IWD.cpp deleted file mode 100644 index 8a5e1c6f..00000000 --- a/src/ObjLoading/ObjContainer/IWD/IWD.cpp +++ /dev/null @@ -1,363 +0,0 @@ -#include "IWD.h" - -#include "ObjLoading.h" -#include "Utils/FileToZlibWrapper.h" - -#include -#include -#include -#include -#include -#include - -namespace fs = std::filesystem; - -ObjContainerRepository IWD::Repository; - -class IWDFile final : public objbuf -{ -public: - class IParent - { - public: - virtual ~IParent() = default; - - virtual void OnIWDFileClose() = 0; - }; - -private: - IParent* m_parent; - bool m_open; - int64_t m_size; - unzFile m_container; - bool m_peeked; - int_type m_peek_symbol; - -public: - IWDFile(IParent* parent, const unzFile container, const int64_t size) - : m_parent(parent), - m_open(true), - m_size(size), - m_container(container), - m_peeked(false), - m_peek_symbol(0) - { - } - - ~IWDFile() override - { - if (m_open) - { - close(); - } - } - -protected: - int_type underflow() override - { - if (m_peeked) - return m_peek_symbol; - - const auto result = unzReadCurrentFile(m_container, &m_peek_symbol, 1u); - - if (result >= 0) - { - m_peeked = true; - return static_cast(m_peek_symbol); - } - - return EOF; - } - - int_type uflow() override - { - if (m_peeked) - { - m_peeked = false; - return m_peek_symbol; - } - - const auto result = unzReadCurrentFile(m_container, &m_peek_symbol, 1u); - return result >= 0 ? static_cast(m_peek_symbol) : EOF; - } - - std::streamsize xsgetn(char* ptr, std::streamsize count) override - { - if (m_peeked && count >= 1) - { - *ptr = static_cast(m_peek_symbol); - ptr++; - count--; - } - - const auto result = unzReadCurrentFile(m_container, ptr, static_cast(count)); - - return result >= 0 ? static_cast(result) : 0; - } - - pos_type seekoff(const off_type off, const std::ios_base::seekdir dir, const std::ios_base::openmode mode) override - { - const auto currentPos = unztell64(m_container); - - pos_type targetPos; - if (dir == std::ios_base::beg) - { - targetPos = off; - } - else if (dir == std::ios_base::cur) - { - targetPos = currentPos + off; - } - else - { - targetPos = m_size - off; - } - - return seekpos(targetPos, mode); - } - - pos_type seekpos(const pos_type pos, const std::ios_base::openmode mode) override - { - const auto currentPos = unztell64(m_container); - - if (static_cast(currentPos) < pos) - { - auto skipAmount = pos - static_cast(currentPos); - while (skipAmount > 0) - { - char temp[1024]; - const auto toRead = skipAmount > sizeof(temp) ? sizeof(temp) : static_cast(skipAmount); - unzReadCurrentFile(m_container, temp, toRead); - skipAmount -= toRead; - } - - return pos; - } - - if (currentPos == pos) - { - // This is fine - return currentPos; - } - - return std::streampos(-1); - } - -public: - _NODISCARD bool is_open() const override - { - return m_open; - } - - bool close() override - { - unzCloseCurrentFile(m_container); - m_open = false; - - m_parent->OnIWDFileClose(); - - return true; - } -}; - -class IWD::Impl : public ISearchPath, public IObjContainer, public IWDFile::IParent -{ - class IWDEntry - { - public: - int64_t m_size{}; - unz_file_pos m_file_pos{}; - }; - - std::string m_path; - std::unique_ptr m_stream; - unzFile m_unz_file; - - IWDFile* m_last_file; - - std::map m_entry_map; - -public: - Impl(std::string path, std::unique_ptr stream) - : m_path(std::move(path)), - m_stream(std::move(stream)), - m_unz_file(nullptr), - m_last_file(nullptr) - { - } - - ~Impl() override - { - if (m_unz_file != nullptr) - { - unzClose(m_unz_file); - m_unz_file = nullptr; - } - } - - Impl(const Impl& other) = delete; - Impl(Impl&& other) noexcept = default; - Impl& operator=(const Impl& other) = delete; - Impl& operator=(Impl&& other) noexcept = default; - - bool Initialize() - { - auto ioFunctions = FileToZlibWrapper::CreateFunctions32ForFile(m_stream.get()); - m_unz_file = unzOpen2("", &ioFunctions); - - if (m_unz_file == nullptr) - { - printf("Could not open IWD \"%s\"\n", m_path.c_str()); - return false; - } - - auto ret = unzGoToFirstFile(m_unz_file); - while (ret == Z_OK) - { - unz_file_info64 info; - char fileNameBuffer[256]; - unzGetCurrentFileInfo64(m_unz_file, &info, fileNameBuffer, sizeof(fileNameBuffer), nullptr, 0, nullptr, 0); - - std::string fileName(fileNameBuffer); - std::filesystem::path path(fileName); - - if (path.has_filename()) - { - IWDEntry entry; - entry.m_size = info.uncompressed_size; - unzGetFilePos(m_unz_file, &entry.m_file_pos); - m_entry_map.emplace(std::move(fileName), entry); - } - - ret = unzGoToNextFile(m_unz_file); - } - - if (ObjLoading::Configuration.Verbose) - { - printf("Loaded IWD \"%s\" with %u entries\n", m_path.c_str(), m_entry_map.size()); - } - - return true; - } - - SearchPathOpenFile Open(const std::string& fileName) override - { - if (m_unz_file == nullptr) - { - return SearchPathOpenFile(); - } - - auto iwdFilename = fileName; - std::ranges::replace(iwdFilename, '\\', '/'); - - const auto iwdEntry = m_entry_map.find(iwdFilename); - - if (iwdEntry != m_entry_map.end()) - { - if (m_last_file != nullptr) - { - throw std::runtime_error("Trying to open new IWD file while last one was not yet closed."); - } - - auto pos = iwdEntry->second.m_file_pos; - unzGoToFilePos(m_unz_file, &pos); - - if (unzOpenCurrentFile(m_unz_file) == UNZ_OK) - { - auto result = std::make_unique(this, m_unz_file, iwdEntry->second.m_size); - m_last_file = result.get(); - return SearchPathOpenFile(std::make_unique(std::move(result)), iwdEntry->second.m_size); - } - - return SearchPathOpenFile(); - } - - return SearchPathOpenFile(); - } - - std::string GetPath() override - { - return m_path; - } - - std::string GetName() override - { - return fs::path(m_path).filename().string(); - } - - void Find(const SearchPathSearchOptions& options, const std::function& callback) override - { - if (options.m_disk_files_only) - { - return; - } - - for (auto& [entryName, entry] : m_entry_map) - { - std::filesystem::path entryPath(entryName); - - if (!options.m_should_include_subdirectories && entryPath.has_parent_path()) - continue; - - if (options.m_filter_extensions && options.m_extension != entryPath.extension().string()) - continue; - - callback(entryName); - } - } - - void OnIWDFileClose() override - { - m_last_file = nullptr; - } -}; - -IWD::IWD(std::string path, std::unique_ptr stream) -{ - m_impl = new Impl(std::move(path), std::move(stream)); -} - -IWD::~IWD() -{ - delete m_impl; - m_impl = nullptr; -} - -IWD::IWD(IWD&& other) noexcept -{ - m_impl = other.m_impl; - other.m_impl = nullptr; -} - -IWD& IWD::operator=(IWD&& other) noexcept -{ - m_impl = other.m_impl; - other.m_impl = nullptr; - - return *this; -} - -bool IWD::Initialize() -{ - return m_impl->Initialize(); -} - -SearchPathOpenFile IWD::Open(const std::string& fileName) -{ - return m_impl->Open(fileName); -} - -std::string IWD::GetPath() -{ - return m_impl->GetPath(); -} - -std::string IWD::GetName() -{ - return m_impl->GetName(); -} - -void IWD::Find(const SearchPathSearchOptions& options, const std::function& callback) -{ - return m_impl->Find(options, callback); -} diff --git a/src/ObjLoading/ObjContainer/IWD/IWD.h b/src/ObjLoading/ObjContainer/IWD/IWD.h deleted file mode 100644 index 84322710..00000000 --- a/src/ObjLoading/ObjContainer/IWD/IWD.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include "ObjContainer/ObjContainerRepository.h" -#include "SearchPath/ISearchPath.h" -#include "Utils/ClassUtils.h" -#include "Utils/ObjStream.h" - -#include - -class IWD final : public ISearchPath, IObjContainer -{ - class Impl; - Impl* m_impl; - -public: - static ObjContainerRepository Repository; - - IWD(std::string path, std::unique_ptr stream); - ~IWD() override; - - IWD(const IWD& other) = delete; - IWD(IWD&& other) noexcept; - IWD& operator=(const IWD& other) = delete; - IWD& operator=(IWD&& other) noexcept; - - /** - * \brief Initializes the IWD container. - * \return \c true when initialization was successful. - */ - bool Initialize(); - - SearchPathOpenFile Open(const std::string& fileName) override; - std::string GetPath() override; - std::string GetName() override; - void Find(const SearchPathSearchOptions& options, const std::function& callback) override; -}; diff --git a/src/ObjLoading/ObjContainer/SoundBank/SoundBankWriter.cpp b/src/ObjLoading/ObjContainer/SoundBank/SoundBankWriter.cpp index 6a68d6f8..878b9a61 100644 --- a/src/ObjLoading/ObjContainer/SoundBank/SoundBankWriter.cpp +++ b/src/ObjLoading/ObjContainer/SoundBank/SoundBankWriter.cpp @@ -61,7 +61,7 @@ class SoundBankWriterImpl : public SoundBankWriter }; public: - explicit SoundBankWriterImpl(std::string fileName, std::ostream& stream, ISearchPath* assetSearchPath) + explicit SoundBankWriterImpl(std::string fileName, std::ostream& stream, ISearchPath& assetSearchPath) : m_file_name(std::move(fileName)), m_stream(stream), m_asset_search_path(assetSearchPath), @@ -212,7 +212,7 @@ public: if (extension.empty()) return false; - const auto file = m_asset_search_path->Open(filePath); + const auto file = m_asset_search_path.Open(filePath); if (!file.IsOpen()) return false; @@ -323,7 +323,7 @@ public: private: std::string m_file_name; std::ostream& m_stream; - ISearchPath* m_asset_search_path; + ISearchPath& m_asset_search_path; std::vector m_sounds; int64_t m_current_offset; @@ -336,7 +336,7 @@ private: std::filesystem::path SoundBankWriter::OutputPath; -std::unique_ptr SoundBankWriter::Create(const std::string& fileName, std::ostream& stream, ISearchPath* assetSearchPath) +std::unique_ptr SoundBankWriter::Create(const std::string& fileName, std::ostream& stream, ISearchPath& assetSearchPath) { return std::make_unique(fileName, stream, assetSearchPath); } diff --git a/src/ObjLoading/ObjContainer/SoundBank/SoundBankWriter.h b/src/ObjLoading/ObjContainer/SoundBank/SoundBankWriter.h index ccd338b3..74de0ae6 100644 --- a/src/ObjLoading/ObjContainer/SoundBank/SoundBankWriter.h +++ b/src/ObjLoading/ObjContainer/SoundBank/SoundBankWriter.h @@ -19,7 +19,7 @@ public: virtual void AddSound(const std::string& soundFilePath, unsigned int soundId, bool looping = false, bool streamed = false) = 0; virtual bool Write(size_t& dataSize) = 0; - static std::unique_ptr Create(const std::string& fileName, std::ostream& stream, ISearchPath* assetSearchPath); + static std::unique_ptr Create(const std::string& fileName, std::ostream& stream, ISearchPath& assetSearchPath); static std::filesystem::path OutputPath; }; diff --git a/src/ObjLoading/ObjLoading.cpp b/src/ObjLoading/ObjLoading.cpp index b50fac75..1626e6f4 100644 --- a/src/ObjLoading/ObjLoading.cpp +++ b/src/ObjLoading/ObjLoading.cpp @@ -1,46 +1,3 @@ #include "ObjLoading.h" -#include "IObjLoader.h" -#include "ObjContainer/IWD/IWD.h" -#include "SearchPath/SearchPaths.h" -#include "Utils/ObjFileStream.h" - -#include - ObjLoading::Configuration_t ObjLoading::Configuration; - -void ObjLoading::LoadIWDsInSearchPath(ISearchPath& searchPath) -{ - searchPath.Find(SearchPathSearchOptions().IncludeSubdirectories(false).FilterExtensions("iwd"), - [&searchPath](const std::string& path) - { - auto file = std::make_unique(path, std::fstream::in | std::fstream::binary); - - if (file->is_open()) - { - auto iwd = std::make_unique(path, std::move(file)); - - if (iwd->Initialize()) - { - IWD::Repository.AddContainer(std::move(iwd), &searchPath); - } - } - }); -} - -void ObjLoading::UnloadIWDsInSearchPath(ISearchPath& searchPath) -{ - IWD::Repository.RemoveContainerReferences(&searchPath); -} - -SearchPaths ObjLoading::GetIWDSearchPaths() -{ - SearchPaths iwdPaths; - - for (auto* iwd : IWD::Repository) - { - iwdPaths.IncludeSearchPath(iwd); - } - - return iwdPaths; -} diff --git a/src/ObjLoading/ObjLoading.h b/src/ObjLoading/ObjLoading.h index 372ef610..08d9a319 100644 --- a/src/ObjLoading/ObjLoading.h +++ b/src/ObjLoading/ObjLoading.h @@ -1,8 +1,5 @@ #pragma once -#include "SearchPath/ISearchPath.h" -#include "SearchPath/SearchPaths.h" - class ObjLoading { public: @@ -13,22 +10,4 @@ public: bool MenuPermissiveParsing = false; bool MenuNoOptimization = false; } Configuration; - - /** - * \brief Loads all IWDs that can be found in a specified search path. - * \param searchPath The search path that contains IWDs to be loaded. - */ - static void LoadIWDsInSearchPath(ISearchPath& searchPath); - - /** - * \brief Unloads all IWDs that were loaded from the specified search path. - * \param searchPath The search path that was used to load the IWDs to be unloaded. - */ - static void UnloadIWDsInSearchPath(ISearchPath& searchPath); - - /** - * \brief Creates a \c SearchPaths object containing all IWDs that are currently loaded. - * \return A \c SearchPaths object containing all IWDs that are currently loaded. - */ - static SearchPaths GetIWDSearchPaths(); }; diff --git a/src/ObjLoading/Parsing/Menu/MenuAssetZoneState.h b/src/ObjLoading/Parsing/Menu/MenuAssetZoneState.h index 54c503f1..3130d261 100644 --- a/src/ObjLoading/Parsing/Menu/MenuAssetZoneState.h +++ b/src/ObjLoading/Parsing/Menu/MenuAssetZoneState.h @@ -1,6 +1,6 @@ #pragma once -#include "AssetLoading/IZoneAssetLoaderState.h" +#include "Asset/IZoneAssetCreationState.h" #include "Domain/CommonFunctionDef.h" #include "Domain/CommonMenuDef.h" @@ -8,7 +8,7 @@ namespace menu { - class MenuAssetZoneState final : public IZoneAssetLoaderState + class MenuAssetZoneState final : public IZoneAssetCreationState { public: std::vector> m_functions; diff --git a/src/ObjLoading/Parsing/Menu/MenuFileReader.cpp b/src/ObjLoading/Parsing/Menu/MenuFileReader.cpp index 710b4dea..d475a806 100644 --- a/src/ObjLoading/Parsing/Menu/MenuFileReader.cpp +++ b/src/ObjLoading/Parsing/Menu/MenuFileReader.cpp @@ -11,36 +11,22 @@ using namespace menu; -MenuFileReader::MenuFileReader(std::istream& stream, std::string fileName, const FeatureLevel featureLevel, include_callback_t includeCallback) - : m_feature_level(featureLevel), +MenuFileReader::MenuFileReader(std::istream& stream, std::string fileName, const FeatureLevel featureLevel, ISearchPath& searchPath) + : SearchPathMultiInputStream(searchPath), + m_feature_level(featureLevel), m_file_name(std::move(fileName)), m_stream(nullptr), m_zone_state(nullptr), m_permissive_mode(false) { - OpenBaseStream(stream, std::move(includeCallback)); + OpenBaseStream(stream); SetupStreamProxies(); m_stream = m_open_streams.back().get(); } -MenuFileReader::MenuFileReader(std::istream& stream, std::string fileName, const FeatureLevel featureLevel) - : m_feature_level(featureLevel), - m_file_name(std::move(fileName)), - m_stream(nullptr), - m_zone_state(nullptr), - m_permissive_mode(false) +bool MenuFileReader::OpenBaseStream(std::istream& stream) { - OpenBaseStream(stream, nullptr); - SetupStreamProxies(); - m_stream = m_open_streams.back().get(); -} - -bool MenuFileReader::OpenBaseStream(std::istream& stream, include_callback_t includeCallback) -{ - if (includeCallback) - m_open_streams.emplace_back(std::make_unique(stream, m_file_name, std::move(includeCallback))); - else - m_open_streams.emplace_back(std::make_unique(stream, m_file_name)); + m_open_streams.emplace_back(std::make_unique(stream, m_file_name, *this)); return true; } @@ -114,9 +100,9 @@ std::unique_ptr MenuFileReader::CreateParsingResult(MenuFileParse return result; } -void MenuFileReader::IncludeZoneState(const MenuAssetZoneState* zoneState) +void MenuFileReader::IncludeZoneState(const MenuAssetZoneState& zoneState) { - m_zone_state = zoneState; + m_zone_state = &zoneState; } void MenuFileReader::SetPermissiveMode(const bool usePermissiveMode) diff --git a/src/ObjLoading/Parsing/Menu/MenuFileReader.h b/src/ObjLoading/Parsing/Menu/MenuFileReader.h index 0947e2d2..894b2ab6 100644 --- a/src/ObjLoading/Parsing/Menu/MenuFileReader.h +++ b/src/ObjLoading/Parsing/Menu/MenuFileReader.h @@ -5,6 +5,8 @@ #include "MenuAssetZoneState.h" #include "MenuFileParserState.h" #include "Parsing/IParserLineStream.h" +#include "SearchPath/ISearchPath.h" +#include "SearchPath/SearchPathMultiInputStream.h" #include #include @@ -12,12 +14,24 @@ namespace menu { - class MenuFileReader + class MenuFileReader : public SearchPathMultiInputStream { public: - using include_callback_t = std::function(const std::string& filename, const std::string& sourceFile)>; + MenuFileReader(std::istream& stream, std::string fileName, FeatureLevel featureLevel, ISearchPath& searchPath); + + void IncludeZoneState(const MenuAssetZoneState& zoneState); + void SetPermissiveMode(bool usePermissiveMode); + + std::unique_ptr ReadMenuFile(); private: + bool OpenBaseStream(std::istream& stream); + void SetupDefinesProxy(); + void SetupStreamProxies(); + + bool IsValidEndState(const MenuFileParserState* state) const; + std::unique_ptr CreateParsingResult(MenuFileParserState* state) const; + const FeatureLevel m_feature_level; const std::string m_file_name; @@ -26,21 +40,5 @@ namespace menu const MenuAssetZoneState* m_zone_state; bool m_permissive_mode; - - bool OpenBaseStream(std::istream& stream, include_callback_t includeCallback); - void SetupDefinesProxy(); - void SetupStreamProxies(); - - bool IsValidEndState(const MenuFileParserState* state) const; - std::unique_ptr CreateParsingResult(MenuFileParserState* state) const; - - public: - MenuFileReader(std::istream& stream, std::string fileName, FeatureLevel featureLevel); - MenuFileReader(std::istream& stream, std::string fileName, FeatureLevel featureLevel, include_callback_t includeCallback); - - void IncludeZoneState(const MenuAssetZoneState* zoneState); - void SetPermissiveMode(bool usePermissiveMode); - - std::unique_ptr ReadMenuFile(); }; } // namespace menu diff --git a/src/ObjLoading/SearchPath/IWD.cpp b/src/ObjLoading/SearchPath/IWD.cpp new file mode 100644 index 00000000..ceea87a1 --- /dev/null +++ b/src/ObjLoading/SearchPath/IWD.cpp @@ -0,0 +1,339 @@ +#include "IWD.h" + +#include "ObjLoading.h" +#include "Utils/FileToZlibWrapper.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fs = std::filesystem; + +namespace +{ + class IwdFile final : public objbuf + { + public: + class IParent + { + public: + IParent() = default; + virtual ~IParent() = default; + IParent(const IParent& other) = default; + IParent(IParent&& other) noexcept = default; + IParent& operator=(const IParent& other) = default; + IParent& operator=(IParent&& other) noexcept = default; + + virtual void OnIwdFileClose() = 0; + }; + + IwdFile(IParent* parent, const unzFile container, const int64_t size) + : m_parent(parent), + m_open(true), + m_size(size), + m_container(container), + m_peeked(false), + m_peek_symbol(0) + { + } + + ~IwdFile() override + { + if (m_open) + { + close(); + } + } + + IwdFile(const IwdFile& other) = default; + IwdFile(IwdFile&& other) noexcept = default; + IwdFile& operator=(const IwdFile& other) = default; + IwdFile& operator=(IwdFile&& other) noexcept = default; + + _NODISCARD bool is_open() const override + { + return m_open; + } + + bool close() override + { + unzCloseCurrentFile(m_container); + m_open = false; + + m_parent->OnIwdFileClose(); + + return true; + } + + protected: + int_type underflow() override + { + if (m_peeked) + return m_peek_symbol; + + const auto result = unzReadCurrentFile(m_container, &m_peek_symbol, 1u); + + if (result >= 0) + { + m_peeked = true; + return m_peek_symbol; + } + + return EOF; + } + + int_type uflow() override + { + if (m_peeked) + { + m_peeked = false; + return m_peek_symbol; + } + + const auto result = unzReadCurrentFile(m_container, &m_peek_symbol, 1u); + return result >= 0 ? m_peek_symbol : EOF; + } + + std::streamsize xsgetn(char* ptr, std::streamsize count) override + { + if (m_peeked && count >= 1) + { + *ptr = static_cast(m_peek_symbol); + ptr++; + count--; + } + + const auto result = unzReadCurrentFile(m_container, ptr, static_cast(count)); + + return result >= 0 ? static_cast(result) : 0; + } + + pos_type seekoff(const off_type off, const std::ios_base::seekdir dir, const std::ios_base::openmode mode) override + { + const auto currentPos = unztell64(m_container); + + pos_type targetPos; + if (dir == std::ios_base::beg) + { + targetPos = off; + } + else if (dir == std::ios_base::cur) + { + targetPos = static_cast(currentPos) + off; + } + else + { + targetPos = m_size - off; + } + + return seekpos(targetPos, mode); + } + + pos_type seekpos(const pos_type pos, const std::ios_base::openmode mode) override + { + const auto currentPos = unztell64(m_container); + + if (static_cast(currentPos) < pos) + { + auto skipAmount = pos - static_cast(currentPos); + while (skipAmount > 0) + { + char temp[1024]; + const auto toRead = skipAmount > sizeof(temp) ? sizeof(temp) : static_cast(skipAmount); + unzReadCurrentFile(m_container, temp, toRead); + skipAmount -= toRead; + } + + return pos; + } + + if (currentPos == pos) + return currentPos; + + return std::streampos(-1); + } + + private: + IParent* m_parent; + bool m_open; + int64_t m_size; + unzFile m_container; + bool m_peeked; + int_type m_peek_symbol; + }; + + struct IwdEntry + { + int64_t m_size; + unz_file_pos m_file_pos; + + explicit IwdEntry(const int64_t size) + : m_size(size), + m_file_pos{} + { + } + }; + + class Iwd final : public ISearchPath, public IwdFile::IParent + { + public: + Iwd(std::string path, std::ifstream stream) + : m_path(std::move(path)), + m_stream(std::move(stream)), + m_unz_file{}, + m_has_open_file(false) + { + } + + ~Iwd() override + { + if (m_unz_file != nullptr) + { + unzClose(m_unz_file); + m_unz_file = nullptr; + } + } + + Iwd(const Iwd& other) = delete; + Iwd(Iwd&& other) noexcept = delete; + Iwd& operator=(const Iwd& other) = delete; + Iwd& operator=(Iwd&& other) noexcept = delete; + + /** + * \brief Initializes the IWD container. + * \return \c true when initialization was successful. + */ + bool Initialize() + { + auto ioFunctions = FileToZlibWrapper::CreateFunctions32ForFile(&m_stream); + m_unz_file = unzOpen2("", &ioFunctions); + + if (m_unz_file == nullptr) + { + std::cerr << std::format("Could not open IWD \"{}\"\n", m_path); + return false; + } + + auto ret = unzGoToFirstFile(m_unz_file); + while (ret == Z_OK) + { + unz_file_info64 info; + char fileNameBuffer[256]; + unzGetCurrentFileInfo64(m_unz_file, &info, fileNameBuffer, sizeof(fileNameBuffer), nullptr, 0, nullptr, 0); + + std::string fileName(fileNameBuffer); + fs::path path(fileName); + + if (path.has_filename()) + { + IwdEntry entry(static_cast(info.uncompressed_size)); + unzGetFilePos(m_unz_file, &entry.m_file_pos); + m_entry_map.emplace(std::move(fileName), entry); + } + + ret = unzGoToNextFile(m_unz_file); + } + + std::cout << std::format("Loaded IWD \"{}\" with {} entries\n", m_path, m_entry_map.size()); + + return true; + } + + SearchPathOpenFile Open(const std::string& fileName) override + { + if (m_unz_file == nullptr) + { + return SearchPathOpenFile(); + } + + auto iwdFilename = fileName; + std::ranges::replace(iwdFilename, '\\', '/'); + + const auto iwdEntry = m_entry_map.find(iwdFilename); + + if (iwdEntry != m_entry_map.end()) + { + assert(!m_has_open_file); + if (m_has_open_file) + { + std::cerr << "Trying to open new IWD file while last one was not yet closed.\n"; + return SearchPathOpenFile(); + } + + auto pos = iwdEntry->second.m_file_pos; + unzGoToFilePos(m_unz_file, &pos); + + if (unzOpenCurrentFile(m_unz_file) == UNZ_OK) + { + auto result = std::make_unique(this, m_unz_file, iwdEntry->second.m_size); + m_has_open_file = true; + return SearchPathOpenFile(std::make_unique(std::move(result)), iwdEntry->second.m_size); + } + + return SearchPathOpenFile(); + } + + return SearchPathOpenFile(); + } + + const std::string& GetPath() override + { + return m_path; + } + + void OnIwdFileClose() override + { + m_has_open_file = false; + } + + void Find(const SearchPathSearchOptions& options, const std::function& callback) override + { + if (options.m_disk_files_only) + { + return; + } + + for (const auto& [entryName, entry] : m_entry_map) + { + std::filesystem::path entryPath(entryName); + + if (!options.m_should_include_subdirectories && entryPath.has_parent_path()) + continue; + + if (options.m_filter_extensions && options.m_extension != entryPath.extension().string()) + continue; + + callback(entryName); + } + } + + private: + std::string m_path; + std::ifstream m_stream; + unzFile m_unz_file; + bool m_has_open_file; + + std::map m_entry_map; + }; +} // namespace + +namespace iwd +{ + std::unique_ptr LoadFromFile(const std::string& path) + { + std::ifstream inputStream(path, std::ios::in | std::ios::binary); + if (!inputStream.is_open()) + return {}; + + auto iwd = std::make_unique(path, std::move(inputStream)); + if (!iwd->Initialize()) + return {}; + + return iwd; + } +} // namespace iwd diff --git a/src/ObjLoading/SearchPath/IWD.h b/src/ObjLoading/SearchPath/IWD.h new file mode 100644 index 00000000..df6ddcf4 --- /dev/null +++ b/src/ObjLoading/SearchPath/IWD.h @@ -0,0 +1,11 @@ +#pragma once + +#include "SearchPath/ISearchPath.h" + +#include +#include + +namespace iwd +{ + std::unique_ptr LoadFromFile(const std::string& path); +} diff --git a/src/ObjLoading/Sound/SoundCurveLoader.cpp b/src/ObjLoading/Sound/SoundCurveLoader.cpp deleted file mode 100644 index cb5034dd..00000000 --- a/src/ObjLoading/Sound/SoundCurveLoader.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "SoundCurveLoader.h" - -#include "Parsing/Graph2D/Graph2DReader.h" - -#include - -namespace sound_curve -{ - std::unique_ptr LoadSoundCurve(const IAssetLoadingManager* manager, const std::string& soundCurveName) - { - auto& searchPath = manager->GetAssetLoadingContext()->m_raw_search_path; - const auto fileName = std::format("soundaliases/{}.vfcurve", soundCurveName); - const auto file = searchPath.Open(fileName); - if (!file.IsOpen()) - { - return nullptr; - } - - return graph2d::Read("sound curve", "SNDCURVE", *file.m_stream, fileName, soundCurveName); - } -} // namespace sound_curve diff --git a/src/ObjLoading/Sound/SoundCurveLoader.h b/src/ObjLoading/Sound/SoundCurveLoader.h deleted file mode 100644 index 7982e780..00000000 --- a/src/ObjLoading/Sound/SoundCurveLoader.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "AssetLoading/IAssetLoadingManager.h" -#include "Parsing/GenericGraph2D.h" - -#include - -namespace sound_curve -{ - std::unique_ptr LoadSoundCurve(const IAssetLoadingManager* manager, const std::string& soundCurveName); -} diff --git a/src/ObjLoading/StructuredDataDef/StructuredDataDefReader.cpp b/src/ObjLoading/StructuredDataDef/StructuredDataDefReader.cpp index 8b5fab15..c5c9f62c 100644 --- a/src/ObjLoading/StructuredDataDef/StructuredDataDefReader.cpp +++ b/src/ObjLoading/StructuredDataDef/StructuredDataDefReader.cpp @@ -7,28 +7,24 @@ #include "Parsing/Impl/ParserSingleInputStream.h" #include "StructuredDataDef/Parsing/StructuredDataDefParser.h" +#include +#include + using namespace sdd; -StructuredDataDefReader::StructuredDataDefReader(std::istream& stream, std::string fileName) - : StructuredDataDefReader(stream, std::move(fileName), nullptr) -{ -} - -StructuredDataDefReader::StructuredDataDefReader(std::istream& stream, std::string fileName, include_callback_t includeCallback) - : m_file_name(std::move(fileName)), +StructuredDataDefReader::StructuredDataDefReader(std::istream& stream, std::string fileName, ISearchPath& searchPath) + : SearchPathMultiInputStream(searchPath), + m_file_name(std::move(fileName)), m_stream(nullptr) { - OpenBaseStream(stream, std::move(includeCallback)); + OpenBaseStream(stream); SetupStreamProxies(); m_stream = m_open_streams.back().get(); } -bool StructuredDataDefReader::OpenBaseStream(std::istream& stream, include_callback_t includeCallback) +bool StructuredDataDefReader::OpenBaseStream(std::istream& stream) { - if (includeCallback) - m_open_streams.emplace_back(std::make_unique(stream, m_file_name, std::move(includeCallback))); - else - m_open_streams.emplace_back(std::make_unique(stream, m_file_name)); + m_open_streams.emplace_back(std::make_unique(stream, m_file_name, *this)); return true; } @@ -58,6 +54,7 @@ std::vector> StructuredDataDefReader::R if (success) return parser->GetDefs(); - std::cout << "Parsing structured data def file \"" << m_file_name << "\" failed!\n"; + std::cerr << std::format("Parsing structured data def file \"{}\" failed!\n", m_file_name); + return {}; } diff --git a/src/ObjLoading/StructuredDataDef/StructuredDataDefReader.h b/src/ObjLoading/StructuredDataDef/StructuredDataDefReader.h index 3ecb8899..b5bdaa66 100644 --- a/src/ObjLoading/StructuredDataDef/StructuredDataDefReader.h +++ b/src/ObjLoading/StructuredDataDef/StructuredDataDefReader.h @@ -1,28 +1,26 @@ #pragma once #include "Parsing/IParserLineStream.h" +#include "SearchPath/ISearchPath.h" +#include "SearchPath/SearchPathMultiInputStream.h" #include "StructuredDataDef/CommonStructuredDataDef.h" #include #include #include -class StructuredDataDefReader +class StructuredDataDefReader : public SearchPathMultiInputStream { public: - using include_callback_t = std::function(const std::string& filename, const std::string& sourceFile)>; + StructuredDataDefReader(std::istream& stream, std::string fileName, ISearchPath& searchPath); + + std::vector> ReadStructureDataDefs(bool& success); private: + bool OpenBaseStream(std::istream& stream); + void SetupStreamProxies(); + std::string m_file_name; IParserLineStream* m_stream; std::vector> m_open_streams; - - bool OpenBaseStream(std::istream& stream, include_callback_t includeCallback); - void SetupStreamProxies(); - -public: - StructuredDataDefReader(std::istream& stream, std::string fileName); - StructuredDataDefReader(std::istream& stream, std::string fileName, include_callback_t includeCallback); - - std::vector> ReadStructureDataDefs(bool& success); }; diff --git a/src/ObjLoading/Techset/TechniqueStateMapCache.h b/src/ObjLoading/Techset/TechniqueStateMapCache.h index 5d9d29a6..aaf8b245 100644 --- a/src/ObjLoading/Techset/TechniqueStateMapCache.h +++ b/src/ObjLoading/Techset/TechniqueStateMapCache.h @@ -1,6 +1,6 @@ #pragma once -#include "AssetLoading/IZoneAssetLoaderState.h" +#include "Asset/IZoneAssetCreationState.h" #include "StateMap/StateMapDefinition.h" #include "Utils/ClassUtils.h" @@ -10,7 +10,7 @@ namespace techset { - class TechniqueStateMapCache final : public IZoneAssetLoaderState + class TechniqueStateMapCache final : public IZoneAssetCreationState { public: _NODISCARD const state_map::StateMapDefinition* GetCachedStateMap(const std::string& name) const; diff --git a/src/ObjLoading/Techset/TechsetDefinitionCache.h b/src/ObjLoading/Techset/TechsetDefinitionCache.h index 83bff720..b231f56c 100644 --- a/src/ObjLoading/Techset/TechsetDefinitionCache.h +++ b/src/ObjLoading/Techset/TechsetDefinitionCache.h @@ -1,6 +1,6 @@ #pragma once -#include "AssetLoading/IZoneAssetLoaderState.h" +#include "Asset/IZoneAssetCreationState.h" #include "TechsetDefinition.h" #include "Utils/ClassUtils.h" @@ -10,7 +10,7 @@ namespace techset { - class TechsetDefinitionCache final : public IZoneAssetLoaderState + class TechsetDefinitionCache final : public IZoneAssetCreationState { public: _NODISCARD TechsetDefinition* GetCachedTechsetDefinition(const std::string& techsetName) const; diff --git a/src/ObjLoading/Techset/TechsetFileReader.cpp b/src/ObjLoading/Techset/TechsetFileReader.cpp index ee1f11fb..6a704b0a 100644 --- a/src/ObjLoading/Techset/TechsetFileReader.cpp +++ b/src/ObjLoading/Techset/TechsetFileReader.cpp @@ -4,6 +4,7 @@ #include "Parsing/Impl/ParserSingleInputStream.h" #include "Parsing/TechsetFileParser.h" +#include #include using namespace techset; @@ -33,6 +34,6 @@ std::unique_ptr TechsetFileReader::ReadTechsetDefini if (success) return parser->GetTechsetDefinition(); - std::cout << "Parsing techset file \"" << m_file_name << "\" failed!\n"; - return {}; + std::cerr << std::format("Parsing techset file \"{}\" failed!\n", m_file_name); + return nullptr; } diff --git a/src/ObjLoading/Weapon/AccuracyGraphLoader.cpp b/src/ObjLoading/Weapon/AccuracyGraphLoader.cpp index de09c162..75c22889 100644 --- a/src/ObjLoading/Weapon/AccuracyGraphLoader.cpp +++ b/src/ObjLoading/Weapon/AccuracyGraphLoader.cpp @@ -7,9 +7,8 @@ namespace { - std::unique_ptr LoadAccuracyGraph(const IAssetLoadingManager* manager, const std::string& graphName, const std::string& subFolder) + std::unique_ptr LoadAccuracyGraph(ISearchPath& searchPath, const std::string& graphName, const std::string& subFolder) { - auto& searchPath = manager->GetAssetLoadingContext()->m_raw_search_path; const auto fileName = std::format("accuracy/{}/{}", subFolder, graphName); const auto file = searchPath.Open(fileName); if (!file.IsOpen()) @@ -22,13 +21,13 @@ namespace } } // namespace -const GenericGraph2D* AccuracyGraphLoader::LoadAiVsAiGraph(const IAssetLoadingManager* manager, const std::string& graphName) +const GenericGraph2D* AccuracyGraphLoader::LoadAiVsAiGraph(ISearchPath& searchPath, const std::string& graphName) { const auto alreadyLoadedGraph = m_loaded_ai_vs_ai_graphs.find(graphName); if (alreadyLoadedGraph != m_loaded_ai_vs_ai_graphs.end()) return alreadyLoadedGraph->second.get(); - auto graph = LoadAccuracyGraph(manager, graphName, "aivsai"); + auto graph = LoadAccuracyGraph(searchPath, graphName, "aivsai"); if (!graph) return nullptr; @@ -38,13 +37,13 @@ const GenericGraph2D* AccuracyGraphLoader::LoadAiVsAiGraph(const IAssetLoadingMa return graphPtr; } -const GenericGraph2D* AccuracyGraphLoader::LoadAiVsPlayerGraph(const IAssetLoadingManager* manager, const std::string& graphName) +const GenericGraph2D* AccuracyGraphLoader::LoadAiVsPlayerGraph(ISearchPath& searchPath, const std::string& graphName) { const auto alreadyLoadedGraph = m_loaded_ai_vs_player_graphs.find(graphName); if (alreadyLoadedGraph != m_loaded_ai_vs_player_graphs.end()) return alreadyLoadedGraph->second.get(); - auto graph = LoadAccuracyGraph(manager, graphName, "aivsplayer"); + auto graph = LoadAccuracyGraph(searchPath, graphName, "aivsplayer"); if (!graph) return nullptr; diff --git a/src/ObjLoading/Weapon/AccuracyGraphLoader.h b/src/ObjLoading/Weapon/AccuracyGraphLoader.h index 216e6618..99610f22 100644 --- a/src/ObjLoading/Weapon/AccuracyGraphLoader.h +++ b/src/ObjLoading/Weapon/AccuracyGraphLoader.h @@ -1,15 +1,18 @@ #pragma once -#include "AssetLoading/IAssetLoadingManager.h" -#include "AssetLoading/IZoneAssetLoaderState.h" + +#include "Asset/IZoneAssetCreationState.h" #include "Parsing/GenericGraph2D.h" +#include "SearchPath/ISearchPath.h" #include +#include +#include -class AccuracyGraphLoader final : public IZoneAssetLoaderState +class AccuracyGraphLoader final : public IZoneAssetCreationState { public: - const GenericGraph2D* LoadAiVsAiGraph(const IAssetLoadingManager* manager, const std::string& graphName); - const GenericGraph2D* LoadAiVsPlayerGraph(const IAssetLoadingManager* manager, const std::string& graphName); + const GenericGraph2D* LoadAiVsAiGraph(ISearchPath& searchPath, const std::string& graphName); + const GenericGraph2D* LoadAiVsPlayerGraph(ISearchPath& searchPath, const std::string& graphName); private: std::unordered_map> m_loaded_ai_vs_ai_graphs; diff --git a/src/ObjLoading/XModel/XModelLoader.cpp.template b/src/ObjLoading/XModel/LoaderXModel.cpp.template similarity index 92% rename from src/ObjLoading/XModel/XModelLoader.cpp.template rename to src/ObjLoading/XModel/LoaderXModel.cpp.template index 01994f05..28447a8d 100644 --- a/src/ObjLoading/XModel/XModelLoader.cpp.template +++ b/src/ObjLoading/XModel/LoaderXModel.cpp.template @@ -1,8 +1,8 @@ #options GAME(IW5, T5, T6) -#filename "Game/" + GAME + "/XModel/XModelLoader" + GAME + ".cpp" +#filename "Game/" + GAME + "/XModel/LoaderXModel" + GAME + ".cpp" -#set LOADER_HEADER "\"XModelLoader" + GAME + ".h\"" +#set LOADER_HEADER "\"LoaderXModel" + GAME + ".h\"" #set COMMON_HEADER "\"Game/" + GAME + "/Common" + GAME + ".h\"" #set CONSTANTS_HEADER "\"Game/" + GAME + "/XModel/XModelConstants" + GAME + ".h\"" #set JSON_HEADER "\"Game/" + GAME + "/XModel/JsonXModel" + GAME + ".h\"" @@ -21,6 +21,7 @@ #include CONSTANTS_HEADER #include JSON_HEADER +#include "Asset/AssetRegistration.h" #include "ObjLoading.h" #include "Utils/QuatInt16.h" #include "Utils/StringUtils.h" @@ -46,25 +47,43 @@ #include #include -namespace GAME +using namespace GAME; + +namespace { - class XModelLoader + class XModelLoader final : public AssetCreator { public: - XModelLoader(std::istream& stream, MemoryManager& memory, IAssetLoadingManager& manager, std::set& dependencies) - : m_stream(stream), - m_memory(memory), - m_script_strings(manager.GetAssetLoadingContext()->m_zone.m_script_strings), - m_manager(manager), - m_part_classification_state(*m_manager.GetAssetLoadingContext()->GetZoneAssetLoaderState()), - m_dependencies(dependencies) - + XModelLoader(MemoryManager& memory, ISearchPath& searchPath, ZoneScriptStrings& scriptStrings) + : m_memory(memory), + m_search_path(searchPath), + m_script_strings(scriptStrings) { } - bool Load(XModel& xmodel) + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - const auto jRoot = nlohmann::json::parse(m_stream); + const auto file = m_search_path.Open(std::format("xmodel/{}.json", assetName)); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + auto* xmodel = m_memory.Alloc(); + xmodel->name = m_memory.Dup(assetName.c_str()); + + AssetRegistration registration(assetName, xmodel); + if (!LoadFromFile(*file.m_stream, *xmodel, context, registration)) + { + std::cerr << std::format("Failed to load xmodel \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); + } + + private: + bool LoadFromFile(std::istream& jsonStream, XModel& xmodel, AssetCreationContext& context, AssetRegistration& registration) + { + const auto jRoot = nlohmann::json::parse(jsonStream); std::string type; unsigned version; @@ -80,7 +99,7 @@ namespace GAME try { const auto jXModel = jRoot.get(); - return CreateXModelFromJson(jXModel, xmodel); + return CreateXModelFromJson(jXModel, xmodel, context, registration); } catch (const nlohmann::json::exception& e) { @@ -90,7 +109,6 @@ namespace GAME return false; } - private: static void PrintError(const XModel& xmodel, const std::string& message) { std::cerr << std::format("Cannot load xmodel \"{}\": {}\n", xmodel.name, message); @@ -234,12 +252,12 @@ namespace GAME info.radiusSquared = halfSizeEigen.squaredNorm(); } - bool ApplyCommonBonesToXModel(const JsonXModelLod& jLod, XModel& xmodel, unsigned lodNumber, const XModelCommon& common) const + bool ApplyCommonBonesToXModel(const JsonXModelLod& jLod, XModel& xmodel, unsigned lodNumber, const XModelCommon& common) { if (common.m_bones.empty()) return true; - m_part_classification_state.Load(HITLOC_NAMES, std::extent_v, m_manager); + m_part_classification_state.Load(HITLOC_NAMES, std::extent_v, m_search_path); const auto boneCount = common.m_bones.size(); constexpr auto maxBones = std::numeric_limits::max(); @@ -614,9 +632,9 @@ namespace GAME return true; } - bool LoadLod(const JsonXModelLod& jLod, XModel& xmodel, unsigned lodNumber) + bool LoadLod(const JsonXModelLod& jLod, XModel& xmodel, unsigned lodNumber, AssetCreationContext& context, AssetRegistration& registration) { - const auto file = m_manager.GetAssetLoadingContext()->m_raw_search_path.Open(jLod.file); + const auto file = m_search_path.Open(jLod.file); if (!file.IsOpen()) { PrintError(xmodel, std::format("Failed to open file for lod {}: \"{}\"", lodNumber, jLod.file)); @@ -664,11 +682,11 @@ namespace GAME materialAssets.reserve(common->m_materials.size()); for (const auto& commonMaterial : common->m_materials) { - auto* assetInfo = m_manager.LoadDependency(commonMaterial.name); + auto* assetInfo = context.LoadDependency(commonMaterial.name); if (!assetInfo) return false; - m_dependencies.emplace(assetInfo); + registration.AddDependency(assetInfo); materialAssets.push_back(assetInfo->Asset()); } @@ -712,7 +730,7 @@ namespace GAME modelSurfs->surfs = m_memory.Alloc(modelSurfs->numsurfs); memcpy(modelSurfs->surfs, &m_surfaces[lodInfo.surfIndex], sizeof(XSurface) * modelSurfs->numsurfs); - m_manager.AddAsset(modelSurfsName, modelSurfs); + registration.AddDependency(context.AddAsset(modelSurfsName, modelSurfs)); lodInfo.modelSurfs = modelSurfs; lodInfo.surfs = modelSurfs->surfs; @@ -785,7 +803,7 @@ namespace GAME #endif } - bool CreateXModelFromJson(const JsonXModel& jXModel, XModel& xmodel) + bool CreateXModelFromJson(const JsonXModel& jXModel, XModel& xmodel, AssetCreationContext& context, AssetRegistration& registration) { constexpr auto maxLods = std::extent_v; if (jXModel.lods.size() > maxLods) @@ -798,7 +816,7 @@ namespace GAME xmodel.numLods = static_cast(jXModel.lods.size()); for (const auto& jLod : jXModel.lods) { - if (!LoadLod(jLod, xmodel, lodNumber++)) + if (!LoadLod(jLod, xmodel, lodNumber++, context, registration)) return false; } @@ -835,13 +853,13 @@ namespace GAME if (jXModel.physPreset) { - auto* physPreset = m_manager.LoadDependency(jXModel.physPreset.value()); + auto* physPreset = context.LoadDependency(jXModel.physPreset.value()); if (!physPreset) { PrintError(xmodel, "Could not find phys preset"); return false; } - m_dependencies.emplace(physPreset); + registration.AddDependency(physPreset); xmodel.physPreset = physPreset->Asset(); } else @@ -852,13 +870,13 @@ namespace GAME #if defined(FEATURE_IW5) if (jXModel.physCollmap) { - auto* physCollmap = m_manager.LoadDependency(jXModel.physCollmap.value()); + auto* physCollmap = context.LoadDependency(jXModel.physCollmap.value()); if (!physCollmap) { PrintError(xmodel, "Could not find phys collmap"); return false; } - m_dependencies.emplace(physCollmap); + registration.AddDependency(physCollmap); xmodel.physCollmap = physCollmap->Asset(); } else @@ -870,13 +888,13 @@ namespace GAME #if defined(FEATURE_T5) || defined(FEATURE_T6) if (jXModel.physConstraints) { - auto* physConstraints = m_manager.LoadDependency(jXModel.physConstraints.value()); + auto* physConstraints = context.LoadDependency(jXModel.physConstraints.value()); if (!physConstraints) { PrintError(xmodel, "Could not find phys constraints"); return false; } - m_dependencies.emplace(physConstraints); + registration.AddDependency(physConstraints); xmodel.physConstraints = physConstraints->Asset(); } else @@ -900,21 +918,17 @@ namespace GAME std::vector m_surfaces; std::vector m_materials; - std::istream& m_stream; MemoryManager& m_memory; + ISearchPath& m_search_path; ZoneScriptStrings& m_script_strings; - IAssetLoadingManager& m_manager; - PartClassificationState& m_part_classification_state; - std::set& m_dependencies; + PartClassificationState m_part_classification_state; }; +} // namespace GAME - bool LoadXModel(std::istream& stream, XModel& xmodel, MemoryManager* memory, IAssetLoadingManager* manager, std::vector& dependencies) +namespace GAME +{ + std::unique_ptr> CreateXModelLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) { - std::set dependenciesSet; - XModelLoader loader(stream, *memory, *manager, dependenciesSet); - - dependencies.assign(dependenciesSet.cbegin(), dependenciesSet.cend()); - - return loader.Load(xmodel); + return std::make_unique(memory, searchPath, zone.m_script_strings); } } // namespace GAME diff --git a/src/ObjLoading/XModel/LoaderXModel.h.template b/src/ObjLoading/XModel/LoaderXModel.h.template new file mode 100644 index 00000000..16075cb2 --- /dev/null +++ b/src/ObjLoading/XModel/LoaderXModel.h.template @@ -0,0 +1,19 @@ +#options GAME (IW5, T5, T6) + +#filename "Game/" + GAME + "/XModel/LoaderXModel" + GAME + ".h" + +#set GAME_HEADER "\"Game/" + GAME + "/" + GAME + ".h\"" + +#pragma once + +#include "Asset/IAssetCreator.h" +#include GAME_HEADER +#include "SearchPath/ISearchPath.h" +#include "Utils/MemoryManager.h" + +#include + +namespace GAME +{ + std::unique_ptr> CreateXModelLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace GAME diff --git a/src/ObjLoading/XModel/PartClassificationState.cpp b/src/ObjLoading/XModel/PartClassificationState.cpp index 6667a4df..e314b03e 100644 --- a/src/ObjLoading/XModel/PartClassificationState.cpp +++ b/src/ObjLoading/XModel/PartClassificationState.cpp @@ -12,7 +12,7 @@ PartClassificationState::PartClassificationState() { } -bool PartClassificationState::Load(const char** hitLocNames, const size_t hitLocNameCount, const IAssetLoadingManager& manager) +bool PartClassificationState::Load(const char** hitLocNames, const size_t hitLocNameCount, ISearchPath& searchPath) { if (m_loaded) return true; @@ -20,7 +20,7 @@ bool PartClassificationState::Load(const char** hitLocNames, const size_t hitLoc if (ObjLoading::Configuration.Verbose) std::cout << "Loading part classification...\n"; - const auto file = manager.GetAssetLoadingContext()->m_raw_search_path.Open(PART_CLASSIFICATION_FILE); + const auto file = searchPath.Open(PART_CLASSIFICATION_FILE); if (!file.IsOpen()) { std::cerr << std::format("Could not load part classification: Failed to open {}\n", PART_CLASSIFICATION_FILE); diff --git a/src/ObjLoading/XModel/PartClassificationState.h b/src/ObjLoading/XModel/PartClassificationState.h index 32bd4afc..76e95a11 100644 --- a/src/ObjLoading/XModel/PartClassificationState.h +++ b/src/ObjLoading/XModel/PartClassificationState.h @@ -1,8 +1,13 @@ #pragma once -#include "AssetLoading/IAssetLoadingManager.h" -#include "AssetLoading/IZoneAssetLoaderState.h" -class PartClassificationState final : public IZoneAssetLoaderState +#include "SearchPath/ISearchPath.h" + +#include +#include +#include +#include + +class PartClassificationState { // TODO: Use MP part classifications when building an mp fastfile static constexpr auto PART_CLASSIFICATION_FILE = "partclassification.csv"; @@ -12,7 +17,7 @@ class PartClassificationState final : public IZoneAssetLoaderState public: PartClassificationState(); - bool Load(const char** hitLocNames, size_t hitLocNameCount, const IAssetLoadingManager& manager); + bool Load(const char** hitLocNames, size_t hitLocNameCount, ISearchPath& searchPath); [[nodiscard]] unsigned GetPartClassificationForBoneName(const std::string& boneName) const; diff --git a/src/ObjLoading/XModel/XModelLoader.h.template b/src/ObjLoading/XModel/XModelLoader.h.template deleted file mode 100644 index 3b9d0729..00000000 --- a/src/ObjLoading/XModel/XModelLoader.h.template +++ /dev/null @@ -1,19 +0,0 @@ -#options GAME (IW5, T5, T6) - -#filename "Game/" + GAME + "/XModel/XModelLoader" + GAME + ".h" - -#set GAME_HEADER "\"Game/" + GAME + "/" + GAME + ".h\"" - -#pragma once - -#include "AssetLoading/IAssetLoadingManager.h" -#include GAME_HEADER -#include "Utils/MemoryManager.h" - -#include -#include - -namespace GAME -{ - bool LoadXModel(std::istream& stream, XModel& xmodel, MemoryManager* memory, IAssetLoadingManager* manager, std::vector& dependencies); -} diff --git a/src/ObjWriting.lua b/src/ObjWriting.lua index ac3e69e8..186fa9d1 100644 --- a/src/ObjWriting.lua +++ b/src/ObjWriting.lua @@ -19,7 +19,6 @@ function ObjWriting:link(links) links:linkto(ObjImage) links:linkto(ObjLoading) links:linkto(ZoneCommon) - links:linkto(minilzo) links:linkto(minizip) links:linkto(libtomcrypt) end @@ -57,7 +56,6 @@ function ObjWriting:project() self:include(includes) Utils:include(includes) - minilzo:include(includes) minizip:include(includes) eigen:include(includes) json:include(includes) diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPhysPreset.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPhysPreset.cpp index 05fe779d..bfd6d990 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPhysPreset.cpp +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPhysPreset.cpp @@ -1,8 +1,8 @@ #include "AssetDumperPhysPreset.h" #include "Game/IW4/InfoString/InfoStringFromStructConverter.h" -#include "Game/IW4/InfoString/PhysPresetFields.h" #include "Game/IW4/ObjConstantsIW4.h" +#include "Game/IW4/PhysPreset/PhysPresetFields.h" #include #include diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTracer.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTracer.cpp index 57592ec2..3a903ebc 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTracer.cpp +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTracer.cpp @@ -2,8 +2,8 @@ #include "Game/IW4/CommonIW4.h" #include "Game/IW4/InfoString/InfoStringFromStructConverter.h" -#include "Game/IW4/InfoString/TracerFields.h" #include "Game/IW4/ObjConstantsIW4.h" +#include "Game/IW4/Tracer/TracerFields.h" #include #include diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVehicle.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVehicle.cpp index d70224c4..56ab8de7 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVehicle.cpp +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVehicle.cpp @@ -3,8 +3,8 @@ #include "Game/IW4/CommonIW4.h" #include "Game/IW4/InfoString/EnumStrings.h" #include "Game/IW4/InfoString/InfoStringFromStructConverter.h" -#include "Game/IW4/InfoString/VehicleFields.h" #include "Game/IW4/ObjConstantsIW4.h" +#include "Game/IW4/Vehicle/VehicleFields.h" #include #include diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.cpp index b61f03a3..e95f3ef5 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.cpp +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.cpp @@ -3,8 +3,8 @@ #include "Game/IW4/CommonIW4.h" #include "Game/IW4/InfoString/EnumStrings.h" #include "Game/IW4/InfoString/InfoStringFromStructConverter.h" -#include "Game/IW4/InfoString/WeaponFields.h" #include "Game/IW4/ObjConstantsIW4.h" +#include "Game/IW4/Weapon/WeaponFields.h" #include "Weapon/AccuracyGraphWriter.h" #include diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperWeapon.cpp b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperWeapon.cpp index 15d5fd5b..83e4cc93 100644 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperWeapon.cpp +++ b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperWeapon.cpp @@ -2,8 +2,8 @@ #include "Game/IW5/CommonIW5.h" #include "Game/IW5/InfoString/InfoStringFromStructConverter.h" -#include "Game/IW5/InfoString/WeaponFields.h" #include "Game/IW5/ObjConstantsIW5.h" +#include "Game/IW5/Weapon/WeaponFields.h" #include "Weapon/AccuracyGraphWriter.h" #include diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysConstraints.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysConstraints.cpp index f4294adf..7be1250a 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysConstraints.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysConstraints.cpp @@ -1,9 +1,8 @@ #include "AssetDumperPhysConstraints.h" -#include "Game/T6/InfoString/EnumStrings.h" #include "Game/T6/InfoString/InfoStringFromStructConverter.h" -#include "Game/T6/InfoString/PhysConstraintsFields.h" #include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/PhysConstraints/PhysConstraintsFields.h" #include #include diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysPreset.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysPreset.cpp index e801928d..d11819f4 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysPreset.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysPreset.cpp @@ -1,8 +1,8 @@ #include "AssetDumperPhysPreset.h" #include "Game/T6/InfoString/InfoStringFromStructConverter.h" -#include "Game/T6/InfoString/PhysPresetFields.h" #include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/PhysPreset/PhysPresetFields.h" #include #include diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTracer.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTracer.cpp index 1ecefb98..0c87e4ee 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTracer.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTracer.cpp @@ -1,9 +1,8 @@ #include "AssetDumperTracer.h" -#include "Game/T6/InfoString/EnumStrings.h" #include "Game/T6/InfoString/InfoStringFromStructConverter.h" -#include "Game/T6/InfoString/TracerFields.h" #include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/Tracer/TracerFields.h" #include #include diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperVehicle.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperVehicle.cpp index 2da65383..cccf418a 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperVehicle.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperVehicle.cpp @@ -1,9 +1,8 @@ #include "AssetDumperVehicle.h" -#include "Game/T6/InfoString/EnumStrings.h" #include "Game/T6/InfoString/InfoStringFromStructConverter.h" -#include "Game/T6/InfoString/VehicleFields.h" #include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/Vehicle/VehicleFields.h" #include #include diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeapon.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeapon.cpp index 79eb9963..24223dc4 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeapon.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeapon.cpp @@ -1,9 +1,9 @@ #include "AssetDumperWeapon.h" -#include "Game/T6/InfoString/EnumStrings.h" #include "Game/T6/InfoString/InfoStringFromStructConverter.h" -#include "Game/T6/InfoString/WeaponFields.h" #include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/Weapon/WeaponFields.h" +#include "Game/T6/Weapon/WeaponStrings.h" #include "Weapon/AccuracyGraphWriter.h" #include diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponAttachment.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponAttachment.cpp index eafec094..0c7fd032 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponAttachment.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponAttachment.cpp @@ -1,9 +1,9 @@ #include "AssetDumperWeaponAttachment.h" -#include "Game/T6/InfoString/EnumStrings.h" #include "Game/T6/InfoString/InfoStringFromStructConverter.h" -#include "Game/T6/InfoString/WeaponAttachmentFields.h" #include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/Weapon/AttachmentFields.h" +#include "Game/T6/Weapon/WeaponStrings.h" #include #include diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponAttachmentUnique.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponAttachmentUnique.cpp index a24006ee..6730771a 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponAttachmentUnique.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponAttachmentUnique.cpp @@ -1,9 +1,9 @@ #include "AssetDumperWeaponAttachmentUnique.h" -#include "Game/T6/InfoString/EnumStrings.h" #include "Game/T6/InfoString/InfoStringFromStructConverter.h" -#include "Game/T6/InfoString/WeaponAttachmentUniqueFields.h" #include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/Weapon/AttachmentUniqueFields.h" +#include "Game/T6/Weapon/WeaponStrings.h" #include #include diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperZBarrier.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperZBarrier.cpp index 1272de95..da165648 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperZBarrier.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperZBarrier.cpp @@ -1,8 +1,8 @@ #include "AssetDumperZBarrier.h" #include "Game/T6/InfoString/InfoStringFromStructConverter.h" -#include "Game/T6/InfoString/ZBarrierFields.h" #include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/ZBarrier/ZBarrierFields.h" #include #include diff --git a/src/ObjWriting/ObjContainer/IPak/IPakWriter.cpp b/src/ObjWriting/ObjContainer/IPak/IPakWriter.cpp deleted file mode 100644 index 819cdf14..00000000 --- a/src/ObjWriting/ObjContainer/IPak/IPakWriter.cpp +++ /dev/null @@ -1,383 +0,0 @@ -#include "IPakWriter.h" - -#include "Game/T6/CommonT6.h" -#include "Game/T6/GameT6.h" -#include "ObjContainer/IPak/IPakTypes.h" -#include "Utils/Alignment.h" - -#include -#include -#include -#include -#include - -class IPakWriterImpl final : public IPakWriter -{ - static constexpr char BRANDING[] = "Created with OAT - OpenAssetTools"; - static constexpr auto SECTION_COUNT = 3; // Index + Data + Branding - - inline static const std::string PAD_DATA = std::string(256, '\xA7'); - -public: - explicit IPakWriterImpl(std::ostream& stream, ISearchPath* assetSearchPath) - : m_stream(stream), - m_asset_search_path(assetSearchPath), - m_current_offset(0), - m_total_size(0), - m_data_section_offset(0), - m_data_section_size(0u), - m_index_section_offset(0), - m_branding_section_offset(0), - m_file_offset(0u), - m_chunk_buffer_window_start(0), - m_current_block{}, - m_current_block_header_offset(0) - { - m_decompressed_buffer = std::make_unique(ipak_consts::IPAK_CHUNK_SIZE); - m_lzo_work_buffer = std::make_unique(LZO1X_1_MEM_COMPRESS); - } - - void AddImage(std::string imageName) override - { - m_images.emplace_back(std::move(imageName)); - } - - void GoTo(const int64_t offset) - { - m_stream.seekp(offset, std::ios::beg); - m_current_offset = offset; - } - - void Write(const void* data, const size_t dataSize) - { - m_stream.write(static_cast(data), dataSize); - m_current_offset += dataSize; - } - - void Pad(const size_t paddingSize) - { - auto paddingSizeLeft = paddingSize; - while (paddingSizeLeft > 0) - { - const auto writeSize = std::min(paddingSizeLeft, PAD_DATA.size()); - Write(PAD_DATA.data(), writeSize); - - paddingSizeLeft -= writeSize; - } - } - - void AlignToChunk() - { - Pad(static_cast(utils::Align(m_current_offset, static_cast(ipak_consts::IPAK_CHUNK_SIZE)) - m_current_offset)); - } - - void AlignToBlockHeader() - { - Pad(static_cast(utils::Align(m_current_offset, static_cast(sizeof(IPakDataBlockHeader))) - m_current_offset)); - } - - void WriteHeaderData() - { - GoTo(0); - - const IPakHeader header{ipak_consts::IPAK_MAGIC, ipak_consts::IPAK_VERSION, static_cast(m_total_size), SECTION_COUNT}; - - const IPakSection dataSection{ - ipak_consts::IPAK_DATA_SECTION, - static_cast(m_data_section_offset), - static_cast(m_data_section_size), - static_cast(m_index_entries.size()), - }; - - const IPakSection indexSection{ - ipak_consts::IPAK_INDEX_SECTION, - static_cast(m_index_section_offset), - static_cast(sizeof(IPakIndexEntry) * m_index_entries.size()), - static_cast(m_index_entries.size()), - }; - - const IPakSection brandingSection{ - ipak_consts::IPAK_BRANDING_SECTION, - static_cast(m_branding_section_offset), - std::extent_v, - 1, - }; - - Write(&header, sizeof(header)); - Write(&dataSection, sizeof(dataSection)); - Write(&indexSection, sizeof(indexSection)); - Write(&brandingSection, sizeof(brandingSection)); - } - - static std::string ImageFileName(const std::string& imageName) - { - std::ostringstream ss; - ss << "images/" << imageName << ".iwi"; - - return ss.str(); - } - - std::unique_ptr ReadImageDataFromSearchPath(const std::string& imageName, size_t& imageSize) const - { - const auto fileName = ImageFileName(imageName); - - const auto openFile = m_asset_search_path->Open(fileName); - if (!openFile.IsOpen()) - { - std::cerr << "Could not open image for writing to IPak \"" << fileName << "\"\n"; - return nullptr; - } - - imageSize = static_cast(openFile.m_length); - auto imageData = std::make_unique(imageSize); - openFile.m_stream->read(imageData.get(), imageSize); - - return imageData; - } - - void FlushBlock() - { - if (m_current_block_header_offset > 0) - { - const auto previousOffset = m_current_offset; - - GoTo(m_current_block_header_offset); - Write(&m_current_block, sizeof(m_current_block)); - GoTo(previousOffset); - } - } - - void FlushChunk() - { - FlushBlock(); - AlignToBlockHeader(); - - const auto nextChunkOffset = utils::Align(m_current_offset, static_cast(ipak_consts::IPAK_CHUNK_SIZE)); - const auto sizeToSkip = static_cast(nextChunkOffset - m_current_offset); - - if (sizeToSkip >= sizeof(IPakDataBlockHeader)) - { - IPakDataBlockHeader skipBlockHeader{}; - skipBlockHeader.countAndOffset.count = 1; - skipBlockHeader.commands[0].compressed = ipak_consts::IPAK_COMMAND_SKIP; - skipBlockHeader.commands[0].size = sizeToSkip - sizeof(IPakDataBlockHeader); - Write(&skipBlockHeader, sizeof(skipBlockHeader)); - } - - AlignToChunk(); - m_chunk_buffer_window_start = m_current_offset; - } - - void StartNewBlock() - { - AlignToBlockHeader(); - - // Skip to the next chunk when only the header could fit into the current chunk anyway - if (static_cast(utils::Align(m_current_offset, static_cast(ipak_consts::IPAK_CHUNK_SIZE)) - m_current_offset) - <= sizeof(IPakDataBlockHeader)) - FlushChunk(); - - m_current_block_header_offset = m_current_offset; - m_current_block = {}; - m_current_block.countAndOffset.offset = static_cast(m_file_offset); - - // Reserve space to later write actual block header data - GoTo(m_current_offset + sizeof(IPakDataBlockHeader)); - } - - void WriteChunkData(const void* data, const size_t dataSize) - { - auto dataOffset = 0u; - while (dataOffset < dataSize) - { - if (m_current_block.countAndOffset.count >= std::extent_v) - { - FlushBlock(); - StartNewBlock(); - } - - const auto remainingSize = dataSize - dataOffset; - const auto remainingChunkBufferWindowSize = std::max((ipak_consts::IPAK_CHUNK_COUNT_PER_READ * ipak_consts::IPAK_CHUNK_SIZE) - - static_cast(m_current_offset - m_chunk_buffer_window_start), - 0u); - - if (remainingChunkBufferWindowSize == 0) - { - FlushChunk(); - StartNewBlock(); - continue; - } - - const auto commandSize = std::min(std::min(remainingSize, ipak_consts::IPAK_COMMAND_DEFAULT_SIZE), remainingChunkBufferWindowSize); - - auto writeUncompressed = true; - if (USE_COMPRESSION) - { - auto outLen = static_cast(ipak_consts::IPAK_CHUNK_SIZE); - const auto result = lzo1x_1_compress(&static_cast(data)[dataOffset], - commandSize, - reinterpret_cast(m_decompressed_buffer.get()), - &outLen, - m_lzo_work_buffer.get()); - - if (result == LZO_E_OK && outLen < commandSize) - { - writeUncompressed = false; - Write(m_decompressed_buffer.get(), outLen); - - const auto currentCommand = m_current_block.countAndOffset.count; - m_current_block.commands[currentCommand].size = static_cast(outLen); - m_current_block.commands[currentCommand].compressed = ipak_consts::IPAK_COMMAND_COMPRESSED; - m_current_block.countAndOffset.count = currentCommand + 1u; - } - } - - if (writeUncompressed) - { - Write(&static_cast(data)[dataOffset], commandSize); - - const auto currentCommand = m_current_block.countAndOffset.count; - m_current_block.commands[currentCommand].size = commandSize; - m_current_block.commands[currentCommand].compressed = ipak_consts::IPAK_COMMAND_UNCOMPRESSED; - m_current_block.countAndOffset.count = currentCommand + 1u; - } - - dataOffset += commandSize; - m_file_offset += commandSize; - } - } - - void StartNewFile() - { - FlushBlock(); - - m_file_offset = 0u; - StartNewBlock(); - m_chunk_buffer_window_start = utils::AlignToPrevious(m_current_offset, static_cast(ipak_consts::IPAK_CHUNK_SIZE)); - } - - bool WriteImageData(const std::string& imageName) - { - size_t imageSize; - const auto imageData = ReadImageDataFromSearchPath(imageName, imageSize); - if (!imageData) - return false; - - const auto nameHash = T6::Common::R_HashString(imageName.c_str(), 0); - const auto dataHash = static_cast(crc32(0u, reinterpret_cast(imageData.get()), imageSize)); - - StartNewFile(); - const auto startOffset = m_current_block_header_offset; - - IPakIndexEntry indexEntry; - indexEntry.key.nameHash = nameHash; - indexEntry.key.dataHash = dataHash & 0x1FFFFFFF; - indexEntry.offset = static_cast(startOffset - m_data_section_offset); - - WriteChunkData(imageData.get(), imageSize); - const auto writtenImageSize = static_cast(m_current_offset - startOffset); - - indexEntry.size = writtenImageSize; - m_index_entries.emplace_back(indexEntry); - - return true; - } - - bool WriteDataSection() - { - AlignToChunk(); - m_data_section_offset = m_current_offset; - m_data_section_size = 0u; - - m_index_entries.reserve(m_images.size()); - - const auto result = std::ranges::all_of(m_images, - [this](const std::string& imageName) - { - return WriteImageData(imageName); - }); - - FlushBlock(); - m_data_section_size = static_cast(m_current_offset - m_data_section_offset); - - return result; - } - - static bool CompareIndices(const IPakIndexEntry& entry1, const IPakIndexEntry& entry2) - { - return entry1.key.combinedKey < entry2.key.combinedKey; - } - - void SortIndexSectionEntries() - { - std::ranges::sort(m_index_entries, CompareIndices); - } - - void WriteIndexSection() - { - AlignToChunk(); - m_index_section_offset = m_current_offset; - - SortIndexSectionEntries(); - - for (const auto& indexEntry : m_index_entries) - Write(&indexEntry, sizeof(indexEntry)); - } - - void WriteBrandingSection() - { - AlignToChunk(); - m_branding_section_offset = m_current_offset; - - Write(BRANDING, std::extent_v); - } - - void WriteFileEnding() - { - AlignToChunk(); - m_total_size = m_current_offset; - } - - bool Write() override - { - // We will write the header and sections later since they need complementary data - GoTo(sizeof(IPakHeader) + sizeof(IPakSection) * SECTION_COUNT); - AlignToChunk(); - - if (!WriteDataSection()) - return false; - - WriteIndexSection(); - WriteBrandingSection(); - WriteFileEnding(); - - WriteHeaderData(); - - return true; - } - -private: - std::ostream& m_stream; - ISearchPath* m_asset_search_path; - std::vector m_images; - - int64_t m_current_offset; - std::vector m_index_entries; - int64_t m_total_size; - int64_t m_data_section_offset; - size_t m_data_section_size; - int64_t m_index_section_offset; - int64_t m_branding_section_offset; - - std::unique_ptr m_decompressed_buffer; - std::unique_ptr m_lzo_work_buffer; - size_t m_file_offset; - int64_t m_chunk_buffer_window_start; - IPakDataBlockHeader m_current_block; - int64_t m_current_block_header_offset; -}; - -std::unique_ptr IPakWriter::Create(std::ostream& stream, ISearchPath* assetSearchPath) -{ - return std::make_unique(stream, assetSearchPath); -} diff --git a/src/ObjWriting/ObjContainer/IPak/IPakWriter.h b/src/ObjWriting/ObjContainer/IPak/IPakWriter.h deleted file mode 100644 index 546ddc1d..00000000 --- a/src/ObjWriting/ObjContainer/IPak/IPakWriter.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include "SearchPath/ISearchPath.h" - -#include -#include - -class IPakWriter -{ -public: - static constexpr auto USE_COMPRESSION = true; - - IPakWriter() = default; - virtual ~IPakWriter() = default; - - IPakWriter(const IPakWriter& other) = default; - IPakWriter(IPakWriter&& other) noexcept = default; - IPakWriter& operator=(const IPakWriter& other) = default; - IPakWriter& operator=(IPakWriter&& other) noexcept = default; - - virtual void AddImage(std::string imageName) = 0; - virtual bool Write() = 0; - - static std::unique_ptr Create(std::ostream& stream, ISearchPath* assetSearchPath); -}; diff --git a/src/ObjWriting/ObjContainer/IWD/IWDWriter.cpp b/src/ObjWriting/ObjContainer/IWD/IWDWriter.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ObjWriting/ObjContainer/IWD/IWDWriter.h b/src/ObjWriting/ObjContainer/IWD/IWDWriter.h deleted file mode 100644 index e69de29b..00000000 diff --git a/src/Parser/Parsing/Impl/IncludingStreamProxy.cpp b/src/Parser/Parsing/Impl/IncludingStreamProxy.cpp index 6b628e8e..f2a96101 100644 --- a/src/Parser/Parsing/Impl/IncludingStreamProxy.cpp +++ b/src/Parser/Parsing/Impl/IncludingStreamProxy.cpp @@ -3,7 +3,7 @@ #include "Parsing/ParsingException.h" #include -#include +#include namespace fs = std::filesystem; @@ -81,11 +81,7 @@ bool IncludingStreamProxy::MatchIncludeDirective(const ParserLine& line, const u const auto filename = line.m_line.substr(filenameStart, filenameEnd - filenameStart); if (!m_stream->IncludeFile(filename)) - { - std::ostringstream errorStr; - errorStr << "Could not include file \"" << filename << "\""; - throw ParsingException(CreatePos(line, currentPos), errorStr.str()); - } + throw ParsingException(CreatePos(line, currentPos), std::format("Could not include file \"{}\"", filename)); return true; } diff --git a/src/Parser/Parsing/Impl/ParserMultiInputStream.cpp b/src/Parser/Parsing/Impl/ParserMultiInputStream.cpp index 78e2d5ee..536a0e3f 100644 --- a/src/Parser/Parsing/Impl/ParserMultiInputStream.cpp +++ b/src/Parser/Parsing/Impl/ParserMultiInputStream.cpp @@ -17,14 +17,14 @@ ParserMultiInputStream::FileInfo::FileInfo(std::istream& stream, std::string fil { } -ParserMultiInputStream::ParserMultiInputStream(std::unique_ptr stream, std::string fileName, include_callback_t includeCallback) - : m_include_callback(std::move(includeCallback)) +ParserMultiInputStream::ParserMultiInputStream(std::unique_ptr stream, std::string fileName, IInclusionCallback& includeCallback) + : m_include_callback(includeCallback) { m_files.emplace(std::move(stream), std::move(fileName)); } -ParserMultiInputStream::ParserMultiInputStream(std::istream& stream, std::string fileName, include_callback_t includeCallback) - : m_include_callback(std::move(includeCallback)) +ParserMultiInputStream::ParserMultiInputStream(std::istream& stream, std::string fileName, IInclusionCallback& includeCallback) + : m_include_callback(includeCallback) { m_files.emplace(stream, std::move(fileName)); } @@ -76,10 +76,7 @@ ParserLine ParserMultiInputStream::NextLine() bool ParserMultiInputStream::IncludeFile(const std::string& filename) { - if (!m_include_callback) - return false; - - auto newFile = m_include_callback(filename, m_files.empty() ? "" : *m_files.top().m_file_path); + auto newFile = m_include_callback.OpenIncludedFile(filename, m_files.empty() ? "" : *m_files.top().m_file_path); if (!newFile) return false; diff --git a/src/Parser/Parsing/Impl/ParserMultiInputStream.h b/src/Parser/Parsing/Impl/ParserMultiInputStream.h index 1d74d659..2b26e7e5 100644 --- a/src/Parser/Parsing/Impl/ParserMultiInputStream.h +++ b/src/Parser/Parsing/Impl/ParserMultiInputStream.h @@ -7,10 +7,25 @@ #include #include +class IInclusionCallback +{ +public: + virtual ~IInclusionCallback() = default; + + virtual std::unique_ptr OpenIncludedFile(const std::string& filename, const std::string& sourceFile) = 0; +}; + class ParserMultiInputStream final : public IParserLineStream { public: - using include_callback_t = std::function(const std::string& filename, const std::string& sourceFile)>; + ParserMultiInputStream(std::unique_ptr stream, std::string fileName, IInclusionCallback& includeCallback); + ParserMultiInputStream(std::istream& stream, std::string fileName, IInclusionCallback& includeCallback); + + ParserLine NextLine() override; + bool IncludeFile(const std::string& filename) override; + void PopCurrentFile() override; + _NODISCARD bool IsOpen() const override; + _NODISCARD bool Eof() const override; private: class FileInfo @@ -25,16 +40,6 @@ private: FileInfo(std::istream& stream, std::string filePath); }; - const include_callback_t m_include_callback; + IInclusionCallback& m_include_callback; std::stack m_files; - -public: - ParserMultiInputStream(std::unique_ptr stream, std::string fileName, include_callback_t includeCallback); - ParserMultiInputStream(std::istream& stream, std::string fileName, include_callback_t includeCallback); - - ParserLine NextLine() override; - bool IncludeFile(const std::string& filename) override; - void PopCurrentFile() override; - _NODISCARD bool IsOpen() const override; - _NODISCARD bool Eof() const override; }; diff --git a/src/Unlinker/Game/T6/ZoneDefWriterT6.cpp b/src/Unlinker/Game/T6/ZoneDefWriterT6.cpp index ad7b197d..5b50ed8d 100644 --- a/src/Unlinker/Game/T6/ZoneDefWriterT6.cpp +++ b/src/Unlinker/Game/T6/ZoneDefWriterT6.cpp @@ -56,7 +56,7 @@ void ZoneDefWriter::WriteMetaData(ZoneDefinitionOutputStream& stream, const Unli for (const auto* kvpAsset : *assetPoolT6->m_key_value_pairs) { const auto* keyValuePairs = kvpAsset->Asset(); - for (auto varIndex = 0; varIndex < keyValuePairs->numVariables; varIndex++) + for (auto varIndex = 0u; varIndex < keyValuePairs->numVariables; varIndex++) WriteKeyValuePair(stream, keyValuePairs->keyValuePairs[varIndex]); } diff --git a/src/Unlinker/Unlinker.cpp b/src/Unlinker/Unlinker.cpp index a4c5df9e..5eae8e33 100644 --- a/src/Unlinker/Unlinker.cpp +++ b/src/Unlinker/Unlinker.cpp @@ -4,16 +4,17 @@ #include "ContentLister/ZoneDefWriter.h" #include "IObjLoader.h" #include "IObjWriter.h" -#include "ObjContainer/IWD/IWD.h" -#include "ObjLoading.h" #include "ObjWriting.h" +#include "SearchPath/IWD.h" #include "SearchPath/SearchPathFilesystem.h" #include "SearchPath/SearchPaths.h" #include "UnlinkerArgs.h" +#include "UnlinkerPaths.h" #include "Utils/ClassUtils.h" #include "Utils/ObjFileStream.h" #include "ZoneLoading.h" +#include #include #include #include @@ -37,13 +38,14 @@ public: if (!shouldContinue) return true; - if (!BuildSearchPaths()) + UnlinkerPaths paths; + if (!paths.LoadUserPaths(m_args)) return false; - if (!LoadZones()) + if (!LoadZones(paths)) return false; - const auto result = UnlinkZones(); + const auto result = UnlinkZones(paths); UnloadZones(); return result; @@ -55,106 +57,6 @@ private: return m_args.m_task != UnlinkerArgs::ProcessingTask::LIST && !m_args.m_skip_obj; } - /** - * \brief Loads a search path. - * \param searchPath The search path to load. - */ - void LoadSearchPath(ISearchPath& searchPath) const - { - if (ShouldLoadObj()) - { - if (m_args.m_verbose) - std::cout << std::format("Loading search path: \"{}\"\n", searchPath.GetPath()); - - ObjLoading::LoadIWDsInSearchPath(searchPath); - } - } - - /** - * \brief Unloads a search path. - * \param searchPath The search path to unload. - */ - void UnloadSearchPath(ISearchPath& searchPath) const - { - if (ShouldLoadObj()) - { - if (m_args.m_verbose) - std::cout << std::format("Unloading search path: \"{}\"\n", searchPath.GetPath()); - - ObjLoading::UnloadIWDsInSearchPath(searchPath); - } - } - - /** - * \brief Loads all search paths that are valid for the specified zone and returns them. - * \param zonePath The path to the zone file that should be prepared for. - * \return A \c SearchPaths object that contains all search paths that should be considered when loading the specified zone. - */ - SearchPaths GetSearchPathsForZone(const std::string& zonePath) - { - SearchPaths searchPathsForZone; - const auto absoluteZoneDirectory = fs::absolute(std::filesystem::path(zonePath).remove_filename()).string(); - - if (m_last_zone_search_path != nullptr && m_last_zone_search_path->GetPath() == absoluteZoneDirectory) - { - searchPathsForZone.IncludeSearchPath(m_last_zone_search_path.get()); - } - else if (m_absolute_search_paths.find(absoluteZoneDirectory) == m_absolute_search_paths.end()) - { - if (m_last_zone_search_path) - { - UnloadSearchPath(*m_last_zone_search_path); - } - - m_last_zone_search_path = std::make_unique(absoluteZoneDirectory); - searchPathsForZone.IncludeSearchPath(m_last_zone_search_path.get()); - LoadSearchPath(*m_last_zone_search_path); - } - - for (auto* iwd : IWD::Repository) - { - searchPathsForZone.IncludeSearchPath(iwd); - } - - return searchPathsForZone; - } - - /** - * \brief Initializes the Unlinker object's search paths based on the user's input. - * \return \c true if building the search paths was successful, otherwise \c false. - */ - bool BuildSearchPaths() - { - for (const auto& path : m_args.m_user_search_paths) - { - auto absolutePath = fs::absolute(path); - - if (!fs::is_directory(absolutePath)) - { - std::cerr << std::format("Could not find directory of search path: \"{}\"\n", path); - return false; - } - - auto searchPath = std::make_unique(absolutePath.string()); - LoadSearchPath(*searchPath); - m_search_paths.CommitSearchPath(std::move(searchPath)); - - m_absolute_search_paths.insert(absolutePath.string()); - } - - if (m_args.m_verbose) - { - std::cout << std::format("{} SearchPaths{}\n", m_absolute_search_paths.size(), !m_absolute_search_paths.empty() ? ":" : ""); - for (const auto& absoluteSearchPath : m_absolute_search_paths) - std::cout << std::format(" \"{}\"\n", absoluteSearchPath); - - if (!m_absolute_search_paths.empty()) - std::cerr << "\n"; - } - - return true; - } - bool WriteZoneDefinitionFile(const Zone& zone, const fs::path& zoneDefinitionFileFolder) const { auto zoneDefinitionFilePath(zoneDefinitionFileFolder); @@ -251,7 +153,7 @@ private: * \brief Performs the tasks specified by the command line arguments on the specified zone. * \param searchPath The search path for obj data. * \param zone The zone to handle. - * \return \c true if handling the zone was successful, otherwise \c false. + * \return \c true if handling the zone was successful, otherwise \c false */ bool HandleZone(ISearchPath& searchPath, Zone& zone) const { @@ -310,7 +212,7 @@ private: return true; } - bool LoadZones() + bool LoadZones(UnlinkerPaths& paths) { for (const auto& zonePath : m_args.m_zones_to_load) { @@ -322,9 +224,7 @@ private: auto absoluteZoneDirectory = absolute(std::filesystem::path(zonePath).remove_filename()).string(); - auto searchPathsForZone = GetSearchPathsForZone(absoluteZoneDirectory); - searchPathsForZone.IncludeSearchPath(&m_search_paths); - + auto searchPathsForZone = paths.GetSearchPathsForZone(absoluteZoneDirectory); auto zone = ZoneLoading::LoadZone(zonePath); if (zone == nullptr) { @@ -338,7 +238,7 @@ private: if (ShouldLoadObj()) { const auto* objLoader = IObjLoader::GetObjLoaderForGame(zone->m_game->GetId()); - objLoader->LoadReferencedContainersForZone(searchPathsForZone, *zone); + objLoader->LoadReferencedContainersForZone(*searchPathsForZone, *zone); } m_loaded_zones.emplace_back(std::move(zone)); @@ -370,7 +270,7 @@ private: m_loaded_zones.clear(); } - bool UnlinkZones() + bool UnlinkZones(UnlinkerPaths& paths) const { for (const auto& zonePath : m_args.m_zones_to_unlink) { @@ -385,8 +285,7 @@ private: zoneDirectory = fs::current_path(); auto absoluteZoneDirectory = absolute(zoneDirectory).string(); - auto searchPathsForZone = GetSearchPathsForZone(absoluteZoneDirectory); - searchPathsForZone.IncludeSearchPath(&m_search_paths); + auto searchPathsForZone = paths.GetSearchPathsForZone(absoluteZoneDirectory); std::string zoneName; auto zone = ZoneLoading::LoadZone(zonePath); @@ -402,9 +301,9 @@ private: const auto* objLoader = IObjLoader::GetObjLoaderForGame(zone->m_game->GetId()); if (ShouldLoadObj()) - objLoader->LoadReferencedContainersForZone(searchPathsForZone, *zone); + objLoader->LoadReferencedContainersForZone(*searchPathsForZone, *zone); - if (!HandleZone(searchPathsForZone, *zone)) + if (!HandleZone(*searchPathsForZone, *zone)) return false; if (ShouldLoadObj()) @@ -419,10 +318,6 @@ private: } UnlinkerArgs m_args; - SearchPaths m_search_paths; - std::unique_ptr m_last_zone_search_path; - std::set m_absolute_search_paths; - std::vector> m_loaded_zones; }; diff --git a/src/Unlinker/UnlinkerArgs.cpp b/src/Unlinker/UnlinkerArgs.cpp index aa2102e6..3d492667 100644 --- a/src/Unlinker/UnlinkerArgs.cpp +++ b/src/Unlinker/UnlinkerArgs.cpp @@ -59,8 +59,7 @@ const CommandLineOption* const OPTION_OUTPUT_FOLDER = CommandLineOption::Builder::Create() .WithShortName("o") .WithLongName("output-folder") - .WithDescription("Specifies the output folder containing the contents of the unlinked zones. Defaults to \"" - + std::string(UnlinkerArgs::DEFAULT_OUTPUT_FOLDER) + "\"") + .WithDescription(std::format("Specifies the output folder containing the contents of the unlinked zones. Defaults to \"{}\"", UnlinkerArgs::DEFAULT_OUTPUT_FOLDER)) .WithParameter("outputFolderPath") .Build(); @@ -178,7 +177,7 @@ void UnlinkerArgs::SetVerbose(const bool isVerbose) ObjWriting::Configuration.Verbose = isVerbose; } -bool UnlinkerArgs::SetImageDumpingMode() +bool UnlinkerArgs::SetImageDumpingMode() const { auto specifiedValue = m_argument_parser.GetValueForOption(OPTION_IMAGE_FORMAT); utils::MakeStringLowerCase(specifiedValue); @@ -196,11 +195,11 @@ bool UnlinkerArgs::SetImageDumpingMode() } const std::string originalValue = m_argument_parser.GetValueForOption(OPTION_IMAGE_FORMAT); - printf("Illegal value: \"%s\" is not a valid image output format. Use -? to see usage information.\n", originalValue.c_str()); + std::cerr << std::format("Illegal value: \"{}\" is not a valid image output format. Use -? to see usage information.\n", originalValue); return false; } -bool UnlinkerArgs::SetModelDumpingMode() +bool UnlinkerArgs::SetModelDumpingMode() const { auto specifiedValue = m_argument_parser.GetValueForOption(OPTION_MODEL_FORMAT); utils::MakeStringLowerCase(specifiedValue); @@ -230,7 +229,7 @@ bool UnlinkerArgs::SetModelDumpingMode() } const std::string originalValue = m_argument_parser.GetValueForOption(OPTION_MODEL_FORMAT); - printf("Illegal value: \"%s\" is not a valid model output format. Use -? to see usage information.\n", originalValue.c_str()); + std::cerr << std::format("Illegal value: \"{}\" is not a valid model output format. Use -? to see usage information.\n", originalValue); return false; } diff --git a/src/Unlinker/UnlinkerArgs.h b/src/Unlinker/UnlinkerArgs.h index fea432b8..0e07dd2b 100644 --- a/src/Unlinker/UnlinkerArgs.h +++ b/src/Unlinker/UnlinkerArgs.h @@ -1,7 +1,9 @@ #pragma once + #include "Utils/Arguments/ArgumentParser.h" #include "Zone/Zone.h" +#include #include #include #include @@ -24,8 +26,8 @@ private: static void PrintVersion(); void SetVerbose(bool isVerbose); - bool SetImageDumpingMode(); - bool SetModelDumpingMode(); + bool SetImageDumpingMode() const; + bool SetModelDumpingMode() const; void AddSpecifiedAssetType(std::string value); void ParseCommaSeparatedAssetTypeString(const std::string& input); @@ -37,7 +39,7 @@ public: LIST }; - enum class AssetTypeHandling + enum class AssetTypeHandling : std::uint8_t { EXCLUDE, INCLUDE diff --git a/src/Unlinker/UnlinkerPaths.cpp b/src/Unlinker/UnlinkerPaths.cpp new file mode 100644 index 00000000..781a1842 --- /dev/null +++ b/src/Unlinker/UnlinkerPaths.cpp @@ -0,0 +1,73 @@ +#include "UnlinkerPaths.h" + +#include "SearchPath/IWD.h" +#include "SearchPath/SearchPathFilesystem.h" +#include "Utils/StringUtils.h" + +#include +#include +#include + +namespace fs = std::filesystem; + +bool UnlinkerPaths::LoadUserPaths(const UnlinkerArgs& args) +{ + for (const auto& path : args.m_user_search_paths) + { + auto absolutePath = fs::absolute(path); + + if (!fs::is_directory(absolutePath)) + { + std::cerr << std::format("Could not find directory of search path: \"{}\"\n", path); + return false; + } + + auto searchPathName = absolutePath.string(); + m_user_paths.CommitSearchPath(std::make_unique(searchPathName)); + m_specified_user_paths.emplace(std::move(searchPathName)); + } + + std::cout << std::format("{} SearchPaths{}\n", m_specified_user_paths.size(), !m_specified_user_paths.empty() ? ":" : ""); + for (const auto& absoluteSearchPath : m_specified_user_paths) + std::cout << std::format(" \"{}\"\n", absoluteSearchPath); + + if (!m_specified_user_paths.empty()) + std::cerr << "\n"; + + return true; +} + +std::unique_ptr UnlinkerPaths::GetSearchPathsForZone(const std::string& zonePath) +{ + const auto absoluteZoneDirectory = fs::absolute(std::filesystem::path(zonePath).remove_filename()); + const auto absoluteZoneDirectoryString = absoluteZoneDirectory.string(); + if (m_last_zone_path != absoluteZoneDirectoryString) + { + m_last_zone_path = absoluteZoneDirectoryString; + m_last_zone_search_paths = SearchPaths(); + m_last_zone_search_paths.CommitSearchPath(std::make_unique(absoluteZoneDirectoryString)); + + std::filesystem::directory_iterator iterator(absoluteZoneDirectory); + const auto end = fs::end(iterator); + for (auto i = fs::begin(iterator); i != end; ++i) + { + if (!i->is_regular_file()) + continue; + + auto extension = i->path().extension().string(); + utils::MakeStringLowerCase(extension); + if (extension == ".iwd") + { + auto iwd = iwd::LoadFromFile(i->path().string()); + if (iwd) + m_last_zone_search_paths.CommitSearchPath(std::move(iwd)); + } + } + } + + auto result = std::make_unique(); + result->IncludeSearchPath(&m_last_zone_search_paths); + result->IncludeSearchPath(&m_user_paths); + + return result; +} diff --git a/src/Unlinker/UnlinkerPaths.h b/src/Unlinker/UnlinkerPaths.h new file mode 100644 index 00000000..7396f523 --- /dev/null +++ b/src/Unlinker/UnlinkerPaths.h @@ -0,0 +1,21 @@ +#pragma once + +#include "SearchPath/SearchPaths.h" +#include "UnlinkerArgs.h" + +#include +#include + +class UnlinkerPaths +{ +public: + bool LoadUserPaths(const UnlinkerArgs& args); + std::unique_ptr GetSearchPathsForZone(const std::string& zonePath); + +private: + std::string m_last_zone_path; + SearchPaths m_last_zone_search_paths; + + std::unordered_set m_specified_user_paths; + SearchPaths m_user_paths; +}; diff --git a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp index a01235ac..b627cf5b 100644 --- a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp @@ -1098,9 +1098,12 @@ class ZoneLoadTemplate::Internal final : BaseTemplate LINE(MarkerClassName(m_env.m_asset) << " marker(m_zone);") LINE("marker.Mark(*pAsset);") LINE("") - LINE("m_asset_info = reinterpret_castm_definition->GetFullName() - << ">*>(LinkAsset(GetAssetName(*pAsset), *pAsset, marker.GetDependencies(), marker.GetUsedScriptStrings(), marker.GetIndirectAssetReferences()));") + LINE("auto* reallocatedAsset = m_zone->GetMemory()->Alloc<" << info->m_definition->GetFullName() << ">();") + LINE("std::memcpy(reallocatedAsset, *pAsset, sizeof(" << info->m_definition->GetFullName() << "));") + LINE("") + LINE("m_asset_info = reinterpret_castm_definition->GetFullName() + << ">*>(LinkAsset(GetAssetName(*pAsset), reallocatedAsset, marker.GetDependencies(), " + "marker.GetUsedScriptStrings(), marker.GetIndirectAssetReferences()));") LINE("*pAsset = m_asset_info->Asset();") m_intendation--; @@ -1275,6 +1278,7 @@ public: LINE("#include \"" << Lower(m_env.m_asset->m_definition->m_name) << "_load_db.h\"") LINE("#include \"" << Lower(m_env.m_asset->m_definition->m_name) << "_mark_db.h\"") LINE("#include ") + LINE("#include ") LINE("") if (!m_env.m_referenced_assets.empty()) diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionAssetList.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionAssetList.cpp deleted file mode 100644 index 203ca22c..00000000 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionAssetList.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "SequenceZoneDefinitionAssetList.h" - -#include "Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.h" - -SequenceZoneDefinitionAssetList::SequenceZoneDefinitionAssetList() -{ - const ZoneDefinitionMatcherFactory create(this); - - AddMatchers({ - create.Keyword("assetlist"), - create.Char(','), - create.Field().Capture(CAPTURE_ASSET_LIST_NAME), - }); -} - -void SequenceZoneDefinitionAssetList::ProcessMatch(ZoneDefinitionParserState* state, SequenceResult& result) const -{ - state->m_definition->m_asset_lists.emplace_back(result.NextCapture(CAPTURE_ASSET_LIST_NAME).FieldValue()); -} diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionInclude.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionInclude.cpp deleted file mode 100644 index 29488a86..00000000 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionInclude.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "SequenceZoneDefinitionInclude.h" - -#include "Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.h" - -SequenceZoneDefinitionInclude::SequenceZoneDefinitionInclude() -{ - const ZoneDefinitionMatcherFactory create(this); - - AddMatchers({ - create.Keyword("include"), - create.Char(','), - create.Field().Capture(CAPTURE_INCLUDE_NAME), - }); -} - -void SequenceZoneDefinitionInclude::ProcessMatch(ZoneDefinitionParserState* state, SequenceResult& result) const -{ - state->m_definition->m_includes.emplace_back(result.NextCapture(CAPTURE_INCLUDE_NAME).FieldValue()); -} diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserState.cpp b/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserState.cpp deleted file mode 100644 index beabf448..00000000 --- a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserState.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "ZoneDefinitionParserState.h" - -ZoneDefinitionParserState::ZoneDefinitionParserState(std::string targetName) - : m_asset_name_resolver(nullptr), - m_definition(std::make_unique()) -{ - m_definition->m_name = std::move(targetName); -} - -void ZoneDefinitionParserState::SetGame(const GameId game) -{ - m_definition->m_game = game; - m_asset_name_resolver = IAssetNameResolver::GetResolverForGame(game); -} diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserState.h b/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserState.h deleted file mode 100644 index 8135636e..00000000 --- a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserState.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "Zone/AssetNameResolver.h" -#include "Zone/Definition/ZoneDefinition.h" - -#include - -class ZoneDefinitionParserState -{ -public: - explicit ZoneDefinitionParserState(std::string targetName); - - void SetGame(GameId game); - - const IAssetNameResolver* m_asset_name_resolver; - std::unique_ptr m_definition; -}; diff --git a/src/ZoneCommon/Pool/AssetPoolDynamic.h b/src/ZoneCommon/Pool/AssetPoolDynamic.h index c7ad62d9..128f2a63 100644 --- a/src/ZoneCommon/Pool/AssetPoolDynamic.h +++ b/src/ZoneCommon/Pool/AssetPoolDynamic.h @@ -29,11 +29,6 @@ public: { GlobalAssetPool::UnlinkAssetPool(this); - for (auto& entry : m_assets) - { - delete entry->Asset(); - } - m_assets.clear(); m_asset_lookup.clear(); } @@ -42,10 +37,6 @@ public: { const auto normalizedName = XAssetInfo::NormalizeAssetName(xAssetInfo->m_name); - T* newAsset = new T(); - memcpy(newAsset, xAssetInfo->Asset(), sizeof(T)); - xAssetInfo->m_ptr = newAsset; - auto* pAssetInfo = xAssetInfo.get(); m_asset_lookup[normalizedName] = pAssetInfo; m_assets.emplace_back(std::move(xAssetInfo)); diff --git a/src/ZoneCommon/Pool/ZoneAssetPools.cpp b/src/ZoneCommon/Pool/ZoneAssetPools.cpp index 9dc79b9a..56b42abf 100644 --- a/src/ZoneCommon/Pool/ZoneAssetPools.cpp +++ b/src/ZoneCommon/Pool/ZoneAssetPools.cpp @@ -1,5 +1,13 @@ #include "ZoneAssetPools.h" +#include "Game/IW3/GameAssetPoolIW3.h" +#include "Game/IW4/GameAssetPoolIW4.h" +#include "Game/IW5/GameAssetPoolIW5.h" +#include "Game/T5/GameAssetPoolT5.h" +#include "Game/T6/GameAssetPoolT6.h" +#include "Game/T6/ZoneConstantsT6.h" + +#include #include ZoneAssetPools::ZoneAssetPools(Zone* zone) @@ -52,3 +60,23 @@ ZoneAssetPools::iterator ZoneAssetPools::end() const { return m_assets_in_order.end(); } + +std::unique_ptr ZoneAssetPools::CreateForGame(const GameId game, Zone* zone, const zone_priority_t priority) +{ + switch (game) + { + case GameId::IW3: + return std::make_unique(zone, priority); + case GameId::IW4: + return std::make_unique(zone, priority); + case GameId::IW5: + return std::make_unique(zone, priority); + case GameId::T5: + return std::make_unique(zone, priority); + case GameId::T6: + return std::make_unique(zone, priority); + default: + assert(false); + return nullptr; + } +} diff --git a/src/ZoneCommon/Pool/ZoneAssetPools.h b/src/ZoneCommon/Pool/ZoneAssetPools.h index 9f6876e0..5f4b1ecf 100644 --- a/src/ZoneCommon/Pool/ZoneAssetPools.h +++ b/src/ZoneCommon/Pool/ZoneAssetPools.h @@ -52,4 +52,6 @@ public: _NODISCARD iterator begin() const; _NODISCARD iterator end() const; + + static std::unique_ptr CreateForGame(GameId game, Zone* zone, zone_priority_t priority); }; diff --git a/src/ZoneCommon/Zone/AssetList/AssetListOutputStream.cpp b/src/ZoneCommon/Zone/AssetList/AssetListOutputStream.cpp new file mode 100644 index 00000000..5df9139e --- /dev/null +++ b/src/ZoneCommon/Zone/AssetList/AssetListOutputStream.cpp @@ -0,0 +1,14 @@ +#include "AssetListOutputStream.h" + +AssetListOutputStream::AssetListOutputStream(std::ostream& stream, const GameId game) + : m_stream(stream), + m_asset_name_resolver(IAssetNameResolver::GetResolverForGame(game)) +{ +} + +void AssetListOutputStream::WriteEntry(const AssetListEntry& entry) +{ + m_stream.WriteColumn(*m_asset_name_resolver->GetAssetTypeName(entry.m_type)); + m_stream.WriteColumn(entry.m_name); + m_stream.NextRow(); +} diff --git a/src/ZoneCommon/Zone/AssetList/AssetListStream.h b/src/ZoneCommon/Zone/AssetList/AssetListOutputStream.h similarity index 54% rename from src/ZoneCommon/Zone/AssetList/AssetListStream.h rename to src/ZoneCommon/Zone/AssetList/AssetListOutputStream.h index da16def6..902d935b 100644 --- a/src/ZoneCommon/Zone/AssetList/AssetListStream.h +++ b/src/ZoneCommon/Zone/AssetList/AssetListOutputStream.h @@ -1,23 +1,12 @@ #pragma once + #include "AssetList.h" #include "Csv/CsvStream.h" #include "Game/IGame.h" +#include "Zone/AssetNameResolver.h" -#include #include -class AssetListInputStream -{ -public: - AssetListInputStream(std::istream& stream, GameId game); - - bool NextEntry(AssetListEntry& entry, bool* failure) const; - -private: - CsvInputStream m_stream; - const IAssetNameResolver* m_asset_name_resolver; -}; - class AssetListOutputStream { public: diff --git a/src/ZoneCommon/Zone/AssetList/AssetListReader.cpp b/src/ZoneCommon/Zone/AssetList/AssetListReader.cpp new file mode 100644 index 00000000..fbc616bc --- /dev/null +++ b/src/ZoneCommon/Zone/AssetList/AssetListReader.cpp @@ -0,0 +1,96 @@ +#include "AssetListReader.h" + +#include "Csv/CsvStream.h" +#include "Game/IGame.h" +#include "Zone/AssetNameResolver.h" + +#include + +namespace +{ + class AssetListInputStream + { + public: + AssetListInputStream(std::istream& stream, GameId game) + : m_stream(stream), + m_asset_name_resolver(IAssetNameResolver::GetResolverForGame(game)) + { + } + + bool NextEntry(AssetListEntry& entry, bool* failure) const + { + std::vector row; + if (failure) + *failure = false; + + while (true) + { + if (!m_stream.NextRow(row)) + return false; + + if (row.empty() || (row.size() == 1 && row[0].empty())) + continue; + + const auto& typeName = row[0]; + const auto maybeType = m_asset_name_resolver->GetAssetTypeByName(typeName); + if (!maybeType) + { + std::cerr << std::format("Unknown asset type name \"{}\"\n", typeName); + if (failure) + *failure = true; + return false; + } + + entry.m_type = *maybeType; + if (row.size() >= 3 && row[1].empty()) + { + entry.m_name = row[2]; + entry.m_is_reference = true; + } + else + { + entry.m_name = row[1]; + entry.m_is_reference = false; + } + + return true; + } + } + + private: + CsvInputStream m_stream; + const IAssetNameResolver* m_asset_name_resolver; + }; +} // namespace + +AssetListReader::AssetListReader(ISearchPath& searchPath, const GameId game) + : m_search_path(searchPath), + m_game(game) +{ +} + +std::optional AssetListReader::ReadAssetList(const std::string& zoneName, const bool logMissing) const +{ + const auto assetListFileName = std::format("assetlist/{}.csv", zoneName); + const auto assetListStream = m_search_path.Open(assetListFileName); + + if (assetListStream.IsOpen()) + { + AssetList assetList; + const AssetListInputStream stream(*assetListStream.m_stream, m_game); + AssetListEntry entry; + + bool failure; + while (stream.NextEntry(entry, &failure)) + { + assetList.m_entries.emplace_back(std::move(entry)); + } + + if (!failure) + return assetList; + } + else if (logMissing) + std::cerr << std::format("Failed to open file for assetlist: {}\n", assetListFileName); + + return std::nullopt; +} diff --git a/src/ZoneCommon/Zone/AssetList/AssetListReader.h b/src/ZoneCommon/Zone/AssetList/AssetListReader.h new file mode 100644 index 00000000..819c1c70 --- /dev/null +++ b/src/ZoneCommon/Zone/AssetList/AssetListReader.h @@ -0,0 +1,20 @@ +#pragma once + +#include "AssetList.h" +#include "Game/IGame.h" +#include "SearchPath/ISearchPath.h" + +#include +#include + +class AssetListReader +{ +public: + AssetListReader(ISearchPath& searchPath, GameId game); + + std::optional ReadAssetList(const std::string& zoneName, bool logMissing = true) const; + +private: + ISearchPath& m_search_path; + GameId m_game; +}; diff --git a/src/ZoneCommon/Zone/AssetList/AssetListStream.cpp b/src/ZoneCommon/Zone/AssetList/AssetListStream.cpp deleted file mode 100644 index 2615ca92..00000000 --- a/src/ZoneCommon/Zone/AssetList/AssetListStream.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "AssetListStream.h" - -#include - -AssetListInputStream::AssetListInputStream(std::istream& stream, const GameId game) - : m_stream(stream), - m_asset_name_resolver(IAssetNameResolver::GetResolverForGame(game)) -{ -} - -bool AssetListInputStream::NextEntry(AssetListEntry& entry, bool* failure) const -{ - std::vector row; - if (failure) - *failure = false; - - while (true) - { - if (!m_stream.NextRow(row)) - return false; - - if (row.empty()) - continue; - - const auto& typeName = row[0]; - const auto maybeType = m_asset_name_resolver->GetAssetTypeByName(typeName); - if (!maybeType) - { - std::cerr << std::format("Unknown asset type name \"{}\"\n", typeName); - if (failure) - *failure = true; - return false; - } - - entry.m_type = *maybeType; - if (row.size() >= 3 && row[1].empty()) - { - entry.m_name = row[2]; - entry.m_is_reference = true; - } - else - { - entry.m_name = row[1]; - entry.m_is_reference = false; - } - - return true; - } -} - -AssetListOutputStream::AssetListOutputStream(std::ostream& stream, const GameId game) - : m_stream(stream), - m_asset_name_resolver(IAssetNameResolver::GetResolverForGame(game)) -{ -} - -void AssetListOutputStream::WriteEntry(const AssetListEntry& entry) -{ - m_stream.WriteColumn(*m_asset_name_resolver->GetAssetTypeName(entry.m_type)); - m_stream.WriteColumn(entry.m_name); - m_stream.NextRow(); -} diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherCharacter.cpp b/src/ZoneCommon/Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherCharacter.cpp similarity index 100% rename from src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherCharacter.cpp rename to src/ZoneCommon/Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherCharacter.cpp diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherCharacter.h b/src/ZoneCommon/Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherCharacter.h similarity index 85% rename from src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherCharacter.h rename to src/ZoneCommon/Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherCharacter.h index 9cb0fc68..4f7f70bd 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherCharacter.h +++ b/src/ZoneCommon/Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherCharacter.h @@ -1,7 +1,7 @@ #pragma once #include "Parsing/Matcher/AbstractMatcher.h" -#include "Parsing/ZoneDefinition/ZoneDefinitionParserValue.h" +#include "Zone/Definition/Parsing/ZoneDefinitionParserValue.h" class ZoneDefinitionMatcherCharacter final : public AbstractMatcher { diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.cpp b/src/ZoneCommon/Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherFactory.cpp similarity index 100% rename from src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.cpp rename to src/ZoneCommon/Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherFactory.cpp diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.h b/src/ZoneCommon/Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherFactory.h similarity index 92% rename from src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.h rename to src/ZoneCommon/Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherFactory.h index 00903ec2..eff3f346 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.h +++ b/src/ZoneCommon/Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherFactory.h @@ -1,7 +1,7 @@ #pragma once #include "Parsing/Matcher/AbstractMatcherFactory.h" -#include "Parsing/ZoneDefinition/ZoneDefinitionParserValue.h" +#include "Zone/Definition/Parsing/ZoneDefinitionParserValue.h" #include diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherKeyword.cpp b/src/ZoneCommon/Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherKeyword.cpp similarity index 100% rename from src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherKeyword.cpp rename to src/ZoneCommon/Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherKeyword.cpp diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherKeyword.h b/src/ZoneCommon/Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherKeyword.h similarity index 87% rename from src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherKeyword.h rename to src/ZoneCommon/Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherKeyword.h index 0a8684a0..a6497937 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherKeyword.h +++ b/src/ZoneCommon/Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherKeyword.h @@ -1,7 +1,7 @@ #pragma once #include "Parsing/Matcher/AbstractMatcher.h" -#include "Parsing/ZoneDefinition/ZoneDefinitionParserValue.h" +#include "Zone/Definition/Parsing/ZoneDefinitionParserValue.h" #include diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherValueType.cpp b/src/ZoneCommon/Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherValueType.cpp similarity index 100% rename from src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherValueType.cpp rename to src/ZoneCommon/Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherValueType.cpp diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherValueType.h b/src/ZoneCommon/Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherValueType.h similarity index 87% rename from src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherValueType.h rename to src/ZoneCommon/Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherValueType.h index 0aefbc85..4a6b3545 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherValueType.h +++ b/src/ZoneCommon/Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherValueType.h @@ -1,7 +1,7 @@ #pragma once #include "Parsing/Matcher/AbstractMatcher.h" -#include "Parsing/ZoneDefinition/ZoneDefinitionParserValue.h" +#include "Zone/Definition/Parsing/ZoneDefinitionParserValue.h" class ZoneDefinitionMatcherValueType final : public AbstractMatcher { diff --git a/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionAssetList.cpp b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionAssetList.cpp new file mode 100644 index 00000000..04730010 --- /dev/null +++ b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionAssetList.cpp @@ -0,0 +1,35 @@ +#include "SequenceZoneDefinitionAssetList.h" + +#include "Zone/AssetList/AssetListReader.h" +#include "Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherFactory.h" + +SequenceZoneDefinitionAssetList::SequenceZoneDefinitionAssetList() +{ + const ZoneDefinitionMatcherFactory create(this); + + AddMatchers({ + create.Keyword("assetlist").Capture(CAPTURE_ASSET_LIST_KEYWORD), + create.Char(','), + create.Field().Capture(CAPTURE_ASSET_LIST_NAME), + }); +} + +void SequenceZoneDefinitionAssetList::ProcessMatch(ZoneDefinitionParserState* state, SequenceResult& result) const +{ + if (state->m_definition->m_game == GameId::COUNT) + { + const auto& assetListKeywordToken = result.NextCapture(CAPTURE_ASSET_LIST_KEYWORD); + throw ParsingException(assetListKeywordToken.GetPos(), "Must define game before using assetlist"); + } + + const auto& assetListNameToken = result.NextCapture(CAPTURE_ASSET_LIST_NAME); + + AssetListReader assetListReader(state->m_search_path, state->m_definition->m_game); + const auto maybeAssetList = assetListReader.ReadAssetList(assetListNameToken.FieldValue()); + + if (!maybeAssetList) + throw ParsingException(assetListNameToken.GetPos(), "Failed to read asset list"); + + for (auto& assetListEntry : maybeAssetList->m_entries) + state->m_definition->m_assets.emplace_back(assetListEntry.m_type, std::move(assetListEntry.m_name), assetListEntry.m_is_reference); +} diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionAssetList.h b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionAssetList.h similarity index 62% rename from src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionAssetList.h rename to src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionAssetList.h index 245fc7b7..72ddee99 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionAssetList.h +++ b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionAssetList.h @@ -1,10 +1,11 @@ #pragma once -#include "Parsing/ZoneDefinition/ZoneDefinitionParser.h" +#include "Zone/Definition/Parsing/ZoneDefinitionParser.h" class SequenceZoneDefinitionAssetList final : public ZoneDefinitionParser::sequence_t { - static constexpr auto CAPTURE_ASSET_LIST_NAME = 1; + static constexpr auto CAPTURE_ASSET_LIST_KEYWORD = 1; + static constexpr auto CAPTURE_ASSET_LIST_NAME = 2; protected: void ProcessMatch(ZoneDefinitionParserState* state, SequenceResult& result) const override; diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionBuild.cpp b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionBuild.cpp similarity index 88% rename from src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionBuild.cpp rename to src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionBuild.cpp index bbae196b..647a0a39 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionBuild.cpp +++ b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionBuild.cpp @@ -1,6 +1,6 @@ #include "SequenceZoneDefinitionBuild.h" -#include "Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.h" +#include "Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherFactory.h" SequenceZoneDefinitionBuild::SequenceZoneDefinitionBuild() { diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionBuild.h b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionBuild.h similarity index 85% rename from src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionBuild.h rename to src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionBuild.h index ff965224..7cb37e88 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionBuild.h +++ b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionBuild.h @@ -1,6 +1,6 @@ #pragma once -#include "Parsing/ZoneDefinition/ZoneDefinitionParser.h" +#include "Zone/Definition/Parsing/ZoneDefinitionParser.h" class SequenceZoneDefinitionBuild final : public ZoneDefinitionParser::sequence_t { diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionEntry.cpp b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionEntry.cpp similarity index 95% rename from src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionEntry.cpp rename to src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionEntry.cpp index d335df3a..f6bcd436 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionEntry.cpp +++ b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionEntry.cpp @@ -1,6 +1,6 @@ #include "SequenceZoneDefinitionEntry.h" -#include "Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.h" +#include "Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherFactory.h" SequenceZoneDefinitionEntry::SequenceZoneDefinitionEntry() { diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionEntry.h b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionEntry.h similarity index 88% rename from src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionEntry.h rename to src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionEntry.h index c88de4ee..d441a607 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionEntry.h +++ b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionEntry.h @@ -1,6 +1,6 @@ #pragma once -#include "Parsing/ZoneDefinition/ZoneDefinitionParser.h" +#include "Zone/Definition/Parsing/ZoneDefinitionParser.h" class SequenceZoneDefinitionEntry final : public ZoneDefinitionParser::sequence_t { diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionIgnore.cpp b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionIgnore.cpp similarity index 88% rename from src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionIgnore.cpp rename to src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionIgnore.cpp index 19b5f59a..918ad88a 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionIgnore.cpp +++ b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionIgnore.cpp @@ -1,6 +1,6 @@ #include "SequenceZoneDefinitionIgnore.h" -#include "Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.h" +#include "Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherFactory.h" SequenceZoneDefinitionIgnore::SequenceZoneDefinitionIgnore() { diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionIgnore.h b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionIgnore.h similarity index 85% rename from src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionIgnore.h rename to src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionIgnore.h index 6fabb705..227b1c7c 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionIgnore.h +++ b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionIgnore.h @@ -1,6 +1,6 @@ #pragma once -#include "Parsing/ZoneDefinition/ZoneDefinitionParser.h" +#include "Zone/Definition/Parsing/ZoneDefinitionParser.h" class SequenceZoneDefinitionIgnore final : public ZoneDefinitionParser::sequence_t { diff --git a/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionInclude.cpp b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionInclude.cpp new file mode 100644 index 00000000..53deeca5 --- /dev/null +++ b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionInclude.cpp @@ -0,0 +1,32 @@ +#include "SequenceZoneDefinitionInclude.h" + +#include "Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherFactory.h" + +#include + +SequenceZoneDefinitionInclude::SequenceZoneDefinitionInclude() +{ + const ZoneDefinitionMatcherFactory create(this); + + AddMatchers({ + create.Keyword("include"), + create.Char(','), + create.Field().Capture(CAPTURE_INCLUDE_NAME), + }); +} + +void SequenceZoneDefinitionInclude::ProcessMatch(ZoneDefinitionParserState* state, SequenceResult& result) const +{ + const auto& inclusionNameToken = result.NextCapture(CAPTURE_INCLUDE_NAME); + const auto inclusionName = inclusionNameToken.FieldValue(); + const auto existingInclusion = state->m_inclusions.find(inclusionName); + if (existingInclusion != state->m_inclusions.end()) + throw ParsingException(inclusionNameToken.GetPos(), "Zone definition has already been included"); + + const auto zoneDefinitionFileNameToInclude = std::format("{}.zone", inclusionName); + + if (!state->m_underlying_stream.IncludeFile(zoneDefinitionFileNameToInclude)) + throw ParsingException(inclusionNameToken.GetPos(), "Could not find zone definition with this filename"); + + state->m_inclusions.emplace(inclusionName); +} diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionInclude.h b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionInclude.h similarity index 85% rename from src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionInclude.h rename to src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionInclude.h index 09f85c17..a86b73fd 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionInclude.h +++ b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionInclude.h @@ -1,6 +1,6 @@ #pragma once -#include "Parsing/ZoneDefinition/ZoneDefinitionParser.h" +#include "Zone/Definition/Parsing/ZoneDefinitionParser.h" class SequenceZoneDefinitionInclude final : public ZoneDefinitionParser::sequence_t { diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionMetaData.cpp b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionMetaData.cpp similarity index 53% rename from src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionMetaData.cpp rename to src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionMetaData.cpp index cb99bd30..68e8d3c1 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionMetaData.cpp +++ b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionMetaData.cpp @@ -1,8 +1,9 @@ #include "SequenceZoneDefinitionMetaData.h" -#include "Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.h" #include "Utils/StringUtils.h" +#include "Zone/Definition/Parsing/Matcher/ZoneDefinitionMatcherFactory.h" +#include #include #include @@ -13,6 +14,9 @@ namespace constexpr auto METADATA_NAME = "name"; constexpr auto METADATA_TYPE = "type"; + constexpr auto METADATA_IPAK = "ipak"; + constexpr auto METADATA_IWD = "iwd"; + std::optional GetGameByName(const std::string& gameName) { auto upperGameName = gameName; @@ -27,6 +31,21 @@ namespace return std::nullopt; } + enum class ProjectType : std::uint8_t + { + NONE, + FASTFILE, + IPAK, + + COUNT + }; + constexpr const char* ProjectType_Names[]{ + "none", + "fastfile", + "ipak", + }; + static_assert(std::extent_v == static_cast(ProjectType::COUNT)); + std::optional GetProjectTypeByName(const std::string& projectTypeName) { auto lowerProjectTypeName = projectTypeName; @@ -54,16 +73,9 @@ SequenceZoneDefinitionMetaData::SequenceZoneDefinitionMetaData() }); } -void SequenceZoneDefinitionMetaData::ProcessMatch(ZoneDefinitionParserState* state, SequenceResult& result) const +namespace { - const auto& keyToken = result.NextCapture(CAPTURE_KEY); - auto key = keyToken.FieldValue(); - const auto& valueToken = result.NextCapture(CAPTURE_VALUE); - const auto& value = valueToken.FieldValue(); - - utils::MakeStringLowerCase(key); - - if (key == METADATA_GAME) + void ProcessMetaDataGame(ZoneDefinitionParserState* state, const ZoneDefinitionParserValue& valueToken, const std::string& value) { const auto game = GetGameByName(value); if (!game) @@ -75,6 +87,52 @@ void SequenceZoneDefinitionMetaData::ProcessMatch(ZoneDefinitionParserState* sta state->SetGame(*game); } + + void ProcessMetaDataType(ZoneDefinitionParserState* state, const ZoneDefinitionParserValue& keyToken, const ZoneDefinitionParserValue& valueToken) + { + const auto projectType = GetProjectTypeByName(valueToken.FieldValue()); + if (!projectType) + throw ParsingException(valueToken.GetPos(), "Unknown project type name"); + + // TODO: Remove deprecated type + + std::string deprecationSuggestedAction; + if (*projectType == ProjectType::IPAK) + { + deprecationSuggestedAction = "Use \">ipak,name_of_ipak\" instead."; + state->StartIPak(state->m_definition->m_name); + } + else if (*projectType == ProjectType::FASTFILE) + { + deprecationSuggestedAction = "A fastfile will always be built when appropriate assets have been added."; + } + else + { + deprecationSuggestedAction = "It now has no effect."; + } + + const auto keyPos = keyToken.GetPos(); + std::cerr << std::format("Warning: {} L{}: Zone definition \">type,{}\" is deprecated and should be removed. {}\n", + keyPos.m_filename.get(), + keyPos.m_line, + keyToken.FieldValue(), + deprecationSuggestedAction); + } +} // namespace + +void SequenceZoneDefinitionMetaData::ProcessMatch(ZoneDefinitionParserState* state, SequenceResult& result) const +{ + const auto& keyToken = result.NextCapture(CAPTURE_KEY); + auto key = keyToken.FieldValue(); + const auto& valueToken = result.NextCapture(CAPTURE_VALUE); + const auto& value = valueToken.FieldValue(); + + utils::MakeStringLowerCase(key); + + if (key == METADATA_GAME) + { + ProcessMetaDataGame(state, valueToken, value); + } else if (key == METADATA_GDT) { state->m_definition->m_gdts.emplace_back(value); @@ -85,9 +143,21 @@ void SequenceZoneDefinitionMetaData::ProcessMatch(ZoneDefinitionParserState* sta } else if (key == METADATA_TYPE) { - const auto projectType = GetProjectTypeByName(value); - if (!projectType) - throw ParsingException(valueToken.GetPos(), "Unknown project type name"); + ProcessMetaDataType(state, keyToken, valueToken); + } + else if (key == METADATA_IPAK) + { + if (!value.empty()) + state->StartIPak(value); + else + throw ParsingException(valueToken.GetPos(), "IPak must have a name"); + } + else if (key == METADATA_IWD) + { + if (!value.empty()) + state->StartIwd(value); + else + throw ParsingException(valueToken.GetPos(), "IWD must have a name"); } else { diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionMetaData.h b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionMetaData.h similarity index 86% rename from src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionMetaData.h rename to src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionMetaData.h index bcb3b249..40d9b802 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/Sequence/SequenceZoneDefinitionMetaData.h +++ b/src/ZoneCommon/Zone/Definition/Parsing/Sequence/SequenceZoneDefinitionMetaData.h @@ -1,6 +1,6 @@ #pragma once -#include "Parsing/ZoneDefinition/ZoneDefinitionParser.h" +#include "Zone/Definition/Parsing/ZoneDefinitionParser.h" class SequenceZoneDefinitionMetaData final : public ZoneDefinitionParser::sequence_t { diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionLexer.cpp b/src/ZoneCommon/Zone/Definition/Parsing/ZoneDefinitionLexer.cpp similarity index 100% rename from src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionLexer.cpp rename to src/ZoneCommon/Zone/Definition/Parsing/ZoneDefinitionLexer.cpp diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionLexer.h b/src/ZoneCommon/Zone/Definition/Parsing/ZoneDefinitionLexer.h similarity index 100% rename from src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionLexer.h rename to src/ZoneCommon/Zone/Definition/Parsing/ZoneDefinitionLexer.h diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParser.cpp b/src/ZoneCommon/Zone/Definition/Parsing/ZoneDefinitionParser.cpp similarity index 78% rename from src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParser.cpp rename to src/ZoneCommon/Zone/Definition/Parsing/ZoneDefinitionParser.cpp index da287d10..e5dc0994 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParser.cpp +++ b/src/ZoneCommon/Zone/Definition/Parsing/ZoneDefinitionParser.cpp @@ -7,8 +7,9 @@ #include "Sequence/SequenceZoneDefinitionInclude.h" #include "Sequence/SequenceZoneDefinitionMetaData.h" -ZoneDefinitionParser::ZoneDefinitionParser(ZoneDefinitionLexer* lexer, std::string targetName, const std::optional maybeGame) - : AbstractParser(lexer, std::make_unique(std::move(targetName))) +ZoneDefinitionParser::ZoneDefinitionParser( + ZoneDefinitionLexer* lexer, std::string targetName, ISearchPath& searchPath, IParserLineStream& underlyingStream, const std::optional maybeGame) + : AbstractParser(lexer, std::make_unique(std::move(targetName), searchPath, underlyingStream)) { if (maybeGame) m_state->SetGame(*maybeGame); @@ -30,5 +31,6 @@ const std::vector ZoneDefinitionParser::GetParsedValue() { + m_state->Finalize(); return std::move(m_state->m_definition); } diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParser.h b/src/ZoneCommon/Zone/Definition/Parsing/ZoneDefinitionParser.h similarity index 61% rename from src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParser.h rename to src/ZoneCommon/Zone/Definition/Parsing/ZoneDefinitionParser.h index 37b37242..7ea0abe2 100644 --- a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParser.h +++ b/src/ZoneCommon/Zone/Definition/Parsing/ZoneDefinitionParser.h @@ -2,6 +2,7 @@ #include "Game/IGame.h" #include "Parsing/Impl/AbstractParser.h" +#include "SearchPath/ISearchPath.h" #include "Zone/Definition/ZoneDefinition.h" #include "ZoneDefinitionLexer.h" #include "ZoneDefinitionParserState.h" @@ -11,10 +12,14 @@ class ZoneDefinitionParser final : public AbstractParser { +public: + ZoneDefinitionParser(ZoneDefinitionLexer* lexer, + std::string targetName, + ISearchPath& searchPath, + IParserLineStream& underlyingStream, + std::optional maybeGame = std::nullopt); + std::unique_ptr GetParsedValue(); + protected: const std::vector& GetTestsForState() override; - -public: - ZoneDefinitionParser(ZoneDefinitionLexer* lexer, std::string targetName, std::optional maybeGame = std::nullopt); - std::unique_ptr GetParsedValue(); }; diff --git a/src/ZoneCommon/Zone/Definition/Parsing/ZoneDefinitionParserState.cpp b/src/ZoneCommon/Zone/Definition/Parsing/ZoneDefinitionParserState.cpp new file mode 100644 index 00000000..30c8d564 --- /dev/null +++ b/src/ZoneCommon/Zone/Definition/Parsing/ZoneDefinitionParserState.cpp @@ -0,0 +1,67 @@ +#include "ZoneDefinitionParserState.h" + +#include + +ZoneDefinitionParserState::ZoneDefinitionParserState(std::string targetName, ISearchPath& searchPath, IParserLineStream& underlyingStream) + : m_search_path(searchPath), + m_underlying_stream(underlyingStream), + m_asset_name_resolver(nullptr), + m_definition(std::make_unique()) + +{ + m_inclusions.emplace(targetName); + m_definition->m_name = std::move(targetName); +} + +void ZoneDefinitionParserState::SetGame(const GameId game) +{ + m_definition->m_game = game; + m_asset_name_resolver = IAssetNameResolver::GetResolverForGame(game); +} + +namespace +{ + void AddCurrentObjContainerToDefinitionIfNecessary(ZoneDefinition& zoneDefinition, std::optional& maybeObjContainer) + { + if (!maybeObjContainer) + return; + + maybeObjContainer->m_asset_end = zoneDefinition.m_assets.size(); + zoneDefinition.m_obj_containers.emplace_back(std::move(*maybeObjContainer)); + maybeObjContainer = std::nullopt; + } + + ZoneDefinitionObjContainer DefineNewObjContainer(const ZoneDefinition& zoneDefinition, std::string name, const ZoneDefinitionObjContainerType type) + { + return ZoneDefinitionObjContainer(std::move(name), type, zoneDefinition.m_assets.size()); + } + + void SortObjContainer(ZoneDefinition& zoneDefinition) + { + std::ranges::sort(zoneDefinition.m_obj_containers, + [](const ZoneDefinitionObjContainer& obj0, const ZoneDefinitionObjContainer& obj1) + { + return obj0.m_asset_start < obj1.m_asset_start; + }); + } +} // namespace + +void ZoneDefinitionParserState::StartIPak(std::string ipakName) +{ + AddCurrentObjContainerToDefinitionIfNecessary(*m_definition, m_current_ipak); + m_current_ipak = DefineNewObjContainer(*m_definition, std::move(ipakName), ZoneDefinitionObjContainerType::IPAK); +} + +void ZoneDefinitionParserState::StartIwd(std::string iwdName) +{ + AddCurrentObjContainerToDefinitionIfNecessary(*m_definition, m_current_iwd); + m_current_iwd = DefineNewObjContainer(*m_definition, std::move(iwdName), ZoneDefinitionObjContainerType::IWD); +} + +void ZoneDefinitionParserState::Finalize() +{ + AddCurrentObjContainerToDefinitionIfNecessary(*m_definition, m_current_ipak); + AddCurrentObjContainerToDefinitionIfNecessary(*m_definition, m_current_iwd); + + SortObjContainer(*m_definition); +} diff --git a/src/ZoneCommon/Zone/Definition/Parsing/ZoneDefinitionParserState.h b/src/ZoneCommon/Zone/Definition/Parsing/ZoneDefinitionParserState.h new file mode 100644 index 00000000..4fa60515 --- /dev/null +++ b/src/ZoneCommon/Zone/Definition/Parsing/ZoneDefinitionParserState.h @@ -0,0 +1,35 @@ +#pragma once + +#include "Parsing/IParserLineStream.h" +#include "SearchPath/ISearchPath.h" +#include "Zone/AssetNameResolver.h" +#include "Zone/Definition/ZoneDefinition.h" + +#include +#include +#include +#include + +class ZoneDefinitionParserState +{ +public: + ZoneDefinitionParserState(std::string targetName, ISearchPath& searchPath, IParserLineStream& underlyingStream); + + void SetGame(GameId game); + + void StartIPak(std::string ipakName); + void StartIwd(std::string iwdName); + + void Finalize(); + + ISearchPath& m_search_path; + IParserLineStream& m_underlying_stream; + std::unordered_set m_inclusions; + + const IAssetNameResolver* m_asset_name_resolver; + + std::optional m_current_ipak; + std::optional m_current_iwd; + + std::unique_ptr m_definition; +}; diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserValue.cpp b/src/ZoneCommon/Zone/Definition/Parsing/ZoneDefinitionParserValue.cpp similarity index 100% rename from src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserValue.cpp rename to src/ZoneCommon/Zone/Definition/Parsing/ZoneDefinitionParserValue.cpp diff --git a/src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserValue.h b/src/ZoneCommon/Zone/Definition/Parsing/ZoneDefinitionParserValue.h similarity index 100% rename from src/ZoneCommon/Parsing/ZoneDefinition/ZoneDefinitionParserValue.h rename to src/ZoneCommon/Zone/Definition/Parsing/ZoneDefinitionParserValue.h diff --git a/src/ZoneCommon/Zone/Definition/ZoneDefinition.cpp b/src/ZoneCommon/Zone/Definition/ZoneDefinition.cpp index ee36f59b..58774642 100644 --- a/src/ZoneCommon/Zone/Definition/ZoneDefinition.cpp +++ b/src/ZoneCommon/Zone/Definition/ZoneDefinition.cpp @@ -1,5 +1,13 @@ #include "ZoneDefinition.h" +ZoneDefinitionObjContainer::ZoneDefinitionObjContainer(std::string name, const ZoneDefinitionObjContainerType type, const unsigned start) + : m_name(std::move(name)), + m_type(type), + m_asset_start(start), + m_asset_end(0u) +{ +} + ZoneDefinitionAsset::ZoneDefinitionAsset(const asset_type_t type, std::string name, const bool isReference) : m_asset_type(type), m_asset_name(std::move(name)), @@ -21,24 +29,6 @@ void ZoneDefinitionProperties::Include(const ZoneDefinitionProperties& otherProp } ZoneDefinition::ZoneDefinition() - : m_type(ProjectType::NONE), - m_game(GameId::COUNT) + : m_game(GameId::COUNT) { } - -void ZoneDefinition::Include(const AssetList& assetListToInclude) -{ - for (const auto& entry : assetListToInclude.m_entries) - m_assets.emplace_back(entry.m_type, entry.m_name, false); -} - -void ZoneDefinition::Include(const ZoneDefinition& definitionToInclude) -{ - m_properties.Include(definitionToInclude.m_properties); - - for (const auto& ignore : definitionToInclude.m_ignores) - m_ignores.emplace_back(ignore); - - for (const auto& asset : definitionToInclude.m_assets) - m_assets.emplace_back(asset); -} diff --git a/src/ZoneCommon/Zone/Definition/ZoneDefinition.h b/src/ZoneCommon/Zone/Definition/ZoneDefinition.h index 515013d1..a00a5b57 100644 --- a/src/ZoneCommon/Zone/Definition/ZoneDefinition.h +++ b/src/ZoneCommon/Zone/Definition/ZoneDefinition.h @@ -4,25 +4,35 @@ #include "Zone/AssetList/AssetList.h" #include "Zone/ZoneTypes.h" +#include #include #include #include -enum class ProjectType +enum class ZoneDefinitionObjContainerType : uint8_t { - NONE, - FASTFILE, - IPAK, - - COUNT + IWD, + IPAK }; -static constexpr const char* ProjectType_Names[]{ - "none", - "fastfile", - "ipak", +class ZoneDefinitionObjContainer +{ +public: + std::string m_name; + ZoneDefinitionObjContainerType m_type; + + /** + * \brief The first asset (inclusive) to include in the obj container. + */ + unsigned m_asset_start; + + /** + * \brief The last asset (exclusive) to include in the obj container. + */ + unsigned m_asset_end; + + ZoneDefinitionObjContainer(std::string name, ZoneDefinitionObjContainerType type, unsigned start); }; -static_assert(std::extent_v == static_cast(ProjectType::COUNT)); class ZoneDefinitionAsset { @@ -50,17 +60,12 @@ class ZoneDefinition public: ZoneDefinition(); - void Include(const AssetList& assetListToInclude); - void Include(const ZoneDefinition& definitionToInclude); - std::string m_name; - ProjectType m_type; GameId m_game; ZoneDefinitionProperties m_properties; - std::vector m_includes; - std::vector m_asset_lists; std::vector m_ignores; std::vector m_targets_to_build; std::vector m_gdts; std::vector m_assets; + std::vector m_obj_containers; }; diff --git a/src/ZoneCommon/Zone/Definition/ZoneDefinitionStream.cpp b/src/ZoneCommon/Zone/Definition/ZoneDefinitionStream.cpp index 2ebc6cee..4b54c7cc 100644 --- a/src/ZoneCommon/Zone/Definition/ZoneDefinitionStream.cpp +++ b/src/ZoneCommon/Zone/Definition/ZoneDefinitionStream.cpp @@ -2,17 +2,18 @@ #include "Parsing/Impl/CommentRemovingStreamProxy.h" #include "Parsing/Impl/DefinesStreamProxy.h" +#include "Parsing/Impl/IncludingStreamProxy.h" #include "Parsing/Impl/ParserSingleInputStream.h" -#include "Parsing/ZoneDefinition/ZoneDefinitionLexer.h" -#include "Parsing/ZoneDefinition/ZoneDefinitionParser.h" +#include "Zone/Definition/Parsing/ZoneDefinitionLexer.h" +#include "Zone/Definition/Parsing/ZoneDefinitionParser.h" #include #include -ZoneDefinitionInputStream::ZoneDefinitionInputStream(std::istream& stream, std::string targetName, std::string fileName, const bool verbose) - : m_target_name(std::move(targetName)), +ZoneDefinitionInputStream::ZoneDefinitionInputStream(std::istream& stream, std::string targetName, std::string fileName, ISearchPath& searchPath) + : SearchPathMultiInputStream(searchPath), + m_target_name(std::move(targetName)), m_file_name(std::move(fileName)), - m_verbose(verbose), m_stream(nullptr), m_previously_set_game(std::nullopt) { @@ -23,15 +24,15 @@ ZoneDefinitionInputStream::ZoneDefinitionInputStream(std::istream& stream, std:: bool ZoneDefinitionInputStream::OpenBaseStream(std::istream& stream) { - m_open_streams.emplace_back(std::make_unique(stream, m_file_name)); + m_open_streams.emplace_back(std::make_unique(stream, m_file_name, *this)); return true; } void ZoneDefinitionInputStream::SetupStreamProxies() { m_open_streams.emplace_back(std::make_unique(m_open_streams.back().get())); - auto definesProxy = std::make_unique(m_open_streams.back().get()); - m_open_streams.emplace_back(std::move(definesProxy)); + m_open_streams.emplace_back(std::make_unique(m_open_streams.back().get())); + m_open_streams.emplace_back(std::make_unique(m_open_streams.back().get())); m_stream = m_open_streams.back().get(); } @@ -43,11 +44,10 @@ void ZoneDefinitionInputStream::SetPreviouslySetGame(GameId game) std::unique_ptr ZoneDefinitionInputStream::ReadDefinition() { - if (m_verbose) - std::cout << std::format("Reading zone definition file: {}\n", m_file_name); + std::cout << std::format("Reading zone definition file: {}\n", m_file_name); const auto lexer = std::make_unique(m_stream); - const auto parser = std::make_unique(lexer.get(), m_target_name, m_previously_set_game); + const auto parser = std::make_unique(lexer.get(), m_target_name, m_search_path, *m_stream, m_previously_set_game); const auto start = std::chrono::steady_clock::now(); std::unique_ptr definition; @@ -55,8 +55,7 @@ std::unique_ptr ZoneDefinitionInputStream::ReadDefinition() definition = parser->GetParsedValue(); const auto end = std::chrono::steady_clock::now(); - if (m_verbose) - std::cout << std::format("Processing zone definition took {}ms\n", std::chrono::duration_cast(end - start).count()); + std::cout << std::format("Processing zone definition took {}ms\n", std::chrono::duration_cast(end - start).count()); return std::move(definition); } diff --git a/src/ZoneCommon/Zone/Definition/ZoneDefinitionStream.h b/src/ZoneCommon/Zone/Definition/ZoneDefinitionStream.h index d4e6b6e2..96f2f734 100644 --- a/src/ZoneCommon/Zone/Definition/ZoneDefinitionStream.h +++ b/src/ZoneCommon/Zone/Definition/ZoneDefinitionStream.h @@ -2,16 +2,18 @@ #include "Game/IGame.h" #include "Parsing/IParserLineStream.h" +#include "SearchPath/ISearchPath.h" +#include "SearchPath/SearchPathMultiInputStream.h" #include "ZoneDefinition.h" #include #include #include -class ZoneDefinitionInputStream +class ZoneDefinitionInputStream : public SearchPathMultiInputStream { public: - ZoneDefinitionInputStream(std::istream& stream, std::string targetName, std::string fileName, bool verbose); + ZoneDefinitionInputStream(std::istream& stream, std::string targetName, std::string fileName, ISearchPath& searchPath); void SetPreviouslySetGame(GameId game); std::unique_ptr ReadDefinition(); @@ -22,7 +24,6 @@ private: std::string m_target_name; std::string m_file_name; - bool m_verbose; IParserLineStream* m_stream; std::vector> m_open_streams; std::optional m_previously_set_game; diff --git a/src/ZoneCommon/Zone/Zone.cpp b/src/ZoneCommon/Zone/Zone.cpp index 88a6b226..f62e300c 100644 --- a/src/ZoneCommon/Zone/Zone.cpp +++ b/src/ZoneCommon/Zone/Zone.cpp @@ -6,8 +6,12 @@ Zone::Zone(std::string name, const zone_priority_t priority, IGame* game) m_name(std::move(name)), m_priority(priority), m_language(GameLanguage::LANGUAGE_NONE), - m_game(game) + m_game(game), + m_pools(ZoneAssetPools::CreateForGame(game->GetId(), this, priority)) { + const auto assetTypeCount = m_pools->GetAssetTypeCount(); + for (auto i = 0; i < assetTypeCount; i++) + m_pools->InitPoolDynamic(i); } Zone::~Zone() diff --git a/test/ObjCommonTestUtils.lua b/test/ObjCommonTestUtils.lua new file mode 100644 index 00000000..b889470d --- /dev/null +++ b/test/ObjCommonTestUtils.lua @@ -0,0 +1,53 @@ +ObjCommonTestUtils = {} + +function ObjCommonTestUtils:include(includes) + if includes:handle(self:name()) then + includedirs { + path.join(TestFolder(), "ObjCommonTestUtils") + } + end +end + +function ObjCommonTestUtils:link(links) + links:add(self:name()) + links:linkto(ObjCommon) +end + +function ObjCommonTestUtils:use() + +end + +function ObjCommonTestUtils:name() + return "ObjCommonTestUtils" +end + +function ObjCommonTestUtils:project() + local folder = TestFolder() + local includes = Includes:create() + local links = Links:create() + + project(self:name()) + targetdir(TargetDirectoryTest) + location "%{wks.location}/test/%{prj.name}" + kind "StaticLib" + language "C++" + + files { + path.join(folder, "ObjCommonTestUtils/**.h"), + path.join(folder, "ObjCommonTestUtils/**.cpp") + } + + vpaths { + ["*"] = { + path.join(folder, "ObjCommonTestUtils") + } + } + + self:include(includes) + ObjCommon:include(includes) + catch2:include(includes) + + links:linkto(ObjCommon) + links:linkto(catch2) + links:linkall() +end diff --git a/test/ObjLoadingTests/Mock/MockSearchPath.cpp b/test/ObjCommonTestUtils/SearchPath/MockSearchPath.cpp similarity index 85% rename from test/ObjLoadingTests/Mock/MockSearchPath.cpp rename to test/ObjCommonTestUtils/SearchPath/MockSearchPath.cpp index 3bf0c92d..e34dff34 100644 --- a/test/ObjLoadingTests/Mock/MockSearchPath.cpp +++ b/test/ObjCommonTestUtils/SearchPath/MockSearchPath.cpp @@ -17,9 +17,10 @@ SearchPathOpenFile MockSearchPath::Open(const std::string& fileName) return {std::make_unique(foundFileData->second), foundFileData->second.size()}; } -std::string MockSearchPath::GetPath() +const std::string& MockSearchPath::GetPath() { - return "MockFiles"; + const static std::string NAME = "MockFiles"; + return NAME; } void MockSearchPath::Find(const SearchPathSearchOptions& options, const std::function& callback) {} diff --git a/test/ObjLoadingTests/Mock/MockSearchPath.h b/test/ObjCommonTestUtils/SearchPath/MockSearchPath.h similarity index 71% rename from test/ObjLoadingTests/Mock/MockSearchPath.h rename to test/ObjCommonTestUtils/SearchPath/MockSearchPath.h index 6951326e..62631e9e 100644 --- a/test/ObjLoadingTests/Mock/MockSearchPath.h +++ b/test/ObjCommonTestUtils/SearchPath/MockSearchPath.h @@ -1,16 +1,18 @@ #pragma once + #include "SearchPath/ISearchPath.h" -#include +#include class MockSearchPath final : public ISearchPath { - std::map m_file_data_map; - public: void AddFileData(std::string fileName, std::string fileData); SearchPathOpenFile Open(const std::string& fileName) override; - std::string GetPath() override; + const std::string& GetPath() override; void Find(const SearchPathSearchOptions& options, const std::function& callback) override; + +private: + std::unordered_map m_file_data_map; }; diff --git a/test/ObjLoadingTests.lua b/test/ObjLoadingTests.lua index e50dec2b..2fc39089 100644 --- a/test/ObjLoadingTests.lua +++ b/test/ObjLoadingTests.lua @@ -43,10 +43,12 @@ function ObjLoadingTests:project() } self:include(includes) + ObjCommonTestUtils:include(includes) ParserTestUtils:include(includes) ObjLoading:include(includes) catch2:include(includes) + links:linkto(ObjCommonTestUtils) links:linkto(ParserTestUtils) links:linkto(ObjLoading) links:linkto(catch2) diff --git a/test/ObjLoadingTests/Game/IW3/AssetLoaders/AssetLoaderStringTableTest.cpp b/test/ObjLoadingTests/Game/IW3/StringTable/AssetLoaderStringTableIW3Test.cpp similarity index 65% rename from test/ObjLoadingTests/Game/IW3/AssetLoaders/AssetLoaderStringTableTest.cpp rename to test/ObjLoadingTests/Game/IW3/StringTable/AssetLoaderStringTableIW3Test.cpp index e3320300..36ee0347 100644 --- a/test/ObjLoadingTests/Game/IW3/AssetLoaders/AssetLoaderStringTableTest.cpp +++ b/test/ObjLoadingTests/Game/IW3/StringTable/AssetLoaderStringTableIW3Test.cpp @@ -1,8 +1,8 @@ -#include "Game/IW3/AssetLoaders/AssetLoaderStringTable.h" +#include "Game/IW3/StringTable/AssetLoaderStringTableIW3.h" #include "Game/IW3/GameIW3.h" -#include "Mock/MockAssetLoadingManager.h" -#include "Mock/MockSearchPath.h" +#include "Pool/ZoneAssetPools.h" +#include "SearchPath/MockSearchPath.h" #include "Utils/MemoryManager.h" #include @@ -21,17 +21,19 @@ namespace "lorem,ipsum"); Zone zone("MockZone", 0, IGame::GetGameById(GameId::IW3)); - MockAssetLoadingManager assetLoadingManager(zone, searchPath); - AssetLoaderStringTable assetLoader; MemoryManager memory; + AssetCreatorCollection creatorCollection(zone); + IgnoredAssetLookup ignoredAssetLookup; + AssetCreationContext context(zone, &creatorCollection, &ignoredAssetLookup); - assetLoader.LoadFromRaw("mp/cooltable.csv", &searchPath, &memory, &assetLoadingManager, &zone); - - auto* assetInfo = reinterpret_cast*>(assetLoadingManager.MockGetAddedAsset("mp/cooltable.csv")); - REQUIRE(assetInfo != nullptr); + auto loader = CreateStringTableLoader(memory, searchPath); + auto result = loader->CreateAsset("mp/cooltable.csv", context); + REQUIRE(result.HasBeenSuccessful()); + const auto* assetInfo = reinterpret_cast*>(result.GetAssetInfo()); const auto* stringTable = assetInfo->Asset(); + REQUIRE(stringTable->name == "mp/cooltable.csv"s); REQUIRE(stringTable->columnCount == 3); REQUIRE(stringTable->rowCount == 2); diff --git a/test/ObjLoadingTests/Game/IW4/AssetLoaders/AssetLoaderStringTableTest.cpp b/test/ObjLoadingTests/Game/IW4/AssetLoaders/LoaderStringTableIW4Test.cpp similarity index 72% rename from test/ObjLoadingTests/Game/IW4/AssetLoaders/AssetLoaderStringTableTest.cpp rename to test/ObjLoadingTests/Game/IW4/AssetLoaders/LoaderStringTableIW4Test.cpp index 5dc5769c..88fbe000 100644 --- a/test/ObjLoadingTests/Game/IW4/AssetLoaders/AssetLoaderStringTableTest.cpp +++ b/test/ObjLoadingTests/Game/IW4/AssetLoaders/LoaderStringTableIW4Test.cpp @@ -1,9 +1,8 @@ -#include "Game/IW4/AssetLoaders/AssetLoaderStringTable.h" +#include "Game/IW4/StringTable/LoaderStringTableIW4.h" #include "Game/IW4/CommonIW4.h" #include "Game/IW4/GameIW4.h" -#include "Mock/MockAssetLoadingManager.h" -#include "Mock/MockSearchPath.h" +#include "SearchPath/MockSearchPath.h" #include "Utils/MemoryManager.h" #include @@ -22,17 +21,19 @@ namespace "lorem,ipsum"); Zone zone("MockZone", 0, IGame::GetGameById(GameId::IW4)); - MockAssetLoadingManager assetLoadingManager(zone, searchPath); - AssetLoaderStringTable assetLoader; MemoryManager memory; + AssetCreatorCollection creatorCollection(zone); + IgnoredAssetLookup ignoredAssetLookup; + AssetCreationContext context(zone, &creatorCollection, &ignoredAssetLookup); - assetLoader.LoadFromRaw("mp/cooltable.csv", &searchPath, &memory, &assetLoadingManager, &zone); - - auto* assetInfo = reinterpret_cast*>(assetLoadingManager.MockGetAddedAsset("mp/cooltable.csv")); - REQUIRE(assetInfo != nullptr); + auto loader = CreateStringTableLoader(memory, searchPath); + auto result = loader->CreateAsset("mp/cooltable.csv", context); + REQUIRE(result.HasBeenSuccessful()); + const auto* assetInfo = reinterpret_cast*>(result.GetAssetInfo()); const auto* stringTable = assetInfo->Asset(); + REQUIRE(stringTable->name == "mp/cooltable.csv"s); REQUIRE(stringTable->columnCount == 3); REQUIRE(stringTable->rowCount == 2); diff --git a/test/ObjLoadingTests/Game/IW4/Menu/MenuParsingIW4IT.cpp b/test/ObjLoadingTests/Game/IW4/Menu/LoaderMenuListIW4Test.cpp similarity index 92% rename from test/ObjLoadingTests/Game/IW4/Menu/MenuParsingIW4IT.cpp rename to test/ObjLoadingTests/Game/IW4/Menu/LoaderMenuListIW4Test.cpp index 195d5621..4c231d78 100644 --- a/test/ObjLoadingTests/Game/IW4/Menu/MenuParsingIW4IT.cpp +++ b/test/ObjLoadingTests/Game/IW4/Menu/LoaderMenuListIW4Test.cpp @@ -1,13 +1,14 @@ -#include "Game/IW4/AssetLoaders/AssetLoaderMenuList.h" +#include "Game/IW4/Menu/LoaderMenuListIW4.h" + #include "Game/IW4/GameIW4.h" -#include "Mock/MockAssetLoadingManager.h" -#include "Mock/MockSearchPath.h" #include "Parsing/Menu/MenuFileReader.h" +#include "SearchPath/MockSearchPath.h" #include "Utils/MemoryManager.h" #include #include #include +#include #include using namespace menu; @@ -23,14 +24,19 @@ namespace test::game::iw4::menu::parsing::it Zone m_zone; MockSearchPath m_search_path; - MockAssetLoadingManager m_manager; - AssetLoaderMenuList m_asset_loader; + std::unique_ptr m_asset_creator; + AssetCreatorCollection m_creator_collection; + IgnoredAssetLookup m_ignored_asset_lookup; + AssetCreationContext m_context; public: MenuParsingItHelper() : m_zone("MockZone", 0, IGame::GetGameById(GameId::IW4)), - m_manager(m_zone, m_search_path) + m_creator_collection(m_zone), + m_ignored_asset_lookup(), + m_context(m_zone, &m_creator_collection, &m_ignored_asset_lookup) { + m_asset_creator = CreateMenuListLoader(*m_zone.GetMemory(), m_search_path); } void AddFile(std::string fileName, std::string data) @@ -48,28 +54,19 @@ namespace test::game::iw4::menu::parsing::it auto* material = m_zone.GetMemory()->Create(); material->info.name = m_zone.GetMemory()->Dup(name.c_str()); - m_manager.MockAddAvailableDependency(ASSET_TYPE_MATERIAL, name, material); + m_context.AddAsset(name, material); return material; } - bool RunIntegrationTest() + AssetCreationResult RunIntegrationTest() { - return m_asset_loader.LoadFromRaw(DEFAULT_ASSET_NAME, &m_search_path, m_zone.GetMemory(), &m_manager, &m_zone); - } - - MenuList* GetMenuListAsset() - { - const auto addedAsset = m_manager.MockGetAddedAsset(DEFAULT_ASSET_NAME); - REQUIRE(addedAsset); - REQUIRE(addedAsset->m_type == ASSET_TYPE_MENULIST); - - return static_cast(addedAsset->m_ptr); + return m_asset_creator->CreateAsset(DEFAULT_ASSET_NAME, m_context); } menuDef_t* GetMenuAsset(const std::string& menuName) { - const auto addedAsset = m_manager.MockGetAddedAsset(menuName); + const auto addedAsset = m_zone.m_pools->GetAsset(ASSET_TYPE_MENU, menuName); REQUIRE(addedAsset); REQUIRE(addedAsset->m_type == ASSET_TYPE_MENU); @@ -91,9 +88,9 @@ namespace test::game::iw4::menu::parsing::it )testmenu"); const auto result = helper.RunIntegrationTest(); - REQUIRE(result); + REQUIRE(result.HasBeenSuccessful()); - const auto* menuList = helper.GetMenuListAsset(); + const auto* menuList = (MenuList*)result.GetAssetInfo()->m_ptr; const auto* menu = helper.GetMenuAsset("Hello"); REQUIRE(menuList->menuCount == 1); @@ -172,9 +169,9 @@ namespace test::game::iw4::menu::parsing::it const auto* funnyDogMaterial = helper.AddMaterial("funny_dog.png"); const auto result = helper.RunIntegrationTest(); - REQUIRE(result); + REQUIRE(result.HasBeenSuccessful()); - const auto* menuList = helper.GetMenuListAsset(); + const auto* menuList = (MenuList*)result.GetAssetInfo()->m_ptr; const auto* menu = helper.GetMenuAsset("Bla"); REQUIRE(menuList->menuCount == 1); @@ -343,9 +340,9 @@ namespace test::game::iw4::menu::parsing::it )testmenu"); const auto result = helper.RunIntegrationTest(); - REQUIRE(result); + REQUIRE(result.HasBeenSuccessful()); - const auto* menuList = helper.GetMenuListAsset(); + const auto* menuList = (MenuList*)result.GetAssetInfo()->m_ptr; const auto* menu = helper.GetMenuAsset("Blab"); REQUIRE(menuList->menuCount == 1); diff --git a/test/ObjLoadingTests/Game/IW5/AssetLoaders/AssetLoaderStringTableTest.cpp b/test/ObjLoadingTests/Game/IW5/AssetLoaders/LoaderStringTableIW5Test.cpp similarity index 72% rename from test/ObjLoadingTests/Game/IW5/AssetLoaders/AssetLoaderStringTableTest.cpp rename to test/ObjLoadingTests/Game/IW5/AssetLoaders/LoaderStringTableIW5Test.cpp index 27f434c8..ab5ac734 100644 --- a/test/ObjLoadingTests/Game/IW5/AssetLoaders/AssetLoaderStringTableTest.cpp +++ b/test/ObjLoadingTests/Game/IW5/AssetLoaders/LoaderStringTableIW5Test.cpp @@ -1,8 +1,7 @@ -#include "Game/IW5/AssetLoaders/AssetLoaderStringTable.h" +#include "Game/IW5/StringTable/LoaderStringTableIW5.h" #include "Game/IW5/GameIW5.h" -#include "Mock/MockAssetLoadingManager.h" -#include "Mock/MockSearchPath.h" +#include "SearchPath/MockSearchPath.h" #include "Utils/MemoryManager.h" #include @@ -21,17 +20,19 @@ namespace "lorem,ipsum"); Zone zone("MockZone", 0, IGame::GetGameById(GameId::IW5)); - MockAssetLoadingManager assetLoadingManager(zone, searchPath); - AssetLoaderStringTable assetLoader; MemoryManager memory; + AssetCreatorCollection creatorCollection(zone); + IgnoredAssetLookup ignoredAssetLookup; + AssetCreationContext context(zone, &creatorCollection, &ignoredAssetLookup); - assetLoader.LoadFromRaw("mp/cooltable.csv", &searchPath, &memory, &assetLoadingManager, &zone); - - auto* assetInfo = reinterpret_cast*>(assetLoadingManager.MockGetAddedAsset("mp/cooltable.csv")); - REQUIRE(assetInfo != nullptr); + auto loader = CreateStringTableLoader(memory, searchPath); + auto result = loader->CreateAsset("mp/cooltable.csv", context); + REQUIRE(result.HasBeenSuccessful()); + const auto* assetInfo = reinterpret_cast*>(result.GetAssetInfo()); const auto* stringTable = assetInfo->Asset(); + REQUIRE(stringTable->name == "mp/cooltable.csv"s); REQUIRE(stringTable->columnCount == 3); REQUIRE(stringTable->rowCount == 2); diff --git a/test/ObjLoadingTests/Game/T5/AssetLoaders/AssetLoaderStringTableTest.cpp b/test/ObjLoadingTests/Game/T5/AssetLoaders/LoaderStringTableT5Test.cpp similarity index 75% rename from test/ObjLoadingTests/Game/T5/AssetLoaders/AssetLoaderStringTableTest.cpp rename to test/ObjLoadingTests/Game/T5/AssetLoaders/LoaderStringTableT5Test.cpp index 6d0c1a40..b86f889a 100644 --- a/test/ObjLoadingTests/Game/T5/AssetLoaders/AssetLoaderStringTableTest.cpp +++ b/test/ObjLoadingTests/Game/T5/AssetLoaders/LoaderStringTableT5Test.cpp @@ -1,8 +1,7 @@ -#include "Game/T5/AssetLoaders/AssetLoaderStringTable.h" +#include "Game/T5/StringTable/LoaderStringTableT5.h" #include "Game/T5/GameT5.h" -#include "Mock/MockAssetLoadingManager.h" -#include "Mock/MockSearchPath.h" +#include "SearchPath/MockSearchPath.h" #include "Utils/MemoryManager.h" #include @@ -21,17 +20,19 @@ namespace "lorem,ipsum"); Zone zone("MockZone", 0, IGame::GetGameById(GameId::T5)); - MockAssetLoadingManager assetLoadingManager(zone, searchPath); - AssetLoaderStringTable assetLoader; MemoryManager memory; + AssetCreatorCollection creatorCollection(zone); + IgnoredAssetLookup ignoredAssetLookup; + AssetCreationContext context(zone, &creatorCollection, &ignoredAssetLookup); - assetLoader.LoadFromRaw("mp/cooltable.csv", &searchPath, &memory, &assetLoadingManager, &zone); - - auto* assetInfo = reinterpret_cast*>(assetLoadingManager.MockGetAddedAsset("mp/cooltable.csv")); - REQUIRE(assetInfo != nullptr); + auto loader = CreateStringTableLoader(memory, searchPath); + auto result = loader->CreateAsset("mp/cooltable.csv", context); + REQUIRE(result.HasBeenSuccessful()); + const auto* assetInfo = reinterpret_cast*>(result.GetAssetInfo()); const auto* stringTable = assetInfo->Asset(); + REQUIRE(stringTable->name == "mp/cooltable.csv"s); REQUIRE(stringTable->columnCount == 3); REQUIRE(stringTable->rowCount == 2); diff --git a/test/ObjLoadingTests/Game/T6/AssetLoaders/AssetLoaderStringTableTest.cpp b/test/ObjLoadingTests/Game/T6/AssetLoaders/LoaderStringTableT6Test.cpp similarity index 75% rename from test/ObjLoadingTests/Game/T6/AssetLoaders/AssetLoaderStringTableTest.cpp rename to test/ObjLoadingTests/Game/T6/AssetLoaders/LoaderStringTableT6Test.cpp index a853c878..c6a9186f 100644 --- a/test/ObjLoadingTests/Game/T6/AssetLoaders/AssetLoaderStringTableTest.cpp +++ b/test/ObjLoadingTests/Game/T6/AssetLoaders/LoaderStringTableT6Test.cpp @@ -1,8 +1,7 @@ -#include "Game/T6/AssetLoaders/AssetLoaderStringTable.h" +#include "Game/T6/StringTable/LoaderStringTableT6.h" #include "Game/T6/GameT6.h" -#include "Mock/MockAssetLoadingManager.h" -#include "Mock/MockSearchPath.h" +#include "SearchPath/MockSearchPath.h" #include "Utils/MemoryManager.h" #include @@ -21,17 +20,19 @@ namespace "lorem,ipsum"); Zone zone("MockZone", 0, IGame::GetGameById(GameId::T6)); - MockAssetLoadingManager assetLoadingManager(zone, searchPath); - AssetLoaderStringTable assetLoader; MemoryManager memory; + AssetCreatorCollection creatorCollection(zone); + IgnoredAssetLookup ignoredAssetLookup; + AssetCreationContext context(zone, &creatorCollection, &ignoredAssetLookup); - assetLoader.LoadFromRaw("mp/cooltable.csv", &searchPath, &memory, &assetLoadingManager, &zone); - - auto* assetInfo = reinterpret_cast*>(assetLoadingManager.MockGetAddedAsset("mp/cooltable.csv")); - REQUIRE(assetInfo != nullptr); + auto loader = CreateStringTableLoader(memory, searchPath); + auto result = loader->CreateAsset("mp/cooltable.csv", context); + REQUIRE(result.HasBeenSuccessful()); + const auto* assetInfo = reinterpret_cast*>(result.GetAssetInfo()); const auto* stringTable = assetInfo->Asset(); + REQUIRE(stringTable->name == "mp/cooltable.csv"s); REQUIRE(stringTable->columnCount == 3); REQUIRE(stringTable->rowCount == 2); diff --git a/test/ObjLoadingTests/Mock/MockAssetLoadingManager.cpp b/test/ObjLoadingTests/Mock/MockAssetLoadingManager.cpp deleted file mode 100644 index ee02a702..00000000 --- a/test/ObjLoadingTests/Mock/MockAssetLoadingManager.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "MockAssetLoadingManager.h" - -MockAssetLoadingManager::MockAssetLoadingManager(Zone& zone, ISearchPath& searchPath) - : m_zone(zone), - m_mock_gdt(std::make_unique()), - m_context(std::make_unique(zone, searchPath, std::vector({m_mock_gdt.get()}))) -{ -} - -AssetLoadingContext* MockAssetLoadingManager::GetAssetLoadingContext() const -{ - return m_context.get(); -} - -XAssetInfoGeneric* MockAssetLoadingManager::AddAsset(std::unique_ptr xAssetInfo) -{ - const auto assetInfoPtr = xAssetInfo.get(); - m_added_assets.emplace(std::make_pair(xAssetInfo->m_name, std::move(xAssetInfo))); - - return assetInfoPtr; -} - -XAssetInfoGeneric* MockAssetLoadingManager::LoadDependency(const asset_type_t assetType, const std::string& assetName) -{ - auto foundDependencies = m_available_dependencies.find(assetName); - - while (foundDependencies != m_available_dependencies.end()) - { - if (foundDependencies->second->m_type == assetType) - return foundDependencies->second.get(); - - ++foundDependencies; - } - - return nullptr; -} - -IndirectAssetReference MockAssetLoadingManager::LoadIndirectAssetReference(const asset_type_t assetType, const std::string& assetName) -{ - return IndirectAssetReference(assetType, assetName); -} - -void MockAssetLoadingManager::MockAddAvailableDependency(const asset_type_t assetType, std::string assetName, void* asset) -{ - auto assetInfo = std::make_unique(assetType, std::move(assetName), asset); - m_available_dependencies.emplace(assetInfo->m_name, std::move(assetInfo)); -} - -XAssetInfoGeneric* MockAssetLoadingManager::MockGetAddedAsset(const std::string& assetName) -{ - const auto foundAsset = m_added_assets.find(assetName); - - if (foundAsset != m_added_assets.end()) - return foundAsset->second.get(); - - return nullptr; -} diff --git a/test/ObjLoadingTests/Mock/MockAssetLoadingManager.h b/test/ObjLoadingTests/Mock/MockAssetLoadingManager.h deleted file mode 100644 index 197b88cc..00000000 --- a/test/ObjLoadingTests/Mock/MockAssetLoadingManager.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "AssetLoading/IAssetLoadingManager.h" - -#include -#include - -class MockAssetLoadingManager final : public IAssetLoadingManager -{ - Zone& m_zone; - std::unique_ptr m_mock_gdt; - std::unique_ptr m_context; - std::map> m_added_assets; - std::multimap> m_available_dependencies; - -public: - MockAssetLoadingManager(Zone& zone, ISearchPath& searchPath); - - _NODISCARD AssetLoadingContext* GetAssetLoadingContext() const override; - XAssetInfoGeneric* AddAsset(std::unique_ptr xAssetInfo) override; - XAssetInfoGeneric* LoadDependency(asset_type_t assetType, const std::string& assetName) override; - IndirectAssetReference LoadIndirectAssetReference(asset_type_t assetType, const std::string& assetName) override; - - void MockAddAvailableDependency(asset_type_t assetType, std::string assetName, void* asset); - XAssetInfoGeneric* MockGetAddedAsset(const std::string& assetName); -}; diff --git a/test/ZoneCommonTests.lua b/test/ZoneCommonTests.lua index 43af18ab..cec3edd9 100644 --- a/test/ZoneCommonTests.lua +++ b/test/ZoneCommonTests.lua @@ -45,9 +45,11 @@ function ZoneCommonTests:project() } self:include(includes) + ObjCommonTestUtils:include(includes) ZoneCommon:include(includes) catch2:include(includes) + links:linkto(ObjCommonTestUtils) links:linkto(ZoneCommon) links:linkto(catch2) links:linkall() diff --git a/test/ZoneCommonTests/Zone/Definition/ZoneDefinitionStreamTests.cpp b/test/ZoneCommonTests/Zone/Definition/ZoneDefinitionStreamTests.cpp index 15638c64..3a17e0c8 100644 --- a/test/ZoneCommonTests/Zone/Definition/ZoneDefinitionStreamTests.cpp +++ b/test/ZoneCommonTests/Zone/Definition/ZoneDefinitionStreamTests.cpp @@ -1,4 +1,5 @@ #include "Game/T6/T6.h" +#include "SearchPath/MockSearchPath.h" #include "Zone/Definition/ZoneDefinitionStream.h" #include @@ -19,7 +20,8 @@ material,gradient_top menu,demo_ingame )sampledata"); - ZoneDefinitionInputStream inputStream(inputData, "test", "test.zone", true); + MockSearchPath mockSearchPath; + ZoneDefinitionInputStream inputStream(inputData, "test", "test.zone", mockSearchPath); const auto result = inputStream.ReadDefinition(); REQUIRE(result); @@ -50,7 +52,8 @@ menu,demo_ingame material,demo_material )sampledata"); - ZoneDefinitionInputStream inputStream(inputData, "test", "test.zone", true); + MockSearchPath mockSearchPath; + ZoneDefinitionInputStream inputStream(inputData, "test", "test.zone", mockSearchPath); const auto result = inputStream.ReadDefinition(); REQUIRE(result); @@ -68,19 +71,48 @@ material,demo_material >name,test_mod include,demo_gun +material,asdf include,demo_scripts )sampledata"); - ZoneDefinitionInputStream inputStream(inputData, "test", "test.zone", true); + MockSearchPath mockSearchPath; + + mockSearchPath.AddFileData("demo_gun.zone", R"sampledata( +>linker.gunPhysics,true +build,other_zone_to_build +ignore,ignored_zone +material,demo_gun_material +)sampledata"); + + mockSearchPath.AddFileData("demo_scripts.zone", R"sampledata( +rawfile,demo_gun_script.gsc +)sampledata"); + + ZoneDefinitionInputStream inputStream(inputData, "test", "test.zone", mockSearchPath); const auto result = inputStream.ReadDefinition(); REQUIRE(result); + REQUIRE(result->m_assets.size() == 3); - REQUIRE(result->m_assets.empty()); - REQUIRE(result->m_includes.size() == 2); + REQUIRE(result->m_assets[0].m_asset_name == "demo_gun_material"); + REQUIRE(result->m_assets[0].m_asset_type == T6::ASSET_TYPE_MATERIAL); - REQUIRE(result->m_includes[0] == "demo_gun"); - REQUIRE(result->m_includes[1] == "demo_scripts"); + REQUIRE(result->m_assets[1].m_asset_name == "asdf"); + REQUIRE(result->m_assets[1].m_asset_type == T6::ASSET_TYPE_MATERIAL); + + REQUIRE(result->m_assets[2].m_asset_name == "demo_gun_script.gsc"); + REQUIRE(result->m_assets[2].m_asset_type == T6::ASSET_TYPE_RAWFILE); + + REQUIRE(!result->m_properties.m_properties.empty()); + const auto includedProperty = result->m_properties.m_properties.find("linker.gunphysics"); + REQUIRE(includedProperty != result->m_properties.m_properties.end()); + REQUIRE(includedProperty->second == "true"); + + REQUIRE(!result->m_ignores.empty()); + REQUIRE(result->m_ignores[0] == "ignored_zone"); + + REQUIRE(!result->m_targets_to_build.empty()); + REQUIRE(result->m_targets_to_build[0] == "other_zone_to_build"); } TEST_CASE("ZoneDefinitionInputStream: Ensure can include assetlists", "[zonedefinition]") @@ -91,21 +123,47 @@ include,demo_scripts >name,test_mod assetlist,code_post_gfx_mp +material,asdf assetlist,common_mp material,test_material )sampledata"); - ZoneDefinitionInputStream inputStream(inputData, "test", "test.zone", true); + MockSearchPath mockSearchPath; + + mockSearchPath.AddFileData("assetlist/code_post_gfx_mp.csv", R"sampledata( +material,post_fx_mat +rawfile,code_post_gfx_mp +)sampledata"); + + mockSearchPath.AddFileData("assetlist/common_mp.csv", R"sampledata( +material,common_mat +rawfile,common_mp +)sampledata"); + + ZoneDefinitionInputStream inputStream(inputData, "test", "test.zone", mockSearchPath); const auto result = inputStream.ReadDefinition(); REQUIRE(result); + REQUIRE(result->m_assets.size() == 6); - REQUIRE(result->m_assets.size() == 1); - REQUIRE(result->m_asset_lists.size() == 2); + REQUIRE(result->m_assets[0].m_asset_name == "post_fx_mat"); + REQUIRE(result->m_assets[0].m_asset_type == T6::ASSET_TYPE_MATERIAL); - REQUIRE(result->m_asset_lists[0] == "code_post_gfx_mp"); - REQUIRE(result->m_asset_lists[1] == "common_mp"); + REQUIRE(result->m_assets[1].m_asset_name == "code_post_gfx_mp"); + REQUIRE(result->m_assets[1].m_asset_type == T6::ASSET_TYPE_RAWFILE); + + REQUIRE(result->m_assets[2].m_asset_name == "asdf"); + REQUIRE(result->m_assets[2].m_asset_type == T6::ASSET_TYPE_MATERIAL); + + REQUIRE(result->m_assets[3].m_asset_name == "common_mat"); + REQUIRE(result->m_assets[3].m_asset_type == T6::ASSET_TYPE_MATERIAL); + + REQUIRE(result->m_assets[4].m_asset_name == "common_mp"); + REQUIRE(result->m_assets[4].m_asset_type == T6::ASSET_TYPE_RAWFILE); + + REQUIRE(result->m_assets[5].m_asset_name == "test_material"); + REQUIRE(result->m_assets[5].m_asset_type == T6::ASSET_TYPE_MATERIAL); } TEST_CASE("ZoneDefinitionInputStream: Ensure can define other build targets", "[zonedefinition]") @@ -122,7 +180,8 @@ material,test_material build,more_mods )sampledata"); - ZoneDefinitionInputStream inputStream(inputData, "test", "test.zone", true); + MockSearchPath mockSearchPath; + ZoneDefinitionInputStream inputStream(inputData, "test", "test.zone", mockSearchPath); const auto result = inputStream.ReadDefinition(); REQUIRE(result); @@ -147,7 +206,8 @@ ignore,common_mp material,test_material )sampledata"); - ZoneDefinitionInputStream inputStream(inputData, "test", "test.zone", true); + MockSearchPath mockSearchPath; + ZoneDefinitionInputStream inputStream(inputData, "test", "test.zone", mockSearchPath); const auto result = inputStream.ReadDefinition(); REQUIRE(result); @@ -171,7 +231,8 @@ material,test_material material,test_material )sampledata"); - ZoneDefinitionInputStream inputStream(inputData, "test", "test.zone", true); + MockSearchPath mockSearchPath; + ZoneDefinitionInputStream inputStream(inputData, "test", "test.zone", mockSearchPath); const auto result = inputStream.ReadDefinition(); REQUIRE(result); @@ -197,7 +258,8 @@ material,test_material >level.ipak_read,code_post_gfx )sampledata"); - ZoneDefinitionInputStream inputStream(inputData, "test", "test.zone", true); + MockSearchPath mockSearchPath; + ZoneDefinitionInputStream inputStream(inputData, "test", "test.zone", mockSearchPath); const auto result = inputStream.ReadDefinition(); REQUIRE(result); @@ -219,4 +281,178 @@ material,test_material ++iterator; REQUIRE(iterator == ipakReadResults.second); } + + TEST_CASE("ZoneDefinitionInputStream: Ensure can define IWD", "[zonedefinition]") + { + std::istringstream inputData(R"sampledata( +// Call Of Duty: Black Ops II +>game,T6 +>name,test_mod + +>iwd,funnyIwd + +material,test_material +material,otherMaterial +material,lastMaterial + +)sampledata"); + + MockSearchPath mockSearchPath; + ZoneDefinitionInputStream inputStream(inputData, "test", "test.zone", mockSearchPath); + + const auto result = inputStream.ReadDefinition(); + REQUIRE(result); + + REQUIRE(result->m_assets.size() == 3); + REQUIRE(result->m_obj_containers.size() == 1); + + REQUIRE(result->m_obj_containers[0].m_type == ZoneDefinitionObjContainerType::IWD); + REQUIRE(result->m_obj_containers[0].m_name == "funnyIwd"); + REQUIRE(result->m_obj_containers[0].m_asset_start == 0u); + REQUIRE(result->m_obj_containers[0].m_asset_end == 3u); + } + + TEST_CASE("ZoneDefinitionInputStream: Defining another IWD stops current one", "[zonedefinition]") + { + std::istringstream inputData(R"sampledata( +// Call Of Duty: Black Ops II +>game,T6 +>name,test_mod + +>iwd,funnyIwd + +material,test_material +material,otherMaterial + +>iwd,otherIwd + +material,lastMaterial + +)sampledata"); + + MockSearchPath mockSearchPath; + ZoneDefinitionInputStream inputStream(inputData, "test", "test.zone", mockSearchPath); + + const auto result = inputStream.ReadDefinition(); + REQUIRE(result); + + REQUIRE(result->m_assets.size() == 3); + REQUIRE(result->m_obj_containers.size() == 2); + + REQUIRE(result->m_obj_containers[0].m_type == ZoneDefinitionObjContainerType::IWD); + REQUIRE(result->m_obj_containers[0].m_name == "funnyIwd"); + REQUIRE(result->m_obj_containers[0].m_asset_start == 0u); + REQUIRE(result->m_obj_containers[0].m_asset_end == 2u); + + REQUIRE(result->m_obj_containers[1].m_type == ZoneDefinitionObjContainerType::IWD); + REQUIRE(result->m_obj_containers[1].m_name == "otherIwd"); + REQUIRE(result->m_obj_containers[1].m_asset_start == 2u); + REQUIRE(result->m_obj_containers[1].m_asset_end == 3u); + } + + TEST_CASE("ZoneDefinitionInputStream: Ensure can define IPak", "[zonedefinition]") + { + std::istringstream inputData(R"sampledata( +// Call Of Duty: Black Ops II +>game,T6 +>name,test_mod + +>ipak,funnyIPak + +material,test_material +material,otherMaterial +material,lastMaterial + +)sampledata"); + + MockSearchPath mockSearchPath; + ZoneDefinitionInputStream inputStream(inputData, "test", "test.zone", mockSearchPath); + + const auto result = inputStream.ReadDefinition(); + REQUIRE(result); + + REQUIRE(result->m_assets.size() == 3); + REQUIRE(result->m_obj_containers.size() == 1); + + REQUIRE(result->m_obj_containers[0].m_type == ZoneDefinitionObjContainerType::IPAK); + REQUIRE(result->m_obj_containers[0].m_name == "funnyIPak"); + REQUIRE(result->m_obj_containers[0].m_asset_start == 0u); + REQUIRE(result->m_obj_containers[0].m_asset_end == 3u); + } + + TEST_CASE("ZoneDefinitionInputStream: Defining another IPak stops current one", "[zonedefinition]") + { + std::istringstream inputData(R"sampledata( +// Call Of Duty: Black Ops II +>game,T6 +>name,test_mod + +>ipak,funnyIPak + +material,test_material +material,otherMaterial + +>ipak,otherIPak + +material,lastMaterial + +)sampledata"); + + MockSearchPath mockSearchPath; + ZoneDefinitionInputStream inputStream(inputData, "test", "test.zone", mockSearchPath); + + const auto result = inputStream.ReadDefinition(); + REQUIRE(result); + + REQUIRE(result->m_assets.size() == 3); + REQUIRE(result->m_obj_containers.size() == 2); + + REQUIRE(result->m_obj_containers[0].m_type == ZoneDefinitionObjContainerType::IPAK); + REQUIRE(result->m_obj_containers[0].m_name == "funnyIPak"); + REQUIRE(result->m_obj_containers[0].m_asset_start == 0u); + REQUIRE(result->m_obj_containers[0].m_asset_end == 2u); + + REQUIRE(result->m_obj_containers[1].m_type == ZoneDefinitionObjContainerType::IPAK); + REQUIRE(result->m_obj_containers[1].m_name == "otherIPak"); + REQUIRE(result->m_obj_containers[1].m_asset_start == 2u); + REQUIRE(result->m_obj_containers[1].m_asset_end == 3u); + } + + TEST_CASE("ZoneDefinitionInputStream: Ensure can define IWD and IPak at the same time", "[zonedefinition]") + { + std::istringstream inputData(R"sampledata( +// Call Of Duty: Black Ops II +>game,T6 +>name,test_mod + +>iwd,funnyIwd + +material,test_material + +>ipak,funnyIPak + +material,otherMaterial +material,lastMaterial + +)sampledata"); + + MockSearchPath mockSearchPath; + ZoneDefinitionInputStream inputStream(inputData, "test", "test.zone", mockSearchPath); + + const auto result = inputStream.ReadDefinition(); + REQUIRE(result); + + REQUIRE(result->m_assets.size() == 3); + REQUIRE(result->m_obj_containers.size() == 2); + + REQUIRE(result->m_obj_containers[0].m_type == ZoneDefinitionObjContainerType::IWD); + REQUIRE(result->m_obj_containers[0].m_name == "funnyIwd"); + REQUIRE(result->m_obj_containers[0].m_asset_start == 0u); + REQUIRE(result->m_obj_containers[0].m_asset_end == 3u); + + REQUIRE(result->m_obj_containers[1].m_type == ZoneDefinitionObjContainerType::IPAK); + REQUIRE(result->m_obj_containers[1].m_name == "funnyIPak"); + REQUIRE(result->m_obj_containers[1].m_asset_start == 1u); + REQUIRE(result->m_obj_containers[1].m_asset_end == 3u); + } } // namespace test::zone::definition::zone_definition_stream