diff --git a/src/ObjCommon/Game/T6/FontIcon/FontIconCommonT6.cpp b/src/ObjCommon/FontIcon/FontIconCommon.cpp similarity index 85% rename from src/ObjCommon/Game/T6/FontIcon/FontIconCommonT6.cpp rename to src/ObjCommon/FontIcon/FontIconCommon.cpp index 5ae57d48..af9cbfb1 100644 --- a/src/ObjCommon/Game/T6/FontIcon/FontIconCommonT6.cpp +++ b/src/ObjCommon/FontIcon/FontIconCommon.cpp @@ -1,11 +1,11 @@ -#include "FontIconCommonT6.h" +#include "FontIconCommon.h" #include "Utils/StringUtils.h" #include namespace fs = std::filesystem; -namespace T6::font_icon +namespace font_icon { std::string GetJsonFileNameForAssetName(const std::string& assetName) { @@ -20,4 +20,4 @@ namespace T6::font_icon return assetName; } -} // namespace T6::font_icon +} // namespace font_icon diff --git a/src/ObjCommon/Game/T6/FontIcon/FontIconCommonT6.h b/src/ObjCommon/FontIcon/FontIconCommon.h similarity index 82% rename from src/ObjCommon/Game/T6/FontIcon/FontIconCommonT6.h rename to src/ObjCommon/FontIcon/FontIconCommon.h index bcce4518..e4c887bd 100644 --- a/src/ObjCommon/Game/T6/FontIcon/FontIconCommonT6.h +++ b/src/ObjCommon/FontIcon/FontIconCommon.h @@ -2,7 +2,7 @@ #include -namespace T6::font_icon +namespace font_icon { std::string GetJsonFileNameForAssetName(const std::string& assetName); } diff --git a/src/ObjCommon/Image/ImageCommon.cpp b/src/ObjCommon/Image/ImageCommon.cpp new file mode 100644 index 00000000..8a605bd7 --- /dev/null +++ b/src/ObjCommon/Image/ImageCommon.cpp @@ -0,0 +1,15 @@ +#include "ImageCommon.h" + +#include +#include + +namespace image +{ + std::string GetFileNameForAsset(std::string assetName, const std::string& extension) + { + std::string cleanAssetName(std::move(assetName)); + std::ranges::replace(cleanAssetName, '*', '_'); + + return std::format("images/{}{}", cleanAssetName, extension); + } +} // namespace image diff --git a/src/ObjCommon/Image/ImageCommon.h b/src/ObjCommon/Image/ImageCommon.h new file mode 100644 index 00000000..1a18b70e --- /dev/null +++ b/src/ObjCommon/Image/ImageCommon.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace image +{ + std::string GetFileNameForAsset(std::string assetName, const std::string& extension); +} diff --git a/src/ObjCommon/Leaderboard/LeaderboardCommon.cpp b/src/ObjCommon/Leaderboard/LeaderboardCommon.cpp new file mode 100644 index 00000000..d3286f36 --- /dev/null +++ b/src/ObjCommon/Leaderboard/LeaderboardCommon.cpp @@ -0,0 +1,11 @@ +#include "LeaderboardCommon.h" + +#include + +namespace leaderboard +{ + std::string GetJsonFileNameForAsset(const std::string& assetName) + { + return std::format("leaderboards/{}.json", assetName); + } +} // namespace leaderboard diff --git a/src/ObjCommon/Leaderboard/LeaderboardCommon.h b/src/ObjCommon/Leaderboard/LeaderboardCommon.h new file mode 100644 index 00000000..ab6958b1 --- /dev/null +++ b/src/ObjCommon/Leaderboard/LeaderboardCommon.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace leaderboard +{ + std::string GetJsonFileNameForAsset(const std::string& assetName); +} diff --git a/src/ObjCommon/LightDef/LightDefCommon.cpp b/src/ObjCommon/LightDef/LightDefCommon.cpp new file mode 100644 index 00000000..b43af370 --- /dev/null +++ b/src/ObjCommon/LightDef/LightDefCommon.cpp @@ -0,0 +1,11 @@ +#include "LightDefCommon.h" + +#include + +namespace light_def +{ + std::string GetFileNameForAsset(const std::string& assetName) + { + return std::format("lights/{}", assetName); + } +} // namespace light_def diff --git a/src/ObjCommon/LightDef/LightDefCommon.h b/src/ObjCommon/LightDef/LightDefCommon.h new file mode 100644 index 00000000..22002431 --- /dev/null +++ b/src/ObjCommon/LightDef/LightDefCommon.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace light_def +{ + std::string GetFileNameForAsset(const std::string& assetName); +} diff --git a/src/ObjCommon/PhysCollmap/PhysCollmapCommon.cpp b/src/ObjCommon/PhysCollmap/PhysCollmapCommon.cpp new file mode 100644 index 00000000..7414207e --- /dev/null +++ b/src/ObjCommon/PhysCollmap/PhysCollmapCommon.cpp @@ -0,0 +1,11 @@ +#include "PhysCollmapCommon.h" + +#include + +namespace phys_collmap +{ + std::string GetFileNameForAssetName(const std::string& assetName) + { + return std::format("phys_collmaps/{}.map", assetName); + } +} // namespace phys_collmap diff --git a/src/ObjCommon/PhysCollmap/PhysCollmapCommon.h b/src/ObjCommon/PhysCollmap/PhysCollmapCommon.h new file mode 100644 index 00000000..eaf0877e --- /dev/null +++ b/src/ObjCommon/PhysCollmap/PhysCollmapCommon.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace phys_collmap +{ + std::string GetFileNameForAssetName(const std::string& assetName); +} diff --git a/src/ObjCommon/PhysConstraints/PhysConstraintsCommon.cpp b/src/ObjCommon/PhysConstraints/PhysConstraintsCommon.cpp new file mode 100644 index 00000000..222a2615 --- /dev/null +++ b/src/ObjCommon/PhysConstraints/PhysConstraintsCommon.cpp @@ -0,0 +1,11 @@ +#include "PhysConstraintsCommon.h" + +#include + +namespace phys_constraints +{ + std::string GetFileNameForAssetName(const std::string& assetName) + { + return std::format("physconstraints/{}", assetName); + } +} // namespace phys_constraints diff --git a/src/ObjCommon/PhysConstraints/PhysConstraintsCommon.h b/src/ObjCommon/PhysConstraints/PhysConstraintsCommon.h new file mode 100644 index 00000000..90ccfb1c --- /dev/null +++ b/src/ObjCommon/PhysConstraints/PhysConstraintsCommon.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace phys_constraints +{ + std::string GetFileNameForAssetName(const std::string& assetName); +} diff --git a/src/ObjCommon/PhysPreset/PhysPresetCommon.cpp b/src/ObjCommon/PhysPreset/PhysPresetCommon.cpp new file mode 100644 index 00000000..66c08396 --- /dev/null +++ b/src/ObjCommon/PhysPreset/PhysPresetCommon.cpp @@ -0,0 +1,11 @@ +#include "PhysPresetCommon.h" + +#include + +namespace phys_preset +{ + std::string GetFileNameForAssetName(const std::string& assetName) + { + return std::format("physic/{}", assetName); + } +} // namespace phys_preset diff --git a/src/ObjCommon/PhysPreset/PhysPresetCommon.h b/src/ObjCommon/PhysPreset/PhysPresetCommon.h new file mode 100644 index 00000000..d627051c --- /dev/null +++ b/src/ObjCommon/PhysPreset/PhysPresetCommon.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace phys_preset +{ + std::string GetFileNameForAssetName(const std::string& assetName); +} diff --git a/src/ObjCommon/Shader/ShaderCommon.cpp b/src/ObjCommon/Shader/ShaderCommon.cpp new file mode 100644 index 00000000..7dc6c7bb --- /dev/null +++ b/src/ObjCommon/Shader/ShaderCommon.cpp @@ -0,0 +1,16 @@ +#include "ShaderCommon.h" + +#include + +namespace shader +{ + std::string GetFileNameForPixelShaderAssetName(const std::string& assetName) + { + return std::format("shader_bin/ps_{}.cso", assetName); + } + + std::string GetFileNameForVertexShaderAssetName(const std::string& assetName) + { + return std::format("shader_bin/vs_{}.cso", assetName); + } +} // namespace shader diff --git a/src/ObjCommon/Shader/ShaderCommon.h b/src/ObjCommon/Shader/ShaderCommon.h new file mode 100644 index 00000000..0e3ef878 --- /dev/null +++ b/src/ObjCommon/Shader/ShaderCommon.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +namespace shader +{ + std::string GetFileNameForPixelShaderAssetName(const std::string& assetName); + std::string GetFileNameForVertexShaderAssetName(const std::string& assetName); +} // namespace shader diff --git a/src/ObjCommon/Sound/SoundCurveCommon.cpp b/src/ObjCommon/Sound/SoundCurveCommon.cpp new file mode 100644 index 00000000..461a3f08 --- /dev/null +++ b/src/ObjCommon/Sound/SoundCurveCommon.cpp @@ -0,0 +1,11 @@ +#include "SoundCurveCommon.h" + +#include + +namespace sound_curve +{ + std::string GetFileNameForAssetName(const std::string& assetName) + { + return std::format("soundaliases/{}.vfcurve", assetName); + } +} // namespace sound_curve diff --git a/src/ObjCommon/Sound/SoundCurveCommon.h b/src/ObjCommon/Sound/SoundCurveCommon.h new file mode 100644 index 00000000..8ac96a84 --- /dev/null +++ b/src/ObjCommon/Sound/SoundCurveCommon.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace sound_curve +{ + std::string GetFileNameForAssetName(const std::string& assetName); +} diff --git a/src/ObjCommon/Techset/TechsetCommon.cpp b/src/ObjCommon/Techset/TechsetCommon.cpp new file mode 100644 index 00000000..f21097bd --- /dev/null +++ b/src/ObjCommon/Techset/TechsetCommon.cpp @@ -0,0 +1,21 @@ +#include "TechsetCommon.h" + +#include + +namespace techset +{ + std::string GetFileNameForStateMapName(const std::string& stateMapName) + { + return std::format("statemaps/{}.sm", stateMapName); + } + + std::string GetFileNameForTechniqueName(const std::string& assetName) + { + return std::format("techniques/{}.tech", assetName); + } + + std::string GetFileNameForTechsetName(const std::string& assetName) + { + return std::format("techsets/{}.techset", assetName); + } +} // namespace techset diff --git a/src/ObjCommon/Techset/TechsetCommon.h b/src/ObjCommon/Techset/TechsetCommon.h new file mode 100644 index 00000000..ad65b5df --- /dev/null +++ b/src/ObjCommon/Techset/TechsetCommon.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace techset +{ + std::string GetFileNameForStateMapName(const std::string& stateMapName); + std::string GetFileNameForTechniqueName(const std::string& assetName); + std::string GetFileNameForTechsetName(const std::string& assetName); +} // namespace techset diff --git a/src/ObjCommon/Tracer/TracerCommon.cpp b/src/ObjCommon/Tracer/TracerCommon.cpp new file mode 100644 index 00000000..d48a0740 --- /dev/null +++ b/src/ObjCommon/Tracer/TracerCommon.cpp @@ -0,0 +1,11 @@ +#include "TracerCommon.h" + +#include + +namespace tracer +{ + std::string GetFileNameForAssetName(const std::string& assetName) + { + return std::format("tracer/{}", assetName); + } +} // namespace tracer diff --git a/src/ObjCommon/Tracer/TracerCommon.h b/src/ObjCommon/Tracer/TracerCommon.h new file mode 100644 index 00000000..d95136b7 --- /dev/null +++ b/src/ObjCommon/Tracer/TracerCommon.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace tracer +{ + std::string GetFileNameForAssetName(const std::string& assetName); +} diff --git a/src/ObjCommon/Vehicle/VehicleCommon.cpp b/src/ObjCommon/Vehicle/VehicleCommon.cpp new file mode 100644 index 00000000..6b1ca27f --- /dev/null +++ b/src/ObjCommon/Vehicle/VehicleCommon.cpp @@ -0,0 +1,11 @@ +#include "VehicleCommon.h" + +#include + +namespace vehicle +{ + std::string GetFileNameForAssetName(const std::string& assetName) + { + return std::format("vehicles/{}", assetName); + } +} // namespace vehicle diff --git a/src/ObjCommon/Vehicle/VehicleCommon.h b/src/ObjCommon/Vehicle/VehicleCommon.h new file mode 100644 index 00000000..ecd96304 --- /dev/null +++ b/src/ObjCommon/Vehicle/VehicleCommon.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace vehicle +{ + std::string GetFileNameForAssetName(const std::string& assetName); +} diff --git a/src/ObjCommon/Weapon/AttachmentCommon.cpp b/src/ObjCommon/Weapon/AttachmentCommon.cpp new file mode 100644 index 00000000..1fd354b3 --- /dev/null +++ b/src/ObjCommon/Weapon/AttachmentCommon.cpp @@ -0,0 +1,16 @@ +#include "AttachmentCommon.h" + +#include + +namespace attachment +{ + std::string GetInfoStringFileNameForAssetName(const std::string& assetName) + { + return std::format("attachment/{}", assetName); + } + + std::string GetJsonFileNameForAssetName(const std::string& assetName) + { + return std::format("attachment/{}.json", assetName); + } +} // namespace attachment diff --git a/src/ObjCommon/Weapon/AttachmentCommon.h b/src/ObjCommon/Weapon/AttachmentCommon.h new file mode 100644 index 00000000..e9566b4f --- /dev/null +++ b/src/ObjCommon/Weapon/AttachmentCommon.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +namespace attachment +{ + std::string GetInfoStringFileNameForAssetName(const std::string& assetName); + std::string GetJsonFileNameForAssetName(const std::string& assetName); +} // namespace attachment diff --git a/src/ObjCommon/Weapon/AttachmentUniqueCommon.cpp b/src/ObjCommon/Weapon/AttachmentUniqueCommon.cpp new file mode 100644 index 00000000..a1b520e3 --- /dev/null +++ b/src/ObjCommon/Weapon/AttachmentUniqueCommon.cpp @@ -0,0 +1,11 @@ +#include "AttachmentUniqueCommon.h" + +#include + +namespace attachment_unique +{ + std::string GetFileNameForAssetName(const std::string& assetName) + { + return std::format("attachmentunique/{}", assetName); + } +} // namespace attachment_unique diff --git a/src/ObjCommon/Weapon/AttachmentUniqueCommon.h b/src/ObjCommon/Weapon/AttachmentUniqueCommon.h new file mode 100644 index 00000000..dcc9accc --- /dev/null +++ b/src/ObjCommon/Weapon/AttachmentUniqueCommon.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace attachment_unique +{ + std::string GetFileNameForAssetName(const std::string& assetName); +} diff --git a/src/ObjCommon/Weapon/CamoCommon.cpp b/src/ObjCommon/Weapon/CamoCommon.cpp new file mode 100644 index 00000000..293794eb --- /dev/null +++ b/src/ObjCommon/Weapon/CamoCommon.cpp @@ -0,0 +1,11 @@ +#include "WeaponCommon.h" + +#include + +namespace camo +{ + std::string GetJsonFileNameForAssetName(const std::string& assetName) + { + return std::format("camo/{}.json", assetName); + } +} // namespace camo diff --git a/src/ObjCommon/Weapon/CamoCommon.h b/src/ObjCommon/Weapon/CamoCommon.h new file mode 100644 index 00000000..b0450767 --- /dev/null +++ b/src/ObjCommon/Weapon/CamoCommon.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace camo +{ + std::string GetJsonFileNameForAssetName(const std::string& assetName); +} diff --git a/src/ObjCommon/Weapon/WeaponCommon.cpp b/src/ObjCommon/Weapon/WeaponCommon.cpp new file mode 100644 index 00000000..704a388c --- /dev/null +++ b/src/ObjCommon/Weapon/WeaponCommon.cpp @@ -0,0 +1,11 @@ +#include "WeaponCommon.h" + +#include + +namespace weapon +{ + std::string GetFileNameForAssetName(const std::string& assetName) + { + return std::format("weapons/{}", assetName); + } +} // namespace weapon diff --git a/src/ObjCommon/Weapon/WeaponCommon.h b/src/ObjCommon/Weapon/WeaponCommon.h new file mode 100644 index 00000000..1d1a350a --- /dev/null +++ b/src/ObjCommon/Weapon/WeaponCommon.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace weapon +{ + std::string GetFileNameForAssetName(const std::string& assetName); +} diff --git a/src/ObjCommon/XModel/XModelCommon.cpp b/src/ObjCommon/XModel/XModelCommon.cpp index a3cfb586..f44e7165 100644 --- a/src/ObjCommon/XModel/XModelCommon.cpp +++ b/src/ObjCommon/XModel/XModelCommon.cpp @@ -1,6 +1,7 @@ #include "XModelCommon.h" #include +#include #include #include @@ -99,3 +100,11 @@ bool operator<(const VertexMergerPos& lhs, const VertexMergerPos& rhs) return false; } + +namespace xmodel +{ + std::string GetJsonFileNameForAssetName(const std::string& assetName) + { + return std::format("xmodel/{}.json", assetName); + } +} // namespace xmodel diff --git a/src/ObjCommon/XModel/XModelCommon.h b/src/ObjCommon/XModel/XModelCommon.h index 2caf68b3..c5f0843c 100644 --- a/src/ObjCommon/XModel/XModelCommon.h +++ b/src/ObjCommon/XModel/XModelCommon.h @@ -127,3 +127,8 @@ struct VertexMergerPos }; typedef DistinctMapper VertexMerger; + +namespace xmodel +{ + std::string GetJsonFileNameForAssetName(const std::string& assetName); +} diff --git a/src/ObjCommon/ZBarrier/ZBarrierCommon.cpp b/src/ObjCommon/ZBarrier/ZBarrierCommon.cpp new file mode 100644 index 00000000..354ccaba --- /dev/null +++ b/src/ObjCommon/ZBarrier/ZBarrierCommon.cpp @@ -0,0 +1,11 @@ +#include "ZBarrierCommon.h" + +#include + +namespace z_barrier +{ + std::string GetFileNameForAssetName(const std::string& assetName) + { + return std::format("zbarrier/{}", assetName); + } +} // namespace z_barrier diff --git a/src/ObjCommon/ZBarrier/ZBarrierCommon.h b/src/ObjCommon/ZBarrier/ZBarrierCommon.h new file mode 100644 index 00000000..e647286c --- /dev/null +++ b/src/ObjCommon/ZBarrier/ZBarrierCommon.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace z_barrier +{ + std::string GetFileNameForAssetName(const std::string& assetName); +} diff --git a/src/ObjCompiling/Game/IW3/ObjCompilerIW3.cpp b/src/ObjCompiling/Game/IW3/ObjCompilerIW3.cpp index 02e34655..29ea2ee1 100644 --- a/src/ObjCompiling/Game/IW3/ObjCompilerIW3.cpp +++ b/src/ObjCompiling/Game/IW3/ObjCompilerIW3.cpp @@ -25,8 +25,8 @@ namespace { auto& memory = zone.Memory(); - if (ImageIwdPostProcessor::AppliesToZoneDefinition(zoneDefinition)) - collection.AddAssetPostProcessor(std::make_unique>(zoneDefinition, searchPath, zoneStates, outDir)); + if (image::IwdPostProcessor::AppliesToZoneDefinition(zoneDefinition)) + collection.AddAssetPostProcessor(std::make_unique>(zoneDefinition, searchPath, zoneStates, outDir)); } } // namespace diff --git a/src/ObjCompiling/Game/IW4/Material/CompilerMaterialIW4.cpp b/src/ObjCompiling/Game/IW4/Material/CompilerMaterialIW4.cpp index 7b54ceaa..82d6ceb5 100644 --- a/src/ObjCompiling/Game/IW4/Material/CompilerMaterialIW4.cpp +++ b/src/ObjCompiling/Game/IW4/Material/CompilerMaterialIW4.cpp @@ -14,6 +14,7 @@ #include "StateMap/StateMapHandler.h" #include "Techset/TechniqueFileReader.h" #include "Techset/TechniqueStateMapCache.h" +#include "Techset/TechsetCommon.h" #include "Techset/TechsetDefinitionCache.h" #include @@ -45,9 +46,9 @@ namespace m_search_path(searchPath), m_context(context), m_registration(registration), - m_state_map_cache(context.GetZoneAssetCreationState()), + m_state_map_cache(context.GetZoneAssetCreationState<::techset::TechniqueStateMapCache>()), m_base_state_bits{}, - m_techset_creator(CreateTechsetLoader(memory, searchPath)) + m_techset_creator(techset::CreateLoaderIW4(memory, searchPath)) { } @@ -793,7 +794,7 @@ namespace m_registration.AddDependency(techset); m_material.techniqueSet = techset->Asset(); - auto& definitionCache = m_context.GetZoneAssetCreationState(); + auto& definitionCache = m_context.GetZoneAssetCreationState<::techset::TechsetDefinitionCache>(); bool failure = false; const auto* techsetDefinition = m_techset_creator->LoadTechsetDefinition(techsetName, m_context, failure); @@ -806,7 +807,7 @@ namespace SetTechniqueSetCameraRegion(techsetDefinition); } - void SetTechniqueSetStateBits(const techset::TechsetDefinition* techsetDefinition) + void SetTechniqueSetStateBits(const ::techset::TechsetDefinition* techsetDefinition) { for (auto i = 0; i < TECHNIQUE_COUNT; i++) { @@ -854,19 +855,19 @@ namespace return stateBits; } - _NODISCARD const state_map::StateMapDefinition* GetStateMapForTechnique(const std::string& techniqueName) const + [[nodiscard]] const state_map::StateMapDefinition* GetStateMapForTechnique(const std::string& techniqueName) const { const auto* preloadedStateMap = m_state_map_cache.GetStateMapForTechnique(techniqueName); if (preloadedStateMap) return preloadedStateMap; - const auto techniqueFileName = GetTechniqueFileName(techniqueName); + const auto techniqueFileName = ::techset::GetFileNameForTechniqueName(techniqueName); const auto file = m_search_path.Open(techniqueFileName); if (!file.IsOpen()) return nullptr; state_map::StateMapFromTechniqueExtractor extractor; - const techset::TechniqueFileReader reader(*file.m_stream, techniqueFileName, &extractor); + const ::techset::TechniqueFileReader reader(*file.m_stream, techniqueFileName, &extractor); if (!reader.ReadTechniqueDefinition()) { m_state_map_cache.SetTechniqueUsesStateMap(techniqueName, nullptr); @@ -890,7 +891,7 @@ namespace return outBits; } - void SetTechniqueSetCameraRegion(const techset::TechsetDefinition* techsetDefinition) const + void SetTechniqueSetCameraRegion(const ::techset::TechsetDefinition* techsetDefinition) const { std::string tempName; if (techsetDefinition->GetTechniqueByIndex(TECHNIQUE_LIT, tempName)) @@ -1316,7 +1317,7 @@ namespace AssetCreationContext& m_context; AssetRegistration& m_registration; - techset::TechniqueStateMapCache& m_state_map_cache; + ::techset::TechniqueStateMapCache& m_state_map_cache; std::unordered_map m_state_bits_per_state_map; GfxStateBits m_base_state_bits; @@ -1324,7 +1325,7 @@ namespace std::vector m_textures; std::vector m_constants; - std::unique_ptr m_techset_creator; + std::unique_ptr m_techset_creator; }; class MaterialLoader final : public AssetCreator @@ -1374,10 +1375,10 @@ namespace }; } // namespace -namespace IW4 +namespace material { - std::unique_ptr> CreateMaterialCompiler(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt) + std::unique_ptr> CreateCompilerIW4(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt) { return std::make_unique(memory, searchPath, gdt); } -} // namespace IW4 +} // namespace material diff --git a/src/ObjCompiling/Game/IW4/Material/CompilerMaterialIW4.h b/src/ObjCompiling/Game/IW4/Material/CompilerMaterialIW4.h index 52c7d3dd..7d3e216a 100644 --- a/src/ObjCompiling/Game/IW4/Material/CompilerMaterialIW4.h +++ b/src/ObjCompiling/Game/IW4/Material/CompilerMaterialIW4.h @@ -6,7 +6,7 @@ #include "SearchPath/ISearchPath.h" #include "Utils/MemoryManager.h" -namespace IW4 +namespace material { - std::unique_ptr> CreateMaterialCompiler(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt); -} // namespace IW4 + std::unique_ptr> CreateCompilerIW4(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt); +} // namespace material diff --git a/src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp b/src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp index f33dd566..3930a746 100644 --- a/src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp +++ b/src/ObjCompiling/Game/IW4/ObjCompilerIW4.cpp @@ -17,10 +17,10 @@ namespace auto& memory = zone.Memory(); #ifdef EXPERIMENTAL_MATERIAL_COMPILATION - collection.AddAssetCreator(CreateMaterialCompiler(memory, searchPath, gdt)); - collection.AddAssetCreator(CreateTechsetLoader(memory, searchPath)); + collection.AddAssetCreator(material::CreateCompilerIW4(memory, searchPath, gdt)); + collection.AddAssetCreator(techset::CreateLoaderIW4(memory, searchPath)); #endif - collection.AddAssetCreator(CreateVertexDeclLoader(memory)); + collection.AddAssetCreator(vertex_decl::CreateLoaderIW4(memory)); } void ConfigurePostProcessors(AssetCreatorCollection& collection, @@ -32,8 +32,8 @@ namespace { auto& memory = zone.Memory(); - if (ImageIwdPostProcessor::AppliesToZoneDefinition(zoneDefinition)) - collection.AddAssetPostProcessor(std::make_unique>(zoneDefinition, searchPath, zoneStates, outDir)); + if (image::IwdPostProcessor::AppliesToZoneDefinition(zoneDefinition)) + collection.AddAssetPostProcessor(std::make_unique>(zoneDefinition, searchPath, zoneStates, outDir)); } } // namespace diff --git a/src/ObjCompiling/Game/IW4/Techset/CompilerTechsetIW4.cpp b/src/ObjCompiling/Game/IW4/Techset/CompilerTechsetIW4.cpp index bb53a3d5..50fe5b4e 100644 --- a/src/ObjCompiling/Game/IW4/Techset/CompilerTechsetIW4.cpp +++ b/src/ObjCompiling/Game/IW4/Techset/CompilerTechsetIW4.cpp @@ -5,9 +5,11 @@ #include "Game/IW4/Shader/LoaderVertexShaderIW4.h" #include "Game/IW4/TechsetConstantsIW4.h" #include "Shader/D3D9ShaderAnalyser.h" +#include "Shader/ShaderCommon.h" #include "StateMap/StateMapReader.h" #include "Techset/TechniqueFileReader.h" #include "Techset/TechniqueStateMapCache.h" +#include "Techset/TechsetCommon.h" #include "Techset/TechsetDefinitionCache.h" #include "Techset/TechsetFileReader.h" #include "Utils/Alignment.h" @@ -24,6 +26,7 @@ #include using namespace IW4; +using namespace ::techset; using namespace std::string_literals; namespace @@ -61,7 +64,7 @@ namespace .first->second.get(); } - literal_t GetAllocatedLiteral(MemoryManager& memory, techset::ShaderArgumentLiteralSource source) + literal_t GetAllocatedLiteral(MemoryManager& memory, ShaderArgumentLiteralSource source) { const auto& existingEntry = m_allocated_literals.find(source); @@ -80,7 +83,7 @@ namespace private: std::unordered_map> m_loaded_techniques; - std::map m_allocated_literals; + std::map m_allocated_literals; }; class ShaderInfoFromFileSystemCacheState final : public IZoneAssetCreationState @@ -120,7 +123,7 @@ namespace std::unordered_map> m_cached_shader_info; }; - class TechniqueCreator final : public techset::ITechniqueDefinitionAcceptor + class TechniqueCreator final : public ITechniqueDefinitionAcceptor { public: class PassShaderArgument @@ -196,14 +199,17 @@ namespace std::vector m_arguments; }; - TechniqueCreator( - const std::string& techniqueName, ISearchPath& searchPath, MemoryManager& memory, AssetCreationContext& context, ITechsetCreator* techsetCreator) + TechniqueCreator(const std::string& techniqueName, + ISearchPath& searchPath, + MemoryManager& memory, + AssetCreationContext& context, + techset::ICreatorIW4* techsetCreator) : m_technique_name(techniqueName), m_search_path(searchPath), m_memory(memory), m_context(context), m_zone_state(context.GetZoneAssetCreationState()), - m_state_map_cache(context.GetZoneAssetCreationState()), + m_state_map_cache(context.GetZoneAssetCreationState()), m_shader_info_cache(context.GetZoneAssetCreationState()), m_techset_creator(techsetCreator) { @@ -229,7 +235,7 @@ namespace || constant.m_type == d3d9::ParameterType::SAMPLER_CUBE; } - bool AutoCreateShaderArgument(const techset::ShaderSelector shaderType, + bool AutoCreateShaderArgument(const ShaderSelector shaderType, const d3d9::ShaderConstant& shaderArgument, const size_t elementOffset, const size_t registerOffset) @@ -238,7 +244,7 @@ namespace auto& pass = m_passes.at(m_passes.size() - 1); const auto isSamplerArgument = IsSamplerArgument(shaderArgument); - if (shaderType == techset::ShaderSelector::VERTEX_SHADER && isSamplerArgument) + if (shaderType == ShaderSelector::VERTEX_SHADER && isSamplerArgument) return false; MaterialShaderArgument argument; @@ -269,7 +275,7 @@ namespace if (!constantSource) return false; - argument.type = shaderType == techset::ShaderSelector::VERTEX_SHADER ? MTL_ARG_CODE_VERTEX_CONST : MTL_ARG_CODE_PIXEL_CONST; + argument.type = shaderType == ShaderSelector::VERTEX_SHADER ? MTL_ARG_CODE_VERTEX_CONST : MTL_ARG_CODE_PIXEL_CONST; argument.u.codeConst.index = static_cast(constantSource->source + elementOffset); argument.u.codeConst.firstRow = 0u; argument.u.codeConst.rowCount = static_cast(shaderArgument.m_type_rows); @@ -300,7 +306,7 @@ namespace { if (!pass.m_handled_vertex_shader_arguments[argumentHandledIndex + elementIndex]) { - if (!AutoCreateShaderArgument(techset::ShaderSelector::VERTEX_SHADER, argument, elementIndex, registerIndex)) + if (!AutoCreateShaderArgument(ShaderSelector::VERTEX_SHADER, argument, elementIndex, registerIndex)) { std::string elementIndexStr; if (argument.m_type_elements > 1) @@ -335,7 +341,7 @@ namespace { if (!pass.m_handled_pixel_shader_arguments[argumentHandledIndex + elementIndex]) { - if (!AutoCreateShaderArgument(techset::ShaderSelector::PIXEL_SHADER, argument, elementIndex, registerIndex)) + if (!AutoCreateShaderArgument(ShaderSelector::PIXEL_SHADER, argument, elementIndex, registerIndex)) { std::ostringstream ss; ss << "Unassigned pixel shader \"" << pass.m_pixel_shader->m_name << "\" arg: " << argument.m_name; @@ -460,7 +466,8 @@ namespace 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, GetVertexShaderFileName(vertexShaderName)); + pass.m_vertex_shader_info = + m_shader_info_cache.LoadShaderInfoFromDisk(m_search_path, ::shader::GetFileNameForVertexShaderAssetName(vertexShaderName)); } else { @@ -495,7 +502,8 @@ namespace 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, GetPixelShaderFileName(pixelShaderName)); + pass.m_pixel_shader_info = + m_shader_info_cache.LoadShaderInfoFromDisk(m_search_path, ::shader::GetFileNameForPixelShaderAssetName(pixelShaderName)); } else { @@ -569,11 +577,8 @@ namespace return foundSource; } - static bool FindShaderArgument(const d3d9::ShaderInfo& shaderInfo, - const techset::ShaderArgument& argument, - size_t& constantIndex, - size_t& registerOffset, - std::string& errorMessage) + static bool FindShaderArgument( + const d3d9::ShaderInfo& shaderInfo, const ShaderArgument& argument, size_t& constantIndex, size_t& registerOffset, std::string& errorMessage) { const auto matchingShaderConstant = std::ranges::find_if(shaderInfo.m_constants, [argument](const d3d9::ShaderConstant& constant) @@ -619,7 +624,7 @@ namespace } static bool SetArgumentCodeConst(MaterialShaderArgument& argument, - const techset::ShaderArgumentCodeSource& source, + const ShaderArgumentCodeSource& source, const d3d9::ShaderConstant& shaderConstant, const unsigned sourceIndex, const unsigned arrayCount, @@ -657,7 +662,7 @@ namespace } static bool SetArgumentCodeSampler(MaterialShaderArgument& argument, - const techset::ShaderArgumentCodeSource& source, + const ShaderArgumentCodeSource& source, const d3d9::ShaderConstant& shaderConstant, const unsigned sourceIndex, const unsigned arrayCount, @@ -692,9 +697,7 @@ namespace return true; } - bool AcceptVertexShaderConstantArgument(const techset::ShaderArgument& shaderArgument, - const techset::ShaderArgumentCodeSource& source, - std::string& errorMessage) + bool AcceptVertexShaderConstantArgument(const ShaderArgument& shaderArgument, const ShaderArgumentCodeSource& source, std::string& errorMessage) { assert(!m_passes.empty()); auto& pass = m_passes.at(m_passes.size() - 1); @@ -742,8 +745,8 @@ namespace return true; } - bool AcceptPixelShaderCodeArgument(const techset::ShaderArgument& shaderArgument, - const techset::ShaderArgumentCodeSource& source, + bool AcceptPixelShaderCodeArgument(const ShaderArgument& shaderArgument, + const ShaderArgumentCodeSource& source, std::string& errorMessage, const bool isSampler) { @@ -823,36 +826,36 @@ namespace return true; } - bool AcceptShaderConstantArgument(const techset::ShaderSelector shader, - const techset::ShaderArgument shaderArgument, - const techset::ShaderArgumentCodeSource source, + bool AcceptShaderConstantArgument(const ShaderSelector shader, + const ShaderArgument shaderArgument, + const ShaderArgumentCodeSource source, std::string& errorMessage) override { - if (shader == techset::ShaderSelector::VERTEX_SHADER) + if (shader == ShaderSelector::VERTEX_SHADER) return AcceptVertexShaderConstantArgument(shaderArgument, source, errorMessage); - assert(shader == techset::ShaderSelector::PIXEL_SHADER); + assert(shader == ShaderSelector::PIXEL_SHADER); return AcceptPixelShaderCodeArgument(shaderArgument, source, errorMessage, false); } - bool AcceptShaderSamplerArgument(const techset::ShaderSelector shader, - const techset::ShaderArgument shaderArgument, - const techset::ShaderArgumentCodeSource source, + bool AcceptShaderSamplerArgument(const ShaderSelector shader, + const ShaderArgument shaderArgument, + const ShaderArgumentCodeSource source, std::string& errorMessage) override { - if (shader == techset::ShaderSelector::VERTEX_SHADER) + if (shader == ShaderSelector::VERTEX_SHADER) { errorMessage = "Vertex sampler are unsupported"; return false; } - assert(shader == techset::ShaderSelector::PIXEL_SHADER); + assert(shader == ShaderSelector::PIXEL_SHADER); return AcceptPixelShaderCodeArgument(shaderArgument, source, errorMessage, true); } - bool AcceptShaderLiteralArgument(const techset::ShaderSelector shader, - const techset::ShaderArgument shaderArgument, - const techset::ShaderArgumentLiteralSource source, + bool AcceptShaderLiteralArgument(const ShaderSelector shader, + const ShaderArgument shaderArgument, + const ShaderArgumentLiteralSource source, std::string& errorMessage) override { assert(!m_passes.empty()); @@ -861,14 +864,14 @@ namespace MaterialShaderArgument argument; const d3d9::ShaderInfo* shaderInfo; - if (shader == techset::ShaderSelector::VERTEX_SHADER) + if (shader == ShaderSelector::VERTEX_SHADER) { argument.type = MTL_ARG_LITERAL_VERTEX_CONST; shaderInfo = pass.m_vertex_shader_info; } else { - assert(shader == techset::ShaderSelector::PIXEL_SHADER); + assert(shader == ShaderSelector::PIXEL_SHADER); argument.type = MTL_ARG_LITERAL_PIXEL_CONST; shaderInfo = pass.m_pixel_shader_info; } @@ -889,7 +892,7 @@ namespace const auto argumentIsSampler = IsSamplerArgument(shaderConstant); if (argumentIsSampler) { - if (shader == techset::ShaderSelector::VERTEX_SHADER) + if (shader == ShaderSelector::VERTEX_SHADER) errorMessage = "Vertex shader argument expects sampler but got constant"; else errorMessage = "Pixel shader argument expects sampler but got constant"; @@ -901,7 +904,7 @@ namespace argument.u.literalConst = m_zone_state.GetAllocatedLiteral(m_memory, source); pass.m_arguments.emplace_back(argument); - if (shader == techset::ShaderSelector::VERTEX_SHADER) + if (shader == ShaderSelector::VERTEX_SHADER) pass.m_handled_vertex_shader_arguments[pass.m_vertex_shader_argument_handled_offset[shaderConstantIndex] + elementOffset] = true; else pass.m_handled_pixel_shader_arguments[pass.m_pixel_shader_argument_handled_offset[shaderConstantIndex] + elementOffset] = true; @@ -909,9 +912,9 @@ namespace return true; } - bool AcceptShaderMaterialArgument(const techset::ShaderSelector shader, - const techset::ShaderArgument shaderArgument, - const techset::ShaderArgumentMaterialSource source, + bool AcceptShaderMaterialArgument(const ShaderSelector shader, + const ShaderArgument shaderArgument, + const ShaderArgumentMaterialSource source, std::string& errorMessage) override { assert(!m_passes.empty()); @@ -920,13 +923,13 @@ namespace MaterialShaderArgument argument; const d3d9::ShaderInfo* shaderInfo; - if (shader == techset::ShaderSelector::VERTEX_SHADER) + if (shader == ShaderSelector::VERTEX_SHADER) { shaderInfo = pass.m_vertex_shader_info; } else { - assert(shader == techset::ShaderSelector::PIXEL_SHADER); + assert(shader == ShaderSelector::PIXEL_SHADER); shaderInfo = pass.m_pixel_shader_info; } @@ -944,7 +947,7 @@ namespace const auto elementOffset = shaderArgument.m_argument_index_specified ? shaderArgument.m_argument_index : 0u; const auto& shaderConstant = shaderInfo->m_constants[shaderConstantIndex]; const auto argumentIsSampler = IsSamplerArgument(shaderConstant); - if (shader == techset::ShaderSelector::VERTEX_SHADER) + if (shader == ShaderSelector::VERTEX_SHADER) { if (argumentIsSampler) { @@ -955,7 +958,7 @@ namespace } else { - assert(shader == techset::ShaderSelector::PIXEL_SHADER); + assert(shader == ShaderSelector::PIXEL_SHADER); argument.type = !argumentIsSampler ? MTL_ARG_MATERIAL_PIXEL_CONST : MTL_ARG_MATERIAL_PIXEL_SAMPLER; } @@ -967,7 +970,7 @@ namespace argument.dest = static_cast(shaderConstant.m_register_index + registerOffset); pass.m_arguments.emplace_back(argument); - if (shader == techset::ShaderSelector::VERTEX_SHADER) + if (shader == ShaderSelector::VERTEX_SHADER) pass.m_handled_vertex_shader_arguments[pass.m_vertex_shader_argument_handled_offset[shaderConstantIndex] + elementOffset] = true; else pass.m_handled_pixel_shader_arguments[pass.m_pixel_shader_argument_handled_offset[shaderConstantIndex] + elementOffset] = true; @@ -1021,15 +1024,15 @@ namespace MemoryManager& m_memory; AssetCreationContext& m_context; TechniqueZoneLoadingState& m_zone_state; - techset::TechniqueStateMapCache& m_state_map_cache; + TechniqueStateMapCache& m_state_map_cache; ShaderInfoFromFileSystemCacheState& m_shader_info_cache; - ITechsetCreator* m_techset_creator; + techset::ICreatorIW4* m_techset_creator; }; class TechniqueLoader { public: - TechniqueLoader(ISearchPath& searchPath, MemoryManager& memory, AssetCreationContext& context, ITechsetCreator* techsetCreator) + TechniqueLoader(ISearchPath& searchPath, MemoryManager& memory, AssetCreationContext& context, techset::ICreatorIW4* techsetCreator) : m_search_path(searchPath), m_memory(memory), m_context(context), @@ -1240,13 +1243,13 @@ namespace MaterialTechnique* LoadTechniqueFromRaw(const std::string& techniqueName, std::vector& dependencies) const { - const auto techniqueFileName = GetTechniqueFileName(techniqueName); + const auto techniqueFileName = GetFileNameForTechniqueName(techniqueName); const auto file = m_search_path.Open(techniqueFileName); if (!file.IsOpen()) return nullptr; TechniqueCreator creator(techniqueName, m_search_path, m_memory, m_context, m_techset_creator); - const techset::TechniqueFileReader reader(*file.m_stream, techniqueFileName, &creator); + const TechniqueFileReader reader(*file.m_stream, techniqueFileName, &creator); if (!reader.ReadTechniqueDefinition()) return nullptr; @@ -1257,10 +1260,10 @@ namespace MemoryManager& m_memory; AssetCreationContext& m_context; TechniqueZoneLoadingState& m_zone_state; - ITechsetCreator* m_techset_creator; + techset::ICreatorIW4* m_techset_creator; }; - class TechsetLoader final : public ITechsetCreator + class TechsetLoader final : public techset::ICreatorIW4 { public: TechsetLoader(MemoryManager& memory, ISearchPath& searchPath) @@ -1280,8 +1283,7 @@ namespace } private: - AssetCreationResult - CreateTechsetFromDefinition(const std::string& assetName, const techset::TechsetDefinition& definition, AssetCreationContext& context) + AssetCreationResult CreateTechsetFromDefinition(const std::string& assetName, const TechsetDefinition& definition, AssetCreationContext& context) { auto* techset = m_memory.Alloc(); techset->name = m_memory.Dup(assetName.c_str()); @@ -1309,20 +1311,20 @@ namespace return AssetCreationResult::Success(context.AddAsset(std::move(registration))); } - techset::TechsetDefinition* LoadTechsetDefinition(const std::string& assetName, AssetCreationContext& context, bool& failure) override + TechsetDefinition* LoadTechsetDefinition(const std::string& assetName, AssetCreationContext& context, bool& failure) override { failure = false; - auto& definitionCache = context.GetZoneAssetCreationState(); + auto& definitionCache = context.GetZoneAssetCreationState(); auto* cachedTechsetDefinition = definitionCache.GetCachedTechsetDefinition(assetName); if (cachedTechsetDefinition) return cachedTechsetDefinition; - const auto techsetFileName = GetTechsetFileName(assetName); + const auto techsetFileName = GetFileNameForTechsetName(assetName); const auto file = m_search_path.Open(techsetFileName); if (!file.IsOpen()) return nullptr; - const techset::TechsetFileReader reader(*file.m_stream, techsetFileName, techniqueTypeNames, std::extent_v); + const TechsetFileReader reader(*file.m_stream, techsetFileName, techniqueTypeNames, std::extent_v); auto techsetDefinition = reader.ReadTechsetDefinition(); if (!techsetDefinition) { @@ -1339,12 +1341,12 @@ namespace const state_map::StateMapDefinition* LoadStateMapDefinition(const std::string& stateMapName, AssetCreationContext& context) override { - auto& stateMapCache = context.GetZoneAssetCreationState(); + auto& stateMapCache = context.GetZoneAssetCreationState(); auto* cachedStateMap = stateMapCache.GetCachedStateMap(stateMapName); if (cachedStateMap) return cachedStateMap; - const auto stateMapFileName = GetStateMapFileName(stateMapName); + const auto stateMapFileName = GetFileNameForStateMapName(stateMapName); const auto file = m_search_path.Open(stateMapFileName); if (!file.IsOpen()) return nullptr; @@ -1367,25 +1369,10 @@ namespace }; } // namespace -namespace IW4 +namespace techset { - std::string GetTechsetFileName(const std::string& techsetAssetName) - { - return std::format("techsets/{}.techset", techsetAssetName); - } - - std::string GetTechniqueFileName(const std::string& techniqueName) - { - return std::format("techniques/{}.tech", techniqueName); - } - - std::string GetStateMapFileName(const std::string& stateMapName) - { - return std::format("statemaps/{}.sm", stateMapName); - } - - std::unique_ptr CreateTechsetLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace IW4 +} // namespace techset diff --git a/src/ObjCompiling/Game/IW4/Techset/CompilerTechsetIW4.h b/src/ObjCompiling/Game/IW4/Techset/CompilerTechsetIW4.h index 2f246031..09fd1375 100644 --- a/src/ObjCompiling/Game/IW4/Techset/CompilerTechsetIW4.h +++ b/src/ObjCompiling/Game/IW4/Techset/CompilerTechsetIW4.h @@ -10,21 +10,17 @@ #include #include -namespace IW4 +namespace techset { - [[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 + class ICreatorIW4 : public AssetCreator { public: - ITechsetCreator() = default; - virtual ~ITechsetCreator() = default; + ICreatorIW4() = default; + virtual ~ICreatorIW4() = default; - virtual techset::TechsetDefinition* LoadTechsetDefinition(const std::string& assetName, AssetCreationContext& context, bool& failure) = 0; + virtual 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 + std::unique_ptr CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath); +} // namespace techset diff --git a/src/ObjCompiling/Game/IW4/Techset/CompilerVertexDeclIW4.cpp b/src/ObjCompiling/Game/IW4/Techset/CompilerVertexDeclIW4.cpp index 391975ee..9ce59278 100644 --- a/src/ObjCompiling/Game/IW4/Techset/CompilerVertexDeclIW4.cpp +++ b/src/ObjCompiling/Game/IW4/Techset/CompilerVertexDeclIW4.cpp @@ -92,10 +92,10 @@ namespace }; } // namespace -namespace IW4 +namespace vertex_decl { - std::unique_ptr> CreateVertexDeclLoader(MemoryManager& memory) + std::unique_ptr> CreateLoaderIW4(MemoryManager& memory) { return std::make_unique(memory); } -} // namespace IW4 +} // namespace vertex_decl diff --git a/src/ObjCompiling/Game/IW4/Techset/CompilerVertexDeclIW4.h b/src/ObjCompiling/Game/IW4/Techset/CompilerVertexDeclIW4.h index d4bd1b68..4713a652 100644 --- a/src/ObjCompiling/Game/IW4/Techset/CompilerVertexDeclIW4.h +++ b/src/ObjCompiling/Game/IW4/Techset/CompilerVertexDeclIW4.h @@ -7,7 +7,7 @@ #include -namespace IW4 +namespace vertex_decl { - std::unique_ptr> CreateVertexDeclLoader(MemoryManager& memory); -} // namespace IW4 + std::unique_ptr> CreateLoaderIW4(MemoryManager& memory); +} // namespace vertex_decl diff --git a/src/ObjCompiling/Game/IW5/ObjCompilerIW5.cpp b/src/ObjCompiling/Game/IW5/ObjCompilerIW5.cpp index fe02ead8..5f9e9bf9 100644 --- a/src/ObjCompiling/Game/IW5/ObjCompilerIW5.cpp +++ b/src/ObjCompiling/Game/IW5/ObjCompilerIW5.cpp @@ -25,8 +25,8 @@ namespace { auto& memory = zone.Memory(); - if (ImageIwdPostProcessor::AppliesToZoneDefinition(zoneDefinition)) - collection.AddAssetPostProcessor(std::make_unique>(zoneDefinition, searchPath, zoneStates, outDir)); + if (image::IwdPostProcessor::AppliesToZoneDefinition(zoneDefinition)) + collection.AddAssetPostProcessor(std::make_unique>(zoneDefinition, searchPath, zoneStates, outDir)); } } // namespace diff --git a/src/ObjCompiling/Game/T5/ObjCompilerT5.cpp b/src/ObjCompiling/Game/T5/ObjCompilerT5.cpp index 3ca4d416..0442c1e8 100644 --- a/src/ObjCompiling/Game/T5/ObjCompilerT5.cpp +++ b/src/ObjCompiling/Game/T5/ObjCompilerT5.cpp @@ -25,8 +25,8 @@ namespace { auto& memory = zone.Memory(); - if (ImageIwdPostProcessor::AppliesToZoneDefinition(zoneDefinition)) - collection.AddAssetPostProcessor(std::make_unique>(zoneDefinition, searchPath, zoneStates, outDir)); + if (image::IwdPostProcessor::AppliesToZoneDefinition(zoneDefinition)) + collection.AddAssetPostProcessor(std::make_unique>(zoneDefinition, searchPath, zoneStates, outDir)); } } // namespace diff --git a/src/ObjCompiling/Game/T6/Image/ImageCompilerT6.cpp b/src/ObjCompiling/Game/T6/Image/ImageCompilerT6.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ObjCompiling/Game/T6/Image/ImageCompilerT6.h b/src/ObjCompiling/Game/T6/Image/ImageCompilerT6.h deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ObjCompiling/Game/T6/KeyValuePairs/KeyValuePairsCompilerT6.cpp b/src/ObjCompiling/Game/T6/KeyValuePairs/KeyValuePairsCompilerT6.cpp index 22da77ce..35724a68 100644 --- a/src/ObjCompiling/Game/T6/KeyValuePairs/KeyValuePairsCompilerT6.cpp +++ b/src/ObjCompiling/Game/T6/KeyValuePairs/KeyValuePairsCompilerT6.cpp @@ -18,7 +18,7 @@ namespace : m_memory(memory), m_zone(zone), m_zone_definition(zoneDefinition), - m_kvp_creator(zoneStates.GetZoneAssetCreationState()) + m_kvp_creator(zoneStates.GetZoneAssetCreationState()) { } @@ -67,15 +67,15 @@ namespace MemoryManager& m_memory; const Zone& m_zone; const ZoneDefinition& m_zone_definition; - KeyValuePairsCreator& m_kvp_creator; + key_value_pairs::Creator& m_kvp_creator; }; } // namespace -namespace T6 +namespace key_value_pairs { std::unique_ptr - CreateKeyValuePairsCompiler(MemoryManager& memory, const Zone& zone, const ZoneDefinition& zoneDefinition, ZoneAssetCreationStateContainer& zoneStates) + CreateCompilerT6(MemoryManager& memory, const Zone& zone, const ZoneDefinition& zoneDefinition, ZoneAssetCreationStateContainer& zoneStates) { return std::make_unique(memory, zone, zoneDefinition, zoneStates); } -} // namespace T6 +} // namespace key_value_pairs diff --git a/src/ObjCompiling/Game/T6/KeyValuePairs/KeyValuePairsCompilerT6.h b/src/ObjCompiling/Game/T6/KeyValuePairs/KeyValuePairsCompilerT6.h index c68c06b5..f5ce8b37 100644 --- a/src/ObjCompiling/Game/T6/KeyValuePairs/KeyValuePairsCompilerT6.h +++ b/src/ObjCompiling/Game/T6/KeyValuePairs/KeyValuePairsCompilerT6.h @@ -9,8 +9,8 @@ #include -namespace T6 +namespace key_value_pairs { std::unique_ptr - CreateKeyValuePairsCompiler(MemoryManager& memory, const Zone& zone, const ZoneDefinition& zoneDefinition, ZoneAssetCreationStateContainer& zoneStates); -} // namespace T6 + CreateCompilerT6(MemoryManager& memory, const Zone& zone, const ZoneDefinition& zoneDefinition, ZoneAssetCreationStateContainer& zoneStates); +} // namespace key_value_pairs diff --git a/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp b/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp index eae90387..8228234d 100644 --- a/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp +++ b/src/ObjCompiling/Game/T6/ObjCompilerT6.cpp @@ -19,7 +19,7 @@ namespace { auto& memory = zone.Memory(); - collection.AddAssetCreator(CreateKeyValuePairsCompiler(memory, zone, zoneDefinition.m_zone_definition, zoneStates)); + collection.AddAssetCreator(key_value_pairs::CreateCompilerT6(memory, zone, zoneDefinition.m_zone_definition, zoneStates)); } void ConfigurePostProcessors(AssetCreatorCollection& collection, @@ -31,11 +31,11 @@ namespace { auto& memory = zone.Memory(); - if (ImageIPakPostProcessor::AppliesToZoneDefinition(zoneDefinition)) - collection.AddAssetPostProcessor(std::make_unique>(zoneDefinition, searchPath, zoneStates, outDir)); + if (image::IPakPostProcessor::AppliesToZoneDefinition(zoneDefinition)) + collection.AddAssetPostProcessor(std::make_unique>(zoneDefinition, searchPath, zoneStates, outDir)); - if (ImageIwdPostProcessor::AppliesToZoneDefinition(zoneDefinition)) - collection.AddAssetPostProcessor(std::make_unique>(zoneDefinition, searchPath, zoneStates, outDir)); + if (image::IwdPostProcessor::AppliesToZoneDefinition(zoneDefinition)) + collection.AddAssetPostProcessor(std::make_unique>(zoneDefinition, searchPath, zoneStates, outDir)); } } // namespace diff --git a/src/ObjCompiling/Image/IPak/IPakCreator.cpp b/src/ObjCompiling/Image/IPak/IPakCreator.cpp index 64134b2b..1f3fd36a 100644 --- a/src/ObjCompiling/Image/IPak/IPakCreator.cpp +++ b/src/ObjCompiling/Image/IPak/IPakCreator.cpp @@ -371,68 +371,71 @@ namespace }; } // namespace -IPakToCreate::IPakToCreate(std::string name) - : m_name(std::move(name)) +namespace image { -} - -void IPakToCreate::AddImage(std::string imageName) -{ - m_image_names.emplace_back(std::move(imageName)); -} - -void IPakToCreate::Build(ISearchPath& searchPath, IOutputPath& outPath) -{ - const auto file = outPath.Open(std::format("{}.ipak", m_name)); - if (!file) + IPakToCreate::IPakToCreate(std::string name) + : m_name(std::move(name)) { - std::cerr << std::format("Failed to open file for ipak {}\n", m_name); - return; } - IPakWriter writer(*file, searchPath, m_image_names); - writer.Write(); + void IPakToCreate::AddImage(std::string imageName) + { + m_image_names.emplace_back(std::move(imageName)); + } - std::cout << std::format("Created ipak {} with {} entries\n", m_name, m_image_names.size()); -} + void IPakToCreate::Build(ISearchPath& searchPath, IOutputPath& outPath) + { + const auto file = outPath.Open(std::format("{}.ipak", m_name)); + if (!file) + { + std::cerr << std::format("Failed to open file for ipak {}\n", m_name); + return; + } -const std::vector& IPakToCreate::GetImageNames() const -{ - return m_image_names; -} + IPakWriter writer(*file, searchPath, m_image_names); + writer.Write(); -IPakCreator::IPakCreator() - : m_kvp_creator(nullptr) -{ -} + std::cout << std::format("Created ipak {} with {} entries\n", m_name, m_image_names.size()); + } -void IPakCreator::Inject(ZoneAssetCreationInjection& inject) -{ - m_kvp_creator = &inject.m_zone_states.GetZoneAssetCreationState(); -} + const std::vector& IPakToCreate::GetImageNames() const + { + return m_image_names; + } -IPakToCreate* IPakCreator::GetOrAddIPak(const std::string& ipakName) -{ - const auto existingIPak = m_ipak_lookup.find(ipakName); - if (existingIPak != m_ipak_lookup.end()) - return existingIPak->second; + IPakCreator::IPakCreator() + : m_kvp_creator(nullptr) + { + } - auto newIPak = std::make_unique(ipakName); - auto* result = newIPak.get(); - m_ipak_lookup.emplace(ipakName, result); - m_ipaks.emplace_back(std::move(newIPak)); + void IPakCreator::Inject(ZoneAssetCreationInjection& inject) + { + m_kvp_creator = &inject.m_zone_states.GetZoneAssetCreationState(); + } - assert(m_kvp_creator); - m_kvp_creator->AddKeyValuePair(CommonKeyValuePair("ipak_read", ipakName)); + IPakToCreate* IPakCreator::GetOrAddIPak(const std::string& ipakName) + { + const auto existingIPak = m_ipak_lookup.find(ipakName); + if (existingIPak != m_ipak_lookup.end()) + return existingIPak->second; - return result; -} + auto newIPak = std::make_unique(ipakName); + auto* result = newIPak.get(); + m_ipak_lookup.emplace(ipakName, result); + m_ipaks.emplace_back(std::move(newIPak)); -void IPakCreator::Finalize(ISearchPath& searchPath, IOutputPath& outPath) -{ - for (const auto& ipakToCreate : m_ipaks) - ipakToCreate->Build(searchPath, outPath); + assert(m_kvp_creator); + m_kvp_creator->AddKeyValuePair(key_value_pairs::CommonKeyValuePair("ipak_read", ipakName)); - m_ipaks.clear(); - m_ipak_lookup.clear(); -} + return result; + } + + void IPakCreator::Finalize(ISearchPath& searchPath, IOutputPath& outPath) + { + for (const auto& ipakToCreate : m_ipaks) + ipakToCreate->Build(searchPath, outPath); + + m_ipaks.clear(); + m_ipak_lookup.clear(); + } +} // namespace image diff --git a/src/ObjCompiling/Image/IPak/IPakCreator.h b/src/ObjCompiling/Image/IPak/IPakCreator.h index 31eed0b2..b7891fbf 100644 --- a/src/ObjCompiling/Image/IPak/IPakCreator.h +++ b/src/ObjCompiling/Image/IPak/IPakCreator.h @@ -9,32 +9,35 @@ #include #include -class IPakToCreate +namespace image { -public: - explicit IPakToCreate(std::string name); + class IPakToCreate + { + public: + explicit IPakToCreate(std::string name); - void AddImage(std::string imageName); - void Build(ISearchPath& searchPath, IOutputPath& outPath); - [[nodiscard]] const std::vector& GetImageNames() const; + void AddImage(std::string imageName); + void Build(ISearchPath& searchPath, IOutputPath& outPath); + [[nodiscard]] const std::vector& GetImageNames() const; -private: - std::string m_name; - std::vector m_image_names; -}; + private: + std::string m_name; + std::vector m_image_names; + }; -class IPakCreator final : public IZoneAssetCreationState -{ -public: - IPakCreator(); + class IPakCreator final : public IZoneAssetCreationState + { + public: + IPakCreator(); - void Inject(ZoneAssetCreationInjection& inject) override; + void Inject(ZoneAssetCreationInjection& inject) override; - IPakToCreate* GetOrAddIPak(const std::string& ipakName); - void Finalize(ISearchPath& searchPath, IOutputPath& outPath); + IPakToCreate* GetOrAddIPak(const std::string& ipakName); + void Finalize(ISearchPath& searchPath, IOutputPath& outPath); -private: - KeyValuePairsCreator* m_kvp_creator; - std::unordered_map m_ipak_lookup; - std::vector> m_ipaks; -}; + private: + key_value_pairs::Creator* m_kvp_creator; + std::unordered_map m_ipak_lookup; + std::vector> m_ipaks; + }; +} // namespace image diff --git a/src/ObjCompiling/Image/ImageIPakPostProcessor.cpp b/src/ObjCompiling/Image/ImageIPakPostProcessor.cpp index 24c0ace2..2c05d22b 100644 --- a/src/ObjCompiling/Image/ImageIPakPostProcessor.cpp +++ b/src/ObjCompiling/Image/ImageIPakPostProcessor.cpp @@ -4,63 +4,66 @@ #include -AbstractImageIPakPostProcessor::AbstractImageIPakPostProcessor(const ZoneDefinitionContext& zoneDefinition, - ISearchPath& searchPath, - ZoneAssetCreationStateContainer& zoneStates, - IOutputPath& outDir) - : m_zone_definition(zoneDefinition), - m_search_path(searchPath), - m_ipak_creator(zoneStates.GetZoneAssetCreationState()), - m_out_dir(outDir), - m_obj_container_index(0u), - m_current_ipak(nullptr), - m_current_ipak_start_index(0u), - m_current_ipak_end_index(0u) +namespace image { - FindNextObjContainer(); -} - -bool AbstractImageIPakPostProcessor::AppliesToZoneDefinition(const ZoneDefinitionContext& zoneDefinition) -{ - return std::ranges::any_of(zoneDefinition.m_zone_definition.m_obj_containers, - [](const ZoneDefinitionObjContainer& objContainer) - { - return objContainer.m_type == ZoneDefinitionObjContainerType::IPAK; - }); -} - -void AbstractImageIPakPostProcessor::FindNextObjContainer() -{ - const auto objContainerCount = m_zone_definition.m_zone_definition.m_obj_containers.size(); - while (m_obj_container_index < objContainerCount) + AbstractIPakPostProcessor::AbstractIPakPostProcessor(const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + ZoneAssetCreationStateContainer& zoneStates, + IOutputPath& outDir) + : m_zone_definition(zoneDefinition), + m_search_path(searchPath), + m_ipak_creator(zoneStates.GetZoneAssetCreationState()), + m_out_dir(outDir), + m_obj_container_index(0u), + m_current_ipak(nullptr), + m_current_ipak_start_index(0u), + m_current_ipak_end_index(0u) { - 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; + FindNextObjContainer(); } - m_current_ipak = nullptr; -} + bool AbstractIPakPostProcessor::AppliesToZoneDefinition(const ZoneDefinitionContext& zoneDefinition) + { + return std::ranges::any_of(zoneDefinition.m_zone_definition.m_obj_containers, + [](const ZoneDefinitionObjContainer& objContainer) + { + return objContainer.m_type == ZoneDefinitionObjContainerType::IPAK; + }); + } -void AbstractImageIPakPostProcessor::PostProcessAsset(XAssetInfoGeneric& assetInfo, AssetCreationContext& context) -{ - if (assetInfo.m_name.empty() || assetInfo.m_name[0] == ',') - return; + void AbstractIPakPostProcessor::FindNextObjContainer() + { + 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++]; - while (m_current_ipak && m_zone_definition.m_asset_index_in_definition >= m_current_ipak_end_index) - FindNextObjContainer(); + if (objContainer.m_type != ZoneDefinitionObjContainerType::IPAK) + continue; - if (m_current_ipak && m_zone_definition.m_asset_index_in_definition >= m_current_ipak_start_index) - m_current_ipak->AddImage(assetInfo.m_name); -} + 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; + } -void AbstractImageIPakPostProcessor::FinalizeZone(AssetCreationContext& context) -{ - m_ipak_creator.Finalize(m_search_path, m_out_dir); -} + m_current_ipak = nullptr; + } + + void AbstractIPakPostProcessor::PostProcessAsset(XAssetInfoGeneric& assetInfo, AssetCreationContext& context) + { + if (assetInfo.m_name.empty() || assetInfo.m_name[0] == ',') + return; + + while (m_current_ipak && m_zone_definition.m_asset_index_in_definition >= m_current_ipak_end_index) + FindNextObjContainer(); + + 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 AbstractIPakPostProcessor::FinalizeZone(AssetCreationContext& context) + { + m_ipak_creator.Finalize(m_search_path, m_out_dir); + } +} // namespace image diff --git a/src/ObjCompiling/Image/ImageIPakPostProcessor.h b/src/ObjCompiling/Image/ImageIPakPostProcessor.h index 675b79cf..b6a6ec2d 100644 --- a/src/ObjCompiling/Image/ImageIPakPostProcessor.h +++ b/src/ObjCompiling/Image/ImageIPakPostProcessor.h @@ -5,48 +5,51 @@ #include "Image/IPak/IPakCreator.h" #include "SearchPath/IOutputPath.h" -class AbstractImageIPakPostProcessor : public IAssetPostProcessor +namespace image { -public: - AbstractImageIPakPostProcessor(const ZoneDefinitionContext& zoneDefinition, - ISearchPath& searchPath, - ZoneAssetCreationStateContainer& zoneStates, - IOutputPath& outDir); - - static bool AppliesToZoneDefinition(const ZoneDefinitionContext& zoneDefinition); - - void PostProcessAsset(XAssetInfoGeneric& assetInfo, AssetCreationContext& context) override; - void FinalizeZone(AssetCreationContext& context) override; - -private: - void FindNextObjContainer(); - - const ZoneDefinitionContext& m_zone_definition; - ISearchPath& m_search_path; - IPakCreator& m_ipak_creator; - IOutputPath& m_out_dir; - - 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, - IOutputPath& outDir) - : AbstractImageIPakPostProcessor(zoneDefinition, searchPath, zoneStates, outDir) + class AbstractIPakPostProcessor : public IAssetPostProcessor { - } + public: + AbstractIPakPostProcessor(const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + ZoneAssetCreationStateContainer& zoneStates, + IOutputPath& outDir); - [[nodiscard]] asset_type_t GetHandlingAssetType() const override + static bool AppliesToZoneDefinition(const ZoneDefinitionContext& zoneDefinition); + + void PostProcessAsset(XAssetInfoGeneric& assetInfo, AssetCreationContext& context) override; + void FinalizeZone(AssetCreationContext& context) override; + + private: + void FindNextObjContainer(); + + const ZoneDefinitionContext& m_zone_definition; + ISearchPath& m_search_path; + IPakCreator& m_ipak_creator; + IOutputPath& m_out_dir; + + unsigned m_obj_container_index; + IPakToCreate* m_current_ipak; + unsigned m_current_ipak_start_index; + unsigned m_current_ipak_end_index; + }; + + template class IPakPostProcessor final : public AbstractIPakPostProcessor { - return AssetType::EnumEntry; - } -}; + public: + static_assert(std::is_base_of_v); + + IPakPostProcessor(const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + ZoneAssetCreationStateContainer& zoneStates, + IOutputPath& outDir) + : AbstractIPakPostProcessor(zoneDefinition, searchPath, zoneStates, outDir) + { + } + + [[nodiscard]] asset_type_t GetHandlingAssetType() const override + { + return AssetType::EnumEntry; + } + }; +} // namespace image diff --git a/src/ObjCompiling/Image/ImageIwdPostProcessor.cpp b/src/ObjCompiling/Image/ImageIwdPostProcessor.cpp index b329546c..3163ea81 100644 --- a/src/ObjCompiling/Image/ImageIwdPostProcessor.cpp +++ b/src/ObjCompiling/Image/ImageIwdPostProcessor.cpp @@ -1,67 +1,71 @@ #include "ImageIwdPostProcessor.h" +#include "Image/ImageCommon.h" #include "Iwd/IwdCreator.h" #include #include -AbstractImageIwdPostProcessor::AbstractImageIwdPostProcessor(const ZoneDefinitionContext& zoneDefinition, - ISearchPath& searchPath, - ZoneAssetCreationStateContainer& zoneStates, - IOutputPath& outDir) - : m_zone_definition(zoneDefinition), - m_search_path(searchPath), - m_iwd_creator(zoneStates.GetZoneAssetCreationState()), - m_out_dir(outDir), - m_obj_container_index(0u), - m_current_iwd(nullptr), - m_current_iwd_start_index(0u), - m_current_iwd_end_index(0u) +namespace image { - FindNextObjContainer(); -} - -bool AbstractImageIwdPostProcessor::AppliesToZoneDefinition(const ZoneDefinitionContext& zoneDefinition) -{ - return std::ranges::any_of(zoneDefinition.m_zone_definition.m_obj_containers, - [](const ZoneDefinitionObjContainer& objContainer) - { - return objContainer.m_type == ZoneDefinitionObjContainerType::IWD; - }); -} - -void AbstractImageIwdPostProcessor::FindNextObjContainer() -{ - const auto objContainerCount = m_zone_definition.m_zone_definition.m_obj_containers.size(); - while (m_obj_container_index < objContainerCount) + AbstractIwdPostProcessor::AbstractIwdPostProcessor(const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + ZoneAssetCreationStateContainer& zoneStates, + IOutputPath& outDir) + : m_zone_definition(zoneDefinition), + m_search_path(searchPath), + m_iwd_creator(zoneStates.GetZoneAssetCreationState()), + m_out_dir(outDir), + m_obj_container_index(0u), + m_current_iwd(nullptr), + m_current_iwd_start_index(0u), + m_current_iwd_end_index(0u) { - 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; + FindNextObjContainer(); } - m_current_iwd = nullptr; -} + bool AbstractIwdPostProcessor::AppliesToZoneDefinition(const ZoneDefinitionContext& zoneDefinition) + { + return std::ranges::any_of(zoneDefinition.m_zone_definition.m_obj_containers, + [](const ZoneDefinitionObjContainer& objContainer) + { + return objContainer.m_type == ZoneDefinitionObjContainerType::IWD; + }); + } -void AbstractImageIwdPostProcessor::PostProcessAsset(XAssetInfoGeneric& assetInfo, AssetCreationContext& context) -{ - if (assetInfo.m_name.empty() || assetInfo.m_name[0] == ',') - return; + void AbstractIwdPostProcessor::FindNextObjContainer() + { + 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++]; - while (m_current_iwd && m_zone_definition.m_asset_index_in_definition >= m_current_iwd_end_index) - FindNextObjContainer(); + if (objContainer.m_type != ZoneDefinitionObjContainerType::IWD) + continue; - 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)); -} + 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; + } -void AbstractImageIwdPostProcessor::FinalizeZone(AssetCreationContext& context) -{ - m_iwd_creator.Finalize(m_search_path, m_out_dir); -} + m_current_iwd = nullptr; + } + + void AbstractIwdPostProcessor::PostProcessAsset(XAssetInfoGeneric& assetInfo, AssetCreationContext& context) + { + if (assetInfo.m_name.empty() || assetInfo.m_name[0] == ',') + return; + + while (m_current_iwd && m_zone_definition.m_asset_index_in_definition >= m_current_iwd_end_index) + FindNextObjContainer(); + + if (m_current_iwd && m_zone_definition.m_asset_index_in_definition >= m_current_iwd_start_index) + m_current_iwd->AddFile(GetFileNameForAsset(assetInfo.m_name, ".iwi")); + } + + void AbstractIwdPostProcessor::FinalizeZone(AssetCreationContext& context) + { + m_iwd_creator.Finalize(m_search_path, m_out_dir); + } +} // namespace image diff --git a/src/ObjCompiling/Image/ImageIwdPostProcessor.h b/src/ObjCompiling/Image/ImageIwdPostProcessor.h index 8225c29f..a7bf657b 100644 --- a/src/ObjCompiling/Image/ImageIwdPostProcessor.h +++ b/src/ObjCompiling/Image/ImageIwdPostProcessor.h @@ -5,48 +5,48 @@ #include "Iwd/IwdCreator.h" #include "SearchPath/IOutputPath.h" -class AbstractImageIwdPostProcessor : public IAssetPostProcessor +namespace image { -public: - AbstractImageIwdPostProcessor(const ZoneDefinitionContext& zoneDefinition, - ISearchPath& searchPath, - ZoneAssetCreationStateContainer& zoneStates, - IOutputPath& outDir); - - static bool AppliesToZoneDefinition(const ZoneDefinitionContext& zoneDefinition); - - void PostProcessAsset(XAssetInfoGeneric& assetInfo, AssetCreationContext& context) override; - void FinalizeZone(AssetCreationContext& context) override; - -private: - void FindNextObjContainer(); - - const ZoneDefinitionContext& m_zone_definition; - ISearchPath& m_search_path; - IwdCreator& m_iwd_creator; - IOutputPath& m_out_dir; - - 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, - IOutputPath& outDir) - : AbstractImageIwdPostProcessor(zoneDefinition, searchPath, zoneStates, outDir) + class AbstractIwdPostProcessor : public IAssetPostProcessor { - } + public: + AbstractIwdPostProcessor(const ZoneDefinitionContext& zoneDefinition, + ISearchPath& searchPath, + ZoneAssetCreationStateContainer& zoneStates, + IOutputPath& outDir); - [[nodiscard]] asset_type_t GetHandlingAssetType() const override + static bool AppliesToZoneDefinition(const ZoneDefinitionContext& zoneDefinition); + + void PostProcessAsset(XAssetInfoGeneric& assetInfo, AssetCreationContext& context) override; + void FinalizeZone(AssetCreationContext& context) override; + + private: + void FindNextObjContainer(); + + const ZoneDefinitionContext& m_zone_definition; + ISearchPath& m_search_path; + IwdCreator& m_iwd_creator; + IOutputPath& m_out_dir; + + unsigned m_obj_container_index; + IwdToCreate* m_current_iwd; + unsigned m_current_iwd_start_index; + unsigned m_current_iwd_end_index; + }; + + template class IwdPostProcessor final : public AbstractIwdPostProcessor { - return AssetType::EnumEntry; - } -}; + public: + static_assert(std::is_base_of_v); + + IwdPostProcessor(const ZoneDefinitionContext& zoneDefinition, ISearchPath& searchPath, ZoneAssetCreationStateContainer& zoneStates, IOutputPath& outDir) + : AbstractIwdPostProcessor(zoneDefinition, searchPath, zoneStates, outDir) + { + } + + [[nodiscard]] asset_type_t GetHandlingAssetType() const override + { + return AssetType::EnumEntry; + } + }; +} // namespace image diff --git a/src/ObjCompiling/KeyValuePairs/KeyValuePairsCreator.cpp b/src/ObjCompiling/KeyValuePairs/KeyValuePairsCreator.cpp index 348a6177..ec9b2cc8 100644 --- a/src/ObjCompiling/KeyValuePairs/KeyValuePairsCreator.cpp +++ b/src/ObjCompiling/KeyValuePairs/KeyValuePairsCreator.cpp @@ -5,72 +5,75 @@ #include #include -CommonKeyValuePair::CommonKeyValuePair(std::string keyStr, std::string value) - : m_key_str(std::move(keyStr)), - m_value(std::move(value)) +namespace key_value_pairs { -} - -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) + CommonKeyValuePair::CommonKeyValuePair(std::string keyStr, std::string value) + : m_key_str(std::move(keyStr)), + m_value(std::move(value)) { - 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::ranges::sort(m_key_value_pairs, - [](const CommonKeyValuePair& v0, const CommonKeyValuePair& v1) - { - if (v0.m_key_str.has_value()) + CommonKeyValuePair::CommonKeyValuePair(const unsigned keyHash, std::string value) + : m_key_hash(keyHash), + m_value(std::move(value)) + { + } + + void Creator::AddKeyValuePair(CommonKeyValuePair keyValuePair) + { + m_key_value_pairs.emplace_back(std::move(keyValuePair)); + } + + void Creator::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::ranges::sort(m_key_value_pairs, + [](const CommonKeyValuePair& v0, const CommonKeyValuePair& v1) { - if (!v1.m_key_str.has_value()) - return true; + if (v0.m_key_str.has_value()) + { + if (!v1.m_key_str.has_value()) + return true; - return *v0.m_key_str < *v1.m_key_str; - } + return *v0.m_key_str < *v1.m_key_str; + } - if (!v1.m_key_hash.has_value()) - return false; + if (!v1.m_key_hash.has_value()) + return false; - return *v0.m_key_hash < *v1.m_key_hash; - }); -} + return *v0.m_key_hash < *v1.m_key_hash; + }); + } -std::vector KeyValuePairsCreator::GetFinalKeyValuePairs() -{ - return std::move(m_key_value_pairs); -} + std::vector Creator::GetFinalKeyValuePairs() + { + return std::move(m_key_value_pairs); + } +} // namespace key_value_pairs diff --git a/src/ObjCompiling/KeyValuePairs/KeyValuePairsCreator.h b/src/ObjCompiling/KeyValuePairs/KeyValuePairsCreator.h index eb91d33f..dd35d260 100644 --- a/src/ObjCompiling/KeyValuePairs/KeyValuePairsCreator.h +++ b/src/ObjCompiling/KeyValuePairs/KeyValuePairsCreator.h @@ -7,24 +7,27 @@ #include #include -class CommonKeyValuePair +namespace key_value_pairs { -public: - CommonKeyValuePair(std::string keyStr, std::string value); - CommonKeyValuePair(unsigned keyHash, std::string value); + 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; -}; + std::optional m_key_str; + std::optional m_key_hash; + std::string m_value; + }; -class KeyValuePairsCreator final : public IZoneAssetCreationState -{ -public: - void AddKeyValuePair(CommonKeyValuePair keyValuePair); - void Finalize(const ZoneDefinition& zoneDefinition); - std::vector GetFinalKeyValuePairs(); + class Creator final : public IZoneAssetCreationState + { + public: + void AddKeyValuePair(CommonKeyValuePair keyValuePair); + void Finalize(const ZoneDefinition& zoneDefinition); + std::vector GetFinalKeyValuePairs(); -private: - std::vector m_key_value_pairs; -}; + private: + std::vector m_key_value_pairs; + }; +} // namespace key_value_pairs diff --git a/src/ObjLoading/Asset/IZoneAssetCreationState.h b/src/ObjLoading/Asset/IZoneAssetCreationState.h index c63b1861..5692f553 100644 --- a/src/ObjLoading/Asset/IZoneAssetCreationState.h +++ b/src/ObjLoading/Asset/IZoneAssetCreationState.h @@ -52,14 +52,15 @@ public: 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)); + std::type_index typeId = typeid(T); + const auto foundEntry = m_zone_asset_creation_states.find(typeId); 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))); + m_zone_asset_creation_states.emplace(std::move(typeId), std::move(newState)); return *newStatePtr; } diff --git a/src/ObjLoading/Game/IW3/Image/AssetLoaderImageIW3.cpp b/src/ObjLoading/Game/IW3/Image/AssetLoaderImageIW3.cpp index a4d921c8..b7f03a20 100644 --- a/src/ObjLoading/Game/IW3/Image/AssetLoaderImageIW3.cpp +++ b/src/ObjLoading/Game/IW3/Image/AssetLoaderImageIW3.cpp @@ -122,10 +122,10 @@ namespace }; } // namespace -namespace IW3 +namespace image { - std::unique_ptr> CreateImageLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace IW3 +} // namespace image diff --git a/src/ObjLoading/Game/IW3/Image/AssetLoaderImageIW3.h b/src/ObjLoading/Game/IW3/Image/AssetLoaderImageIW3.h index ce4dbb81..b8d60124 100644 --- a/src/ObjLoading/Game/IW3/Image/AssetLoaderImageIW3.h +++ b/src/ObjLoading/Game/IW3/Image/AssetLoaderImageIW3.h @@ -7,7 +7,7 @@ #include -namespace IW3 +namespace image { - std::unique_ptr> CreateImageLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace IW3 + std::unique_ptr> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath); +} // namespace image diff --git a/src/ObjLoading/Game/IW3/Localize/AssetLoaderLocalizeIW3.cpp b/src/ObjLoading/Game/IW3/Localize/AssetLoaderLocalizeIW3.cpp index c7f2572f..0afa5b6c 100644 --- a/src/ObjLoading/Game/IW3/Localize/AssetLoaderLocalizeIW3.cpp +++ b/src/ObjLoading/Game/IW3/Localize/AssetLoaderLocalizeIW3.cpp @@ -36,10 +36,10 @@ namespace }; } // namespace -namespace IW3 +namespace localize { - std::unique_ptr> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + std::unique_ptr> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) { return std::make_unique(memory, searchPath, zone); } -} // namespace IW3 +} // namespace localize diff --git a/src/ObjLoading/Game/IW3/Localize/AssetLoaderLocalizeIW3.h b/src/ObjLoading/Game/IW3/Localize/AssetLoaderLocalizeIW3.h index 5469d4ca..7d1c30ed 100644 --- a/src/ObjLoading/Game/IW3/Localize/AssetLoaderLocalizeIW3.h +++ b/src/ObjLoading/Game/IW3/Localize/AssetLoaderLocalizeIW3.h @@ -8,7 +8,7 @@ #include -namespace IW3 +namespace localize { - std::unique_ptr> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); -} // namespace IW3 + std::unique_ptr> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace localize diff --git a/src/ObjLoading/Game/IW3/Material/LoaderMaterialIW3.cpp b/src/ObjLoading/Game/IW3/Material/LoaderMaterialIW3.cpp index aec04c81..5172498a 100644 --- a/src/ObjLoading/Game/IW3/Material/LoaderMaterialIW3.cpp +++ b/src/ObjLoading/Game/IW3/Material/LoaderMaterialIW3.cpp @@ -45,10 +45,10 @@ namespace }; } // namespace -namespace IW3 +namespace material { - std::unique_ptr> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace IW3 +} // namespace material diff --git a/src/ObjLoading/Game/IW3/Material/LoaderMaterialIW3.h b/src/ObjLoading/Game/IW3/Material/LoaderMaterialIW3.h index 8d2dd024..fd51d2c4 100644 --- a/src/ObjLoading/Game/IW3/Material/LoaderMaterialIW3.h +++ b/src/ObjLoading/Game/IW3/Material/LoaderMaterialIW3.h @@ -6,7 +6,7 @@ #include "SearchPath/ISearchPath.h" #include "Utils/MemoryManager.h" -namespace IW3 +namespace material { - std::unique_ptr> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace IW3 + std::unique_ptr> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath); +} // namespace material diff --git a/src/ObjLoading/Game/IW3/ObjLoaderIW3.cpp b/src/ObjLoading/Game/IW3/ObjLoaderIW3.cpp index 9c2ef22f..fb2c1627 100644 --- a/src/ObjLoading/Game/IW3/ObjLoaderIW3.cpp +++ b/src/ObjLoading/Game/IW3/ObjLoaderIW3.cpp @@ -3,6 +3,7 @@ #include "Asset/GlobalAssetPoolsLoader.h" #include "Game/IW3/GameIW3.h" #include "Game/IW3/IW3.h" +#include "Game/IW3/XModel/LoaderXModelIW3.h" #include "Image/AssetLoaderImageIW3.h" #include "Localize/AssetLoaderLocalizeIW3.h" #include "Material/LoaderMaterialIW3.h" @@ -90,10 +91,10 @@ namespace // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); - // collection.AddAssetCreator(std::make_unique(memory)); - collection.AddAssetCreator(CreateMaterialLoader(memory, searchPath)); + collection.AddAssetCreator(xmodel::CreateLoaderIW3(memory, searchPath, zone)); + collection.AddAssetCreator(material::CreateLoaderIW3(memory, searchPath)); // collection.AddAssetCreator(std::make_unique(memory)); - collection.AddAssetCreator(CreateImageLoader(memory, searchPath)); + collection.AddAssetCreator(image::CreateLoaderIW3(memory, searchPath)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); @@ -107,13 +108,13 @@ namespace // 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(localize::CreateLoaderIW3(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(raw_file::CreateLoaderIW3(memory, searchPath)); + collection.AddAssetCreator(string_table::CreateLoaderIW3(memory, searchPath)); } } // namespace diff --git a/src/ObjLoading/Game/IW3/RawFile/AssetLoaderRawFileIW3.cpp b/src/ObjLoading/Game/IW3/RawFile/AssetLoaderRawFileIW3.cpp index 92a19b21..ffeaef61 100644 --- a/src/ObjLoading/Game/IW3/RawFile/AssetLoaderRawFileIW3.cpp +++ b/src/ObjLoading/Game/IW3/RawFile/AssetLoaderRawFileIW3.cpp @@ -44,10 +44,10 @@ namespace }; } // namespace -namespace IW3 +namespace raw_file { - std::unique_ptr> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace IW3 +} // namespace raw_file diff --git a/src/ObjLoading/Game/IW3/RawFile/AssetLoaderRawFileIW3.h b/src/ObjLoading/Game/IW3/RawFile/AssetLoaderRawFileIW3.h index cddae3ea..914c0529 100644 --- a/src/ObjLoading/Game/IW3/RawFile/AssetLoaderRawFileIW3.h +++ b/src/ObjLoading/Game/IW3/RawFile/AssetLoaderRawFileIW3.h @@ -7,7 +7,7 @@ #include -namespace IW3 +namespace raw_file { - std::unique_ptr> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace IW3 + std::unique_ptr> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath); +} // namespace raw_file diff --git a/src/ObjLoading/Game/IW3/StringTable/AssetLoaderStringTableIW3.cpp b/src/ObjLoading/Game/IW3/StringTable/AssetLoaderStringTableIW3.cpp index bb7303ec..e8146808 100644 --- a/src/ObjLoading/Game/IW3/StringTable/AssetLoaderStringTableIW3.cpp +++ b/src/ObjLoading/Game/IW3/StringTable/AssetLoaderStringTableIW3.cpp @@ -38,10 +38,10 @@ namespace }; } // namespace -namespace IW3 +namespace string_table { - std::unique_ptr> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace IW3 +} // namespace string_table diff --git a/src/ObjLoading/Game/IW3/StringTable/AssetLoaderStringTableIW3.h b/src/ObjLoading/Game/IW3/StringTable/AssetLoaderStringTableIW3.h index 76702596..5b5a1ded 100644 --- a/src/ObjLoading/Game/IW3/StringTable/AssetLoaderStringTableIW3.h +++ b/src/ObjLoading/Game/IW3/StringTable/AssetLoaderStringTableIW3.h @@ -7,7 +7,7 @@ #include -namespace IW3 +namespace string_table { - std::unique_ptr> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace IW3 + std::unique_ptr> CreateLoaderIW3(MemoryManager& memory, ISearchPath& searchPath); +} // namespace string_table diff --git a/src/ObjLoading/Game/IW4/Leaderboard/JsonLeaderboardDefLoader.cpp b/src/ObjLoading/Game/IW4/Leaderboard/JsonLeaderboardDefLoader.cpp deleted file mode 100644 index 35c64c27..00000000 --- a/src/ObjLoading/Game/IW4/Leaderboard/JsonLeaderboardDefLoader.cpp +++ /dev/null @@ -1,114 +0,0 @@ -#include "JsonLeaderboardDefLoader.h" - -#include "Game/IW4/CommonIW4.h" -#include "Game/IW4/Leaderboard/JsonLeaderboardDef.h" - -#include -#include -#include - -using namespace nlohmann; -using namespace IW4; - -namespace -{ - class JsonLoader - { - public: - JsonLoader(std::istream& stream, MemoryManager& memory) - : m_stream(stream), - m_memory(memory) - { - } - - bool Load(LeaderboardDef& leaderboardDef) const - { - try - { - const auto jRoot = json::parse(m_stream); - std::string type; - unsigned version; - - jRoot.at("_type").get_to(type); - jRoot.at("_version").get_to(version); - - if (type != "leaderboard" || version != 1u) - { - std::cerr << std::format("Tried to load leaderboard \"{}\" but did not find expected type leaderboard of version 1\n", leaderboardDef.name); - return false; - } - - const auto jLeaderboard = jRoot.get(); - return CreateLeaderboardFromJson(jLeaderboard, leaderboardDef); - } - catch (const json::exception& e) - { - std::cerr << std::format("Failed to parse json of leaderboard: {}\n", e.what()); - } - - return false; - } - - private: - bool CreateColumnDefFromJson(const JsonColumnDef& jColumn, LbColumnDef& lbColumnDef, LeaderboardDef& leaderboardDef) const - { - lbColumnDef.name = m_memory.Dup(jColumn.name.c_str()); - - lbColumnDef.id = jColumn.colId; - lbColumnDef.propertyId = jColumn.propertyId.value_or(0); - lbColumnDef.hidden = jColumn.hidden.value_or(false); - - if (jColumn.statName) - lbColumnDef.statName = m_memory.Dup(jColumn.statName->c_str()); - else - lbColumnDef.statName = nullptr; - - lbColumnDef.type = jColumn.type; - - lbColumnDef.precision = jColumn.precision.value_or(0); - lbColumnDef.agg = jColumn.aggregationFunction; - - return true; - } - - bool CreateLeaderboardFromJson(const JsonLeaderboardDef& jLeaderboardDef, LeaderboardDef& leaderboardDef) const - { - leaderboardDef.id = jLeaderboardDef.id; - - leaderboardDef.xpColId = jLeaderboardDef.xpColId.value_or(-1); - leaderboardDef.prestigeColId = jLeaderboardDef.prestigeColId.value_or(-1); - - if (!jLeaderboardDef.columns.empty()) - { - leaderboardDef.columnCount = static_cast(jLeaderboardDef.columns.size()); - leaderboardDef.columns = m_memory.Alloc(leaderboardDef.columnCount); - - for (auto i = 0; i < leaderboardDef.columnCount; i++) - { - if (!CreateColumnDefFromJson(jLeaderboardDef.columns[i], leaderboardDef.columns[i], leaderboardDef)) - return false; - } - } - else - { - leaderboardDef.columnCount = 0; - leaderboardDef.columns = nullptr; - } - - return true; - } - - std::istream& m_stream; - MemoryManager& m_memory; - }; -} // namespace - -namespace IW4 -{ - bool LoadLeaderboardAsJson(std::istream& stream, LeaderboardDef& leaderboard, MemoryManager* memory) - { - const JsonLoader loader(stream, *memory); - - return loader.Load(leaderboard); - } -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/Leaderboard/JsonLeaderboardDefLoader.h b/src/ObjLoading/Game/IW4/Leaderboard/JsonLeaderboardDefLoader.h deleted file mode 100644 index 22f85756..00000000 --- a/src/ObjLoading/Game/IW4/Leaderboard/JsonLeaderboardDefLoader.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "Game/IW4/IW4.h" -#include "Utils/MemoryManager.h" - -#include - -namespace IW4 -{ - bool LoadLeaderboardAsJson(std::istream& stream, LeaderboardDef& leaderboard, MemoryManager* memory); -} // namespace IW4 diff --git a/src/ObjLoading/Game/IW4/Leaderboard/LoaderLeaderboardIW4.cpp b/src/ObjLoading/Game/IW4/Leaderboard/LoaderLeaderboardIW4.cpp index 550472dc..b0acadf4 100644 --- a/src/ObjLoading/Game/IW4/Leaderboard/LoaderLeaderboardIW4.cpp +++ b/src/ObjLoading/Game/IW4/Leaderboard/LoaderLeaderboardIW4.cpp @@ -1,16 +1,109 @@ #include "LoaderLeaderboardIW4.h" #include "Game/IW4/IW4.h" -#include "JsonLeaderboardDefLoader.h" +#include "Game/IW4/Leaderboard/JsonLeaderboardDef.h" +#include "Leaderboard/LeaderboardCommon.h" #include #include #include +#include +using namespace nlohmann; using namespace IW4; namespace { + class JsonLoader + { + public: + JsonLoader(std::istream& stream, MemoryManager& memory) + : m_stream(stream), + m_memory(memory) + { + } + + bool Load(LeaderboardDef& leaderboardDef) const + { + try + { + const auto jRoot = json::parse(m_stream); + std::string type; + unsigned version; + + jRoot.at("_type").get_to(type); + jRoot.at("_version").get_to(version); + + if (type != "leaderboard" || version != 1u) + { + std::cerr << std::format("Tried to load leaderboard \"{}\" but did not find expected type leaderboard of version 1\n", leaderboardDef.name); + return false; + } + + const auto jLeaderboard = jRoot.get(); + return CreateLeaderboardFromJson(jLeaderboard, leaderboardDef); + } + catch (const json::exception& e) + { + std::cerr << std::format("Failed to parse json of leaderboard: {}\n", e.what()); + } + + return false; + } + + private: + bool CreateColumnDefFromJson(const JsonColumnDef& jColumn, LbColumnDef& lbColumnDef, LeaderboardDef& leaderboardDef) const + { + lbColumnDef.name = m_memory.Dup(jColumn.name.c_str()); + + lbColumnDef.id = jColumn.colId; + lbColumnDef.propertyId = jColumn.propertyId.value_or(0); + lbColumnDef.hidden = jColumn.hidden.value_or(false); + + if (jColumn.statName) + lbColumnDef.statName = m_memory.Dup(jColumn.statName->c_str()); + else + lbColumnDef.statName = nullptr; + + lbColumnDef.type = jColumn.type; + + lbColumnDef.precision = jColumn.precision.value_or(0); + lbColumnDef.agg = jColumn.aggregationFunction; + + return true; + } + + bool CreateLeaderboardFromJson(const JsonLeaderboardDef& jLeaderboardDef, LeaderboardDef& leaderboardDef) const + { + leaderboardDef.id = jLeaderboardDef.id; + + leaderboardDef.xpColId = jLeaderboardDef.xpColId.value_or(-1); + leaderboardDef.prestigeColId = jLeaderboardDef.prestigeColId.value_or(-1); + + if (!jLeaderboardDef.columns.empty()) + { + leaderboardDef.columnCount = static_cast(jLeaderboardDef.columns.size()); + leaderboardDef.columns = m_memory.Alloc(leaderboardDef.columnCount); + + for (auto i = 0; i < leaderboardDef.columnCount; i++) + { + if (!CreateColumnDefFromJson(jLeaderboardDef.columns[i], leaderboardDef.columns[i], leaderboardDef)) + return false; + } + } + else + { + leaderboardDef.columnCount = 0; + leaderboardDef.columns = nullptr; + } + + return true; + } + + std::istream& m_stream; + MemoryManager& m_memory; + }; + class LeaderboardLoader final : public AssetCreator { public: @@ -22,14 +115,15 @@ namespace AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - const auto file = m_search_path.Open(std::format("leaderboards/{}.json", assetName)); + const auto file = m_search_path.Open(leaderboard::GetJsonFileNameForAsset(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)) + const JsonLoader loader(*file.m_stream, m_memory); + if (!loader.Load(*leaderboardDef)) { std::cerr << std::format("Failed to load leaderboard \"{}\"\n", assetName); return AssetCreationResult::Failure(); @@ -44,10 +138,10 @@ namespace }; } // namespace -namespace IW4 +namespace leaderboard { - std::unique_ptr> CreateLeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace IW4 +} // namespace leaderboard diff --git a/src/ObjLoading/Game/IW4/Leaderboard/LoaderLeaderboardIW4.h b/src/ObjLoading/Game/IW4/Leaderboard/LoaderLeaderboardIW4.h index 3f0a86ce..931a8fca 100644 --- a/src/ObjLoading/Game/IW4/Leaderboard/LoaderLeaderboardIW4.h +++ b/src/ObjLoading/Game/IW4/Leaderboard/LoaderLeaderboardIW4.h @@ -7,7 +7,7 @@ #include -namespace IW4 +namespace leaderboard { - std::unique_ptr> CreateLeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace IW4 + std::unique_ptr> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath); +} // namespace leaderboard diff --git a/src/ObjLoading/Game/IW4/LightDef/LoaderLightDefIW4.cpp b/src/ObjLoading/Game/IW4/LightDef/LightDefLoaderIW4.cpp similarity index 86% rename from src/ObjLoading/Game/IW4/LightDef/LoaderLightDefIW4.cpp rename to src/ObjLoading/Game/IW4/LightDef/LightDefLoaderIW4.cpp index 0563554e..1485c361 100644 --- a/src/ObjLoading/Game/IW4/LightDef/LoaderLightDefIW4.cpp +++ b/src/ObjLoading/Game/IW4/LightDef/LightDefLoaderIW4.cpp @@ -1,6 +1,7 @@ -#include "LoaderLightDefIW4.h" +#include "LightDefLoaderIW4.h" #include "Game/IW4/IW4.h" +#include "LightDef/LightDefCommon.h" #include #include @@ -23,7 +24,7 @@ namespace AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - const auto filename = GetAssetFilename(assetName); + const auto filename = light_def::GetFileNameForAsset(assetName); const auto file = m_search_path.Open(filename); if (!file.IsOpen()) return AssetCreationResult::NoAction(); @@ -61,20 +62,15 @@ namespace } private: - std::string GetAssetFilename(const std::string& assetName) - { - return std::format("lights/{}", assetName); - } - MemoryManager& m_memory; ISearchPath& m_search_path; }; } // namespace -namespace IW4 +namespace light_def { - std::unique_ptr> CreateLightDefLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace IW4 +} // namespace light_def diff --git a/src/ObjLoading/Game/IW4/LightDef/LoaderLightDefIW4.h b/src/ObjLoading/Game/IW4/LightDef/LightDefLoaderIW4.h similarity index 50% rename from src/ObjLoading/Game/IW4/LightDef/LoaderLightDefIW4.h rename to src/ObjLoading/Game/IW4/LightDef/LightDefLoaderIW4.h index 92eec1bb..7ac2880c 100644 --- a/src/ObjLoading/Game/IW4/LightDef/LoaderLightDefIW4.h +++ b/src/ObjLoading/Game/IW4/LightDef/LightDefLoaderIW4.h @@ -7,7 +7,7 @@ #include -namespace IW4 +namespace light_def { - std::unique_ptr> CreateLightDefLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace IW4 + std::unique_ptr> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath); +} // namespace light_def diff --git a/src/ObjLoading/Game/IW4/Localize/LoaderLocalizeIW4.cpp b/src/ObjLoading/Game/IW4/Localize/LoaderLocalizeIW4.cpp index 795939ed..64ce403f 100644 --- a/src/ObjLoading/Game/IW4/Localize/LoaderLocalizeIW4.cpp +++ b/src/ObjLoading/Game/IW4/Localize/LoaderLocalizeIW4.cpp @@ -35,10 +35,10 @@ namespace }; } // namespace -namespace IW4 +namespace localize { - std::unique_ptr> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + std::unique_ptr> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) { return std::make_unique(memory, searchPath, zone); } -} // namespace IW4 +} // namespace localize diff --git a/src/ObjLoading/Game/IW4/Localize/LoaderLocalizeIW4.h b/src/ObjLoading/Game/IW4/Localize/LoaderLocalizeIW4.h index c7ae0d9d..e6abda46 100644 --- a/src/ObjLoading/Game/IW4/Localize/LoaderLocalizeIW4.h +++ b/src/ObjLoading/Game/IW4/Localize/LoaderLocalizeIW4.h @@ -8,7 +8,7 @@ #include -namespace IW4 +namespace localize { - std::unique_ptr> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); -} // namespace IW4 + std::unique_ptr> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace localize diff --git a/src/ObjLoading/Game/IW4/Material/LoaderMaterialIW4.cpp b/src/ObjLoading/Game/IW4/Material/LoaderMaterialIW4.cpp index be3bf8b0..b6367630 100644 --- a/src/ObjLoading/Game/IW4/Material/LoaderMaterialIW4.cpp +++ b/src/ObjLoading/Game/IW4/Material/LoaderMaterialIW4.cpp @@ -45,10 +45,10 @@ namespace }; } // namespace -namespace IW4 +namespace material { - std::unique_ptr> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace IW4 +} // namespace material diff --git a/src/ObjLoading/Game/IW4/Material/LoaderMaterialIW4.h b/src/ObjLoading/Game/IW4/Material/LoaderMaterialIW4.h index efd0a610..6016cc17 100644 --- a/src/ObjLoading/Game/IW4/Material/LoaderMaterialIW4.h +++ b/src/ObjLoading/Game/IW4/Material/LoaderMaterialIW4.h @@ -6,7 +6,7 @@ #include "SearchPath/ISearchPath.h" #include "Utils/MemoryManager.h" -namespace IW4 +namespace material { - std::unique_ptr> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace IW4 + std::unique_ptr> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath); +} // namespace material diff --git a/src/ObjLoading/Game/IW4/Menu/LoaderMenuListIW4.cpp b/src/ObjLoading/Game/IW4/Menu/LoaderMenuListIW4.cpp index 52e00c74..91fb70a0 100644 --- a/src/ObjLoading/Game/IW4/Menu/LoaderMenuListIW4.cpp +++ b/src/ObjLoading/Game/IW4/Menu/LoaderMenuListIW4.cpp @@ -212,10 +212,10 @@ namespace }; } // namespace -namespace IW4 +namespace menu { - std::unique_ptr> CreateMenuListLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateMenuListLoaderIW4(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace IW4 +} // namespace menu diff --git a/src/ObjLoading/Game/IW4/Menu/LoaderMenuListIW4.h b/src/ObjLoading/Game/IW4/Menu/LoaderMenuListIW4.h index 6a1d0499..a22d7b2c 100644 --- a/src/ObjLoading/Game/IW4/Menu/LoaderMenuListIW4.h +++ b/src/ObjLoading/Game/IW4/Menu/LoaderMenuListIW4.h @@ -7,7 +7,7 @@ #include -namespace IW4 +namespace menu { - std::unique_ptr> CreateMenuListLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace IW4 + std::unique_ptr> CreateMenuListLoaderIW4(MemoryManager& memory, ISearchPath& searchPath); +} // namespace menu diff --git a/src/ObjLoading/Game/IW4/ObjLoaderIW4.cpp b/src/ObjLoading/Game/IW4/ObjLoaderIW4.cpp index f90d1afd..ad5b83c4 100644 --- a/src/ObjLoading/Game/IW4/ObjLoaderIW4.cpp +++ b/src/ObjLoading/Game/IW4/ObjLoaderIW4.cpp @@ -5,7 +5,7 @@ #include "Game/IW4/IW4.h" #include "Game/IW4/XModel/LoaderXModelIW4.h" #include "Leaderboard/LoaderLeaderboardIW4.h" -#include "LightDef/LoaderLightDefIW4.h" +#include "LightDef/LightDefLoaderIW4.h" #include "Localize/LoaderLocalizeIW4.h" #include "Material/LoaderMaterialIW4.h" #include "Menu/LoaderMenuListIW4.h" @@ -119,19 +119,19 @@ namespace { auto& memory = zone.Memory(); - collection.AddAssetCreator(std::make_unique(memory, searchPath, zone)); - collection.AddAssetCreator(std::make_unique(memory, gdt, zone)); + collection.AddAssetCreator(phys_preset::CreateRawLoaderIW4(memory, searchPath, zone)); + collection.AddAssetCreator(phys_preset::CreateGdtLoaderIW4(memory, gdt, zone)); // 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(CreatePixelShaderLoader(memory, searchPath)); - collection.AddAssetCreator(CreateVertexShaderLoader(memory, searchPath)); + collection.AddAssetCreator(xmodel::CreateLoaderIW4(memory, searchPath, zone)); + collection.AddAssetCreator(material::CreateLoaderIW4(memory, searchPath)); + collection.AddAssetCreator(shader::CreatePixelShaderLoaderIW4(memory, searchPath)); + collection.AddAssetCreator(shader::CreateVertexShaderLoaderIW4(memory, searchPath)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); - collection.AddAssetCreator(CreateSoundCurveLoader(memory, searchPath)); + collection.AddAssetCreator(sound_curve::CreateLoaderIW4(memory, searchPath)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); @@ -140,19 +140,19 @@ namespace // 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(light_def::CreateLoaderIW4(memory, searchPath)); // collection.AddAssetCreator(std::make_unique(memory)); - collection.AddAssetCreator(CreateMenuListLoader(memory, searchPath)); + collection.AddAssetCreator(menu::CreateMenuListLoaderIW4(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(localize::CreateLoaderIW4(memory, searchPath, zone)); + collection.AddAssetCreator(weapon::CreateRawLoaderIW4(memory, searchPath, zone)); + collection.AddAssetCreator(weapon::CreateGdtLoaderIW4(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(raw_file::CreateLoaderIW4(memory, searchPath)); + collection.AddAssetCreator(string_table::CreateLoaderIW4(memory, searchPath)); + collection.AddAssetCreator(leaderboard::CreateLoaderIW4(memory, searchPath)); + collection.AddAssetCreator(structured_data_def::CreateLoaderIW4(memory, searchPath)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); diff --git a/src/ObjLoading/Game/IW4/PhysPreset/GdtLoaderPhysPresetIW4.cpp b/src/ObjLoading/Game/IW4/PhysPreset/GdtLoaderPhysPresetIW4.cpp index afd65d70..26634fd7 100644 --- a/src/ObjLoading/Game/IW4/PhysPreset/GdtLoaderPhysPresetIW4.cpp +++ b/src/ObjLoading/Game/IW4/PhysPreset/GdtLoaderPhysPresetIW4.cpp @@ -10,26 +10,43 @@ using namespace IW4; -GdtLoaderPhysPreset::GdtLoaderPhysPreset(MemoryManager& memory, IGdtQueryable& gdt, Zone& zone) - : m_memory(memory), - m_gdt(gdt), - m_zone(zone) +namespace { -} - -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)) + class GdtLoaderPhysPreset final : public AssetCreator { - std::cerr << std::format("Failed to read phys preset gdt entry: \"{}\"\n", assetName); - return AssetCreationResult::Failure(); - } + public: + GdtLoaderPhysPreset(MemoryManager& memory, IGdtQueryable& gdt, Zone& zone) + : m_gdt(gdt), + m_info_string_loader(memory, zone) + { + } - InfoStringLoaderPhysPreset infoStringLoader(m_memory, m_zone); - return infoStringLoader.CreateAsset(assetName, infoString, context); -} + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const 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(); + } + + return m_info_string_loader.CreateAsset(assetName, infoString, context); + } + + private: + IGdtQueryable& m_gdt; + phys_preset::InfoStringLoaderIW4 m_info_string_loader; + }; +} // namespace + +namespace phys_preset +{ + std::unique_ptr> CreateGdtLoaderIW4(MemoryManager& memory, IGdtQueryable& gdt, Zone& zone) + { + return std::make_unique(memory, gdt, zone); + } +} // namespace phys_preset diff --git a/src/ObjLoading/Game/IW4/PhysPreset/GdtLoaderPhysPresetIW4.h b/src/ObjLoading/Game/IW4/PhysPreset/GdtLoaderPhysPresetIW4.h index 59b65bc1..c5e474f6 100644 --- a/src/ObjLoading/Game/IW4/PhysPreset/GdtLoaderPhysPresetIW4.h +++ b/src/ObjLoading/Game/IW4/PhysPreset/GdtLoaderPhysPresetIW4.h @@ -3,20 +3,12 @@ #include "Asset/IAssetCreator.h" #include "Game/IW4/IW4.h" #include "Gdt/IGdtQueryable.h" +#include "SearchPath/ISearchPath.h" #include "Utils/MemoryManager.h" -namespace IW4 +#include + +namespace phys_preset { - 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 + std::unique_ptr> CreateGdtLoaderIW4(MemoryManager& memory, IGdtQueryable& gdt, Zone& zone); +} // namespace phys_preset diff --git a/src/ObjLoading/Game/IW4/PhysPreset/InfoStringLoaderPhysPresetIW4.cpp b/src/ObjLoading/Game/IW4/PhysPreset/InfoStringLoaderPhysPresetIW4.cpp index 25c8cc89..e8b69203 100644 --- a/src/ObjLoading/Game/IW4/PhysPreset/InfoStringLoaderPhysPresetIW4.cpp +++ b/src/ObjLoading/Game/IW4/PhysPreset/InfoStringLoaderPhysPresetIW4.cpp @@ -58,30 +58,33 @@ namespace } } // namespace -InfoStringLoaderPhysPreset::InfoStringLoaderPhysPreset(MemoryManager& memory, Zone& zone) - : m_memory(memory), - m_zone(zone) +namespace phys_preset { -} - -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()) + InfoStringLoaderIW4::InfoStringLoaderIW4(MemoryManager& memory, Zone& zone) + : m_memory(memory), + m_zone(zone) { - 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()); + AssetCreationResult InfoStringLoaderIW4::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) + { + PhysPresetInfo presetInfo; + std::memset(&presetInfo, 0, sizeof(presetInfo)); - return AssetCreationResult::Success(context.AddAsset(std::move(registration))); -} + 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))); + } +} // namespace phys_preset diff --git a/src/ObjLoading/Game/IW4/PhysPreset/InfoStringLoaderPhysPresetIW4.h b/src/ObjLoading/Game/IW4/PhysPreset/InfoStringLoaderPhysPresetIW4.h index 0ca1cede..1618bd80 100644 --- a/src/ObjLoading/Game/IW4/PhysPreset/InfoStringLoaderPhysPresetIW4.h +++ b/src/ObjLoading/Game/IW4/PhysPreset/InfoStringLoaderPhysPresetIW4.h @@ -4,12 +4,12 @@ #include "Asset/AssetCreationResult.h" #include "InfoString/InfoString.h" -namespace IW4 +namespace phys_preset { - class InfoStringLoaderPhysPreset + class InfoStringLoaderIW4 { public: - InfoStringLoaderPhysPreset(MemoryManager& memory, Zone& zone); + InfoStringLoaderIW4(MemoryManager& memory, Zone& zone); AssetCreationResult CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context); @@ -17,4 +17,4 @@ namespace IW4 MemoryManager& m_memory; Zone& m_zone; }; -} // namespace IW4 +} // namespace phys_preset diff --git a/src/ObjLoading/Game/IW4/PhysPreset/RawLoaderPhysPresetIW4.cpp b/src/ObjLoading/Game/IW4/PhysPreset/RawLoaderPhysPresetIW4.cpp index ada031ac..5d05a588 100644 --- a/src/ObjLoading/Game/IW4/PhysPreset/RawLoaderPhysPresetIW4.cpp +++ b/src/ObjLoading/Game/IW4/PhysPreset/RawLoaderPhysPresetIW4.cpp @@ -4,33 +4,51 @@ #include "Game/IW4/ObjConstantsIW4.h" #include "InfoString/InfoString.h" #include "InfoStringLoaderPhysPresetIW4.h" +#include "PhysPreset/PhysPresetCommon.h" #include #include using namespace IW4; -RawLoaderPhysPreset::RawLoaderPhysPreset(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) - : m_memory(memory), - m_search_path(searchPath), - m_zone(zone) +namespace { -} - -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)) + class RawLoaderPhysPreset final : public AssetCreator { - std::cerr << std::format("Could not parse as info string file: \"{}\"\n", fileName); - return AssetCreationResult::Failure(); - } + public: + RawLoaderPhysPreset(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_search_path(searchPath), + m_info_string_loader(memory, zone) + { + } - InfoStringLoaderPhysPreset infoStringLoader(m_memory, m_zone); - return infoStringLoader.CreateAsset(assetName, infoString, context); -} + AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override + { + const auto fileName = phys_preset::GetFileNameForAssetName(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; + phys_preset::InfoStringLoaderIW4 m_info_string_loader; + }; +} // namespace + +namespace phys_preset +{ + std::unique_ptr> CreateRawLoaderIW4(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + { + return std::make_unique(memory, searchPath, zone); + } +} // namespace phys_preset diff --git a/src/ObjLoading/Game/IW4/PhysPreset/RawLoaderPhysPresetIW4.h b/src/ObjLoading/Game/IW4/PhysPreset/RawLoaderPhysPresetIW4.h index 1c3dd841..ab78361b 100644 --- a/src/ObjLoading/Game/IW4/PhysPreset/RawLoaderPhysPresetIW4.h +++ b/src/ObjLoading/Game/IW4/PhysPreset/RawLoaderPhysPresetIW4.h @@ -5,18 +5,9 @@ #include "SearchPath/ISearchPath.h" #include "Utils/MemoryManager.h" -namespace IW4 +#include + +namespace phys_preset { - 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 + std::unique_ptr> CreateRawLoaderIW4(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace phys_preset diff --git a/src/ObjLoading/Game/IW4/RawFile/LoaderRawFileIW4.cpp b/src/ObjLoading/Game/IW4/RawFile/LoaderRawFileIW4.cpp index 5d708aa9..2b25158a 100644 --- a/src/ObjLoading/Game/IW4/RawFile/LoaderRawFileIW4.cpp +++ b/src/ObjLoading/Game/IW4/RawFile/LoaderRawFileIW4.cpp @@ -82,10 +82,10 @@ namespace }; } // namespace -namespace IW4 +namespace raw_file { - std::unique_ptr> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace IW4 +} // namespace raw_file diff --git a/src/ObjLoading/Game/IW4/RawFile/LoaderRawFileIW4.h b/src/ObjLoading/Game/IW4/RawFile/LoaderRawFileIW4.h index e8163342..624b5b69 100644 --- a/src/ObjLoading/Game/IW4/RawFile/LoaderRawFileIW4.h +++ b/src/ObjLoading/Game/IW4/RawFile/LoaderRawFileIW4.h @@ -7,7 +7,7 @@ #include -namespace IW4 +namespace raw_file { - std::unique_ptr> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace IW4 + std::unique_ptr> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath); +} // namespace raw_file diff --git a/src/ObjLoading/Game/IW4/Shader/LoaderPixelShaderIW4.cpp b/src/ObjLoading/Game/IW4/Shader/LoaderPixelShaderIW4.cpp index 670e6879..1d6ad597 100644 --- a/src/ObjLoading/Game/IW4/Shader/LoaderPixelShaderIW4.cpp +++ b/src/ObjLoading/Game/IW4/Shader/LoaderPixelShaderIW4.cpp @@ -1,6 +1,7 @@ #include "LoaderPixelShaderIW4.h" #include "Game/IW4/IW4.h" +#include "Shader/ShaderCommon.h" #include #include @@ -21,7 +22,7 @@ namespace AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - const auto fileName = GetPixelShaderFileName(assetName); + const auto fileName = shader::GetFileNameForPixelShaderAssetName(assetName); const auto file = m_search_path.Open(fileName); if (!file.IsOpen()) return AssetCreationResult::NoAction(); @@ -53,15 +54,10 @@ namespace }; } // namespace -namespace IW4 +namespace shader { - std::string GetPixelShaderFileName(const std::string& pixelShaderAssetName) - { - return std::format("shader_bin/ps_{}.cso", pixelShaderAssetName); - } - - std::unique_ptr> CreatePixelShaderLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreatePixelShaderLoaderIW4(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace IW4 +} // namespace shader diff --git a/src/ObjLoading/Game/IW4/Shader/LoaderPixelShaderIW4.h b/src/ObjLoading/Game/IW4/Shader/LoaderPixelShaderIW4.h index d29d29ba..0bc212a5 100644 --- a/src/ObjLoading/Game/IW4/Shader/LoaderPixelShaderIW4.h +++ b/src/ObjLoading/Game/IW4/Shader/LoaderPixelShaderIW4.h @@ -7,9 +7,7 @@ #include -namespace IW4 +namespace shader { - [[nodiscard]] std::string GetPixelShaderFileName(const std::string& pixelShaderAssetName); - - std::unique_ptr> CreatePixelShaderLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace IW4 + std::unique_ptr> CreatePixelShaderLoaderIW4(MemoryManager& memory, ISearchPath& searchPath); +} // namespace shader diff --git a/src/ObjLoading/Game/IW4/Shader/LoaderVertexShaderIW4.cpp b/src/ObjLoading/Game/IW4/Shader/LoaderVertexShaderIW4.cpp index 6c1dd5bb..99bea4dd 100644 --- a/src/ObjLoading/Game/IW4/Shader/LoaderVertexShaderIW4.cpp +++ b/src/ObjLoading/Game/IW4/Shader/LoaderVertexShaderIW4.cpp @@ -1,6 +1,7 @@ #include "LoaderVertexShaderIW4.h" #include "Game/IW4/IW4.h" +#include "Shader/ShaderCommon.h" #include #include @@ -21,7 +22,7 @@ namespace AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - const auto fileName = GetVertexShaderFileName(assetName); + const auto fileName = shader::GetFileNameForVertexShaderAssetName(assetName); const auto file = m_search_path.Open(fileName); if (!file.IsOpen()) return AssetCreationResult::NoAction(); @@ -53,15 +54,10 @@ namespace }; } // namespace -namespace IW4 +namespace shader { - std::string GetVertexShaderFileName(const std::string& vertexShaderAssetName) - { - return std::format("shader_bin/vs_{}.cso", vertexShaderAssetName); - } - - std::unique_ptr> CreateVertexShaderLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateVertexShaderLoaderIW4(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace IW4 +} // namespace shader diff --git a/src/ObjLoading/Game/IW4/Shader/LoaderVertexShaderIW4.h b/src/ObjLoading/Game/IW4/Shader/LoaderVertexShaderIW4.h index e8139af0..28076aaf 100644 --- a/src/ObjLoading/Game/IW4/Shader/LoaderVertexShaderIW4.h +++ b/src/ObjLoading/Game/IW4/Shader/LoaderVertexShaderIW4.h @@ -7,9 +7,7 @@ #include -namespace IW4 +namespace shader { - [[nodiscard]] std::string GetVertexShaderFileName(const std::string& vertexShaderAssetName); - - std::unique_ptr> CreateVertexShaderLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace IW4 + std::unique_ptr> CreateVertexShaderLoaderIW4(MemoryManager& memory, ISearchPath& searchPath); +} // namespace shader diff --git a/src/ObjLoading/Game/IW4/Sound/LoaderSoundCurveIW4.cpp b/src/ObjLoading/Game/IW4/Sound/LoaderSoundCurveIW4.cpp index 5f760754..765b4bfb 100644 --- a/src/ObjLoading/Game/IW4/Sound/LoaderSoundCurveIW4.cpp +++ b/src/ObjLoading/Game/IW4/Sound/LoaderSoundCurveIW4.cpp @@ -4,6 +4,7 @@ #include "ObjLoading.h" #include "Parsing/Graph2D/Graph2DReader.h" #include "Pool/GlobalAssetPool.h" +#include "Sound/SoundCurveCommon.h" #include #include @@ -25,7 +26,7 @@ namespace AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - const auto fileName = std::format("soundaliases/{}.vfcurve", assetName); + const auto fileName = sound_curve::GetFileNameForAssetName(assetName); const auto file = m_search_path.Open(fileName); if (!file.IsOpen()) return AssetCreationResult::NoAction(); @@ -69,10 +70,10 @@ namespace }; } // namespace -namespace IW4 +namespace sound_curve { - std::unique_ptr> CreateSoundCurveLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace IW4 +} // namespace sound_curve diff --git a/src/ObjLoading/Game/IW4/Sound/LoaderSoundCurveIW4.h b/src/ObjLoading/Game/IW4/Sound/LoaderSoundCurveIW4.h index 19f1bb3c..b8b12cd3 100644 --- a/src/ObjLoading/Game/IW4/Sound/LoaderSoundCurveIW4.h +++ b/src/ObjLoading/Game/IW4/Sound/LoaderSoundCurveIW4.h @@ -7,7 +7,7 @@ #include -namespace IW4 +namespace sound_curve { - std::unique_ptr> CreateSoundCurveLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace IW4 + std::unique_ptr> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath); +} // namespace sound_curve diff --git a/src/ObjLoading/Game/IW4/StringTable/LoaderStringTableIW4.cpp b/src/ObjLoading/Game/IW4/StringTable/LoaderStringTableIW4.cpp index d4530772..11483031 100644 --- a/src/ObjLoading/Game/IW4/StringTable/LoaderStringTableIW4.cpp +++ b/src/ObjLoading/Game/IW4/StringTable/LoaderStringTableIW4.cpp @@ -38,10 +38,10 @@ namespace }; } // namespace -namespace IW4 +namespace string_table { - std::unique_ptr> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace IW4 +} // namespace string_table diff --git a/src/ObjLoading/Game/IW4/StringTable/LoaderStringTableIW4.h b/src/ObjLoading/Game/IW4/StringTable/LoaderStringTableIW4.h index c9cbd55f..89c53c50 100644 --- a/src/ObjLoading/Game/IW4/StringTable/LoaderStringTableIW4.h +++ b/src/ObjLoading/Game/IW4/StringTable/LoaderStringTableIW4.h @@ -7,7 +7,7 @@ #include -namespace IW4 +namespace string_table { - std::unique_ptr> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace IW4 + std::unique_ptr> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath); +} // namespace string_table diff --git a/src/ObjLoading/Game/IW4/StructuredDataDef/LoaderStructuredDataDefIW4.cpp b/src/ObjLoading/Game/IW4/StructuredDataDef/LoaderStructuredDataDefIW4.cpp index 6f662ab2..673d715d 100644 --- a/src/ObjLoading/Game/IW4/StructuredDataDef/LoaderStructuredDataDefIW4.cpp +++ b/src/ObjLoading/Game/IW4/StructuredDataDef/LoaderStructuredDataDefIW4.cpp @@ -207,10 +207,10 @@ namespace }; } // namespace -namespace IW4 +namespace structured_data_def { - std::unique_ptr> CreateStructuredDataDefLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace IW4 +} // namespace structured_data_def diff --git a/src/ObjLoading/Game/IW4/StructuredDataDef/LoaderStructuredDataDefIW4.h b/src/ObjLoading/Game/IW4/StructuredDataDef/LoaderStructuredDataDefIW4.h index 22d40f09..527a9389 100644 --- a/src/ObjLoading/Game/IW4/StructuredDataDef/LoaderStructuredDataDefIW4.h +++ b/src/ObjLoading/Game/IW4/StructuredDataDef/LoaderStructuredDataDefIW4.h @@ -7,7 +7,7 @@ #include -namespace IW4 +namespace structured_data_def { - std::unique_ptr> CreateStructuredDataDefLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace IW4 + std::unique_ptr> CreateLoaderIW4(MemoryManager& memory, ISearchPath& searchPath); +} // namespace structured_data_def diff --git a/src/ObjLoading/Game/IW4/Weapon/GdtLoaderWeaponIW4.cpp b/src/ObjLoading/Game/IW4/Weapon/GdtLoaderWeaponIW4.cpp index 9b585add..ef632e47 100644 --- a/src/ObjLoading/Game/IW4/Weapon/GdtLoaderWeaponIW4.cpp +++ b/src/ObjLoading/Game/IW4/Weapon/GdtLoaderWeaponIW4.cpp @@ -40,14 +40,14 @@ namespace private: IGdtQueryable& m_gdt; - InfoStringLoaderWeapon m_info_string_loader; + weapon::InfoStringLoaderIW4 m_info_string_loader; }; } // namespace -namespace IW4 +namespace weapon { - std::unique_ptr> CreateGdtWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + std::unique_ptr> CreateGdtLoaderIW4(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) { return std::make_unique(memory, searchPath, gdt, zone); } -} // namespace IW4 +} // namespace weapon diff --git a/src/ObjLoading/Game/IW4/Weapon/GdtLoaderWeaponIW4.h b/src/ObjLoading/Game/IW4/Weapon/GdtLoaderWeaponIW4.h index 44a699b8..6fcac0a4 100644 --- a/src/ObjLoading/Game/IW4/Weapon/GdtLoaderWeaponIW4.h +++ b/src/ObjLoading/Game/IW4/Weapon/GdtLoaderWeaponIW4.h @@ -8,7 +8,7 @@ #include -namespace IW4 +namespace weapon { - std::unique_ptr> CreateGdtWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); -} // namespace IW4 + std::unique_ptr> CreateGdtLoaderIW4(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); +} // namespace weapon diff --git a/src/ObjLoading/Game/IW4/Weapon/InfoStringLoaderWeaponIW4.cpp b/src/ObjLoading/Game/IW4/Weapon/InfoStringLoaderWeaponIW4.cpp index e44ef3c2..be8ac8d6 100644 --- a/src/ObjLoading/Game/IW4/Weapon/InfoStringLoaderWeaponIW4.cpp +++ b/src/ObjLoading/Game/IW4/Weapon/InfoStringLoaderWeaponIW4.cpp @@ -426,33 +426,36 @@ namespace } } // namespace -InfoStringLoaderWeapon::InfoStringLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) - : m_memory(memory), - m_search_path(searchPath), - m_zone(zone) +namespace weapon { -} - -AssetCreationResult InfoStringLoaderWeapon::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) -{ - auto* weaponFullDef = m_memory.Alloc(); - - InitWeaponFullDef(*weaponFullDef); - weaponFullDef->weapCompleteDef.szInternalName = m_memory.Dup(assetName.c_str()); - - 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()) + InfoStringLoaderIW4::InfoStringLoaderIW4(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_memory(memory), + m_search_path(searchPath), + m_zone(zone) { - std::cerr << std::format("Failed to parse weapon: \"{}\"\n", assetName); - return AssetCreationResult::Failure(); } - CalculateWeaponFields(*weaponFullDef, m_memory); + AssetCreationResult InfoStringLoaderIW4::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) + { + auto* weaponFullDef = m_memory.Alloc(); - LoadAccuracyGraphs(*weaponFullDef, m_memory, m_search_path, context); + InitWeaponFullDef(*weaponFullDef); + weaponFullDef->weapCompleteDef.szInternalName = m_memory.Dup(assetName.c_str()); - return AssetCreationResult::Success(context.AddAsset(std::move(registration))); -} + 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 << std::format("Failed to parse weapon: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + CalculateWeaponFields(*weaponFullDef, m_memory); + + LoadAccuracyGraphs(*weaponFullDef, m_memory, m_search_path, context); + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); + } +} // namespace weapon diff --git a/src/ObjLoading/Game/IW4/Weapon/InfoStringLoaderWeaponIW4.h b/src/ObjLoading/Game/IW4/Weapon/InfoStringLoaderWeaponIW4.h index 59204d85..1f82539b 100644 --- a/src/ObjLoading/Game/IW4/Weapon/InfoStringLoaderWeaponIW4.h +++ b/src/ObjLoading/Game/IW4/Weapon/InfoStringLoaderWeaponIW4.h @@ -4,12 +4,12 @@ #include "Asset/AssetCreationResult.h" #include "InfoString/InfoString.h" -namespace IW4 +namespace weapon { - class InfoStringLoaderWeapon + class InfoStringLoaderIW4 { public: - InfoStringLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); + InfoStringLoaderIW4(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); AssetCreationResult CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context); @@ -18,4 +18,4 @@ namespace IW4 ISearchPath& m_search_path; Zone& m_zone; }; -} // namespace IW4 +} // namespace weapon diff --git a/src/ObjLoading/Game/IW4/Weapon/RawLoaderWeaponIW4.cpp b/src/ObjLoading/Game/IW4/Weapon/RawLoaderWeaponIW4.cpp index a1b7b656..ae6de026 100644 --- a/src/ObjLoading/Game/IW4/Weapon/RawLoaderWeaponIW4.cpp +++ b/src/ObjLoading/Game/IW4/Weapon/RawLoaderWeaponIW4.cpp @@ -4,6 +4,7 @@ #include "Game/IW4/ObjConstantsIW4.h" #include "InfoString/InfoString.h" #include "InfoStringLoaderWeaponIW4.h" +#include "Weapon/WeaponCommon.h" #include #include @@ -24,7 +25,7 @@ namespace AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - const auto fileName = std::format("weapons/{}", assetName); + const auto fileName = weapon::GetFileNameForAssetName(assetName); const auto file = m_search_path.Open(fileName); if (!file.IsOpen()) return AssetCreationResult::NoAction(); @@ -41,14 +42,14 @@ namespace private: ISearchPath& m_search_path; - InfoStringLoaderWeapon m_info_string_loader; + weapon::InfoStringLoaderIW4 m_info_string_loader; }; } // namespace -namespace IW4 +namespace weapon { - std::unique_ptr> CreateRawWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + std::unique_ptr> CreateRawLoaderIW4(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) { return std::make_unique(memory, searchPath, zone); } -} // namespace IW4 +} // namespace weapon diff --git a/src/ObjLoading/Game/IW4/Weapon/RawLoaderWeaponIW4.h b/src/ObjLoading/Game/IW4/Weapon/RawLoaderWeaponIW4.h index 786d7ce3..208fc440 100644 --- a/src/ObjLoading/Game/IW4/Weapon/RawLoaderWeaponIW4.h +++ b/src/ObjLoading/Game/IW4/Weapon/RawLoaderWeaponIW4.h @@ -7,7 +7,7 @@ #include -namespace IW4 +namespace weapon { - std::unique_ptr> CreateRawWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); -} // namespace IW4 + std::unique_ptr> CreateRawLoaderIW4(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace weapon diff --git a/src/ObjLoading/Game/IW5/Image/LoaderImageIW5.cpp b/src/ObjLoading/Game/IW5/Image/LoaderImageIW5.cpp index f30d27e4..0f812f80 100644 --- a/src/ObjLoading/Game/IW5/Image/LoaderImageIW5.cpp +++ b/src/ObjLoading/Game/IW5/Image/LoaderImageIW5.cpp @@ -1,6 +1,7 @@ #include "LoaderImageIW5.h" #include "Game/IW5/IW5.h" +#include "Image/ImageCommon.h" #include "Image/IwiLoader.h" #include @@ -25,7 +26,7 @@ namespace AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - const auto fileName = std::format("images/{}.iwi", assetName); + const auto fileName = image::GetFileNameForAsset(assetName, ".iwi"); const auto file = m_search_path.Open(fileName); if (!file.IsOpen()) return AssetCreationResult::NoAction(); @@ -60,10 +61,10 @@ namespace }; } // namespace -namespace IW5 +namespace image { - std::unique_ptr> CreateImageLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace IW5 +} // namespace image diff --git a/src/ObjLoading/Game/IW5/Image/LoaderImageIW5.h b/src/ObjLoading/Game/IW5/Image/LoaderImageIW5.h index 66609137..b95a8f23 100644 --- a/src/ObjLoading/Game/IW5/Image/LoaderImageIW5.h +++ b/src/ObjLoading/Game/IW5/Image/LoaderImageIW5.h @@ -7,7 +7,7 @@ #include -namespace IW5 +namespace image { - std::unique_ptr> CreateImageLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace IW5 + std::unique_ptr> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath); +} // namespace image diff --git a/src/ObjLoading/Game/IW5/Leaderboard/JsonLeaderboardDefLoader.cpp b/src/ObjLoading/Game/IW5/Leaderboard/JsonLeaderboardDefLoader.cpp deleted file mode 100644 index df4d9625..00000000 --- a/src/ObjLoading/Game/IW5/Leaderboard/JsonLeaderboardDefLoader.cpp +++ /dev/null @@ -1,131 +0,0 @@ -#include "JsonLeaderboardDefLoader.h" - -#include "Game/IW5/CommonIW5.h" -#include "Game/IW5/Leaderboard/JsonLeaderboardDef.h" - -#include -#include -#include - -using namespace nlohmann; -using namespace IW5; - -namespace -{ - class JsonLoader - { - public: - JsonLoader(std::istream& stream, MemoryManager& memory) - : m_stream(stream), - m_memory(memory) - { - } - - bool Load(LeaderboardDef& leaderboardDef) const - { - try - { - const auto jRoot = json::parse(m_stream); - std::string type; - unsigned version; - - jRoot.at("_type").get_to(type); - jRoot.at("_version").get_to(version); - - if (type != "leaderboard" || version != 1u) - { - std::cerr << std::format("Tried to load leaderboard \"{}\" but did not find expected type leaderboard of version 1\n", leaderboardDef.name); - return false; - } - - const auto jLeaderboard = jRoot.get(); - return CreateLeaderboardFromJson(jLeaderboard, leaderboardDef); - } - catch (const json::exception& e) - { - std::cerr << std::format("Failed to parse json of leaderboard: {}\n", e.what()); - } - - return false; - } - - private: - static bool CreateTrackTypeFlagsFromJson(const JsonLeaderboardDef& jLeaderboardDef, int& trackTypeFlags) - { - for (const auto trackType : jLeaderboardDef.trackTypes) - trackTypeFlags |= 1 << trackType; - - return true; - } - - bool CreateColumnDefFromJson(const JsonColumnDef& jColumn, LbColumnDef& lbColumnDef, LeaderboardDef& leaderboardDef) const - { - lbColumnDef.name = m_memory.Dup(jColumn.name.c_str()); - - lbColumnDef.id = jColumn.colId; - lbColumnDef.propertyId = jColumn.propertyId.value_or(0); - lbColumnDef.hidden = jColumn.hidden.value_or(false); - - if (jColumn.statName) - lbColumnDef.statName = m_memory.Dup(jColumn.statName->c_str()); - else - lbColumnDef.statName = nullptr; - - lbColumnDef.type = jColumn.type; - - lbColumnDef.precision = jColumn.precision.value_or(0); - - lbColumnDef.agg = jColumn.aggregationFunction; - - lbColumnDef.uiCalColX = jColumn.uiCalColX.value_or(0); - lbColumnDef.uiCalColY = jColumn.uiCalColY.value_or(0); - - return true; - } - - bool CreateLeaderboardFromJson(const JsonLeaderboardDef& jLeaderboardDef, LeaderboardDef& leaderboardDef) const - { - leaderboardDef.id = jLeaderboardDef.id; - - leaderboardDef.xpColId = jLeaderboardDef.xpColId.value_or(-1); - leaderboardDef.prestigeColId = jLeaderboardDef.prestigeColId.value_or(-1); - - if (!jLeaderboardDef.columns.empty()) - { - leaderboardDef.columnCount = static_cast(jLeaderboardDef.columns.size()); - leaderboardDef.columns = m_memory.Alloc(leaderboardDef.columnCount); - - for (auto i = 0; i < leaderboardDef.columnCount; i++) - { - if (!CreateColumnDefFromJson(jLeaderboardDef.columns[i], leaderboardDef.columns[i], leaderboardDef)) - return false; - } - } - else - { - leaderboardDef.columnCount = 0; - leaderboardDef.columns = nullptr; - } - - leaderboardDef.updateType = jLeaderboardDef.updateType; - - if (!CreateTrackTypeFlagsFromJson(jLeaderboardDef, leaderboardDef.trackTypes)) - return false; - - return true; - } - - std::istream& m_stream; - MemoryManager& m_memory; - }; -} // namespace - -namespace IW5 -{ - bool LoadLeaderboardAsJson(std::istream& stream, LeaderboardDef& leaderboard, MemoryManager& memory) - { - const JsonLoader loader(stream, memory); - - return loader.Load(leaderboard); - } -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Leaderboard/JsonLeaderboardDefLoader.h b/src/ObjLoading/Game/IW5/Leaderboard/JsonLeaderboardDefLoader.h deleted file mode 100644 index 753a5db3..00000000 --- a/src/ObjLoading/Game/IW5/Leaderboard/JsonLeaderboardDefLoader.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "Game/IW5/IW5.h" -#include "Utils/MemoryManager.h" - -#include - -namespace IW5 -{ - 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 index c18ed86b..aa25767a 100644 --- a/src/ObjLoading/Game/IW5/Leaderboard/LoaderLeaderboardIW5.cpp +++ b/src/ObjLoading/Game/IW5/Leaderboard/LoaderLeaderboardIW5.cpp @@ -1,16 +1,126 @@ #include "LoaderLeaderboardIW5.h" #include "Game/IW5/IW5.h" -#include "JsonLeaderboardDefLoader.h" +#include "Game/IW5/Leaderboard/JsonLeaderboardDef.h" +#include "Leaderboard/LeaderboardCommon.h" #include #include #include +#include +using namespace nlohmann; using namespace IW5; namespace { + class JsonLoader + { + public: + JsonLoader(std::istream& stream, MemoryManager& memory) + : m_stream(stream), + m_memory(memory) + { + } + + bool Load(LeaderboardDef& leaderboardDef) const + { + try + { + const auto jRoot = json::parse(m_stream); + std::string type; + unsigned version; + + jRoot.at("_type").get_to(type); + jRoot.at("_version").get_to(version); + + if (type != "leaderboard" || version != 1u) + { + std::cerr << std::format("Tried to load leaderboard \"{}\" but did not find expected type leaderboard of version 1\n", leaderboardDef.name); + return false; + } + + const auto jLeaderboard = jRoot.get(); + return CreateLeaderboardFromJson(jLeaderboard, leaderboardDef); + } + catch (const json::exception& e) + { + std::cerr << std::format("Failed to parse json of leaderboard: {}\n", e.what()); + } + + return false; + } + + private: + static bool CreateTrackTypeFlagsFromJson(const JsonLeaderboardDef& jLeaderboardDef, int& trackTypeFlags) + { + for (const auto trackType : jLeaderboardDef.trackTypes) + trackTypeFlags |= 1 << trackType; + + return true; + } + + bool CreateColumnDefFromJson(const JsonColumnDef& jColumn, LbColumnDef& lbColumnDef, LeaderboardDef& leaderboardDef) const + { + lbColumnDef.name = m_memory.Dup(jColumn.name.c_str()); + + lbColumnDef.id = jColumn.colId; + lbColumnDef.propertyId = jColumn.propertyId.value_or(0); + lbColumnDef.hidden = jColumn.hidden.value_or(false); + + if (jColumn.statName) + lbColumnDef.statName = m_memory.Dup(jColumn.statName->c_str()); + else + lbColumnDef.statName = nullptr; + + lbColumnDef.type = jColumn.type; + + lbColumnDef.precision = jColumn.precision.value_or(0); + + lbColumnDef.agg = jColumn.aggregationFunction; + + lbColumnDef.uiCalColX = jColumn.uiCalColX.value_or(0); + lbColumnDef.uiCalColY = jColumn.uiCalColY.value_or(0); + + return true; + } + + bool CreateLeaderboardFromJson(const JsonLeaderboardDef& jLeaderboardDef, LeaderboardDef& leaderboardDef) const + { + leaderboardDef.id = jLeaderboardDef.id; + + leaderboardDef.xpColId = jLeaderboardDef.xpColId.value_or(-1); + leaderboardDef.prestigeColId = jLeaderboardDef.prestigeColId.value_or(-1); + + if (!jLeaderboardDef.columns.empty()) + { + leaderboardDef.columnCount = static_cast(jLeaderboardDef.columns.size()); + leaderboardDef.columns = m_memory.Alloc(leaderboardDef.columnCount); + + for (auto i = 0; i < leaderboardDef.columnCount; i++) + { + if (!CreateColumnDefFromJson(jLeaderboardDef.columns[i], leaderboardDef.columns[i], leaderboardDef)) + return false; + } + } + else + { + leaderboardDef.columnCount = 0; + leaderboardDef.columns = nullptr; + } + + leaderboardDef.updateType = jLeaderboardDef.updateType; + + if (!CreateTrackTypeFlagsFromJson(jLeaderboardDef, leaderboardDef.trackTypes)) + return false; + + return true; + } + + std::istream& m_stream; + MemoryManager& m_memory; + }; + class LeaderboardLoader final : public AssetCreator { public: @@ -22,14 +132,15 @@ namespace AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - const auto file = m_search_path.Open(std::format("leaderboards/{}.json", assetName)); + const auto file = m_search_path.Open(leaderboard::GetJsonFileNameForAsset(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)) + const JsonLoader loader(*file.m_stream, m_memory); + if (!loader.Load(*leaderboardDef)) { std::cerr << std::format("Failed to load leaderboard \"{}\"\n", assetName); return AssetCreationResult::Failure(); @@ -44,10 +155,10 @@ namespace }; } // namespace -namespace IW5 +namespace leaderboard { - std::unique_ptr> CreateLeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace IW5 +} // namespace leaderboard diff --git a/src/ObjLoading/Game/IW5/Leaderboard/LoaderLeaderboardIW5.h b/src/ObjLoading/Game/IW5/Leaderboard/LoaderLeaderboardIW5.h index 6c144840..d2841638 100644 --- a/src/ObjLoading/Game/IW5/Leaderboard/LoaderLeaderboardIW5.h +++ b/src/ObjLoading/Game/IW5/Leaderboard/LoaderLeaderboardIW5.h @@ -7,7 +7,7 @@ #include -namespace IW5 +namespace leaderboard { - std::unique_ptr> CreateLeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace IW5 + std::unique_ptr> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath); +} // namespace leaderboard diff --git a/src/ObjLoading/Game/IW5/Localize/LoaderLocalizeIW5.cpp b/src/ObjLoading/Game/IW5/Localize/LoaderLocalizeIW5.cpp index a531c42f..a7512a26 100644 --- a/src/ObjLoading/Game/IW5/Localize/LoaderLocalizeIW5.cpp +++ b/src/ObjLoading/Game/IW5/Localize/LoaderLocalizeIW5.cpp @@ -35,10 +35,10 @@ namespace }; } // namespace -namespace IW5 +namespace localize { - std::unique_ptr> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + std::unique_ptr> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) { return std::make_unique(memory, searchPath, zone); } -} // namespace IW5 +} // namespace localize diff --git a/src/ObjLoading/Game/IW5/Localize/LoaderLocalizeIW5.h b/src/ObjLoading/Game/IW5/Localize/LoaderLocalizeIW5.h index 6c47a8d1..f161e6c6 100644 --- a/src/ObjLoading/Game/IW5/Localize/LoaderLocalizeIW5.h +++ b/src/ObjLoading/Game/IW5/Localize/LoaderLocalizeIW5.h @@ -8,7 +8,7 @@ #include -namespace IW5 +namespace localize { - std::unique_ptr> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); -} // namespace IW5 + std::unique_ptr> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace localize diff --git a/src/ObjLoading/Game/IW5/Material/LoaderMaterialIW5.cpp b/src/ObjLoading/Game/IW5/Material/LoaderMaterialIW5.cpp index 189e368f..3a72f0bb 100644 --- a/src/ObjLoading/Game/IW5/Material/LoaderMaterialIW5.cpp +++ b/src/ObjLoading/Game/IW5/Material/LoaderMaterialIW5.cpp @@ -45,10 +45,10 @@ namespace }; } // namespace -namespace IW5 +namespace material { - std::unique_ptr> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace IW5 +} // namespace material diff --git a/src/ObjLoading/Game/IW5/Material/LoaderMaterialIW5.h b/src/ObjLoading/Game/IW5/Material/LoaderMaterialIW5.h index 5488c1a7..ebfaf88d 100644 --- a/src/ObjLoading/Game/IW5/Material/LoaderMaterialIW5.h +++ b/src/ObjLoading/Game/IW5/Material/LoaderMaterialIW5.h @@ -7,7 +7,7 @@ #include -namespace IW5 +namespace material { - std::unique_ptr> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace IW5 + std::unique_ptr> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath); +} // namespace material diff --git a/src/ObjLoading/Game/IW5/Menu/LoaderMenuListIW5.cpp b/src/ObjLoading/Game/IW5/Menu/LoaderMenuListIW5.cpp index 46e6938c..ca7414df 100644 --- a/src/ObjLoading/Game/IW5/Menu/LoaderMenuListIW5.cpp +++ b/src/ObjLoading/Game/IW5/Menu/LoaderMenuListIW5.cpp @@ -212,10 +212,10 @@ namespace }; } // namespace -namespace IW5 +namespace menu { - std::unique_ptr> CreateMenuListLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateMenuListLoaderIW5(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace IW5 +} // namespace menu diff --git a/src/ObjLoading/Game/IW5/Menu/LoaderMenuListIW5.h b/src/ObjLoading/Game/IW5/Menu/LoaderMenuListIW5.h index 823161b8..4a8f1c4b 100644 --- a/src/ObjLoading/Game/IW5/Menu/LoaderMenuListIW5.h +++ b/src/ObjLoading/Game/IW5/Menu/LoaderMenuListIW5.h @@ -7,7 +7,7 @@ #include -namespace IW5 +namespace menu { - std::unique_ptr> CreateMenuListLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace IW5 + std::unique_ptr> CreateMenuListLoaderIW5(MemoryManager& memory, ISearchPath& searchPath); +} // namespace menu diff --git a/src/ObjLoading/Game/IW5/Menu/MenuConverterIW5.h b/src/ObjLoading/Game/IW5/Menu/MenuConverterIW5.h index 2f112270..c0b03845 100644 --- a/src/ObjLoading/Game/IW5/Menu/MenuConverterIW5.h +++ b/src/ObjLoading/Game/IW5/Menu/MenuConverterIW5.h @@ -14,7 +14,7 @@ namespace IW5 IMenuConverter() = default; virtual ~IMenuConverter() = default; - virtual void ConvertMenu(const menu::CommonMenuDef& commonMenu, menuDef_t& menu, AssetRegistration& registration) = 0; + 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); }; diff --git a/src/ObjLoading/Game/IW5/ObjLoaderIW5.cpp b/src/ObjLoading/Game/IW5/ObjLoaderIW5.cpp index 4755450f..cb3d96cd 100644 --- a/src/ObjLoading/Game/IW5/ObjLoaderIW5.cpp +++ b/src/ObjLoading/Game/IW5/ObjLoaderIW5.cpp @@ -125,13 +125,13 @@ namespace // 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(xmodel::CreateLoaderIW5(memory, searchPath, zone)); + collection.AddAssetCreator(material::CreateLoaderIW5(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(image::CreateLoaderIW5(memory, searchPath)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); @@ -145,19 +145,19 @@ namespace // 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(menu::CreateMenuListLoaderIW5(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(localize::CreateLoaderIW5(memory, searchPath, zone)); + collection.AddAssetCreator(attachment::CreateLoaderIW5(memory, searchPath)); + collection.AddAssetCreator(weapon::CreateRawLoaderIW5(memory, searchPath, zone)); + collection.AddAssetCreator(weapon::CreateGdtLoaderIW5(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(raw_file::CreateLoaderIW5(memory, searchPath)); + collection.AddAssetCreator(script::CreateLoaderIW5(memory, searchPath)); + collection.AddAssetCreator(string_table::CreateLoaderIW5(memory, searchPath)); + collection.AddAssetCreator(leaderboard::CreateLoaderIW5(memory, searchPath)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); diff --git a/src/ObjLoading/Game/IW5/RawFile/LoaderRawFileIW5.cpp b/src/ObjLoading/Game/IW5/RawFile/LoaderRawFileIW5.cpp index 139e9ad3..fe67715a 100644 --- a/src/ObjLoading/Game/IW5/RawFile/LoaderRawFileIW5.cpp +++ b/src/ObjLoading/Game/IW5/RawFile/LoaderRawFileIW5.cpp @@ -81,10 +81,10 @@ namespace }; } // namespace -namespace IW5 +namespace raw_file { - std::unique_ptr> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace IW5 +} // namespace raw_file diff --git a/src/ObjLoading/Game/IW5/RawFile/LoaderRawFileIW5.h b/src/ObjLoading/Game/IW5/RawFile/LoaderRawFileIW5.h index 3099146e..a8b2ad97 100644 --- a/src/ObjLoading/Game/IW5/RawFile/LoaderRawFileIW5.h +++ b/src/ObjLoading/Game/IW5/RawFile/LoaderRawFileIW5.h @@ -7,7 +7,7 @@ #include -namespace IW5 +namespace raw_file { - std::unique_ptr> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace IW5 + std::unique_ptr> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath); +} // namespace raw_file diff --git a/src/ObjLoading/Game/IW5/Script/LoaderScriptFileIW5.cpp b/src/ObjLoading/Game/IW5/Script/LoaderScriptFileIW5.cpp index 5ae68da9..5e64f0a3 100644 --- a/src/ObjLoading/Game/IW5/Script/LoaderScriptFileIW5.cpp +++ b/src/ObjLoading/Game/IW5/Script/LoaderScriptFileIW5.cpp @@ -79,10 +79,10 @@ namespace }; } // namespace -namespace IW5 +namespace script { - std::unique_ptr> CreateScriptLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace IW5 +} // namespace script diff --git a/src/ObjLoading/Game/IW5/Script/LoaderScriptFileIW5.h b/src/ObjLoading/Game/IW5/Script/LoaderScriptFileIW5.h index 457a0957..5d960798 100644 --- a/src/ObjLoading/Game/IW5/Script/LoaderScriptFileIW5.h +++ b/src/ObjLoading/Game/IW5/Script/LoaderScriptFileIW5.h @@ -7,7 +7,7 @@ #include -namespace IW5 +namespace script { - std::unique_ptr> CreateScriptLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace IW5 + std::unique_ptr> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath); +} // namespace script diff --git a/src/ObjLoading/Game/IW5/StringTable/LoaderStringTableIW5.cpp b/src/ObjLoading/Game/IW5/StringTable/LoaderStringTableIW5.cpp index 2ca18723..ba499cd1 100644 --- a/src/ObjLoading/Game/IW5/StringTable/LoaderStringTableIW5.cpp +++ b/src/ObjLoading/Game/IW5/StringTable/LoaderStringTableIW5.cpp @@ -40,10 +40,10 @@ namespace }; } // namespace -namespace IW5 +namespace string_table { - std::unique_ptr> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace IW5 +} // namespace string_table diff --git a/src/ObjLoading/Game/IW5/StringTable/LoaderStringTableIW5.h b/src/ObjLoading/Game/IW5/StringTable/LoaderStringTableIW5.h index e07bf9c7..52d88396 100644 --- a/src/ObjLoading/Game/IW5/StringTable/LoaderStringTableIW5.h +++ b/src/ObjLoading/Game/IW5/StringTable/LoaderStringTableIW5.h @@ -7,7 +7,7 @@ #include -namespace IW5 +namespace string_table { - std::unique_ptr> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace IW5 + std::unique_ptr> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath); +} // namespace string_table diff --git a/src/ObjLoading/Game/IW5/Weapon/GdtLoaderWeaponIW5.cpp b/src/ObjLoading/Game/IW5/Weapon/GdtLoaderWeaponIW5.cpp index 03897a0d..19f5d7c7 100644 --- a/src/ObjLoading/Game/IW5/Weapon/GdtLoaderWeaponIW5.cpp +++ b/src/ObjLoading/Game/IW5/Weapon/GdtLoaderWeaponIW5.cpp @@ -40,14 +40,14 @@ namespace private: IGdtQueryable& m_gdt; - InfoStringLoaderWeapon m_info_string_loader; + weapon::InfoStringLoaderIW5 m_info_string_loader; }; } // namespace -namespace IW5 +namespace weapon { - std::unique_ptr> CreateGdtWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + std::unique_ptr> CreateGdtLoaderIW5(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) { return std::make_unique(memory, searchPath, gdt, zone); } -} // namespace IW5 +} // namespace weapon diff --git a/src/ObjLoading/Game/IW5/Weapon/GdtLoaderWeaponIW5.h b/src/ObjLoading/Game/IW5/Weapon/GdtLoaderWeaponIW5.h index 0e86b336..f4b729c1 100644 --- a/src/ObjLoading/Game/IW5/Weapon/GdtLoaderWeaponIW5.h +++ b/src/ObjLoading/Game/IW5/Weapon/GdtLoaderWeaponIW5.h @@ -8,7 +8,7 @@ #include -namespace IW5 +namespace weapon { - std::unique_ptr> CreateGdtWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); -} // namespace IW5 + std::unique_ptr> CreateGdtLoaderIW5(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); +} // namespace weapon diff --git a/src/ObjLoading/Game/IW5/Weapon/InfoStringLoaderWeaponIW5.cpp b/src/ObjLoading/Game/IW5/Weapon/InfoStringLoaderWeaponIW5.cpp index 93f82995..aaaa6c27 100644 --- a/src/ObjLoading/Game/IW5/Weapon/InfoStringLoaderWeaponIW5.cpp +++ b/src/ObjLoading/Game/IW5/Weapon/InfoStringLoaderWeaponIW5.cpp @@ -856,33 +856,36 @@ namespace } } // namespace -InfoStringLoaderWeapon::InfoStringLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) - : m_memory(memory), - m_search_path(searchPath), - m_zone(zone) +namespace weapon { -} - -AssetCreationResult InfoStringLoaderWeapon::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) const -{ - auto* weaponFullDef = m_memory.Alloc(); - - InitWeaponFullDef(*weaponFullDef); - weaponFullDef->weapCompleteDef.szInternalName = m_memory.Dup(assetName.c_str()); - - 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()) + InfoStringLoaderIW5::InfoStringLoaderIW5(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_memory(memory), + m_search_path(searchPath), + m_zone(zone) { - std::cerr << std::format("Failed to parse weapon: \"{}\"\n", assetName); - return AssetCreationResult::Failure(); } - CalculateWeaponFields(*weaponFullDef, m_memory); + AssetCreationResult InfoStringLoaderIW5::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) const + { + auto* weaponFullDef = m_memory.Alloc(); - LoadAccuracyGraphs(*weaponFullDef, m_memory, m_search_path, context); + InitWeaponFullDef(*weaponFullDef); + weaponFullDef->weapCompleteDef.szInternalName = m_memory.Dup(assetName.c_str()); - return AssetCreationResult::Success(context.AddAsset(std::move(registration))); -} + 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 << std::format("Failed to parse weapon: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + CalculateWeaponFields(*weaponFullDef, m_memory); + + LoadAccuracyGraphs(*weaponFullDef, m_memory, m_search_path, context); + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); + } +} // namespace weapon diff --git a/src/ObjLoading/Game/IW5/Weapon/InfoStringLoaderWeaponIW5.h b/src/ObjLoading/Game/IW5/Weapon/InfoStringLoaderWeaponIW5.h index 40f14367..d8935b8c 100644 --- a/src/ObjLoading/Game/IW5/Weapon/InfoStringLoaderWeaponIW5.h +++ b/src/ObjLoading/Game/IW5/Weapon/InfoStringLoaderWeaponIW5.h @@ -4,12 +4,12 @@ #include "Asset/AssetCreationResult.h" #include "InfoString/InfoString.h" -namespace IW5 +namespace weapon { - class InfoStringLoaderWeapon + class InfoStringLoaderIW5 { public: - InfoStringLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); + InfoStringLoaderIW5(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); AssetCreationResult CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) const; @@ -18,4 +18,4 @@ namespace IW5 ISearchPath& m_search_path; Zone& m_zone; }; -} // namespace IW5 +} // namespace weapon diff --git a/src/ObjLoading/Game/IW5/Weapon/JsonWeaponAttachmentLoader.cpp b/src/ObjLoading/Game/IW5/Weapon/JsonWeaponAttachmentLoader.cpp deleted file mode 100644 index 44d1bf68..00000000 --- a/src/ObjLoading/Game/IW5/Weapon/JsonWeaponAttachmentLoader.cpp +++ /dev/null @@ -1,645 +0,0 @@ -#include "JsonWeaponAttachmentLoader.h" - -#include "Game/IW5/CommonIW5.h" -#include "Game/IW5/Weapon/JsonWeaponAttachment.h" - -#include -#include -#include - -using namespace nlohmann; -using namespace IW5; - -namespace -{ - class JsonLoader - { - public: - JsonLoader(std::istream& stream, MemoryManager& memory, AssetCreationContext& context, AssetRegistration& registration) - : m_stream(stream), - m_memory(memory), - m_context(context), - m_registration(registration) - - { - } - - bool Load(WeaponAttachment& attachment) const - { - try - { - const auto jRoot = json::parse(m_stream); - std::string type; - unsigned version; - - jRoot.at("_type").get_to(type); - jRoot.at("_version").get_to(version); - - if (type != "attachment" || version != 1u) - { - std::cerr << "Tried to load attachment \"" << attachment.szInternalName << "\" but did not find expected type attachment of version 1\n"; - return false; - } - - const auto jAttachment = jRoot.get(); - return CreateWeaponAttachmentFromJson(jAttachment, attachment); - } - catch (const json::exception& e) - { - std::cerr << std::format("Failed to parse json of attachment: {}\n", e.what()); - } - - return false; - } - - private: - static void PrintError(const WeaponAttachment& attachment, const std::string& message) - { - std::cerr << "Cannot load attachment \"" << attachment.szInternalName << "\": " << message << "\n"; - } - - bool CreateWeaponAttachmentFromJson(const JsonWeaponAttachment& jAttachment, WeaponAttachment& attachment) const - { -#define CONVERT_XMODEL_ARRAY(propertyName, count) \ - CreateXModelArrayFromJson(jAttachment.propertyName, attachment.propertyName, #propertyName, count, attachment); - -#define CONVERT_ATTRIBUTE(attributeClass, attributeName) \ - if (jAttachment.attributeName) \ - { \ - using AttributeType = std::remove_pointer_t; \ - attachment.attributeName = m_memory.Alloc(); \ - if (!Create##attributeClass##FromJson(jAttachment.attributeName.value(), *attachment.attributeName, attachment)) \ - return false; \ - } \ - else \ - attachment.attributeName = nullptr; - - attachment.szDisplayName = m_memory.Dup(jAttachment.displayName.c_str()); - attachment.type = jAttachment.type; - attachment.weaponType = jAttachment.weaponType; - attachment.weapClass = jAttachment.weapClass; - - CONVERT_XMODEL_ARRAY(worldModels, ATTACHMENT_WORLD_MODEL_COUNT) - CONVERT_XMODEL_ARRAY(viewModels, ATTACHMENT_VIEW_MODEL_COUNT) - CONVERT_XMODEL_ARRAY(reticleViewModels, ATTACHMENT_RETICLE_VIEW_MODEL_COUNT) - - CONVERT_ATTRIBUTE(AttAmmoGeneral, ammoGeneral) - CONVERT_ATTRIBUTE(AttSight, sight) - CONVERT_ATTRIBUTE(AttReload, reload) - CONVERT_ATTRIBUTE(AttAddOns, addOns) - CONVERT_ATTRIBUTE(AttGeneral, general) - CONVERT_ATTRIBUTE(AttAimAssist, aimAssist) - CONVERT_ATTRIBUTE(AttAmmunition, ammunition) - CONVERT_ATTRIBUTE(AttDamage, damage) - CONVERT_ATTRIBUTE(AttLocationDamage, locationDamage) - CONVERT_ATTRIBUTE(AttIdleSettings, idleSettings) - CONVERT_ATTRIBUTE(AttADSSettings, adsSettings) - CONVERT_ATTRIBUTE(AttADSSettings, adsSettingsMain) - CONVERT_ATTRIBUTE(AttHipSpread, hipSpread) - CONVERT_ATTRIBUTE(AttGunKick, gunKick) - CONVERT_ATTRIBUTE(AttViewKick, viewKick) - CONVERT_ATTRIBUTE(AttADSOverlay, adsOverlay) - CONVERT_ATTRIBUTE(AttUI, ui) - CONVERT_ATTRIBUTE(AttRumbles, rumbles) - CONVERT_ATTRIBUTE(AttProjectile, projectile) - - attachment.ammunitionScale = jAttachment.ammunitionScale; - attachment.damageScale = jAttachment.damageScale; - attachment.damageScaleMin = jAttachment.damageScaleMin; - attachment.stateTimersScale = jAttachment.stateTimersScale; - attachment.fireTimersScale = jAttachment.fireTimersScale; - attachment.idleSettingsScale = jAttachment.idleSettingsScale; - attachment.adsSettingsScale = jAttachment.adsSettingsScale; - attachment.adsSettingsScaleMain = jAttachment.adsSettingsScaleMain; - attachment.hipSpreadScale = jAttachment.hipSpreadScale; - attachment.gunKickScale = jAttachment.gunKickScale; - attachment.viewKickScale = jAttachment.viewKickScale; - attachment.viewCenterScale = jAttachment.viewCenterScale; - attachment.loadIndex = jAttachment.loadIndex; - attachment.hideIronSightsWithThisAttachment = jAttachment.hideIronSightsWithThisAttachment; - attachment.shareAmmoWithAlt = jAttachment.shareAmmoWithAlt; - - return true; - } - - bool CreateTracerFromJson(const std::string& assetName, TracerDef*& tracerPtr, const WeaponAttachment& attachment) const - { - auto* tracer = m_context.LoadDependency(assetName); - if (!tracer) - { - PrintError(attachment, std::format("Could not find tracer {}", assetName)); - return false; - } - m_registration.AddDependency(tracer); - tracerPtr = tracer->Asset(); - - return true; - } - - bool CreateMaterialFromJson(const std::string& assetName, Material*& materialPtr, const WeaponAttachment& attachment) const - { - auto* material = m_context.LoadDependency(assetName); - if (!material) - { - PrintError(attachment, std::format("Could not find material {}", assetName)); - return false; - } - m_registration.AddDependency(material); - materialPtr = material->Asset(); - - return true; - } - - bool CreateFxFromJson(const std::string& assetName, FxEffectDef*& fxPtr, const WeaponAttachment& attachment) const - { - auto* fx = m_context.LoadDependency(assetName); - if (!fx) - { - PrintError(attachment, std::format("Could not find fx {}", assetName)); - return false; - } - m_registration.AddDependency(fx); - fxPtr = fx->Asset(); - - return true; - } - - bool CreateSoundFromJson(const std::string& assetName, SndAliasCustom& sndAliasCustom, const WeaponAttachment& attachment) const - { - m_registration.AddIndirectAssetReference(m_context.LoadIndirectAssetReference(assetName)); - sndAliasCustom.name = m_memory.Alloc(); - sndAliasCustom.name->soundName = m_memory.Dup(assetName.c_str()); - - return true; - } - - bool CreateXModelFromJson(const std::string& assetName, XModel*& xmodelPtr, const WeaponAttachment& attachment) const - { - auto* xmodel = m_context.LoadDependency(assetName); - if (!xmodel) - { - PrintError(attachment, std::format("Could not find xmodel {}", assetName)); - return false; - } - m_registration.AddDependency(xmodel); - xmodelPtr = xmodel->Asset(); - - return true; - } - - bool CreateXModelArrayFromJson(const std::vector& jXmodelArray, - XModel**& xmodelArray, - const char* propertyName, - size_t propertyCount, - const WeaponAttachment& attachment) const - { - if (!jXmodelArray.empty()) - { - const auto arraySize = jXmodelArray.size(); - if (arraySize > propertyCount) - { - PrintError(attachment, std::format("{} size cannot exceed {}", propertyName, propertyCount)); - return false; - } - xmodelArray = m_memory.Alloc(propertyCount); - memset(xmodelArray, 0, sizeof(void*) * propertyCount); - - for (auto i = 0u; i < arraySize; i++) - { - if (!CreateXModelFromJson(jXmodelArray[i], xmodelArray[i], attachment)) - return false; - } - } - else - { - xmodelArray = nullptr; - } - - return true; - } - - bool CreateAttAmmoGeneralFromJson(const JsonAttAmmoGeneral& jAmmoGeneral, AttAmmoGeneral& ammoGeneral, const WeaponAttachment& attachment) const - { - ammoGeneral.penetrateType = jAmmoGeneral.penetrateType; - ammoGeneral.penetrateMultiplier = jAmmoGeneral.penetrateMultiplier; - ammoGeneral.impactType = jAmmoGeneral.impactType; - ammoGeneral.fireType = jAmmoGeneral.fireType; - - if (jAmmoGeneral.tracerType) - { - if (!CreateTracerFromJson(jAmmoGeneral.tracerType.value(), ammoGeneral.tracerType, attachment)) - return false; - } - else - ammoGeneral.tracerType = nullptr; - - ammoGeneral.rifleBullet = jAmmoGeneral.rifleBullet; - ammoGeneral.armorPiercing = jAmmoGeneral.armorPiercing; - - return true; - } - - static bool CreateAttSightFromJson(const JsonAttSight& jSight, AttSight& sight, const WeaponAttachment& attachment) - { - sight.aimDownSight = jSight.aimDownSight; - sight.adsFire = jSight.adsFire; - sight.rechamberWhileAds = jSight.rechamberWhileAds; - sight.noAdsWhenMagEmpty = jSight.noAdsWhenMagEmpty; - sight.canHoldBreath = jSight.canHoldBreath; - sight.canVariableZoom = jSight.canVariableZoom; - sight.hideRailWithThisScope = jSight.hideRailWithThisScope; - - return true; - } - - static bool CreateAttReloadFromJson(const JsonAttReload& jReload, AttReload& reload, const WeaponAttachment& attachment) - { - reload.noPartialReload = jReload.noPartialReload; - reload.segmentedReload = jReload.segmentedReload; - - return true; - } - - static bool CreateAttAddOnsFromJson(const JsonAttAddOns& jAddOns, AttAddOns& addOns, const WeaponAttachment& attachment) - { - addOns.motionTracker = jAddOns.motionTracker; - addOns.silenced = jAddOns.silenced; - - return true; - } - - bool CreateAttGeneralFromJson(const JsonAttGeneral& jGeneral, AttGeneral& general, const WeaponAttachment& attachment) const - { - general.boltAction = jGeneral.boltAction; - general.inheritsPerks = jGeneral.inheritsPerks; - general.enemyCrosshairRange = jGeneral.enemyCrosshairRange; - - if (jGeneral.reticleCenter) - { - if (!CreateMaterialFromJson(jGeneral.reticleCenter.value(), general.reticleCenter, attachment)) - return false; - } - else - general.reticleCenter = nullptr; - - if (jGeneral.reticleSide) - { - if (!CreateMaterialFromJson(jGeneral.reticleSide.value(), general.reticleSide, attachment)) - return false; - } - else - general.reticleSide = nullptr; - - general.reticleCenterSize = jGeneral.reticleCenterSize; - general.reticleSideSize = jGeneral.reticleSideSize; - general.moveSpeedScale = jGeneral.moveSpeedScale; - general.adsMoveSpeedScale = jGeneral.adsMoveSpeedScale; - - return true; - } - - static bool CreateAttAimAssistFromJson(const JsonAttAimAssist& jAimAssist, AttAimAssist& aimAssist, const WeaponAttachment& attachment) - { - aimAssist.autoAimRange = jAimAssist.autoAimRange; - aimAssist.aimAssistRange = jAimAssist.aimAssistRange; - aimAssist.aimAssistRangeAds = jAimAssist.aimAssistRangeAds; - - return true; - } - - static bool CreateAttAmmunitionFromJson(const JsonAttAmmunition& jAmmunition, AttAmmunition& ammunition, const WeaponAttachment& attachment) - { - ammunition.maxAmmo = jAmmunition.maxAmmo; - ammunition.startAmmo = jAmmunition.startAmmo; - ammunition.clipSize = jAmmunition.clipSize; - ammunition.shotCount = jAmmunition.shotCount; - ammunition.reloadAmmoAdd = jAmmunition.reloadAmmoAdd; - ammunition.reloadStartAdd = jAmmunition.reloadStartAdd; - - return true; - } - - static bool CreateAttDamageFromJson(const JsonAttDamage& jDamage, AttDamage& damage, const WeaponAttachment& attachment) - { - damage.damage = jDamage.damage; - damage.minDamage = jDamage.minDamage; - damage.meleeDamage = jDamage.meleeDamage; - damage.maxDamageRange = jDamage.maxDamageRange; - damage.minDamageRange = jDamage.minDamageRange; - damage.playerDamage = jDamage.playerDamage; - damage.minPlayerDamage = jDamage.minPlayerDamage; - - return true; - } - - static bool - CreateAttLocationDamageFromJson(const JsonAttLocationDamage& jLocationDamage, AttLocationDamage& locationDamage, const WeaponAttachment& attachment) - { - locationDamage.locNone = jLocationDamage.locNone; - locationDamage.locHelmet = jLocationDamage.locHelmet; - locationDamage.locHead = jLocationDamage.locHead; - locationDamage.locNeck = jLocationDamage.locNeck; - locationDamage.locTorsoUpper = jLocationDamage.locTorsoUpper; - locationDamage.locTorsoLower = jLocationDamage.locTorsoLower; - locationDamage.locRightArmUpper = jLocationDamage.locRightArmUpper; - locationDamage.locRightArmLower = jLocationDamage.locRightArmLower; - locationDamage.locRightHand = jLocationDamage.locRightHand; - locationDamage.locLeftArmUpper = jLocationDamage.locLeftArmUpper; - locationDamage.locLeftArmLower = jLocationDamage.locLeftArmLower; - locationDamage.locLeftHand = jLocationDamage.locLeftHand; - locationDamage.locRightLegUpper = jLocationDamage.locRightLegUpper; - locationDamage.locRightLegLower = jLocationDamage.locRightLegLower; - locationDamage.locRightFoot = jLocationDamage.locRightFoot; - locationDamage.locLeftLegUpper = jLocationDamage.locLeftLegUpper; - locationDamage.locLeftLegLower = jLocationDamage.locLeftLegLower; - locationDamage.locLeftFoot = jLocationDamage.locLeftFoot; - locationDamage.locGun = jLocationDamage.locGun; - - return true; - } - - static bool CreateAttIdleSettingsFromJson(const JsonAttIdleSettings& jIdleSettings, AttIdleSettings& idleSettings, const WeaponAttachment& attachment) - { - idleSettings.hipIdleAmount = jIdleSettings.hipIdleAmount; - idleSettings.hipIdleSpeed = jIdleSettings.hipIdleSpeed; - idleSettings.idleCrouchFactor = jIdleSettings.idleCrouchFactor; - idleSettings.idleProneFactor = jIdleSettings.idleProneFactor; - idleSettings.adsIdleLerpStartTime = jIdleSettings.adsIdleLerpStartTime; - idleSettings.adsIdleLerpTime = jIdleSettings.adsIdleLerpTime; - - return true; - } - - static bool CreateAttADSSettingsFromJson(const JsonAttADSSettings& jAdsSettings, AttADSSettings& adsSettings, const WeaponAttachment& attachment) - { - adsSettings.adsSpread = jAdsSettings.adsSpread; - adsSettings.adsAimPitch = jAdsSettings.adsAimPitch; - adsSettings.adsTransInTime = jAdsSettings.adsTransInTime; - adsSettings.adsTransOutTime = jAdsSettings.adsTransOutTime; - adsSettings.adsReloadTransTime = jAdsSettings.adsReloadTransTime; - adsSettings.adsCrosshairInFrac = jAdsSettings.adsCrosshairInFrac; - adsSettings.adsCrosshairOutFrac = jAdsSettings.adsCrosshairOutFrac; - adsSettings.adsZoomFov = jAdsSettings.adsZoomFov; - adsSettings.adsZoomInFrac = jAdsSettings.adsZoomInFrac; - adsSettings.adsZoomOutFrac = jAdsSettings.adsZoomOutFrac; - adsSettings.adsBobFactor = jAdsSettings.adsBobFactor; - adsSettings.adsViewBobMult = jAdsSettings.adsViewBobMult; - adsSettings.adsViewErrorMin = jAdsSettings.adsViewErrorMin; - adsSettings.adsViewErrorMax = jAdsSettings.adsViewErrorMax; - - return true; - } - - static bool CreateAttHipSpreadFromJson(const JsonAttHipSpread& jHipSpread, AttHipSpread& hipSpread, const WeaponAttachment& attachment) - { - hipSpread.hipSpreadStandMin = jHipSpread.hipSpreadStandMin; - hipSpread.hipSpreadDuckedMin = jHipSpread.hipSpreadDuckedMin; - hipSpread.hipSpreadProneMin = jHipSpread.hipSpreadProneMin; - hipSpread.hipSpreadMax = jHipSpread.hipSpreadMax; - hipSpread.hipSpreadDuckedMax = jHipSpread.hipSpreadDuckedMax; - hipSpread.hipSpreadProneMax = jHipSpread.hipSpreadProneMax; - hipSpread.hipSpreadFireAdd = jHipSpread.hipSpreadFireAdd; - hipSpread.hipSpreadTurnAdd = jHipSpread.hipSpreadTurnAdd; - hipSpread.hipSpreadMoveAdd = jHipSpread.hipSpreadMoveAdd; - hipSpread.hipSpreadDecayRate = jHipSpread.hipSpreadDecayRate; - hipSpread.hipSpreadDuckedDecay = jHipSpread.hipSpreadDuckedDecay; - hipSpread.hipSpreadProneDecay = jHipSpread.hipSpreadProneDecay; - - return true; - } - - static bool CreateAttGunKickFromJson(const JsonAttGunKick& jGunKick, AttGunKick& gunKick, const WeaponAttachment& attachment) - { - gunKick.hipGunKickReducedKickBullets = jGunKick.hipGunKickReducedKickBullets; - gunKick.hipGunKickReducedKickPercent = jGunKick.hipGunKickReducedKickPercent; - gunKick.hipGunKickPitchMin = jGunKick.hipGunKickPitchMin; - gunKick.hipGunKickPitchMax = jGunKick.hipGunKickPitchMax; - gunKick.hipGunKickYawMin = jGunKick.hipGunKickYawMin; - gunKick.hipGunKickYawMax = jGunKick.hipGunKickYawMax; - gunKick.hipGunKickAccel = jGunKick.hipGunKickAccel; - gunKick.hipGunKickSpeedMax = jGunKick.hipGunKickSpeedMax; - gunKick.hipGunKickSpeedDecay = jGunKick.hipGunKickSpeedDecay; - gunKick.hipGunKickStaticDecay = jGunKick.hipGunKickStaticDecay; - gunKick.adsGunKickReducedKickBullets = jGunKick.adsGunKickReducedKickBullets; - gunKick.adsGunKickReducedKickPercent = jGunKick.adsGunKickReducedKickPercent; - gunKick.adsGunKickPitchMin = jGunKick.adsGunKickPitchMin; - gunKick.adsGunKickPitchMax = jGunKick.adsGunKickPitchMax; - gunKick.adsGunKickYawMin = jGunKick.adsGunKickYawMin; - gunKick.adsGunKickYawMax = jGunKick.adsGunKickYawMax; - gunKick.adsGunKickAccel = jGunKick.adsGunKickAccel; - gunKick.adsGunKickSpeedMax = jGunKick.adsGunKickSpeedMax; - gunKick.adsGunKickSpeedDecay = jGunKick.adsGunKickSpeedDecay; - gunKick.adsGunKickStaticDecay = jGunKick.adsGunKickStaticDecay; - - return true; - } - - static bool CreateAttViewKickFromJson(const JsonAttViewKick& jViewKick, AttViewKick& viewKick, const WeaponAttachment& attachment) - { - viewKick.hipViewKickPitchMin = jViewKick.hipViewKickPitchMin; - viewKick.hipViewKickPitchMax = jViewKick.hipViewKickPitchMax; - viewKick.hipViewKickYawMin = jViewKick.hipViewKickYawMin; - viewKick.hipViewKickYawMax = jViewKick.hipViewKickYawMax; - viewKick.hipViewKickCenterSpeed = jViewKick.hipViewKickCenterSpeed; - viewKick.adsViewKickPitchMin = jViewKick.adsViewKickPitchMin; - viewKick.adsViewKickPitchMax = jViewKick.adsViewKickPitchMax; - viewKick.adsViewKickYawMin = jViewKick.adsViewKickYawMin; - viewKick.adsViewKickYawMax = jViewKick.adsViewKickYawMax; - viewKick.adsViewKickCenterSpeed = jViewKick.adsViewKickCenterSpeed; - - return true; - } - - bool CreateAttADSOverlayFromJson(const JsonAttADSOverlay& jAdsOverlay, AttADSOverlay& adsOverlay, const WeaponAttachment& attachment) const - { - if (jAdsOverlay.shader) - { - if (!CreateMaterialFromJson(jAdsOverlay.shader.value(), adsOverlay.overlay.shader, attachment)) - return false; - } - else - adsOverlay.overlay.shader = nullptr; - - if (jAdsOverlay.shaderLowRes) - { - if (!CreateMaterialFromJson(jAdsOverlay.shaderLowRes.value(), adsOverlay.overlay.shaderLowRes, attachment)) - return false; - } - else - adsOverlay.overlay.shaderLowRes = nullptr; - - if (jAdsOverlay.shaderEMP) - { - if (!CreateMaterialFromJson(jAdsOverlay.shaderEMP.value(), adsOverlay.overlay.shaderEMP, attachment)) - return false; - } - else - adsOverlay.overlay.shaderEMP = nullptr; - - if (jAdsOverlay.shaderEMPLowRes) - { - if (!CreateMaterialFromJson(jAdsOverlay.shaderEMPLowRes.value(), adsOverlay.overlay.shaderEMPLowRes, attachment)) - return false; - } - else - adsOverlay.overlay.shaderEMPLowRes = nullptr; - - adsOverlay.overlay.reticle = jAdsOverlay.reticle; - adsOverlay.overlay.width = jAdsOverlay.width; - adsOverlay.overlay.height = jAdsOverlay.height; - adsOverlay.overlay.widthSplitscreen = jAdsOverlay.widthSplitscreen; - adsOverlay.overlay.heightSplitscreen = jAdsOverlay.heightSplitscreen; - adsOverlay.thermalScope = jAdsOverlay.thermalScope; - - return true; - } - - bool CreateAttUIFromJson(const JsonAttUI& jUi, AttUI& ui, const WeaponAttachment& attachment) const - { - if (jUi.dpadIcon) - { - if (!CreateMaterialFromJson(jUi.dpadIcon.value(), ui.dpadIcon, attachment)) - return false; - } - else - ui.dpadIcon = nullptr; - - if (jUi.ammoCounterIcon) - { - if (!CreateMaterialFromJson(jUi.ammoCounterIcon.value(), ui.ammoCounterIcon, attachment)) - return false; - } - else - ui.ammoCounterIcon = nullptr; - - ui.dpadIconRatio = jUi.dpadIconRatio; - ui.ammoCounterIconRatio = jUi.ammoCounterIconRatio; - ui.ammoCounterClip = jUi.ammoCounterClip; - - return true; - } - - bool CreateAttRumblesFromJson(const JsonAttRumbles& jRumbles, AttRumbles& rumbles, const WeaponAttachment& attachment) const - { - if (jRumbles.fireRumble) - rumbles.fireRumble = m_memory.Dup(jRumbles.fireRumble.value().c_str()); - else - rumbles.fireRumble = nullptr; - - if (jRumbles.meleeImpactRumble) - rumbles.meleeImpactRumble = m_memory.Dup(jRumbles.meleeImpactRumble.value().c_str()); - else - rumbles.meleeImpactRumble = nullptr; - - return true; - } - - bool CreateAttProjectileFromJson(const JsonAttProjectile& jProjectile, AttProjectile& projectile, const WeaponAttachment& attachment) const - { - projectile.explosionRadius = jProjectile.explosionRadius; - projectile.explosionInnerDamage = jProjectile.explosionInnerDamage; - projectile.explosionOuterDamage = jProjectile.explosionOuterDamage; - projectile.damageConeAngle = jProjectile.damageConeAngle; - projectile.projectileSpeed = jProjectile.projectileSpeed; - projectile.projectileSpeedUp = jProjectile.projectileSpeedUp; - projectile.projectileActivateDist = jProjectile.projectileActivateDist; - projectile.projectileLifetime = jProjectile.projectileLifetime; - - if (jProjectile.projectileModel) - { - if (!CreateXModelFromJson(jProjectile.projectileModel.value(), projectile.projectileModel, attachment)) - return false; - } - else - projectile.projectileModel = nullptr; - - projectile.projExplosionType = jProjectile.projExplosionType; - - if (jProjectile.projExplosionEffect) - { - if (!CreateFxFromJson(jProjectile.projExplosionEffect.value(), projectile.projExplosionEffect, attachment)) - return false; - } - else - projectile.projExplosionEffect = nullptr; - - projectile.projExplosionEffectForceNormalUp = jProjectile.projExplosionEffectForceNormalUp; - - if (jProjectile.projExplosionSound) - { - if (!CreateSoundFromJson(jProjectile.projExplosionSound.value(), projectile.projExplosionSound, attachment)) - return false; - } - else - projectile.projExplosionSound.name = nullptr; - - if (jProjectile.projDudEffect) - { - if (!CreateFxFromJson(jProjectile.projDudEffect.value(), projectile.projDudEffect, attachment)) - return false; - } - else - projectile.projDudEffect = nullptr; - - if (jProjectile.projDudSound) - { - if (!CreateSoundFromJson(jProjectile.projDudSound.value(), projectile.projDudSound, attachment)) - return false; - } - else - projectile.projDudSound.name = nullptr; - - projectile.projImpactExplode = jProjectile.projImpactExplode; - projectile.destabilizationRateTime = jProjectile.destabilizationRateTime; - projectile.destabilizationCurvatureMax = jProjectile.destabilizationCurvatureMax; - projectile.destabilizeDistance = jProjectile.destabilizeDistance; - - if (jProjectile.projTrailEffect) - { - if (!CreateFxFromJson(jProjectile.projTrailEffect.value(), projectile.projTrailEffect, attachment)) - return false; - } - else - projectile.projTrailEffect = nullptr; - - projectile.projIgnitionDelay = jProjectile.projIgnitionDelay; - - if (jProjectile.projIgnitionEffect) - { - if (!CreateFxFromJson(jProjectile.projIgnitionEffect.value(), projectile.projIgnitionEffect, attachment)) - return false; - } - else - projectile.projIgnitionEffect = nullptr; - - if (jProjectile.projIgnitionSound) - { - if (!CreateSoundFromJson(jProjectile.projIgnitionSound.value(), projectile.projIgnitionSound, attachment)) - return false; - } - else - projectile.projIgnitionSound.name = nullptr; - - return true; - } - - std::istream& m_stream; - MemoryManager& m_memory; - AssetCreationContext& m_context; - AssetRegistration& m_registration; - }; -} // namespace - -namespace IW5 -{ - bool LoadWeaponAttachmentAsJson(std::istream& stream, - WeaponAttachment& attachment, - MemoryManager& memory, - AssetCreationContext& context, - AssetRegistration& registration) - { - const JsonLoader loader(stream, memory, context, registration); - - return loader.Load(attachment); - } -} // namespace IW5 diff --git a/src/ObjLoading/Game/IW5/Weapon/JsonWeaponAttachmentLoader.h b/src/ObjLoading/Game/IW5/Weapon/JsonWeaponAttachmentLoader.h deleted file mode 100644 index 5b9d7b06..00000000 --- a/src/ObjLoading/Game/IW5/Weapon/JsonWeaponAttachmentLoader.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "Asset/AssetCreationContext.h" -#include "Asset/AssetRegistration.h" -#include "Game/IW5/IW5.h" -#include "Utils/MemoryManager.h" - -#include - -namespace IW5 -{ - bool LoadWeaponAttachmentAsJson(std::istream& stream, - WeaponAttachment& attachment, - 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 index ac7197c1..492baea4 100644 --- a/src/ObjLoading/Game/IW5/Weapon/LoaderAttachmentIW5.cpp +++ b/src/ObjLoading/Game/IW5/Weapon/LoaderAttachmentIW5.cpp @@ -1,16 +1,636 @@ #include "LoaderAttachmentIW5.h" #include "Game/IW5/IW5.h" -#include "JsonWeaponAttachmentLoader.h" +#include "Game/IW5/Weapon/JsonWeaponAttachment.h" +#include "Weapon/AttachmentCommon.h" #include #include #include +#include +using namespace nlohmann; using namespace IW5; namespace { + class JsonLoader + { + public: + JsonLoader(std::istream& stream, MemoryManager& memory, AssetCreationContext& context, AssetRegistration& registration) + : m_stream(stream), + m_memory(memory), + m_context(context), + m_registration(registration) + + { + } + + bool Load(WeaponAttachment& attachment) const + { + try + { + const auto jRoot = json::parse(m_stream); + std::string type; + unsigned version; + + jRoot.at("_type").get_to(type); + jRoot.at("_version").get_to(version); + + if (type != "attachment" || version != 1u) + { + std::cerr << "Tried to load attachment \"" << attachment.szInternalName << "\" but did not find expected type attachment of version 1\n"; + return false; + } + + const auto jAttachment = jRoot.get(); + return CreateWeaponAttachmentFromJson(jAttachment, attachment); + } + catch (const json::exception& e) + { + std::cerr << std::format("Failed to parse json of attachment: {}\n", e.what()); + } + + return false; + } + + private: + static void PrintError(const WeaponAttachment& attachment, const std::string& message) + { + std::cerr << "Cannot load attachment \"" << attachment.szInternalName << "\": " << message << "\n"; + } + + bool CreateWeaponAttachmentFromJson(const JsonWeaponAttachment& jAttachment, WeaponAttachment& attachment) const + { +#define CONVERT_XMODEL_ARRAY(propertyName, count) \ + CreateXModelArrayFromJson(jAttachment.propertyName, attachment.propertyName, #propertyName, count, attachment); + +#define CONVERT_ATTRIBUTE(attributeClass, attributeName) \ + if (jAttachment.attributeName) \ + { \ + using AttributeType = std::remove_pointer_t; \ + attachment.attributeName = m_memory.Alloc(); \ + if (!Create##attributeClass##FromJson(jAttachment.attributeName.value(), *attachment.attributeName, attachment)) \ + return false; \ + } \ + else \ + attachment.attributeName = nullptr; + + attachment.szDisplayName = m_memory.Dup(jAttachment.displayName.c_str()); + attachment.type = jAttachment.type; + attachment.weaponType = jAttachment.weaponType; + attachment.weapClass = jAttachment.weapClass; + + CONVERT_XMODEL_ARRAY(worldModels, ATTACHMENT_WORLD_MODEL_COUNT) + CONVERT_XMODEL_ARRAY(viewModels, ATTACHMENT_VIEW_MODEL_COUNT) + CONVERT_XMODEL_ARRAY(reticleViewModels, ATTACHMENT_RETICLE_VIEW_MODEL_COUNT) + + CONVERT_ATTRIBUTE(AttAmmoGeneral, ammoGeneral) + CONVERT_ATTRIBUTE(AttSight, sight) + CONVERT_ATTRIBUTE(AttReload, reload) + CONVERT_ATTRIBUTE(AttAddOns, addOns) + CONVERT_ATTRIBUTE(AttGeneral, general) + CONVERT_ATTRIBUTE(AttAimAssist, aimAssist) + CONVERT_ATTRIBUTE(AttAmmunition, ammunition) + CONVERT_ATTRIBUTE(AttDamage, damage) + CONVERT_ATTRIBUTE(AttLocationDamage, locationDamage) + CONVERT_ATTRIBUTE(AttIdleSettings, idleSettings) + CONVERT_ATTRIBUTE(AttADSSettings, adsSettings) + CONVERT_ATTRIBUTE(AttADSSettings, adsSettingsMain) + CONVERT_ATTRIBUTE(AttHipSpread, hipSpread) + CONVERT_ATTRIBUTE(AttGunKick, gunKick) + CONVERT_ATTRIBUTE(AttViewKick, viewKick) + CONVERT_ATTRIBUTE(AttADSOverlay, adsOverlay) + CONVERT_ATTRIBUTE(AttUI, ui) + CONVERT_ATTRIBUTE(AttRumbles, rumbles) + CONVERT_ATTRIBUTE(AttProjectile, projectile) + + attachment.ammunitionScale = jAttachment.ammunitionScale; + attachment.damageScale = jAttachment.damageScale; + attachment.damageScaleMin = jAttachment.damageScaleMin; + attachment.stateTimersScale = jAttachment.stateTimersScale; + attachment.fireTimersScale = jAttachment.fireTimersScale; + attachment.idleSettingsScale = jAttachment.idleSettingsScale; + attachment.adsSettingsScale = jAttachment.adsSettingsScale; + attachment.adsSettingsScaleMain = jAttachment.adsSettingsScaleMain; + attachment.hipSpreadScale = jAttachment.hipSpreadScale; + attachment.gunKickScale = jAttachment.gunKickScale; + attachment.viewKickScale = jAttachment.viewKickScale; + attachment.viewCenterScale = jAttachment.viewCenterScale; + attachment.loadIndex = jAttachment.loadIndex; + attachment.hideIronSightsWithThisAttachment = jAttachment.hideIronSightsWithThisAttachment; + attachment.shareAmmoWithAlt = jAttachment.shareAmmoWithAlt; + + return true; + } + + bool CreateTracerFromJson(const std::string& assetName, TracerDef*& tracerPtr, const WeaponAttachment& attachment) const + { + auto* tracer = m_context.LoadDependency(assetName); + if (!tracer) + { + PrintError(attachment, std::format("Could not find tracer {}", assetName)); + return false; + } + m_registration.AddDependency(tracer); + tracerPtr = tracer->Asset(); + + return true; + } + + bool CreateMaterialFromJson(const std::string& assetName, Material*& materialPtr, const WeaponAttachment& attachment) const + { + auto* material = m_context.LoadDependency(assetName); + if (!material) + { + PrintError(attachment, std::format("Could not find material {}", assetName)); + return false; + } + m_registration.AddDependency(material); + materialPtr = material->Asset(); + + return true; + } + + bool CreateFxFromJson(const std::string& assetName, FxEffectDef*& fxPtr, const WeaponAttachment& attachment) const + { + auto* fx = m_context.LoadDependency(assetName); + if (!fx) + { + PrintError(attachment, std::format("Could not find fx {}", assetName)); + return false; + } + m_registration.AddDependency(fx); + fxPtr = fx->Asset(); + + return true; + } + + bool CreateSoundFromJson(const std::string& assetName, SndAliasCustom& sndAliasCustom, const WeaponAttachment& attachment) const + { + m_registration.AddIndirectAssetReference(m_context.LoadIndirectAssetReference(assetName)); + sndAliasCustom.name = m_memory.Alloc(); + sndAliasCustom.name->soundName = m_memory.Dup(assetName.c_str()); + + return true; + } + + bool CreateXModelFromJson(const std::string& assetName, XModel*& xmodelPtr, const WeaponAttachment& attachment) const + { + auto* xmodel = m_context.LoadDependency(assetName); + if (!xmodel) + { + PrintError(attachment, std::format("Could not find xmodel {}", assetName)); + return false; + } + m_registration.AddDependency(xmodel); + xmodelPtr = xmodel->Asset(); + + return true; + } + + bool CreateXModelArrayFromJson(const std::vector& jXmodelArray, + XModel**& xmodelArray, + const char* propertyName, + size_t propertyCount, + const WeaponAttachment& attachment) const + { + if (!jXmodelArray.empty()) + { + const auto arraySize = jXmodelArray.size(); + if (arraySize > propertyCount) + { + PrintError(attachment, std::format("{} size cannot exceed {}", propertyName, propertyCount)); + return false; + } + xmodelArray = m_memory.Alloc(propertyCount); + memset(xmodelArray, 0, sizeof(void*) * propertyCount); + + for (auto i = 0u; i < arraySize; i++) + { + if (!CreateXModelFromJson(jXmodelArray[i], xmodelArray[i], attachment)) + return false; + } + } + else + { + xmodelArray = nullptr; + } + + return true; + } + + bool CreateAttAmmoGeneralFromJson(const JsonAttAmmoGeneral& jAmmoGeneral, AttAmmoGeneral& ammoGeneral, const WeaponAttachment& attachment) const + { + ammoGeneral.penetrateType = jAmmoGeneral.penetrateType; + ammoGeneral.penetrateMultiplier = jAmmoGeneral.penetrateMultiplier; + ammoGeneral.impactType = jAmmoGeneral.impactType; + ammoGeneral.fireType = jAmmoGeneral.fireType; + + if (jAmmoGeneral.tracerType) + { + if (!CreateTracerFromJson(jAmmoGeneral.tracerType.value(), ammoGeneral.tracerType, attachment)) + return false; + } + else + ammoGeneral.tracerType = nullptr; + + ammoGeneral.rifleBullet = jAmmoGeneral.rifleBullet; + ammoGeneral.armorPiercing = jAmmoGeneral.armorPiercing; + + return true; + } + + static bool CreateAttSightFromJson(const JsonAttSight& jSight, AttSight& sight, const WeaponAttachment& attachment) + { + sight.aimDownSight = jSight.aimDownSight; + sight.adsFire = jSight.adsFire; + sight.rechamberWhileAds = jSight.rechamberWhileAds; + sight.noAdsWhenMagEmpty = jSight.noAdsWhenMagEmpty; + sight.canHoldBreath = jSight.canHoldBreath; + sight.canVariableZoom = jSight.canVariableZoom; + sight.hideRailWithThisScope = jSight.hideRailWithThisScope; + + return true; + } + + static bool CreateAttReloadFromJson(const JsonAttReload& jReload, AttReload& reload, const WeaponAttachment& attachment) + { + reload.noPartialReload = jReload.noPartialReload; + reload.segmentedReload = jReload.segmentedReload; + + return true; + } + + static bool CreateAttAddOnsFromJson(const JsonAttAddOns& jAddOns, AttAddOns& addOns, const WeaponAttachment& attachment) + { + addOns.motionTracker = jAddOns.motionTracker; + addOns.silenced = jAddOns.silenced; + + return true; + } + + bool CreateAttGeneralFromJson(const JsonAttGeneral& jGeneral, AttGeneral& general, const WeaponAttachment& attachment) const + { + general.boltAction = jGeneral.boltAction; + general.inheritsPerks = jGeneral.inheritsPerks; + general.enemyCrosshairRange = jGeneral.enemyCrosshairRange; + + if (jGeneral.reticleCenter) + { + if (!CreateMaterialFromJson(jGeneral.reticleCenter.value(), general.reticleCenter, attachment)) + return false; + } + else + general.reticleCenter = nullptr; + + if (jGeneral.reticleSide) + { + if (!CreateMaterialFromJson(jGeneral.reticleSide.value(), general.reticleSide, attachment)) + return false; + } + else + general.reticleSide = nullptr; + + general.reticleCenterSize = jGeneral.reticleCenterSize; + general.reticleSideSize = jGeneral.reticleSideSize; + general.moveSpeedScale = jGeneral.moveSpeedScale; + general.adsMoveSpeedScale = jGeneral.adsMoveSpeedScale; + + return true; + } + + static bool CreateAttAimAssistFromJson(const JsonAttAimAssist& jAimAssist, AttAimAssist& aimAssist, const WeaponAttachment& attachment) + { + aimAssist.autoAimRange = jAimAssist.autoAimRange; + aimAssist.aimAssistRange = jAimAssist.aimAssistRange; + aimAssist.aimAssistRangeAds = jAimAssist.aimAssistRangeAds; + + return true; + } + + static bool CreateAttAmmunitionFromJson(const JsonAttAmmunition& jAmmunition, AttAmmunition& ammunition, const WeaponAttachment& attachment) + { + ammunition.maxAmmo = jAmmunition.maxAmmo; + ammunition.startAmmo = jAmmunition.startAmmo; + ammunition.clipSize = jAmmunition.clipSize; + ammunition.shotCount = jAmmunition.shotCount; + ammunition.reloadAmmoAdd = jAmmunition.reloadAmmoAdd; + ammunition.reloadStartAdd = jAmmunition.reloadStartAdd; + + return true; + } + + static bool CreateAttDamageFromJson(const JsonAttDamage& jDamage, AttDamage& damage, const WeaponAttachment& attachment) + { + damage.damage = jDamage.damage; + damage.minDamage = jDamage.minDamage; + damage.meleeDamage = jDamage.meleeDamage; + damage.maxDamageRange = jDamage.maxDamageRange; + damage.minDamageRange = jDamage.minDamageRange; + damage.playerDamage = jDamage.playerDamage; + damage.minPlayerDamage = jDamage.minPlayerDamage; + + return true; + } + + static bool + CreateAttLocationDamageFromJson(const JsonAttLocationDamage& jLocationDamage, AttLocationDamage& locationDamage, const WeaponAttachment& attachment) + { + locationDamage.locNone = jLocationDamage.locNone; + locationDamage.locHelmet = jLocationDamage.locHelmet; + locationDamage.locHead = jLocationDamage.locHead; + locationDamage.locNeck = jLocationDamage.locNeck; + locationDamage.locTorsoUpper = jLocationDamage.locTorsoUpper; + locationDamage.locTorsoLower = jLocationDamage.locTorsoLower; + locationDamage.locRightArmUpper = jLocationDamage.locRightArmUpper; + locationDamage.locRightArmLower = jLocationDamage.locRightArmLower; + locationDamage.locRightHand = jLocationDamage.locRightHand; + locationDamage.locLeftArmUpper = jLocationDamage.locLeftArmUpper; + locationDamage.locLeftArmLower = jLocationDamage.locLeftArmLower; + locationDamage.locLeftHand = jLocationDamage.locLeftHand; + locationDamage.locRightLegUpper = jLocationDamage.locRightLegUpper; + locationDamage.locRightLegLower = jLocationDamage.locRightLegLower; + locationDamage.locRightFoot = jLocationDamage.locRightFoot; + locationDamage.locLeftLegUpper = jLocationDamage.locLeftLegUpper; + locationDamage.locLeftLegLower = jLocationDamage.locLeftLegLower; + locationDamage.locLeftFoot = jLocationDamage.locLeftFoot; + locationDamage.locGun = jLocationDamage.locGun; + + return true; + } + + static bool CreateAttIdleSettingsFromJson(const JsonAttIdleSettings& jIdleSettings, AttIdleSettings& idleSettings, const WeaponAttachment& attachment) + { + idleSettings.hipIdleAmount = jIdleSettings.hipIdleAmount; + idleSettings.hipIdleSpeed = jIdleSettings.hipIdleSpeed; + idleSettings.idleCrouchFactor = jIdleSettings.idleCrouchFactor; + idleSettings.idleProneFactor = jIdleSettings.idleProneFactor; + idleSettings.adsIdleLerpStartTime = jIdleSettings.adsIdleLerpStartTime; + idleSettings.adsIdleLerpTime = jIdleSettings.adsIdleLerpTime; + + return true; + } + + static bool CreateAttADSSettingsFromJson(const JsonAttADSSettings& jAdsSettings, AttADSSettings& adsSettings, const WeaponAttachment& attachment) + { + adsSettings.adsSpread = jAdsSettings.adsSpread; + adsSettings.adsAimPitch = jAdsSettings.adsAimPitch; + adsSettings.adsTransInTime = jAdsSettings.adsTransInTime; + adsSettings.adsTransOutTime = jAdsSettings.adsTransOutTime; + adsSettings.adsReloadTransTime = jAdsSettings.adsReloadTransTime; + adsSettings.adsCrosshairInFrac = jAdsSettings.adsCrosshairInFrac; + adsSettings.adsCrosshairOutFrac = jAdsSettings.adsCrosshairOutFrac; + adsSettings.adsZoomFov = jAdsSettings.adsZoomFov; + adsSettings.adsZoomInFrac = jAdsSettings.adsZoomInFrac; + adsSettings.adsZoomOutFrac = jAdsSettings.adsZoomOutFrac; + adsSettings.adsBobFactor = jAdsSettings.adsBobFactor; + adsSettings.adsViewBobMult = jAdsSettings.adsViewBobMult; + adsSettings.adsViewErrorMin = jAdsSettings.adsViewErrorMin; + adsSettings.adsViewErrorMax = jAdsSettings.adsViewErrorMax; + + return true; + } + + static bool CreateAttHipSpreadFromJson(const JsonAttHipSpread& jHipSpread, AttHipSpread& hipSpread, const WeaponAttachment& attachment) + { + hipSpread.hipSpreadStandMin = jHipSpread.hipSpreadStandMin; + hipSpread.hipSpreadDuckedMin = jHipSpread.hipSpreadDuckedMin; + hipSpread.hipSpreadProneMin = jHipSpread.hipSpreadProneMin; + hipSpread.hipSpreadMax = jHipSpread.hipSpreadMax; + hipSpread.hipSpreadDuckedMax = jHipSpread.hipSpreadDuckedMax; + hipSpread.hipSpreadProneMax = jHipSpread.hipSpreadProneMax; + hipSpread.hipSpreadFireAdd = jHipSpread.hipSpreadFireAdd; + hipSpread.hipSpreadTurnAdd = jHipSpread.hipSpreadTurnAdd; + hipSpread.hipSpreadMoveAdd = jHipSpread.hipSpreadMoveAdd; + hipSpread.hipSpreadDecayRate = jHipSpread.hipSpreadDecayRate; + hipSpread.hipSpreadDuckedDecay = jHipSpread.hipSpreadDuckedDecay; + hipSpread.hipSpreadProneDecay = jHipSpread.hipSpreadProneDecay; + + return true; + } + + static bool CreateAttGunKickFromJson(const JsonAttGunKick& jGunKick, AttGunKick& gunKick, const WeaponAttachment& attachment) + { + gunKick.hipGunKickReducedKickBullets = jGunKick.hipGunKickReducedKickBullets; + gunKick.hipGunKickReducedKickPercent = jGunKick.hipGunKickReducedKickPercent; + gunKick.hipGunKickPitchMin = jGunKick.hipGunKickPitchMin; + gunKick.hipGunKickPitchMax = jGunKick.hipGunKickPitchMax; + gunKick.hipGunKickYawMin = jGunKick.hipGunKickYawMin; + gunKick.hipGunKickYawMax = jGunKick.hipGunKickYawMax; + gunKick.hipGunKickAccel = jGunKick.hipGunKickAccel; + gunKick.hipGunKickSpeedMax = jGunKick.hipGunKickSpeedMax; + gunKick.hipGunKickSpeedDecay = jGunKick.hipGunKickSpeedDecay; + gunKick.hipGunKickStaticDecay = jGunKick.hipGunKickStaticDecay; + gunKick.adsGunKickReducedKickBullets = jGunKick.adsGunKickReducedKickBullets; + gunKick.adsGunKickReducedKickPercent = jGunKick.adsGunKickReducedKickPercent; + gunKick.adsGunKickPitchMin = jGunKick.adsGunKickPitchMin; + gunKick.adsGunKickPitchMax = jGunKick.adsGunKickPitchMax; + gunKick.adsGunKickYawMin = jGunKick.adsGunKickYawMin; + gunKick.adsGunKickYawMax = jGunKick.adsGunKickYawMax; + gunKick.adsGunKickAccel = jGunKick.adsGunKickAccel; + gunKick.adsGunKickSpeedMax = jGunKick.adsGunKickSpeedMax; + gunKick.adsGunKickSpeedDecay = jGunKick.adsGunKickSpeedDecay; + gunKick.adsGunKickStaticDecay = jGunKick.adsGunKickStaticDecay; + + return true; + } + + static bool CreateAttViewKickFromJson(const JsonAttViewKick& jViewKick, AttViewKick& viewKick, const WeaponAttachment& attachment) + { + viewKick.hipViewKickPitchMin = jViewKick.hipViewKickPitchMin; + viewKick.hipViewKickPitchMax = jViewKick.hipViewKickPitchMax; + viewKick.hipViewKickYawMin = jViewKick.hipViewKickYawMin; + viewKick.hipViewKickYawMax = jViewKick.hipViewKickYawMax; + viewKick.hipViewKickCenterSpeed = jViewKick.hipViewKickCenterSpeed; + viewKick.adsViewKickPitchMin = jViewKick.adsViewKickPitchMin; + viewKick.adsViewKickPitchMax = jViewKick.adsViewKickPitchMax; + viewKick.adsViewKickYawMin = jViewKick.adsViewKickYawMin; + viewKick.adsViewKickYawMax = jViewKick.adsViewKickYawMax; + viewKick.adsViewKickCenterSpeed = jViewKick.adsViewKickCenterSpeed; + + return true; + } + + bool CreateAttADSOverlayFromJson(const JsonAttADSOverlay& jAdsOverlay, AttADSOverlay& adsOverlay, const WeaponAttachment& attachment) const + { + if (jAdsOverlay.shader) + { + if (!CreateMaterialFromJson(jAdsOverlay.shader.value(), adsOverlay.overlay.shader, attachment)) + return false; + } + else + adsOverlay.overlay.shader = nullptr; + + if (jAdsOverlay.shaderLowRes) + { + if (!CreateMaterialFromJson(jAdsOverlay.shaderLowRes.value(), adsOverlay.overlay.shaderLowRes, attachment)) + return false; + } + else + adsOverlay.overlay.shaderLowRes = nullptr; + + if (jAdsOverlay.shaderEMP) + { + if (!CreateMaterialFromJson(jAdsOverlay.shaderEMP.value(), adsOverlay.overlay.shaderEMP, attachment)) + return false; + } + else + adsOverlay.overlay.shaderEMP = nullptr; + + if (jAdsOverlay.shaderEMPLowRes) + { + if (!CreateMaterialFromJson(jAdsOverlay.shaderEMPLowRes.value(), adsOverlay.overlay.shaderEMPLowRes, attachment)) + return false; + } + else + adsOverlay.overlay.shaderEMPLowRes = nullptr; + + adsOverlay.overlay.reticle = jAdsOverlay.reticle; + adsOverlay.overlay.width = jAdsOverlay.width; + adsOverlay.overlay.height = jAdsOverlay.height; + adsOverlay.overlay.widthSplitscreen = jAdsOverlay.widthSplitscreen; + adsOverlay.overlay.heightSplitscreen = jAdsOverlay.heightSplitscreen; + adsOverlay.thermalScope = jAdsOverlay.thermalScope; + + return true; + } + + bool CreateAttUIFromJson(const JsonAttUI& jUi, AttUI& ui, const WeaponAttachment& attachment) const + { + if (jUi.dpadIcon) + { + if (!CreateMaterialFromJson(jUi.dpadIcon.value(), ui.dpadIcon, attachment)) + return false; + } + else + ui.dpadIcon = nullptr; + + if (jUi.ammoCounterIcon) + { + if (!CreateMaterialFromJson(jUi.ammoCounterIcon.value(), ui.ammoCounterIcon, attachment)) + return false; + } + else + ui.ammoCounterIcon = nullptr; + + ui.dpadIconRatio = jUi.dpadIconRatio; + ui.ammoCounterIconRatio = jUi.ammoCounterIconRatio; + ui.ammoCounterClip = jUi.ammoCounterClip; + + return true; + } + + bool CreateAttRumblesFromJson(const JsonAttRumbles& jRumbles, AttRumbles& rumbles, const WeaponAttachment& attachment) const + { + if (jRumbles.fireRumble) + rumbles.fireRumble = m_memory.Dup(jRumbles.fireRumble.value().c_str()); + else + rumbles.fireRumble = nullptr; + + if (jRumbles.meleeImpactRumble) + rumbles.meleeImpactRumble = m_memory.Dup(jRumbles.meleeImpactRumble.value().c_str()); + else + rumbles.meleeImpactRumble = nullptr; + + return true; + } + + bool CreateAttProjectileFromJson(const JsonAttProjectile& jProjectile, AttProjectile& projectile, const WeaponAttachment& attachment) const + { + projectile.explosionRadius = jProjectile.explosionRadius; + projectile.explosionInnerDamage = jProjectile.explosionInnerDamage; + projectile.explosionOuterDamage = jProjectile.explosionOuterDamage; + projectile.damageConeAngle = jProjectile.damageConeAngle; + projectile.projectileSpeed = jProjectile.projectileSpeed; + projectile.projectileSpeedUp = jProjectile.projectileSpeedUp; + projectile.projectileActivateDist = jProjectile.projectileActivateDist; + projectile.projectileLifetime = jProjectile.projectileLifetime; + + if (jProjectile.projectileModel) + { + if (!CreateXModelFromJson(jProjectile.projectileModel.value(), projectile.projectileModel, attachment)) + return false; + } + else + projectile.projectileModel = nullptr; + + projectile.projExplosionType = jProjectile.projExplosionType; + + if (jProjectile.projExplosionEffect) + { + if (!CreateFxFromJson(jProjectile.projExplosionEffect.value(), projectile.projExplosionEffect, attachment)) + return false; + } + else + projectile.projExplosionEffect = nullptr; + + projectile.projExplosionEffectForceNormalUp = jProjectile.projExplosionEffectForceNormalUp; + + if (jProjectile.projExplosionSound) + { + if (!CreateSoundFromJson(jProjectile.projExplosionSound.value(), projectile.projExplosionSound, attachment)) + return false; + } + else + projectile.projExplosionSound.name = nullptr; + + if (jProjectile.projDudEffect) + { + if (!CreateFxFromJson(jProjectile.projDudEffect.value(), projectile.projDudEffect, attachment)) + return false; + } + else + projectile.projDudEffect = nullptr; + + if (jProjectile.projDudSound) + { + if (!CreateSoundFromJson(jProjectile.projDudSound.value(), projectile.projDudSound, attachment)) + return false; + } + else + projectile.projDudSound.name = nullptr; + + projectile.projImpactExplode = jProjectile.projImpactExplode; + projectile.destabilizationRateTime = jProjectile.destabilizationRateTime; + projectile.destabilizationCurvatureMax = jProjectile.destabilizationCurvatureMax; + projectile.destabilizeDistance = jProjectile.destabilizeDistance; + + if (jProjectile.projTrailEffect) + { + if (!CreateFxFromJson(jProjectile.projTrailEffect.value(), projectile.projTrailEffect, attachment)) + return false; + } + else + projectile.projTrailEffect = nullptr; + + projectile.projIgnitionDelay = jProjectile.projIgnitionDelay; + + if (jProjectile.projIgnitionEffect) + { + if (!CreateFxFromJson(jProjectile.projIgnitionEffect.value(), projectile.projIgnitionEffect, attachment)) + return false; + } + else + projectile.projIgnitionEffect = nullptr; + + if (jProjectile.projIgnitionSound) + { + if (!CreateSoundFromJson(jProjectile.projIgnitionSound.value(), projectile.projIgnitionSound, attachment)) + return false; + } + else + projectile.projIgnitionSound.name = nullptr; + + return true; + } + + std::istream& m_stream; + MemoryManager& m_memory; + AssetCreationContext& m_context; + AssetRegistration& m_registration; + }; + class AttachmentLoader final : public AssetCreator { public: @@ -22,7 +642,7 @@ namespace AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - const auto file = m_search_path.Open(std::format("attachment/{}.json", assetName)); + const auto file = m_search_path.Open(attachment::GetJsonFileNameForAssetName(assetName)); if (!file.IsOpen()) return AssetCreationResult::NoAction(); @@ -30,7 +650,8 @@ namespace attachment->szInternalName = m_memory.Dup(assetName.c_str()); AssetRegistration registration(assetName, attachment); - if (!LoadWeaponAttachmentAsJson(*file.m_stream, *attachment, m_memory, context, registration)) + const JsonLoader loader(*file.m_stream, m_memory, context, registration); + if (!loader.Load(*attachment)) { std::cerr << std::format("Failed to load attachment \"{}\"\n", assetName); return AssetCreationResult::Failure(); @@ -45,10 +666,10 @@ namespace }; } // namespace -namespace IW5 +namespace attachment { - std::unique_ptr> CreateAttachmentLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace IW5 +} // namespace attachment diff --git a/src/ObjLoading/Game/IW5/Weapon/LoaderAttachmentIW5.h b/src/ObjLoading/Game/IW5/Weapon/LoaderAttachmentIW5.h index ec43ff96..5ba1c07e 100644 --- a/src/ObjLoading/Game/IW5/Weapon/LoaderAttachmentIW5.h +++ b/src/ObjLoading/Game/IW5/Weapon/LoaderAttachmentIW5.h @@ -7,7 +7,7 @@ #include -namespace IW5 +namespace attachment { - std::unique_ptr> CreateAttachmentLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace IW5 + std::unique_ptr> CreateLoaderIW5(MemoryManager& memory, ISearchPath& searchPath); +} // namespace attachment diff --git a/src/ObjLoading/Game/IW5/Weapon/RawLoaderWeaponIW5.cpp b/src/ObjLoading/Game/IW5/Weapon/RawLoaderWeaponIW5.cpp index 642efa2e..8d30bf2a 100644 --- a/src/ObjLoading/Game/IW5/Weapon/RawLoaderWeaponIW5.cpp +++ b/src/ObjLoading/Game/IW5/Weapon/RawLoaderWeaponIW5.cpp @@ -4,12 +4,14 @@ #include "Game/IW5/ObjConstantsIW5.h" #include "InfoString/InfoString.h" #include "InfoStringLoaderWeaponIW5.h" +#include "Weapon/WeaponCommon.h" #include #include #include using namespace IW5; +using namespace ::weapon; namespace { @@ -24,7 +26,7 @@ namespace AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - const auto fileName = std::format("weapons/{}", assetName); + const auto fileName = GetFileNameForAssetName(assetName); const auto file = m_search_path.Open(fileName); if (!file.IsOpen()) return AssetCreationResult::NoAction(); @@ -41,14 +43,14 @@ namespace private: ISearchPath& m_search_path; - InfoStringLoaderWeapon m_info_string_loader; + weapon::InfoStringLoaderIW5 m_info_string_loader; }; } // namespace -namespace IW5 +namespace weapon { - std::unique_ptr> CreateRawWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + std::unique_ptr> CreateRawLoaderIW5(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) { return std::make_unique(memory, searchPath, zone); } -} // namespace IW5 +} // namespace weapon diff --git a/src/ObjLoading/Game/IW5/Weapon/RawLoaderWeaponIW5.h b/src/ObjLoading/Game/IW5/Weapon/RawLoaderWeaponIW5.h index d5df5fcf..88b8053a 100644 --- a/src/ObjLoading/Game/IW5/Weapon/RawLoaderWeaponIW5.h +++ b/src/ObjLoading/Game/IW5/Weapon/RawLoaderWeaponIW5.h @@ -7,7 +7,7 @@ #include -namespace IW5 +namespace weapon { - std::unique_ptr> CreateRawWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); -} // namespace IW5 + std::unique_ptr> CreateRawLoaderIW5(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace weapon diff --git a/src/ObjLoading/Game/T5/Localize/LoaderLocalizeT5.cpp b/src/ObjLoading/Game/T5/Localize/LoaderLocalizeT5.cpp index 175b71fb..c66a7f93 100644 --- a/src/ObjLoading/Game/T5/Localize/LoaderLocalizeT5.cpp +++ b/src/ObjLoading/Game/T5/Localize/LoaderLocalizeT5.cpp @@ -35,10 +35,10 @@ namespace }; } // namespace -namespace T5 +namespace localize { - std::unique_ptr> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + std::unique_ptr> CreateLoaderT5(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) { return std::make_unique(memory, searchPath, zone); } -} // namespace T5 +} // namespace localize diff --git a/src/ObjLoading/Game/T5/Localize/LoaderLocalizeT5.h b/src/ObjLoading/Game/T5/Localize/LoaderLocalizeT5.h index fd71deb5..a6d14d5e 100644 --- a/src/ObjLoading/Game/T5/Localize/LoaderLocalizeT5.h +++ b/src/ObjLoading/Game/T5/Localize/LoaderLocalizeT5.h @@ -8,7 +8,7 @@ #include -namespace T5 +namespace localize { - std::unique_ptr> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); -} // namespace T5 + std::unique_ptr> CreateLoaderT5(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace localize diff --git a/src/ObjLoading/Game/T5/Material/LoaderMaterialT5.cpp b/src/ObjLoading/Game/T5/Material/LoaderMaterialT5.cpp index a362e728..093f5e04 100644 --- a/src/ObjLoading/Game/T5/Material/LoaderMaterialT5.cpp +++ b/src/ObjLoading/Game/T5/Material/LoaderMaterialT5.cpp @@ -45,10 +45,10 @@ namespace }; } // namespace -namespace T5 +namespace material { - std::unique_ptr> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderT5(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace T5 +} // namespace material diff --git a/src/ObjLoading/Game/T5/Material/LoaderMaterialT5.h b/src/ObjLoading/Game/T5/Material/LoaderMaterialT5.h index 22c337ff..8b11165a 100644 --- a/src/ObjLoading/Game/T5/Material/LoaderMaterialT5.h +++ b/src/ObjLoading/Game/T5/Material/LoaderMaterialT5.h @@ -6,7 +6,7 @@ #include "SearchPath/ISearchPath.h" #include "Utils/MemoryManager.h" -namespace T5 +namespace material { - std::unique_ptr> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace T5 + std::unique_ptr> CreateLoaderT5(MemoryManager& memory, ISearchPath& searchPath); +} // namespace material diff --git a/src/ObjLoading/Game/T5/ObjLoaderT5.cpp b/src/ObjLoading/Game/T5/ObjLoaderT5.cpp index f877d17c..cc67cc5a 100644 --- a/src/ObjLoading/Game/T5/ObjLoaderT5.cpp +++ b/src/ObjLoading/Game/T5/ObjLoaderT5.cpp @@ -104,8 +104,8 @@ namespace // 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(xmodel::CreateLoaderT5(memory, searchPath, zone)); + collection.AddAssetCreator(material::CreateLoaderT5(memory, searchPath)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); @@ -120,13 +120,13 @@ namespace // 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(localize::CreateLoaderT5(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(raw_file::CreateLoaderT5(memory, searchPath)); + collection.AddAssetCreator(string_table::CreateLoaderT5(memory, searchPath)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); diff --git a/src/ObjLoading/Game/T5/RawFile/LoaderRawFileT5.cpp b/src/ObjLoading/Game/T5/RawFile/LoaderRawFileT5.cpp index ec7ec152..f261f06f 100644 --- a/src/ObjLoading/Game/T5/RawFile/LoaderRawFileT5.cpp +++ b/src/ObjLoading/Game/T5/RawFile/LoaderRawFileT5.cpp @@ -114,10 +114,10 @@ namespace }; } // namespace -namespace T5 +namespace raw_file { - std::unique_ptr> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderT5(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace T5 +} // namespace raw_file diff --git a/src/ObjLoading/Game/T5/RawFile/LoaderRawFileT5.h b/src/ObjLoading/Game/T5/RawFile/LoaderRawFileT5.h index 42e83ed3..ba06bd12 100644 --- a/src/ObjLoading/Game/T5/RawFile/LoaderRawFileT5.h +++ b/src/ObjLoading/Game/T5/RawFile/LoaderRawFileT5.h @@ -7,7 +7,7 @@ #include -namespace T5 +namespace raw_file { - std::unique_ptr> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace T5 + std::unique_ptr> CreateLoaderT5(MemoryManager& memory, ISearchPath& searchPath); +} // namespace raw_file diff --git a/src/ObjLoading/Game/T5/StringTable/LoaderStringTableT5.cpp b/src/ObjLoading/Game/T5/StringTable/LoaderStringTableT5.cpp index f50b423a..b1085572 100644 --- a/src/ObjLoading/Game/T5/StringTable/LoaderStringTableT5.cpp +++ b/src/ObjLoading/Game/T5/StringTable/LoaderStringTableT5.cpp @@ -37,10 +37,10 @@ namespace }; } // namespace -namespace T5 +namespace string_table { - std::unique_ptr> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderT5(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace T5 +} // namespace string_table diff --git a/src/ObjLoading/Game/T5/StringTable/LoaderStringTableT5.h b/src/ObjLoading/Game/T5/StringTable/LoaderStringTableT5.h index 3479639b..81146e31 100644 --- a/src/ObjLoading/Game/T5/StringTable/LoaderStringTableT5.h +++ b/src/ObjLoading/Game/T5/StringTable/LoaderStringTableT5.h @@ -7,7 +7,7 @@ #include -namespace T5 +namespace string_table { - std::unique_ptr> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace T5 + std::unique_ptr> CreateLoaderT5(MemoryManager& memory, ISearchPath& searchPath); +} // namespace string_table diff --git a/src/ObjLoading/Game/T6/FontIcon/CsvLoaderFontIconT6.cpp b/src/ObjLoading/Game/T6/FontIcon/CsvLoaderFontIconT6.cpp index ca53435b..4d135cf3 100644 --- a/src/ObjLoading/Game/T6/FontIcon/CsvLoaderFontIconT6.cpp +++ b/src/ObjLoading/Game/T6/FontIcon/CsvLoaderFontIconT6.cpp @@ -282,10 +282,10 @@ namespace }; } // namespace -namespace T6 +namespace font_icon { - std::unique_ptr> CreateCsvFontIconLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateCsvLoaderT6(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace T6 +} // namespace font_icon diff --git a/src/ObjLoading/Game/T6/FontIcon/CsvLoaderFontIconT6.h b/src/ObjLoading/Game/T6/FontIcon/CsvLoaderFontIconT6.h index 7bb1e58f..ea6d60a2 100644 --- a/src/ObjLoading/Game/T6/FontIcon/CsvLoaderFontIconT6.h +++ b/src/ObjLoading/Game/T6/FontIcon/CsvLoaderFontIconT6.h @@ -7,7 +7,7 @@ #include -namespace T6 +namespace font_icon { - std::unique_ptr> CreateCsvFontIconLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace T6 + std::unique_ptr> CreateCsvLoaderT6(MemoryManager& memory, ISearchPath& searchPath); +} // namespace font_icon diff --git a/src/ObjLoading/Game/T6/FontIcon/JsonLoaderFontIconT6.cpp b/src/ObjLoading/Game/T6/FontIcon/JsonLoaderFontIconT6.cpp index 002e778c..fe909307 100644 --- a/src/ObjLoading/Game/T6/FontIcon/JsonLoaderFontIconT6.cpp +++ b/src/ObjLoading/Game/T6/FontIcon/JsonLoaderFontIconT6.cpp @@ -1,7 +1,7 @@ #include "JsonLoaderFontIconT6.h" +#include "FontIcon/FontIconCommon.h" #include "Game/T6/CommonT6.h" -#include "Game/T6/FontIcon/FontIconCommonT6.h" #include "Game/T6/FontIcon/JsonFontIconT6.h" #include "Game/T6/T6.h" @@ -141,10 +141,10 @@ namespace }; } // namespace -namespace T6 +namespace font_icon { - std::unique_ptr> CreateJsonFontIconLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateJsonLoaderT6(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace T6 +} // namespace font_icon diff --git a/src/ObjLoading/Game/T6/FontIcon/JsonLoaderFontIconT6.h b/src/ObjLoading/Game/T6/FontIcon/JsonLoaderFontIconT6.h index 7938827a..262354df 100644 --- a/src/ObjLoading/Game/T6/FontIcon/JsonLoaderFontIconT6.h +++ b/src/ObjLoading/Game/T6/FontIcon/JsonLoaderFontIconT6.h @@ -7,7 +7,7 @@ #include -namespace T6 +namespace font_icon { - std::unique_ptr> CreateJsonFontIconLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace T6 + std::unique_ptr> CreateJsonLoaderT6(MemoryManager& memory, ISearchPath& searchPath); +} // namespace font_icon diff --git a/src/ObjLoading/Game/T6/Image/LoaderImageT6.cpp b/src/ObjLoading/Game/T6/Image/LoaderImageT6.cpp index 5c26a32d..0c618792 100644 --- a/src/ObjLoading/Game/T6/Image/LoaderImageT6.cpp +++ b/src/ObjLoading/Game/T6/Image/LoaderImageT6.cpp @@ -2,6 +2,7 @@ #include "Game/T6/CommonT6.h" #include "Game/T6/T6.h" +#include "Image/ImageCommon.h" #include "Image/IwiLoader.h" #include @@ -25,7 +26,7 @@ namespace AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - const auto fileName = std::format("images/{}.iwi", assetName); + const auto fileName = image::GetFileNameForAsset(assetName, ".iwi"); const auto file = m_search_path.Open(fileName); if (!file.IsOpen()) return AssetCreationResult::NoAction(); @@ -68,10 +69,10 @@ namespace }; } // namespace -namespace T6 +namespace image { - std::unique_ptr> CreateImageLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace T6 +} // namespace image diff --git a/src/ObjLoading/Game/T6/Image/LoaderImageT6.h b/src/ObjLoading/Game/T6/Image/LoaderImageT6.h index 6c1bfb1f..610af102 100644 --- a/src/ObjLoading/Game/T6/Image/LoaderImageT6.h +++ b/src/ObjLoading/Game/T6/Image/LoaderImageT6.h @@ -7,7 +7,7 @@ #include -namespace T6 +namespace image { - std::unique_ptr> CreateImageLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace T6 + std::unique_ptr> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath); +} // namespace image diff --git a/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.h b/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.h deleted file mode 100644 index 6145d04d..00000000 --- a/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "Game/T6/T6.h" -#include "Utils/MemoryManager.h" - -#include - -namespace T6 -{ - bool LoadLeaderboardAsJson(std::istream& stream, LeaderboardDef& leaderboard, MemoryManager& memory); -} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp b/src/ObjLoading/Game/T6/Leaderboard/JsonLoaderLeaderboardT6.cpp similarity index 73% rename from src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp rename to src/ObjLoading/Game/T6/Leaderboard/JsonLoaderLeaderboardT6.cpp index b4f7823f..3a8415ec 100644 --- a/src/ObjLoading/Game/T6/Leaderboard/JsonLeaderboardDefLoader.cpp +++ b/src/ObjLoading/Game/T6/Leaderboard/JsonLoaderLeaderboardT6.cpp @@ -1,8 +1,11 @@ -#include "JsonLeaderboardDefLoader.h" +#include "JsonLoaderLeaderboardT6.h" #include "Game/T6/CommonT6.h" #include "Game/T6/Leaderboard/JsonLeaderboardDef.h" +#include "Game/T6/T6.h" +#include "Leaderboard/LeaderboardCommon.h" +#include #include #include #include @@ -124,13 +127,45 @@ namespace std::istream& m_stream; MemoryManager& m_memory; }; + + 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(leaderboard::GetJsonFileNameForAsset(assetName)); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + auto* leaderboardDef = m_memory.Alloc(); + leaderboardDef->name = m_memory.Dup(assetName.c_str()); + + const JsonLoader loader(*file.m_stream, m_memory); + if (!loader.Load(*leaderboardDef)) + { + 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 +namespace leaderboard { - bool LoadLeaderboardAsJson(std::istream& stream, LeaderboardDef& leaderboard, MemoryManager& memory) + std::unique_ptr> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath) { - const JsonLoader loader(stream, memory); - return loader.Load(leaderboard); + return std::make_unique(memory, searchPath); } -} // namespace T6 +} // namespace leaderboard diff --git a/src/ObjLoading/Game/T6/Leaderboard/JsonLoaderLeaderboardT6.h b/src/ObjLoading/Game/T6/Leaderboard/JsonLoaderLeaderboardT6.h new file mode 100644 index 00000000..cbe7c604 --- /dev/null +++ b/src/ObjLoading/Game/T6/Leaderboard/JsonLoaderLeaderboardT6.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 leaderboard +{ + std::unique_ptr> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath); +} // namespace leaderboard diff --git a/src/ObjLoading/Game/T6/Leaderboard/LoaderLeaderboardT6.cpp b/src/ObjLoading/Game/T6/Leaderboard/LoaderLeaderboardT6.cpp deleted file mode 100644 index ae08c020..00000000 --- a/src/ObjLoading/Game/T6/Leaderboard/LoaderLeaderboardT6.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#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/Localize/LoaderLocalizeT6.cpp b/src/ObjLoading/Game/T6/Localize/LocalizeLoaderT6.cpp similarity index 86% rename from src/ObjLoading/Game/T6/Localize/LoaderLocalizeT6.cpp rename to src/ObjLoading/Game/T6/Localize/LocalizeLoaderT6.cpp index c4a3b77d..a51abb2f 100644 --- a/src/ObjLoading/Game/T6/Localize/LoaderLocalizeT6.cpp +++ b/src/ObjLoading/Game/T6/Localize/LocalizeLoaderT6.cpp @@ -1,4 +1,4 @@ -#include "LoaderLocalizeT6.h" +#include "LocalizeLoaderT6.h" #include "Localize/CommonLocalizeLoader.h" @@ -35,10 +35,10 @@ namespace }; } // namespace -namespace T6 +namespace localize { - std::unique_ptr> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + std::unique_ptr> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) { return std::make_unique(memory, searchPath, zone); } -} // namespace T6 +} // namespace localize diff --git a/src/ObjLoading/Game/T6/Localize/LoaderLocalizeT6.h b/src/ObjLoading/Game/T6/Localize/LocalizeLoaderT6.h similarity index 51% rename from src/ObjLoading/Game/T6/Localize/LoaderLocalizeT6.h rename to src/ObjLoading/Game/T6/Localize/LocalizeLoaderT6.h index 991f53b1..dc7f49eb 100644 --- a/src/ObjLoading/Game/T6/Localize/LoaderLocalizeT6.h +++ b/src/ObjLoading/Game/T6/Localize/LocalizeLoaderT6.h @@ -8,7 +8,7 @@ #include -namespace T6 +namespace localize { - std::unique_ptr> CreateLocalizeLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); -} // namespace T6 + std::unique_ptr> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace localize diff --git a/src/ObjLoading/Game/T6/Material/LoaderMaterialT6.cpp b/src/ObjLoading/Game/T6/Material/LoaderMaterialT6.cpp index 5458b96e..82e3649b 100644 --- a/src/ObjLoading/Game/T6/Material/LoaderMaterialT6.cpp +++ b/src/ObjLoading/Game/T6/Material/LoaderMaterialT6.cpp @@ -45,10 +45,10 @@ namespace }; } // namespace -namespace T6 +namespace material { - std::unique_ptr> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace T6 +} // namespace material diff --git a/src/ObjLoading/Game/T6/Material/LoaderMaterialT6.h b/src/ObjLoading/Game/T6/Material/LoaderMaterialT6.h index 22cd78dc..af1a1f92 100644 --- a/src/ObjLoading/Game/T6/Material/LoaderMaterialT6.h +++ b/src/ObjLoading/Game/T6/Material/LoaderMaterialT6.h @@ -7,7 +7,7 @@ #include -namespace T6 +namespace material { - std::unique_ptr> CreateMaterialLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace T6 + std::unique_ptr> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath); +} // namespace material diff --git a/src/ObjLoading/Game/T6/ObjLoaderT6.cpp b/src/ObjLoading/Game/T6/ObjLoaderT6.cpp index a1f029f3..9281a38b 100644 --- a/src/ObjLoading/Game/T6/ObjLoaderT6.cpp +++ b/src/ObjLoading/Game/T6/ObjLoaderT6.cpp @@ -13,8 +13,8 @@ #include "Image/IwiTypes.h" #include "Image/LoaderImageT6.h" #include "Image/Texture.h" -#include "Leaderboard/LoaderLeaderboardT6.h" -#include "Localize/LoaderLocalizeT6.h" +#include "Leaderboard/JsonLoaderLeaderboardT6.h" +#include "Localize/LocalizeLoaderT6.h" #include "Material/LoaderMaterialT6.h" #include "ObjContainer/IPak/IPak.h" #include "ObjLoading.h" @@ -32,13 +32,13 @@ #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 "Weapon/AttachmentGdtLoaderT6.h" +#include "Weapon/AttachmentRawLoaderT6.h" +#include "Weapon/AttachmentUniqueGdtLoaderT6.h" +#include "Weapon/AttachmentUniqueRawLoaderT6.h" +#include "Weapon/CamoJsonLoaderT6.h" +#include "Weapon/WeaponGdtLoaderT6.h" +#include "Weapon/WeaponRawLoaderT6.h" #include "ZBarrier/GdtLoaderZBarrierT6.h" #include "ZBarrier/RawLoaderZBarrierT6.h" @@ -393,17 +393,17 @@ namespace T6 { auto& memory = zone.Memory(); - 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(phys_preset::CreateRawLoaderT6(memory, searchPath, zone)); + collection.AddAssetCreator(phys_preset::CreateGdtLoaderT6(memory, gdt, zone)); + collection.AddAssetCreator(phys_constraints::CreateRawLoaderT6(memory, searchPath, zone)); + collection.AddAssetCreator(phys_constraints::CreateGdtLoaderT6(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(xmodel::CreateLoaderT6(memory, searchPath, zone)); + collection.AddAssetCreator(material::CreateLoaderT6(memory, searchPath)); // collection.AddAssetCreator(std::make_unique(memory)); - collection.AddAssetCreator(CreateImageLoader(memory, searchPath)); - collection.AddAssetCreator(CreateSoundBankLoader(memory, searchPath)); + collection.AddAssetCreator(image::CreateLoaderT6(memory, searchPath)); + collection.AddAssetCreator(sound::CreateSoundBankLoaderT6(memory, searchPath)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); @@ -413,41 +413,41 @@ namespace T6 // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); - collection.AddAssetCreator(CreateCsvFontIconLoader(memory, searchPath)); - collection.AddAssetCreator(CreateJsonFontIconLoader(memory, searchPath)); + collection.AddAssetCreator(font_icon::CreateCsvLoaderT6(memory, searchPath)); + collection.AddAssetCreator(font_icon::CreateJsonLoaderT6(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(localize::CreateLoaderT6(memory, searchPath, zone)); + collection.AddAssetCreator(weapon::CreateRawLoaderT6(memory, searchPath, zone)); + collection.AddAssetCreator(weapon::CreateGdtLoaderT6(memory, searchPath, gdt, zone)); + collection.AddAssetCreator(attachment::CreateRawLoaderT6(memory, searchPath, zone)); + collection.AddAssetCreator(attachment::CreateGdtLoaderT6(memory, searchPath, gdt, zone)); + collection.AddAssetCreator(attachment_unique::CreateRawLoaderT6(memory, searchPath, zone)); + collection.AddAssetCreator(attachment_unique::CreateGdtLoaderT6(memory, searchPath, gdt, zone)); + collection.AddAssetCreator(camo::CreateJsonLoaderT6(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(raw_file::CreateLoaderT6(memory, searchPath)); + collection.AddAssetCreator(string_table::CreateLoaderT6(memory, searchPath)); + collection.AddAssetCreator(leaderboard::CreateLoaderT6(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(script::CreateLoaderT6(memory, searchPath)); + collection.AddAssetCreator(vehicle::CreateRawLoaderT6(memory, searchPath, zone)); + collection.AddAssetCreator(vehicle::CreateGdtLoaderT6(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(qdb::CreateLoaderT6(memory, searchPath)); + collection.AddAssetCreator(slug::CreateLoaderT6(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)); + collection.AddAssetCreator(z_barrier::CreateRawLoaderT6(memory, searchPath, zone)); + collection.AddAssetCreator(z_barrier::CreateGdtLoaderT6(memory, searchPath, gdt, zone)); } } // namespace diff --git a/src/ObjLoading/Game/T6/PhysConstraints/GdtLoaderPhysConstraintsT6.cpp b/src/ObjLoading/Game/T6/PhysConstraints/GdtLoaderPhysConstraintsT6.cpp index d6c35c5d..3b033248 100644 --- a/src/ObjLoading/Game/T6/PhysConstraints/GdtLoaderPhysConstraintsT6.cpp +++ b/src/ObjLoading/Game/T6/PhysConstraints/GdtLoaderPhysConstraintsT6.cpp @@ -40,15 +40,14 @@ namespace private: IGdtQueryable& m_gdt; - InfoStringLoaderPhysConstraints m_info_string_loader; + phys_constraints::InfoStringLoaderT6 m_info_string_loader; }; } // namespace -namespace T6 +namespace phys_constraints { - std::unique_ptr> - CreateGdtPhysConstraintsLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + std::unique_ptr> CreateGdtLoaderT6(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) { return std::make_unique(memory, searchPath, gdt, zone); } -} // namespace T6 +} // namespace phys_constraints diff --git a/src/ObjLoading/Game/T6/PhysConstraints/GdtLoaderPhysConstraintsT6.h b/src/ObjLoading/Game/T6/PhysConstraints/GdtLoaderPhysConstraintsT6.h index 45b70188..c35e49bd 100644 --- a/src/ObjLoading/Game/T6/PhysConstraints/GdtLoaderPhysConstraintsT6.h +++ b/src/ObjLoading/Game/T6/PhysConstraints/GdtLoaderPhysConstraintsT6.h @@ -8,8 +8,7 @@ #include -namespace T6 +namespace phys_constraints { - std::unique_ptr> - CreateGdtPhysConstraintsLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); -} // namespace T6 + std::unique_ptr> CreateGdtLoaderT6(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); +} // namespace phys_constraints diff --git a/src/ObjLoading/Game/T6/PhysConstraints/InfoStringLoaderPhysConstraintsT6.cpp b/src/ObjLoading/Game/T6/PhysConstraints/InfoStringLoaderPhysConstraintsT6.cpp index ab29df7e..525d9771 100644 --- a/src/ObjLoading/Game/T6/PhysConstraints/InfoStringLoaderPhysConstraintsT6.cpp +++ b/src/ObjLoading/Game/T6/PhysConstraints/InfoStringLoaderPhysConstraintsT6.cpp @@ -76,35 +76,38 @@ namespace } } // namespace -InfoStringLoaderPhysConstraints::InfoStringLoaderPhysConstraints(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) - : m_memory(memory), - m_search_path(searchPath), - m_zone(zone) +namespace phys_constraints { -} - -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()) + InfoStringLoaderT6::InfoStringLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_memory(memory), + m_search_path(searchPath), + m_zone(zone) { - 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("")); + AssetCreationResult InfoStringLoaderT6::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) + { + auto* physConstraints = m_memory.Alloc(); + physConstraints->name = m_memory.Dup(assetName.c_str()); - return AssetCreationResult::Success(context.AddAsset(std::move(registration))); -} + 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))); + } +} // namespace phys_constraints diff --git a/src/ObjLoading/Game/T6/PhysConstraints/InfoStringLoaderPhysConstraintsT6.h b/src/ObjLoading/Game/T6/PhysConstraints/InfoStringLoaderPhysConstraintsT6.h index dbebb186..134b3500 100644 --- a/src/ObjLoading/Game/T6/PhysConstraints/InfoStringLoaderPhysConstraintsT6.h +++ b/src/ObjLoading/Game/T6/PhysConstraints/InfoStringLoaderPhysConstraintsT6.h @@ -4,12 +4,12 @@ #include "Asset/AssetCreationResult.h" #include "InfoString/InfoString.h" -namespace T6 +namespace phys_constraints { - class InfoStringLoaderPhysConstraints + class InfoStringLoaderT6 { public: - InfoStringLoaderPhysConstraints(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); + InfoStringLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); AssetCreationResult CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context); @@ -18,4 +18,4 @@ namespace T6 ISearchPath& m_search_path; Zone& m_zone; }; -} // namespace T6 +} // namespace phys_constraints diff --git a/src/ObjLoading/Game/T6/PhysConstraints/RawLoaderPhysConstraintsT6.cpp b/src/ObjLoading/Game/T6/PhysConstraints/RawLoaderPhysConstraintsT6.cpp index 607a3c82..a4edbb53 100644 --- a/src/ObjLoading/Game/T6/PhysConstraints/RawLoaderPhysConstraintsT6.cpp +++ b/src/ObjLoading/Game/T6/PhysConstraints/RawLoaderPhysConstraintsT6.cpp @@ -4,6 +4,7 @@ #include "Game/T6/T6.h" #include "InfoString/InfoString.h" #include "InfoStringLoaderPhysConstraintsT6.h" +#include "PhysConstraints/PhysConstraintsCommon.h" #include #include @@ -24,7 +25,7 @@ namespace AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - const auto fileName = std::format("physconstraints/{}", assetName); + const auto fileName = phys_constraints::GetFileNameForAssetName(assetName); const auto file = m_search_path.Open(fileName); if (!file.IsOpen()) return AssetCreationResult::NoAction(); @@ -41,14 +42,14 @@ namespace private: ISearchPath& m_search_path; - InfoStringLoaderPhysConstraints m_info_string_loader; + phys_constraints::InfoStringLoaderT6 m_info_string_loader; }; } // namespace -namespace T6 +namespace phys_constraints { - std::unique_ptr> CreateRawPhysConstraintsLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + std::unique_ptr> CreateRawLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) { return std::make_unique(memory, searchPath, zone); } -} // namespace T6 +} // namespace phys_constraints diff --git a/src/ObjLoading/Game/T6/PhysConstraints/RawLoaderPhysConstraintsT6.h b/src/ObjLoading/Game/T6/PhysConstraints/RawLoaderPhysConstraintsT6.h index dc88bc45..33342687 100644 --- a/src/ObjLoading/Game/T6/PhysConstraints/RawLoaderPhysConstraintsT6.h +++ b/src/ObjLoading/Game/T6/PhysConstraints/RawLoaderPhysConstraintsT6.h @@ -7,7 +7,7 @@ #include -namespace T6 +namespace phys_constraints { - std::unique_ptr> CreateRawPhysConstraintsLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); -} // namespace T6 + std::unique_ptr> CreateRawLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace phys_constraints diff --git a/src/ObjLoading/Game/T6/PhysPreset/GdtLoaderPhysPresetT6.cpp b/src/ObjLoading/Game/T6/PhysPreset/GdtLoaderPhysPresetT6.cpp index 9d7f179f..36679dab 100644 --- a/src/ObjLoading/Game/T6/PhysPreset/GdtLoaderPhysPresetT6.cpp +++ b/src/ObjLoading/Game/T6/PhysPreset/GdtLoaderPhysPresetT6.cpp @@ -16,15 +16,15 @@ namespace class GdtLoaderPhysPreset final : public AssetCreator { public: - GdtLoaderPhysPreset(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + GdtLoaderPhysPreset(MemoryManager& memory, IGdtQueryable& gdt, Zone& zone) : m_gdt(gdt), - m_info_string_loader(memory, searchPath, zone) + m_info_string_loader(memory, zone) { } AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - const auto* gdtEntry = m_gdt.GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_WEAPON, assetName); + const auto* gdtEntry = m_gdt.GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_PHYS_PRESET, assetName); if (gdtEntry == nullptr) return AssetCreationResult::NoAction(); @@ -40,14 +40,14 @@ namespace private: IGdtQueryable& m_gdt; - InfoStringLoaderPhysPreset m_info_string_loader; + phys_preset::InfoStringLoaderT6 m_info_string_loader; }; } // namespace -namespace T6 +namespace phys_preset { - std::unique_ptr> CreateGdtPhysPresetLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + std::unique_ptr> CreateGdtLoaderT6(MemoryManager& memory, IGdtQueryable& gdt, Zone& zone) { - return std::make_unique(memory, searchPath, gdt, zone); + return std::make_unique(memory, gdt, zone); } -} // namespace T6 +} // namespace phys_preset diff --git a/src/ObjLoading/Game/T6/PhysPreset/GdtLoaderPhysPresetT6.h b/src/ObjLoading/Game/T6/PhysPreset/GdtLoaderPhysPresetT6.h index c2fdbe8d..bc167205 100644 --- a/src/ObjLoading/Game/T6/PhysPreset/GdtLoaderPhysPresetT6.h +++ b/src/ObjLoading/Game/T6/PhysPreset/GdtLoaderPhysPresetT6.h @@ -8,7 +8,7 @@ #include -namespace T6 +namespace phys_preset { - std::unique_ptr> CreateGdtPhysPresetLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); -} // namespace T6 + std::unique_ptr> CreateGdtLoaderT6(MemoryManager& memory, IGdtQueryable& gdt, Zone& zone); +} // namespace phys_preset diff --git a/src/ObjLoading/Game/T6/PhysPreset/InfoStringLoaderPhysPresetT6.cpp b/src/ObjLoading/Game/T6/PhysPreset/InfoStringLoaderPhysPresetT6.cpp index fbd2b9d2..6e996ad1 100644 --- a/src/ObjLoading/Game/T6/PhysPreset/InfoStringLoaderPhysPresetT6.cpp +++ b/src/ObjLoading/Game/T6/PhysPreset/InfoStringLoaderPhysPresetT6.cpp @@ -60,31 +60,39 @@ namespace } } // namespace -InfoStringLoaderPhysPreset::InfoStringLoaderPhysPreset(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) - : m_memory(memory), - m_search_path(searchPath), - m_zone(zone) +namespace phys_preset { -} - -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()) + InfoStringLoaderT6::InfoStringLoaderT6(MemoryManager& memory, Zone& zone) + : m_memory(memory), + m_zone(zone) { - std::cerr << std::format("Failed to parse phys preset: \"{}\"\n", assetName); - return AssetCreationResult::Failure(); } - CopyFromPhysPresetInfo(physPresetInfo, *physPreset); + AssetCreationResult InfoStringLoaderT6::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) + { + auto* physPreset = m_memory.Alloc(); + physPreset->name = m_memory.Dup(assetName.c_str()); - return AssetCreationResult::Success(context.AddAsset(std::move(registration))); -} + 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))); + } +} // namespace phys_preset diff --git a/src/ObjLoading/Game/T6/PhysPreset/InfoStringLoaderPhysPresetT6.h b/src/ObjLoading/Game/T6/PhysPreset/InfoStringLoaderPhysPresetT6.h index 3e214d60..06e10b2f 100644 --- a/src/ObjLoading/Game/T6/PhysPreset/InfoStringLoaderPhysPresetT6.h +++ b/src/ObjLoading/Game/T6/PhysPreset/InfoStringLoaderPhysPresetT6.h @@ -4,18 +4,17 @@ #include "Asset/AssetCreationResult.h" #include "InfoString/InfoString.h" -namespace T6 +namespace phys_preset { - class InfoStringLoaderPhysPreset + class InfoStringLoaderT6 { public: - InfoStringLoaderPhysPreset(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); + InfoStringLoaderT6(MemoryManager& memory, 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 +} // namespace phys_preset diff --git a/src/ObjLoading/Game/T6/PhysPreset/RawLoaderPhysPresetT6.cpp b/src/ObjLoading/Game/T6/PhysPreset/RawLoaderPhysPresetT6.cpp index 4fe78db8..46430470 100644 --- a/src/ObjLoading/Game/T6/PhysPreset/RawLoaderPhysPresetT6.cpp +++ b/src/ObjLoading/Game/T6/PhysPreset/RawLoaderPhysPresetT6.cpp @@ -4,6 +4,7 @@ #include "Game/T6/T6.h" #include "InfoString/InfoString.h" #include "InfoStringLoaderPhysPresetT6.h" +#include "PhysPreset/PhysPresetCommon.h" #include #include @@ -18,13 +19,13 @@ namespace public: RawLoaderPhysPreset(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) : m_search_path(searchPath), - m_info_string_loader(memory, searchPath, zone) + m_info_string_loader(memory, zone) { } AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - const auto fileName = std::format("physic/{}", assetName); + const auto fileName = phys_preset::GetFileNameForAssetName(assetName); const auto file = m_search_path.Open(fileName); if (!file.IsOpen()) return AssetCreationResult::NoAction(); @@ -41,14 +42,14 @@ namespace private: ISearchPath& m_search_path; - InfoStringLoaderPhysPreset m_info_string_loader; + phys_preset::InfoStringLoaderT6 m_info_string_loader; }; } // namespace -namespace T6 +namespace phys_preset { - std::unique_ptr> CreateRawPhysPresetLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + std::unique_ptr> CreateRawLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) { return std::make_unique(memory, searchPath, zone); } -} // namespace T6 +} // namespace phys_preset diff --git a/src/ObjLoading/Game/T6/PhysPreset/RawLoaderPhysPresetT6.h b/src/ObjLoading/Game/T6/PhysPreset/RawLoaderPhysPresetT6.h index 44070d9b..f319a936 100644 --- a/src/ObjLoading/Game/T6/PhysPreset/RawLoaderPhysPresetT6.h +++ b/src/ObjLoading/Game/T6/PhysPreset/RawLoaderPhysPresetT6.h @@ -7,7 +7,7 @@ #include -namespace T6 +namespace phys_preset { - std::unique_ptr> CreateRawPhysPresetLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); -} // namespace T6 + std::unique_ptr> CreateRawLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace phys_preset diff --git a/src/ObjLoading/Game/T6/Qdb/LoaderQdbT6.cpp b/src/ObjLoading/Game/T6/Qdb/LoaderQdbT6.cpp index e00e88ac..e1327edc 100644 --- a/src/ObjLoading/Game/T6/Qdb/LoaderQdbT6.cpp +++ b/src/ObjLoading/Game/T6/Qdb/LoaderQdbT6.cpp @@ -44,10 +44,10 @@ namespace }; } // namespace -namespace T6 +namespace qdb { - std::unique_ptr> CreateQdbLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace T6 +} // namespace qdb diff --git a/src/ObjLoading/Game/T6/Qdb/LoaderQdbT6.h b/src/ObjLoading/Game/T6/Qdb/LoaderQdbT6.h index a8d5f9c9..17a44611 100644 --- a/src/ObjLoading/Game/T6/Qdb/LoaderQdbT6.h +++ b/src/ObjLoading/Game/T6/Qdb/LoaderQdbT6.h @@ -7,7 +7,7 @@ #include -namespace T6 +namespace qdb { - std::unique_ptr> CreateQdbLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace T6 + std::unique_ptr> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath); +} // namespace qdb diff --git a/src/ObjLoading/Game/T6/RawFile/LoaderRawFileT6.cpp b/src/ObjLoading/Game/T6/RawFile/LoaderRawFileT6.cpp index f3352243..8782da60 100644 --- a/src/ObjLoading/Game/T6/RawFile/LoaderRawFileT6.cpp +++ b/src/ObjLoading/Game/T6/RawFile/LoaderRawFileT6.cpp @@ -114,10 +114,10 @@ namespace }; } // namespace -namespace T6 +namespace raw_file { - std::unique_ptr> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace T6 +} // namespace raw_file diff --git a/src/ObjLoading/Game/T6/RawFile/LoaderRawFileT6.h b/src/ObjLoading/Game/T6/RawFile/LoaderRawFileT6.h index db44f9a5..1ef99df6 100644 --- a/src/ObjLoading/Game/T6/RawFile/LoaderRawFileT6.h +++ b/src/ObjLoading/Game/T6/RawFile/LoaderRawFileT6.h @@ -7,7 +7,7 @@ #include -namespace T6 +namespace raw_file { - std::unique_ptr> CreateRawFileLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace T6 + std::unique_ptr> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath); +} // namespace raw_file diff --git a/src/ObjLoading/Game/T6/Script/LoaderScriptT6.cpp b/src/ObjLoading/Game/T6/Script/LoaderScriptT6.cpp index 5d30b473..a7284bc7 100644 --- a/src/ObjLoading/Game/T6/Script/LoaderScriptT6.cpp +++ b/src/ObjLoading/Game/T6/Script/LoaderScriptT6.cpp @@ -44,10 +44,10 @@ namespace }; } // namespace -namespace T6 +namespace script { - std::unique_ptr> CreateScriptLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace T6 +} // namespace script diff --git a/src/ObjLoading/Game/T6/Script/LoaderScriptT6.h b/src/ObjLoading/Game/T6/Script/LoaderScriptT6.h index 754da2ec..ebaab5da 100644 --- a/src/ObjLoading/Game/T6/Script/LoaderScriptT6.h +++ b/src/ObjLoading/Game/T6/Script/LoaderScriptT6.h @@ -7,7 +7,7 @@ #include -namespace T6 +namespace script { - std::unique_ptr> CreateScriptLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace T6 + std::unique_ptr> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath); +} // namespace script diff --git a/src/ObjLoading/Game/T6/Slug/LoaderSlugT6.cpp b/src/ObjLoading/Game/T6/Slug/LoaderSlugT6.cpp index f527a521..cce61264 100644 --- a/src/ObjLoading/Game/T6/Slug/LoaderSlugT6.cpp +++ b/src/ObjLoading/Game/T6/Slug/LoaderSlugT6.cpp @@ -44,10 +44,10 @@ namespace }; } // namespace -namespace T6 +namespace slug { - std::unique_ptr> CreateSlugLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace T6 +} // namespace slug diff --git a/src/ObjLoading/Game/T6/Slug/LoaderSlugT6.h b/src/ObjLoading/Game/T6/Slug/LoaderSlugT6.h index 49da9e84..fefc89c1 100644 --- a/src/ObjLoading/Game/T6/Slug/LoaderSlugT6.h +++ b/src/ObjLoading/Game/T6/Slug/LoaderSlugT6.h @@ -7,7 +7,7 @@ #include -namespace T6 +namespace slug { - std::unique_ptr> CreateSlugLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace T6 + std::unique_ptr> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath); +} // namespace slug diff --git a/src/ObjLoading/Game/T6/Sound/LoaderSoundBankT6.cpp b/src/ObjLoading/Game/T6/Sound/LoaderSoundBankT6.cpp index f72d2a77..9b9b3781 100644 --- a/src/ObjLoading/Game/T6/Sound/LoaderSoundBankT6.cpp +++ b/src/ObjLoading/Game/T6/Sound/LoaderSoundBankT6.cpp @@ -1079,10 +1079,10 @@ namespace }; } // namespace -namespace T6 +namespace sound { - std::unique_ptr> CreateSoundBankLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateSoundBankLoaderT6(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace T6 +} // namespace sound diff --git a/src/ObjLoading/Game/T6/Sound/LoaderSoundBankT6.h b/src/ObjLoading/Game/T6/Sound/LoaderSoundBankT6.h index 6e99e962..358b7710 100644 --- a/src/ObjLoading/Game/T6/Sound/LoaderSoundBankT6.h +++ b/src/ObjLoading/Game/T6/Sound/LoaderSoundBankT6.h @@ -7,7 +7,7 @@ #include -namespace T6 +namespace sound { - std::unique_ptr> CreateSoundBankLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace T6 + std::unique_ptr> CreateSoundBankLoaderT6(MemoryManager& memory, ISearchPath& searchPath); +} // namespace sound diff --git a/src/ObjLoading/Game/T6/StringTable/LoaderStringTableT6.cpp b/src/ObjLoading/Game/T6/StringTable/LoaderStringTableT6.cpp index d9560241..d5e092d6 100644 --- a/src/ObjLoading/Game/T6/StringTable/LoaderStringTableT6.cpp +++ b/src/ObjLoading/Game/T6/StringTable/LoaderStringTableT6.cpp @@ -38,10 +38,10 @@ namespace }; } // namespace -namespace T6 +namespace string_table { - std::unique_ptr> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace T6 +} // namespace string_table diff --git a/src/ObjLoading/Game/T6/StringTable/LoaderStringTableT6.h b/src/ObjLoading/Game/T6/StringTable/LoaderStringTableT6.h index 7db144c6..bebd85b2 100644 --- a/src/ObjLoading/Game/T6/StringTable/LoaderStringTableT6.h +++ b/src/ObjLoading/Game/T6/StringTable/LoaderStringTableT6.h @@ -7,7 +7,7 @@ #include -namespace T6 +namespace string_table { - std::unique_ptr> CreateStringTableLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace T6 + std::unique_ptr> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath); +} // namespace string_table diff --git a/src/ObjLoading/Game/T6/Tracer/GdtLoaderTracerT6.cpp b/src/ObjLoading/Game/T6/Tracer/GdtLoaderTracerT6.cpp index ee7376ed..7cad238c 100644 --- a/src/ObjLoading/Game/T6/Tracer/GdtLoaderTracerT6.cpp +++ b/src/ObjLoading/Game/T6/Tracer/GdtLoaderTracerT6.cpp @@ -40,14 +40,14 @@ namespace private: IGdtQueryable& m_gdt; - InfoStringLoaderTracer m_info_string_loader; + tracer::InfoStringLoaderT6 m_info_string_loader; }; } // namespace -namespace T6 +namespace tracer { - std::unique_ptr> CreateGdtTracerLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + std::unique_ptr> CreateGdtLoaderT6(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) { return std::make_unique(memory, searchPath, gdt, zone); } -} // namespace T6 +} // namespace tracer diff --git a/src/ObjLoading/Game/T6/Tracer/GdtLoaderTracerT6.h b/src/ObjLoading/Game/T6/Tracer/GdtLoaderTracerT6.h index d3059ce3..e48dd81b 100644 --- a/src/ObjLoading/Game/T6/Tracer/GdtLoaderTracerT6.h +++ b/src/ObjLoading/Game/T6/Tracer/GdtLoaderTracerT6.h @@ -8,7 +8,7 @@ #include -namespace T6 +namespace tracer { - std::unique_ptr> CreateGdtTracerLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); -} // namespace T6 + std::unique_ptr> CreateGdtLoaderT6(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); +} // namespace tracer diff --git a/src/ObjLoading/Game/T6/Tracer/InfoStringLoaderTracerT6.cpp b/src/ObjLoading/Game/T6/Tracer/InfoStringLoaderTracerT6.cpp index 00c21757..e7bc4377 100644 --- a/src/ObjLoading/Game/T6/Tracer/InfoStringLoaderTracerT6.cpp +++ b/src/ObjLoading/Game/T6/Tracer/InfoStringLoaderTracerT6.cpp @@ -3,6 +3,7 @@ #include "Game/T6/InfoString/InfoStringToStructConverter.h" #include "Game/T6/T6.h" #include "Game/T6/Tracer/TracerFields.h" +#include "Tracer/TracerCommon.h" #include #include @@ -46,27 +47,31 @@ namespace }; } // namespace -InfoStringLoaderTracer::InfoStringLoaderTracer(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) - : m_memory(memory), - m_search_path(searchPath), - m_zone(zone) +namespace tracer { -} - -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()) + InfoStringLoaderT6::InfoStringLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_memory(memory), + m_search_path(searchPath), + m_zone(zone) { - std::cerr << std::format("Failed to parse tracer: \"{}\"\n", assetName); - return AssetCreationResult::Failure(); } - return AssetCreationResult::Success(context.AddAsset(std::move(registration))); -} + AssetCreationResult InfoStringLoaderT6::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))); + } + +} // namespace tracer diff --git a/src/ObjLoading/Game/T6/Tracer/InfoStringLoaderTracerT6.h b/src/ObjLoading/Game/T6/Tracer/InfoStringLoaderTracerT6.h index 141c8216..d5ace0a6 100644 --- a/src/ObjLoading/Game/T6/Tracer/InfoStringLoaderTracerT6.h +++ b/src/ObjLoading/Game/T6/Tracer/InfoStringLoaderTracerT6.h @@ -4,12 +4,12 @@ #include "Asset/AssetCreationResult.h" #include "InfoString/InfoString.h" -namespace T6 +namespace tracer { - class InfoStringLoaderTracer + class InfoStringLoaderT6 { public: - InfoStringLoaderTracer(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); + InfoStringLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); AssetCreationResult CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context); @@ -18,4 +18,4 @@ namespace T6 ISearchPath& m_search_path; Zone& m_zone; }; -} // namespace T6 +} // namespace tracer diff --git a/src/ObjLoading/Game/T6/Tracer/RawLoaderTracerT6.cpp b/src/ObjLoading/Game/T6/Tracer/RawLoaderTracerT6.cpp index 16eb7ea9..ff3fdc42 100644 --- a/src/ObjLoading/Game/T6/Tracer/RawLoaderTracerT6.cpp +++ b/src/ObjLoading/Game/T6/Tracer/RawLoaderTracerT6.cpp @@ -4,6 +4,7 @@ #include "Game/T6/T6.h" #include "InfoString/InfoString.h" #include "InfoStringLoaderTracerT6.h" +#include "Tracer/TracerCommon.h" #include #include @@ -24,7 +25,7 @@ namespace AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - const auto fileName = std::format("tracer/{}", assetName); + const auto fileName = tracer::GetFileNameForAssetName(assetName); const auto file = m_search_path.Open(fileName); if (!file.IsOpen()) return AssetCreationResult::NoAction(); @@ -41,14 +42,14 @@ namespace private: ISearchPath& m_search_path; - InfoStringLoaderTracer m_info_string_loader; + tracer::InfoStringLoaderT6 m_info_string_loader; }; } // namespace -namespace T6 +namespace tracer { - std::unique_ptr> CreateRawTracerLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + std::unique_ptr> CreateRawLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) { return std::make_unique(memory, searchPath, zone); } -} // namespace T6 +} // namespace tracer diff --git a/src/ObjLoading/Game/T6/Tracer/RawLoaderTracerT6.h b/src/ObjLoading/Game/T6/Tracer/RawLoaderTracerT6.h index a41e74c2..3667c410 100644 --- a/src/ObjLoading/Game/T6/Tracer/RawLoaderTracerT6.h +++ b/src/ObjLoading/Game/T6/Tracer/RawLoaderTracerT6.h @@ -7,7 +7,7 @@ #include -namespace T6 +namespace tracer { - std::unique_ptr> CreateRawTracerLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); -} // namespace T6 + std::unique_ptr> CreateRawLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace tracer diff --git a/src/ObjLoading/Game/T6/Vehicle/GdtLoaderVehicleT6.cpp b/src/ObjLoading/Game/T6/Vehicle/GdtLoaderVehicleT6.cpp index 7b224773..e0267246 100644 --- a/src/ObjLoading/Game/T6/Vehicle/GdtLoaderVehicleT6.cpp +++ b/src/ObjLoading/Game/T6/Vehicle/GdtLoaderVehicleT6.cpp @@ -40,14 +40,14 @@ namespace private: IGdtQueryable& m_gdt; - InfoStringLoaderVehicle m_info_string_loader; + vehicle::InfoStringLoaderT6 m_info_string_loader; }; } // namespace -namespace T6 +namespace vehicle { - std::unique_ptr> CreateGdtVehicleLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + std::unique_ptr> CreateGdtLoaderT6(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) { return std::make_unique(memory, searchPath, gdt, zone); } -} // namespace T6 +} // namespace vehicle diff --git a/src/ObjLoading/Game/T6/Vehicle/GdtLoaderVehicleT6.h b/src/ObjLoading/Game/T6/Vehicle/GdtLoaderVehicleT6.h index fee2a56d..4bc647fe 100644 --- a/src/ObjLoading/Game/T6/Vehicle/GdtLoaderVehicleT6.h +++ b/src/ObjLoading/Game/T6/Vehicle/GdtLoaderVehicleT6.h @@ -8,7 +8,7 @@ #include -namespace T6 +namespace vehicle { - std::unique_ptr> CreateGdtVehicleLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); -} // namespace T6 + std::unique_ptr> CreateGdtLoaderT6(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); +} // namespace vehicle diff --git a/src/ObjLoading/Game/T6/Vehicle/InfoStringLoaderVehicleT6.cpp b/src/ObjLoading/Game/T6/Vehicle/InfoStringLoaderVehicleT6.cpp index 4999f0bb..76f4c2ce 100644 --- a/src/ObjLoading/Game/T6/Vehicle/InfoStringLoaderVehicleT6.cpp +++ b/src/ObjLoading/Game/T6/Vehicle/InfoStringLoaderVehicleT6.cpp @@ -107,27 +107,30 @@ namespace }; } // namespace -InfoStringLoaderVehicle::InfoStringLoaderVehicle(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) - : m_memory(memory), - m_search_path(searchPath), - m_zone(zone) +namespace vehicle { -} - -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, m_zone.m_script_strings, m_memory, context, registration, vehicle_fields, std::extent_v); - if (!converter.Convert()) + InfoStringLoaderT6::InfoStringLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_memory(memory), + m_search_path(searchPath), + m_zone(zone) { - std::cerr << std::format("Failed to parse vehicle: \"{}\"\n", assetName); - return AssetCreationResult::Failure(); } - return AssetCreationResult::Success(context.AddAsset(std::move(registration))); -} + AssetCreationResult InfoStringLoaderT6::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, m_zone.m_script_strings, m_memory, context, registration, vehicle_fields, std::extent_v); + if (!converter.Convert()) + { + std::cerr << std::format("Failed to parse vehicle: \"{}\"\n", assetName); + return AssetCreationResult::Failure(); + } + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); + } +} // namespace vehicle diff --git a/src/ObjLoading/Game/T6/Vehicle/InfoStringLoaderVehicleT6.h b/src/ObjLoading/Game/T6/Vehicle/InfoStringLoaderVehicleT6.h index 9aed730e..15995e94 100644 --- a/src/ObjLoading/Game/T6/Vehicle/InfoStringLoaderVehicleT6.h +++ b/src/ObjLoading/Game/T6/Vehicle/InfoStringLoaderVehicleT6.h @@ -4,12 +4,12 @@ #include "Asset/AssetCreationResult.h" #include "InfoString/InfoString.h" -namespace T6 +namespace vehicle { - class InfoStringLoaderVehicle + class InfoStringLoaderT6 { public: - InfoStringLoaderVehicle(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); + InfoStringLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); AssetCreationResult CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context); @@ -18,4 +18,4 @@ namespace T6 ISearchPath& m_search_path; Zone& m_zone; }; -} // namespace T6 +} // namespace vehicle diff --git a/src/ObjLoading/Game/T6/Vehicle/RawLoaderVehicleT6.cpp b/src/ObjLoading/Game/T6/Vehicle/RawLoaderVehicleT6.cpp index 68a8299e..a7b5368b 100644 --- a/src/ObjLoading/Game/T6/Vehicle/RawLoaderVehicleT6.cpp +++ b/src/ObjLoading/Game/T6/Vehicle/RawLoaderVehicleT6.cpp @@ -4,6 +4,7 @@ #include "Game/T6/T6.h" #include "InfoString/InfoString.h" #include "InfoStringLoaderVehicleT6.h" +#include "Vehicle/VehicleCommon.h" #include #include @@ -24,7 +25,7 @@ namespace AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - const auto fileName = std::format("vehicles/{}", assetName); + const auto fileName = vehicle::GetFileNameForAssetName(assetName); const auto file = m_search_path.Open(fileName); if (!file.IsOpen()) return AssetCreationResult::NoAction(); @@ -41,14 +42,14 @@ namespace private: ISearchPath& m_search_path; - InfoStringLoaderVehicle m_info_string_loader; + vehicle::InfoStringLoaderT6 m_info_string_loader; }; } // namespace -namespace T6 +namespace vehicle { - std::unique_ptr> CreateRawVehicleLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + std::unique_ptr> CreateRawLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) { return std::make_unique(memory, searchPath, zone); } -} // namespace T6 +} // namespace vehicle diff --git a/src/ObjLoading/Game/T6/Vehicle/RawLoaderVehicleT6.h b/src/ObjLoading/Game/T6/Vehicle/RawLoaderVehicleT6.h index e88d6909..59759b0a 100644 --- a/src/ObjLoading/Game/T6/Vehicle/RawLoaderVehicleT6.h +++ b/src/ObjLoading/Game/T6/Vehicle/RawLoaderVehicleT6.h @@ -7,7 +7,7 @@ #include -namespace T6 +namespace vehicle { - std::unique_ptr> CreateRawVehicleLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); -} // namespace T6 + std::unique_ptr> CreateRawLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace vehicle diff --git a/src/ObjLoading/Game/T6/Weapon/GdtLoaderAttachmentT6.cpp b/src/ObjLoading/Game/T6/Weapon/AttachmentGdtLoaderT6.cpp similarity index 80% rename from src/ObjLoading/Game/T6/Weapon/GdtLoaderAttachmentT6.cpp rename to src/ObjLoading/Game/T6/Weapon/AttachmentGdtLoaderT6.cpp index ceecfd7f..66a3b1d9 100644 --- a/src/ObjLoading/Game/T6/Weapon/GdtLoaderAttachmentT6.cpp +++ b/src/ObjLoading/Game/T6/Weapon/AttachmentGdtLoaderT6.cpp @@ -1,9 +1,9 @@ -#include "GdtLoaderAttachmentT6.h" +#include "AttachmentGdtLoaderT6.h" +#include "AttachmentInfoStringLoaderT6.h" #include "Game/T6/ObjConstantsT6.h" #include "Game/T6/T6.h" #include "InfoString/InfoString.h" -#include "InfoStringLoaderAttachmentT6.h" #include #include @@ -40,14 +40,14 @@ namespace private: IGdtQueryable& m_gdt; - InfoStringLoaderAttachment m_info_string_loader; + attachment::InfoStringLoaderT6 m_info_string_loader; }; } // namespace -namespace T6 +namespace attachment { - std::unique_ptr> CreateGdtAttachmentLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + std::unique_ptr> CreateGdtLoaderT6(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) { return std::make_unique(memory, searchPath, gdt, zone); } -} // namespace T6 +} // namespace attachment diff --git a/src/ObjLoading/Game/T6/Weapon/AttachmentGdtLoaderT6.h b/src/ObjLoading/Game/T6/Weapon/AttachmentGdtLoaderT6.h new file mode 100644 index 00000000..f2ca06ac --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/AttachmentGdtLoaderT6.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 attachment +{ + std::unique_ptr> CreateGdtLoaderT6(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); +} // namespace attachment diff --git a/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentT6.cpp b/src/ObjLoading/Game/T6/Weapon/AttachmentInfoStringLoaderT6.cpp similarity index 76% rename from src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentT6.cpp rename to src/ObjLoading/Game/T6/Weapon/AttachmentInfoStringLoaderT6.cpp index 83f71735..dd296d58 100644 --- a/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentT6.cpp +++ b/src/ObjLoading/Game/T6/Weapon/AttachmentInfoStringLoaderT6.cpp @@ -1,4 +1,4 @@ -#include "InfoStringLoaderAttachmentT6.h" +#include "AttachmentInfoStringLoaderT6.h" #include "Game/T6/InfoString/InfoStringToStructConverter.h" #include "Game/T6/T6.h" @@ -93,29 +93,32 @@ namespace } } // namespace -InfoStringLoaderAttachment::InfoStringLoaderAttachment(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) - : m_memory(memory), - m_search_path(searchPath), - m_zone(zone) +namespace attachment { -} - -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()) + InfoStringLoaderT6::InfoStringLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_memory(memory), + m_search_path(searchPath), + m_zone(zone) { - std::cerr << std::format("Failed to parse attachment: \"{}\"\n", assetName); - return AssetCreationResult::Failure(); } - CalculateAttachmentFields(*attachment); + AssetCreationResult InfoStringLoaderT6::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) + { + auto* attachment = m_memory.Alloc(); + attachment->szInternalName = m_memory.Dup(assetName.c_str()); - return AssetCreationResult::Success(context.AddAsset(std::move(registration))); -} + 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))); + } +} // namespace attachment diff --git a/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentT6.h b/src/ObjLoading/Game/T6/Weapon/AttachmentInfoStringLoaderT6.h similarity index 70% rename from src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentT6.h rename to src/ObjLoading/Game/T6/Weapon/AttachmentInfoStringLoaderT6.h index fc6d020d..b4782772 100644 --- a/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentT6.h +++ b/src/ObjLoading/Game/T6/Weapon/AttachmentInfoStringLoaderT6.h @@ -4,12 +4,12 @@ #include "Asset/AssetCreationResult.h" #include "InfoString/InfoString.h" -namespace T6 +namespace attachment { - class InfoStringLoaderAttachment + class InfoStringLoaderT6 { public: - InfoStringLoaderAttachment(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); + InfoStringLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); AssetCreationResult CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context); @@ -18,4 +18,4 @@ namespace T6 ISearchPath& m_search_path; Zone& m_zone; }; -} // namespace T6 +} // namespace attachment diff --git a/src/ObjLoading/Game/T6/Weapon/RawLoaderAttachmentT6.cpp b/src/ObjLoading/Game/T6/Weapon/AttachmentRawLoaderT6.cpp similarity index 74% rename from src/ObjLoading/Game/T6/Weapon/RawLoaderAttachmentT6.cpp rename to src/ObjLoading/Game/T6/Weapon/AttachmentRawLoaderT6.cpp index bf318b2d..815694d4 100644 --- a/src/ObjLoading/Game/T6/Weapon/RawLoaderAttachmentT6.cpp +++ b/src/ObjLoading/Game/T6/Weapon/AttachmentRawLoaderT6.cpp @@ -1,15 +1,17 @@ -#include "RawLoaderAttachmentT6.h" +#include "AttachmentRawLoaderT6.h" +#include "AttachmentInfoStringLoaderT6.h" #include "Game/T6/ObjConstantsT6.h" #include "Game/T6/T6.h" #include "InfoString/InfoString.h" -#include "InfoStringLoaderAttachmentT6.h" +#include "Weapon/AttachmentCommon.h" #include #include #include using namespace T6; +using namespace ::attachment; namespace { @@ -24,7 +26,7 @@ namespace AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - const auto fileName = std::format("attachment/{}", assetName); + const auto fileName = GetInfoStringFileNameForAssetName(assetName); const auto file = m_search_path.Open(fileName); if (!file.IsOpen()) return AssetCreationResult::NoAction(); @@ -41,14 +43,14 @@ namespace private: ISearchPath& m_search_path; - InfoStringLoaderAttachment m_info_string_loader; + attachment::InfoStringLoaderT6 m_info_string_loader; }; } // namespace -namespace T6 +namespace attachment { - std::unique_ptr> CreateRawAttachmentLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + std::unique_ptr> CreateRawLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) { return std::make_unique(memory, searchPath, zone); } -} // namespace T6 +} // namespace attachment diff --git a/src/ObjLoading/Game/T6/Weapon/AttachmentRawLoaderT6.h b/src/ObjLoading/Game/T6/Weapon/AttachmentRawLoaderT6.h new file mode 100644 index 00000000..43748226 --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/AttachmentRawLoaderT6.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 attachment +{ + std::unique_ptr> CreateRawLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace attachment diff --git a/src/ObjLoading/Game/T6/Weapon/GdtLoaderAttachmentUniqueT6.cpp b/src/ObjLoading/Game/T6/Weapon/AttachmentUniqueGdtLoaderT6.cpp similarity index 79% rename from src/ObjLoading/Game/T6/Weapon/GdtLoaderAttachmentUniqueT6.cpp rename to src/ObjLoading/Game/T6/Weapon/AttachmentUniqueGdtLoaderT6.cpp index ab53d947..01a9a006 100644 --- a/src/ObjLoading/Game/T6/Weapon/GdtLoaderAttachmentUniqueT6.cpp +++ b/src/ObjLoading/Game/T6/Weapon/AttachmentUniqueGdtLoaderT6.cpp @@ -1,9 +1,9 @@ -#include "GdtLoaderAttachmentUniqueT6.h" +#include "AttachmentUniqueGdtLoaderT6.h" +#include "AttachmentUniqueInfoStringLoaderT6.h" #include "Game/T6/ObjConstantsT6.h" #include "Game/T6/T6.h" #include "InfoString/InfoString.h" -#include "InfoStringLoaderAttachmentUniqueT6.h" #include #include @@ -40,15 +40,14 @@ namespace private: IGdtQueryable& m_gdt; - InfoStringLoaderAttachmentUnique m_info_string_loader; + attachment_unique::InfoStringLoaderT6 m_info_string_loader; }; } // namespace -namespace T6 +namespace attachment_unique { - std::unique_ptr> - CreateGdtAttachmentUniqueLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + std::unique_ptr> CreateGdtLoaderT6(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) { return std::make_unique(memory, searchPath, gdt, zone); } -} // namespace T6 +} // namespace attachment_unique diff --git a/src/ObjLoading/Game/T6/Weapon/AttachmentUniqueGdtLoaderT6.h b/src/ObjLoading/Game/T6/Weapon/AttachmentUniqueGdtLoaderT6.h new file mode 100644 index 00000000..1b1ad408 --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/AttachmentUniqueGdtLoaderT6.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 attachment_unique +{ + std::unique_ptr> CreateGdtLoaderT6(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); +} // namespace attachment_unique diff --git a/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentUniqueT6.cpp b/src/ObjLoading/Game/T6/Weapon/AttachmentUniqueInfoStringLoaderT6.cpp similarity index 64% rename from src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentUniqueT6.cpp rename to src/ObjLoading/Game/T6/Weapon/AttachmentUniqueInfoStringLoaderT6.cpp index 98a17081..059091a1 100644 --- a/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentUniqueT6.cpp +++ b/src/ObjLoading/Game/T6/Weapon/AttachmentUniqueInfoStringLoaderT6.cpp @@ -1,4 +1,4 @@ -#include "InfoStringLoaderAttachmentUniqueT6.h" +#include "AttachmentUniqueInfoStringLoaderT6.h" #include "Game/T6/InfoString/InfoStringToStructConverter.h" #include "Game/T6/T6.h" @@ -141,7 +141,7 @@ namespace { // combinedAttachmentTypeMask std::vector attachmentsFromName; - if (!InfoStringLoaderAttachmentUnique::ExtractAttachmentsFromAssetName(assetName, attachmentsFromName)) + if (!attachment_unique::ExtractAttachmentsFromAssetNameT6(assetName, attachmentsFromName)) { std::cerr << std::format("Failed to determine attachments from attachment unique name \"{}\"\n", assetName); return false; @@ -159,86 +159,89 @@ namespace } } // namespace -bool InfoStringLoaderAttachmentUnique::ExtractAttachmentsFromAssetName(const std::string& assetName, std::vector& attachmentList) +namespace attachment_unique { - std::vector parts; - - auto attachCount = 1u; - auto partStart = 0u; - for (auto ci = 0u; ci < assetName.size(); ci++) + bool ExtractAttachmentsFromAssetNameT6(const std::string& assetName, std::vector& attachmentList) { - if (assetName[ci] == '_') + std::vector parts; + + auto attachCount = 1u; + auto partStart = 0u; + for (auto ci = 0u; ci < assetName.size(); 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]) + if (assetName[ci] == '_') { - attachmentList.push_back(static_cast(attachIndex)); - foundAttachment = true; - break; + 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 (!foundAttachment) - return false; + 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; } - 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()) + InfoStringLoaderT6::InfoStringLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_memory(memory), + m_search_path(searchPath), + m_zone(zone) { - std::cerr << std::format("Failed to parse attachment unique: \"{}\"\n", assetName); - return AssetCreationResult::Failure(); } - CalculateAttachmentUniqueFields(assetName, *attachmentUniqueFull); + AssetCreationResult InfoStringLoaderT6::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) + { + auto* attachmentUniqueFull = m_memory.Alloc(); + attachmentUniqueFull->attachment.szInternalName = m_memory.Dup(assetName.c_str()); - return AssetCreationResult::Success(context.AddAsset(std::move(registration))); -} + 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(); + } + + CalculateAttachmentUniqueFields(assetName, *attachmentUniqueFull); + + return AssetCreationResult::Success(context.AddAsset(std::move(registration))); + } +} // namespace attachment_unique diff --git a/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentUniqueT6.h b/src/ObjLoading/Game/T6/Weapon/AttachmentUniqueInfoStringLoaderT6.h similarity index 59% rename from src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentUniqueT6.h rename to src/ObjLoading/Game/T6/Weapon/AttachmentUniqueInfoStringLoaderT6.h index 3ff89621..265b294f 100644 --- a/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderAttachmentUniqueT6.h +++ b/src/ObjLoading/Game/T6/Weapon/AttachmentUniqueInfoStringLoaderT6.h @@ -7,20 +7,20 @@ #include -namespace T6 +namespace attachment_unique { - class InfoStringLoaderAttachmentUnique + bool ExtractAttachmentsFromAssetNameT6(const std::string& assetName, std::vector& attachmentList); + + class InfoStringLoaderT6 { public: - InfoStringLoaderAttachmentUnique(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); + InfoStringLoaderT6(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 +} // namespace attachment_unique diff --git a/src/ObjLoading/Game/T6/Weapon/RawLoaderAttachmentUniqueT6.cpp b/src/ObjLoading/Game/T6/Weapon/AttachmentUniqueRawLoaderT6.cpp similarity index 64% rename from src/ObjLoading/Game/T6/Weapon/RawLoaderAttachmentUniqueT6.cpp rename to src/ObjLoading/Game/T6/Weapon/AttachmentUniqueRawLoaderT6.cpp index f3af0c30..a8a11dd0 100644 --- a/src/ObjLoading/Game/T6/Weapon/RawLoaderAttachmentUniqueT6.cpp +++ b/src/ObjLoading/Game/T6/Weapon/AttachmentUniqueRawLoaderT6.cpp @@ -1,9 +1,10 @@ -#include "RawLoaderAttachmentUniqueT6.h" +#include "AttachmentUniqueRawLoaderT6.h" +#include "AttachmentUniqueInfoStringLoaderT6.h" #include "Game/T6/ObjConstantsT6.h" #include "Game/T6/T6.h" #include "InfoString/InfoString.h" -#include "InfoStringLoaderAttachmentUniqueT6.h" +#include "Weapon/AttachmentUniqueCommon.h" #include #include @@ -13,10 +14,10 @@ using namespace T6; namespace { - class RawLoaderAttachmentUnique final : public AssetCreator + class RawLoader final : public AssetCreator { public: - RawLoaderAttachmentUnique(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + RawLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) : m_search_path(searchPath), m_info_string_loader(memory, searchPath, zone) { @@ -24,7 +25,7 @@ namespace AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - const auto fileName = std::format("attachmentunique/{}", assetName); + const auto fileName = attachment_unique::GetFileNameForAssetName(assetName); const auto file = m_search_path.Open(fileName); if (!file.IsOpen()) return AssetCreationResult::NoAction(); @@ -41,14 +42,14 @@ namespace private: ISearchPath& m_search_path; - InfoStringLoaderAttachmentUnique m_info_string_loader; + attachment_unique::InfoStringLoaderT6 m_info_string_loader; }; } // namespace -namespace T6 +namespace attachment_unique { - std::unique_ptr> CreateRawAttachmentUniqueLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + std::unique_ptr> CreateRawLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) { - return std::make_unique(memory, searchPath, zone); + return std::make_unique(memory, searchPath, zone); } -} // namespace T6 +} // namespace attachment_unique diff --git a/src/ObjLoading/Game/T6/Weapon/AttachmentUniqueRawLoaderT6.h b/src/ObjLoading/Game/T6/Weapon/AttachmentUniqueRawLoaderT6.h new file mode 100644 index 00000000..b6c83a64 --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/AttachmentUniqueRawLoaderT6.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 attachment_unique +{ + std::unique_ptr> CreateRawLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace attachment_unique diff --git a/src/ObjLoading/Game/T6/Weapon/JsonWeaponCamoLoaderT6.cpp b/src/ObjLoading/Game/T6/Weapon/CamoJsonLoaderT6.cpp similarity index 84% rename from src/ObjLoading/Game/T6/Weapon/JsonWeaponCamoLoaderT6.cpp rename to src/ObjLoading/Game/T6/Weapon/CamoJsonLoaderT6.cpp index 75bbe247..c1a2fdbb 100644 --- a/src/ObjLoading/Game/T6/Weapon/JsonWeaponCamoLoaderT6.cpp +++ b/src/ObjLoading/Game/T6/Weapon/CamoJsonLoaderT6.cpp @@ -1,8 +1,11 @@ -#include "JsonWeaponCamoLoaderT6.h" +#include "CamoJsonLoaderT6.h" -#include "Game/T6/CommonT6.h" #include "Game/T6/Json/JsonWeaponCamo.h" +#include "Game/T6/T6.h" +#include "Pool/GlobalAssetPool.h" +#include "Weapon/CamoCommon.h" +#include #include #include #include @@ -55,7 +58,7 @@ namespace private: static void PrintError(const WeaponCamo& weaponCamo, const std::string& message) { - std::cerr << "Cannot load weapon camo \"" << weaponCamo.name << "\": " << message << "\n"; + std::cerr << std::format("Cannot load weapon camo \"{}\": {}\n", weaponCamo.name, message); } bool CreateWeaponCamoSetFromJson(const JsonWeaponCamoSet& jWeaponCamoSet, WeaponCamoSet& weaponCamoSet, const WeaponCamo& weaponCamo) const @@ -237,15 +240,46 @@ namespace AssetCreationContext& m_context; AssetRegistration& m_registration; }; + + 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(camo::GetJsonFileNameForAssetName(assetName)); + if (!file.IsOpen()) + return AssetCreationResult::NoAction(); + + auto* weaponCamo = m_memory.Alloc(); + weaponCamo->name = m_memory.Dup(assetName.c_str()); + + AssetRegistration registration(assetName, weaponCamo); + const JsonLoader loader(*file.m_stream, m_memory, context, registration); + if (!loader.Load(*weaponCamo)) + { + 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 +namespace camo { - bool LoadWeaponCamoAsJson( - std::istream& stream, WeaponCamo& weaponCamo, MemoryManager& memory, AssetCreationContext& context, AssetRegistration& registration) + std::unique_ptr> CreateJsonLoaderT6(MemoryManager& memory, ISearchPath& searchPath) { - const JsonLoader loader(stream, memory, context, registration); - - return loader.Load(weaponCamo); + return std::make_unique(memory, searchPath); } -} // namespace T6 +} // namespace camo diff --git a/src/ObjLoading/Game/T6/Leaderboard/LoaderLeaderboardT6.h b/src/ObjLoading/Game/T6/Weapon/CamoJsonLoaderT6.h similarity index 50% rename from src/ObjLoading/Game/T6/Leaderboard/LoaderLeaderboardT6.h rename to src/ObjLoading/Game/T6/Weapon/CamoJsonLoaderT6.h index df060b90..cd6da51d 100644 --- a/src/ObjLoading/Game/T6/Leaderboard/LoaderLeaderboardT6.h +++ b/src/ObjLoading/Game/T6/Weapon/CamoJsonLoaderT6.h @@ -7,7 +7,7 @@ #include -namespace T6 +namespace camo { - std::unique_ptr> CreateLeaderboardLoader(MemoryManager& memory, ISearchPath& searchPath); -} // namespace T6 + std::unique_ptr> CreateJsonLoaderT6(MemoryManager& memory, ISearchPath& searchPath); +} // namespace camo diff --git a/src/ObjLoading/Game/T6/Weapon/GdtLoaderAttachmentT6.h b/src/ObjLoading/Game/T6/Weapon/GdtLoaderAttachmentT6.h deleted file mode 100644 index 6455b204..00000000 --- a/src/ObjLoading/Game/T6/Weapon/GdtLoaderAttachmentT6.h +++ /dev/null @@ -1,14 +0,0 @@ -#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.h b/src/ObjLoading/Game/T6/Weapon/GdtLoaderAttachmentUniqueT6.h deleted file mode 100644 index 3e39221d..00000000 --- a/src/ObjLoading/Game/T6/Weapon/GdtLoaderAttachmentUniqueT6.h +++ /dev/null @@ -1,15 +0,0 @@ -#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/JsonWeaponCamoLoaderT6.h b/src/ObjLoading/Game/T6/Weapon/JsonWeaponCamoLoaderT6.h deleted file mode 100644 index 6f5aea17..00000000 --- a/src/ObjLoading/Game/T6/Weapon/JsonWeaponCamoLoaderT6.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Asset/AssetCreationContext.h" -#include "Asset/AssetRegistration.h" -#include "Game/T6/T6.h" -#include "Utils/MemoryManager.h" - -#include - -namespace T6 -{ - bool LoadWeaponCamoAsJson( - 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 deleted file mode 100644 index c3409ac8..00000000 --- a/src/ObjLoading/Game/T6/Weapon/LoaderWeaponCamoT6.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#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 deleted file mode 100644 index b5270fba..00000000 --- a/src/ObjLoading/Game/T6/Weapon/LoaderWeaponCamoT6.h +++ /dev/null @@ -1,13 +0,0 @@ -#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.h b/src/ObjLoading/Game/T6/Weapon/RawLoaderAttachmentT6.h deleted file mode 100644 index d83631d1..00000000 --- a/src/ObjLoading/Game/T6/Weapon/RawLoaderAttachmentT6.h +++ /dev/null @@ -1,13 +0,0 @@ -#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.h b/src/ObjLoading/Game/T6/Weapon/RawLoaderAttachmentUniqueT6.h deleted file mode 100644 index 47b66237..00000000 --- a/src/ObjLoading/Game/T6/Weapon/RawLoaderAttachmentUniqueT6.h +++ /dev/null @@ -1,13 +0,0 @@ -#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.h b/src/ObjLoading/Game/T6/Weapon/RawLoaderWeaponT6.h deleted file mode 100644 index 8eedbb71..00000000 --- a/src/ObjLoading/Game/T6/Weapon/RawLoaderWeaponT6.h +++ /dev/null @@ -1,13 +0,0 @@ -#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/Weapon/GdtLoaderWeaponT6.cpp b/src/ObjLoading/Game/T6/Weapon/WeaponGdtLoaderT6.cpp similarity index 81% rename from src/ObjLoading/Game/T6/Weapon/GdtLoaderWeaponT6.cpp rename to src/ObjLoading/Game/T6/Weapon/WeaponGdtLoaderT6.cpp index 702213dd..02f77115 100644 --- a/src/ObjLoading/Game/T6/Weapon/GdtLoaderWeaponT6.cpp +++ b/src/ObjLoading/Game/T6/Weapon/WeaponGdtLoaderT6.cpp @@ -1,9 +1,9 @@ -#include "GdtLoaderWeaponT6.h" +#include "WeaponGdtLoaderT6.h" #include "Game/T6/ObjConstantsT6.h" #include "Game/T6/T6.h" #include "InfoString/InfoString.h" -#include "InfoStringLoaderWeaponT6.h" +#include "WeaponInfoStringLoaderT6.h" #include #include @@ -40,14 +40,14 @@ namespace private: IGdtQueryable& m_gdt; - InfoStringLoaderWeapon m_info_string_loader; + weapon::InfoStringLoaderT6 m_info_string_loader; }; } // namespace -namespace T6 +namespace weapon { - std::unique_ptr> CreateGdtWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + std::unique_ptr> CreateGdtLoaderT6(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) { return std::make_unique(memory, searchPath, gdt, zone); } -} // namespace T6 +} // namespace weapon diff --git a/src/ObjLoading/Game/T6/Weapon/GdtLoaderWeaponT6.h b/src/ObjLoading/Game/T6/Weapon/WeaponGdtLoaderT6.h similarity index 56% rename from src/ObjLoading/Game/T6/Weapon/GdtLoaderWeaponT6.h rename to src/ObjLoading/Game/T6/Weapon/WeaponGdtLoaderT6.h index fdb1882b..ef2b6914 100644 --- a/src/ObjLoading/Game/T6/Weapon/GdtLoaderWeaponT6.h +++ b/src/ObjLoading/Game/T6/Weapon/WeaponGdtLoaderT6.h @@ -8,7 +8,7 @@ #include -namespace T6 +namespace weapon { - std::unique_ptr> CreateGdtWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); -} // namespace T6 + std::unique_ptr> CreateGdtLoaderT6(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); +} // namespace weapon diff --git a/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderWeaponT6.cpp b/src/ObjLoading/Game/T6/Weapon/WeaponInfoStringLoaderT6.cpp similarity index 95% rename from src/ObjLoading/Game/T6/Weapon/InfoStringLoaderWeaponT6.cpp rename to src/ObjLoading/Game/T6/Weapon/WeaponInfoStringLoaderT6.cpp index 6d97ceab..ccaf394e 100644 --- a/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderWeaponT6.cpp +++ b/src/ObjLoading/Game/T6/Weapon/WeaponInfoStringLoaderT6.cpp @@ -1,10 +1,10 @@ -#include "InfoStringLoaderWeaponT6.h" +#include "WeaponInfoStringLoaderT6.h" +#include "AttachmentUniqueInfoStringLoaderT6.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 @@ -568,8 +568,7 @@ namespace && weapon.attachmentUniques[attachmentUniqueIndex]->attachmentType != attachmentUnique.attachmentType) { std::vector attachments; - if (InfoStringLoaderAttachmentUnique::ExtractAttachmentsFromAssetName(weapon.attachmentUniques[attachmentUniqueIndex]->szInternalName, - attachments) + if (attachment_unique::ExtractAttachmentsFromAssetNameT6(weapon.attachmentUniques[attachmentUniqueIndex]->szInternalName, attachments) && attachments.front() == attachmentUnique.attachmentType) { if (lastSibling == nullptr) @@ -600,34 +599,37 @@ namespace } } // namespace -InfoStringLoaderWeapon::InfoStringLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) - : m_memory(memory), - m_search_path(searchPath), - m_zone(zone) +namespace weapon { -} - -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()) + InfoStringLoaderT6::InfoStringLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_memory(memory), + m_search_path(searchPath), + m_zone(zone) { - std::cerr << std::format("Failed to parse weapon: \"{}\"\n", assetName); - return AssetCreationResult::Failure(); } - CalculateWeaponFields(*weaponFullDef); - CalculateAttachmentFields(*weaponFullDef); + AssetCreationResult InfoStringLoaderT6::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) + { + auto* weaponFullDef = m_memory.Alloc(); + weaponFullDef->weapVariantDef.szInternalName = m_memory.Dup(assetName.c_str()); - LoadAccuracyGraphs(*weaponFullDef, m_memory, m_search_path, context); + LinkWeaponFullDefSubStructs(*weaponFullDef); - return AssetCreationResult::Success(context.AddAsset(std::move(registration))); -} + 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))); + } +} // namespace weapon diff --git a/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderWeaponT6.h b/src/ObjLoading/Game/T6/Weapon/WeaponInfoStringLoaderT6.h similarity index 71% rename from src/ObjLoading/Game/T6/Weapon/InfoStringLoaderWeaponT6.h rename to src/ObjLoading/Game/T6/Weapon/WeaponInfoStringLoaderT6.h index f745963a..a4d146cb 100644 --- a/src/ObjLoading/Game/T6/Weapon/InfoStringLoaderWeaponT6.h +++ b/src/ObjLoading/Game/T6/Weapon/WeaponInfoStringLoaderT6.h @@ -4,12 +4,12 @@ #include "Asset/AssetCreationResult.h" #include "InfoString/InfoString.h" -namespace T6 +namespace weapon { - class InfoStringLoaderWeapon + class InfoStringLoaderT6 { public: - InfoStringLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); + InfoStringLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); AssetCreationResult CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context); @@ -18,4 +18,4 @@ namespace T6 ISearchPath& m_search_path; Zone& m_zone; }; -} // namespace T6 +} // namespace weapon diff --git a/src/ObjLoading/Game/T6/Weapon/RawLoaderWeaponT6.cpp b/src/ObjLoading/Game/T6/Weapon/WeaponRawLoaderT6.cpp similarity index 64% rename from src/ObjLoading/Game/T6/Weapon/RawLoaderWeaponT6.cpp rename to src/ObjLoading/Game/T6/Weapon/WeaponRawLoaderT6.cpp index 36cbcd48..97f37dec 100644 --- a/src/ObjLoading/Game/T6/Weapon/RawLoaderWeaponT6.cpp +++ b/src/ObjLoading/Game/T6/Weapon/WeaponRawLoaderT6.cpp @@ -1,9 +1,10 @@ -#include "RawLoaderWeaponT6.h" +#include "WeaponRawLoaderT6.h" #include "Game/T6/ObjConstantsT6.h" #include "Game/T6/T6.h" #include "InfoString/InfoString.h" -#include "InfoStringLoaderWeaponT6.h" +#include "Weapon/WeaponCommon.h" +#include "WeaponInfoStringLoaderT6.h" #include #include @@ -13,10 +14,10 @@ using namespace T6; namespace { - class RawLoaderWeapon final : public AssetCreator + class RawLoader final : public AssetCreator { public: - RawLoaderWeapon(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + RawLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) : m_search_path(searchPath), m_info_string_loader(memory, searchPath, zone) { @@ -24,7 +25,7 @@ namespace AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - const auto fileName = std::format("weapons/{}", assetName); + const auto fileName = weapon::GetFileNameForAssetName(assetName); const auto file = m_search_path.Open(fileName); if (!file.IsOpen()) return AssetCreationResult::NoAction(); @@ -41,14 +42,14 @@ namespace private: ISearchPath& m_search_path; - InfoStringLoaderWeapon m_info_string_loader; + weapon::InfoStringLoaderT6 m_info_string_loader; }; } // namespace -namespace T6 +namespace weapon { - std::unique_ptr> CreateRawWeaponLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + std::unique_ptr> CreateRawLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) { - return std::make_unique(memory, searchPath, zone); + return std::make_unique(memory, searchPath, zone); } -} // namespace T6 +} // namespace weapon diff --git a/src/ObjLoading/Game/T6/Weapon/WeaponRawLoaderT6.h b/src/ObjLoading/Game/T6/Weapon/WeaponRawLoaderT6.h new file mode 100644 index 00000000..f026b99b --- /dev/null +++ b/src/ObjLoading/Game/T6/Weapon/WeaponRawLoaderT6.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 weapon +{ + std::unique_ptr> CreateRawLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace weapon diff --git a/src/ObjLoading/Game/T6/ZBarrier/GdtLoaderZBarrierT6.cpp b/src/ObjLoading/Game/T6/ZBarrier/GdtLoaderZBarrierT6.cpp index cba149e6..09dbb255 100644 --- a/src/ObjLoading/Game/T6/ZBarrier/GdtLoaderZBarrierT6.cpp +++ b/src/ObjLoading/Game/T6/ZBarrier/GdtLoaderZBarrierT6.cpp @@ -40,14 +40,14 @@ namespace private: IGdtQueryable& m_gdt; - InfoStringLoaderZBarrier m_info_string_loader; + z_barrier::InfoStringLoaderT6 m_info_string_loader; }; } // namespace -namespace T6 +namespace z_barrier { - std::unique_ptr> CreateGdtZBarrierLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) + std::unique_ptr> CreateGdtLoaderT6(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone) { return std::make_unique(memory, searchPath, gdt, zone); } -} // namespace T6 +} // namespace z_barrier diff --git a/src/ObjLoading/Game/T6/ZBarrier/GdtLoaderZBarrierT6.h b/src/ObjLoading/Game/T6/ZBarrier/GdtLoaderZBarrierT6.h index af3796b9..abf79682 100644 --- a/src/ObjLoading/Game/T6/ZBarrier/GdtLoaderZBarrierT6.h +++ b/src/ObjLoading/Game/T6/ZBarrier/GdtLoaderZBarrierT6.h @@ -8,7 +8,7 @@ #include -namespace T6 +namespace z_barrier { - std::unique_ptr> CreateGdtZBarrierLoader(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); -} // namespace T6 + std::unique_ptr> CreateGdtLoaderT6(MemoryManager& memory, ISearchPath& searchPath, IGdtQueryable& gdt, Zone& zone); +} // namespace z_barrier diff --git a/src/ObjLoading/Game/T6/ZBarrier/InfoStringLoaderZBarrierT6.cpp b/src/ObjLoading/Game/T6/ZBarrier/InfoStringLoaderZBarrierT6.cpp index 23c460b9..3952a969 100644 --- a/src/ObjLoading/Game/T6/ZBarrier/InfoStringLoaderZBarrierT6.cpp +++ b/src/ObjLoading/Game/T6/ZBarrier/InfoStringLoaderZBarrierT6.cpp @@ -55,29 +55,32 @@ namespace } } // namespace -InfoStringLoaderZBarrier::InfoStringLoaderZBarrier(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) - : m_memory(memory), - m_search_path(searchPath), - m_zone(zone) +namespace z_barrier { -} - -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()) + InfoStringLoaderT6::InfoStringLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + : m_memory(memory), + m_search_path(searchPath), + m_zone(zone) { - std::cerr << std::format("Failed to parse zbarrier: \"{}\"\n", assetName); - return AssetCreationResult::Failure(); } - CalculateZBarrierFields(*zbarrier); + AssetCreationResult InfoStringLoaderT6::CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context) + { + auto* zbarrier = m_memory.Alloc(); + zbarrier->name = m_memory.Dup(assetName.c_str()); - return AssetCreationResult::Success(context.AddAsset(std::move(registration))); -} + 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))); + } +} // namespace z_barrier diff --git a/src/ObjLoading/Game/T6/ZBarrier/InfoStringLoaderZBarrierT6.h b/src/ObjLoading/Game/T6/ZBarrier/InfoStringLoaderZBarrierT6.h index 5a70ec28..403fec2e 100644 --- a/src/ObjLoading/Game/T6/ZBarrier/InfoStringLoaderZBarrierT6.h +++ b/src/ObjLoading/Game/T6/ZBarrier/InfoStringLoaderZBarrierT6.h @@ -4,12 +4,12 @@ #include "Asset/AssetCreationResult.h" #include "InfoString/InfoString.h" -namespace T6 +namespace z_barrier { - class InfoStringLoaderZBarrier + class InfoStringLoaderT6 { public: - InfoStringLoaderZBarrier(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); + InfoStringLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); AssetCreationResult CreateAsset(const std::string& assetName, const InfoString& infoString, AssetCreationContext& context); @@ -18,4 +18,4 @@ namespace T6 ISearchPath& m_search_path; Zone& m_zone; }; -} // namespace T6 +} // namespace z_barrier diff --git a/src/ObjLoading/Game/T6/ZBarrier/RawLoaderZBarrierT6.cpp b/src/ObjLoading/Game/T6/ZBarrier/RawLoaderZBarrierT6.cpp index 0a7d56d0..9b169786 100644 --- a/src/ObjLoading/Game/T6/ZBarrier/RawLoaderZBarrierT6.cpp +++ b/src/ObjLoading/Game/T6/ZBarrier/RawLoaderZBarrierT6.cpp @@ -4,6 +4,7 @@ #include "Game/T6/T6.h" #include "InfoString/InfoString.h" #include "InfoStringLoaderZBarrierT6.h" +#include "ZBarrier/ZBarrierCommon.h" #include #include @@ -24,7 +25,7 @@ namespace AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { - const auto fileName = std::format("zbarrier/{}", assetName); + const auto fileName = z_barrier::GetFileNameForAssetName(assetName); const auto file = m_search_path.Open(fileName); if (!file.IsOpen()) return AssetCreationResult::NoAction(); @@ -41,14 +42,14 @@ namespace private: ISearchPath& m_search_path; - InfoStringLoaderZBarrier m_info_string_loader; + z_barrier::InfoStringLoaderT6 m_info_string_loader; }; } // namespace -namespace T6 +namespace z_barrier { - std::unique_ptr> CreateRawZBarrierLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + std::unique_ptr> CreateRawLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) { return std::make_unique(memory, searchPath, zone); } -} // namespace T6 +} // namespace z_barrier diff --git a/src/ObjLoading/Game/T6/ZBarrier/RawLoaderZBarrierT6.h b/src/ObjLoading/Game/T6/ZBarrier/RawLoaderZBarrierT6.h index 007b2306..87ed18db 100644 --- a/src/ObjLoading/Game/T6/ZBarrier/RawLoaderZBarrierT6.h +++ b/src/ObjLoading/Game/T6/ZBarrier/RawLoaderZBarrierT6.h @@ -7,7 +7,7 @@ #include -namespace T6 +namespace z_barrier { - std::unique_ptr> CreateRawZBarrierLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); -} // namespace T6 + std::unique_ptr> CreateRawLoaderT6(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); +} // namespace z_barrier diff --git a/src/ObjLoading/Techset/TechniqueFileReader.h b/src/ObjLoading/Techset/TechniqueFileReader.h index fe85f9a8..2090304b 100644 --- a/src/ObjLoading/Techset/TechniqueFileReader.h +++ b/src/ObjLoading/Techset/TechniqueFileReader.h @@ -11,14 +11,15 @@ namespace techset { class TechniqueFileReader { + public: + TechniqueFileReader(std::istream& stream, std::string fileName, ITechniqueDefinitionAcceptor* acceptor); + + [[nodiscard]] bool ReadTechniqueDefinition() const; + + private: std::string m_file_name; ITechniqueDefinitionAcceptor* m_acceptor; std::unique_ptr m_base_stream; std::unique_ptr m_comment_proxy; - - public: - TechniqueFileReader(std::istream& stream, std::string fileName, ITechniqueDefinitionAcceptor* acceptor); - - _NODISCARD bool ReadTechniqueDefinition() const; }; } // namespace techset diff --git a/src/ObjLoading/XModel/LoaderXModel.cpp.template b/src/ObjLoading/XModel/LoaderXModel.cpp.template index 493bfc80..c47b260e 100644 --- a/src/ObjLoading/XModel/LoaderXModel.cpp.template +++ b/src/ObjLoading/XModel/LoaderXModel.cpp.template @@ -1082,9 +1082,11 @@ namespace }; } // namespace -namespace GAME +#set CREATE_LOADER_METHOD "CreateLoader" + GAME + +namespace xmodel { - std::unique_ptr> CreateXModelLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone) + std::unique_ptr> CREATE_LOADER_METHOD (MemoryManager& memory, ISearchPath& searchPath, Zone& zone) { return std::make_unique(memory, searchPath, zone.m_script_strings); } diff --git a/src/ObjLoading/XModel/LoaderXModel.h.template b/src/ObjLoading/XModel/LoaderXModel.h.template index 4d296a58..f6668ca2 100644 --- a/src/ObjLoading/XModel/LoaderXModel.h.template +++ b/src/ObjLoading/XModel/LoaderXModel.h.template @@ -13,7 +13,9 @@ #include -namespace GAME +#set CREATE_LOADER_METHOD "CreateLoader" + GAME + +namespace xmodel { - std::unique_ptr> CreateXModelLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone); + std::unique_ptr> CREATE_LOADER_METHOD (MemoryManager& memory, ISearchPath& searchPath, Zone& zone); } // namespace GAME diff --git a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperGfxImage.h b/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperGfxImage.h deleted file mode 100644 index 009a7e57..00000000 --- a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperGfxImage.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW3/IW3.h" -#include "Image/IImageWriter.h" - -#include - -namespace IW3 -{ - class AssetDumperGfxImage final : public AbstractAssetDumper - { - std::unique_ptr m_writer; - - [[nodiscard]] std::string GetAssetFileName(const XAssetInfo& asset) const; - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - - public: - AssetDumperGfxImage(); - }; -} // namespace IW3 diff --git a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperLoadedSound.cpp b/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperLoadedSound.cpp deleted file mode 100644 index de40981f..00000000 --- a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperLoadedSound.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "AssetDumperLoadedSound.h" - -#include "Sound/WavTypes.h" -#include "Sound/WavWriter.h" - -#include - -using namespace IW3; - -bool AssetDumperLoadedSound::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperLoadedSound::DumpWavPcm(const LoadedSound* asset, std::ostream& stream) -{ - const WavWriter writer(stream); - - const WavMetaData metaData{.channelCount = static_cast(asset->sound.info.channels), - .samplesPerSec = static_cast(asset->sound.info.rate), - .bitsPerSample = static_cast(asset->sound.info.bits)}; - - writer.WritePcmHeader(metaData, asset->sound.info.data_len); - writer.WritePcmData(asset->sound.data, asset->sound.info.data_len); -} - -void AssetDumperLoadedSound::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* loadedSound = asset->Asset(); - const auto assetFile = context.OpenAssetFile(std::format("sound/{}", asset->m_name)); - - if (!assetFile) - return; - - auto& stream = *assetFile; - switch (static_cast(loadedSound->sound.info.format)) - { - case WavFormat::PCM: - DumpWavPcm(loadedSound, stream); - break; - - default: - std::cerr << std::format("Unknown format {} for loaded sound: {}\n", loadedSound->sound.info.format, loadedSound->name); - break; - } -} diff --git a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperLoadedSound.h b/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperLoadedSound.h deleted file mode 100644 index 239e3b5b..00000000 --- a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperLoadedSound.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW3/IW3.h" - -namespace IW3 -{ - class AssetDumperLoadedSound final : public AbstractAssetDumper - { - static void DumpWavPcm(const LoadedSound* asset, std::ostream& stream); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW3 diff --git a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperLocalizeEntry.cpp b/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperLocalizeEntry.cpp deleted file mode 100644 index d95a03b7..00000000 --- a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperLocalizeEntry.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "AssetDumperLocalizeEntry.h" - -#include "Dumping/Localize/StringFileDumper.h" -#include "Localize/LocalizeCommon.h" - -#include -#include - -using namespace IW3; - -void AssetDumperLocalizeEntry::DumpPool(AssetDumpingContext& context, AssetPool* pool) -{ - if (pool->m_asset_lookup.empty()) - return; - - const auto language = LocalizeCommon::GetNameOfLanguage(context.m_zone.m_language); - const auto assetFile = context.OpenAssetFile(std::format("{}/localizedstrings/{}.str", language, context.m_zone.m_name)); - - if (assetFile) - { - StringFileDumper stringFileDumper(context.m_zone, *assetFile); - - stringFileDumper.SetLanguageName(language); - - // Magic string. Original string files do have this config file. The purpose of the config file is unknown though. - stringFileDumper.SetConfigFile(R"(C:/trees/cod3/cod3/bin/StringEd.cfg)"); - - stringFileDumper.SetNotes(""); - - for (auto* localizeEntry : *pool) - { - stringFileDumper.WriteLocalizeEntry(localizeEntry->m_name, localizeEntry->Asset()->value); - } - - stringFileDumper.Finalize(); - } - else - { - std::cerr << std::format("Could not create string file for dumping localized strings of zone '{}'\n", context.m_zone.m_name); - } -} diff --git a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperLocalizeEntry.h b/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperLocalizeEntry.h deleted file mode 100644 index 02d18955..00000000 --- a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperLocalizeEntry.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW3/IW3.h" - -namespace IW3 -{ - class AssetDumperLocalizeEntry final : public IAssetDumper - { - public: - void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; - }; -} // namespace IW3 diff --git a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperMapEnts.cpp b/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperMapEnts.cpp deleted file mode 100644 index 9e9cd441..00000000 --- a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperMapEnts.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "AssetDumperMapEnts.h" - -using namespace IW3; - -bool AssetDumperMapEnts::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperMapEnts::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* mapEnts = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name + ".ents"); - - if (!assetFile) - return; - - auto& stream = *assetFile; - stream.write(mapEnts->entityString, mapEnts->numEntityChars); -} diff --git a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperMapEnts.h b/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperMapEnts.h deleted file mode 100644 index c769bec0..00000000 --- a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperMapEnts.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW3/IW3.h" - -namespace IW3 -{ - class AssetDumperMapEnts final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW3 diff --git a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperRawFile.cpp b/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperRawFile.cpp deleted file mode 100644 index bd9b7ecd..00000000 --- a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperRawFile.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "AssetDumperRawFile.h" - -using namespace IW3; - -bool AssetDumperRawFile::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperRawFile::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* rawFile = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - stream.write(rawFile->buffer, rawFile->len); -} diff --git a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperRawFile.h b/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperRawFile.h deleted file mode 100644 index abeeda26..00000000 --- a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperRawFile.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW3/IW3.h" - -namespace IW3 -{ - class AssetDumperRawFile final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW3 diff --git a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperStringTable.cpp b/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperStringTable.cpp deleted file mode 100644 index 26c8d514..00000000 --- a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperStringTable.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "AssetDumperStringTable.h" - -#include "Csv/CsvStream.h" - -using namespace IW3; - -bool AssetDumperStringTable::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperStringTable::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* stringTable = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name); - - if (!assetFile) - return; - - CsvOutputStream csv(*assetFile); - - for (auto row = 0; row < stringTable->rowCount; row++) - { - for (auto column = 0; column < stringTable->columnCount; column++) - { - csv.WriteColumn(stringTable->values[column + row * stringTable->columnCount]); - } - - csv.NextRow(); - } -} diff --git a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperStringTable.h b/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperStringTable.h deleted file mode 100644 index 915f4a40..00000000 --- a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperStringTable.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW3/IW3.h" - -namespace IW3 -{ - class AssetDumperStringTable final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW3 diff --git a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperWeapon.cpp b/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperWeapon.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperWeapon.h b/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperWeapon.h deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperXModel.cpp b/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperXModel.cpp deleted file mode 100644 index 1491047c..00000000 --- a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperXModel.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "AssetDumperXModel.h" - -#include "Game/IW3/XModel/XModelDumperIW3.h" - -using namespace IW3; - -bool AssetDumperXModel::ShouldDump(XAssetInfo* asset) -{ - return !asset->m_name.empty() && asset->m_name[0] != ','; -} - -void AssetDumperXModel::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - DumpXModel(context, asset); -} diff --git a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperXModel.h b/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperXModel.h deleted file mode 100644 index e8aa5df8..00000000 --- a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperXModel.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW3/IW3.h" - -namespace IW3 -{ - class AssetDumperXModel final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW3 diff --git a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperGfxImage.cpp b/src/ObjWriting/Game/IW3/Image/ImageDumperIW3.cpp similarity index 57% rename from src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperGfxImage.cpp rename to src/ObjWriting/Game/IW3/Image/ImageDumperIW3.cpp index 5f76f1c4..245e5790 100644 --- a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperGfxImage.cpp +++ b/src/ObjWriting/Game/IW3/Image/ImageDumperIW3.cpp @@ -1,7 +1,8 @@ -#include "AssetDumperGfxImage.h" +#include "ImageDumperIW3.h" #include "Image/DdsWriter.h" #include "Image/Dx9TextureLoader.h" +#include "Image/ImageCommon.h" #include "Image/IwiLoader.h" #include "Image/IwiTypes.h" #include "Image/IwiWriter6.h" @@ -38,7 +39,7 @@ namespace std::unique_ptr LoadImageFromIwi(const GfxImage& image, ISearchPath& searchPath) { - const auto imageFileName = std::format("images/{}.iwi", image.name); + const auto imageFileName = image::GetFileNameForAsset(image.name, ".iwi"); const auto filePathImage = searchPath.Open(imageFileName); if (!filePathImage.IsOpen()) { @@ -58,48 +59,43 @@ namespace } } // namespace -AssetDumperGfxImage::AssetDumperGfxImage() +namespace image { - switch (ObjWriting::Configuration.ImageOutputFormat) + DumperIW3::DumperIW3() { - case ObjWriting::Configuration_t::ImageOutputFormat_e::DDS: - m_writer = std::make_unique(); - break; - case ObjWriting::Configuration_t::ImageOutputFormat_e::IWI: - m_writer = std::make_unique(); - break; - default: - assert(false); - m_writer = nullptr; - break; + switch (ObjWriting::Configuration.ImageOutputFormat) + { + case ObjWriting::Configuration_t::ImageOutputFormat_e::DDS: + m_writer = std::make_unique(); + break; + case ObjWriting::Configuration_t::ImageOutputFormat_e::IWI: + m_writer = std::make_unique(); + break; + default: + assert(false); + m_writer = nullptr; + break; + } } -} -bool AssetDumperGfxImage::ShouldDump(XAssetInfo* asset) -{ - return true; -} + bool DumperIW3::ShouldDump(XAssetInfo* asset) + { + return true; + } -std::string AssetDumperGfxImage::GetAssetFileName(const XAssetInfo& asset) const -{ - auto cleanAssetName = asset.m_name; - std::ranges::replace(cleanAssetName, '*', '_'); + void DumperIW3::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* image = asset->Asset(); + const auto texture = LoadImageData(context.m_obj_search_path, *image); + if (!texture) + return; - return std::format("images/{}{}", cleanAssetName, m_writer->GetFileExtension()); -} + const auto assetFile = context.OpenAssetFile(GetFileNameForAsset(asset->m_name, m_writer->GetFileExtension())); -void AssetDumperGfxImage::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* image = asset->Asset(); - const auto texture = LoadImageData(context.m_obj_search_path, *image); - if (!texture) - return; + if (!assetFile) + return; - const auto assetFile = context.OpenAssetFile(GetAssetFileName(*asset)); - - if (!assetFile) - return; - - auto& stream = *assetFile; - m_writer->DumpImage(stream, texture.get()); -} + auto& stream = *assetFile; + m_writer->DumpImage(stream, texture.get()); + } +} // namespace image diff --git a/src/ObjWriting/Game/IW3/Image/ImageDumperIW3.h b/src/ObjWriting/Game/IW3/Image/ImageDumperIW3.h new file mode 100644 index 00000000..7a1b181c --- /dev/null +++ b/src/ObjWriting/Game/IW3/Image/ImageDumperIW3.h @@ -0,0 +1,23 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW3/IW3.h" +#include "Image/IImageWriter.h" + +#include + +namespace image +{ + class DumperIW3 final : public AbstractAssetDumper + { + public: + DumperIW3(); + + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + + private: + std::unique_ptr m_writer; + }; +} // namespace image diff --git a/src/ObjWriting/Game/IW3/Localize/LocalizeDumperIW3.cpp b/src/ObjWriting/Game/IW3/Localize/LocalizeDumperIW3.cpp new file mode 100644 index 00000000..9cb481db --- /dev/null +++ b/src/ObjWriting/Game/IW3/Localize/LocalizeDumperIW3.cpp @@ -0,0 +1,44 @@ +#include "LocalizeDumperIW3.h" + +#include "Dumping/Localize/StringFileDumper.h" +#include "Localize/LocalizeCommon.h" + +#include +#include + +using namespace IW3; + +namespace localize +{ + void DumperIW3::DumpPool(AssetDumpingContext& context, AssetPool* pool) + { + if (pool->m_asset_lookup.empty()) + return; + + const auto language = LocalizeCommon::GetNameOfLanguage(context.m_zone.m_language); + const auto assetFile = context.OpenAssetFile(std::format("{}/localizedstrings/{}.str", language, context.m_zone.m_name)); + + if (assetFile) + { + StringFileDumper stringFileDumper(context.m_zone, *assetFile); + + stringFileDumper.SetLanguageName(language); + + // Magic string. Original string files do have this config file. The purpose of the config file is unknown though. + stringFileDumper.SetConfigFile(R"(C:/trees/cod3/cod3/bin/StringEd.cfg)"); + + stringFileDumper.SetNotes(""); + + for (auto* localizeEntry : *pool) + { + stringFileDumper.WriteLocalizeEntry(localizeEntry->m_name, localizeEntry->Asset()->value); + } + + stringFileDumper.Finalize(); + } + else + { + std::cerr << std::format("Could not create string file for dumping localized strings of zone '{}'\n", context.m_zone.m_name); + } + } +} // namespace localize diff --git a/src/ObjWriting/Game/IW3/Localize/LocalizeDumperIW3.h b/src/ObjWriting/Game/IW3/Localize/LocalizeDumperIW3.h new file mode 100644 index 00000000..4cebd7c8 --- /dev/null +++ b/src/ObjWriting/Game/IW3/Localize/LocalizeDumperIW3.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW3/IW3.h" + +namespace localize +{ + class DumperIW3 final : public IAssetDumper + { + public: + void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; + }; +} // namespace localize diff --git a/src/ObjWriting/Game/IW3/Maps/MapEntsDumperIW3.cpp b/src/ObjWriting/Game/IW3/Maps/MapEntsDumperIW3.cpp new file mode 100644 index 00000000..759623e4 --- /dev/null +++ b/src/ObjWriting/Game/IW3/Maps/MapEntsDumperIW3.cpp @@ -0,0 +1,23 @@ +#include "MapEntsDumperIW3.h" + +using namespace IW3; + +namespace map_ents +{ + bool DumperIW3::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperIW3::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* mapEnts = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name + ".ents"); + + if (!assetFile) + return; + + auto& stream = *assetFile; + stream.write(mapEnts->entityString, mapEnts->numEntityChars); + } +} // namespace map_ents diff --git a/src/ObjWriting/Game/IW3/Maps/MapEntsDumperIW3.h b/src/ObjWriting/Game/IW3/Maps/MapEntsDumperIW3.h new file mode 100644 index 00000000..cd41ccc8 --- /dev/null +++ b/src/ObjWriting/Game/IW3/Maps/MapEntsDumperIW3.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW3/IW3.h" + +namespace map_ents +{ + class DumperIW3 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace map_ents diff --git a/src/ObjWriting/Game/IW3/Material/DumperMaterialIW3.cpp b/src/ObjWriting/Game/IW3/Material/DumperMaterialIW3.cpp deleted file mode 100644 index bb3a87a8..00000000 --- a/src/ObjWriting/Game/IW3/Material/DumperMaterialIW3.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "DumperMaterialIW3.h" - -#include "Game/IW3/Material/JsonMaterialWriterIW3.h" -#include "Game/IW3/Material/MaterialConstantZoneStateIW3.h" -#include "Material/MaterialCommon.h" - -using namespace IW3; - -void AssetDumperMaterial::DumpPool(AssetDumpingContext& context, AssetPool* pool) -{ - auto* materialConstantState = context.GetZoneAssetDumperState(); - materialConstantState->ExtractNamesFromZone(); - - AbstractAssetDumper::DumpPool(context, pool); -} - -bool AssetDumperMaterial::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperMaterial::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto assetFile = context.OpenAssetFile(material::GetFileNameForAssetName(asset->m_name)); - - if (!assetFile) - return; - - DumpMaterialAsJson(*assetFile, *asset->Asset(), context); -} diff --git a/src/ObjWriting/Game/IW3/Material/DumperMaterialIW3.h b/src/ObjWriting/Game/IW3/Material/DumperMaterialIW3.h deleted file mode 100644 index 8438f6af..00000000 --- a/src/ObjWriting/Game/IW3/Material/DumperMaterialIW3.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW3/IW3.h" - -namespace IW3 -{ - class AssetDumperMaterial final : public AbstractAssetDumper - { - public: - void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW3 diff --git a/src/ObjWriting/Game/IW3/ObjWriterIW3.cpp b/src/ObjWriting/Game/IW3/ObjWriterIW3.cpp index 55da3a17..418e3156 100644 --- a/src/ObjWriting/Game/IW3/ObjWriterIW3.cpp +++ b/src/ObjWriting/Game/IW3/ObjWriterIW3.cpp @@ -1,16 +1,15 @@ #include "ObjWriterIW3.h" -#include "AssetDumpers/AssetDumperGfxImage.h" -#include "AssetDumpers/AssetDumperLoadedSound.h" -#include "AssetDumpers/AssetDumperLocalizeEntry.h" -#include "AssetDumpers/AssetDumperMapEnts.h" -#include "AssetDumpers/AssetDumperRawFile.h" -#include "AssetDumpers/AssetDumperStringTable.h" -#include "AssetDumpers/AssetDumperWeapon.h" -#include "AssetDumpers/AssetDumperXModel.h" #include "Game/IW3/GameAssetPoolIW3.h" -#include "Material/DumperMaterialIW3.h" +#include "Game/IW3/Material/MaterialJsonDumperIW3.h" +#include "Game/IW3/XModel/XModelDumperIW3.h" +#include "Image/ImageDumperIW3.h" +#include "Localize/LocalizeDumperIW3.h" +#include "Maps/MapEntsDumperIW3.h" #include "ObjWriting.h" +#include "RawFile/RawFileDumperIW3.h" +#include "Sound/LoadedSoundDumperIW3.h" +#include "StringTable/StringTableDumperIW3.h" using namespace IW3; @@ -27,30 +26,30 @@ bool ObjWriter::DumpZone(AssetDumpingContext& context) const // DUMP_ASSET_POOL(AssetDumperPhysPreset, m_phys_preset, ASSET_TYPE_PHYSPRESET) // DUMP_ASSET_POOL(AssetDumperXAnimParts, m_xanim_parts, ASSET_TYPE_XANIMPARTS) - DUMP_ASSET_POOL(AssetDumperXModel, m_xmodel, ASSET_TYPE_XMODEL) - DUMP_ASSET_POOL(AssetDumperMaterial, m_material, ASSET_TYPE_MATERIAL) + DUMP_ASSET_POOL(xmodel::DumperIW3, m_xmodel, ASSET_TYPE_XMODEL) + DUMP_ASSET_POOL(material::JsonDumperIW3, m_material, ASSET_TYPE_MATERIAL) // DUMP_ASSET_POOL(AssetDumperMaterialTechniqueSet, m_technique_set, ASSET_TYPE_TECHNIQUE_SET) - DUMP_ASSET_POOL(AssetDumperGfxImage, m_image, ASSET_TYPE_IMAGE) + DUMP_ASSET_POOL(image::DumperIW3, m_image, ASSET_TYPE_IMAGE) // DUMP_ASSET_POOL(AssetDumpersnd_alias_list_t, m_sound, ASSET_TYPE_SOUND) // DUMP_ASSET_POOL(AssetDumperSndCurve, m_sound_curve, ASSET_TYPE_SOUND_CURVE) - DUMP_ASSET_POOL(AssetDumperLoadedSound, m_loaded_sound, ASSET_TYPE_LOADED_SOUND) + DUMP_ASSET_POOL(sound::LoadedSoundDumperIW3, m_loaded_sound, ASSET_TYPE_LOADED_SOUND) // DUMP_ASSET_POOL(AssetDumperClipMap, m_clip_map, ASSET_TYPE_CLIPMAP_PVS) // DUMP_ASSET_POOL(AssetDumperComWorld, m_com_world, ASSET_TYPE_COMWORLD) // DUMP_ASSET_POOL(AssetDumperGameWorldSp, m_game_world_sp, ASSET_TYPE_GAMEWORLD_SP) // DUMP_ASSET_POOL(AssetDumperGameWorldMp, m_game_world_mp, ASSET_TYPE_GAMEWORLD_MP) - DUMP_ASSET_POOL(AssetDumperMapEnts, m_map_ents, ASSET_TYPE_MAP_ENTS) + DUMP_ASSET_POOL(map_ents::DumperIW3, m_map_ents, ASSET_TYPE_MAP_ENTS) // DUMP_ASSET_POOL(AssetDumperGfxWorld, m_gfx_world, ASSET_TYPE_GFXWORLD) // DUMP_ASSET_POOL(AssetDumperGfxLightDef, m_gfx_light_def, ASSET_TYPE_LIGHT_DEF) // DUMP_ASSET_POOL(AssetDumperFont_s, m_font, ASSET_TYPE_FONT) // DUMP_ASSET_POOL(AssetDumperMenuList, m_menu_list, ASSET_TYPE_MENULIST) // DUMP_ASSET_POOL(AssetDumpermenuDef_t, m_menu_def, ASSET_TYPE_MENU) - DUMP_ASSET_POOL(AssetDumperLocalizeEntry, m_localize, ASSET_TYPE_LOCALIZE_ENTRY) + DUMP_ASSET_POOL(localize::DumperIW3, m_localize, ASSET_TYPE_LOCALIZE_ENTRY) // DUMP_ASSET_POOL(AssetDumperWeapon, m_weapon, ASSET_TYPE_WEAPON) // DUMP_ASSET_POOL(AssetDumperSndDriverGlobals, m_snd_driver_globals, ASSET_TYPE_SNDDRIVER_GLOBALS) // DUMP_ASSET_POOL(AssetDumperFxEffectDef, m_fx, ASSET_TYPE_FX) // DUMP_ASSET_POOL(AssetDumperFxImpactTable, m_fx_impact_table, ASSET_TYPE_IMPACT_FX) - DUMP_ASSET_POOL(AssetDumperRawFile, m_raw_file, ASSET_TYPE_RAWFILE) - DUMP_ASSET_POOL(AssetDumperStringTable, m_string_table, ASSET_TYPE_STRINGTABLE) + DUMP_ASSET_POOL(raw_file::DumperIW3, m_raw_file, ASSET_TYPE_RAWFILE) + DUMP_ASSET_POOL(string_table::DumperIW3, m_string_table, ASSET_TYPE_STRINGTABLE) return true; diff --git a/src/ObjWriting/Game/IW3/RawFile/RawFileDumperIW3.cpp b/src/ObjWriting/Game/IW3/RawFile/RawFileDumperIW3.cpp new file mode 100644 index 00000000..4b2eb11b --- /dev/null +++ b/src/ObjWriting/Game/IW3/RawFile/RawFileDumperIW3.cpp @@ -0,0 +1,23 @@ +#include "RawFileDumperIW3.h" + +using namespace IW3; + +namespace raw_file +{ + bool DumperIW3::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperIW3::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* rawFile = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name); + + if (!assetFile) + return; + + auto& stream = *assetFile; + stream.write(rawFile->buffer, rawFile->len); + } +} // namespace raw_file diff --git a/src/ObjWriting/Game/IW3/RawFile/RawFileDumperIW3.h b/src/ObjWriting/Game/IW3/RawFile/RawFileDumperIW3.h new file mode 100644 index 00000000..250bea7c --- /dev/null +++ b/src/ObjWriting/Game/IW3/RawFile/RawFileDumperIW3.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW3/IW3.h" + +namespace raw_file +{ + class DumperIW3 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace raw_file diff --git a/src/ObjWriting/Game/IW3/Sound/LoadedSoundDumperIW3.cpp b/src/ObjWriting/Game/IW3/Sound/LoadedSoundDumperIW3.cpp new file mode 100644 index 00000000..ccf79977 --- /dev/null +++ b/src/ObjWriting/Game/IW3/Sound/LoadedSoundDumperIW3.cpp @@ -0,0 +1,52 @@ +#include "LoadedSoundDumperIW3.h" + +#include "Sound/WavTypes.h" +#include "Sound/WavWriter.h" + +#include + +using namespace IW3; + +namespace +{ + void DumpWavPcm(const LoadedSound* asset, std::ostream& stream) + { + const WavWriter writer(stream); + + const WavMetaData metaData{.channelCount = static_cast(asset->sound.info.channels), + .samplesPerSec = static_cast(asset->sound.info.rate), + .bitsPerSample = static_cast(asset->sound.info.bits)}; + + writer.WritePcmHeader(metaData, asset->sound.info.data_len); + writer.WritePcmData(asset->sound.data, asset->sound.info.data_len); + } +} // namespace + +namespace sound +{ + bool LoadedSoundDumperIW3::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void LoadedSoundDumperIW3::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* loadedSound = asset->Asset(); + const auto assetFile = context.OpenAssetFile(std::format("sound/{}", asset->m_name)); + + if (!assetFile) + return; + + auto& stream = *assetFile; + switch (static_cast(loadedSound->sound.info.format)) + { + case WavFormat::PCM: + DumpWavPcm(loadedSound, stream); + break; + + default: + std::cerr << std::format("Unknown format {} for loaded sound: {}\n", loadedSound->sound.info.format, loadedSound->name); + break; + } + } +} // namespace sound diff --git a/src/ObjWriting/Game/IW3/Sound/LoadedSoundDumperIW3.h b/src/ObjWriting/Game/IW3/Sound/LoadedSoundDumperIW3.h new file mode 100644 index 00000000..458af961 --- /dev/null +++ b/src/ObjWriting/Game/IW3/Sound/LoadedSoundDumperIW3.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW3/IW3.h" + +namespace sound +{ + class LoadedSoundDumperIW3 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace sound diff --git a/src/ObjWriting/Game/IW3/StringTable/StringTableDumperIW3.cpp b/src/ObjWriting/Game/IW3/StringTable/StringTableDumperIW3.cpp new file mode 100644 index 00000000..b7188a34 --- /dev/null +++ b/src/ObjWriting/Game/IW3/StringTable/StringTableDumperIW3.cpp @@ -0,0 +1,34 @@ +#include "StringTableDumperIW3.h" + +#include "Csv/CsvStream.h" + +using namespace IW3; + +namespace string_table +{ + bool DumperIW3::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperIW3::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* stringTable = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name); + + if (!assetFile) + return; + + CsvOutputStream csv(*assetFile); + + for (auto row = 0; row < stringTable->rowCount; row++) + { + for (auto column = 0; column < stringTable->columnCount; column++) + { + csv.WriteColumn(stringTable->values[column + row * stringTable->columnCount]); + } + + csv.NextRow(); + } + } +} // namespace string_table diff --git a/src/ObjWriting/Game/IW3/StringTable/StringTableDumperIW3.h b/src/ObjWriting/Game/IW3/StringTable/StringTableDumperIW3.h new file mode 100644 index 00000000..21ef05d5 --- /dev/null +++ b/src/ObjWriting/Game/IW3/StringTable/StringTableDumperIW3.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW3/IW3.h" + +namespace string_table +{ + class DumperIW3 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace string_table diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperAddonMapEnts.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperAddonMapEnts.cpp deleted file mode 100644 index 58c745c5..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperAddonMapEnts.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#define NOMINMAX -#include "AssetDumperAddonMapEnts.h" - -#include - -using namespace IW4; - -bool AssetDumperAddonMapEnts::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperAddonMapEnts::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* addonMapEnts = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - - stream.write(addonMapEnts->entityString, std::max(addonMapEnts->numEntityChars - 1, 0)); -} diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperAddonMapEnts.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperAddonMapEnts.h deleted file mode 100644 index 8a5ad601..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperAddonMapEnts.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" - -namespace IW4 -{ - class AssetDumperAddonMapEnts final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxImage.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxImage.h deleted file mode 100644 index bcbee6ec..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxImage.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" -#include "Image/IImageWriter.h" - -#include - -namespace IW4 -{ - class AssetDumperGfxImage final : public AbstractAssetDumper - { - std::unique_ptr m_writer; - - [[nodiscard]] std::string GetAssetFileName(const XAssetInfo& asset) const; - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - - public: - AssetDumperGfxImage(); - }; -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxLightDef.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxLightDef.cpp deleted file mode 100644 index af05c62d..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxLightDef.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "AssetDumperGfxLightDef.h" - -#include - -using namespace IW4; - -std::string AssetDumperGfxLightDef::GetAssetFilename(const std::string& assetName) -{ - std::ostringstream ss; - - ss << "lights/" << assetName; - - return ss.str(); -} - -bool AssetDumperGfxLightDef::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperGfxLightDef::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* lightDef = asset->Asset(); - const auto assetFile = context.OpenAssetFile(GetAssetFilename(asset->m_name)); - - if (!assetFile || lightDef->attenuation.image == nullptr || lightDef->attenuation.image->name == nullptr) - return; - - auto& stream = *assetFile; - - const auto* imageName = lightDef->attenuation.image->name; - if (imageName[0] == ',') - imageName = &imageName[1]; - - stream << lightDef->attenuation.samplerState << imageName << static_cast(lightDef->lmapLookupStart); -} diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxLightDef.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxLightDef.h deleted file mode 100644 index 275712ef..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxLightDef.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" - -namespace IW4 -{ - class AssetDumperGfxLightDef final : public AbstractAssetDumper - { - static std::string GetAssetFilename(const std::string& assetName); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLeaderboardDef.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLeaderboardDef.cpp deleted file mode 100644 index a761b471..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLeaderboardDef.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "AssetDumperLeaderboardDef.h" - -#include "Game/IW4/Leaderboard/JsonLeaderboardDefWriter.h" - -#include -#include - -using namespace IW4; - -bool AssetDumperLeaderboardDef::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperLeaderboardDef::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto assetName = asset->m_name; - const auto assetFile = context.OpenAssetFile(std::format("leaderboards/{}.json", assetName)); - - if (!assetFile) - return; - - DumpLeaderboardDefAsJson(*assetFile, asset->Asset()); -} diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLeaderboardDef.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLeaderboardDef.h deleted file mode 100644 index c8a344bf..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLeaderboardDef.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" - -namespace IW4 -{ - class AssetDumperLeaderboardDef final : public AbstractAssetDumper - { - protected: - _NODISCARD bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLoadedSound.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLoadedSound.cpp deleted file mode 100644 index 7348db5e..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLoadedSound.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "AssetDumperLoadedSound.h" - -#include "Sound/WavTypes.h" -#include "Sound/WavWriter.h" - -#include - -using namespace IW4; - -bool AssetDumperLoadedSound::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperLoadedSound::DumpWavPcm(const LoadedSound* asset, std::ostream& stream) -{ - const WavWriter writer(stream); - - const WavMetaData metaData{.channelCount = static_cast(asset->sound.info.channels), - .samplesPerSec = static_cast(asset->sound.info.rate), - .bitsPerSample = static_cast(asset->sound.info.bits)}; - - writer.WritePcmHeader(metaData, asset->sound.info.data_len); - writer.WritePcmData(asset->sound.data, asset->sound.info.data_len); -} - -void AssetDumperLoadedSound::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* loadedSound = asset->Asset(); - const auto assetFile = context.OpenAssetFile(std::format("sound/{}", asset->m_name)); - - if (!assetFile) - return; - - auto& stream = *assetFile; - switch (static_cast(loadedSound->sound.info.format)) - { - case WavFormat::PCM: - DumpWavPcm(loadedSound, stream); - break; - - default: - std::cerr << std::format("Unknown format {} for loaded sound: {}\n", loadedSound->sound.info.format, loadedSound->name); - break; - } -} diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLoadedSound.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLoadedSound.h deleted file mode 100644 index 8065af76..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLoadedSound.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" - -namespace IW4 -{ - class AssetDumperLoadedSound final : public AbstractAssetDumper - { - static void DumpWavPcm(const LoadedSound* asset, std::ostream& stream); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLocalizeEntry.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLocalizeEntry.cpp deleted file mode 100644 index ef1799ac..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLocalizeEntry.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "AssetDumperLocalizeEntry.h" - -#include "Dumping/Localize/StringFileDumper.h" -#include "Localize/LocalizeCommon.h" - -#include -#include - -using namespace IW4; - -void AssetDumperLocalizeEntry::DumpPool(AssetDumpingContext& context, AssetPool* pool) -{ - if (pool->m_asset_lookup.empty()) - return; - - const auto language = LocalizeCommon::GetNameOfLanguage(context.m_zone.m_language); - const auto assetFile = context.OpenAssetFile(std::format("{}/localizedstrings/{}.str", language, context.m_zone.m_name)); - - if (assetFile) - { - StringFileDumper stringFileDumper(context.m_zone, *assetFile); - - stringFileDumper.SetLanguageName(language); - - // Magic string. Original string files do have this config file. The purpose of the config file is unknown though. - stringFileDumper.SetConfigFile(R"(C:/trees/cod3/cod3/bin/StringEd.cfg)"); - - stringFileDumper.SetNotes(""); - - for (auto* localizeEntry : *pool) - { - stringFileDumper.WriteLocalizeEntry(localizeEntry->m_name, localizeEntry->Asset()->value); - } - - stringFileDumper.Finalize(); - } - else - { - std::cerr << std::format("Could not create string file for dumping localized strings of zone '{}'\n", context.m_zone.m_name); - } -} diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLocalizeEntry.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLocalizeEntry.h deleted file mode 100644 index cc1e07f2..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLocalizeEntry.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" - -namespace IW4 -{ - class AssetDumperLocalizeEntry final : public IAssetDumper - { - public: - void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; - }; -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMenuDef.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMenuDef.cpp deleted file mode 100644 index 4a90b9ad..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMenuDef.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "AssetDumperMenuDef.h" - -#include "AssetDumperMenuList.h" -#include "Game/IW4/GameAssetPoolIW4.h" -#include "Game/IW4/Menu/MenuDumperIW4.h" -#include "Menu/AbstractMenuDumper.h" -#include "ObjWriting.h" - -#include -#include - -using namespace IW4; - -std::string AssetDumperMenuDef::GetPathForMenu(menu::MenuDumpingZoneState* zoneState, XAssetInfo* asset) -{ - const auto menuDumpingState = zoneState->m_menu_dumping_state_map.find(asset->Asset()); - - if (menuDumpingState == zoneState->m_menu_dumping_state_map.end()) - return "ui_mp/" + std::string(asset->Asset()->window.name) + ".menu"; - - return menuDumpingState->second.m_path; -} - -bool AssetDumperMenuDef::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperMenuDef::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* menu = asset->Asset(); - auto* zoneState = context.GetZoneAssetDumperState(); - - if (!ObjWriting::ShouldHandleAssetType(ASSET_TYPE_MENULIST)) - { - // Make sure menu paths based on menu lists are created - const auto* gameAssetPool = dynamic_cast(asset->m_zone->m_pools.get()); - for (auto* menuListAsset : *gameAssetPool->m_menu_list) - AssetDumperMenuList::CreateDumpingStateForMenuList(zoneState, menuListAsset->Asset()); - } - - const auto menuFilePath = GetPathForMenu(zoneState, asset); - const auto assetFile = context.OpenAssetFile(menuFilePath); - - if (!assetFile) - return; - - MenuDumper menuDumper(*assetFile); - - menuDumper.Start(); - menuDumper.WriteMenu(menu); - menuDumper.End(); -} diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMenuDef.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMenuDef.h deleted file mode 100644 index fbebc2c6..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMenuDef.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" -#include "Menu/MenuDumpingZoneState.h" - -namespace IW4 -{ - class AssetDumperMenuDef final : public AbstractAssetDumper - { - static std::string GetPathForMenu(menu::MenuDumpingZoneState* zoneState, XAssetInfo* asset); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMenuList.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMenuList.cpp deleted file mode 100644 index 2c4c690d..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMenuList.cpp +++ /dev/null @@ -1,179 +0,0 @@ -#include "AssetDumperMenuList.h" - -#include "Game/IW4/Menu/MenuDumperIW4.h" -#include "Menu/AbstractMenuDumper.h" -#include "ObjWriting.h" - -#include -#include -#include -#include - -namespace fs = std::filesystem; - -using namespace IW4; - -std::vector AssetDumperMenuList::GetAllUniqueExpressionSupportingData(const MenuList* menuList) -{ - std::vector result; - std::set alreadyAddedSupportingData; - - if (menuList->menus == nullptr) - return result; - - for (auto i = 0; i < menuList->menuCount; i++) - { - if (menuList->menus[i] == nullptr) - continue; - - const auto* menu = menuList->menus[i]; - - if (menu->expressionData == nullptr) - continue; - - if (alreadyAddedSupportingData.find(menu->expressionData) == alreadyAddedSupportingData.end()) - { - result.push_back(menu->expressionData); - alreadyAddedSupportingData.emplace(menu->expressionData); - } - } - - return result; -} - -void AssetDumperMenuList::DumpFunctions(MenuDumper& menuDumper, const MenuList* menuList) -{ - const auto allSupportingData = GetAllUniqueExpressionSupportingData(menuList); - auto functionIndex = 0u; - - assert(allSupportingData.size() <= 1); - - for (const auto* supportingData : allSupportingData) - { - if (supportingData->uifunctions.functions == nullptr) - continue; - - for (auto i = 0; i < supportingData->uifunctions.totalFunctions; i++) - { - const auto* function = supportingData->uifunctions.functions[i]; - if (function != nullptr) - { - std::stringstream ss; - ss << "FUNC_" << functionIndex; - - menuDumper.WriteFunctionDef(ss.str(), function); - } - - functionIndex++; - } - } -} - -void AssetDumperMenuList::DumpMenus(MenuDumper& menuDumper, menu::MenuDumpingZoneState* zoneState, const MenuList* menuList) -{ - for (auto menuNum = 0; menuNum < menuList->menuCount; menuNum++) - { - const auto* menu = menuList->menus[menuNum]; - - const auto menuDumpingState = zoneState->m_menu_dumping_state_map.find(menu); - if (menuDumpingState == zoneState->m_menu_dumping_state_map.end()) - continue; - - // If the menu was embedded directly as menu list write its data in the menu list file - if (menuDumpingState->second.m_alias_menu_list == menuList) - menuDumper.WriteMenu(menu); - else - menuDumper.IncludeMenu(menuDumpingState->second.m_path); - } -} - -bool AssetDumperMenuList::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperMenuList::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* menuList = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name); - - if (!assetFile) - return; - - auto* zoneState = context.GetZoneAssetDumperState(); - - MenuDumper menuDumper(*assetFile); - - menuDumper.Start(); - - if (!ObjWriting::Configuration.MenuLegacyMode) - DumpFunctions(menuDumper, menuList); - - DumpMenus(menuDumper, zoneState, menuList); - - menuDumper.End(); -} - -std::string AssetDumperMenuList::PathForMenu(const std::string& menuListParentPath, const menuDef_t* menu) -{ - const auto* menuAssetName = menu->window.name; - - if (!menuAssetName) - return ""; - - if (menuAssetName[0] == ',') - menuAssetName = &menuAssetName[1]; - - std::ostringstream ss; - ss << menuListParentPath << menuAssetName << ".menu"; - - return ss.str(); -} - -void AssetDumperMenuList::CreateDumpingStateForMenuList(menu::MenuDumpingZoneState* zoneState, const MenuList* menuList) -{ - if (menuList->menuCount <= 0 || menuList->menus == nullptr || menuList->name == nullptr) - return; - - const std::string menuListName(menuList->name); - const fs::path p(menuListName); - std::string parentPath; - if (p.has_parent_path()) - parentPath = p.parent_path().string() + "/"; - - for (auto i = 0; i < menuList->menuCount; i++) - { - auto* menu = menuList->menus[i]; - - if (menu == nullptr) - continue; - - auto existingState = zoneState->m_menu_dumping_state_map.find(menu); - if (existingState == zoneState->m_menu_dumping_state_map.end()) - { - auto menuPath = PathForMenu(parentPath, menu); - const auto isTheSameAsMenuList = menuPath == menuListName; - zoneState->CreateMenuDumpingState(menu, std::move(menuPath), isTheSameAsMenuList ? menuList : nullptr); - } - else if (existingState->second.m_alias_menu_list == nullptr) - { - auto menuPath = PathForMenu(parentPath, menu); - const auto isTheSameAsMenuList = menuPath == menuListName; - if (isTheSameAsMenuList) - { - existingState->second.m_alias_menu_list = menuList; - existingState->second.m_path = std::move(menuPath); - } - } - } -} - -void AssetDumperMenuList::DumpPool(AssetDumpingContext& context, AssetPool* pool) -{ - auto* zoneState = context.GetZoneAssetDumperState(); - - for (auto* asset : *pool) - CreateDumpingStateForMenuList(zoneState, asset->Asset()); - - AbstractAssetDumper::DumpPool(context, pool); -} diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMenuList.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMenuList.h deleted file mode 100644 index 2e368d7f..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMenuList.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" -#include "Game/IW4/Menu/MenuDumperIW4.h" -#include "Menu/MenuDumpingZoneState.h" - -namespace IW4 -{ - class AssetDumperMenuList final : public AbstractAssetDumper - { - static std::vector GetAllUniqueExpressionSupportingData(const MenuList* menuList); - - static void DumpFunctions(MenuDumper& menuDumper, const MenuList* menuList); - static void DumpMenus(MenuDumper& menuDumper, menu::MenuDumpingZoneState* zoneState, const MenuList* menuList); - - static std::string PathForMenu(const std::string& menuListParentPath, const menuDef_t* menu); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - - public: - static void CreateDumpingStateForMenuList(menu::MenuDumpingZoneState* zoneState, const MenuList* menuList); - void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; - }; -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPhysCollmap.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPhysCollmap.cpp deleted file mode 100644 index 7055e8aa..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPhysCollmap.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include "AssetDumperPhysCollmap.h" - -#include "Dumping/MapFile/MapFileDumper.h" - -#include -#include - -using namespace IW4; - -std::string AssetDumperPhysCollmap::GetAssetFilename(const std::string& assetName) -{ - std::ostringstream ss; - - ss << "phys_collmaps/" << assetName << ".map"; - - return ss.str(); -} - -bool AssetDumperPhysCollmap::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperPhysCollmap::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* physCollmap = asset->Asset(); - const auto assetFile = context.OpenAssetFile(GetAssetFilename(asset->m_name)); - - if (!assetFile) - return; - - MapFileDumper mapFileDumper(*assetFile); - mapFileDumper.Init(); - - if (physCollmap->count <= 0 || physCollmap->geoms == nullptr) - return; - - mapFileDumper.BeginEntity(); - - mapFileDumper.WriteKeyValue("classname", "worldspawn"); - - for (auto i = 0u; i < physCollmap->count; i++) - { - const auto& geom = physCollmap->geoms[i]; - mapFileDumper.BeginBrush(); - - switch (geom.type) - { - case PHYS_GEOM_NONE: - // TODO: Dump BrushWrapper (probably GJK related) - mapFileDumper.WriteComment("TODO: Brush data"); - break; - case PHYS_GEOM_BOX: - mapFileDumper.WritePhysicsBox({ - {geom.bounds.midPoint.v[0], geom.bounds.midPoint.v[1], geom.bounds.midPoint.v[2]}, - {geom.bounds.halfSize.v[0], geom.bounds.halfSize.v[1], geom.bounds.halfSize.v[2]}, - {geom.orientation[0][0], geom.orientation[0][1], geom.orientation[0][2] }, - {geom.orientation[1][0], geom.orientation[1][1], geom.orientation[1][2] }, - {geom.orientation[2][0], geom.orientation[2][1], geom.orientation[2][2] } - }); - break; - - case PHYS_GEOM_CYLINDER: - mapFileDumper.WritePhysicsCylinder({ - {geom.bounds.midPoint.v[0], geom.bounds.midPoint.v[1], geom.bounds.midPoint.v[2]}, - geom.bounds.halfSize.v[0], - geom.bounds.halfSize.v[2] * 2, - {geom.orientation[0][0], geom.orientation[0][1], geom.orientation[0][2] } - }); - break; - - case PHYS_GEOM_BRUSHMODEL: - case PHYS_GEOM_BRUSH: - case PHYS_GEOM_COLLMAP: - case PHYS_GEOM_CAPSULE: - case PHYS_GEOM_GLASS: - default: - // These do not seem to appear inside any collmap assets - assert(false); - break; - } - - mapFileDumper.EndBrush(); - } - - mapFileDumper.EndEntity(); -} diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPhysCollmap.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPhysCollmap.h deleted file mode 100644 index 213f1ce1..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPhysCollmap.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" - -namespace IW4 -{ - class AssetDumperPhysCollmap final : public AbstractAssetDumper - { - static std::string GetAssetFilename(const std::string& assetName); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPhysPreset.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPhysPreset.cpp deleted file mode 100644 index bfd6d990..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPhysPreset.cpp +++ /dev/null @@ -1,107 +0,0 @@ -#include "AssetDumperPhysPreset.h" - -#include "Game/IW4/InfoString/InfoStringFromStructConverter.h" -#include "Game/IW4/ObjConstantsIW4.h" -#include "Game/IW4/PhysPreset/PhysPresetFields.h" - -#include -#include -#include -#include - -using namespace IW4; - -namespace IW4 -{ - class InfoStringFromPhysPresetConverter final : public InfoStringFromStructConverter - { - protected: - void FillFromExtensionField(const cspField_t& field) override - { - assert(false); - } - - public: - InfoStringFromPhysPresetConverter(const PhysPresetInfo* structure, - const cspField_t* fields, - const size_t fieldCount, - std::function scriptStringValueCallback) - : InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback)) - { - } - }; -} // namespace IW4 - -void AssetDumperPhysPreset::CopyToPhysPresetInfo(const PhysPreset* physPreset, PhysPresetInfo* physPresetInfo) -{ - physPresetInfo->mass = std::clamp(physPreset->mass * 1000.0f, 1.0f, 2000.0f); - physPresetInfo->bounce = physPreset->bounce; - - if (std::isinf(physPreset->friction)) - { - physPresetInfo->isFrictionInfinity = 1; - physPresetInfo->friction = 0; - } - else - { - physPresetInfo->isFrictionInfinity = 0; - physPresetInfo->friction = physPreset->friction; - } - - physPresetInfo->bulletForceScale = physPreset->bulletForceScale; - physPresetInfo->explosiveForceScale = physPreset->explosiveForceScale; - physPresetInfo->sndAliasPrefix = physPreset->sndAliasPrefix; - physPresetInfo->piecesSpreadFraction = physPreset->piecesSpreadFraction; - physPresetInfo->piecesUpwardVelocity = physPreset->piecesUpwardVelocity; - physPresetInfo->tempDefaultToCylinder = physPreset->tempDefaultToCylinder ? 1 : 0; - physPresetInfo->perSurfaceSndAlias = physPreset->perSurfaceSndAlias ? 1 : 0; -} - -InfoString AssetDumperPhysPreset::CreateInfoString(XAssetInfo* asset) -{ - auto* physPresetInfo = new PhysPresetInfo; - CopyToPhysPresetInfo(asset->Asset(), physPresetInfo); - - InfoStringFromPhysPresetConverter converter(physPresetInfo, - phys_preset_fields, - std::extent_v, - [asset](const scr_string_t scrStr) -> std::string - { - assert(scrStr < asset->m_zone->m_script_strings.Count()); - if (scrStr >= asset->m_zone->m_script_strings.Count()) - return ""; - - return asset->m_zone->m_script_strings[scrStr]; - }); - - return converter.Convert(); -} - -bool AssetDumperPhysPreset::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperPhysPreset::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - // Only dump raw when no gdt available - if (context.m_gdt) - { - const auto infoString = CreateInfoString(asset); - GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_PHYS_PRESET); - infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_PHYS_PRESET, gdtEntry); - context.m_gdt->WriteEntry(gdtEntry); - } - else - { - const auto assetFile = context.OpenAssetFile("physic/" + asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - const auto infoString = CreateInfoString(asset); - const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_PHYS_PRESET); - stream.write(stringValue.c_str(), stringValue.size()); - } -} diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPhysPreset.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPhysPreset.h deleted file mode 100644 index 5de816cc..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPhysPreset.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" -#include "InfoString/InfoString.h" - -namespace IW4 -{ - class AssetDumperPhysPreset final : public AbstractAssetDumper - { - static void CopyToPhysPresetInfo(const PhysPreset* physPreset, PhysPresetInfo* physPresetInfo); - static InfoString CreateInfoString(XAssetInfo* asset); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPixelShader.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPixelShader.cpp deleted file mode 100644 index 40bb4089..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPixelShader.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "AssetDumperPixelShader.h" - -#include - -using namespace IW4; - -bool AssetDumperPixelShader::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperPixelShader::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* pixelShader = asset->Asset(); - - std::ostringstream ss; - ss << "shader_bin/ps_" << pixelShader->name << ".cso"; - - const auto shaderFile = context.OpenAssetFile(ss.str()); - - if (!shaderFile) - return; - - shaderFile->write(reinterpret_cast(pixelShader->prog.loadDef.program), - static_cast(pixelShader->prog.loadDef.programSize) * 4u); -} diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPixelShader.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPixelShader.h deleted file mode 100644 index 925e80f9..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperPixelShader.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" - -namespace IW4 -{ - class AssetDumperPixelShader final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperRawFile.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperRawFile.h deleted file mode 100644 index 5b2c2120..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperRawFile.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" - -namespace IW4 -{ - class AssetDumperRawFile final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperSndCurve.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperSndCurve.cpp deleted file mode 100644 index 71958fbb..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperSndCurve.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "AssetDumperSndCurve.h" - -#include "Dumping/SndCurve/SndCurveDumper.h" - -#include - -using namespace IW4; - -std::string AssetDumperSndCurve::GetAssetFilename(const std::string& assetName) -{ - std::ostringstream ss; - - ss << "soundaliases/" << assetName << ".vfcurve"; - - return ss.str(); -} - -bool AssetDumperSndCurve::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperSndCurve::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* sndCurve = asset->Asset(); - - const auto assetFile = context.OpenAssetFile(GetAssetFilename(sndCurve->filename)); - - if (!assetFile) - return; - - SndCurveDumper dumper(*assetFile); - - const auto knotCount = std::min(static_cast(sndCurve->knotCount), std::extent_v); - dumper.Init(knotCount); - - for (auto i = 0u; i < knotCount; i++) - dumper.WriteKnot(sndCurve->knots[i][0], sndCurve->knots[i][1]); -} diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperSndCurve.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperSndCurve.h deleted file mode 100644 index 0139fafe..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperSndCurve.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" - -namespace IW4 -{ - class AssetDumperSndCurve final : public AbstractAssetDumper - { - static std::string GetAssetFilename(const std::string& assetName); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStringTable.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStringTable.cpp deleted file mode 100644 index 8a7bd5e4..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStringTable.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "AssetDumperStringTable.h" - -#include "Csv/CsvStream.h" - -using namespace IW4; - -bool AssetDumperStringTable::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperStringTable::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* stringTable = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name); - - if (!assetFile) - return; - - CsvOutputStream csv(*assetFile); - - for (auto row = 0; row < stringTable->rowCount; row++) - { - for (auto column = 0; column < stringTable->columnCount; column++) - { - const auto* cell = &stringTable->values[column + row * stringTable->columnCount]; - if (cell->string != nullptr) - { - csv.WriteColumn(cell->string); - } - else - { - csv.WriteColumn(""); - } - } - - csv.NextRow(); - } -} diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStringTable.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStringTable.h deleted file mode 100644 index 9d50d431..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStringTable.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" - -namespace IW4 -{ - class AssetDumperStringTable final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStructuredDataDefSet.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStructuredDataDefSet.cpp deleted file mode 100644 index f25c6bf4..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStructuredDataDefSet.cpp +++ /dev/null @@ -1,206 +0,0 @@ -#include "AssetDumperStructuredDataDefSet.h" - -#include "StructuredDataDef/StructuredDataDefDumper.h" - -#include -#include -#include - -using namespace IW4; -using namespace std::string_literals; - -CommonStructuredDataType AssetDumperStructuredDataDefSet::ConvertType(const CommonStructuredDataDef* def, const StructuredDataType in) -{ - CommonStructuredDataType out; - - switch (in.type) - { - case DATA_INT: - out.m_category = CommonStructuredDataTypeCategory::INT; - break; - case DATA_BYTE: - out.m_category = CommonStructuredDataTypeCategory::BYTE; - break; - case DATA_BOOL: - out.m_category = CommonStructuredDataTypeCategory::BOOL; - break; - case DATA_FLOAT: - out.m_category = CommonStructuredDataTypeCategory::FLOAT; - break; - case DATA_SHORT: - out.m_category = CommonStructuredDataTypeCategory::SHORT; - break; - case DATA_STRING: - out.m_category = CommonStructuredDataTypeCategory::STRING; - out.m_info.string_length = in.u.stringDataLength; - break; - case DATA_ENUM: - assert(!def->m_enums.empty()); - out.m_category = CommonStructuredDataTypeCategory::ENUM; - out.m_info.type_index = std::max(std::min(static_cast(in.u.enumIndex), def->m_enums.size() - 1uz), 0uz); - break; - case DATA_STRUCT: - assert(!def->m_structs.empty()); - out.m_category = CommonStructuredDataTypeCategory::STRUCT; - out.m_info.type_index = std::max(std::min(static_cast(in.u.structIndex), def->m_structs.size() - 1uz), 0uz); - break; - case DATA_INDEXED_ARRAY: - assert(!def->m_indexed_arrays.empty()); - out.m_category = CommonStructuredDataTypeCategory::INDEXED_ARRAY; - out.m_info.type_index = std::max(std::min(static_cast(in.u.indexedArrayIndex), def->m_indexed_arrays.size() - 1uz), 0uz); - break; - case DATA_ENUM_ARRAY: - assert(!def->m_enumed_arrays.empty()); - out.m_category = CommonStructuredDataTypeCategory::ENUM_ARRAY; - out.m_info.type_index = std::max(std::min(static_cast(in.u.enumedArrayIndex), def->m_enumed_arrays.size() - 1uz), 0uz); - break; - case DATA_COUNT: - default: - assert(false); - break; - } - - return out; -} - -void AssetDumperStructuredDataDefSet::ConvertEnum(CommonStructuredDataEnum* out, const StructuredDataEnum* in, const size_t enumIndex) -{ - out->m_name = "ENUM_" + std::to_string(enumIndex); - - if (in->reservedEntryCount > 0 && in->reservedEntryCount != in->entryCount) - out->m_reserved_entry_count = std::max(in->reservedEntryCount, 0); - else - out->m_reserved_entry_count = -1; - - out->m_entries.resize(static_cast(std::max(in->entryCount, 0))); - for (auto i = 0u; i < out->m_entries.size(); i++) - { - auto& outEntry = out->m_entries[i]; - const auto& inEntry = in->entries[i]; - - outEntry.m_name = std::string(inEntry.string); - outEntry.m_value = inEntry.index; - } - - out->SortEntriesByOffset(); -} - -void AssetDumperStructuredDataDefSet::ConvertStruct(const CommonStructuredDataDef* def, - const StructuredDataDef* gameDef, - CommonStructuredDataStruct* out, - const StructuredDataStruct* in, - const size_t structIndex) -{ - if (gameDef->rootType.type == DATA_STRUCT && structIndex == static_cast(gameDef->rootType.u.structIndex)) - { - out->m_name = "root"; - out->m_size_in_byte = gameDef->size; - } - else - { - out->m_name = "STRUCT_" + std::to_string(structIndex); - out->m_size_in_byte = static_cast(std::max(in->size, 0)); - } - - out->m_bit_offset = in->bitOffset; - - out->m_properties.resize(static_cast(std::max(in->propertyCount, 0))); - for (auto i = 0u; i < out->m_properties.size(); i++) - { - auto& outProperty = out->m_properties[i]; - const auto& inProperty = in->properties[i]; - - outProperty.m_name = std::string(inProperty.name); - outProperty.m_type = ConvertType(def, inProperty.type); - - if (inProperty.type.type == DATA_BOOL) - outProperty.m_offset_in_bits = inProperty.offset; - else - outProperty.m_offset_in_bits = inProperty.offset * 8; - } - - out->SortPropertiesByOffset(); -} - -void AssetDumperStructuredDataDefSet::ConvertIndexedArray(const CommonStructuredDataDef* def, - CommonStructuredDataIndexedArray* out, - const StructuredDataIndexedArray* in) -{ - out->m_element_count = static_cast(std::max(in->arraySize, 0)); - out->m_element_size_in_bits = in->elementType.type == DATA_BOOL ? 1 : in->elementSize * 8; - out->m_array_type = ConvertType(def, in->elementType); -} - -void AssetDumperStructuredDataDefSet::ConvertEnumedArray(const CommonStructuredDataDef* def, - CommonStructuredDataEnumedArray* out, - const StructuredDataEnumedArray* in) -{ - assert(!def->m_enums.empty()); - out->m_element_size_in_bits = in->elementType.type == DATA_BOOL ? 1 : in->elementSize * 8; - out->m_array_type = ConvertType(def, in->elementType); - out->m_enum_index = std::max(std::min(static_cast(in->enumIndex), def->m_enums.size() - 1uz), 0uz); - - if (def->m_enums.empty()) - { - assert(false); - return; - } - - out->m_element_count = def->m_enums[out->m_enum_index]->ElementCount(); -} - -std::unique_ptr AssetDumperStructuredDataDefSet::ConvertDef(const StructuredDataDef* in) -{ - auto out = std::make_unique(); - - out->m_version = in->version; - out->m_checksum = in->formatChecksum; - out->m_size_in_byte = in->size; - - out->m_enums.resize(static_cast(std::max(in->enumCount, 0))); - out->m_structs.resize(static_cast(std::max(in->structCount, 0))); - out->m_indexed_arrays.resize(static_cast(std::max(in->indexedArrayCount, 0))); - out->m_enumed_arrays.resize(static_cast(std::max(in->enumedArrayCount, 0))); - - for (auto i = 0u; i < out->m_enums.size(); i++) - { - auto _enum = std::make_unique(); - ConvertEnum(_enum.get(), &in->enums[i], i); - out->m_enums[i] = std::move(_enum); - } - for (auto i = 0u; i < out->m_structs.size(); i++) - { - auto _struct = std::make_unique(); - ConvertStruct(out.get(), in, _struct.get(), &in->structs[i], i); - out->m_structs[i] = std::move(_struct); - } - for (auto i = 0u; i < out->m_indexed_arrays.size(); i++) - ConvertIndexedArray(out.get(), &out->m_indexed_arrays[i], &in->indexedArrays[i]); - for (auto i = 0u; i < out->m_enumed_arrays.size(); i++) - ConvertEnumedArray(out.get(), &out->m_enumed_arrays[i], &in->enumedArrays[i]); - - out->m_root_type = ConvertType(out.get(), in->rootType); - - return out; -} - -bool AssetDumperStructuredDataDefSet::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperStructuredDataDefSet::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* set = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name); - - if (!assetFile || set->defs == nullptr) - return; - - StructuredDataDefDumper dumper(*assetFile); - for (auto i = 0u; i < set->defCount; i++) - { - const auto def = ConvertDef(&set->defs[i]); - dumper.DumpDef(*def); - } -} diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStructuredDataDefSet.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStructuredDataDefSet.h deleted file mode 100644 index 7859af57..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperStructuredDataDefSet.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" -#include "StructuredDataDef/CommonStructuredDataDef.h" - -#include - -namespace IW4 -{ - class AssetDumperStructuredDataDefSet final : public AbstractAssetDumper - { - static CommonStructuredDataType ConvertType(const CommonStructuredDataDef* def, StructuredDataType in); - static void ConvertEnum(CommonStructuredDataEnum* out, const StructuredDataEnum* in, size_t enumIndex); - static void ConvertStruct(const CommonStructuredDataDef* def, - const StructuredDataDef* gameDef, - CommonStructuredDataStruct* out, - const StructuredDataStruct* in, - size_t structIndex); - static void ConvertIndexedArray(const CommonStructuredDataDef* def, CommonStructuredDataIndexedArray* out, const StructuredDataIndexedArray* in); - static void ConvertEnumedArray(const CommonStructuredDataDef* def, CommonStructuredDataEnumedArray* out, const StructuredDataEnumedArray* in); - static std::unique_ptr ConvertDef(const StructuredDataDef* in); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTechniqueSet.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTechniqueSet.h deleted file mode 100644 index 67495b9b..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTechniqueSet.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" - -namespace IW4 -{ - class AssetDumperTechniqueSet final : public AbstractAssetDumper - { - static std::string GetTechniqueFileName(const MaterialTechnique* technique); - static std::string GetTechsetFileName(const MaterialTechniqueSet* techset); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTracer.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTracer.cpp deleted file mode 100644 index 3a903ebc..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTracer.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include "AssetDumperTracer.h" - -#include "Game/IW4/CommonIW4.h" -#include "Game/IW4/InfoString/InfoStringFromStructConverter.h" -#include "Game/IW4/ObjConstantsIW4.h" -#include "Game/IW4/Tracer/TracerFields.h" - -#include -#include -#include - -using namespace IW4; - -namespace IW4 -{ - class InfoStringFromTracerConverter final : public InfoStringFromStructConverter - { - protected: - void FillFromExtensionField(const cspField_t& field) override - { - assert(false); - } - - public: - InfoStringFromTracerConverter(const TracerDef* structure, - const cspField_t* fields, - const size_t fieldCount, - std::function scriptStringValueCallback) - : InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback)) - { - } - }; -} // namespace IW4 - -InfoString AssetDumperTracer::CreateInfoString(XAssetInfo* asset) -{ - InfoStringFromTracerConverter converter(asset->Asset(), - tracer_fields, - std::extent_v, - [asset](const scr_string_t scrStr) -> std::string - { - assert(scrStr < asset->m_zone->m_script_strings.Count()); - if (scrStr >= asset->m_zone->m_script_strings.Count()) - return ""; - - return asset->m_zone->m_script_strings[scrStr]; - }); - - return converter.Convert(); -} - -bool AssetDumperTracer::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperTracer::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - // Only dump raw when no gdt available - if (context.m_gdt) - { - const auto infoString = CreateInfoString(asset); - GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_TRACER); - infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_TRACER, gdtEntry); - context.m_gdt->WriteEntry(gdtEntry); - } - else - { - const auto assetFile = context.OpenAssetFile("tracer/" + asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - const auto infoString = CreateInfoString(asset); - const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_TRACER); - stream.write(stringValue.c_str(), stringValue.size()); - } -} diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTracer.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTracer.h deleted file mode 100644 index 6e32b860..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTracer.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" -#include "InfoString/InfoString.h" - -namespace IW4 -{ - class AssetDumperTracer final : public AbstractAssetDumper - { - static InfoString CreateInfoString(XAssetInfo* asset); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVehicle.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVehicle.h deleted file mode 100644 index 66a1f074..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVehicle.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" -#include "InfoString/InfoString.h" - -namespace IW4 -{ - class AssetDumperVehicle final : public AbstractAssetDumper - { - static InfoString CreateInfoString(XAssetInfo* asset); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVertexShader.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVertexShader.cpp deleted file mode 100644 index 6bc12d7a..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVertexShader.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "AssetDumperVertexShader.h" - -#include - -using namespace IW4; - -bool AssetDumperVertexShader::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperVertexShader::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* vertexShader = asset->Asset(); - - std::ostringstream ss; - ss << "shader_bin/vs_" << vertexShader->name << ".cso"; - - const auto shaderFile = context.OpenAssetFile(ss.str()); - - if (!shaderFile) - return; - - shaderFile->write(reinterpret_cast(vertexShader->prog.loadDef.program), - static_cast(vertexShader->prog.loadDef.programSize) * 4u); -} diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVertexShader.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVertexShader.h deleted file mode 100644 index a9d631ef..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVertexShader.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" - -namespace IW4 -{ - class AssetDumperVertexShader final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.h deleted file mode 100644 index 3abade7f..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" -#include "InfoString/InfoString.h" - -namespace IW4 -{ - class AssetDumperWeapon final : public AbstractAssetDumper - { - static void CopyToFullDef(const WeaponCompleteDef* weapon, WeaponFullDef* fullDef); - static InfoString CreateInfoString(XAssetInfo* asset); - static void DumpAccuracyGraphs(AssetDumpingContext& context, XAssetInfo* asset); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperXModel.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperXModel.cpp deleted file mode 100644 index a82ddbd8..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperXModel.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "AssetDumperXModel.h" - -#include "Game/IW4/XModel/XModelDumperIW4.h" - -using namespace IW4; - -bool AssetDumperXModel::ShouldDump(XAssetInfo* asset) -{ - return !asset->m_name.empty() && asset->m_name[0] != ','; -} - -void AssetDumperXModel::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - DumpXModel(context, asset); -} diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperXModel.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperXModel.h deleted file mode 100644 index 84be5262..00000000 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperXModel.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" - -namespace IW4 -{ - class AssetDumperXModel final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxImage.cpp b/src/ObjWriting/Game/IW4/Image/ImageDumperIW4.cpp similarity index 56% rename from src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxImage.cpp rename to src/ObjWriting/Game/IW4/Image/ImageDumperIW4.cpp index 4490e520..57fd3cf3 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperGfxImage.cpp +++ b/src/ObjWriting/Game/IW4/Image/ImageDumperIW4.cpp @@ -1,7 +1,8 @@ -#include "AssetDumperGfxImage.h" +#include "ImageDumperIW4.h" #include "Image/DdsWriter.h" #include "Image/Dx9TextureLoader.h" +#include "Image/ImageCommon.h" #include "Image/IwiLoader.h" #include "Image/IwiWriter8.h" #include "ObjWriting.h" @@ -35,7 +36,7 @@ namespace std::unique_ptr LoadImageFromIwi(const GfxImage& image, ISearchPath& searchPath) { - const auto imageFileName = std::format("images/{}.iwi", image.name); + const auto imageFileName = image::GetFileNameForAsset(image.name, ".iwi"); const auto filePathImage = searchPath.Open(imageFileName); if (!filePathImage.IsOpen()) { @@ -55,48 +56,43 @@ namespace } } // namespace -AssetDumperGfxImage::AssetDumperGfxImage() +namespace image { - switch (ObjWriting::Configuration.ImageOutputFormat) + DumperIW4::DumperIW4() { - case ObjWriting::Configuration_t::ImageOutputFormat_e::DDS: - m_writer = std::make_unique(); - break; - case ObjWriting::Configuration_t::ImageOutputFormat_e::IWI: - m_writer = std::make_unique(); - break; - default: - assert(false); - m_writer = nullptr; - break; + switch (ObjWriting::Configuration.ImageOutputFormat) + { + case ObjWriting::Configuration_t::ImageOutputFormat_e::DDS: + m_writer = std::make_unique(); + break; + case ObjWriting::Configuration_t::ImageOutputFormat_e::IWI: + m_writer = std::make_unique(); + break; + default: + assert(false); + m_writer = nullptr; + break; + } } -} -bool AssetDumperGfxImage::ShouldDump(XAssetInfo* asset) -{ - return true; -} + bool DumperIW4::ShouldDump(XAssetInfo* asset) + { + return true; + } -std::string AssetDumperGfxImage::GetAssetFileName(const XAssetInfo& asset) const -{ - auto cleanAssetName = asset.m_name; - std::ranges::replace(cleanAssetName, '*', '_'); + void DumperIW4::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* image = asset->Asset(); + const auto texture = LoadImageData(context.m_obj_search_path, *image); + if (!texture) + return; - return std::format("images/{}{}", cleanAssetName, m_writer->GetFileExtension()); -} + const auto assetFile = context.OpenAssetFile(GetFileNameForAsset(asset->m_name, m_writer->GetFileExtension())); -void AssetDumperGfxImage::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* image = asset->Asset(); - const auto texture = LoadImageData(context.m_obj_search_path, *image); - if (!texture) - return; + if (!assetFile) + return; - const auto assetFile = context.OpenAssetFile(GetAssetFileName(*asset)); - - if (!assetFile) - return; - - auto& stream = *assetFile; - m_writer->DumpImage(stream, texture.get()); -} + auto& stream = *assetFile; + m_writer->DumpImage(stream, texture.get()); + } +} // namespace image diff --git a/src/ObjWriting/Game/IW4/Image/ImageDumperIW4.h b/src/ObjWriting/Game/IW4/Image/ImageDumperIW4.h new file mode 100644 index 00000000..5d268ccc --- /dev/null +++ b/src/ObjWriting/Game/IW4/Image/ImageDumperIW4.h @@ -0,0 +1,23 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" +#include "Image/IImageWriter.h" + +#include + +namespace image +{ + class DumperIW4 final : public AbstractAssetDumper + { + public: + DumperIW4(); + + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + + private: + std::unique_ptr m_writer; + }; +} // namespace image diff --git a/src/ObjWriting/Game/IW4/Leaderboard/JsonLeaderboardDefWriter.h b/src/ObjWriting/Game/IW4/Leaderboard/JsonLeaderboardDefWriter.h deleted file mode 100644 index a1b4546d..00000000 --- a/src/ObjWriting/Game/IW4/Leaderboard/JsonLeaderboardDefWriter.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "Dumping/AssetDumpingContext.h" -#include "Game/IW4/IW4.h" - -#include - -namespace IW4 -{ - void DumpLeaderboardDefAsJson(std::ostream& stream, const LeaderboardDef* leaderboardDef); -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/Leaderboard/JsonLeaderboardDefWriter.cpp b/src/ObjWriting/Game/IW4/Leaderboard/LeaderboardJsonDumperIW4.cpp similarity index 73% rename from src/ObjWriting/Game/IW4/Leaderboard/JsonLeaderboardDefWriter.cpp rename to src/ObjWriting/Game/IW4/Leaderboard/LeaderboardJsonDumperIW4.cpp index fe6628bf..80ed3625 100644 --- a/src/ObjWriting/Game/IW4/Leaderboard/JsonLeaderboardDefWriter.cpp +++ b/src/ObjWriting/Game/IW4/Leaderboard/LeaderboardJsonDumperIW4.cpp @@ -1,7 +1,8 @@ -#include "JsonLeaderboardDefWriter.h" +#include "LeaderboardJsonDumperIW4.h" #include "Game/IW4/CommonIW4.h" #include "Game/IW4/Leaderboard/JsonLeaderboardDef.h" +#include "Leaderboard/LeaderboardCommon.h" #include #include @@ -11,18 +12,18 @@ using namespace IW4; namespace { - class JsonDumper + class Dumper { public: - explicit JsonDumper(std::ostream& stream) + explicit Dumper(std::ostream& stream) : m_stream(stream) { } - void Dump(const LeaderboardDef* leaderboardDef) const + void Dump(const LeaderboardDef& leaderboardDef) const { JsonLeaderboardDef jsonLeaderboardDef; - CreateJsonLeaderboardDef(jsonLeaderboardDef, *leaderboardDef); + CreateJsonLeaderboardDef(jsonLeaderboardDef, leaderboardDef); json jRoot = jsonLeaderboardDef; @@ -74,11 +75,21 @@ namespace }; } // namespace -namespace IW4 +namespace leaderboard { - void DumpLeaderboardDefAsJson(std::ostream& stream, const LeaderboardDef* leaderboardDef) + bool JsonDumperIW4::ShouldDump(XAssetInfo* asset) { - JsonDumper dumper(stream); - dumper.Dump(leaderboardDef); + return true; } -} // namespace IW4 + + void JsonDumperIW4::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto assetFile = context.OpenAssetFile(GetJsonFileNameForAsset(asset->m_name)); + + if (!assetFile) + return; + + Dumper dumper(*assetFile); + dumper.Dump(*asset->Asset()); + } +} // namespace leaderboard diff --git a/src/ObjWriting/Game/IW4/Leaderboard/LeaderboardJsonDumperIW4.h b/src/ObjWriting/Game/IW4/Leaderboard/LeaderboardJsonDumperIW4.h new file mode 100644 index 00000000..a56e5127 --- /dev/null +++ b/src/ObjWriting/Game/IW4/Leaderboard/LeaderboardJsonDumperIW4.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" + +namespace leaderboard +{ + class JsonDumperIW4 final : public AbstractAssetDumper + { + protected: + [[nodiscard]] bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace leaderboard diff --git a/src/ObjWriting/Game/IW4/LightDef/LightDefDumperIW4.cpp b/src/ObjWriting/Game/IW4/LightDef/LightDefDumperIW4.cpp new file mode 100644 index 00000000..205df266 --- /dev/null +++ b/src/ObjWriting/Game/IW4/LightDef/LightDefDumperIW4.cpp @@ -0,0 +1,32 @@ +#include "LightDefDumperIW4.h" + +#include "LightDef/LightDefCommon.h" + +#include + +using namespace IW4; + +namespace light_def +{ + bool DumperIW4::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperIW4::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* lightDef = asset->Asset(); + const auto assetFile = context.OpenAssetFile(GetFileNameForAsset(asset->m_name)); + + if (!assetFile || lightDef->attenuation.image == nullptr || lightDef->attenuation.image->name == nullptr) + return; + + auto& stream = *assetFile; + + const auto* imageName = lightDef->attenuation.image->name; + if (imageName[0] == ',') + imageName = &imageName[1]; + + stream << lightDef->attenuation.samplerState << imageName << static_cast(lightDef->lmapLookupStart); + } +} // namespace light_def diff --git a/src/ObjWriting/Game/IW4/LightDef/LightDefDumperIW4.h b/src/ObjWriting/Game/IW4/LightDef/LightDefDumperIW4.h new file mode 100644 index 00000000..29531abb --- /dev/null +++ b/src/ObjWriting/Game/IW4/LightDef/LightDefDumperIW4.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" + +namespace light_def +{ + class DumperIW4 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace light_def diff --git a/src/ObjWriting/Game/IW4/Localize/LocalizeDumperIW4.cpp b/src/ObjWriting/Game/IW4/Localize/LocalizeDumperIW4.cpp new file mode 100644 index 00000000..77b4b44e --- /dev/null +++ b/src/ObjWriting/Game/IW4/Localize/LocalizeDumperIW4.cpp @@ -0,0 +1,44 @@ +#include "LocalizeDumperIW4.h" + +#include "Dumping/Localize/StringFileDumper.h" +#include "Localize/LocalizeCommon.h" + +#include +#include + +using namespace IW4; + +namespace localize +{ + void DumperIW4::DumpPool(AssetDumpingContext& context, AssetPool* pool) + { + if (pool->m_asset_lookup.empty()) + return; + + const auto language = LocalizeCommon::GetNameOfLanguage(context.m_zone.m_language); + const auto assetFile = context.OpenAssetFile(std::format("{}/localizedstrings/{}.str", language, context.m_zone.m_name)); + + if (assetFile) + { + StringFileDumper stringFileDumper(context.m_zone, *assetFile); + + stringFileDumper.SetLanguageName(language); + + // Magic string. Original string files do have this config file. The purpose of the config file is unknown though. + stringFileDumper.SetConfigFile(R"(C:/trees/cod3/cod3/bin/StringEd.cfg)"); + + stringFileDumper.SetNotes(""); + + for (auto* localizeEntry : *pool) + { + stringFileDumper.WriteLocalizeEntry(localizeEntry->m_name, localizeEntry->Asset()->value); + } + + stringFileDumper.Finalize(); + } + else + { + std::cerr << std::format("Could not create string file for dumping localized strings of zone '{}'\n", context.m_zone.m_name); + } + } +} // namespace localize diff --git a/src/ObjWriting/Game/IW4/Localize/LocalizeDumperIW4.h b/src/ObjWriting/Game/IW4/Localize/LocalizeDumperIW4.h new file mode 100644 index 00000000..fd88c200 --- /dev/null +++ b/src/ObjWriting/Game/IW4/Localize/LocalizeDumperIW4.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" + +namespace localize +{ + class DumperIW4 final : public IAssetDumper + { + public: + void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; + }; +} // namespace localize diff --git a/src/ObjWriting/Game/IW4/Maps/AddonMapEntsDumperIW4.cpp b/src/ObjWriting/Game/IW4/Maps/AddonMapEntsDumperIW4.cpp new file mode 100644 index 00000000..37b45249 --- /dev/null +++ b/src/ObjWriting/Game/IW4/Maps/AddonMapEntsDumperIW4.cpp @@ -0,0 +1,27 @@ +#define NOMINMAX +#include "AddonMapEntsDumperIW4.h" + +#include + +using namespace IW4; + +namespace addon_map_ents +{ + bool DumperIW4::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperIW4::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* addonMapEnts = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name); + + if (!assetFile) + return; + + auto& stream = *assetFile; + + stream.write(addonMapEnts->entityString, std::max(addonMapEnts->numEntityChars - 1, 0)); + } +} // namespace addon_map_ents diff --git a/src/ObjWriting/Game/IW4/Maps/AddonMapEntsDumperIW4.h b/src/ObjWriting/Game/IW4/Maps/AddonMapEntsDumperIW4.h new file mode 100644 index 00000000..4f1ef6c8 --- /dev/null +++ b/src/ObjWriting/Game/IW4/Maps/AddonMapEntsDumperIW4.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" + +namespace addon_map_ents +{ + class DumperIW4 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace addon_map_ents diff --git a/src/ObjWriting/Game/IW4/Material/DecompilingMaterialDumperIW4.h b/src/ObjWriting/Game/IW4/Material/DecompilingMaterialDumperIW4.h deleted file mode 100644 index c6792591..00000000 --- a/src/ObjWriting/Game/IW4/Material/DecompilingMaterialDumperIW4.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include "Dumping/AssetDumpingContext.h" -#include "Game/IW4/IW4.h" -#include "Obj/Gdt/GdtStream.h" - -namespace IW4 -{ - void DecompileMaterialToGdt(GdtOutputStream& out, const Material& material, AssetDumpingContext& context); -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/Material/DumperMaterialIW4.cpp b/src/ObjWriting/Game/IW4/Material/DumperMaterialIW4.cpp deleted file mode 100644 index 9d10c301..00000000 --- a/src/ObjWriting/Game/IW4/Material/DumperMaterialIW4.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "DumperMaterialIW4.h" - -#include "DecompilingMaterialDumperIW4.h" -#include "Game/IW4/Material/JsonMaterialWriterIW4.h" -#include "Game/IW4/Material/MaterialConstantZoneStateIW4.h" -#include "Material/MaterialCommon.h" - -using namespace IW4; - -void AssetDumperMaterial::DumpPool(AssetDumpingContext& context, AssetPool* pool) -{ - auto* materialConstantState = context.GetZoneAssetDumperState(); - materialConstantState->ExtractNamesFromZone(); - - AbstractAssetDumper::DumpPool(context, pool); -} - -bool AssetDumperMaterial::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperMaterial::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ -#ifdef EXPERIMENTAL_MATERIAL_COMPILATION - if (context.m_gdt) - { - DecompileMaterialToGdt(*context.m_gdt, *asset->Asset(), context); - } -#else - const auto assetFile = context.OpenAssetFile(material::GetFileNameForAssetName(asset->m_name)); - - if (!assetFile) - return; - - DumpMaterialAsJson(*assetFile, *asset->Asset(), context); -#endif -} diff --git a/src/ObjWriting/Game/IW4/Material/DumperMaterialIW4.h b/src/ObjWriting/Game/IW4/Material/DumperMaterialIW4.h deleted file mode 100644 index 1d3447f3..00000000 --- a/src/ObjWriting/Game/IW4/Material/DumperMaterialIW4.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW4/IW4.h" - -namespace IW4 -{ - class AssetDumperMaterial final : public AbstractAssetDumper - { - public: - void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW4 diff --git a/src/ObjWriting/Game/IW4/Material/DecompilingMaterialDumperIW4.cpp b/src/ObjWriting/Game/IW4/Material/MaterialDecompilingDumperIW4.cpp similarity index 99% rename from src/ObjWriting/Game/IW4/Material/DecompilingMaterialDumperIW4.cpp rename to src/ObjWriting/Game/IW4/Material/MaterialDecompilingDumperIW4.cpp index e6a5443d..a61c012a 100644 --- a/src/ObjWriting/Game/IW4/Material/DecompilingMaterialDumperIW4.cpp +++ b/src/ObjWriting/Game/IW4/Material/MaterialDecompilingDumperIW4.cpp @@ -1,4 +1,4 @@ -#include "DecompilingMaterialDumperIW4.h" +#include "MaterialDecompilingDumperIW4.h" #include "Game/IW4/MaterialConstantsIW4.h" #include "Game/IW4/ObjConstantsIW4.h" @@ -1108,11 +1108,19 @@ namespace }; } // namespace -namespace IW4 +namespace material { - void DecompileMaterialToGdt(GdtOutputStream& out, const Material& material, AssetDumpingContext& context) + bool DecompilingGdtDumperIW4::ShouldDump(XAssetInfo* asset) { - MaterialGdtDumper dumper(material); - out.WriteEntry(dumper.CreateGdtEntry()); + return true; } -} // namespace IW4 + + void DecompilingGdtDumperIW4::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + if (!context.m_gdt) + return; + + MaterialGdtDumper dumper(*asset->Asset()); + context.m_gdt->WriteEntry(dumper.CreateGdtEntry()); + } +} // namespace material diff --git a/src/ObjWriting/Game/IW4/Material/MaterialDecompilingDumperIW4.h b/src/ObjWriting/Game/IW4/Material/MaterialDecompilingDumperIW4.h new file mode 100644 index 00000000..e6b73e35 --- /dev/null +++ b/src/ObjWriting/Game/IW4/Material/MaterialDecompilingDumperIW4.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" + +namespace material +{ + class DecompilingGdtDumperIW4 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace material diff --git a/src/ObjWriting/Game/IW4/Menu/MenuDumperIW4.cpp b/src/ObjWriting/Game/IW4/Menu/MenuDumperIW4.cpp index 5d65da59..d3828080 100644 --- a/src/ObjWriting/Game/IW4/Menu/MenuDumperIW4.cpp +++ b/src/ObjWriting/Game/IW4/Menu/MenuDumperIW4.cpp @@ -1,923 +1,59 @@ #include "MenuDumperIW4.h" -#include "Game/IW4/MenuConstantsIW4.h" +#include "Game/IW4/GameAssetPoolIW4.h" +#include "Game/IW4/Menu/MenuDumperIW4.h" +#include "MenuListDumperIW4.h" +#include "MenuWriterIW4.h" #include "ObjWriting.h" -#include -#include -#include +#include +#include using namespace IW4; -// Uncomment this macro to skip interpretative expression dumping -// #define DUMP_NAIVE - -#ifdef DUMP_NAIVE -#define DUMP_FUNC WriteStatementNaive -#else -#define DUMP_FUNC WriteStatementSkipInitialUnnecessaryParenthesis -#endif - -size_t MenuDumper::FindStatementClosingParenthesis(const Statement_s* statement, const size_t openingParenthesisPosition) +namespace { - assert(statement->numEntries >= 0); - assert(openingParenthesisPosition < static_cast(statement->numEntries)); - - const auto statementEnd = static_cast(statement->numEntries); - - // The openingParenthesisPosition does not necessarily point to an actual opening parenthesis operator. That's fine though. - // We will pretend it does since the game does sometimes leave out opening parenthesis from the entries. - auto currentParenthesisDepth = 1; - for (auto currentSearchPosition = openingParenthesisPosition + 1; currentSearchPosition < statementEnd; currentSearchPosition++) + std::string GetPathForMenu(menu::MenuDumpingZoneState* zoneState, XAssetInfo* asset) { - const auto& expEntry = statement->entries[currentSearchPosition]; - if (expEntry.type != EET_OPERATOR) - continue; + const auto menuDumpingState = zoneState->m_menu_dumping_state_map.find(asset->Asset()); - // Any function means a "left out" left paren - if (expEntry.data.op == OP_LEFTPAREN || expEntry.data.op >= OP_COUNT) - { - currentParenthesisDepth++; - } - else if (expEntry.data.op == OP_RIGHTPAREN) - { - if (currentParenthesisDepth > 0) - currentParenthesisDepth--; - if (currentParenthesisDepth == 0) - return currentSearchPosition; - } + if (menuDumpingState == zoneState->m_menu_dumping_state_map.end()) + return "ui_mp/" + std::string(asset->Asset()->window.name) + ".menu"; + + return menuDumpingState->second.m_path; + } +} // namespace + +namespace menu +{ + bool MenuDumperIW4::ShouldDump(XAssetInfo* asset) + { + return true; } - return statementEnd; -} - -void MenuDumper::WriteStatementOperator(const Statement_s* statement, size_t& currentPos, bool& spaceNext) const -{ - const auto& expEntry = statement->entries[currentPos]; - - if (spaceNext && expEntry.data.op != OP_COMMA) - m_stream << " "; - - if (expEntry.data.op == OP_LEFTPAREN) + void MenuDumperIW4::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) { - const auto closingParenPos = FindStatementClosingParenthesis(statement, currentPos); - m_stream << "("; - WriteStatementEntryRange(statement, currentPos + 1, closingParenPos); - m_stream << ")"; + const auto* menu = asset->Asset(); + auto* zoneState = context.GetZoneAssetDumperState(); - currentPos = closingParenPos + 1; - spaceNext = true; - } - else if (expEntry.data.op >= EXP_FUNC_STATIC_DVAR_INT && expEntry.data.op <= EXP_FUNC_STATIC_DVAR_STRING) - { - switch (expEntry.data.op) + if (!ObjWriting::ShouldHandleAssetType(ASSET_TYPE_MENULIST)) { - case EXP_FUNC_STATIC_DVAR_INT: - m_stream << "dvarint"; - break; - - case EXP_FUNC_STATIC_DVAR_BOOL: - m_stream << "dvarbool"; - break; - - case EXP_FUNC_STATIC_DVAR_FLOAT: - m_stream << "dvarfloat"; - break; - - case EXP_FUNC_STATIC_DVAR_STRING: - m_stream << "dvarstring"; - break; - - default: - break; + // Make sure menu paths based on menu lists are created + const auto* gameAssetPool = dynamic_cast(asset->m_zone->m_pools.get()); + for (auto* menuListAsset : *gameAssetPool->m_menu_list) + CreateDumpingStateForMenuListIW4(zoneState, menuListAsset->Asset()); } - // Functions do not have opening parenthesis in the entries. We can just pretend they do though - const auto closingParenPos = FindStatementClosingParenthesis(statement, currentPos); - m_stream << "("; + const auto menuFilePath = GetPathForMenu(zoneState, asset); + const auto assetFile = context.OpenAssetFile(menuFilePath); - if (closingParenPos - currentPos + 1 >= 1) - { - const auto& staticDvarEntry = statement->entries[currentPos + 1]; - if (staticDvarEntry.type == EET_OPERAND && staticDvarEntry.data.operand.dataType == VAL_INT) - { - if (statement->supportingData && statement->supportingData->staticDvarList.staticDvars && staticDvarEntry.data.operand.internals.intVal >= 0 - && staticDvarEntry.data.operand.internals.intVal < statement->supportingData->staticDvarList.numStaticDvars) - { - const auto* staticDvar = statement->supportingData->staticDvarList.staticDvars[staticDvarEntry.data.operand.internals.intVal]; - if (staticDvar && staticDvar->dvarName) - m_stream << staticDvar->dvarName; - } - else - { - m_stream << "#INVALID_DVAR_INDEX"; - } - } - else - { - m_stream << "#INVALID_DVAR_OPERAND"; - } - } + if (!assetFile) + return; - m_stream << ")"; - currentPos = closingParenPos + 1; - spaceNext = true; + auto menuWriter = CreateMenuWriterIW4(*assetFile); + + menuWriter->Start(); + menuWriter->WriteMenu(*menu); + menuWriter->End(); } - else - { - if (expEntry.data.op >= 0 && static_cast(expEntry.data.op) < std::extent_v) - m_stream << g_expFunctionNames[expEntry.data.op]; - - if (expEntry.data.op >= OP_COUNT) - { - // Functions do not have opening parenthesis in the entries. We can just pretend they do though - const auto closingParenPos = FindStatementClosingParenthesis(statement, currentPos); - m_stream << "("; - WriteStatementEntryRange(statement, currentPos + 1, closingParenPos); - m_stream << ")"; - currentPos = closingParenPos + 1; - } - else - currentPos++; - - spaceNext = expEntry.data.op != OP_NOT; - } -} - -void MenuDumper::WriteStatementOperandFunction(const Statement_s* statement, const size_t currentPos) const -{ - const auto& operand = statement->entries[currentPos].data.operand; - - if (operand.internals.function == nullptr) - return; - - if (!ObjWriting::Configuration.MenuLegacyMode) - { - int functionIndex = -1; - if (statement->supportingData && statement->supportingData->uifunctions.functions) - { - for (auto supportingFunctionIndex = 0; supportingFunctionIndex < statement->supportingData->uifunctions.totalFunctions; supportingFunctionIndex++) - { - if (statement->supportingData->uifunctions.functions[supportingFunctionIndex] == operand.internals.function) - { - functionIndex = supportingFunctionIndex; - break; - } - } - } - - if (functionIndex >= 0) - m_stream << "FUNC_" << functionIndex; - else - m_stream << "INVALID_FUNC"; - m_stream << "()"; - } - else - { - m_stream << "("; - WriteStatementSkipInitialUnnecessaryParenthesis(operand.internals.function); - m_stream << ")"; - } -} - -void MenuDumper::WriteStatementOperand(const Statement_s* statement, size_t& currentPos, bool& spaceNext) const -{ - const auto& expEntry = statement->entries[currentPos]; - - if (spaceNext) - m_stream << " "; - - const auto& operand = expEntry.data.operand; - - switch (operand.dataType) - { - case VAL_FLOAT: - m_stream << operand.internals.floatVal; - break; - - case VAL_INT: - m_stream << operand.internals.intVal; - break; - - case VAL_STRING: - WriteEscapedString(operand.internals.stringVal.string); - break; - - case VAL_FUNCTION: - WriteStatementOperandFunction(statement, currentPos); - break; - - default: - break; - } - - currentPos++; - spaceNext = true; -} - -void MenuDumper::WriteStatementEntryRange(const Statement_s* statement, const size_t startOffset, const size_t endOffset) const -{ - assert(startOffset <= endOffset); - assert(endOffset <= static_cast(statement->numEntries)); - - auto currentPos = startOffset; - auto spaceNext = false; - while (currentPos < endOffset) - { - const auto& expEntry = statement->entries[currentPos]; - - if (expEntry.type == EET_OPERATOR) - { - WriteStatementOperator(statement, currentPos, spaceNext); - } - else - { - WriteStatementOperand(statement, currentPos, spaceNext); - } - } -} - -void MenuDumper::WriteStatement(const Statement_s* statement) const -{ - if (statement == nullptr || statement->numEntries < 0) - return; - - WriteStatementEntryRange(statement, 0, static_cast(statement->numEntries)); -} - -void MenuDumper::WriteStatementSkipInitialUnnecessaryParenthesis(const Statement_s* statementValue) const -{ - if (statementValue == nullptr || statementValue->numEntries < 0) - return; - - const auto statementEnd = static_cast(statementValue->numEntries); - - if (statementValue->numEntries >= 1 && statementValue->entries[0].type == EET_OPERATOR && statementValue->entries[0].data.op == OP_LEFTPAREN) - { - const auto parenthesisEnd = FindStatementClosingParenthesis(statementValue, 0); - - if (parenthesisEnd >= statementEnd) - WriteStatementEntryRange(statementValue, 1, statementEnd); - else if (parenthesisEnd == statementEnd - 1) - WriteStatementEntryRange(statementValue, 1, statementEnd - 1); - else - WriteStatementEntryRange(statementValue, 0, statementEnd); - } - else - { - WriteStatementEntryRange(statementValue, 0, statementEnd); - } -} - -void MenuDumper::WriteStatementNaive(const Statement_s* statement) const -{ - const auto entryCount = static_cast(statement->numEntries); - - const auto missingClosingParenthesis = statement->numEntries > 0 && statement->entries[0].type == EET_OPERATOR - && statement->entries[0].data.op == OP_LEFTPAREN - && FindStatementClosingParenthesis(statement, 0) >= static_cast(statement->numEntries); - - for (auto i = 0uz; i < entryCount; i++) - { - const auto& entry = statement->entries[i]; - if (entry.type == EET_OPERAND) - { - size_t pos = i; - bool discard = false; - WriteStatementOperand(statement, pos, discard); - } - else if (entry.data.op >= EXP_FUNC_STATIC_DVAR_INT && entry.data.op <= EXP_FUNC_STATIC_DVAR_STRING) - { - switch (entry.data.op) - { - case EXP_FUNC_STATIC_DVAR_INT: - m_stream << "dvarint"; - break; - - case EXP_FUNC_STATIC_DVAR_BOOL: - m_stream << "dvarbool"; - break; - - case EXP_FUNC_STATIC_DVAR_FLOAT: - m_stream << "dvarfloat"; - break; - - case EXP_FUNC_STATIC_DVAR_STRING: - m_stream << "dvarstring"; - break; - - default: - break; - } - - // Functions do not have opening parenthesis in the entries. We can just pretend they do though - const auto closingParenPos = FindStatementClosingParenthesis(statement, i); - m_stream << "("; - - if (closingParenPos - i + 1u >= 1u) - { - const auto& staticDvarEntry = statement->entries[i + 1]; - if (staticDvarEntry.type == EET_OPERAND && staticDvarEntry.data.operand.dataType == VAL_INT) - { - if (statement->supportingData && statement->supportingData->staticDvarList.staticDvars && staticDvarEntry.data.operand.internals.intVal >= 0 - && staticDvarEntry.data.operand.internals.intVal < statement->supportingData->staticDvarList.numStaticDvars) - { - const auto* staticDvar = statement->supportingData->staticDvarList.staticDvars[staticDvarEntry.data.operand.internals.intVal]; - if (staticDvar && staticDvar->dvarName) - m_stream << staticDvar->dvarName; - } - else - { - m_stream << "#INVALID_DVAR_INDEX"; - } - } - else - { - m_stream << "#INVALID_DVAR_OPERAND"; - } - } - - m_stream << ")"; - i = closingParenPos; - } - else - { - assert(entry.data.op >= 0 && static_cast(entry.data.op) < std::extent_v); - if (entry.data.op >= 0 && static_cast(entry.data.op) < std::extent_v) - m_stream << g_expFunctionNames[entry.data.op]; - if (entry.data.op >= OP_COUNT) - m_stream << "("; - } - } - - if (missingClosingParenthesis) - m_stream << ")"; -} - -void MenuDumper::WriteStatementProperty(const std::string& propertyKey, const Statement_s* statementValue, bool isBooleanStatement) const -{ - if (statementValue == nullptr || statementValue->numEntries < 0) - return; - - Indent(); - WriteKey(propertyKey); - - if (isBooleanStatement) - { - m_stream << "when("; - DUMP_FUNC(statementValue); - m_stream << ");\n"; - } - else - { - DUMP_FUNC(statementValue); - m_stream << ";\n"; - } -} - -void MenuDumper::WriteSetLocalVarData(const std::string& setFunction, const SetLocalVarData* setLocalVarData) const -{ - if (setLocalVarData == nullptr) - return; - - Indent(); - m_stream << setFunction << " " << setLocalVarData->localVarName << " "; - WriteStatement(setLocalVarData->expression); - m_stream << ";\n"; -} - -// #define WRITE_ORIGINAL_SCRIPT - -void MenuDumper::WriteUnconditionalScript(const char* script) const -{ -#ifdef WRITE_ORIGINAL_SCRIPT - Indent(); - m_stream << script << "\n"; - return; -#endif - - const auto tokenList = CreateScriptTokenList(script); - - auto isNewStatement = true; - for (const auto& token : tokenList) - { - if (isNewStatement) - { - if (token == ";") - continue; - - Indent(); - } - - if (token == ";") - { - m_stream << ";\n"; - isNewStatement = true; - continue; - } - - if (!isNewStatement) - m_stream << " "; - else - isNewStatement = false; - - if (DoesTokenNeedQuotationMarks(token)) - m_stream << "\"" << token << "\""; - else - m_stream << token; - } - - if (!isNewStatement) - m_stream << ";\n"; -} - -void MenuDumper::WriteMenuEventHandlerSet(const MenuEventHandlerSet* eventHandlerSet) -{ - Indent(); - m_stream << "{\n"; - IncIndent(); - - for (auto i = 0; i < eventHandlerSet->eventHandlerCount; i++) - { - const auto* eventHandler = eventHandlerSet->eventHandlers[i]; - if (eventHandler == nullptr) - continue; - - switch (eventHandler->eventType) - { - case EVENT_UNCONDITIONAL: - WriteUnconditionalScript(eventHandler->eventData.unconditionalScript); - break; - - case EVENT_IF: - if (eventHandler->eventData.conditionalScript == nullptr || eventHandler->eventData.conditionalScript->eventExpression == nullptr - || eventHandler->eventData.conditionalScript->eventHandlerSet == nullptr) - { - continue; - } - - Indent(); - m_stream << "if ("; - WriteStatementSkipInitialUnnecessaryParenthesis(eventHandler->eventData.conditionalScript->eventExpression); - m_stream << ")\n"; - WriteMenuEventHandlerSet(eventHandler->eventData.conditionalScript->eventHandlerSet); - break; - - case EVENT_ELSE: - if (eventHandler->eventData.elseScript == nullptr) - continue; - - Indent(); - m_stream << "else\n"; - WriteMenuEventHandlerSet(eventHandler->eventData.elseScript); - break; - - case EVENT_SET_LOCAL_VAR_BOOL: - WriteSetLocalVarData("setLocalVarBool", eventHandler->eventData.setLocalVarData); - break; - - case EVENT_SET_LOCAL_VAR_INT: - WriteSetLocalVarData("setLocalVarInt", eventHandler->eventData.setLocalVarData); - break; - - case EVENT_SET_LOCAL_VAR_FLOAT: - WriteSetLocalVarData("setLocalVarFloat", eventHandler->eventData.setLocalVarData); - break; - - case EVENT_SET_LOCAL_VAR_STRING: - WriteSetLocalVarData("setLocalVarString", eventHandler->eventData.setLocalVarData); - break; - - default: - break; - } - } - - DecIndent(); - Indent(); - m_stream << "}\n"; -} - -void MenuDumper::WriteMenuEventHandlerSetProperty(const std::string& propertyKey, const MenuEventHandlerSet* eventHandlerSetValue) -{ - if (eventHandlerSetValue == nullptr) - return; - - Indent(); - m_stream << propertyKey << "\n"; - WriteMenuEventHandlerSet(eventHandlerSetValue); -} - -void MenuDumper::WriteRectProperty(const std::string& propertyKey, const rectDef_s& rect) const -{ - Indent(); - WriteKey(propertyKey); - m_stream << rect.x << " " << rect.y << " " << rect.w << " " << rect.h << " " << static_cast(rect.horzAlign) << " " << static_cast(rect.vertAlign) - << "\n"; -} - -void MenuDumper::WriteMaterialProperty(const std::string& propertyKey, const Material* materialValue) const -{ - if (materialValue == nullptr || materialValue->info.name == nullptr) - return; - - if (materialValue->info.name[0] == ',') - WriteStringProperty(propertyKey, &materialValue->info.name[1]); - else - WriteStringProperty(propertyKey, materialValue->info.name); -} - -void MenuDumper::WriteSoundAliasProperty(const std::string& propertyKey, const snd_alias_list_t* soundAliasValue) const -{ - if (soundAliasValue == nullptr) - return; - - WriteStringProperty(propertyKey, soundAliasValue->aliasName); -} - -void MenuDumper::WriteDecodeEffectProperty(const std::string& propertyKey, const itemDef_s* item) const -{ - if (!item->decayActive) - return; - - Indent(); - WriteKey(propertyKey); - m_stream << item->fxLetterTime << " " << item->fxDecayStartTime << " " << item->fxDecayDuration << "\n"; -} - -void MenuDumper::WriteItemKeyHandlerProperty(const ItemKeyHandler* itemKeyHandlerValue) -{ - for (const auto* currentHandler = itemKeyHandlerValue; currentHandler; currentHandler = currentHandler->next) - { - if (currentHandler->key >= '!' && currentHandler->key <= '~' && currentHandler->key != '"') - { - std::ostringstream ss; - ss << "execKey \"" << static_cast(currentHandler->key) << "\""; - WriteMenuEventHandlerSetProperty(ss.str(), currentHandler->action); - } - else - { - std::ostringstream ss; - ss << "execKeyInt " << currentHandler->key; - WriteMenuEventHandlerSetProperty(ss.str(), currentHandler->action); - } - } -} - -void MenuDumper::WriteFloatExpressionsProperty(const ItemFloatExpression* floatExpressions, int floatExpressionCount) const -{ - if (!floatExpressions) - return; - - for (int i = 0; i < floatExpressionCount; i++) - { - const auto& floatExpression = floatExpressions[i]; - - if (floatExpression.target < 0 || floatExpression.target >= ITEM_FLOATEXP_TGT_COUNT) - continue; - - std::string propertyName = std::string("exp ") + floatExpressionTargetBindings[floatExpression.target].name + std::string(" ") - + floatExpressionTargetBindings[floatExpression.target].componentName; - - WriteStatementProperty(propertyName, floatExpression.expression, false); - } -} - -void MenuDumper::WriteMultiTokenStringProperty(const std::string& propertyKey, const char* value) const -{ - if (!value) - return; - - Indent(); - WriteKey(propertyKey); - - const auto tokenList = CreateScriptTokenList(value); - - auto firstToken = true; - m_stream << "{ "; - for (const auto& token : tokenList) - { - if (firstToken) - firstToken = false; - else - m_stream << ";"; - m_stream << "\"" << token << "\""; - } - if (!firstToken) - m_stream << " "; - m_stream << "}\n"; -} - -void MenuDumper::WriteColumnProperty(const std::string& propertyKey, const listBoxDef_s* listBox) const -{ - if (listBox->numColumns <= 0) - return; - - Indent(); - WriteKey(propertyKey); - m_stream << listBox->numColumns << "\n"; - - for (auto col = 0; col < listBox->numColumns; col++) - { - Indent(); - for (auto i = 0u; i < MENU_KEY_SPACING; i++) - m_stream << " "; - - m_stream << listBox->columnInfo[col].pos << " " << listBox->columnInfo[col].width << " " << listBox->columnInfo[col].maxChars << " " - << listBox->columnInfo[col].alignment << "\n"; - } -} - -void MenuDumper::WriteListBoxProperties(const itemDef_s* item) -{ - if (item->type != ITEM_TYPE_LISTBOX || item->typeData.listBox == nullptr) - return; - - const auto* listBox = item->typeData.listBox; - WriteKeywordProperty("notselectable", listBox->notselectable != 0); - WriteKeywordProperty("noscrollbars", listBox->noScrollBars != 0); - WriteKeywordProperty("usepaging", listBox->usePaging != 0); - WriteFloatProperty("elementwidth", listBox->elementWidth, 0.0f); - WriteFloatProperty("elementheight", listBox->elementHeight, 0.0f); - WriteFloatProperty("feeder", item->special, 0.0f); - WriteIntProperty("elementtype", listBox->elementStyle, 0); - WriteColumnProperty("columns", listBox); - WriteMenuEventHandlerSetProperty("doubleclick", listBox->onDoubleClick); - WriteColorProperty("selectBorder", listBox->selectBorder, COLOR_0000); - WriteMaterialProperty("selectIcon", listBox->selectIcon); -} - -void MenuDumper::WriteDvarFloatProperty(const std::string& propertyKey, const itemDef_s* item, const editFieldDef_s* editField) const -{ - if (item->dvar == nullptr) - return; - - Indent(); - WriteKey(propertyKey); - m_stream << "\"" << item->dvar << "\" " << editField->defVal << " " << editField->minVal << " " << editField->maxVal << "\n"; -} - -void MenuDumper::WriteEditFieldProperties(const itemDef_s* item) const -{ - switch (item->type) - { - case ITEM_TYPE_TEXT: - case ITEM_TYPE_EDITFIELD: - case ITEM_TYPE_NUMERICFIELD: - case ITEM_TYPE_SLIDER: - case ITEM_TYPE_YESNO: - case ITEM_TYPE_BIND: - case ITEM_TYPE_VALIDFILEFIELD: - case ITEM_TYPE_DECIMALFIELD: - case ITEM_TYPE_UPREDITFIELD: - case ITEM_TYPE_EMAILFIELD: - case ITEM_TYPE_PASSWORDFIELD: - break; - - default: - return; - } - - if (item->typeData.editField == nullptr) - return; - - const auto* editField = item->typeData.editField; - if (std::fabs(-1.0f - editField->defVal) >= std::numeric_limits::epsilon() - || std::fabs(-1.0f - editField->minVal) >= std::numeric_limits::epsilon() - || std::fabs(-1.0f - editField->maxVal) >= std::numeric_limits::epsilon()) - { - WriteDvarFloatProperty("dvarFloat", item, editField); - } - else - { - WriteStringProperty("dvar", item->dvar); - } - WriteStringProperty("localvar", item->localVar); - WriteIntProperty("maxChars", editField->maxChars, 0); - WriteKeywordProperty("maxCharsGotoNext", editField->maxCharsGotoNext != 0); - WriteIntProperty("maxPaintChars", editField->maxPaintChars, 0); -} - -void MenuDumper::WriteMultiValueProperty(const multiDef_s* multiDef) const -{ - Indent(); - if (multiDef->strDef) - WriteKey("dvarStrList"); - else - WriteKey("dvarFloatList"); - - m_stream << "{"; - for (auto i = 0; i < multiDef->count; i++) - { - if (multiDef->dvarList[i] == nullptr || multiDef->strDef && multiDef->dvarStr[i] == nullptr) - continue; - - m_stream << " \"" << multiDef->dvarList[i] << "\""; - - if (multiDef->strDef) - m_stream << " \"" << multiDef->dvarStr[i] << "\""; - else - m_stream << " " << multiDef->dvarValue[i] << ""; - } - m_stream << " }\n"; -} - -void MenuDumper::WriteMultiProperties(const itemDef_s* item) const -{ - if (item->type != ITEM_TYPE_MULTI || item->typeData.multi == nullptr) - return; - - const auto* multiDef = item->typeData.multi; - - if (multiDef->count <= 0) - return; - - WriteStringProperty("dvar", item->dvar); - WriteStringProperty("localvar", item->localVar); - WriteMultiValueProperty(multiDef); -} - -void MenuDumper::WriteEnumDvarProperties(const itemDef_s* item) const -{ - if (item->type != ITEM_TYPE_DVARENUM) - return; - - WriteStringProperty("dvar", item->dvar); - WriteStringProperty("localvar", item->localVar); - WriteStringProperty("dvarEnumList", item->typeData.enumDvarName); -} - -void MenuDumper::WriteTickerProperties(const itemDef_s* item) const -{ - if (item->type != ITEM_TYPE_NEWS_TICKER || item->typeData.ticker == nullptr) - return; - - const auto* newsTickerDef = item->typeData.ticker; - WriteIntProperty("spacing", newsTickerDef->spacing, 0); - WriteIntProperty("speed", newsTickerDef->speed, 0); - WriteIntProperty("newsfeed", newsTickerDef->feedId, 0); -} - -void MenuDumper::WriteItemData(const itemDef_s* item) -{ - WriteStringProperty("name", item->window.name); - WriteStringProperty("text", item->text); - WriteKeywordProperty("textsavegame", item->itemFlags & ITEM_FLAG_SAVE_GAME_INFO); - WriteKeywordProperty("textcinematicsubtitle", item->itemFlags & ITEM_FLAG_CINEMATIC_SUBTITLE); - WriteStringProperty("group", item->window.group); - WriteRectProperty("rect", item->window.rectClient); - WriteIntProperty("style", item->window.style, 0); - WriteKeywordProperty("decoration", item->window.staticFlags & WINDOW_FLAG_DECORATION); - WriteKeywordProperty("autowrapped", item->window.staticFlags & WINDOW_FLAG_AUTO_WRAPPED); - WriteKeywordProperty("horizontalscroll", item->window.staticFlags & WINDOW_FLAG_HORIZONTAL_SCROLL); - WriteIntProperty("type", item->type, ITEM_TYPE_TEXT); - WriteIntProperty("border", item->window.border, 0); - WriteFloatProperty("borderSize", item->window.borderSize, 0.0f); - - if (item->visibleExp) - WriteStatementProperty("visible", item->visibleExp, true); - else if (item->window.dynamicFlags[0] & WINDOW_FLAG_VISIBLE) - WriteIntProperty("visible", 1, 0); - - WriteStatementProperty("disabled", item->disabledExp, true); - WriteIntProperty("ownerdraw", item->window.ownerDraw, 0); - WriteFlagsProperty("ownerdrawFlag", item->window.ownerDrawFlags); - WriteIntProperty("align", item->alignment, 0); - WriteIntProperty("textalign", item->textAlignMode, 0); - WriteFloatProperty("textalignx", item->textalignx, 0.0f); - WriteFloatProperty("textaligny", item->textaligny, 0.0f); - WriteFloatProperty("textscale", item->textscale, 0.0f); - WriteIntProperty("textstyle", item->textStyle, 0); - WriteIntProperty("textfont", item->fontEnum, 0); - WriteColorProperty("backcolor", item->window.backColor, COLOR_0000); - WriteColorProperty("forecolor", item->window.foreColor, COLOR_1111); - WriteColorProperty("bordercolor", item->window.borderColor, COLOR_0000); - WriteColorProperty("outlinecolor", item->window.outlineColor, COLOR_0000); - WriteColorProperty("disablecolor", item->window.disableColor, COLOR_0000); - WriteColorProperty("glowcolor", item->glowColor, COLOR_0000); - WriteMaterialProperty("background", item->window.background); - WriteMenuEventHandlerSetProperty("onFocus", item->onFocus); - WriteMenuEventHandlerSetProperty("leaveFocus", item->leaveFocus); - WriteMenuEventHandlerSetProperty("mouseEnter", item->mouseEnter); - WriteMenuEventHandlerSetProperty("mouseExit", item->mouseExit); - WriteMenuEventHandlerSetProperty("mouseEnterText", item->mouseEnterText); - WriteMenuEventHandlerSetProperty("mouseExitText", item->mouseExitText); - WriteMenuEventHandlerSetProperty("action", item->action); - WriteMenuEventHandlerSetProperty("accept", item->accept); - // WriteFloatProperty("special", item->special, 0.0f); - WriteSoundAliasProperty("focusSound", item->focusSound); - WriteStringProperty("dvarTest", item->dvarTest); - - if (item->dvarFlags & ITEM_DVAR_FLAG_ENABLE) - WriteMultiTokenStringProperty("enableDvar", item->enableDvar); - else if (item->dvarFlags & ITEM_DVAR_FLAG_DISABLE) - WriteMultiTokenStringProperty("disableDvar", item->enableDvar); - else if (item->dvarFlags & ITEM_DVAR_FLAG_SHOW) - WriteMultiTokenStringProperty("showDvar", item->enableDvar); - else if (item->dvarFlags & ITEM_DVAR_FLAG_HIDE) - WriteMultiTokenStringProperty("hideDvar", item->enableDvar); - else if (item->dvarFlags & ITEM_DVAR_FLAG_FOCUS) - WriteMultiTokenStringProperty("focusDvar", item->enableDvar); - - WriteItemKeyHandlerProperty(item->onKey); - WriteStatementProperty("exp text", item->textExp, false); - WriteStatementProperty("exp material", item->materialExp, false); - WriteFloatExpressionsProperty(item->floatExpressions, item->floatExpressionCount); - WriteIntProperty("gamemsgwindowindex", item->gameMsgWindowIndex, 0); - WriteIntProperty("gamemsgwindowmode", item->gameMsgWindowMode, 0); - WriteDecodeEffectProperty("decodeEffect", item); - - WriteListBoxProperties(item); - WriteEditFieldProperties(item); - WriteMultiProperties(item); - WriteEnumDvarProperties(item); - WriteTickerProperties(item); -} - -void MenuDumper::WriteItemDefs(const itemDef_s* const* itemDefs, size_t itemCount) -{ - for (auto i = 0u; i < itemCount; i++) - { - StartItemDefScope(); - - WriteItemData(itemDefs[i]); - - EndScope(); - } -} - -void MenuDumper::WriteMenuData(const menuDef_t* menu) -{ - WriteStringProperty("name", menu->window.name); - WriteBoolProperty("fullscreen", menu->fullScreen, false); - WriteKeywordProperty("screenSpace", menu->window.staticFlags & WINDOW_FLAG_SCREEN_SPACE); - WriteKeywordProperty("decoration", menu->window.staticFlags & WINDOW_FLAG_DECORATION); - WriteRectProperty("rect", menu->window.rect); - WriteIntProperty("style", menu->window.style, 0); - WriteIntProperty("border", menu->window.border, 0); - WriteFloatProperty("borderSize", menu->window.borderSize, 0.0f); - WriteColorProperty("backcolor", menu->window.backColor, COLOR_0000); - WriteColorProperty("forecolor", menu->window.foreColor, COLOR_1111); - WriteColorProperty("bordercolor", menu->window.borderColor, COLOR_0000); - WriteColorProperty("focuscolor", menu->focusColor, COLOR_0000); - WriteColorProperty("outlinecolor", menu->window.outlineColor, COLOR_0000); - WriteMaterialProperty("background", menu->window.background); - WriteIntProperty("ownerdraw", menu->window.ownerDraw, 0); - WriteFlagsProperty("ownerdrawFlag", menu->window.ownerDrawFlags); - WriteKeywordProperty("outOfBoundsClick", menu->window.staticFlags & WINDOW_FLAG_OUT_OF_BOUNDS_CLICK); - WriteStringProperty("soundLoop", menu->soundName); - WriteKeywordProperty("popup", menu->window.staticFlags & WINDOW_FLAG_POPUP); - WriteFloatProperty("fadeClamp", menu->fadeClamp, 0.0f); - WriteIntProperty("fadeCycle", menu->fadeCycle, 0); - WriteFloatProperty("fadeAmount", menu->fadeAmount, 0.0f); - WriteFloatProperty("fadeInAmount", menu->fadeInAmount, 0.0f); - WriteFloatProperty("blurWorld", menu->blurRadius, 0.0f); - WriteKeywordProperty("legacySplitScreenScale", menu->window.staticFlags & WINDOW_FLAG_LEGACY_SPLIT_SCREEN_SCALE); - WriteKeywordProperty("hiddenDuringScope", menu->window.staticFlags & WINDOW_FLAG_HIDDEN_DURING_SCOPE); - WriteKeywordProperty("hiddenDuringFlashbang", menu->window.staticFlags & WINDOW_FLAG_HIDDEN_DURING_FLASH_BANG); - WriteKeywordProperty("hiddenDuringUI", menu->window.staticFlags & WINDOW_FLAG_HIDDEN_DURING_UI); - WriteStringProperty("allowedBinding", menu->allowedBinding); - WriteKeywordProperty("textOnlyFocus", menu->window.staticFlags & WINDOW_FLAG_TEXT_ONLY_FOCUS); - - if (menu->visibleExp) - WriteStatementProperty("visible", menu->visibleExp, true); - else if (menu->window.dynamicFlags[0] & WINDOW_FLAG_VISIBLE) - WriteIntProperty("visible", 1, 0); - - WriteStatementProperty("exp rect X", menu->rectXExp, false); - WriteStatementProperty("exp rect Y", menu->rectYExp, false); - WriteStatementProperty("exp rect W", menu->rectWExp, false); - WriteStatementProperty("exp rect H", menu->rectHExp, false); - WriteStatementProperty("exp openSound", menu->openSoundExp, false); - WriteStatementProperty("exp closeSound", menu->closeSoundExp, false); - WriteMenuEventHandlerSetProperty("onOpen", menu->onOpen); - WriteMenuEventHandlerSetProperty("onClose", menu->onClose); - WriteMenuEventHandlerSetProperty("onRequestClose", menu->onCloseRequest); - WriteMenuEventHandlerSetProperty("onESC", menu->onESC); - WriteItemKeyHandlerProperty(menu->onKey); - WriteItemDefs(menu->items, menu->itemCount); -} - -MenuDumper::MenuDumper(std::ostream& stream) - : AbstractMenuDumper(stream) -{ -} - -void MenuDumper::WriteFunctionDef(const std::string& functionName, const Statement_s* statement) -{ - StartFunctionDefScope(); - - WriteStringProperty("name", functionName); - WriteStatementProperty("value", statement, false); - - EndScope(); -} - -void MenuDumper::WriteMenu(const menuDef_t* menu) -{ - StartMenuDefScope(); - - WriteMenuData(menu); - - EndScope(); -} +} // namespace menu diff --git a/src/ObjWriting/Game/IW4/Menu/MenuDumperIW4.h b/src/ObjWriting/Game/IW4/Menu/MenuDumperIW4.h index 9baff905..43317e26 100644 --- a/src/ObjWriting/Game/IW4/Menu/MenuDumperIW4.h +++ b/src/ObjWriting/Game/IW4/Menu/MenuDumperIW4.h @@ -1,57 +1,15 @@ #pragma once +#include "Dumping/AbstractAssetDumper.h" #include "Game/IW4/IW4.h" -#include "Menu/AbstractMenuDumper.h" +#include "Menu/MenuDumpingZoneState.h" -#include - -namespace IW4 +namespace menu { - class MenuDumper : public AbstractMenuDumper + class MenuDumperIW4 final : public AbstractAssetDumper { - static size_t FindStatementClosingParenthesis(const Statement_s* statement, size_t openingParenthesisPosition); - - void WriteStatementNaive(const Statement_s* statement) const; - - void WriteStatementOperator(const Statement_s* statement, size_t& currentPos, bool& spaceNext) const; - void WriteStatementOperandFunction(const Statement_s* statement, size_t currentPos) const; - void WriteStatementOperand(const Statement_s* statement, size_t& currentPos, bool& spaceNext) const; - void WriteStatementEntryRange(const Statement_s* statement, size_t startOffset, size_t endOffset) const; - void WriteStatement(const Statement_s* statement) const; - void WriteStatementSkipInitialUnnecessaryParenthesis(const Statement_s* statementValue) const; - void WriteStatementProperty(const std::string& propertyKey, const Statement_s* statementValue, bool isBooleanStatement) const; - - void WriteSetLocalVarData(const std::string& setFunction, const SetLocalVarData* setLocalVarData) const; - void WriteUnconditionalScript(const char* script) const; - void WriteMenuEventHandlerSet(const MenuEventHandlerSet* eventHandlerSet); - void WriteMenuEventHandlerSetProperty(const std::string& propertyKey, const MenuEventHandlerSet* eventHandlerSetValue); - - void WriteRectProperty(const std::string& propertyKey, const rectDef_s& rect) const; - void WriteMaterialProperty(const std::string& propertyKey, const Material* materialValue) const; - void WriteSoundAliasProperty(const std::string& propertyKey, const snd_alias_list_t* soundAliasValue) const; - void WriteDecodeEffectProperty(const std::string& propertyKey, const itemDef_s* item) const; - void WriteItemKeyHandlerProperty(const ItemKeyHandler* itemKeyHandlerValue); - void WriteMultiTokenStringProperty(const std::string& propertyKey, const char* value) const; - void WriteFloatExpressionsProperty(const ItemFloatExpression* floatExpressions, int floatExpressionCount) const; - void WriteColumnProperty(const std::string& propertyKey, const listBoxDef_s* listBox) const; - - void WriteListBoxProperties(const itemDef_s* item); - void WriteDvarFloatProperty(const std::string& propertyKey, const itemDef_s* item, const editFieldDef_s* editField) const; - void WriteEditFieldProperties(const itemDef_s* item) const; - void WriteMultiValueProperty(const multiDef_s* multiDef) const; - void WriteMultiProperties(const itemDef_s* item) const; - void WriteEnumDvarProperties(const itemDef_s* item) const; - void WriteTickerProperties(const itemDef_s* item) const; - - void WriteItemData(const itemDef_s* item); - void WriteItemDefs(const itemDef_s* const* itemDefs, size_t itemCount); - - void WriteMenuData(const menuDef_t* menu); - - public: - explicit MenuDumper(std::ostream& stream); - - void WriteFunctionDef(const std::string& functionName, const Statement_s* statement); - void WriteMenu(const menuDef_t* menu); + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; }; -} // namespace IW4 +} // namespace menu diff --git a/src/ObjWriting/Game/IW4/Menu/MenuListDumperIW4.cpp b/src/ObjWriting/Game/IW4/Menu/MenuListDumperIW4.cpp new file mode 100644 index 00000000..7946dfe9 --- /dev/null +++ b/src/ObjWriting/Game/IW4/Menu/MenuListDumperIW4.cpp @@ -0,0 +1,186 @@ +#include "MenuListDumperIW4.h" + +#include "Game/IW4/Menu/MenuDumperIW4.h" +#include "Menu/AbstractMenuWriter.h" +#include "MenuWriterIW4.h" +#include "ObjWriting.h" + +#include +#include +#include +#include + +namespace fs = std::filesystem; + +using namespace IW4; + +namespace +{ + std::vector GetAllUniqueExpressionSupportingData(const MenuList* menuList) + { + std::vector result; + std::set alreadyAddedSupportingData; + + if (menuList->menus == nullptr) + return result; + + for (auto i = 0; i < menuList->menuCount; i++) + { + if (menuList->menus[i] == nullptr) + continue; + + const auto* menu = menuList->menus[i]; + + if (menu->expressionData == nullptr) + continue; + + if (alreadyAddedSupportingData.find(menu->expressionData) == alreadyAddedSupportingData.end()) + { + result.push_back(menu->expressionData); + alreadyAddedSupportingData.emplace(menu->expressionData); + } + } + + return result; + } + + void DumpFunctions(menu::IWriterIW4& menuDumper, const MenuList* menuList) + { + const auto allSupportingData = GetAllUniqueExpressionSupportingData(menuList); + auto functionIndex = 0u; + + assert(allSupportingData.size() <= 1); + + for (const auto* supportingData : allSupportingData) + { + if (supportingData->uifunctions.functions == nullptr) + continue; + + for (auto i = 0; i < supportingData->uifunctions.totalFunctions; i++) + { + const auto* function = supportingData->uifunctions.functions[i]; + if (function != nullptr) + { + std::stringstream ss; + ss << "FUNC_" << functionIndex; + + menuDumper.WriteFunctionDef(ss.str(), function); + } + + functionIndex++; + } + } + } + + void DumpMenus(menu::IWriterIW4& menuDumper, menu::MenuDumpingZoneState* zoneState, const MenuList* menuList) + { + for (auto menuNum = 0; menuNum < menuList->menuCount; menuNum++) + { + const auto* menu = menuList->menus[menuNum]; + + const auto menuDumpingState = zoneState->m_menu_dumping_state_map.find(menu); + if (menuDumpingState == zoneState->m_menu_dumping_state_map.end()) + continue; + + // If the menu was embedded directly as menu list write its data in the menu list file + if (menuDumpingState->second.m_alias_menu_list == menuList) + menuDumper.WriteMenu(*menu); + else + menuDumper.IncludeMenu(menuDumpingState->second.m_path); + } + } + + std::string PathForMenu(const std::string& menuListParentPath, const menuDef_t* menu) + { + const auto* menuAssetName = menu->window.name; + + if (!menuAssetName) + return ""; + + if (menuAssetName[0] == ',') + menuAssetName = &menuAssetName[1]; + + std::ostringstream ss; + ss << menuListParentPath << menuAssetName << ".menu"; + + return ss.str(); + } +} // namespace + +namespace menu +{ + void CreateDumpingStateForMenuListIW4(MenuDumpingZoneState* zoneState, const MenuList* menuList) + { + if (menuList->menuCount <= 0 || menuList->menus == nullptr || menuList->name == nullptr) + return; + + const std::string menuListName(menuList->name); + const fs::path p(menuListName); + std::string parentPath; + if (p.has_parent_path()) + parentPath = p.parent_path().string() + "/"; + + for (auto i = 0; i < menuList->menuCount; i++) + { + auto* menu = menuList->menus[i]; + + if (menu == nullptr) + continue; + + auto existingState = zoneState->m_menu_dumping_state_map.find(menu); + if (existingState == zoneState->m_menu_dumping_state_map.end()) + { + auto menuPath = PathForMenu(parentPath, menu); + const auto isTheSameAsMenuList = menuPath == menuListName; + zoneState->CreateMenuDumpingState(menu, std::move(menuPath), isTheSameAsMenuList ? menuList : nullptr); + } + else if (existingState->second.m_alias_menu_list == nullptr) + { + auto menuPath = PathForMenu(parentPath, menu); + const auto isTheSameAsMenuList = menuPath == menuListName; + if (isTheSameAsMenuList) + { + existingState->second.m_alias_menu_list = menuList; + existingState->second.m_path = std::move(menuPath); + } + } + } + } + + bool MenuListDumperIW4::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void MenuListDumperIW4::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* menuList = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name); + + if (!assetFile) + return; + + auto* zoneState = context.GetZoneAssetDumperState(); + + auto menuWriter = CreateMenuWriterIW4(*assetFile); + + menuWriter->Start(); + + if (!ObjWriting::Configuration.MenuLegacyMode) + DumpFunctions(*menuWriter, menuList); + + DumpMenus(*menuWriter, zoneState, menuList); + + menuWriter->End(); + } + + void MenuListDumperIW4::DumpPool(AssetDumpingContext& context, AssetPool* pool) + { + auto* zoneState = context.GetZoneAssetDumperState(); + + for (auto* asset : *pool) + CreateDumpingStateForMenuListIW4(zoneState, asset->Asset()); + + AbstractAssetDumper::DumpPool(context, pool); + } +} // namespace menu diff --git a/src/ObjWriting/Game/IW4/Menu/MenuListDumperIW4.h b/src/ObjWriting/Game/IW4/Menu/MenuListDumperIW4.h new file mode 100644 index 00000000..b9329966 --- /dev/null +++ b/src/ObjWriting/Game/IW4/Menu/MenuListDumperIW4.h @@ -0,0 +1,21 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" +#include "Game/IW4/Menu/MenuDumperIW4.h" +#include "Menu/MenuDumpingZoneState.h" + +namespace menu +{ + void CreateDumpingStateForMenuListIW4(MenuDumpingZoneState* zoneState, const IW4::MenuList* menuList); + + class MenuListDumperIW4 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + + public: + void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; + }; +} // namespace menu diff --git a/src/ObjWriting/Game/IW4/Menu/MenuWriterIW4.cpp b/src/ObjWriting/Game/IW4/Menu/MenuWriterIW4.cpp new file mode 100644 index 00000000..b20cec15 --- /dev/null +++ b/src/ObjWriting/Game/IW4/Menu/MenuWriterIW4.cpp @@ -0,0 +1,957 @@ +#include "MenuWriterIW4.h" + +#include "Game/IW4/MenuConstantsIW4.h" +#include "Menu/AbstractMenuWriter.h" +#include "ObjWriting.h" + +#include +#include +#include + +using namespace IW4; + +// Uncomment this macro to skip interpretative expression dumping +// #define DUMP_NAIVE + +#ifdef DUMP_NAIVE +#define DUMP_FUNC WriteStatementNaive +#else +#define DUMP_FUNC WriteStatementSkipInitialUnnecessaryParenthesis +#endif + +namespace +{ + size_t FindStatementClosingParenthesis(const Statement_s* statement, const size_t openingParenthesisPosition) + { + assert(statement->numEntries >= 0); + assert(openingParenthesisPosition < static_cast(statement->numEntries)); + + const auto statementEnd = static_cast(statement->numEntries); + + // The openingParenthesisPosition does not necessarily point to an actual opening parenthesis operator. That's fine though. + // We will pretend it does since the game does sometimes leave out opening parenthesis from the entries. + auto currentParenthesisDepth = 1; + for (auto currentSearchPosition = openingParenthesisPosition + 1; currentSearchPosition < statementEnd; currentSearchPosition++) + { + const auto& expEntry = statement->entries[currentSearchPosition]; + if (expEntry.type != EET_OPERATOR) + continue; + + // Any function means a "left out" left paren + if (expEntry.data.op == OP_LEFTPAREN || expEntry.data.op >= OP_COUNT) + { + currentParenthesisDepth++; + } + else if (expEntry.data.op == OP_RIGHTPAREN) + { + if (currentParenthesisDepth > 0) + currentParenthesisDepth--; + if (currentParenthesisDepth == 0) + return currentSearchPosition; + } + } + + return statementEnd; + } + + class MenuWriter final : public ::menu::AbstractBaseWriter, public menu::IWriterIW4 + { + public: + explicit MenuWriter(std::ostream& stream) + : AbstractBaseWriter(stream) + { + } + + void WriteFunctionDef(const std::string& functionName, const Statement_s* statement) override + { + StartFunctionDefScope(); + + WriteStringProperty("name", functionName); + WriteStatementProperty("value", statement, false); + + EndScope(); + } + + void WriteMenu(const menuDef_t& menu) override + { + StartMenuDefScope(); + + WriteMenuData(&menu); + + EndScope(); + } + + void Start() override + { + AbstractBaseWriter::Start(); + } + + void End() override + { + AbstractBaseWriter::End(); + } + + void IncludeMenu(const std::string& menuPath) const override + { + AbstractBaseWriter::IncludeMenu(menuPath); + } + + private: + void WriteStatementNaive(const Statement_s* statement) const + { + const auto entryCount = static_cast(statement->numEntries); + + const auto missingClosingParenthesis = statement->numEntries > 0 && statement->entries[0].type == EET_OPERATOR + && statement->entries[0].data.op == OP_LEFTPAREN + && FindStatementClosingParenthesis(statement, 0) >= static_cast(statement->numEntries); + + for (auto i = 0uz; i < entryCount; i++) + { + const auto& entry = statement->entries[i]; + if (entry.type == EET_OPERAND) + { + size_t pos = i; + bool discard = false; + WriteStatementOperand(statement, pos, discard); + } + else if (entry.data.op >= EXP_FUNC_STATIC_DVAR_INT && entry.data.op <= EXP_FUNC_STATIC_DVAR_STRING) + { + switch (entry.data.op) + { + case EXP_FUNC_STATIC_DVAR_INT: + m_stream << "dvarint"; + break; + + case EXP_FUNC_STATIC_DVAR_BOOL: + m_stream << "dvarbool"; + break; + + case EXP_FUNC_STATIC_DVAR_FLOAT: + m_stream << "dvarfloat"; + break; + + case EXP_FUNC_STATIC_DVAR_STRING: + m_stream << "dvarstring"; + break; + + default: + break; + } + + // Functions do not have opening parenthesis in the entries. We can just pretend they do though + const auto closingParenPos = FindStatementClosingParenthesis(statement, i); + m_stream << "("; + + if (closingParenPos - i + 1u >= 1u) + { + const auto& staticDvarEntry = statement->entries[i + 1]; + if (staticDvarEntry.type == EET_OPERAND && staticDvarEntry.data.operand.dataType == VAL_INT) + { + if (statement->supportingData && statement->supportingData->staticDvarList.staticDvars + && staticDvarEntry.data.operand.internals.intVal >= 0 + && staticDvarEntry.data.operand.internals.intVal < statement->supportingData->staticDvarList.numStaticDvars) + { + const auto* staticDvar = statement->supportingData->staticDvarList.staticDvars[staticDvarEntry.data.operand.internals.intVal]; + if (staticDvar && staticDvar->dvarName) + m_stream << staticDvar->dvarName; + } + else + { + m_stream << "#INVALID_DVAR_INDEX"; + } + } + else + { + m_stream << "#INVALID_DVAR_OPERAND"; + } + } + + m_stream << ")"; + i = closingParenPos; + } + else + { + assert(entry.data.op >= 0 && static_cast(entry.data.op) < std::extent_v); + if (entry.data.op >= 0 && static_cast(entry.data.op) < std::extent_v) + m_stream << g_expFunctionNames[entry.data.op]; + if (entry.data.op >= OP_COUNT) + m_stream << "("; + } + } + + if (missingClosingParenthesis) + m_stream << ")"; + } + + void WriteStatementOperator(const Statement_s* statement, size_t& currentPos, bool& spaceNext) const + { + const auto& expEntry = statement->entries[currentPos]; + + if (spaceNext && expEntry.data.op != OP_COMMA) + m_stream << " "; + + if (expEntry.data.op == OP_LEFTPAREN) + { + const auto closingParenPos = FindStatementClosingParenthesis(statement, currentPos); + m_stream << "("; + WriteStatementEntryRange(statement, currentPos + 1, closingParenPos); + m_stream << ")"; + + currentPos = closingParenPos + 1; + spaceNext = true; + } + else if (expEntry.data.op >= EXP_FUNC_STATIC_DVAR_INT && expEntry.data.op <= EXP_FUNC_STATIC_DVAR_STRING) + { + switch (expEntry.data.op) + { + case EXP_FUNC_STATIC_DVAR_INT: + m_stream << "dvarint"; + break; + + case EXP_FUNC_STATIC_DVAR_BOOL: + m_stream << "dvarbool"; + break; + + case EXP_FUNC_STATIC_DVAR_FLOAT: + m_stream << "dvarfloat"; + break; + + case EXP_FUNC_STATIC_DVAR_STRING: + m_stream << "dvarstring"; + break; + + default: + break; + } + + // Functions do not have opening parenthesis in the entries. We can just pretend they do though + const auto closingParenPos = FindStatementClosingParenthesis(statement, currentPos); + m_stream << "("; + + if (closingParenPos - currentPos + 1 >= 1) + { + const auto& staticDvarEntry = statement->entries[currentPos + 1]; + if (staticDvarEntry.type == EET_OPERAND && staticDvarEntry.data.operand.dataType == VAL_INT) + { + if (statement->supportingData && statement->supportingData->staticDvarList.staticDvars + && staticDvarEntry.data.operand.internals.intVal >= 0 + && staticDvarEntry.data.operand.internals.intVal < statement->supportingData->staticDvarList.numStaticDvars) + { + const auto* staticDvar = statement->supportingData->staticDvarList.staticDvars[staticDvarEntry.data.operand.internals.intVal]; + if (staticDvar && staticDvar->dvarName) + m_stream << staticDvar->dvarName; + } + else + { + m_stream << "#INVALID_DVAR_INDEX"; + } + } + else + { + m_stream << "#INVALID_DVAR_OPERAND"; + } + } + + m_stream << ")"; + currentPos = closingParenPos + 1; + spaceNext = true; + } + else + { + if (expEntry.data.op >= 0 && static_cast(expEntry.data.op) < std::extent_v) + m_stream << g_expFunctionNames[expEntry.data.op]; + + if (expEntry.data.op >= OP_COUNT) + { + // Functions do not have opening parenthesis in the entries. We can just pretend they do though + const auto closingParenPos = FindStatementClosingParenthesis(statement, currentPos); + m_stream << "("; + WriteStatementEntryRange(statement, currentPos + 1, closingParenPos); + m_stream << ")"; + currentPos = closingParenPos + 1; + } + else + currentPos++; + + spaceNext = expEntry.data.op != OP_NOT; + } + } + + void WriteStatementOperandFunction(const Statement_s* statement, size_t currentPos) const + { + const auto& operand = statement->entries[currentPos].data.operand; + + if (operand.internals.function == nullptr) + return; + + if (!ObjWriting::Configuration.MenuLegacyMode) + { + int functionIndex = -1; + if (statement->supportingData && statement->supportingData->uifunctions.functions) + { + for (auto supportingFunctionIndex = 0; supportingFunctionIndex < statement->supportingData->uifunctions.totalFunctions; + supportingFunctionIndex++) + { + if (statement->supportingData->uifunctions.functions[supportingFunctionIndex] == operand.internals.function) + { + functionIndex = supportingFunctionIndex; + break; + } + } + } + + if (functionIndex >= 0) + m_stream << "FUNC_" << functionIndex; + else + m_stream << "INVALID_FUNC"; + m_stream << "()"; + } + else + { + m_stream << "("; + WriteStatementSkipInitialUnnecessaryParenthesis(operand.internals.function); + m_stream << ")"; + } + } + + void WriteStatementOperand(const Statement_s* statement, size_t& currentPos, bool& spaceNext) const + { + const auto& expEntry = statement->entries[currentPos]; + + if (spaceNext) + m_stream << " "; + + const auto& operand = expEntry.data.operand; + + switch (operand.dataType) + { + case VAL_FLOAT: + m_stream << operand.internals.floatVal; + break; + + case VAL_INT: + m_stream << operand.internals.intVal; + break; + + case VAL_STRING: + WriteEscapedString(operand.internals.stringVal.string); + break; + + case VAL_FUNCTION: + WriteStatementOperandFunction(statement, currentPos); + break; + + default: + break; + } + + currentPos++; + spaceNext = true; + } + + void WriteStatementEntryRange(const Statement_s* statement, size_t startOffset, size_t endOffset) const + { + assert(startOffset <= endOffset); + assert(endOffset <= static_cast(statement->numEntries)); + + auto currentPos = startOffset; + auto spaceNext = false; + while (currentPos < endOffset) + { + const auto& expEntry = statement->entries[currentPos]; + + if (expEntry.type == EET_OPERATOR) + { + WriteStatementOperator(statement, currentPos, spaceNext); + } + else + { + WriteStatementOperand(statement, currentPos, spaceNext); + } + } + } + + void WriteStatement(const Statement_s* statement) const + { + if (statement == nullptr || statement->numEntries < 0) + return; + + WriteStatementEntryRange(statement, 0, static_cast(statement->numEntries)); + } + + void WriteStatementSkipInitialUnnecessaryParenthesis(const Statement_s* statementValue) const + { + if (statementValue == nullptr || statementValue->numEntries < 0) + return; + + const auto statementEnd = static_cast(statementValue->numEntries); + + if (statementValue->numEntries >= 1 && statementValue->entries[0].type == EET_OPERATOR && statementValue->entries[0].data.op == OP_LEFTPAREN) + { + const auto parenthesisEnd = FindStatementClosingParenthesis(statementValue, 0); + + if (parenthesisEnd >= statementEnd) + WriteStatementEntryRange(statementValue, 1, statementEnd); + else if (parenthesisEnd == statementEnd - 1) + WriteStatementEntryRange(statementValue, 1, statementEnd - 1); + else + WriteStatementEntryRange(statementValue, 0, statementEnd); + } + else + { + WriteStatementEntryRange(statementValue, 0, statementEnd); + } + } + + void WriteStatementProperty(const std::string& propertyKey, const Statement_s* statementValue, bool isBooleanStatement) const + { + if (statementValue == nullptr || statementValue->numEntries < 0) + return; + + Indent(); + WriteKey(propertyKey); + + if (isBooleanStatement) + { + m_stream << "when("; + DUMP_FUNC(statementValue); + m_stream << ");\n"; + } + else + { + DUMP_FUNC(statementValue); + m_stream << ";\n"; + } + } + + void WriteSetLocalVarData(const std::string& setFunction, const SetLocalVarData* setLocalVarData) const + { + if (setLocalVarData == nullptr) + return; + + Indent(); + m_stream << setFunction << " " << setLocalVarData->localVarName << " "; + WriteStatement(setLocalVarData->expression); + m_stream << ";\n"; + } + + // #define WRITE_ORIGINAL_SCRIPT + void WriteUnconditionalScript(const char* script) const + { +#ifdef WRITE_ORIGINAL_SCRIPT + Indent(); + m_stream << script << "\n"; + return; +#endif + + const auto tokenList = CreateScriptTokenList(script); + + auto isNewStatement = true; + for (const auto& token : tokenList) + { + if (isNewStatement) + { + if (token == ";") + continue; + + Indent(); + } + + if (token == ";") + { + m_stream << ";\n"; + isNewStatement = true; + continue; + } + + if (!isNewStatement) + m_stream << " "; + else + isNewStatement = false; + + if (DoesTokenNeedQuotationMarks(token)) + m_stream << "\"" << token << "\""; + else + m_stream << token; + } + + if (!isNewStatement) + m_stream << ";\n"; + } + + void WriteMenuEventHandlerSet(const MenuEventHandlerSet* eventHandlerSet) + { + Indent(); + m_stream << "{\n"; + IncIndent(); + + for (auto i = 0; i < eventHandlerSet->eventHandlerCount; i++) + { + const auto* eventHandler = eventHandlerSet->eventHandlers[i]; + if (eventHandler == nullptr) + continue; + + switch (eventHandler->eventType) + { + case EVENT_UNCONDITIONAL: + WriteUnconditionalScript(eventHandler->eventData.unconditionalScript); + break; + + case EVENT_IF: + if (eventHandler->eventData.conditionalScript == nullptr || eventHandler->eventData.conditionalScript->eventExpression == nullptr + || eventHandler->eventData.conditionalScript->eventHandlerSet == nullptr) + { + continue; + } + + Indent(); + m_stream << "if ("; + WriteStatementSkipInitialUnnecessaryParenthesis(eventHandler->eventData.conditionalScript->eventExpression); + m_stream << ")\n"; + WriteMenuEventHandlerSet(eventHandler->eventData.conditionalScript->eventHandlerSet); + break; + + case EVENT_ELSE: + if (eventHandler->eventData.elseScript == nullptr) + continue; + + Indent(); + m_stream << "else\n"; + WriteMenuEventHandlerSet(eventHandler->eventData.elseScript); + break; + + case EVENT_SET_LOCAL_VAR_BOOL: + WriteSetLocalVarData("setLocalVarBool", eventHandler->eventData.setLocalVarData); + break; + + case EVENT_SET_LOCAL_VAR_INT: + WriteSetLocalVarData("setLocalVarInt", eventHandler->eventData.setLocalVarData); + break; + + case EVENT_SET_LOCAL_VAR_FLOAT: + WriteSetLocalVarData("setLocalVarFloat", eventHandler->eventData.setLocalVarData); + break; + + case EVENT_SET_LOCAL_VAR_STRING: + WriteSetLocalVarData("setLocalVarString", eventHandler->eventData.setLocalVarData); + break; + + default: + break; + } + } + + DecIndent(); + Indent(); + m_stream << "}\n"; + } + + void WriteMenuEventHandlerSetProperty(const std::string& propertyKey, const MenuEventHandlerSet* eventHandlerSetValue) + { + if (eventHandlerSetValue == nullptr) + return; + + Indent(); + m_stream << propertyKey << "\n"; + WriteMenuEventHandlerSet(eventHandlerSetValue); + } + + void WriteRectProperty(const std::string& propertyKey, const rectDef_s& rect) const + { + Indent(); + WriteKey(propertyKey); + m_stream << rect.x << " " << rect.y << " " << rect.w << " " << rect.h << " " << static_cast(rect.horzAlign) << " " + << static_cast(rect.vertAlign) << "\n"; + } + + void WriteMaterialProperty(const std::string& propertyKey, const Material* materialValue) const + { + if (materialValue == nullptr || materialValue->info.name == nullptr) + return; + + if (materialValue->info.name[0] == ',') + WriteStringProperty(propertyKey, &materialValue->info.name[1]); + else + WriteStringProperty(propertyKey, materialValue->info.name); + } + + void WriteSoundAliasProperty(const std::string& propertyKey, const snd_alias_list_t* soundAliasValue) const + { + if (soundAliasValue == nullptr) + return; + + WriteStringProperty(propertyKey, soundAliasValue->aliasName); + } + + void WriteDecodeEffectProperty(const std::string& propertyKey, const itemDef_s* item) const + { + if (!item->decayActive) + return; + + Indent(); + WriteKey(propertyKey); + m_stream << item->fxLetterTime << " " << item->fxDecayStartTime << " " << item->fxDecayDuration << "\n"; + } + + void WriteItemKeyHandlerProperty(const ItemKeyHandler* itemKeyHandlerValue) + { + for (const auto* currentHandler = itemKeyHandlerValue; currentHandler; currentHandler = currentHandler->next) + { + if (currentHandler->key >= '!' && currentHandler->key <= '~' && currentHandler->key != '"') + { + std::ostringstream ss; + ss << "execKey \"" << static_cast(currentHandler->key) << "\""; + WriteMenuEventHandlerSetProperty(ss.str(), currentHandler->action); + } + else + { + std::ostringstream ss; + ss << "execKeyInt " << currentHandler->key; + WriteMenuEventHandlerSetProperty(ss.str(), currentHandler->action); + } + } + } + + void WriteMultiTokenStringProperty(const std::string& propertyKey, const char* value) const + { + if (!value) + return; + + Indent(); + WriteKey(propertyKey); + + const auto tokenList = CreateScriptTokenList(value); + + auto firstToken = true; + m_stream << "{ "; + for (const auto& token : tokenList) + { + if (firstToken) + firstToken = false; + else + m_stream << ";"; + m_stream << "\"" << token << "\""; + } + if (!firstToken) + m_stream << " "; + m_stream << "}\n"; + } + + void WriteFloatExpressionsProperty(const ItemFloatExpression* floatExpressions, int floatExpressionCount) const + { + if (!floatExpressions) + return; + + for (int i = 0; i < floatExpressionCount; i++) + { + const auto& floatExpression = floatExpressions[i]; + + if (floatExpression.target < 0 || floatExpression.target >= ITEM_FLOATEXP_TGT_COUNT) + continue; + + std::string propertyName = std::string("exp ") + floatExpressionTargetBindings[floatExpression.target].name + std::string(" ") + + floatExpressionTargetBindings[floatExpression.target].componentName; + + WriteStatementProperty(propertyName, floatExpression.expression, false); + } + } + + void WriteColumnProperty(const std::string& propertyKey, const listBoxDef_s* listBox) const + { + if (listBox->numColumns <= 0) + return; + + Indent(); + WriteKey(propertyKey); + m_stream << listBox->numColumns << "\n"; + + for (auto col = 0; col < listBox->numColumns; col++) + { + Indent(); + for (auto i = 0u; i < MENU_KEY_SPACING; i++) + m_stream << " "; + + m_stream << listBox->columnInfo[col].pos << " " << listBox->columnInfo[col].width << " " << listBox->columnInfo[col].maxChars << " " + << listBox->columnInfo[col].alignment << "\n"; + } + } + + void WriteListBoxProperties(const itemDef_s* item) + { + if (item->type != ITEM_TYPE_LISTBOX || item->typeData.listBox == nullptr) + return; + + const auto* listBox = item->typeData.listBox; + WriteKeywordProperty("notselectable", listBox->notselectable != 0); + WriteKeywordProperty("noscrollbars", listBox->noScrollBars != 0); + WriteKeywordProperty("usepaging", listBox->usePaging != 0); + WriteFloatProperty("elementwidth", listBox->elementWidth, 0.0f); + WriteFloatProperty("elementheight", listBox->elementHeight, 0.0f); + WriteFloatProperty("feeder", item->special, 0.0f); + WriteIntProperty("elementtype", listBox->elementStyle, 0); + WriteColumnProperty("columns", listBox); + WriteMenuEventHandlerSetProperty("doubleclick", listBox->onDoubleClick); + WriteColorProperty("selectBorder", listBox->selectBorder, COLOR_0000); + WriteMaterialProperty("selectIcon", listBox->selectIcon); + } + + void WriteDvarFloatProperty(const std::string& propertyKey, const itemDef_s* item, const editFieldDef_s* editField) const + { + if (item->dvar == nullptr) + return; + + Indent(); + WriteKey(propertyKey); + m_stream << "\"" << item->dvar << "\" " << editField->defVal << " " << editField->minVal << " " << editField->maxVal << "\n"; + } + + void WriteEditFieldProperties(const itemDef_s* item) const + { + switch (item->type) + { + case ITEM_TYPE_TEXT: + case ITEM_TYPE_EDITFIELD: + case ITEM_TYPE_NUMERICFIELD: + case ITEM_TYPE_SLIDER: + case ITEM_TYPE_YESNO: + case ITEM_TYPE_BIND: + case ITEM_TYPE_VALIDFILEFIELD: + case ITEM_TYPE_DECIMALFIELD: + case ITEM_TYPE_UPREDITFIELD: + case ITEM_TYPE_EMAILFIELD: + case ITEM_TYPE_PASSWORDFIELD: + break; + + default: + return; + } + + if (item->typeData.editField == nullptr) + return; + + const auto* editField = item->typeData.editField; + if (std::fabs(-1.0f - editField->defVal) >= std::numeric_limits::epsilon() + || std::fabs(-1.0f - editField->minVal) >= std::numeric_limits::epsilon() + || std::fabs(-1.0f - editField->maxVal) >= std::numeric_limits::epsilon()) + { + WriteDvarFloatProperty("dvarFloat", item, editField); + } + else + { + WriteStringProperty("dvar", item->dvar); + } + WriteStringProperty("localvar", item->localVar); + WriteIntProperty("maxChars", editField->maxChars, 0); + WriteKeywordProperty("maxCharsGotoNext", editField->maxCharsGotoNext != 0); + WriteIntProperty("maxPaintChars", editField->maxPaintChars, 0); + } + + void WriteMultiValueProperty(const multiDef_s* multiDef) const + { + Indent(); + if (multiDef->strDef) + WriteKey("dvarStrList"); + else + WriteKey("dvarFloatList"); + + m_stream << "{"; + for (auto i = 0; i < multiDef->count; i++) + { + if (multiDef->dvarList[i] == nullptr || multiDef->strDef && multiDef->dvarStr[i] == nullptr) + continue; + + m_stream << " \"" << multiDef->dvarList[i] << "\""; + + if (multiDef->strDef) + m_stream << " \"" << multiDef->dvarStr[i] << "\""; + else + m_stream << " " << multiDef->dvarValue[i] << ""; + } + m_stream << " }\n"; + } + + void WriteMultiProperties(const itemDef_s* item) const + { + if (item->type != ITEM_TYPE_MULTI || item->typeData.multi == nullptr) + return; + + const auto* multiDef = item->typeData.multi; + + if (multiDef->count <= 0) + return; + + WriteStringProperty("dvar", item->dvar); + WriteStringProperty("localvar", item->localVar); + WriteMultiValueProperty(multiDef); + } + + void WriteEnumDvarProperties(const itemDef_s* item) const + { + if (item->type != ITEM_TYPE_DVARENUM) + return; + + WriteStringProperty("dvar", item->dvar); + WriteStringProperty("localvar", item->localVar); + WriteStringProperty("dvarEnumList", item->typeData.enumDvarName); + } + + void WriteTickerProperties(const itemDef_s* item) const + { + if (item->type != ITEM_TYPE_NEWS_TICKER || item->typeData.ticker == nullptr) + return; + + const auto* newsTickerDef = item->typeData.ticker; + WriteIntProperty("spacing", newsTickerDef->spacing, 0); + WriteIntProperty("speed", newsTickerDef->speed, 0); + WriteIntProperty("newsfeed", newsTickerDef->feedId, 0); + } + + void WriteItemData(const itemDef_s* item) + { + WriteStringProperty("name", item->window.name); + WriteStringProperty("text", item->text); + WriteKeywordProperty("textsavegame", item->itemFlags & ITEM_FLAG_SAVE_GAME_INFO); + WriteKeywordProperty("textcinematicsubtitle", item->itemFlags & ITEM_FLAG_CINEMATIC_SUBTITLE); + WriteStringProperty("group", item->window.group); + WriteRectProperty("rect", item->window.rectClient); + WriteIntProperty("style", item->window.style, 0); + WriteKeywordProperty("decoration", item->window.staticFlags & WINDOW_FLAG_DECORATION); + WriteKeywordProperty("autowrapped", item->window.staticFlags & WINDOW_FLAG_AUTO_WRAPPED); + WriteKeywordProperty("horizontalscroll", item->window.staticFlags & WINDOW_FLAG_HORIZONTAL_SCROLL); + WriteIntProperty("type", item->type, ITEM_TYPE_TEXT); + WriteIntProperty("border", item->window.border, 0); + WriteFloatProperty("borderSize", item->window.borderSize, 0.0f); + + if (item->visibleExp) + WriteStatementProperty("visible", item->visibleExp, true); + else if (item->window.dynamicFlags[0] & WINDOW_FLAG_VISIBLE) + WriteIntProperty("visible", 1, 0); + + WriteStatementProperty("disabled", item->disabledExp, true); + WriteIntProperty("ownerdraw", item->window.ownerDraw, 0); + WriteFlagsProperty("ownerdrawFlag", item->window.ownerDrawFlags); + WriteIntProperty("align", item->alignment, 0); + WriteIntProperty("textalign", item->textAlignMode, 0); + WriteFloatProperty("textalignx", item->textalignx, 0.0f); + WriteFloatProperty("textaligny", item->textaligny, 0.0f); + WriteFloatProperty("textscale", item->textscale, 0.0f); + WriteIntProperty("textstyle", item->textStyle, 0); + WriteIntProperty("textfont", item->fontEnum, 0); + WriteColorProperty("backcolor", item->window.backColor, COLOR_0000); + WriteColorProperty("forecolor", item->window.foreColor, COLOR_1111); + WriteColorProperty("bordercolor", item->window.borderColor, COLOR_0000); + WriteColorProperty("outlinecolor", item->window.outlineColor, COLOR_0000); + WriteColorProperty("disablecolor", item->window.disableColor, COLOR_0000); + WriteColorProperty("glowcolor", item->glowColor, COLOR_0000); + WriteMaterialProperty("background", item->window.background); + WriteMenuEventHandlerSetProperty("onFocus", item->onFocus); + WriteMenuEventHandlerSetProperty("leaveFocus", item->leaveFocus); + WriteMenuEventHandlerSetProperty("mouseEnter", item->mouseEnter); + WriteMenuEventHandlerSetProperty("mouseExit", item->mouseExit); + WriteMenuEventHandlerSetProperty("mouseEnterText", item->mouseEnterText); + WriteMenuEventHandlerSetProperty("mouseExitText", item->mouseExitText); + WriteMenuEventHandlerSetProperty("action", item->action); + WriteMenuEventHandlerSetProperty("accept", item->accept); + // WriteFloatProperty("special", item->special, 0.0f); + WriteSoundAliasProperty("focusSound", item->focusSound); + WriteStringProperty("dvarTest", item->dvarTest); + + if (item->dvarFlags & ITEM_DVAR_FLAG_ENABLE) + WriteMultiTokenStringProperty("enableDvar", item->enableDvar); + else if (item->dvarFlags & ITEM_DVAR_FLAG_DISABLE) + WriteMultiTokenStringProperty("disableDvar", item->enableDvar); + else if (item->dvarFlags & ITEM_DVAR_FLAG_SHOW) + WriteMultiTokenStringProperty("showDvar", item->enableDvar); + else if (item->dvarFlags & ITEM_DVAR_FLAG_HIDE) + WriteMultiTokenStringProperty("hideDvar", item->enableDvar); + else if (item->dvarFlags & ITEM_DVAR_FLAG_FOCUS) + WriteMultiTokenStringProperty("focusDvar", item->enableDvar); + + WriteItemKeyHandlerProperty(item->onKey); + WriteStatementProperty("exp text", item->textExp, false); + WriteStatementProperty("exp material", item->materialExp, false); + WriteFloatExpressionsProperty(item->floatExpressions, item->floatExpressionCount); + WriteIntProperty("gamemsgwindowindex", item->gameMsgWindowIndex, 0); + WriteIntProperty("gamemsgwindowmode", item->gameMsgWindowMode, 0); + WriteDecodeEffectProperty("decodeEffect", item); + + WriteListBoxProperties(item); + WriteEditFieldProperties(item); + WriteMultiProperties(item); + WriteEnumDvarProperties(item); + WriteTickerProperties(item); + } + + void WriteItemDefs(const itemDef_s* const* itemDefs, size_t itemCount) + { + for (auto i = 0u; i < itemCount; i++) + { + StartItemDefScope(); + + WriteItemData(itemDefs[i]); + + EndScope(); + } + } + + void WriteMenuData(const menuDef_t* menu) + { + WriteStringProperty("name", menu->window.name); + WriteBoolProperty("fullscreen", menu->fullScreen, false); + WriteKeywordProperty("screenSpace", menu->window.staticFlags & WINDOW_FLAG_SCREEN_SPACE); + WriteKeywordProperty("decoration", menu->window.staticFlags & WINDOW_FLAG_DECORATION); + WriteRectProperty("rect", menu->window.rect); + WriteIntProperty("style", menu->window.style, 0); + WriteIntProperty("border", menu->window.border, 0); + WriteFloatProperty("borderSize", menu->window.borderSize, 0.0f); + WriteColorProperty("backcolor", menu->window.backColor, COLOR_0000); + WriteColorProperty("forecolor", menu->window.foreColor, COLOR_1111); + WriteColorProperty("bordercolor", menu->window.borderColor, COLOR_0000); + WriteColorProperty("focuscolor", menu->focusColor, COLOR_0000); + WriteColorProperty("outlinecolor", menu->window.outlineColor, COLOR_0000); + WriteMaterialProperty("background", menu->window.background); + WriteIntProperty("ownerdraw", menu->window.ownerDraw, 0); + WriteFlagsProperty("ownerdrawFlag", menu->window.ownerDrawFlags); + WriteKeywordProperty("outOfBoundsClick", menu->window.staticFlags & WINDOW_FLAG_OUT_OF_BOUNDS_CLICK); + WriteStringProperty("soundLoop", menu->soundName); + WriteKeywordProperty("popup", menu->window.staticFlags & WINDOW_FLAG_POPUP); + WriteFloatProperty("fadeClamp", menu->fadeClamp, 0.0f); + WriteIntProperty("fadeCycle", menu->fadeCycle, 0); + WriteFloatProperty("fadeAmount", menu->fadeAmount, 0.0f); + WriteFloatProperty("fadeInAmount", menu->fadeInAmount, 0.0f); + WriteFloatProperty("blurWorld", menu->blurRadius, 0.0f); + WriteKeywordProperty("legacySplitScreenScale", menu->window.staticFlags & WINDOW_FLAG_LEGACY_SPLIT_SCREEN_SCALE); + WriteKeywordProperty("hiddenDuringScope", menu->window.staticFlags & WINDOW_FLAG_HIDDEN_DURING_SCOPE); + WriteKeywordProperty("hiddenDuringFlashbang", menu->window.staticFlags & WINDOW_FLAG_HIDDEN_DURING_FLASH_BANG); + WriteKeywordProperty("hiddenDuringUI", menu->window.staticFlags & WINDOW_FLAG_HIDDEN_DURING_UI); + WriteStringProperty("allowedBinding", menu->allowedBinding); + WriteKeywordProperty("textOnlyFocus", menu->window.staticFlags & WINDOW_FLAG_TEXT_ONLY_FOCUS); + + if (menu->visibleExp) + WriteStatementProperty("visible", menu->visibleExp, true); + else if (menu->window.dynamicFlags[0] & WINDOW_FLAG_VISIBLE) + WriteIntProperty("visible", 1, 0); + + WriteStatementProperty("exp rect X", menu->rectXExp, false); + WriteStatementProperty("exp rect Y", menu->rectYExp, false); + WriteStatementProperty("exp rect W", menu->rectWExp, false); + WriteStatementProperty("exp rect H", menu->rectHExp, false); + WriteStatementProperty("exp openSound", menu->openSoundExp, false); + WriteStatementProperty("exp closeSound", menu->closeSoundExp, false); + WriteMenuEventHandlerSetProperty("onOpen", menu->onOpen); + WriteMenuEventHandlerSetProperty("onClose", menu->onClose); + WriteMenuEventHandlerSetProperty("onRequestClose", menu->onCloseRequest); + WriteMenuEventHandlerSetProperty("onESC", menu->onESC); + WriteItemKeyHandlerProperty(menu->onKey); + WriteItemDefs(menu->items, menu->itemCount); + } + }; +} // namespace + +namespace menu +{ + std::unique_ptr CreateMenuWriterIW4(std::ostream& stream) + { + return std::make_unique(stream); + } +} // namespace menu diff --git a/src/ObjWriting/Game/IW4/Menu/MenuWriterIW4.h b/src/ObjWriting/Game/IW4/Menu/MenuWriterIW4.h new file mode 100644 index 00000000..3988bbb3 --- /dev/null +++ b/src/ObjWriting/Game/IW4/Menu/MenuWriterIW4.h @@ -0,0 +1,19 @@ +#pragma once + +#include "Game/IW4/IW4.h" +#include "Menu/IMenuWriter.h" + +#include +#include + +namespace menu +{ + class IWriterIW4 : public IWriter + { + public: + virtual void WriteFunctionDef(const std::string& functionName, const IW4::Statement_s* statement) = 0; + virtual void WriteMenu(const IW4::menuDef_t& menu) = 0; + }; + + std::unique_ptr CreateMenuWriterIW4(std::ostream& stream); +} // namespace menu diff --git a/src/ObjWriting/Game/IW4/ObjWriterIW4.cpp b/src/ObjWriting/Game/IW4/ObjWriterIW4.cpp index 0516a4af..b749a985 100644 --- a/src/ObjWriting/Game/IW4/ObjWriterIW4.cpp +++ b/src/ObjWriting/Game/IW4/ObjWriterIW4.cpp @@ -1,29 +1,30 @@ #include "ObjWriterIW4.h" -#include "AssetDumpers/AssetDumperAddonMapEnts.h" -#include "AssetDumpers/AssetDumperGfxImage.h" -#include "AssetDumpers/AssetDumperGfxLightDef.h" -#include "AssetDumpers/AssetDumperLeaderboardDef.h" -#include "AssetDumpers/AssetDumperLoadedSound.h" -#include "AssetDumpers/AssetDumperLocalizeEntry.h" -#include "AssetDumpers/AssetDumperMenuDef.h" -#include "AssetDumpers/AssetDumperMenuList.h" -#include "AssetDumpers/AssetDumperPhysCollmap.h" -#include "AssetDumpers/AssetDumperPhysPreset.h" -#include "AssetDumpers/AssetDumperPixelShader.h" -#include "AssetDumpers/AssetDumperRawFile.h" -#include "AssetDumpers/AssetDumperSndCurve.h" -#include "AssetDumpers/AssetDumperStringTable.h" -#include "AssetDumpers/AssetDumperStructuredDataDefSet.h" -#include "AssetDumpers/AssetDumperTechniqueSet.h" -#include "AssetDumpers/AssetDumperTracer.h" -#include "AssetDumpers/AssetDumperVehicle.h" -#include "AssetDumpers/AssetDumperVertexShader.h" -#include "AssetDumpers/AssetDumperWeapon.h" -#include "AssetDumpers/AssetDumperXModel.h" #include "Game/IW4/GameAssetPoolIW4.h" -#include "Material/DumperMaterialIW4.h" +#include "Game/IW4/Material/MaterialJsonDumperIW4.h" +#include "Game/IW4/XModel/XModelDumperIW4.h" +#include "Image/ImageDumperIW4.h" +#include "Leaderboard/LeaderboardJsonDumperIW4.h" +#include "LightDef/LightDefDumperIW4.h" +#include "Localize/LocalizeDumperIW4.h" +#include "Maps/AddonMapEntsDumperIW4.h" +#include "Material/MaterialDecompilingDumperIW4.h" +#include "Menu/MenuDumperIW4.h" +#include "Menu/MenuListDumperIW4.h" #include "ObjWriting.h" +#include "PhysCollmap/PhysCollmapDumperIW4.h" +#include "PhysPreset/PhysPresetInfoStringDumperIW4.h" +#include "RawFile/RawFileDumperIW4.h" +#include "Shader/PixelShaderDumperIW4.h" +#include "Shader/VertexShaderDumperIW4.h" +#include "Sound/LoadedSoundDumperIW4.h" +#include "Sound/SndCurveDumperIW4.h" +#include "StringTable/StringTableDumperIW4.h" +#include "StructuredDataDef/StructuredDataDefDumperIW4.h" +#include "Techset/TechsetDumperIW4.h" +#include "Tracer/TracerDumperIW4.h" +#include "Vehicle/VehicleDumperIW4.h" +#include "Weapon/WeaponDumperIW4.h" using namespace IW4; @@ -38,18 +39,21 @@ bool ObjWriter::DumpZone(AssetDumpingContext& context) const const auto* assetPools = dynamic_cast(context.m_zone.m_pools.get()); - DUMP_ASSET_POOL(AssetDumperPhysPreset, m_phys_preset, ASSET_TYPE_PHYSPRESET) - DUMP_ASSET_POOL(AssetDumperPhysCollmap, m_phys_collmap, ASSET_TYPE_PHYSCOLLMAP) + DUMP_ASSET_POOL(phys_preset::InfoStringDumperIW4, m_phys_preset, ASSET_TYPE_PHYSPRESET) + DUMP_ASSET_POOL(phys_collmap::DumperIW4, m_phys_collmap, ASSET_TYPE_PHYSCOLLMAP) // DUMP_ASSET_POOL(AssetDumperXAnimParts, m_xanim_parts, ASSET_TYPE_XANIMPARTS) - DUMP_ASSET_POOL(AssetDumperXModel, m_xmodel, ASSET_TYPE_XMODEL) - DUMP_ASSET_POOL(AssetDumperMaterial, m_material, ASSET_TYPE_MATERIAL) - DUMP_ASSET_POOL(AssetDumperPixelShader, m_material_pixel_shader, ASSET_TYPE_PIXELSHADER) - DUMP_ASSET_POOL(AssetDumperVertexShader, m_material_vertex_shader, ASSET_TYPE_VERTEXSHADER) - DUMP_ASSET_POOL(AssetDumperTechniqueSet, m_technique_set, ASSET_TYPE_TECHNIQUE_SET) - DUMP_ASSET_POOL(AssetDumperGfxImage, m_image, ASSET_TYPE_IMAGE) + DUMP_ASSET_POOL(xmodel::DumperIW4, m_xmodel, ASSET_TYPE_XMODEL) + DUMP_ASSET_POOL(material::JsonDumperIW4, m_material, ASSET_TYPE_MATERIAL) +#ifdef EXPERIMENTAL_MATERIAL_COMPILATION + DUMP_ASSET_POOL(material::DecompilingGdtDumperIW4, m_material, ASSET_TYPE_MATERIAL) +#endif + DUMP_ASSET_POOL(shader::PixelShaderDumperIW4, m_material_pixel_shader, ASSET_TYPE_PIXELSHADER) + DUMP_ASSET_POOL(shader::VertexShaderDumperIW4, m_material_vertex_shader, ASSET_TYPE_VERTEXSHADER) + DUMP_ASSET_POOL(techset::DumperIW4, m_technique_set, ASSET_TYPE_TECHNIQUE_SET) + DUMP_ASSET_POOL(image::DumperIW4, m_image, ASSET_TYPE_IMAGE) // DUMP_ASSET_POOL(AssetDumpersnd_alias_list_t, m_sound, ASSET_TYPE_SOUND) - DUMP_ASSET_POOL(AssetDumperSndCurve, m_sound_curve, ASSET_TYPE_SOUND_CURVE) - DUMP_ASSET_POOL(AssetDumperLoadedSound, m_loaded_sound, ASSET_TYPE_LOADED_SOUND) + DUMP_ASSET_POOL(sound_curve::DumperIW4, m_sound_curve, ASSET_TYPE_SOUND_CURVE) + DUMP_ASSET_POOL(sound::LoadedSoundDumperIW4, m_loaded_sound, ASSET_TYPE_LOADED_SOUND) // DUMP_ASSET_POOL(AssetDumperClipMap, m_clip_map, ASSET_TYPE_CLIPMAP_MP) // DUMP_ASSET_POOL(AssetDumperComWorld, m_com_world, ASSET_TYPE_COMWORLD) // DUMP_ASSET_POOL(AssetDumperGameWorldSp, m_game_world_sp, ASSET_TYPE_GAMEWORLD_SP) @@ -57,22 +61,22 @@ bool ObjWriter::DumpZone(AssetDumpingContext& context) const // DUMP_ASSET_POOL(AssetDumperMapEnts, m_map_ents, ASSET_TYPE_MAP_ENTS) // DUMP_ASSET_POOL(AssetDumperFxWorld, m_fx_world, ASSET_TYPE_FXWORLD) // DUMP_ASSET_POOL(AssetDumperGfxWorld, m_gfx_world, ASSET_TYPE_GFXWORLD) - DUMP_ASSET_POOL(AssetDumperGfxLightDef, m_gfx_light_def, ASSET_TYPE_LIGHT_DEF) + DUMP_ASSET_POOL(light_def::DumperIW4, m_gfx_light_def, ASSET_TYPE_LIGHT_DEF) // DUMP_ASSET_POOL(AssetDumperFont_s, m_font, ASSET_TYPE_FONT) - DUMP_ASSET_POOL(AssetDumperMenuList, m_menu_list, ASSET_TYPE_MENULIST) - DUMP_ASSET_POOL(AssetDumperMenuDef, m_menu_def, ASSET_TYPE_MENU) - DUMP_ASSET_POOL(AssetDumperLocalizeEntry, m_localize, ASSET_TYPE_LOCALIZE_ENTRY) - DUMP_ASSET_POOL(AssetDumperWeapon, m_weapon, ASSET_TYPE_WEAPON) + DUMP_ASSET_POOL(menu::MenuListDumperIW4, m_menu_list, ASSET_TYPE_MENULIST) + DUMP_ASSET_POOL(menu::MenuDumperIW4, m_menu_def, ASSET_TYPE_MENU) + DUMP_ASSET_POOL(localize::DumperIW4, m_localize, ASSET_TYPE_LOCALIZE_ENTRY) + DUMP_ASSET_POOL(weapon::DumperIW4, m_weapon, ASSET_TYPE_WEAPON) // DUMP_ASSET_POOL(AssetDumperSndDriverGlobals, m_snd_driver_globals, ASSET_TYPE_SNDDRIVER_GLOBALS) // DUMP_ASSET_POOL(AssetDumperFxEffectDef, m_fx, ASSET_TYPE_FX) // DUMP_ASSET_POOL(AssetDumperFxImpactTable, m_fx_impact_table, ASSET_TYPE_IMPACT_FX) - DUMP_ASSET_POOL(AssetDumperRawFile, m_raw_file, ASSET_TYPE_RAWFILE) - DUMP_ASSET_POOL(AssetDumperStringTable, m_string_table, ASSET_TYPE_STRINGTABLE) - DUMP_ASSET_POOL(AssetDumperLeaderboardDef, m_leaderboard, ASSET_TYPE_LEADERBOARD) - DUMP_ASSET_POOL(AssetDumperStructuredDataDefSet, m_structed_data_def_set, ASSET_TYPE_STRUCTURED_DATA_DEF) - DUMP_ASSET_POOL(AssetDumperTracer, m_tracer, ASSET_TYPE_TRACER) - DUMP_ASSET_POOL(AssetDumperVehicle, m_vehicle, ASSET_TYPE_VEHICLE) - DUMP_ASSET_POOL(AssetDumperAddonMapEnts, m_addon_map_ents, ASSET_TYPE_ADDON_MAP_ENTS) + DUMP_ASSET_POOL(raw_file::DumperIW4, m_raw_file, ASSET_TYPE_RAWFILE) + DUMP_ASSET_POOL(string_table::DumperIW4, m_string_table, ASSET_TYPE_STRINGTABLE) + DUMP_ASSET_POOL(leaderboard::JsonDumperIW4, m_leaderboard, ASSET_TYPE_LEADERBOARD) + DUMP_ASSET_POOL(structured_data_def::DumperIW4, m_structed_data_def_set, ASSET_TYPE_STRUCTURED_DATA_DEF) + DUMP_ASSET_POOL(tracer::DumperIW4, m_tracer, ASSET_TYPE_TRACER) + DUMP_ASSET_POOL(vehicle::DumperIW4, m_vehicle, ASSET_TYPE_VEHICLE) + DUMP_ASSET_POOL(addon_map_ents::DumperIW4, m_addon_map_ents, ASSET_TYPE_ADDON_MAP_ENTS) return true; diff --git a/src/ObjWriting/Game/IW4/PhysCollmap/PhysCollmapDumperIW4.cpp b/src/ObjWriting/Game/IW4/PhysCollmap/PhysCollmapDumperIW4.cpp new file mode 100644 index 00000000..523c64c8 --- /dev/null +++ b/src/ObjWriting/Game/IW4/PhysCollmap/PhysCollmapDumperIW4.cpp @@ -0,0 +1,82 @@ +#include "PhysCollmapDumperIW4.h" + +#include "Dumping/MapFile/MapFileDumper.h" +#include "PhysCollmap/PhysCollmapCommon.h" + +#include +#include + +using namespace IW4; + +namespace phys_collmap +{ + bool DumperIW4::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperIW4::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* physCollmap = asset->Asset(); + const auto assetFile = context.OpenAssetFile(phys_collmap::GetFileNameForAssetName(asset->m_name)); + + if (!assetFile) + return; + + MapFileDumper mapFileDumper(*assetFile); + mapFileDumper.Init(); + + if (physCollmap->count <= 0 || physCollmap->geoms == nullptr) + return; + + mapFileDumper.BeginEntity(); + + mapFileDumper.WriteKeyValue("classname", "worldspawn"); + + for (auto i = 0u; i < physCollmap->count; i++) + { + const auto& geom = physCollmap->geoms[i]; + mapFileDumper.BeginBrush(); + + switch (geom.type) + { + case PHYS_GEOM_NONE: + // TODO: Dump BrushWrapper (probably GJK related) + mapFileDumper.WriteComment("TODO: Brush data"); + break; + case PHYS_GEOM_BOX: + mapFileDumper.WritePhysicsBox({ + {geom.bounds.midPoint.v[0], geom.bounds.midPoint.v[1], geom.bounds.midPoint.v[2]}, + {geom.bounds.halfSize.v[0], geom.bounds.halfSize.v[1], geom.bounds.halfSize.v[2]}, + {geom.orientation[0][0], geom.orientation[0][1], geom.orientation[0][2] }, + {geom.orientation[1][0], geom.orientation[1][1], geom.orientation[1][2] }, + {geom.orientation[2][0], geom.orientation[2][1], geom.orientation[2][2] } + }); + break; + + case PHYS_GEOM_CYLINDER: + mapFileDumper.WritePhysicsCylinder({ + {geom.bounds.midPoint.v[0], geom.bounds.midPoint.v[1], geom.bounds.midPoint.v[2]}, + geom.bounds.halfSize.v[0], + geom.bounds.halfSize.v[2] * 2, + {geom.orientation[0][0], geom.orientation[0][1], geom.orientation[0][2] } + }); + break; + + case PHYS_GEOM_BRUSHMODEL: + case PHYS_GEOM_BRUSH: + case PHYS_GEOM_COLLMAP: + case PHYS_GEOM_CAPSULE: + case PHYS_GEOM_GLASS: + default: + // These do not seem to appear inside any collmap assets + assert(false); + break; + } + + mapFileDumper.EndBrush(); + } + + mapFileDumper.EndEntity(); + } +} // namespace phys_collmap diff --git a/src/ObjWriting/Game/IW4/PhysCollmap/PhysCollmapDumperIW4.h b/src/ObjWriting/Game/IW4/PhysCollmap/PhysCollmapDumperIW4.h new file mode 100644 index 00000000..4dbf68d6 --- /dev/null +++ b/src/ObjWriting/Game/IW4/PhysCollmap/PhysCollmapDumperIW4.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" + +namespace phys_collmap +{ + class DumperIW4 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace phys_collmap diff --git a/src/ObjWriting/Game/IW4/PhysPreset/PhysPresetInfoStringDumperIW4.cpp b/src/ObjWriting/Game/IW4/PhysPreset/PhysPresetInfoStringDumperIW4.cpp new file mode 100644 index 00000000..41ac1f64 --- /dev/null +++ b/src/ObjWriting/Game/IW4/PhysPreset/PhysPresetInfoStringDumperIW4.cpp @@ -0,0 +1,111 @@ +#include "PhysPresetInfoStringDumperIW4.h" + +#include "Game/IW4/InfoString/InfoStringFromStructConverter.h" +#include "Game/IW4/ObjConstantsIW4.h" +#include "Game/IW4/PhysPreset/PhysPresetFields.h" +#include "PhysPreset/PhysPresetCommon.h" + +#include +#include +#include +#include + +using namespace IW4; + +namespace +{ + class InfoStringFromPhysPresetConverter final : public InfoStringFromStructConverter + { + protected: + void FillFromExtensionField(const cspField_t& field) override + { + assert(false); + } + + public: + InfoStringFromPhysPresetConverter(const PhysPresetInfo* structure, + const cspField_t* fields, + const size_t fieldCount, + std::function scriptStringValueCallback) + : InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback)) + { + } + }; + + void CopyToPhysPresetInfo(const PhysPreset* physPreset, PhysPresetInfo* physPresetInfo) + { + physPresetInfo->mass = std::clamp(physPreset->mass * 1000.0f, 1.0f, 2000.0f); + physPresetInfo->bounce = physPreset->bounce; + + if (std::isinf(physPreset->friction)) + { + physPresetInfo->isFrictionInfinity = 1; + physPresetInfo->friction = 0; + } + else + { + physPresetInfo->isFrictionInfinity = 0; + physPresetInfo->friction = physPreset->friction; + } + + physPresetInfo->bulletForceScale = physPreset->bulletForceScale; + physPresetInfo->explosiveForceScale = physPreset->explosiveForceScale; + physPresetInfo->sndAliasPrefix = physPreset->sndAliasPrefix; + physPresetInfo->piecesSpreadFraction = physPreset->piecesSpreadFraction; + physPresetInfo->piecesUpwardVelocity = physPreset->piecesUpwardVelocity; + physPresetInfo->tempDefaultToCylinder = physPreset->tempDefaultToCylinder ? 1 : 0; + physPresetInfo->perSurfaceSndAlias = physPreset->perSurfaceSndAlias ? 1 : 0; + } + + InfoString CreateInfoString(XAssetInfo* asset) + { + auto* physPresetInfo = new PhysPresetInfo; + CopyToPhysPresetInfo(asset->Asset(), physPresetInfo); + + InfoStringFromPhysPresetConverter converter(physPresetInfo, + phys_preset_fields, + std::extent_v, + [asset](const scr_string_t scrStr) -> std::string + { + assert(scrStr < asset->m_zone->m_script_strings.Count()); + if (scrStr >= asset->m_zone->m_script_strings.Count()) + return ""; + + return asset->m_zone->m_script_strings[scrStr]; + }); + + return converter.Convert(); + } +} // namespace + +namespace phys_preset +{ + bool InfoStringDumperIW4::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void InfoStringDumperIW4::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + // Only dump raw when no gdt available + if (context.m_gdt) + { + const auto infoString = CreateInfoString(asset); + GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_PHYS_PRESET); + infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_PHYS_PRESET, gdtEntry); + context.m_gdt->WriteEntry(gdtEntry); + } + else + { + const auto assetFile = context.OpenAssetFile(GetFileNameForAssetName(asset->m_name)); + + if (!assetFile) + return; + + auto& stream = *assetFile; + const auto infoString = CreateInfoString(asset); + const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_PHYS_PRESET); + stream.write(stringValue.c_str(), stringValue.size()); + } + } +} // namespace phys_preset diff --git a/src/ObjWriting/Game/IW4/PhysPreset/PhysPresetInfoStringDumperIW4.h b/src/ObjWriting/Game/IW4/PhysPreset/PhysPresetInfoStringDumperIW4.h new file mode 100644 index 00000000..4651c1e0 --- /dev/null +++ b/src/ObjWriting/Game/IW4/PhysPreset/PhysPresetInfoStringDumperIW4.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" +#include "InfoString/InfoString.h" + +namespace phys_preset +{ + class InfoStringDumperIW4 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace phys_preset diff --git a/src/ObjWriting/Game/IW4/RawFile/RawFileDumperIW4.cpp b/src/ObjWriting/Game/IW4/RawFile/RawFileDumperIW4.cpp new file mode 100644 index 00000000..9698e608 --- /dev/null +++ b/src/ObjWriting/Game/IW4/RawFile/RawFileDumperIW4.cpp @@ -0,0 +1,70 @@ +#include "RawFileDumperIW4.h" + +#include +#include +#include + +using namespace IW4; + +namespace raw_file +{ + bool DumperIW4::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperIW4::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* rawFile = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name); + + if (!assetFile) + return; + + auto& stream = *assetFile; + if (rawFile->compressedLen > 0) + { + z_stream_s zs{}; + + zs.zalloc = Z_NULL; + zs.zfree = Z_NULL; + zs.opaque = Z_NULL; + zs.avail_in = 0; + zs.next_in = Z_NULL; + + int ret = inflateInit(&zs); + + if (ret != Z_OK) + { + throw std::runtime_error("Initializing inflate failed"); + } + + zs.next_in = reinterpret_cast(rawFile->data.compressedBuffer); + zs.avail_in = rawFile->compressedLen; + + Bytef buffer[0x1000]; + + while (zs.avail_in > 0) + { + zs.next_out = buffer; + zs.avail_out = sizeof(buffer); + ret = inflate(&zs, Z_SYNC_FLUSH); + + if (ret < 0) + { + std::cerr << std::format("Inflate failed when attempting to dump rawfile '{}'\n", rawFile->name); + inflateEnd(&zs); + return; + } + + stream.write(reinterpret_cast(buffer), sizeof(buffer) - zs.avail_out); + } + + inflateEnd(&zs); + } + else if (rawFile->len > 0) + { + stream.write(rawFile->data.buffer, rawFile->len); + } + } +} // namespace raw_file diff --git a/src/ObjWriting/Game/IW4/RawFile/RawFileDumperIW4.h b/src/ObjWriting/Game/IW4/RawFile/RawFileDumperIW4.h new file mode 100644 index 00000000..9b8966ea --- /dev/null +++ b/src/ObjWriting/Game/IW4/RawFile/RawFileDumperIW4.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" + +namespace raw_file +{ + class DumperIW4 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace raw_file diff --git a/src/ObjWriting/Game/IW4/Shader/PixelShaderDumperIW4.cpp b/src/ObjWriting/Game/IW4/Shader/PixelShaderDumperIW4.cpp new file mode 100644 index 00000000..318c9a68 --- /dev/null +++ b/src/ObjWriting/Game/IW4/Shader/PixelShaderDumperIW4.cpp @@ -0,0 +1,25 @@ +#include "PixelShaderDumperIW4.h" + +#include "Shader/ShaderCommon.h" + +using namespace IW4; + +namespace shader +{ + bool PixelShaderDumperIW4::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void PixelShaderDumperIW4::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* pixelShader = asset->Asset(); + const auto shaderFile = context.OpenAssetFile(shader::GetFileNameForPixelShaderAssetName(asset->m_name)); + + if (!shaderFile) + return; + + shaderFile->write(reinterpret_cast(pixelShader->prog.loadDef.program), + static_cast(pixelShader->prog.loadDef.programSize) * 4u); + } +} // namespace shader diff --git a/src/ObjWriting/Game/IW4/Shader/PixelShaderDumperIW4.h b/src/ObjWriting/Game/IW4/Shader/PixelShaderDumperIW4.h new file mode 100644 index 00000000..01404d0a --- /dev/null +++ b/src/ObjWriting/Game/IW4/Shader/PixelShaderDumperIW4.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" + +namespace shader +{ + class PixelShaderDumperIW4 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace shader diff --git a/src/ObjWriting/Game/IW4/Shader/VertexShaderDumperIW4.cpp b/src/ObjWriting/Game/IW4/Shader/VertexShaderDumperIW4.cpp new file mode 100644 index 00000000..c3954562 --- /dev/null +++ b/src/ObjWriting/Game/IW4/Shader/VertexShaderDumperIW4.cpp @@ -0,0 +1,25 @@ +#include "VertexShaderDumperIW4.h" + +#include "Shader/ShaderCommon.h" + +using namespace IW4; + +namespace shader +{ + bool VertexShaderDumperIW4::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void VertexShaderDumperIW4::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* vertexShader = asset->Asset(); + const auto shaderFile = context.OpenAssetFile(shader::GetFileNameForVertexShaderAssetName(asset->m_name)); + + if (!shaderFile) + return; + + shaderFile->write(reinterpret_cast(vertexShader->prog.loadDef.program), + static_cast(vertexShader->prog.loadDef.programSize) * 4u); + } +} // namespace shader diff --git a/src/ObjWriting/Game/IW4/Shader/VertexShaderDumperIW4.h b/src/ObjWriting/Game/IW4/Shader/VertexShaderDumperIW4.h new file mode 100644 index 00000000..1b722461 --- /dev/null +++ b/src/ObjWriting/Game/IW4/Shader/VertexShaderDumperIW4.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" + +namespace shader +{ + class VertexShaderDumperIW4 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace shader diff --git a/src/ObjWriting/Game/IW4/Sound/LoadedSoundDumperIW4.cpp b/src/ObjWriting/Game/IW4/Sound/LoadedSoundDumperIW4.cpp new file mode 100644 index 00000000..8a2c6360 --- /dev/null +++ b/src/ObjWriting/Game/IW4/Sound/LoadedSoundDumperIW4.cpp @@ -0,0 +1,52 @@ +#include "LoadedSoundDumperIW4.h" + +#include "Sound/WavTypes.h" +#include "Sound/WavWriter.h" + +#include + +using namespace IW4; + +namespace +{ + void DumpWavPcm(const LoadedSound* asset, std::ostream& stream) + { + const WavWriter writer(stream); + + const WavMetaData metaData{.channelCount = static_cast(asset->sound.info.channels), + .samplesPerSec = static_cast(asset->sound.info.rate), + .bitsPerSample = static_cast(asset->sound.info.bits)}; + + writer.WritePcmHeader(metaData, asset->sound.info.data_len); + writer.WritePcmData(asset->sound.data, asset->sound.info.data_len); + } +} // namespace + +namespace sound +{ + bool LoadedSoundDumperIW4::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void LoadedSoundDumperIW4::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* loadedSound = asset->Asset(); + const auto assetFile = context.OpenAssetFile(std::format("sound/{}", asset->m_name)); + + if (!assetFile) + return; + + auto& stream = *assetFile; + switch (static_cast(loadedSound->sound.info.format)) + { + case WavFormat::PCM: + DumpWavPcm(loadedSound, stream); + break; + + default: + std::cerr << std::format("Unknown format {} for loaded sound: {}\n", loadedSound->sound.info.format, loadedSound->name); + break; + } + } +} // namespace sound diff --git a/src/ObjWriting/Game/IW4/Sound/LoadedSoundDumperIW4.h b/src/ObjWriting/Game/IW4/Sound/LoadedSoundDumperIW4.h new file mode 100644 index 00000000..7256bc88 --- /dev/null +++ b/src/ObjWriting/Game/IW4/Sound/LoadedSoundDumperIW4.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" + +namespace sound +{ + class LoadedSoundDumperIW4 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace sound diff --git a/src/ObjWriting/Game/IW4/Sound/SndCurveDumperIW4.cpp b/src/ObjWriting/Game/IW4/Sound/SndCurveDumperIW4.cpp new file mode 100644 index 00000000..b7e00629 --- /dev/null +++ b/src/ObjWriting/Game/IW4/Sound/SndCurveDumperIW4.cpp @@ -0,0 +1,34 @@ +#include "SndCurveDumperIW4.h" + +#include "Sound/SndCurveDumper.h" +#include "Sound/SoundCurveCommon.h" + +#include + +using namespace IW4; + +namespace sound_curve +{ + bool DumperIW4::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperIW4::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* sndCurve = asset->Asset(); + + const auto assetFile = context.OpenAssetFile(GetFileNameForAssetName(sndCurve->filename)); + + if (!assetFile) + return; + + SndCurveDumper dumper(*assetFile); + + const auto knotCount = std::min(static_cast(sndCurve->knotCount), std::extent_v); + dumper.Init(knotCount); + + for (auto i = 0u; i < knotCount; i++) + dumper.WriteKnot(sndCurve->knots[i][0], sndCurve->knots[i][1]); + } +} // namespace sound_curve diff --git a/src/ObjWriting/Game/IW4/Sound/SndCurveDumperIW4.h b/src/ObjWriting/Game/IW4/Sound/SndCurveDumperIW4.h new file mode 100644 index 00000000..241b7a79 --- /dev/null +++ b/src/ObjWriting/Game/IW4/Sound/SndCurveDumperIW4.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" + +namespace sound_curve +{ + class DumperIW4 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace sound_curve diff --git a/src/ObjWriting/Game/IW4/StringTable/StringTableDumperIW4.cpp b/src/ObjWriting/Game/IW4/StringTable/StringTableDumperIW4.cpp new file mode 100644 index 00000000..784164e2 --- /dev/null +++ b/src/ObjWriting/Game/IW4/StringTable/StringTableDumperIW4.cpp @@ -0,0 +1,42 @@ +#include "StringTableDumperIW4.h" + +#include "Csv/CsvStream.h" + +using namespace IW4; + +namespace string_table +{ + bool DumperIW4::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperIW4::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* stringTable = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name); + + if (!assetFile) + return; + + CsvOutputStream csv(*assetFile); + + for (auto row = 0; row < stringTable->rowCount; row++) + { + for (auto column = 0; column < stringTable->columnCount; column++) + { + const auto* cell = &stringTable->values[column + row * stringTable->columnCount]; + if (cell->string != nullptr) + { + csv.WriteColumn(cell->string); + } + else + { + csv.WriteColumn(""); + } + } + + csv.NextRow(); + } + } +} // namespace string_table diff --git a/src/ObjWriting/Game/IW4/StringTable/StringTableDumperIW4.h b/src/ObjWriting/Game/IW4/StringTable/StringTableDumperIW4.h new file mode 100644 index 00000000..93f1af2b --- /dev/null +++ b/src/ObjWriting/Game/IW4/StringTable/StringTableDumperIW4.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" + +namespace string_table +{ + class DumperIW4 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace string_table diff --git a/src/ObjWriting/Game/IW4/StructuredDataDef/StructuredDataDefDumperIW4.cpp b/src/ObjWriting/Game/IW4/StructuredDataDef/StructuredDataDefDumperIW4.cpp new file mode 100644 index 00000000..2e5cf317 --- /dev/null +++ b/src/ObjWriting/Game/IW4/StructuredDataDef/StructuredDataDefDumperIW4.cpp @@ -0,0 +1,208 @@ +#include "StructuredDataDefDumperIW4.h" + +#include "StructuredDataDef/StructuredDataDefDumper.h" + +#include +#include +#include + +using namespace IW4; +using namespace std::string_literals; + +namespace +{ + CommonStructuredDataType ConvertType(const CommonStructuredDataDef* def, const StructuredDataType in) + { + CommonStructuredDataType out; + + switch (in.type) + { + case DATA_INT: + out.m_category = CommonStructuredDataTypeCategory::INT; + break; + case DATA_BYTE: + out.m_category = CommonStructuredDataTypeCategory::BYTE; + break; + case DATA_BOOL: + out.m_category = CommonStructuredDataTypeCategory::BOOL; + break; + case DATA_FLOAT: + out.m_category = CommonStructuredDataTypeCategory::FLOAT; + break; + case DATA_SHORT: + out.m_category = CommonStructuredDataTypeCategory::SHORT; + break; + case DATA_STRING: + out.m_category = CommonStructuredDataTypeCategory::STRING; + out.m_info.string_length = in.u.stringDataLength; + break; + case DATA_ENUM: + assert(!def->m_enums.empty()); + out.m_category = CommonStructuredDataTypeCategory::ENUM; + out.m_info.type_index = std::max(std::min(static_cast(in.u.enumIndex), def->m_enums.size() - 1uz), 0uz); + break; + case DATA_STRUCT: + assert(!def->m_structs.empty()); + out.m_category = CommonStructuredDataTypeCategory::STRUCT; + out.m_info.type_index = std::max(std::min(static_cast(in.u.structIndex), def->m_structs.size() - 1uz), 0uz); + break; + case DATA_INDEXED_ARRAY: + assert(!def->m_indexed_arrays.empty()); + out.m_category = CommonStructuredDataTypeCategory::INDEXED_ARRAY; + out.m_info.type_index = std::max(std::min(static_cast(in.u.indexedArrayIndex), def->m_indexed_arrays.size() - 1uz), 0uz); + break; + case DATA_ENUM_ARRAY: + assert(!def->m_enumed_arrays.empty()); + out.m_category = CommonStructuredDataTypeCategory::ENUM_ARRAY; + out.m_info.type_index = std::max(std::min(static_cast(in.u.enumedArrayIndex), def->m_enumed_arrays.size() - 1uz), 0uz); + break; + case DATA_COUNT: + default: + assert(false); + break; + } + + return out; + } + + void ConvertEnum(CommonStructuredDataEnum* out, const StructuredDataEnum* in, const size_t enumIndex) + { + out->m_name = "ENUM_" + std::to_string(enumIndex); + + if (in->reservedEntryCount > 0 && in->reservedEntryCount != in->entryCount) + out->m_reserved_entry_count = std::max(in->reservedEntryCount, 0); + else + out->m_reserved_entry_count = -1; + + out->m_entries.resize(static_cast(std::max(in->entryCount, 0))); + for (auto i = 0u; i < out->m_entries.size(); i++) + { + auto& outEntry = out->m_entries[i]; + const auto& inEntry = in->entries[i]; + + outEntry.m_name = std::string(inEntry.string); + outEntry.m_value = inEntry.index; + } + + out->SortEntriesByOffset(); + } + + void ConvertStruct(const CommonStructuredDataDef* def, + const StructuredDataDef* gameDef, + CommonStructuredDataStruct* out, + const StructuredDataStruct* in, + const size_t structIndex) + { + if (gameDef->rootType.type == DATA_STRUCT && structIndex == static_cast(gameDef->rootType.u.structIndex)) + { + out->m_name = "root"; + out->m_size_in_byte = gameDef->size; + } + else + { + out->m_name = "STRUCT_" + std::to_string(structIndex); + out->m_size_in_byte = static_cast(std::max(in->size, 0)); + } + + out->m_bit_offset = in->bitOffset; + + out->m_properties.resize(static_cast(std::max(in->propertyCount, 0))); + for (auto i = 0u; i < out->m_properties.size(); i++) + { + auto& outProperty = out->m_properties[i]; + const auto& inProperty = in->properties[i]; + + outProperty.m_name = std::string(inProperty.name); + outProperty.m_type = ConvertType(def, inProperty.type); + + if (inProperty.type.type == DATA_BOOL) + outProperty.m_offset_in_bits = inProperty.offset; + else + outProperty.m_offset_in_bits = inProperty.offset * 8; + } + + out->SortPropertiesByOffset(); + } + + void ConvertIndexedArray(const CommonStructuredDataDef* def, CommonStructuredDataIndexedArray* out, const StructuredDataIndexedArray* in) + { + out->m_element_count = static_cast(std::max(in->arraySize, 0)); + out->m_element_size_in_bits = in->elementType.type == DATA_BOOL ? 1 : in->elementSize * 8; + out->m_array_type = ConvertType(def, in->elementType); + } + + void ConvertEnumedArray(const CommonStructuredDataDef* def, CommonStructuredDataEnumedArray* out, const StructuredDataEnumedArray* in) + { + assert(!def->m_enums.empty()); + out->m_element_size_in_bits = in->elementType.type == DATA_BOOL ? 1 : in->elementSize * 8; + out->m_array_type = ConvertType(def, in->elementType); + out->m_enum_index = std::max(std::min(static_cast(in->enumIndex), def->m_enums.size() - 1uz), 0uz); + + if (def->m_enums.empty()) + { + assert(false); + return; + } + + out->m_element_count = def->m_enums[out->m_enum_index]->ElementCount(); + } + + std::unique_ptr ConvertDef(const StructuredDataDef* in) + { + auto out = std::make_unique(); + + out->m_version = in->version; + out->m_checksum = in->formatChecksum; + out->m_size_in_byte = in->size; + + out->m_enums.resize(static_cast(std::max(in->enumCount, 0))); + out->m_structs.resize(static_cast(std::max(in->structCount, 0))); + out->m_indexed_arrays.resize(static_cast(std::max(in->indexedArrayCount, 0))); + out->m_enumed_arrays.resize(static_cast(std::max(in->enumedArrayCount, 0))); + + for (auto i = 0u; i < out->m_enums.size(); i++) + { + auto _enum = std::make_unique(); + ConvertEnum(_enum.get(), &in->enums[i], i); + out->m_enums[i] = std::move(_enum); + } + for (auto i = 0u; i < out->m_structs.size(); i++) + { + auto _struct = std::make_unique(); + ConvertStruct(out.get(), in, _struct.get(), &in->structs[i], i); + out->m_structs[i] = std::move(_struct); + } + for (auto i = 0u; i < out->m_indexed_arrays.size(); i++) + ConvertIndexedArray(out.get(), &out->m_indexed_arrays[i], &in->indexedArrays[i]); + for (auto i = 0u; i < out->m_enumed_arrays.size(); i++) + ConvertEnumedArray(out.get(), &out->m_enumed_arrays[i], &in->enumedArrays[i]); + + out->m_root_type = ConvertType(out.get(), in->rootType); + + return out; + } +} // namespace + +namespace structured_data_def +{ + bool DumperIW4::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperIW4::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* set = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name); + + if (!assetFile || set->defs == nullptr) + return; + + StructuredDataDefDumper dumper(*assetFile); + for (auto i = 0u; i < set->defCount; i++) + { + const auto def = ConvertDef(&set->defs[i]); + dumper.DumpDef(*def); + } + } +} // namespace structured_data_def diff --git a/src/ObjWriting/Game/IW4/StructuredDataDef/StructuredDataDefDumperIW4.h b/src/ObjWriting/Game/IW4/StructuredDataDef/StructuredDataDefDumperIW4.h new file mode 100644 index 00000000..e03d8c61 --- /dev/null +++ b/src/ObjWriting/Game/IW4/StructuredDataDef/StructuredDataDefDumperIW4.h @@ -0,0 +1,17 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" +#include "StructuredDataDef/CommonStructuredDataDef.h" + +#include + +namespace structured_data_def +{ + class DumperIW4 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace structured_data_def diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTechniqueSet.cpp b/src/ObjWriting/Game/IW4/Techset/TechsetDumperIW4.cpp similarity index 94% rename from src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTechniqueSet.cpp rename to src/ObjWriting/Game/IW4/Techset/TechsetDumperIW4.cpp index 101d323d..24ae8652 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperTechniqueSet.cpp +++ b/src/ObjWriting/Game/IW4/Techset/TechsetDumperIW4.cpp @@ -1,9 +1,10 @@ -#include "AssetDumperTechniqueSet.h" +#include "TechsetDumperIW4.h" #include "Dumping/AbstractTextDumper.h" #include "Game/IW4/TechsetConstantsIW4.h" #include "Pool/GlobalAssetPool.h" #include "Shader/D3D9ShaderAnalyser.h" +#include "Techset/TechsetCommon.h" #include #include @@ -531,48 +532,37 @@ namespace IW4 }; } // namespace IW4 -std::string AssetDumperTechniqueSet::GetTechniqueFileName(const MaterialTechnique* technique) +namespace techset { - std::ostringstream ss; - ss << "techniques/" << technique->name << ".tech"; - return ss.str(); -} - -std::string AssetDumperTechniqueSet::GetTechsetFileName(const MaterialTechniqueSet* techset) -{ - std::ostringstream ss; - ss << "techsets/" << techset->name << ".techset"; - return ss.str(); -} - -bool AssetDumperTechniqueSet::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperTechniqueSet::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* techset = asset->Asset(); - - const auto techsetFile = context.OpenAssetFile(GetTechsetFileName(techset)); - - if (techsetFile) + bool DumperIW4::ShouldDump(XAssetInfo* asset) { - TechsetFileWriter writer(*techsetFile); - writer.DumpTechset(techset); + return true; } - auto* techniqueState = context.GetZoneAssetDumperState(); - for (const auto* technique : techset->techniques) + void DumperIW4::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) { - if (technique && techniqueState->ShouldDumpTechnique(technique)) + const auto* techset = asset->Asset(); + + const auto techsetFile = context.OpenAssetFile(GetFileNameForTechsetName(techset->name)); + + if (techsetFile) { - const auto techniqueFile = context.OpenAssetFile(GetTechniqueFileName(technique)); - if (techniqueFile) + TechsetFileWriter writer(*techsetFile); + writer.DumpTechset(techset); + } + + auto* techniqueState = context.GetZoneAssetDumperState(); + for (const auto* technique : techset->techniques) + { + if (technique && techniqueState->ShouldDumpTechnique(technique)) { - TechniqueFileWriter writer(*techniqueFile); - writer.DumpTechnique(technique); + const auto techniqueFile = context.OpenAssetFile(GetFileNameForTechniqueName(technique->name)); + if (techniqueFile) + { + TechniqueFileWriter writer(*techniqueFile); + writer.DumpTechnique(technique); + } } } } -} +} // namespace techset diff --git a/src/ObjWriting/Game/IW4/Techset/TechsetDumperIW4.h b/src/ObjWriting/Game/IW4/Techset/TechsetDumperIW4.h new file mode 100644 index 00000000..8115f527 --- /dev/null +++ b/src/ObjWriting/Game/IW4/Techset/TechsetDumperIW4.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" + +namespace techset +{ + class DumperIW4 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace techset diff --git a/src/ObjWriting/Game/IW4/Tracer/TracerDumperIW4.cpp b/src/ObjWriting/Game/IW4/Tracer/TracerDumperIW4.cpp new file mode 100644 index 00000000..2e3635f8 --- /dev/null +++ b/src/ObjWriting/Game/IW4/Tracer/TracerDumperIW4.cpp @@ -0,0 +1,83 @@ +#include "TracerDumperIW4.h" + +#include "Game/IW4/CommonIW4.h" +#include "Game/IW4/InfoString/InfoStringFromStructConverter.h" +#include "Game/IW4/ObjConstantsIW4.h" +#include "Game/IW4/Tracer/TracerFields.h" +#include "Tracer/TracerCommon.h" + +#include +#include +#include + +using namespace IW4; + +namespace +{ + class InfoStringFromTracerConverter final : public InfoStringFromStructConverter + { + protected: + void FillFromExtensionField(const cspField_t& field) override + { + assert(false); + } + + public: + InfoStringFromTracerConverter(const TracerDef* structure, + const cspField_t* fields, + const size_t fieldCount, + std::function scriptStringValueCallback) + : InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback)) + { + } + }; + + InfoString CreateInfoString(XAssetInfo* asset) + { + InfoStringFromTracerConverter converter(asset->Asset(), + tracer_fields, + std::extent_v, + [asset](const scr_string_t scrStr) -> std::string + { + assert(scrStr < asset->m_zone->m_script_strings.Count()); + if (scrStr >= asset->m_zone->m_script_strings.Count()) + return ""; + + return asset->m_zone->m_script_strings[scrStr]; + }); + + return converter.Convert(); + } +} // namespace + +namespace tracer +{ + bool DumperIW4::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperIW4::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + // Only dump raw when no gdt available + if (context.m_gdt) + { + const auto infoString = CreateInfoString(asset); + GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_TRACER); + infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_TRACER, gdtEntry); + context.m_gdt->WriteEntry(gdtEntry); + } + else + { + const auto assetFile = context.OpenAssetFile(GetFileNameForAssetName(asset->m_name)); + + if (!assetFile) + return; + + auto& stream = *assetFile; + const auto infoString = CreateInfoString(asset); + const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_TRACER); + stream.write(stringValue.c_str(), stringValue.size()); + } + } +} // namespace tracer diff --git a/src/ObjWriting/Game/IW4/Tracer/TracerDumperIW4.h b/src/ObjWriting/Game/IW4/Tracer/TracerDumperIW4.h new file mode 100644 index 00000000..d13a9f60 --- /dev/null +++ b/src/ObjWriting/Game/IW4/Tracer/TracerDumperIW4.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" +#include "InfoString/InfoString.h" + +namespace tracer +{ + class DumperIW4 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace tracer diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVehicle.cpp b/src/ObjWriting/Game/IW4/Vehicle/VehicleDumperIW4.cpp similarity index 54% rename from src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVehicle.cpp rename to src/ObjWriting/Game/IW4/Vehicle/VehicleDumperIW4.cpp index 56ab8de7..9110b559 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperVehicle.cpp +++ b/src/ObjWriting/Game/IW4/Vehicle/VehicleDumperIW4.cpp @@ -1,10 +1,11 @@ -#include "AssetDumperVehicle.h" +#include "VehicleDumperIW4.h" #include "Game/IW4/CommonIW4.h" #include "Game/IW4/InfoString/EnumStrings.h" #include "Game/IW4/InfoString/InfoStringFromStructConverter.h" #include "Game/IW4/ObjConstantsIW4.h" #include "Game/IW4/Vehicle/VehicleFields.h" +#include "Vehicle/VehicleCommon.h" #include #include @@ -12,7 +13,7 @@ using namespace IW4; -namespace IW4 +namespace { class InfoStringFromVehicleConverter final : public InfoStringFromStructConverter { @@ -71,50 +72,53 @@ namespace IW4 { } }; -} // namespace IW4 -InfoString AssetDumperVehicle::CreateInfoString(XAssetInfo* asset) -{ - InfoStringFromVehicleConverter converter(asset->Asset(), - vehicle_fields, - std::extent_v, - [asset](const scr_string_t scrStr) -> std::string - { - assert(scrStr < asset->m_zone->m_script_strings.Count()); - if (scrStr >= asset->m_zone->m_script_strings.Count()) - return ""; - - return asset->m_zone->m_script_strings[scrStr]; - }); - - return converter.Convert(); -} - -bool AssetDumperVehicle::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperVehicle::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - // Only dump raw when no gdt available - if (context.m_gdt) + InfoString CreateInfoString(XAssetInfo* asset) { - const auto infoString = CreateInfoString(asset); - GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_VEHICLE); - infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_VEHICLE, gdtEntry); - context.m_gdt->WriteEntry(gdtEntry); + InfoStringFromVehicleConverter converter(asset->Asset(), + vehicle_fields, + std::extent_v, + [asset](const scr_string_t scrStr) -> std::string + { + assert(scrStr < asset->m_zone->m_script_strings.Count()); + if (scrStr >= asset->m_zone->m_script_strings.Count()) + return ""; + + return asset->m_zone->m_script_strings[scrStr]; + }); + + return converter.Convert(); } - else +} // namespace + +namespace vehicle +{ + bool DumperIW4::ShouldDump(XAssetInfo* asset) { - const auto assetFile = context.OpenAssetFile("vehicles/" + asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - const auto infoString = CreateInfoString(asset); - const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_VEHICLE); - stream.write(stringValue.c_str(), stringValue.size()); + return true; } -} + + void DumperIW4::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + // Only dump raw when no gdt available + if (context.m_gdt) + { + const auto infoString = CreateInfoString(asset); + GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_VEHICLE); + infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_VEHICLE, gdtEntry); + context.m_gdt->WriteEntry(gdtEntry); + } + else + { + const auto assetFile = context.OpenAssetFile(GetFileNameForAssetName(asset->m_name)); + + if (!assetFile) + return; + + auto& stream = *assetFile; + const auto infoString = CreateInfoString(asset); + const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_VEHICLE); + stream.write(stringValue.c_str(), stringValue.size()); + } + } +} // namespace vehicle diff --git a/src/ObjWriting/Game/IW4/Vehicle/VehicleDumperIW4.h b/src/ObjWriting/Game/IW4/Vehicle/VehicleDumperIW4.h new file mode 100644 index 00000000..5afae348 --- /dev/null +++ b/src/ObjWriting/Game/IW4/Vehicle/VehicleDumperIW4.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" +#include "InfoString/InfoString.h" + +namespace vehicle +{ + class DumperIW4 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace vehicle diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.cpp b/src/ObjWriting/Game/IW4/Weapon/WeaponDumperIW4.cpp similarity index 50% rename from src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.cpp rename to src/ObjWriting/Game/IW4/Weapon/WeaponDumperIW4.cpp index 0d388e3c..1ebabfe7 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.cpp +++ b/src/ObjWriting/Game/IW4/Weapon/WeaponDumperIW4.cpp @@ -1,4 +1,4 @@ -#include "AssetDumperWeapon.h" +#include "WeaponDumperIW4.h" #include "Game/IW4/CommonIW4.h" #include "Game/IW4/InfoString/EnumStrings.h" @@ -6,6 +6,7 @@ #include "Game/IW4/ObjConstantsIW4.h" #include "Game/IW4/Weapon/WeaponFields.h" #include "Weapon/AccuracyGraphWriter.h" +#include "Weapon/WeaponCommon.h" #include #include @@ -14,7 +15,7 @@ using namespace IW4; -namespace IW4 +namespace { class InfoStringFromWeaponConverter final : public InfoStringFromStructConverter { @@ -237,195 +238,201 @@ namespace IW4 return graph; } -} // namespace IW4 -void AssetDumperWeapon::CopyToFullDef(const WeaponCompleteDef* weapon, WeaponFullDef* fullDef) -{ - fullDef->weapCompleteDef = *weapon; - - if (weapon->weapDef) + void CopyToFullDef(const WeaponCompleteDef* weapon, WeaponFullDef* fullDef) { - fullDef->weapDef = *weapon->weapDef; - fullDef->weapCompleteDef.weapDef = &fullDef->weapDef; + fullDef->weapCompleteDef = *weapon; + + if (weapon->weapDef) + { + fullDef->weapDef = *weapon->weapDef; + fullDef->weapCompleteDef.weapDef = &fullDef->weapDef; + } + + if (weapon->hideTags) + { + assert(sizeof(WeaponFullDef::hideTags) >= sizeof(scr_string_t) * std::extent_v); + memcpy(fullDef->hideTags, weapon->hideTags, sizeof(scr_string_t) * std::extent_v); + fullDef->weapCompleteDef.hideTags = fullDef->hideTags; + } + + if (weapon->szXAnims) + { + assert(sizeof(WeaponFullDef::szXAnims) >= sizeof(void*) * NUM_WEAP_ANIMS); + memcpy(fullDef->szXAnims, weapon->szXAnims, sizeof(void*) * NUM_WEAP_ANIMS); + fullDef->weapCompleteDef.szXAnims = fullDef->szXAnims; + } + + if (fullDef->weapDef.gunXModel) + { + assert(sizeof(WeaponFullDef::gunXModel) >= sizeof(void*) * std::extent_v); + memcpy(fullDef->gunXModel, fullDef->weapDef.gunXModel, sizeof(void*) * std::extent_v); + fullDef->weapDef.gunXModel = fullDef->gunXModel; + } + + if (fullDef->weapDef.szXAnimsRightHanded) + { + assert(sizeof(WeaponFullDef::szXAnimsRightHanded) >= sizeof(void*) * NUM_WEAP_ANIMS); + memcpy(fullDef->szXAnimsRightHanded, fullDef->weapDef.szXAnimsRightHanded, sizeof(void*) * NUM_WEAP_ANIMS); + fullDef->weapDef.szXAnimsRightHanded = fullDef->szXAnimsRightHanded; + } + + if (fullDef->weapDef.szXAnimsLeftHanded) + { + assert(sizeof(WeaponFullDef::szXAnimsLeftHanded) >= sizeof(void*) * NUM_WEAP_ANIMS); + memcpy(fullDef->szXAnimsLeftHanded, fullDef->weapDef.szXAnimsLeftHanded, sizeof(void*) * NUM_WEAP_ANIMS); + fullDef->weapDef.szXAnimsLeftHanded = fullDef->szXAnimsLeftHanded; + } + + if (fullDef->weapDef.notetrackSoundMapKeys) + { + assert(sizeof(WeaponFullDef::notetrackSoundMapKeys) >= sizeof(scr_string_t) * std::extent_v); + memcpy(fullDef->notetrackSoundMapKeys, + fullDef->weapDef.notetrackSoundMapKeys, + sizeof(scr_string_t) * std::extent_v); + fullDef->weapDef.notetrackSoundMapKeys = fullDef->notetrackSoundMapKeys; + } + + if (fullDef->weapDef.notetrackSoundMapValues) + { + assert(sizeof(WeaponFullDef::notetrackSoundMapValues) >= sizeof(scr_string_t) * std::extent_v); + memcpy(fullDef->notetrackSoundMapValues, + fullDef->weapDef.notetrackSoundMapValues, + sizeof(scr_string_t) * std::extent_v); + fullDef->weapDef.notetrackSoundMapValues = fullDef->notetrackSoundMapValues; + } + + if (fullDef->weapDef.notetrackRumbleMapKeys) + { + assert(sizeof(WeaponFullDef::notetrackRumbleMapKeys) >= sizeof(scr_string_t) * std::extent_v); + memcpy(fullDef->notetrackRumbleMapKeys, + fullDef->weapDef.notetrackRumbleMapKeys, + sizeof(scr_string_t) * std::extent_v); + fullDef->weapDef.notetrackRumbleMapKeys = fullDef->notetrackRumbleMapKeys; + } + + if (fullDef->weapDef.notetrackRumbleMapValues) + { + assert(sizeof(WeaponFullDef::notetrackRumbleMapValues) >= sizeof(scr_string_t) * std::extent_v); + memcpy(fullDef->notetrackRumbleMapValues, + fullDef->weapDef.notetrackRumbleMapValues, + sizeof(scr_string_t) * std::extent_v); + fullDef->weapDef.notetrackRumbleMapValues = fullDef->notetrackRumbleMapValues; + } + + if (fullDef->weapDef.worldModel) + { + assert(sizeof(WeaponFullDef::worldModel) >= sizeof(void*) * std::extent_v); + memcpy(fullDef->worldModel, fullDef->weapDef.worldModel, sizeof(void*) * std::extent_v); + fullDef->weapDef.worldModel = fullDef->worldModel; + } + + if (fullDef->weapDef.parallelBounce) + { + assert(sizeof(WeaponFullDef::parallelBounce) >= sizeof(float) * std::extent_v); + memcpy(fullDef->parallelBounce, fullDef->weapDef.parallelBounce, sizeof(float) * std::extent_v); + fullDef->weapDef.parallelBounce = fullDef->parallelBounce; + } + + if (fullDef->weapDef.perpendicularBounce) + { + assert(sizeof(WeaponFullDef::perpendicularBounce) >= sizeof(float) * std::extent_v); + memcpy(fullDef->perpendicularBounce, + fullDef->weapDef.perpendicularBounce, + sizeof(float) * std::extent_v); + fullDef->weapDef.perpendicularBounce = fullDef->perpendicularBounce; + } + + if (fullDef->weapDef.locationDamageMultipliers) + { + assert(sizeof(WeaponFullDef::locationDamageMultipliers) >= sizeof(float) * std::extent_v); + memcpy(fullDef->locationDamageMultipliers, + fullDef->weapDef.locationDamageMultipliers, + sizeof(float) * std::extent_v); + fullDef->weapDef.locationDamageMultipliers = fullDef->locationDamageMultipliers; + } } - if (weapon->hideTags) + InfoString CreateInfoString(XAssetInfo* asset) { - assert(sizeof(WeaponFullDef::hideTags) >= sizeof(scr_string_t) * std::extent_v); - memcpy(fullDef->hideTags, weapon->hideTags, sizeof(scr_string_t) * std::extent_v); - fullDef->weapCompleteDef.hideTags = fullDef->hideTags; + const auto fullDef = std::make_unique(); + memset(fullDef.get(), 0, sizeof(WeaponFullDef)); + CopyToFullDef(asset->Asset(), fullDef.get()); + + InfoStringFromWeaponConverter converter(fullDef.get(), + weapon_fields, + std::extent_v, + [asset](const scr_string_t scrStr) -> std::string + { + assert(scrStr < asset->m_zone->m_script_strings.Count()); + if (scrStr >= asset->m_zone->m_script_strings.Count()) + return ""; + + return asset->m_zone->m_script_strings[scrStr]; + }); + + return converter.Convert(); } - if (weapon->szXAnims) + void DumpAccuracyGraphs(AssetDumpingContext& context, XAssetInfo* asset) { - assert(sizeof(WeaponFullDef::szXAnims) >= sizeof(void*) * NUM_WEAP_ANIMS); - memcpy(fullDef->szXAnims, weapon->szXAnims, sizeof(void*) * NUM_WEAP_ANIMS); - fullDef->weapCompleteDef.szXAnims = fullDef->szXAnims; - } + auto* accuracyGraphWriter = context.GetZoneAssetDumperState(); + const auto weapon = asset->Asset(); + const auto* weapDef = weapon->weapDef; - if (fullDef->weapDef.gunXModel) - { - assert(sizeof(WeaponFullDef::gunXModel) >= sizeof(void*) * std::extent_v); - memcpy(fullDef->gunXModel, fullDef->weapDef.gunXModel, sizeof(void*) * std::extent_v); - fullDef->weapDef.gunXModel = fullDef->gunXModel; - } - - if (fullDef->weapDef.szXAnimsRightHanded) - { - assert(sizeof(WeaponFullDef::szXAnimsRightHanded) >= sizeof(void*) * NUM_WEAP_ANIMS); - memcpy(fullDef->szXAnimsRightHanded, fullDef->weapDef.szXAnimsRightHanded, sizeof(void*) * NUM_WEAP_ANIMS); - fullDef->weapDef.szXAnimsRightHanded = fullDef->szXAnimsRightHanded; - } - - if (fullDef->weapDef.szXAnimsLeftHanded) - { - assert(sizeof(WeaponFullDef::szXAnimsLeftHanded) >= sizeof(void*) * NUM_WEAP_ANIMS); - memcpy(fullDef->szXAnimsLeftHanded, fullDef->weapDef.szXAnimsLeftHanded, sizeof(void*) * NUM_WEAP_ANIMS); - fullDef->weapDef.szXAnimsLeftHanded = fullDef->szXAnimsLeftHanded; - } - - if (fullDef->weapDef.notetrackSoundMapKeys) - { - assert(sizeof(WeaponFullDef::notetrackSoundMapKeys) >= sizeof(scr_string_t) * std::extent_v); - memcpy(fullDef->notetrackSoundMapKeys, - fullDef->weapDef.notetrackSoundMapKeys, - sizeof(scr_string_t) * std::extent_v); - fullDef->weapDef.notetrackSoundMapKeys = fullDef->notetrackSoundMapKeys; - } - - if (fullDef->weapDef.notetrackSoundMapValues) - { - assert(sizeof(WeaponFullDef::notetrackSoundMapValues) >= sizeof(scr_string_t) * std::extent_v); - memcpy(fullDef->notetrackSoundMapValues, - fullDef->weapDef.notetrackSoundMapValues, - sizeof(scr_string_t) * std::extent_v); - fullDef->weapDef.notetrackSoundMapValues = fullDef->notetrackSoundMapValues; - } - - if (fullDef->weapDef.notetrackRumbleMapKeys) - { - assert(sizeof(WeaponFullDef::notetrackRumbleMapKeys) >= sizeof(scr_string_t) * std::extent_v); - memcpy(fullDef->notetrackRumbleMapKeys, - fullDef->weapDef.notetrackRumbleMapKeys, - sizeof(scr_string_t) * std::extent_v); - fullDef->weapDef.notetrackRumbleMapKeys = fullDef->notetrackRumbleMapKeys; - } - - if (fullDef->weapDef.notetrackRumbleMapValues) - { - assert(sizeof(WeaponFullDef::notetrackRumbleMapValues) >= sizeof(scr_string_t) * std::extent_v); - memcpy(fullDef->notetrackRumbleMapValues, - fullDef->weapDef.notetrackRumbleMapValues, - sizeof(scr_string_t) * std::extent_v); - fullDef->weapDef.notetrackRumbleMapValues = fullDef->notetrackRumbleMapValues; - } - - if (fullDef->weapDef.worldModel) - { - assert(sizeof(WeaponFullDef::worldModel) >= sizeof(void*) * std::extent_v); - memcpy(fullDef->worldModel, fullDef->weapDef.worldModel, sizeof(void*) * std::extent_v); - fullDef->weapDef.worldModel = fullDef->worldModel; - } - - if (fullDef->weapDef.parallelBounce) - { - assert(sizeof(WeaponFullDef::parallelBounce) >= sizeof(float) * std::extent_v); - memcpy(fullDef->parallelBounce, fullDef->weapDef.parallelBounce, sizeof(float) * std::extent_v); - fullDef->weapDef.parallelBounce = fullDef->parallelBounce; - } - - if (fullDef->weapDef.perpendicularBounce) - { - assert(sizeof(WeaponFullDef::perpendicularBounce) >= sizeof(float) * std::extent_v); - memcpy(fullDef->perpendicularBounce, fullDef->weapDef.perpendicularBounce, sizeof(float) * std::extent_v); - fullDef->weapDef.perpendicularBounce = fullDef->perpendicularBounce; - } - - if (fullDef->weapDef.locationDamageMultipliers) - { - assert(sizeof(WeaponFullDef::locationDamageMultipliers) >= sizeof(float) * std::extent_v); - memcpy(fullDef->locationDamageMultipliers, - fullDef->weapDef.locationDamageMultipliers, - sizeof(float) * std::extent_v); - fullDef->weapDef.locationDamageMultipliers = fullDef->locationDamageMultipliers; - } -} - -InfoString AssetDumperWeapon::CreateInfoString(XAssetInfo* asset) -{ - const auto fullDef = std::make_unique(); - memset(fullDef.get(), 0, sizeof(WeaponFullDef)); - CopyToFullDef(asset->Asset(), fullDef.get()); - - InfoStringFromWeaponConverter converter(fullDef.get(), - weapon_fields, - std::extent_v, - [asset](const scr_string_t scrStr) -> std::string - { - assert(scrStr < asset->m_zone->m_script_strings.Count()); - if (scrStr >= asset->m_zone->m_script_strings.Count()) - return ""; - - return asset->m_zone->m_script_strings[scrStr]; - }); - - return converter.Convert(); -} - -void AssetDumperWeapon::DumpAccuracyGraphs(AssetDumpingContext& context, XAssetInfo* asset) -{ - auto* accuracyGraphWriter = context.GetZoneAssetDumperState(); - const auto weapon = asset->Asset(); - const auto* weapDef = weapon->weapDef; - - if (!weapDef) - return; - - if (weapDef->aiVsAiAccuracyGraphName && weapDef->originalAiVsAiAccuracyGraphKnots - && accuracyGraphWriter->ShouldDumpAiVsAiGraph(weapDef->aiVsAiAccuracyGraphName)) - { - AccuracyGraphWriter::DumpAiVsAiGraph( - context, - ConvertAccuracyGraph(weapDef->aiVsAiAccuracyGraphName, weapDef->originalAiVsAiAccuracyGraphKnots, weapDef->originalAiVsAiAccuracyGraphKnotCount)); - } - - if (weapDef->aiVsPlayerAccuracyGraphName && weapDef->originalAiVsPlayerAccuracyGraphKnots - && accuracyGraphWriter->ShouldDumpAiVsPlayerGraph(weapDef->aiVsPlayerAccuracyGraphName)) - { - AccuracyGraphWriter::DumpAiVsPlayerGraph(context, - ConvertAccuracyGraph(weapDef->aiVsPlayerAccuracyGraphName, - weapDef->originalAiVsPlayerAccuracyGraphKnots, - weapDef->originalAiVsPlayerAccuracyGraphKnotCount)); - } -} - -bool AssetDumperWeapon::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperWeapon::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - // Only dump raw when no gdt available - if (context.m_gdt) - { - const auto infoString = CreateInfoString(asset); - GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_WEAPON); - infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_WEAPON, gdtEntry); - context.m_gdt->WriteEntry(gdtEntry); - } - else - { - const auto assetFile = context.OpenAssetFile("weapons/" + asset->m_name); - - if (!assetFile) + if (!weapDef) return; - auto& stream = *assetFile; - const auto infoString = CreateInfoString(asset); - const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_WEAPON); - stream.write(stringValue.c_str(), stringValue.size()); + if (weapDef->aiVsAiAccuracyGraphName && weapDef->originalAiVsAiAccuracyGraphKnots + && accuracyGraphWriter->ShouldDumpAiVsAiGraph(weapDef->aiVsAiAccuracyGraphName)) + { + AccuracyGraphWriter::DumpAiVsAiGraph(context, + ConvertAccuracyGraph(weapDef->aiVsAiAccuracyGraphName, + weapDef->originalAiVsAiAccuracyGraphKnots, + weapDef->originalAiVsAiAccuracyGraphKnotCount)); + } + + if (weapDef->aiVsPlayerAccuracyGraphName && weapDef->originalAiVsPlayerAccuracyGraphKnots + && accuracyGraphWriter->ShouldDumpAiVsPlayerGraph(weapDef->aiVsPlayerAccuracyGraphName)) + { + AccuracyGraphWriter::DumpAiVsPlayerGraph(context, + ConvertAccuracyGraph(weapDef->aiVsPlayerAccuracyGraphName, + weapDef->originalAiVsPlayerAccuracyGraphKnots, + weapDef->originalAiVsPlayerAccuracyGraphKnotCount)); + } + } +} // namespace + +namespace weapon +{ + bool DumperIW4::ShouldDump(XAssetInfo* asset) + { + return true; } - DumpAccuracyGraphs(context, asset); -} + void DumperIW4::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + // Only dump raw when no gdt available + if (context.m_gdt) + { + const auto infoString = CreateInfoString(asset); + GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_WEAPON); + infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_WEAPON, gdtEntry); + context.m_gdt->WriteEntry(gdtEntry); + } + else + { + const auto assetFile = context.OpenAssetFile(GetFileNameForAssetName(asset->m_name)); + + if (!assetFile) + return; + + auto& stream = *assetFile; + const auto infoString = CreateInfoString(asset); + const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_WEAPON); + stream.write(stringValue.c_str(), stringValue.size()); + } + + DumpAccuracyGraphs(context, asset); + } +} // namespace weapon diff --git a/src/ObjWriting/Game/IW4/Weapon/WeaponDumperIW4.h b/src/ObjWriting/Game/IW4/Weapon/WeaponDumperIW4.h new file mode 100644 index 00000000..d6935e77 --- /dev/null +++ b/src/ObjWriting/Game/IW4/Weapon/WeaponDumperIW4.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW4/IW4.h" +#include "InfoString/InfoString.h" + +namespace weapon +{ + class DumperIW4 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace weapon diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperAddonMapEnts.cpp b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperAddonMapEnts.cpp deleted file mode 100644 index 547881cf..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperAddonMapEnts.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#define NOMINMAX -#include "AssetDumperAddonMapEnts.h" - -#include - -using namespace IW5; - -bool AssetDumperAddonMapEnts::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperAddonMapEnts::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* addonMapEnts = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - stream.write(addonMapEnts->entityString, std::max(addonMapEnts->numEntityChars - 1, 0)); -} diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperAddonMapEnts.h b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperAddonMapEnts.h deleted file mode 100644 index 9e5ec39d..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperAddonMapEnts.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW5/IW5.h" - -namespace IW5 -{ - class AssetDumperAddonMapEnts final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW5 diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperGfxImage.h b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperGfxImage.h deleted file mode 100644 index fac3f66b..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperGfxImage.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW5/IW5.h" -#include "Image/IImageWriter.h" - -#include - -namespace IW5 -{ - class AssetDumperGfxImage final : public AbstractAssetDumper - { - std::unique_ptr m_writer; - - [[nodiscard]] std::string GetAssetFileName(const XAssetInfo& asset) const; - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - - public: - AssetDumperGfxImage(); - }; -} // namespace IW5 diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLeaderboardDef.cpp b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLeaderboardDef.cpp deleted file mode 100644 index 9b1804f2..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLeaderboardDef.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "AssetDumperLeaderboardDef.h" - -#include "Game/IW5/Leaderboard/JsonLeaderboardDefWriter.h" - -#include -#include - -using namespace IW5; - -bool AssetDumperLeaderboardDef::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperLeaderboardDef::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto assetName = asset->m_name; - const auto assetFile = context.OpenAssetFile(std::format("leaderboards/{}.json", assetName)); - - if (!assetFile) - return; - - DumpLeaderboardDefAsJson(*assetFile, asset->Asset()); -} diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLeaderboardDef.h b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLeaderboardDef.h deleted file mode 100644 index 934ad940..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLeaderboardDef.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW5/IW5.h" - -namespace IW5 -{ - class AssetDumperLeaderboardDef final : public AbstractAssetDumper - { - protected: - _NODISCARD bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW5 diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLoadedSound.cpp b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLoadedSound.cpp deleted file mode 100644 index 7cb254e2..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLoadedSound.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "AssetDumperLoadedSound.h" - -#include "Sound/WavTypes.h" -#include "Sound/WavWriter.h" - -#include - -using namespace IW5; - -bool AssetDumperLoadedSound::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperLoadedSound::DumpWavPcm(const LoadedSound* asset, std::ostream& stream) -{ - const WavWriter writer(stream); - - const WavMetaData metaData{.channelCount = static_cast(asset->sound.info.channels), - .samplesPerSec = static_cast(asset->sound.info.rate), - .bitsPerSample = static_cast(asset->sound.info.bits)}; - - writer.WritePcmHeader(metaData, asset->sound.info.data_len); - writer.WritePcmData(asset->sound.data, asset->sound.info.data_len); -} - -void AssetDumperLoadedSound::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* loadedSound = asset->Asset(); - const auto assetFile = context.OpenAssetFile(std::format("sound/{}", asset->m_name)); - - if (!assetFile) - return; - - auto& stream = *assetFile; - switch (static_cast(loadedSound->sound.info.format)) - { - case WavFormat::PCM: - DumpWavPcm(loadedSound, stream); - break; - - default: - std::cerr << std::format("Unknown format {} for loaded sound: {}\n", loadedSound->sound.info.format, loadedSound->name); - break; - } -} diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLoadedSound.h b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLoadedSound.h deleted file mode 100644 index 4f575072..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLoadedSound.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW5/IW5.h" - -namespace IW5 -{ - class AssetDumperLoadedSound final : public AbstractAssetDumper - { - static void DumpWavPcm(const LoadedSound* asset, std::ostream& stream); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW5 diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLocalizeEntry.cpp b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLocalizeEntry.cpp deleted file mode 100644 index 600e41b8..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLocalizeEntry.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "AssetDumperLocalizeEntry.h" - -#include "Dumping/Localize/StringFileDumper.h" -#include "Localize/LocalizeCommon.h" - -#include -#include - -using namespace IW5; - -void AssetDumperLocalizeEntry::DumpPool(AssetDumpingContext& context, AssetPool* pool) -{ - if (pool->m_asset_lookup.empty()) - return; - - const auto language = LocalizeCommon::GetNameOfLanguage(context.m_zone.m_language); - const auto assetFile = context.OpenAssetFile(std::format("{}/localizedstrings/{}.str", language, context.m_zone.m_name)); - - if (assetFile) - { - StringFileDumper stringFileDumper(context.m_zone, *assetFile); - - stringFileDumper.SetLanguageName(language); - - // Magic string. Original string files do have this config file. The purpose of the config file is unknown though. - stringFileDumper.SetConfigFile(R"(C:/trees/cod3/cod3/bin/StringEd.cfg)"); - - stringFileDumper.SetNotes(""); - - for (auto* localizeEntry : *pool) - { - stringFileDumper.WriteLocalizeEntry(localizeEntry->m_name, localizeEntry->Asset()->value); - } - - stringFileDumper.Finalize(); - } - else - { - std::cerr << std::format("Could not create string file for dumping localized strings of zone '{}'\n", context.m_zone.m_name); - } -} diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLocalizeEntry.h b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLocalizeEntry.h deleted file mode 100644 index 151dcd73..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLocalizeEntry.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW5/IW5.h" - -namespace IW5 -{ - class AssetDumperLocalizeEntry final : public IAssetDumper - { - public: - void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; - }; -} // namespace IW5 diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperMenuDef.cpp b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperMenuDef.cpp deleted file mode 100644 index b14b5dbe..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperMenuDef.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include "AssetDumperMenuDef.h" - -#include "Game/IW5/GameAssetPoolIW5.h" -#include "Game/IW5/Menu/MenuDumperIW5.h" -#include "Menu/AbstractMenuDumper.h" -#include "ObjWriting.h" - -#include -#include - -namespace fs = std::filesystem; - -using namespace IW5; - -const MenuList* AssetDumperMenuDef::GetParentMenuList(XAssetInfo* asset) -{ - const auto* menu = asset->Asset(); - const auto* gameAssetPool = dynamic_cast(asset->m_zone->m_pools.get()); - for (const auto* menuList : *gameAssetPool->m_menu_list) - { - const auto* menuListAsset = menuList->Asset(); - - for (auto menuIndex = 0; menuIndex < menuListAsset->menuCount; menuIndex++) - { - if (menuListAsset->menus[menuIndex] == menu) - return menuListAsset; - } - } - - return nullptr; -} - -std::string AssetDumperMenuDef::GetPathForMenu(XAssetInfo* asset) -{ - const auto* list = GetParentMenuList(asset); - - if (!list) - return "ui_mp/" + std::string(asset->Asset()->window.name) + ".menu"; - - const fs::path p(list->name); - std::string parentPath; - if (p.has_parent_path()) - parentPath = p.parent_path().string() + "/"; - - return parentPath + std::string(asset->Asset()->window.name) + ".menu"; -} - -bool AssetDumperMenuDef::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperMenuDef::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* menu = asset->Asset(); - const auto menuFilePath = GetPathForMenu(asset); - - if (ObjWriting::ShouldHandleAssetType(ASSET_TYPE_MENULIST)) - { - // Don't dump menu file separately if the name matches the menu list - const auto* menuListParent = GetParentMenuList(asset); - if (menuListParent && menuFilePath == menuListParent->name) - return; - } - - const auto assetFile = context.OpenAssetFile(menuFilePath); - - if (!assetFile) - return; - - MenuDumper menuDumper(*assetFile); - - menuDumper.Start(); - menuDumper.WriteMenu(menu); - menuDumper.End(); -} diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperMenuDef.h b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperMenuDef.h deleted file mode 100644 index 696da199..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperMenuDef.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW5/IW5.h" - -namespace IW5 -{ - class AssetDumperMenuDef final : public AbstractAssetDumper - { - static const MenuList* GetParentMenuList(XAssetInfo* asset); - static std::string GetPathForMenu(XAssetInfo* asset); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW5 diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperMenuList.cpp b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperMenuList.cpp deleted file mode 100644 index c3b9bb44..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperMenuList.cpp +++ /dev/null @@ -1,128 +0,0 @@ -#include "AssetDumperMenuList.h" - -#include "Game/IW5/Menu/MenuDumperIW5.h" -#include "Menu/AbstractMenuDumper.h" -#include "ObjWriting.h" - -#include -#include -#include -#include - -namespace fs = std::filesystem; - -using namespace IW5; - -std::vector AssetDumperMenuList::GetAllUniqueExpressionSupportingData(const MenuList* menuList) -{ - std::vector result; - std::set alreadyAddedSupportingData; - - if (menuList->menus == nullptr) - return result; - - for (auto i = 0; i < menuList->menuCount; i++) - { - if (menuList->menus[i] == nullptr) - continue; - - const auto* menu = menuList->menus[i]; - - if (menu->data == nullptr || menu->data->expressionData == nullptr) - continue; - - if (alreadyAddedSupportingData.find(menu->data->expressionData) == alreadyAddedSupportingData.end()) - { - result.push_back(menu->data->expressionData); - alreadyAddedSupportingData.emplace(menu->data->expressionData); - } - } - - return result; -} - -void AssetDumperMenuList::DumpFunctions(MenuDumper& menuDumper, const MenuList* menuList) -{ - const auto allSupportingData = GetAllUniqueExpressionSupportingData(menuList); - auto functionIndex = 0u; - - assert(allSupportingData.size() <= 1); - - for (const auto* supportingData : allSupportingData) - { - if (supportingData->uifunctions.functions == nullptr) - continue; - - for (auto i = 0; i < supportingData->uifunctions.totalFunctions; i++) - { - const auto* function = supportingData->uifunctions.functions[i]; - if (function == nullptr) - continue; - - std::stringstream ss; - ss << "FUNC_" << functionIndex; - - menuDumper.WriteFunctionDef(ss.str(), function); - - functionIndex++; - } - } -} - -void AssetDumperMenuList::DumpMenus(MenuDumper& menuDumper, const MenuList* menuList) -{ - const fs::path p(menuList->name); - - std::string parentPath; - if (p.has_parent_path()) - parentPath = p.parent_path().string() + "/"; - - for (auto menuNum = 0; menuNum < menuList->menuCount; menuNum++) - { - const auto* menu = menuList->menus[menuNum]; - const auto* menuAssetName = menu->window.name; - - bool isReference = false; - if (menuAssetName && menuAssetName[0] == ',') - { - menuAssetName = &menuAssetName[1]; - isReference = true; - } - - std::ostringstream ss; - ss << parentPath << menuAssetName << ".menu"; - - const auto menuName = ss.str(); - - // If the menu was embedded directly as menu list write its data in the menu list file - if (!isReference && menuName == menuList->name) - menuDumper.WriteMenu(menu); - else - menuDumper.IncludeMenu(ss.str()); - } -} - -bool AssetDumperMenuList::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperMenuList::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* menuList = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name); - - if (!assetFile) - return; - - MenuDumper menuDumper(*assetFile); - - menuDumper.Start(); - - if (!ObjWriting::Configuration.MenuLegacyMode) - DumpFunctions(menuDumper, menuList); - - DumpMenus(menuDumper, menuList); - - menuDumper.End(); -} diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperMenuList.h b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperMenuList.h deleted file mode 100644 index 58a83904..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperMenuList.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW5/IW5.h" -#include "Game/IW5/Menu/MenuDumperIW5.h" - -namespace IW5 -{ - class AssetDumperMenuList final : public AbstractAssetDumper - { - static std::vector GetAllUniqueExpressionSupportingData(const MenuList* menuList); - - static void DumpFunctions(MenuDumper& menuDumper, const MenuList* menuList); - static void DumpMenus(MenuDumper& menuDumper, const MenuList* menuList); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW5 diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperRawFile.cpp b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperRawFile.cpp deleted file mode 100644 index 283b8bda..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperRawFile.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "AssetDumperRawFile.h" - -#include -#include -#include - -using namespace IW5; - -bool AssetDumperRawFile::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperRawFile::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* rawFile = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - if (rawFile->compressedLen <= 0) - return; - - z_stream_s zs{}; - zs.zalloc = Z_NULL; - zs.zfree = Z_NULL; - zs.opaque = Z_NULL; - zs.avail_in = 0; - zs.next_in = Z_NULL; - - int ret = inflateInit(&zs); - - if (ret != Z_OK) - { - throw std::runtime_error("Initializing inflate failed"); - } - - zs.next_in = reinterpret_cast(rawFile->buffer); - zs.avail_in = rawFile->compressedLen; - - Bytef buffer[0x1000]; - - while (zs.avail_in > 0) - { - zs.next_out = buffer; - zs.avail_out = sizeof(buffer); - ret = inflate(&zs, Z_SYNC_FLUSH); - - if (ret < 0) - { - std::cerr << std::format("Inflate failed when attempting to dump rawfile '{}'\n", rawFile->name); - inflateEnd(&zs); - return; - } - - stream.write(reinterpret_cast(buffer), sizeof(buffer) - zs.avail_out); - } - - inflateEnd(&zs); -} diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperRawFile.h b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperRawFile.h deleted file mode 100644 index 57e35274..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperRawFile.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW5/IW5.h" - -namespace IW5 -{ - class AssetDumperRawFile final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW5 diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperScriptFile.cpp b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperScriptFile.cpp deleted file mode 100644 index c432a700..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperScriptFile.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "AssetDumperScriptFile.h" - -using namespace IW5; - -bool AssetDumperScriptFile::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -// See https://github.com/xensik/gsc-tool#file-format for an in-depth explanation about the .gscbin format -void AssetDumperScriptFile::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - auto* scriptFile = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name + ".gscbin"); - - if (!assetFile) - return; - - auto& stream = *assetFile; - - // Dump the name and the numeric fields - stream.write(asset->m_name.c_str(), asset->m_name.size() + 1); - stream.write(reinterpret_cast(&scriptFile->compressedLen), sizeof(scriptFile->compressedLen)); - stream.write(reinterpret_cast(&scriptFile->len), sizeof(scriptFile->len)); - stream.write(reinterpret_cast(&scriptFile->bytecodeLen), sizeof(scriptFile->bytecodeLen)); - - // Dump the buffers - stream.write(scriptFile->buffer, scriptFile->compressedLen); - stream.write(reinterpret_cast(scriptFile->bytecode), scriptFile->bytecodeLen); -} diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperScriptFile.h b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperScriptFile.h deleted file mode 100644 index 2397f387..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperScriptFile.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW5/IW5.h" - -namespace IW5 -{ - class AssetDumperScriptFile final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW5 diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperStringTable.cpp b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperStringTable.cpp deleted file mode 100644 index 0612c075..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperStringTable.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "AssetDumperStringTable.h" - -#include "Csv/CsvStream.h" - -using namespace IW5; - -bool AssetDumperStringTable::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperStringTable::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* stringTable = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name); - - if (!assetFile) - return; - - CsvOutputStream csv(*assetFile); - - for (auto row = 0; row < stringTable->rowCount; row++) - { - for (auto column = 0; column < stringTable->columnCount; column++) - { - const auto* cell = &stringTable->values[column + row * stringTable->columnCount]; - if (cell->string != nullptr) - { - csv.WriteColumn(cell->string); - } - else - { - csv.WriteColumn(""); - } - } - - csv.NextRow(); - } -} diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperStringTable.h b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperStringTable.h deleted file mode 100644 index 9e834267..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperStringTable.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW5/IW5.h" - -namespace IW5 -{ - class AssetDumperStringTable final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW5 diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperWeapon.h b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperWeapon.h deleted file mode 100644 index d13b00a5..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperWeapon.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW5/IW5.h" -#include "InfoString/InfoString.h" - -namespace IW5 -{ - class AssetDumperWeapon final : public AbstractAssetDumper - { - static void CopyToFullDef(const WeaponCompleteDef* weapon, WeaponFullDef* fullDef); - static InfoString CreateInfoString(XAssetInfo* asset); - static void DumpAccuracyGraphs(AssetDumpingContext& context, XAssetInfo* asset); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW5 diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperWeaponAttachment.cpp b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperWeaponAttachment.cpp deleted file mode 100644 index d63e1649..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperWeaponAttachment.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "AssetDumperWeaponAttachment.h" - -#include "Game/IW5/Weapon/JsonWeaponAttachmentWriter.h" - -#include - -using namespace IW5; - -bool AssetDumperWeaponAttachment::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperWeaponAttachment::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto assetFile = context.OpenAssetFile(std::format("attachment/{}.json", asset->m_name)); - - if (!assetFile) - return; - - DumpWeaponAttachmentAsJson(*assetFile, asset->Asset(), context); -} diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperWeaponAttachment.h b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperWeaponAttachment.h deleted file mode 100644 index 11f32004..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperWeaponAttachment.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW5/IW5.h" - -namespace IW5 -{ - class AssetDumperWeaponAttachment final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW5 diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperXModel.cpp b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperXModel.cpp deleted file mode 100644 index bd882e41..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperXModel.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "AssetDumperXModel.h" - -#include "Game/IW5/XModel/XModelDumperIW5.h" - -using namespace IW5; - -bool AssetDumperXModel::ShouldDump(XAssetInfo* asset) -{ - return !asset->m_name.empty() && asset->m_name[0] != ','; -} - -void AssetDumperXModel::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - DumpXModel(context, asset); -} diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperXModel.h b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperXModel.h deleted file mode 100644 index 28880a59..00000000 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperXModel.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW5/IW5.h" - -namespace IW5 -{ - class AssetDumperXModel final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW5 diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperGfxImage.cpp b/src/ObjWriting/Game/IW5/Image/ImageDumperIW5.cpp similarity index 56% rename from src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperGfxImage.cpp rename to src/ObjWriting/Game/IW5/Image/ImageDumperIW5.cpp index 82d3cca1..e25b8227 100644 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperGfxImage.cpp +++ b/src/ObjWriting/Game/IW5/Image/ImageDumperIW5.cpp @@ -1,7 +1,8 @@ -#include "AssetDumperGfxImage.h" +#include "ImageDumperIW5.h" #include "Image/DdsWriter.h" #include "Image/Dx9TextureLoader.h" +#include "Image/ImageCommon.h" #include "Image/IwiLoader.h" #include "Image/IwiWriter8.h" #include "ObjWriting.h" @@ -36,7 +37,7 @@ namespace std::unique_ptr LoadImageFromIwi(const GfxImage& image, ISearchPath& searchPath) { - const auto imageFileName = std::format("images/{}.iwi", image.name); + const auto imageFileName = image::GetFileNameForAsset(image.name, ".iwi"); const auto filePathImage = searchPath.Open(imageFileName); if (!filePathImage.IsOpen()) { @@ -56,48 +57,43 @@ namespace } } // namespace -AssetDumperGfxImage::AssetDumperGfxImage() +namespace image { - switch (ObjWriting::Configuration.ImageOutputFormat) + DumperIW5::DumperIW5() { - case ObjWriting::Configuration_t::ImageOutputFormat_e::DDS: - m_writer = std::make_unique(); - break; - case ObjWriting::Configuration_t::ImageOutputFormat_e::IWI: - m_writer = std::make_unique(); - break; - default: - assert(false); - m_writer = nullptr; - break; + switch (ObjWriting::Configuration.ImageOutputFormat) + { + case ObjWriting::Configuration_t::ImageOutputFormat_e::DDS: + m_writer = std::make_unique(); + break; + case ObjWriting::Configuration_t::ImageOutputFormat_e::IWI: + m_writer = std::make_unique(); + break; + default: + assert(false); + m_writer = nullptr; + break; + } } -} -bool AssetDumperGfxImage::ShouldDump(XAssetInfo* asset) -{ - return true; -} + bool DumperIW5::ShouldDump(XAssetInfo* asset) + { + return true; + } -std::string AssetDumperGfxImage::GetAssetFileName(const XAssetInfo& asset) const -{ - auto cleanAssetName = asset.m_name; - std::ranges::replace(cleanAssetName, '*', '_'); + void DumperIW5::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* image = asset->Asset(); + const auto texture = LoadImageData(context.m_obj_search_path, *image); + if (!texture) + return; - return std::format("images/{}{}", cleanAssetName, m_writer->GetFileExtension()); -} + const auto assetFile = context.OpenAssetFile(GetFileNameForAsset(asset->m_name, m_writer->GetFileExtension())); -void AssetDumperGfxImage::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* image = asset->Asset(); - const auto texture = LoadImageData(context.m_obj_search_path, *image); - if (!texture) - return; + if (!assetFile) + return; - const auto assetFile = context.OpenAssetFile(GetAssetFileName(*asset)); - - if (!assetFile) - return; - - auto& stream = *assetFile; - m_writer->DumpImage(stream, texture.get()); -} + auto& stream = *assetFile; + m_writer->DumpImage(stream, texture.get()); + } +} // namespace image diff --git a/src/ObjWriting/Game/IW5/Image/ImageDumperIW5.h b/src/ObjWriting/Game/IW5/Image/ImageDumperIW5.h new file mode 100644 index 00000000..414465aa --- /dev/null +++ b/src/ObjWriting/Game/IW5/Image/ImageDumperIW5.h @@ -0,0 +1,23 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW5/IW5.h" +#include "Image/IImageWriter.h" + +#include + +namespace image +{ + class DumperIW5 final : public AbstractAssetDumper + { + public: + DumperIW5(); + + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + + private: + std::unique_ptr m_writer; + }; +} // namespace image diff --git a/src/ObjWriting/Game/IW5/Leaderboard/JsonLeaderboardDefWriter.h b/src/ObjWriting/Game/IW5/Leaderboard/JsonLeaderboardDefWriter.h deleted file mode 100644 index b992e6b2..00000000 --- a/src/ObjWriting/Game/IW5/Leaderboard/JsonLeaderboardDefWriter.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "Dumping/AssetDumpingContext.h" -#include "Game/IW5/IW5.h" - -#include - -namespace IW5 -{ - void DumpLeaderboardDefAsJson(std::ostream& stream, const LeaderboardDef* leaderboardDef); -} // namespace IW5 diff --git a/src/ObjWriting/Game/IW5/Leaderboard/JsonLeaderboardDefWriter.cpp b/src/ObjWriting/Game/IW5/Leaderboard/LeaderboardJsonDumperIW5.cpp similarity index 77% rename from src/ObjWriting/Game/IW5/Leaderboard/JsonLeaderboardDefWriter.cpp rename to src/ObjWriting/Game/IW5/Leaderboard/LeaderboardJsonDumperIW5.cpp index ef365d79..f79ea849 100644 --- a/src/ObjWriting/Game/IW5/Leaderboard/JsonLeaderboardDefWriter.cpp +++ b/src/ObjWriting/Game/IW5/Leaderboard/LeaderboardJsonDumperIW5.cpp @@ -1,28 +1,30 @@ -#include "JsonLeaderboardDefWriter.h" +#include "LeaderboardJsonDumperIW5.h" #include "Game/IW5/CommonIW5.h" #include "Game/IW5/Leaderboard/JsonLeaderboardDef.h" +#include "Leaderboard/LeaderboardCommon.h" #include #include +#include using namespace nlohmann; using namespace IW5; namespace { - class JsonDumper + class Dumper { public: - explicit JsonDumper(std::ostream& stream) + explicit Dumper(std::ostream& stream) : m_stream(stream) { } - void Dump(const LeaderboardDef* leaderboardDef) const + void Dump(const LeaderboardDef& leaderboardDef) const { JsonLeaderboardDef jsonLeaderboardDef; - CreateJsonLeaderboardDef(jsonLeaderboardDef, *leaderboardDef); + CreateJsonLeaderboardDef(jsonLeaderboardDef, leaderboardDef); json jRoot = jsonLeaderboardDef; @@ -90,11 +92,21 @@ namespace }; } // namespace -namespace IW5 +namespace leaderboard { - void DumpLeaderboardDefAsJson(std::ostream& stream, const LeaderboardDef* leaderboardDef) + bool JsonDumperIW5::ShouldDump(XAssetInfo* asset) { - JsonDumper dumper(stream); - dumper.Dump(leaderboardDef); + return true; } -} // namespace IW5 + + void JsonDumperIW5::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto assetFile = context.OpenAssetFile(GetJsonFileNameForAsset(asset->m_name)); + + if (!assetFile) + return; + + Dumper dumper(*assetFile); + dumper.Dump(*asset->Asset()); + } +} // namespace leaderboard diff --git a/src/ObjWriting/Game/IW5/Leaderboard/LeaderboardJsonDumperIW5.h b/src/ObjWriting/Game/IW5/Leaderboard/LeaderboardJsonDumperIW5.h new file mode 100644 index 00000000..3e6ff7f8 --- /dev/null +++ b/src/ObjWriting/Game/IW5/Leaderboard/LeaderboardJsonDumperIW5.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW5/IW5.h" + +namespace leaderboard +{ + class JsonDumperIW5 final : public AbstractAssetDumper + { + protected: + [[nodiscard]] bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace leaderboard diff --git a/src/ObjWriting/Game/IW5/Localize/LocalizeDumperIW5.cpp b/src/ObjWriting/Game/IW5/Localize/LocalizeDumperIW5.cpp new file mode 100644 index 00000000..c8b7b0d0 --- /dev/null +++ b/src/ObjWriting/Game/IW5/Localize/LocalizeDumperIW5.cpp @@ -0,0 +1,44 @@ +#include "LocalizeDumperIW5.h" + +#include "Dumping/Localize/StringFileDumper.h" +#include "Localize/LocalizeCommon.h" + +#include +#include + +using namespace IW5; + +namespace localize +{ + void DumperIW5::DumpPool(AssetDumpingContext& context, AssetPool* pool) + { + if (pool->m_asset_lookup.empty()) + return; + + const auto language = LocalizeCommon::GetNameOfLanguage(context.m_zone.m_language); + const auto assetFile = context.OpenAssetFile(std::format("{}/localizedstrings/{}.str", language, context.m_zone.m_name)); + + if (assetFile) + { + StringFileDumper stringFileDumper(context.m_zone, *assetFile); + + stringFileDumper.SetLanguageName(language); + + // Magic string. Original string files do have this config file. The purpose of the config file is unknown though. + stringFileDumper.SetConfigFile(R"(C:/trees/cod3/cod3/bin/StringEd.cfg)"); + + stringFileDumper.SetNotes(""); + + for (auto* localizeEntry : *pool) + { + stringFileDumper.WriteLocalizeEntry(localizeEntry->m_name, localizeEntry->Asset()->value); + } + + stringFileDumper.Finalize(); + } + else + { + std::cerr << std::format("Could not create string file for dumping localized strings of zone '{}'\n", context.m_zone.m_name); + } + } +} // namespace localize diff --git a/src/ObjWriting/Game/IW5/Localize/LocalizeDumperIW5.h b/src/ObjWriting/Game/IW5/Localize/LocalizeDumperIW5.h new file mode 100644 index 00000000..26373073 --- /dev/null +++ b/src/ObjWriting/Game/IW5/Localize/LocalizeDumperIW5.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW5/IW5.h" + +namespace localize +{ + class DumperIW5 final : public IAssetDumper + { + public: + void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; + }; +} // namespace localize diff --git a/src/ObjWriting/Game/IW5/Maps/AddonMapEntsDumperIW5.cpp b/src/ObjWriting/Game/IW5/Maps/AddonMapEntsDumperIW5.cpp new file mode 100644 index 00000000..3facfa1c --- /dev/null +++ b/src/ObjWriting/Game/IW5/Maps/AddonMapEntsDumperIW5.cpp @@ -0,0 +1,26 @@ +#define NOMINMAX +#include "AddonMapEntsDumperIW5.h" + +#include + +using namespace IW5; + +namespace addon_map_ents +{ + bool DumperIW5::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperIW5::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* addonMapEnts = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name); + + if (!assetFile) + return; + + auto& stream = *assetFile; + stream.write(addonMapEnts->entityString, std::max(addonMapEnts->numEntityChars - 1, 0)); + } +} // namespace addon_map_ents diff --git a/src/ObjWriting/Game/IW5/Maps/AddonMapEntsDumperIW5.h b/src/ObjWriting/Game/IW5/Maps/AddonMapEntsDumperIW5.h new file mode 100644 index 00000000..6c251086 --- /dev/null +++ b/src/ObjWriting/Game/IW5/Maps/AddonMapEntsDumperIW5.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW5/IW5.h" + +namespace addon_map_ents +{ + class DumperIW5 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace addon_map_ents diff --git a/src/ObjWriting/Game/IW5/Material/DumperMaterialIW5.cpp b/src/ObjWriting/Game/IW5/Material/DumperMaterialIW5.cpp deleted file mode 100644 index b8e705cb..00000000 --- a/src/ObjWriting/Game/IW5/Material/DumperMaterialIW5.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "DumperMaterialIW5.h" - -#include "Game/IW5/Material/JsonMaterialWriterIW5.h" -#include "Game/IW5/Material/MaterialConstantZoneStateIW5.h" -#include "Material/MaterialCommon.h" - -using namespace IW5; - -void AssetDumperMaterial::DumpPool(AssetDumpingContext& context, AssetPool* pool) -{ - auto* materialConstantState = context.GetZoneAssetDumperState(); - materialConstantState->ExtractNamesFromZone(); - - AbstractAssetDumper::DumpPool(context, pool); -} - -bool AssetDumperMaterial::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperMaterial::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto assetFile = context.OpenAssetFile(material::GetFileNameForAssetName(asset->m_name)); - - if (!assetFile) - return; - - const auto* material = asset->Asset(); - DumpMaterialAsJson(*assetFile, *material, context); -} diff --git a/src/ObjWriting/Game/IW5/Material/DumperMaterialIW5.h b/src/ObjWriting/Game/IW5/Material/DumperMaterialIW5.h deleted file mode 100644 index 12e57790..00000000 --- a/src/ObjWriting/Game/IW5/Material/DumperMaterialIW5.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/IW5/IW5.h" - -namespace IW5 -{ - class AssetDumperMaterial final : public AbstractAssetDumper - { - public: - void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace IW5 diff --git a/src/ObjWriting/Game/IW5/Menu/MenuDumperIW5.cpp b/src/ObjWriting/Game/IW5/Menu/MenuDumperIW5.cpp index d96e3c0b..2abe44a0 100644 --- a/src/ObjWriting/Game/IW5/Menu/MenuDumperIW5.cpp +++ b/src/ObjWriting/Game/IW5/Menu/MenuDumperIW5.cpp @@ -1,920 +1,83 @@ #include "MenuDumperIW5.h" -#include "Game/IW5/MenuConstantsIW5.h" +#include "Game/IW5/GameAssetPoolIW5.h" +#include "Game/IW5/Menu/MenuDumperIW5.h" +#include "MenuWriterIW5.h" #include "ObjWriting.h" -#include -#include -#include +#include +#include +#include + +namespace fs = std::filesystem; using namespace IW5; -// Uncomment this macro to skip interpretative expression dumping -// #define DUMP_NAIVE - -#ifdef DUMP_NAIVE -#define DUMP_FUNC WriteStatementNaive -#else -#define DUMP_FUNC WriteStatementSkipInitialUnnecessaryParenthesis -#endif - -size_t MenuDumper::FindStatementClosingParenthesis(const Statement_s* statement, size_t openingParenthesisPosition) +namespace { - assert(statement->numEntries >= 0); - assert(openingParenthesisPosition < static_cast(statement->numEntries)); - - const auto statementEnd = static_cast(statement->numEntries); - - // The openingParenthesisPosition does not necessarily point to an actual opening parenthesis operator. That's fine though. - // We will pretend it does since the game does sometimes leave out opening parenthesis from the entries. - auto currentParenthesisDepth = 1; - for (auto currentSearchPosition = openingParenthesisPosition + 1; currentSearchPosition < statementEnd; currentSearchPosition++) + const MenuList* GetParentMenuList(XAssetInfo* asset) { - const auto& expEntry = statement->entries[currentSearchPosition]; - if (expEntry.type != EET_OPERATOR) - continue; - - // Any function means a "left out" left paren - if (expEntry.data.op == OP_LEFTPAREN || expEntry.data.op >= OP_COUNT) + const auto* menu = asset->Asset(); + const auto* gameAssetPool = dynamic_cast(asset->m_zone->m_pools.get()); + for (const auto* menuList : *gameAssetPool->m_menu_list) { - currentParenthesisDepth++; - } - else if (expEntry.data.op == OP_RIGHTPAREN) - { - if (currentParenthesisDepth > 0) - currentParenthesisDepth--; - if (currentParenthesisDepth == 0) - return currentSearchPosition; - } - } + const auto* menuListAsset = menuList->Asset(); - return statementEnd; -} - -void MenuDumper::WriteStatementOperator(const Statement_s* statement, size_t& currentPos, bool& spaceNext) const -{ - const auto& expEntry = statement->entries[currentPos]; - - if (spaceNext && expEntry.data.op != OP_COMMA) - m_stream << " "; - - if (expEntry.data.op == OP_LEFTPAREN) - { - const auto closingParenPos = FindStatementClosingParenthesis(statement, currentPos); - m_stream << "("; - WriteStatementEntryRange(statement, currentPos + 1, closingParenPos); - m_stream << ")"; - - currentPos = closingParenPos + 1; - spaceNext = true; - } - else if (expEntry.data.op >= EXP_FUNC_STATIC_DVAR_INT && expEntry.data.op <= EXP_FUNC_STATIC_DVAR_STRING) - { - switch (expEntry.data.op) - { - case EXP_FUNC_STATIC_DVAR_INT: - m_stream << "dvarint"; - break; - - case EXP_FUNC_STATIC_DVAR_BOOL: - m_stream << "dvarbool"; - break; - - case EXP_FUNC_STATIC_DVAR_FLOAT: - m_stream << "dvarfloat"; - break; - - case EXP_FUNC_STATIC_DVAR_STRING: - m_stream << "dvarstring"; - break; - - default: - break; - } - - // Functions do not have opening parenthesis in the entries. We can just pretend they do though - const auto closingParenPos = FindStatementClosingParenthesis(statement, currentPos); - m_stream << "("; - - if (closingParenPos - currentPos + 1 >= 1) - { - const auto& staticDvarEntry = statement->entries[currentPos + 1]; - if (staticDvarEntry.type == EET_OPERAND && staticDvarEntry.data.operand.dataType == VAL_INT) + for (auto menuIndex = 0; menuIndex < menuListAsset->menuCount; menuIndex++) { - if (statement->supportingData && statement->supportingData->staticDvarList.staticDvars && staticDvarEntry.data.operand.internals.intVal >= 0 - && staticDvarEntry.data.operand.internals.intVal < statement->supportingData->staticDvarList.numStaticDvars) - { - const auto* staticDvar = statement->supportingData->staticDvarList.staticDvars[staticDvarEntry.data.operand.internals.intVal]; - if (staticDvar && staticDvar->dvarName) - m_stream << staticDvar->dvarName; - } - else - { - m_stream << "#INVALID_DVAR_INDEX"; - } - } - else - { - m_stream << "#INVALID_DVAR_OPERAND"; + if (menuListAsset->menus[menuIndex] == menu) + return menuListAsset; } } - m_stream << ")"; - currentPos = closingParenPos + 1; - spaceNext = true; + return nullptr; } - else + + std::string GetPathForMenu(XAssetInfo* asset) { - if (expEntry.data.op >= 0 && static_cast(expEntry.data.op) < std::extent_v) - m_stream << g_expFunctionNames[expEntry.data.op]; + const auto* list = GetParentMenuList(asset); - if (expEntry.data.op >= OP_COUNT) - { - // Functions do not have opening parenthesis in the entries. We can just pretend they do though - const auto closingParenPos = FindStatementClosingParenthesis(statement, currentPos); - m_stream << "("; - WriteStatementEntryRange(statement, currentPos + 1, closingParenPos); - m_stream << ")"; - currentPos = closingParenPos + 1; - } - else - currentPos++; + if (!list) + return std::format("ui_mp/{}.menu", asset->Asset()->window.name); - spaceNext = expEntry.data.op != OP_NOT; + const fs::path p(list->name); + std::string parentPath; + if (p.has_parent_path()) + parentPath = p.parent_path().string() + "/"; + + return std::format("{}{}.menu", parentPath, asset->Asset()->window.name); } -} +} // namespace -void MenuDumper::WriteStatementOperandFunction(const Statement_s* statement, const size_t currentPos) const +namespace menu { - const auto& operand = statement->entries[currentPos].data.operand; - - if (operand.internals.function == nullptr) - return; - - if (!ObjWriting::Configuration.MenuLegacyMode) + bool MenuDumperIW5::ShouldDump(XAssetInfo* asset) { - int functionIndex = -1; - if (statement->supportingData && statement->supportingData->uifunctions.functions) + return true; + } + + void MenuDumperIW5::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* menu = asset->Asset(); + const auto menuFilePath = GetPathForMenu(asset); + + if (ObjWriting::ShouldHandleAssetType(ASSET_TYPE_MENULIST)) { - for (auto supportingFunctionIndex = 0; supportingFunctionIndex < statement->supportingData->uifunctions.totalFunctions; supportingFunctionIndex++) - { - if (statement->supportingData->uifunctions.functions[supportingFunctionIndex] == operand.internals.function) - { - functionIndex = supportingFunctionIndex; - break; - } - } + // Don't dump menu file separately if the name matches the menu list + const auto* menuListParent = GetParentMenuList(asset); + if (menuListParent && menuFilePath == menuListParent->name) + return; } - if (functionIndex >= 0) - m_stream << "FUNC_" << functionIndex; - else - m_stream << "INVALID_FUNC"; - m_stream << "()"; + const auto assetFile = context.OpenAssetFile(menuFilePath); + + if (!assetFile) + return; + + auto menuWriter = CreateMenuWriterIW5(*assetFile); + + menuWriter->Start(); + menuWriter->WriteMenu(*menu); + menuWriter->End(); } - else - { - m_stream << "("; - WriteStatementSkipInitialUnnecessaryParenthesis(operand.internals.function); - m_stream << ")"; - } -} - -void MenuDumper::WriteStatementOperand(const Statement_s* statement, size_t& currentPos, bool& spaceNext) const -{ - const auto& expEntry = statement->entries[currentPos]; - - if (spaceNext) - m_stream << " "; - - const auto& operand = expEntry.data.operand; - - switch (operand.dataType) - { - case VAL_FLOAT: - m_stream << operand.internals.floatVal; - break; - - case VAL_INT: - m_stream << operand.internals.intVal; - break; - - case VAL_STRING: - WriteEscapedString(operand.internals.stringVal.string); - break; - - case VAL_FUNCTION: - WriteStatementOperandFunction(statement, currentPos); - break; - - default: - break; - } - - currentPos++; - spaceNext = true; -} - -void MenuDumper::WriteStatementEntryRange(const Statement_s* statement, size_t startOffset, size_t endOffset) const -{ - assert(startOffset <= endOffset); - assert(endOffset <= static_cast(statement->numEntries)); - - auto currentPos = startOffset; - auto spaceNext = false; - while (currentPos < endOffset) - { - const auto& expEntry = statement->entries[currentPos]; - - if (expEntry.type == EET_OPERATOR) - { - WriteStatementOperator(statement, currentPos, spaceNext); - } - else - { - WriteStatementOperand(statement, currentPos, spaceNext); - } - } -} - -void MenuDumper::WriteStatementNaive(const Statement_s* statement) const -{ - const auto entryCount = static_cast(statement->numEntries); - for (auto i = 0uz; i < entryCount; i++) - { - const auto& entry = statement->entries[i]; - if (entry.type == EET_OPERAND) - { - size_t pos = i; - bool discard = false; - WriteStatementOperand(statement, pos, discard); - } - else if (entry.data.op >= EXP_FUNC_STATIC_DVAR_INT && entry.data.op <= EXP_FUNC_STATIC_DVAR_STRING) - { - switch (entry.data.op) - { - case EXP_FUNC_STATIC_DVAR_INT: - m_stream << "dvarint"; - break; - - case EXP_FUNC_STATIC_DVAR_BOOL: - m_stream << "dvarbool"; - break; - - case EXP_FUNC_STATIC_DVAR_FLOAT: - m_stream << "dvarfloat"; - break; - - case EXP_FUNC_STATIC_DVAR_STRING: - m_stream << "dvarstring"; - break; - - default: - break; - } - - // Functions do not have opening parenthesis in the entries. We can just pretend they do though - const auto closingParenPos = FindStatementClosingParenthesis(statement, i); - m_stream << "("; - - if (closingParenPos - i + 1u >= 1u) - { - const auto& staticDvarEntry = statement->entries[i + 1u]; - if (staticDvarEntry.type == EET_OPERAND && staticDvarEntry.data.operand.dataType == VAL_INT) - { - if (statement->supportingData && statement->supportingData->staticDvarList.staticDvars && staticDvarEntry.data.operand.internals.intVal >= 0 - && staticDvarEntry.data.operand.internals.intVal < statement->supportingData->staticDvarList.numStaticDvars) - { - const auto* staticDvar = statement->supportingData->staticDvarList.staticDvars[staticDvarEntry.data.operand.internals.intVal]; - if (staticDvar && staticDvar->dvarName) - m_stream << staticDvar->dvarName; - } - else - { - m_stream << "#INVALID_DVAR_INDEX"; - } - } - else - { - m_stream << "#INVALID_DVAR_OPERAND"; - } - } - - m_stream << ")"; - i = closingParenPos; - } - else - { - assert(entry.data.op >= 0 && static_cast(entry.data.op) < std::extent_v); - if (entry.data.op >= 0 && static_cast(entry.data.op) < std::extent_v) - m_stream << g_expFunctionNames[entry.data.op]; - if (entry.data.op >= OP_COUNT) - m_stream << "("; - } - } -} - -void MenuDumper::WriteStatement(const Statement_s* statement) const -{ - if (statement == nullptr || statement->numEntries < 0) - return; - - WriteStatementEntryRange(statement, 0, static_cast(statement->numEntries)); -} - -void MenuDumper::WriteStatementSkipInitialUnnecessaryParenthesis(const Statement_s* statementValue) const -{ - if (statementValue == nullptr || statementValue->numEntries < 0) - return; - - const auto statementEnd = static_cast(statementValue->numEntries); - - if (statementValue->numEntries >= 1 && statementValue->entries[0].type == EET_OPERATOR && statementValue->entries[0].data.op == OP_LEFTPAREN) - { - const auto parenthesisEnd = FindStatementClosingParenthesis(statementValue, 0); - - if (parenthesisEnd >= statementEnd) - WriteStatementEntryRange(statementValue, 1, statementEnd); - else if (parenthesisEnd == statementEnd - 1) - WriteStatementEntryRange(statementValue, 1, statementEnd - 1); - else - WriteStatementEntryRange(statementValue, 0, statementEnd); - } - else - { - WriteStatementEntryRange(statementValue, 0, statementEnd); - } -} - -void MenuDumper::WriteStatementProperty(const std::string& propertyKey, const Statement_s* statementValue, bool isBooleanStatement) const -{ - if (statementValue == nullptr || statementValue->numEntries < 0) - return; - - Indent(); - WriteKey(propertyKey); - - if (isBooleanStatement) - { - m_stream << "when("; - DUMP_FUNC(statementValue); - m_stream << ");\n"; - } - else - { - DUMP_FUNC(statementValue); - m_stream << ";\n"; - } -} - -void MenuDumper::WriteSetLocalVarData(const std::string& setFunction, const SetLocalVarData* setLocalVarData) const -{ - if (setLocalVarData == nullptr) - return; - - Indent(); - m_stream << setFunction << " " << setLocalVarData->localVarName << " "; - WriteStatement(setLocalVarData->expression); - m_stream << ";\n"; -} - -// #define WRITE_ORIGINAL_SCRIPT - -void MenuDumper::WriteUnconditionalScript(const char* script) const -{ -#ifdef WRITE_ORIGINAL_SCRIPT - Indent(); - m_stream << script << "\n"; - return; -#endif - - const auto tokenList = CreateScriptTokenList(script); - - auto isNewStatement = true; - for (const auto& token : tokenList) - { - if (isNewStatement) - { - if (token == ";") - continue; - - Indent(); - } - - if (token == ";") - { - m_stream << ";\n"; - isNewStatement = true; - continue; - } - - if (!isNewStatement) - m_stream << " "; - else - isNewStatement = false; - - if (DoesTokenNeedQuotationMarks(token)) - m_stream << "\"" << token << "\""; - else - m_stream << token; - } - - if (!isNewStatement) - m_stream << ";\n"; -} - -void MenuDumper::WriteMenuEventHandlerSet(const MenuEventHandlerSet* eventHandlerSet) -{ - Indent(); - m_stream << "{\n"; - IncIndent(); - - for (auto i = 0; i < eventHandlerSet->eventHandlerCount; i++) - { - const auto* eventHandler = eventHandlerSet->eventHandlers[i]; - if (eventHandler == nullptr) - continue; - - switch (eventHandler->eventType) - { - case EVENT_UNCONDITIONAL: - WriteUnconditionalScript(eventHandler->eventData.unconditionalScript); - break; - - case EVENT_IF: - if (eventHandler->eventData.conditionalScript == nullptr || eventHandler->eventData.conditionalScript->eventExpression == nullptr - || eventHandler->eventData.conditionalScript->eventHandlerSet == nullptr) - { - continue; - } - - Indent(); - m_stream << "if ("; - WriteStatementSkipInitialUnnecessaryParenthesis(eventHandler->eventData.conditionalScript->eventExpression); - m_stream << ")\n"; - WriteMenuEventHandlerSet(eventHandler->eventData.conditionalScript->eventHandlerSet); - break; - - case EVENT_ELSE: - if (eventHandler->eventData.elseScript == nullptr) - continue; - - Indent(); - m_stream << "else\n"; - WriteMenuEventHandlerSet(eventHandler->eventData.elseScript); - break; - - case EVENT_SET_LOCAL_VAR_BOOL: - WriteSetLocalVarData("setLocalVarBool", eventHandler->eventData.setLocalVarData); - break; - - case EVENT_SET_LOCAL_VAR_INT: - WriteSetLocalVarData("setLocalVarInt", eventHandler->eventData.setLocalVarData); - break; - - case EVENT_SET_LOCAL_VAR_FLOAT: - WriteSetLocalVarData("setLocalVarFloat", eventHandler->eventData.setLocalVarData); - break; - - case EVENT_SET_LOCAL_VAR_STRING: - WriteSetLocalVarData("setLocalVarString", eventHandler->eventData.setLocalVarData); - break; - - default: - break; - } - } - - DecIndent(); - Indent(); - m_stream << "}\n"; -} - -void MenuDumper::WriteMenuEventHandlerSetProperty(const std::string& propertyKey, const MenuEventHandlerSet* eventHandlerSetValue) -{ - if (eventHandlerSetValue == nullptr) - return; - - Indent(); - m_stream << propertyKey << "\n"; - WriteMenuEventHandlerSet(eventHandlerSetValue); -} - -void MenuDumper::WriteRectProperty(const std::string& propertyKey, const rectDef_s& rect) const -{ - Indent(); - WriteKey(propertyKey); - m_stream << rect.x << " " << rect.y << " " << rect.w << " " << rect.h << " " << static_cast(rect.horzAlign) << " " << static_cast(rect.vertAlign) - << "\n"; -} - -void MenuDumper::WriteMaterialProperty(const std::string& propertyKey, const Material* materialValue) const -{ - if (materialValue == nullptr || materialValue->info.name == nullptr) - return; - - if (materialValue->info.name[0] == ',') - WriteStringProperty(propertyKey, &materialValue->info.name[1]); - else - WriteStringProperty(propertyKey, materialValue->info.name); -} - -void MenuDumper::WriteSoundAliasProperty(const std::string& propertyKey, const snd_alias_list_t* soundAliasValue) const -{ - if (soundAliasValue == nullptr) - return; - - WriteStringProperty(propertyKey, soundAliasValue->aliasName); -} - -void MenuDumper::WriteDecodeEffectProperty(const std::string& propertyKey, const itemDef_s* item) const -{ - if (!item->decayActive) - return; - - Indent(); - WriteKey(propertyKey); - m_stream << item->fxLetterTime << " " << item->fxDecayStartTime << " " << item->fxDecayDuration << "\n"; -} - -void MenuDumper::WriteItemKeyHandlerProperty(const ItemKeyHandler* itemKeyHandlerValue) -{ - for (const auto* currentHandler = itemKeyHandlerValue; currentHandler; currentHandler = currentHandler->next) - { - if (currentHandler->key >= '!' && currentHandler->key <= '~' && currentHandler->key != '"') - { - std::ostringstream ss; - ss << "execKey \"" << static_cast(currentHandler->key) << "\""; - WriteMenuEventHandlerSetProperty(ss.str(), currentHandler->action); - } - else - { - std::ostringstream ss; - ss << "execKeyInt " << currentHandler->key; - WriteMenuEventHandlerSetProperty(ss.str(), currentHandler->action); - } - } -} - -void MenuDumper::WriteFloatExpressionsProperty(const ItemFloatExpression* floatExpressions, int floatExpressionCount) const -{ - if (!floatExpressions) - return; - - for (int i = 0; i < floatExpressionCount; i++) - { - const auto& floatExpression = floatExpressions[i]; - - if (floatExpression.target < 0 || floatExpression.target >= ITEM_FLOATEXP_TGT_COUNT) - continue; - - std::string propertyName = std::string("exp ") + floatExpressionTargetBindings[floatExpression.target].name + std::string(" ") - + floatExpressionTargetBindings[floatExpression.target].componentName; - - WriteStatementProperty(propertyName, floatExpression.expression, false); - } -} - -void MenuDumper::WriteMultiTokenStringProperty(const std::string& propertyKey, const char* value) const -{ - if (!value) - return; - - Indent(); - WriteKey(propertyKey); - - const auto tokenList = CreateScriptTokenList(value); - - auto firstToken = true; - m_stream << "{ "; - for (const auto& token : tokenList) - { - if (firstToken) - firstToken = false; - else - m_stream << ";"; - m_stream << "\"" << token << "\""; - } - if (!firstToken) - m_stream << " "; - m_stream << "}\n"; -} - -void MenuDumper::WriteColumnProperty(const std::string& propertyKey, const listBoxDef_s* listBox) const -{ - if (listBox->numColumns <= 0) - return; - - Indent(); - WriteKey(propertyKey); - m_stream << listBox->numColumns << "\n"; - - for (auto col = 0; col < listBox->numColumns; col++) - { - Indent(); - for (auto i = 0u; i < MENU_KEY_SPACING; i++) - m_stream << " "; - - m_stream << listBox->columnInfo[col].xpos << " " << listBox->columnInfo[col].ypos << " " << listBox->columnInfo[col].width << " " - << listBox->columnInfo[col].height << " " << listBox->columnInfo[col].maxChars << " " << listBox->columnInfo[col].alignment << "\n"; - } -} - -void MenuDumper::WriteListBoxProperties(const itemDef_s* item) -{ - if (item->type != ITEM_TYPE_LISTBOX || item->typeData.listBox == nullptr) - return; - - const auto* listBox = item->typeData.listBox; - WriteKeywordProperty("notselectable", listBox->notselectable != 0); - WriteKeywordProperty("noscrollbars", listBox->noScrollBars != 0); - WriteKeywordProperty("usepaging", listBox->usePaging != 0); - WriteFloatProperty("elementwidth", listBox->elementWidth, 0.0f); - WriteFloatProperty("elementheight", listBox->elementHeight, 0.0f); - WriteFloatProperty("feeder", item->special, 0.0f); - WriteIntProperty("elementtype", listBox->elementStyle, 0); - WriteColumnProperty("columns", listBox); - WriteMenuEventHandlerSetProperty("doubleclick", listBox->onDoubleClick); - WriteColorProperty("selectBorder", listBox->selectBorder, COLOR_0000); - WriteMaterialProperty("selectIcon", listBox->selectIcon); - WriteStatementProperty("exp elementheight", listBox->elementHeightExp, false); -} - -void MenuDumper::WriteDvarFloatProperty(const std::string& propertyKey, const itemDef_s* item, const editFieldDef_s* editField) const -{ - if (item->dvar == nullptr) - return; - - Indent(); - WriteKey(propertyKey); - m_stream << "\"" << item->dvar << "\" " << editField->stepVal << " " << editField->minVal << " " << editField->maxVal << "\n"; -} - -void MenuDumper::WriteEditFieldProperties(const itemDef_s* item) const -{ - switch (item->type) - { - case ITEM_TYPE_TEXT: - case ITEM_TYPE_EDITFIELD: - case ITEM_TYPE_NUMERICFIELD: - case ITEM_TYPE_SLIDER: - case ITEM_TYPE_YESNO: - case ITEM_TYPE_BIND: - case ITEM_TYPE_VALIDFILEFIELD: - case ITEM_TYPE_DECIMALFIELD: - case ITEM_TYPE_UPREDITFIELD: - case ITEM_TYPE_EMAILFIELD: - case ITEM_TYPE_PASSWORDFIELD: - break; - - default: - return; - } - - if (item->typeData.editField == nullptr) - return; - - const auto* editField = item->typeData.editField; - if (std::fabs(-1.0f - editField->stepVal) >= std::numeric_limits::epsilon() - || std::fabs(-1.0f - editField->minVal) >= std::numeric_limits::epsilon() - || std::fabs(-1.0f - editField->maxVal) >= std::numeric_limits::epsilon()) - { - WriteDvarFloatProperty("dvarFloat", item, editField); - } - else - { - WriteStringProperty("dvar", item->dvar); - } - WriteStringProperty("localvar", item->localVar); - WriteIntProperty("maxChars", editField->maxChars, 0); - WriteKeywordProperty("maxCharsGotoNext", editField->maxCharsGotoNext != 0); - WriteIntProperty("maxPaintChars", editField->maxPaintChars, 0); -} - -void MenuDumper::WriteMultiValueProperty(const multiDef_s* multiDef) const -{ - Indent(); - if (multiDef->strDef) - WriteKey("dvarStrList"); - else - WriteKey("dvarFloatList"); - - m_stream << "{"; - for (auto i = 0; i < multiDef->count; i++) - { - if (multiDef->dvarList[i] == nullptr || multiDef->strDef && multiDef->dvarStr[i] == nullptr) - continue; - - m_stream << " \"" << multiDef->dvarList[i] << "\""; - - if (multiDef->strDef) - m_stream << " \"" << multiDef->dvarStr[i] << "\""; - else - m_stream << " " << multiDef->dvarValue[i] << ""; - } - m_stream << " }\n"; -} - -void MenuDumper::WriteMultiProperties(const itemDef_s* item) const -{ - if (item->type != ITEM_TYPE_MULTI || item->typeData.multi == nullptr) - return; - - const auto* multiDef = item->typeData.multi; - - if (multiDef->count <= 0) - return; - - WriteStringProperty("dvar", item->dvar); - WriteStringProperty("localvar", item->localVar); - WriteMultiValueProperty(multiDef); -} - -void MenuDumper::WriteEnumDvarProperties(const itemDef_s* item) const -{ - if (item->type != ITEM_TYPE_DVARENUM) - return; - - WriteStringProperty("dvar", item->dvar); - WriteStringProperty("localvar", item->localVar); - WriteStringProperty("dvarEnumList", item->typeData.enumDvarName); -} - -void MenuDumper::WriteTickerProperties(const itemDef_s* item) const -{ - if (item->type != ITEM_TYPE_NEWS_TICKER || item->typeData.ticker == nullptr) - return; - - const auto* newsTickerDef = item->typeData.ticker; - WriteIntProperty("spacing", newsTickerDef->spacing, 0); - WriteIntProperty("speed", newsTickerDef->speed, 0); - WriteIntProperty("newsfeed", newsTickerDef->feedId, 0); -} - -void MenuDumper::WriteItemData(const itemDef_s* item) -{ - WriteStringProperty("name", item->window.name); - WriteStringProperty("text", item->text); - WriteKeywordProperty("textsavegame", item->itemFlags & ITEM_FLAG_SAVE_GAME_INFO); - WriteKeywordProperty("textcinematicsubtitle", item->itemFlags & ITEM_FLAG_CINEMATIC_SUBTITLE); - WriteStringProperty("group", item->window.group); - WriteRectProperty("rect", item->window.rectClient); - WriteIntProperty("style", item->window.style, 0); - WriteKeywordProperty("decoration", item->window.staticFlags & WINDOW_FLAG_DECORATION); - WriteKeywordProperty("autowrapped", item->window.staticFlags & WINDOW_FLAG_AUTO_WRAPPED); - WriteKeywordProperty("horizontalscroll", item->window.staticFlags & WINDOW_FLAG_HORIZONTAL_SCROLL); - WriteIntProperty("type", item->type, ITEM_TYPE_TEXT); - WriteIntProperty("border", item->window.border, 0); - WriteFloatProperty("borderSize", item->window.borderSize, 0.0f); - - if (item->visibleExp) - WriteStatementProperty("visible", item->visibleExp, true); - else if (item->window.dynamicFlags[0] & WINDOW_FLAG_VISIBLE) - WriteIntProperty("visible", 1, 0); - - WriteStatementProperty("disabled", item->disabledExp, true); - WriteIntProperty("ownerdraw", item->window.ownerDraw, 0); - WriteFlagsProperty("ownerdrawFlag", item->window.ownerDrawFlags); - WriteIntProperty("align", item->alignment, 0); - WriteIntProperty("textalign", item->textAlignMode, 0); - WriteFloatProperty("textalignx", item->textalignx, 0.0f); - WriteFloatProperty("textaligny", item->textaligny, 0.0f); - WriteFloatProperty("textscale", item->textscale, 0.0f); - WriteIntProperty("textstyle", item->textStyle, 0); - WriteIntProperty("textfont", item->fontEnum, 0); - WriteColorProperty("backcolor", item->window.backColor, COLOR_0000); - WriteColorProperty("forecolor", item->window.foreColor, COLOR_1111); - WriteColorProperty("bordercolor", item->window.borderColor, COLOR_0000); - WriteColorProperty("outlinecolor", item->window.outlineColor, COLOR_0000); - WriteColorProperty("disablecolor", item->window.disableColor, COLOR_0000); - WriteColorProperty("glowcolor", item->glowColor, COLOR_0000); - WriteMaterialProperty("background", item->window.background); - WriteMenuEventHandlerSetProperty("onFocus", item->onFocus); - WriteMenuEventHandlerSetProperty("hasFocus", item->hasFocus); - WriteMenuEventHandlerSetProperty("leaveFocus", item->leaveFocus); - WriteMenuEventHandlerSetProperty("mouseEnter", item->mouseEnter); - WriteMenuEventHandlerSetProperty("mouseExit", item->mouseExit); - WriteMenuEventHandlerSetProperty("mouseEnterText", item->mouseEnterText); - WriteMenuEventHandlerSetProperty("mouseExitText", item->mouseExitText); - WriteMenuEventHandlerSetProperty("action", item->action); - WriteMenuEventHandlerSetProperty("accept", item->accept); - // WriteFloatProperty("special", item->special, 0.0f); - WriteSoundAliasProperty("focusSound", item->focusSound); - WriteStringProperty("dvarTest", item->dvarTest); - - if (item->dvarFlags & ITEM_DVAR_FLAG_ENABLE) - WriteMultiTokenStringProperty("enableDvar", item->enableDvar); - else if (item->dvarFlags & ITEM_DVAR_FLAG_DISABLE) - WriteMultiTokenStringProperty("disableDvar", item->enableDvar); - else if (item->dvarFlags & ITEM_DVAR_FLAG_SHOW) - WriteMultiTokenStringProperty("showDvar", item->enableDvar); - else if (item->dvarFlags & ITEM_DVAR_FLAG_HIDE) - WriteMultiTokenStringProperty("hideDvar", item->enableDvar); - else if (item->dvarFlags & ITEM_DVAR_FLAG_FOCUS) - WriteMultiTokenStringProperty("focusDvar", item->enableDvar); - - WriteItemKeyHandlerProperty(item->onKey); - WriteStatementProperty("exp text", item->textExp, false); - WriteStatementProperty("exp textaligny", item->textAlignYExp, false); - WriteStatementProperty("exp material", item->materialExp, false); - WriteFloatExpressionsProperty(item->floatExpressions, item->floatExpressionCount); - WriteIntProperty("gamemsgwindowindex", item->gameMsgWindowIndex, 0); - WriteIntProperty("gamemsgwindowmode", item->gameMsgWindowMode, 0); - WriteDecodeEffectProperty("decodeEffect", item); - - WriteListBoxProperties(item); - WriteEditFieldProperties(item); - WriteMultiProperties(item); - WriteEnumDvarProperties(item); - WriteTickerProperties(item); -} - -void MenuDumper::WriteItemDefs(const itemDef_s* const* itemDefs, size_t itemCount) -{ - for (auto i = 0u; i < itemCount; i++) - { - StartItemDefScope(); - - WriteItemData(itemDefs[i]); - - EndScope(); - } -} - -void MenuDumper::WriteMenuData(const menuDef_t* menu) -{ - WriteStringProperty("name", menu->window.name); - WriteBoolProperty("fullscreen", menu->data->fullScreen, false); - WriteKeywordProperty("screenSpace", menu->window.staticFlags & WINDOW_FLAG_SCREEN_SPACE); - WriteKeywordProperty("decoration", menu->window.staticFlags & WINDOW_FLAG_DECORATION); - WriteRectProperty("rect", menu->window.rect); - WriteIntProperty("style", menu->window.style, 0); - WriteIntProperty("border", menu->window.border, 0); - WriteFloatProperty("borderSize", menu->window.borderSize, 0.0f); - WriteColorProperty("backcolor", menu->window.backColor, COLOR_0000); - WriteColorProperty("forecolor", menu->window.foreColor, COLOR_1111); - WriteColorProperty("bordercolor", menu->window.borderColor, COLOR_0000); - WriteColorProperty("focuscolor", menu->data->focusColor, COLOR_0000); - WriteColorProperty("outlinecolor", menu->window.outlineColor, COLOR_0000); - WriteMaterialProperty("background", menu->window.background); - WriteIntProperty("ownerdraw", menu->window.ownerDraw, 0); - WriteFlagsProperty("ownerdrawFlag", menu->window.ownerDrawFlags); - WriteKeywordProperty("outOfBoundsClick", menu->window.staticFlags & WINDOW_FLAG_OUT_OF_BOUNDS_CLICK); - WriteStringProperty("soundLoop", menu->data->soundName); - WriteKeywordProperty("popup", menu->window.staticFlags & WINDOW_FLAG_POPUP); - WriteFloatProperty("fadeClamp", menu->data->fadeClamp, 0.0f); - WriteIntProperty("fadeCycle", menu->data->fadeCycle, 0); - WriteFloatProperty("fadeAmount", menu->data->fadeAmount, 0.0f); - WriteFloatProperty("fadeInAmount", menu->data->fadeInAmount, 0.0f); - WriteFloatProperty("blurWorld", menu->data->blurRadius, 0.0f); - WriteKeywordProperty("legacySplitScreenScale", menu->window.staticFlags & WINDOW_FLAG_LEGACY_SPLIT_SCREEN_SCALE); - WriteKeywordProperty("hiddenDuringScope", menu->window.staticFlags & WINDOW_FLAG_HIDDEN_DURING_SCOPE); - WriteKeywordProperty("hiddenDuringFlashbang", menu->window.staticFlags & WINDOW_FLAG_HIDDEN_DURING_FLASH_BANG); - WriteKeywordProperty("hiddenDuringUI", menu->window.staticFlags & WINDOW_FLAG_HIDDEN_DURING_UI); - WriteStringProperty("allowedBinding", menu->data->allowedBinding); - WriteKeywordProperty("textOnlyFocus", menu->window.staticFlags & WINDOW_FLAG_TEXT_ONLY_FOCUS); - - if (menu->data->visibleExp) - WriteStatementProperty("visible", menu->data->visibleExp, true); - else if (menu->window.dynamicFlags[0] & WINDOW_FLAG_VISIBLE) - WriteIntProperty("visible", 1, 0); - - WriteStatementProperty("exp rect X", menu->data->rectXExp, false); - WriteStatementProperty("exp rect Y", menu->data->rectYExp, false); - WriteStatementProperty("exp rect W", menu->data->rectWExp, false); - WriteStatementProperty("exp rect H", menu->data->rectHExp, false); - WriteStatementProperty("exp openSound", menu->data->openSoundExp, false); - WriteStatementProperty("exp closeSound", menu->data->closeSoundExp, false); - WriteStatementProperty("exp soundLoop", menu->data->soundLoopExp, false); - WriteMenuEventHandlerSetProperty("onOpen", menu->data->onOpen); - WriteMenuEventHandlerSetProperty("onClose", menu->data->onClose); - WriteMenuEventHandlerSetProperty("onRequestClose", menu->data->onCloseRequest); - WriteMenuEventHandlerSetProperty("onESC", menu->data->onESC); - WriteMenuEventHandlerSetProperty("onFocusDueToClose", menu->data->onFocusDueToClose); - WriteItemKeyHandlerProperty(menu->data->onKey); - WriteItemDefs(menu->items, menu->itemCount); -} - -MenuDumper::MenuDumper(std::ostream& stream) - : AbstractMenuDumper(stream) -{ -} - -void MenuDumper::WriteFunctionDef(const std::string& functionName, const Statement_s* statement) -{ - StartFunctionDefScope(); - - WriteStringProperty("name", functionName); - WriteStatementProperty("value", statement, false); - - EndScope(); -} - -void MenuDumper::WriteMenu(const menuDef_t* menu) -{ - StartMenuDefScope(); - - WriteMenuData(menu); - - EndScope(); -} +} // namespace menu diff --git a/src/ObjWriting/Game/IW5/Menu/MenuDumperIW5.h b/src/ObjWriting/Game/IW5/Menu/MenuDumperIW5.h index 9e3e3000..03577fcb 100644 --- a/src/ObjWriting/Game/IW5/Menu/MenuDumperIW5.h +++ b/src/ObjWriting/Game/IW5/Menu/MenuDumperIW5.h @@ -1,57 +1,15 @@ #pragma once +#include "Dumping/AbstractAssetDumper.h" #include "Game/IW5/IW5.h" -#include "Menu/AbstractMenuDumper.h" +#include "Game/IW5/Menu/MenuDumperIW5.h" -#include - -namespace IW5 +namespace menu { - class MenuDumper : public AbstractMenuDumper + class MenuDumperIW5 final : public AbstractAssetDumper { - static size_t FindStatementClosingParenthesis(const Statement_s* statement, size_t openingParenthesisPosition); - - void WriteStatementNaive(const Statement_s* statement) const; - - void WriteStatementOperator(const Statement_s* statement, size_t& currentPos, bool& spaceNext) const; - void WriteStatementOperandFunction(const Statement_s* statement, size_t currentPos) const; - void WriteStatementOperand(const Statement_s* statement, size_t& currentPos, bool& spaceNext) const; - void WriteStatementEntryRange(const Statement_s* statement, size_t startOffset, size_t endOffset) const; - void WriteStatement(const Statement_s* statement) const; - void WriteStatementSkipInitialUnnecessaryParenthesis(const Statement_s* statementValue) const; - void WriteStatementProperty(const std::string& propertyKey, const Statement_s* statementValue, bool isBooleanStatement) const; - - void WriteSetLocalVarData(const std::string& setFunction, const SetLocalVarData* setLocalVarData) const; - void WriteUnconditionalScript(const char* script) const; - void WriteMenuEventHandlerSet(const MenuEventHandlerSet* eventHandlerSet); - void WriteMenuEventHandlerSetProperty(const std::string& propertyKey, const MenuEventHandlerSet* eventHandlerSetValue); - - void WriteRectProperty(const std::string& propertyKey, const rectDef_s& rect) const; - void WriteMaterialProperty(const std::string& propertyKey, const Material* materialValue) const; - void WriteSoundAliasProperty(const std::string& propertyKey, const snd_alias_list_t* soundAliasValue) const; - void WriteDecodeEffectProperty(const std::string& propertyKey, const itemDef_s* item) const; - void WriteItemKeyHandlerProperty(const ItemKeyHandler* itemKeyHandlerValue); - void WriteMultiTokenStringProperty(const std::string& propertyKey, const char* value) const; - void WriteFloatExpressionsProperty(const ItemFloatExpression* floatExpressions, int floatExpressionCount) const; - void WriteColumnProperty(const std::string& propertyKey, const listBoxDef_s* listBox) const; - - void WriteListBoxProperties(const itemDef_s* item); - void WriteDvarFloatProperty(const std::string& propertyKey, const itemDef_s* item, const editFieldDef_s* editField) const; - void WriteEditFieldProperties(const itemDef_s* item) const; - void WriteMultiValueProperty(const multiDef_s* multiDef) const; - void WriteMultiProperties(const itemDef_s* item) const; - void WriteEnumDvarProperties(const itemDef_s* item) const; - void WriteTickerProperties(const itemDef_s* item) const; - - void WriteItemData(const itemDef_s* item); - void WriteItemDefs(const itemDef_s* const* itemDefs, size_t itemCount); - - void WriteMenuData(const menuDef_t* menu); - - public: - explicit MenuDumper(std::ostream& stream); - - void WriteFunctionDef(const std::string& functionName, const Statement_s* statement); - void WriteMenu(const menuDef_t* menu); + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; }; -} // namespace IW5 +} // namespace menu diff --git a/src/ObjWriting/Game/IW5/Menu/MenuListDumperIW5.cpp b/src/ObjWriting/Game/IW5/Menu/MenuListDumperIW5.cpp new file mode 100644 index 00000000..9a1d674c --- /dev/null +++ b/src/ObjWriting/Game/IW5/Menu/MenuListDumperIW5.cpp @@ -0,0 +1,133 @@ +#include "MenuListDumperIW5.h" + +#include "Game/IW5/Menu/MenuWriterIW5.h" +#include "Menu/AbstractMenuWriter.h" +#include "MenuWriterIW5.h" +#include "ObjWriting.h" + +#include +#include +#include +#include +#include + +namespace fs = std::filesystem; + +using namespace IW5; + +namespace +{ + std::vector GetAllUniqueExpressionSupportingData(const MenuList* menuList) + { + std::vector result; + std::set alreadyAddedSupportingData; + + if (menuList->menus == nullptr) + return result; + + for (auto i = 0; i < menuList->menuCount; i++) + { + if (menuList->menus[i] == nullptr) + continue; + + const auto* menu = menuList->menus[i]; + + if (menu->data == nullptr || menu->data->expressionData == nullptr) + continue; + + if (alreadyAddedSupportingData.find(menu->data->expressionData) == alreadyAddedSupportingData.end()) + { + result.push_back(menu->data->expressionData); + alreadyAddedSupportingData.emplace(menu->data->expressionData); + } + } + + return result; + } + + void DumpFunctions(menu::IWriterIW5& menuDumper, const MenuList* menuList) + { + const auto allSupportingData = GetAllUniqueExpressionSupportingData(menuList); + auto functionIndex = 0u; + + assert(allSupportingData.size() <= 1); + + for (const auto* supportingData : allSupportingData) + { + if (supportingData->uifunctions.functions == nullptr) + continue; + + for (auto i = 0; i < supportingData->uifunctions.totalFunctions; i++) + { + const auto* function = supportingData->uifunctions.functions[i]; + if (function == nullptr) + continue; + + menuDumper.WriteFunctionDef(std::format("FUNC_{}", functionIndex), function); + + functionIndex++; + } + } + } + + void DumpMenus(menu::IWriterIW5& menuDumper, const MenuList* menuList) + { + const fs::path p(menuList->name); + + std::string parentPath; + if (p.has_parent_path()) + parentPath = p.parent_path().string() + "/"; + + for (auto menuNum = 0; menuNum < menuList->menuCount; menuNum++) + { + const auto* menu = menuList->menus[menuNum]; + const auto* menuAssetName = menu->window.name; + + bool isReference = false; + if (menuAssetName && menuAssetName[0] == ',') + { + menuAssetName = &menuAssetName[1]; + isReference = true; + } + + std::ostringstream ss; + ss << parentPath << menuAssetName << ".menu"; + + const auto menuName = ss.str(); + + // If the menu was embedded directly as menu list write its data in the menu list file + if (!isReference && menuName == menuList->name) + menuDumper.WriteMenu(*menu); + else + menuDumper.IncludeMenu(ss.str()); + } + } +} // namespace + +namespace menu +{ + bool MenuListDumperIW5::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void MenuListDumperIW5::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* menuList = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name); + + if (!assetFile) + return; + + auto menuWriter = CreateMenuWriterIW5(*assetFile); + + menuWriter->Start(); + + if (!ObjWriting::Configuration.MenuLegacyMode) + DumpFunctions(*menuWriter, menuList); + + DumpMenus(*menuWriter, menuList); + + menuWriter->End(); + } +} // namespace menu diff --git a/src/ObjWriting/Game/IW5/Menu/MenuListDumperIW5.h b/src/ObjWriting/Game/IW5/Menu/MenuListDumperIW5.h new file mode 100644 index 00000000..d4da415f --- /dev/null +++ b/src/ObjWriting/Game/IW5/Menu/MenuListDumperIW5.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW5/IW5.h" + +namespace menu +{ + class MenuListDumperIW5 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace menu diff --git a/src/ObjWriting/Game/IW5/Menu/MenuWriterIW5.cpp b/src/ObjWriting/Game/IW5/Menu/MenuWriterIW5.cpp new file mode 100644 index 00000000..72a9307c --- /dev/null +++ b/src/ObjWriting/Game/IW5/Menu/MenuWriterIW5.cpp @@ -0,0 +1,957 @@ +#include "MenuWriterIW5.h" + +#include "Game/IW5/MenuConstantsIW5.h" +#include "Menu/AbstractMenuWriter.h" +#include "ObjWriting.h" + +#include +#include +#include + +using namespace IW5; + +// Uncomment this macro to skip interpretative expression dumping +// #define DUMP_NAIVE + +#ifdef DUMP_NAIVE +#define DUMP_FUNC WriteStatementNaive +#else +#define DUMP_FUNC WriteStatementSkipInitialUnnecessaryParenthesis +#endif + +namespace +{ + size_t FindStatementClosingParenthesis(const Statement_s* statement, const size_t openingParenthesisPosition) + { + assert(statement->numEntries >= 0); + assert(openingParenthesisPosition < static_cast(statement->numEntries)); + + const auto statementEnd = static_cast(statement->numEntries); + + // The openingParenthesisPosition does not necessarily point to an actual opening parenthesis operator. That's fine though. + // We will pretend it does since the game does sometimes leave out opening parenthesis from the entries. + auto currentParenthesisDepth = 1; + for (auto currentSearchPosition = openingParenthesisPosition + 1; currentSearchPosition < statementEnd; currentSearchPosition++) + { + const auto& expEntry = statement->entries[currentSearchPosition]; + if (expEntry.type != EET_OPERATOR) + continue; + + // Any function means a "left out" left paren + if (expEntry.data.op == OP_LEFTPAREN || expEntry.data.op >= OP_COUNT) + { + currentParenthesisDepth++; + } + else if (expEntry.data.op == OP_RIGHTPAREN) + { + if (currentParenthesisDepth > 0) + currentParenthesisDepth--; + if (currentParenthesisDepth == 0) + return currentSearchPosition; + } + } + + return statementEnd; + } +} // namespace + +namespace +{ + class MenuWriter final : public menu::AbstractBaseWriter, public menu::IWriterIW5 + { + public: + explicit MenuWriter(std::ostream& stream) + : AbstractBaseWriter(stream) + { + } + + void WriteFunctionDef(const std::string& functionName, const Statement_s* statement) override + { + StartFunctionDefScope(); + + WriteStringProperty("name", functionName); + WriteStatementProperty("value", statement, false); + + EndScope(); + } + + void WriteMenu(const menuDef_t& menu) override + { + StartMenuDefScope(); + + WriteMenuData(&menu); + + EndScope(); + } + + void Start() override + { + AbstractBaseWriter::Start(); + } + + void End() override + { + AbstractBaseWriter::End(); + } + + void IncludeMenu(const std::string& menuPath) const override + { + AbstractBaseWriter::IncludeMenu(menuPath); + } + + private: + void WriteStatementNaive(const Statement_s* statement) const + { + const auto entryCount = static_cast(statement->numEntries); + for (auto i = 0uz; i < entryCount; i++) + { + const auto& entry = statement->entries[i]; + if (entry.type == EET_OPERAND) + { + size_t pos = i; + bool discard = false; + WriteStatementOperand(statement, pos, discard); + } + else if (entry.data.op >= EXP_FUNC_STATIC_DVAR_INT && entry.data.op <= EXP_FUNC_STATIC_DVAR_STRING) + { + switch (entry.data.op) + { + case EXP_FUNC_STATIC_DVAR_INT: + m_stream << "dvarint"; + break; + + case EXP_FUNC_STATIC_DVAR_BOOL: + m_stream << "dvarbool"; + break; + + case EXP_FUNC_STATIC_DVAR_FLOAT: + m_stream << "dvarfloat"; + break; + + case EXP_FUNC_STATIC_DVAR_STRING: + m_stream << "dvarstring"; + break; + + default: + break; + } + + // Functions do not have opening parenthesis in the entries. We can just pretend they do though + const auto closingParenPos = FindStatementClosingParenthesis(statement, i); + m_stream << "("; + + if (closingParenPos - i + 1u >= 1u) + { + const auto& staticDvarEntry = statement->entries[i + 1u]; + if (staticDvarEntry.type == EET_OPERAND && staticDvarEntry.data.operand.dataType == VAL_INT) + { + if (statement->supportingData && statement->supportingData->staticDvarList.staticDvars + && staticDvarEntry.data.operand.internals.intVal >= 0 + && staticDvarEntry.data.operand.internals.intVal < statement->supportingData->staticDvarList.numStaticDvars) + { + const auto* staticDvar = statement->supportingData->staticDvarList.staticDvars[staticDvarEntry.data.operand.internals.intVal]; + if (staticDvar && staticDvar->dvarName) + m_stream << staticDvar->dvarName; + } + else + { + m_stream << "#INVALID_DVAR_INDEX"; + } + } + else + { + m_stream << "#INVALID_DVAR_OPERAND"; + } + } + + m_stream << ")"; + i = closingParenPos; + } + else + { + assert(entry.data.op >= 0 && static_cast(entry.data.op) < std::extent_v); + if (entry.data.op >= 0 && static_cast(entry.data.op) < std::extent_v) + m_stream << g_expFunctionNames[entry.data.op]; + if (entry.data.op >= OP_COUNT) + m_stream << "("; + } + } + } + + void WriteStatementOperator(const Statement_s* statement, size_t& currentPos, bool& spaceNext) const + { + const auto& expEntry = statement->entries[currentPos]; + + if (spaceNext && expEntry.data.op != OP_COMMA) + m_stream << " "; + + if (expEntry.data.op == OP_LEFTPAREN) + { + const auto closingParenPos = FindStatementClosingParenthesis(statement, currentPos); + m_stream << "("; + WriteStatementEntryRange(statement, currentPos + 1, closingParenPos); + m_stream << ")"; + + currentPos = closingParenPos + 1; + spaceNext = true; + } + else if (expEntry.data.op >= EXP_FUNC_STATIC_DVAR_INT && expEntry.data.op <= EXP_FUNC_STATIC_DVAR_STRING) + { + switch (expEntry.data.op) + { + case EXP_FUNC_STATIC_DVAR_INT: + m_stream << "dvarint"; + break; + + case EXP_FUNC_STATIC_DVAR_BOOL: + m_stream << "dvarbool"; + break; + + case EXP_FUNC_STATIC_DVAR_FLOAT: + m_stream << "dvarfloat"; + break; + + case EXP_FUNC_STATIC_DVAR_STRING: + m_stream << "dvarstring"; + break; + + default: + break; + } + + // Functions do not have opening parenthesis in the entries. We can just pretend they do though + const auto closingParenPos = FindStatementClosingParenthesis(statement, currentPos); + m_stream << "("; + + if (closingParenPos - currentPos + 1 >= 1) + { + const auto& staticDvarEntry = statement->entries[currentPos + 1]; + if (staticDvarEntry.type == EET_OPERAND && staticDvarEntry.data.operand.dataType == VAL_INT) + { + if (statement->supportingData && statement->supportingData->staticDvarList.staticDvars + && staticDvarEntry.data.operand.internals.intVal >= 0 + && staticDvarEntry.data.operand.internals.intVal < statement->supportingData->staticDvarList.numStaticDvars) + { + const auto* staticDvar = statement->supportingData->staticDvarList.staticDvars[staticDvarEntry.data.operand.internals.intVal]; + if (staticDvar && staticDvar->dvarName) + m_stream << staticDvar->dvarName; + } + else + { + m_stream << "#INVALID_DVAR_INDEX"; + } + } + else + { + m_stream << "#INVALID_DVAR_OPERAND"; + } + } + + m_stream << ")"; + currentPos = closingParenPos + 1; + spaceNext = true; + } + else + { + if (expEntry.data.op >= 0 && static_cast(expEntry.data.op) < std::extent_v) + m_stream << g_expFunctionNames[expEntry.data.op]; + + if (expEntry.data.op >= OP_COUNT) + { + // Functions do not have opening parenthesis in the entries. We can just pretend they do though + const auto closingParenPos = FindStatementClosingParenthesis(statement, currentPos); + m_stream << "("; + WriteStatementEntryRange(statement, currentPos + 1, closingParenPos); + m_stream << ")"; + currentPos = closingParenPos + 1; + } + else + currentPos++; + + spaceNext = expEntry.data.op != OP_NOT; + } + } + + void WriteStatementOperandFunction(const Statement_s* statement, size_t currentPos) const + { + const auto& operand = statement->entries[currentPos].data.operand; + + if (operand.internals.function == nullptr) + return; + + if (!ObjWriting::Configuration.MenuLegacyMode) + { + int functionIndex = -1; + if (statement->supportingData && statement->supportingData->uifunctions.functions) + { + for (auto supportingFunctionIndex = 0; supportingFunctionIndex < statement->supportingData->uifunctions.totalFunctions; + supportingFunctionIndex++) + { + if (statement->supportingData->uifunctions.functions[supportingFunctionIndex] == operand.internals.function) + { + functionIndex = supportingFunctionIndex; + break; + } + } + } + + if (functionIndex >= 0) + m_stream << "FUNC_" << functionIndex; + else + m_stream << "INVALID_FUNC"; + m_stream << "()"; + } + else + { + m_stream << "("; + WriteStatementSkipInitialUnnecessaryParenthesis(operand.internals.function); + m_stream << ")"; + } + } + + void WriteStatementOperand(const Statement_s* statement, size_t& currentPos, bool& spaceNext) const + { + const auto& expEntry = statement->entries[currentPos]; + + if (spaceNext) + m_stream << " "; + + const auto& operand = expEntry.data.operand; + + switch (operand.dataType) + { + case VAL_FLOAT: + m_stream << operand.internals.floatVal; + break; + + case VAL_INT: + m_stream << operand.internals.intVal; + break; + + case VAL_STRING: + WriteEscapedString(operand.internals.stringVal.string); + break; + + case VAL_FUNCTION: + WriteStatementOperandFunction(statement, currentPos); + break; + + default: + break; + } + + currentPos++; + spaceNext = true; + } + + void WriteStatementEntryRange(const Statement_s* statement, size_t startOffset, size_t endOffset) const + { + assert(startOffset <= endOffset); + assert(endOffset <= static_cast(statement->numEntries)); + + auto currentPos = startOffset; + auto spaceNext = false; + while (currentPos < endOffset) + { + const auto& expEntry = statement->entries[currentPos]; + + if (expEntry.type == EET_OPERATOR) + { + WriteStatementOperator(statement, currentPos, spaceNext); + } + else + { + WriteStatementOperand(statement, currentPos, spaceNext); + } + } + } + + void WriteStatement(const Statement_s* statement) const + { + if (statement == nullptr || statement->numEntries < 0) + return; + + WriteStatementEntryRange(statement, 0, static_cast(statement->numEntries)); + } + + void WriteStatementSkipInitialUnnecessaryParenthesis(const Statement_s* statementValue) const + { + if (statementValue == nullptr || statementValue->numEntries < 0) + return; + + const auto statementEnd = static_cast(statementValue->numEntries); + + if (statementValue->numEntries >= 1 && statementValue->entries[0].type == EET_OPERATOR && statementValue->entries[0].data.op == OP_LEFTPAREN) + { + const auto parenthesisEnd = FindStatementClosingParenthesis(statementValue, 0); + + if (parenthesisEnd >= statementEnd) + WriteStatementEntryRange(statementValue, 1, statementEnd); + else if (parenthesisEnd == statementEnd - 1) + WriteStatementEntryRange(statementValue, 1, statementEnd - 1); + else + WriteStatementEntryRange(statementValue, 0, statementEnd); + } + else + { + WriteStatementEntryRange(statementValue, 0, statementEnd); + } + } + + void WriteStatementProperty(const std::string& propertyKey, const Statement_s* statementValue, bool isBooleanStatement) const + { + if (statementValue == nullptr || statementValue->numEntries < 0) + return; + + Indent(); + WriteKey(propertyKey); + + if (isBooleanStatement) + { + m_stream << "when("; + DUMP_FUNC(statementValue); + m_stream << ");\n"; + } + else + { + DUMP_FUNC(statementValue); + m_stream << ";\n"; + } + } + + void WriteSetLocalVarData(const std::string& setFunction, const SetLocalVarData* setLocalVarData) const + { + if (setLocalVarData == nullptr) + return; + + Indent(); + m_stream << setFunction << " " << setLocalVarData->localVarName << " "; + WriteStatement(setLocalVarData->expression); + m_stream << ";\n"; + } + + // #define WRITE_ORIGINAL_SCRIPT + void WriteUnconditionalScript(const char* script) const + { +#ifdef WRITE_ORIGINAL_SCRIPT + Indent(); + m_stream << script << "\n"; + return; +#endif + + const auto tokenList = CreateScriptTokenList(script); + + auto isNewStatement = true; + for (const auto& token : tokenList) + { + if (isNewStatement) + { + if (token == ";") + continue; + + Indent(); + } + + if (token == ";") + { + m_stream << ";\n"; + isNewStatement = true; + continue; + } + + if (!isNewStatement) + m_stream << " "; + else + isNewStatement = false; + + if (DoesTokenNeedQuotationMarks(token)) + m_stream << "\"" << token << "\""; + else + m_stream << token; + } + + if (!isNewStatement) + m_stream << ";\n"; + } + + void WriteMenuEventHandlerSet(const MenuEventHandlerSet* eventHandlerSet) + { + Indent(); + m_stream << "{\n"; + IncIndent(); + + for (auto i = 0; i < eventHandlerSet->eventHandlerCount; i++) + { + const auto* eventHandler = eventHandlerSet->eventHandlers[i]; + if (eventHandler == nullptr) + continue; + + switch (eventHandler->eventType) + { + case EVENT_UNCONDITIONAL: + WriteUnconditionalScript(eventHandler->eventData.unconditionalScript); + break; + + case EVENT_IF: + if (eventHandler->eventData.conditionalScript == nullptr || eventHandler->eventData.conditionalScript->eventExpression == nullptr + || eventHandler->eventData.conditionalScript->eventHandlerSet == nullptr) + { + continue; + } + + Indent(); + m_stream << "if ("; + WriteStatementSkipInitialUnnecessaryParenthesis(eventHandler->eventData.conditionalScript->eventExpression); + m_stream << ")\n"; + WriteMenuEventHandlerSet(eventHandler->eventData.conditionalScript->eventHandlerSet); + break; + + case EVENT_ELSE: + if (eventHandler->eventData.elseScript == nullptr) + continue; + + Indent(); + m_stream << "else\n"; + WriteMenuEventHandlerSet(eventHandler->eventData.elseScript); + break; + + case EVENT_SET_LOCAL_VAR_BOOL: + WriteSetLocalVarData("setLocalVarBool", eventHandler->eventData.setLocalVarData); + break; + + case EVENT_SET_LOCAL_VAR_INT: + WriteSetLocalVarData("setLocalVarInt", eventHandler->eventData.setLocalVarData); + break; + + case EVENT_SET_LOCAL_VAR_FLOAT: + WriteSetLocalVarData("setLocalVarFloat", eventHandler->eventData.setLocalVarData); + break; + + case EVENT_SET_LOCAL_VAR_STRING: + WriteSetLocalVarData("setLocalVarString", eventHandler->eventData.setLocalVarData); + break; + + default: + break; + } + } + + DecIndent(); + Indent(); + m_stream << "}\n"; + } + + void WriteMenuEventHandlerSetProperty(const std::string& propertyKey, const MenuEventHandlerSet* eventHandlerSetValue) + { + if (eventHandlerSetValue == nullptr) + return; + + Indent(); + m_stream << propertyKey << "\n"; + WriteMenuEventHandlerSet(eventHandlerSetValue); + } + + void WriteRectProperty(const std::string& propertyKey, const rectDef_s& rect) const + { + Indent(); + WriteKey(propertyKey); + m_stream << rect.x << " " << rect.y << " " << rect.w << " " << rect.h << " " << static_cast(rect.horzAlign) << " " + << static_cast(rect.vertAlign) << "\n"; + } + + void WriteMaterialProperty(const std::string& propertyKey, const Material* materialValue) const + { + if (materialValue == nullptr || materialValue->info.name == nullptr) + return; + + if (materialValue->info.name[0] == ',') + WriteStringProperty(propertyKey, &materialValue->info.name[1]); + else + WriteStringProperty(propertyKey, materialValue->info.name); + } + + void WriteSoundAliasProperty(const std::string& propertyKey, const snd_alias_list_t* soundAliasValue) const + { + if (soundAliasValue == nullptr) + return; + + WriteStringProperty(propertyKey, soundAliasValue->aliasName); + } + + void WriteDecodeEffectProperty(const std::string& propertyKey, const itemDef_s* item) const + { + if (!item->decayActive) + return; + + Indent(); + WriteKey(propertyKey); + m_stream << item->fxLetterTime << " " << item->fxDecayStartTime << " " << item->fxDecayDuration << "\n"; + } + + void WriteItemKeyHandlerProperty(const ItemKeyHandler* itemKeyHandlerValue) + { + for (const auto* currentHandler = itemKeyHandlerValue; currentHandler; currentHandler = currentHandler->next) + { + if (currentHandler->key >= '!' && currentHandler->key <= '~' && currentHandler->key != '"') + { + std::ostringstream ss; + ss << "execKey \"" << static_cast(currentHandler->key) << "\""; + WriteMenuEventHandlerSetProperty(ss.str(), currentHandler->action); + } + else + { + std::ostringstream ss; + ss << "execKeyInt " << currentHandler->key; + WriteMenuEventHandlerSetProperty(ss.str(), currentHandler->action); + } + } + } + + void WriteMultiTokenStringProperty(const std::string& propertyKey, const char* value) const + { + if (!value) + return; + + Indent(); + WriteKey(propertyKey); + + const auto tokenList = CreateScriptTokenList(value); + + auto firstToken = true; + m_stream << "{ "; + for (const auto& token : tokenList) + { + if (firstToken) + firstToken = false; + else + m_stream << ";"; + m_stream << "\"" << token << "\""; + } + if (!firstToken) + m_stream << " "; + m_stream << "}\n"; + } + + void WriteFloatExpressionsProperty(const ItemFloatExpression* floatExpressions, int floatExpressionCount) const + { + if (!floatExpressions) + return; + + for (int i = 0; i < floatExpressionCount; i++) + { + const auto& floatExpression = floatExpressions[i]; + + if (floatExpression.target < 0 || floatExpression.target >= ITEM_FLOATEXP_TGT_COUNT) + continue; + + std::string propertyName = std::string("exp ") + floatExpressionTargetBindings[floatExpression.target].name + std::string(" ") + + floatExpressionTargetBindings[floatExpression.target].componentName; + + WriteStatementProperty(propertyName, floatExpression.expression, false); + } + } + + void WriteColumnProperty(const std::string& propertyKey, const listBoxDef_s* listBox) const + { + if (listBox->numColumns <= 0) + return; + + Indent(); + WriteKey(propertyKey); + m_stream << listBox->numColumns << "\n"; + + for (auto col = 0; col < listBox->numColumns; col++) + { + Indent(); + for (auto i = 0u; i < MENU_KEY_SPACING; i++) + m_stream << " "; + + m_stream << listBox->columnInfo[col].xpos << " " << listBox->columnInfo[col].ypos << " " << listBox->columnInfo[col].width << " " + << listBox->columnInfo[col].height << " " << listBox->columnInfo[col].maxChars << " " << listBox->columnInfo[col].alignment << "\n"; + } + } + + void WriteListBoxProperties(const itemDef_s* item) + { + if (item->type != ITEM_TYPE_LISTBOX || item->typeData.listBox == nullptr) + return; + + const auto* listBox = item->typeData.listBox; + WriteKeywordProperty("notselectable", listBox->notselectable != 0); + WriteKeywordProperty("noscrollbars", listBox->noScrollBars != 0); + WriteKeywordProperty("usepaging", listBox->usePaging != 0); + WriteFloatProperty("elementwidth", listBox->elementWidth, 0.0f); + WriteFloatProperty("elementheight", listBox->elementHeight, 0.0f); + WriteFloatProperty("feeder", item->special, 0.0f); + WriteIntProperty("elementtype", listBox->elementStyle, 0); + WriteColumnProperty("columns", listBox); + WriteMenuEventHandlerSetProperty("doubleclick", listBox->onDoubleClick); + WriteColorProperty("selectBorder", listBox->selectBorder, COLOR_0000); + WriteMaterialProperty("selectIcon", listBox->selectIcon); + WriteStatementProperty("exp elementheight", listBox->elementHeightExp, false); + } + + void WriteDvarFloatProperty(const std::string& propertyKey, const itemDef_s* item, const editFieldDef_s* editField) const + { + if (item->dvar == nullptr) + return; + + Indent(); + WriteKey(propertyKey); + m_stream << "\"" << item->dvar << "\" " << editField->stepVal << " " << editField->minVal << " " << editField->maxVal << "\n"; + } + + void WriteEditFieldProperties(const itemDef_s* item) const + { + switch (item->type) + { + case ITEM_TYPE_TEXT: + case ITEM_TYPE_EDITFIELD: + case ITEM_TYPE_NUMERICFIELD: + case ITEM_TYPE_SLIDER: + case ITEM_TYPE_YESNO: + case ITEM_TYPE_BIND: + case ITEM_TYPE_VALIDFILEFIELD: + case ITEM_TYPE_DECIMALFIELD: + case ITEM_TYPE_UPREDITFIELD: + case ITEM_TYPE_EMAILFIELD: + case ITEM_TYPE_PASSWORDFIELD: + break; + + default: + return; + } + + if (item->typeData.editField == nullptr) + return; + + const auto* editField = item->typeData.editField; + if (std::fabs(-1.0f - editField->stepVal) >= std::numeric_limits::epsilon() + || std::fabs(-1.0f - editField->minVal) >= std::numeric_limits::epsilon() + || std::fabs(-1.0f - editField->maxVal) >= std::numeric_limits::epsilon()) + { + WriteDvarFloatProperty("dvarFloat", item, editField); + } + else + { + WriteStringProperty("dvar", item->dvar); + } + WriteStringProperty("localvar", item->localVar); + WriteIntProperty("maxChars", editField->maxChars, 0); + WriteKeywordProperty("maxCharsGotoNext", editField->maxCharsGotoNext != 0); + WriteIntProperty("maxPaintChars", editField->maxPaintChars, 0); + } + + void WriteMultiValueProperty(const multiDef_s* multiDef) const + { + Indent(); + if (multiDef->strDef) + WriteKey("dvarStrList"); + else + WriteKey("dvarFloatList"); + + m_stream << "{"; + for (auto i = 0; i < multiDef->count; i++) + { + if (multiDef->dvarList[i] == nullptr || multiDef->strDef && multiDef->dvarStr[i] == nullptr) + continue; + + m_stream << " \"" << multiDef->dvarList[i] << "\""; + + if (multiDef->strDef) + m_stream << " \"" << multiDef->dvarStr[i] << "\""; + else + m_stream << " " << multiDef->dvarValue[i] << ""; + } + m_stream << " }\n"; + } + + void WriteMultiProperties(const itemDef_s* item) const + { + if (item->type != ITEM_TYPE_MULTI || item->typeData.multi == nullptr) + return; + + const auto* multiDef = item->typeData.multi; + + if (multiDef->count <= 0) + return; + + WriteStringProperty("dvar", item->dvar); + WriteStringProperty("localvar", item->localVar); + WriteMultiValueProperty(multiDef); + } + + void WriteEnumDvarProperties(const itemDef_s* item) const + { + if (item->type != ITEM_TYPE_DVARENUM) + return; + + WriteStringProperty("dvar", item->dvar); + WriteStringProperty("localvar", item->localVar); + WriteStringProperty("dvarEnumList", item->typeData.enumDvarName); + } + + void WriteTickerProperties(const itemDef_s* item) const + { + if (item->type != ITEM_TYPE_NEWS_TICKER || item->typeData.ticker == nullptr) + return; + + const auto* newsTickerDef = item->typeData.ticker; + WriteIntProperty("spacing", newsTickerDef->spacing, 0); + WriteIntProperty("speed", newsTickerDef->speed, 0); + WriteIntProperty("newsfeed", newsTickerDef->feedId, 0); + } + + void WriteItemData(const itemDef_s* item) + { + WriteStringProperty("name", item->window.name); + WriteStringProperty("text", item->text); + WriteKeywordProperty("textsavegame", item->itemFlags & ITEM_FLAG_SAVE_GAME_INFO); + WriteKeywordProperty("textcinematicsubtitle", item->itemFlags & ITEM_FLAG_CINEMATIC_SUBTITLE); + WriteStringProperty("group", item->window.group); + WriteRectProperty("rect", item->window.rectClient); + WriteIntProperty("style", item->window.style, 0); + WriteKeywordProperty("decoration", item->window.staticFlags & WINDOW_FLAG_DECORATION); + WriteKeywordProperty("autowrapped", item->window.staticFlags & WINDOW_FLAG_AUTO_WRAPPED); + WriteKeywordProperty("horizontalscroll", item->window.staticFlags & WINDOW_FLAG_HORIZONTAL_SCROLL); + WriteIntProperty("type", item->type, ITEM_TYPE_TEXT); + WriteIntProperty("border", item->window.border, 0); + WriteFloatProperty("borderSize", item->window.borderSize, 0.0f); + + if (item->visibleExp) + WriteStatementProperty("visible", item->visibleExp, true); + else if (item->window.dynamicFlags[0] & WINDOW_FLAG_VISIBLE) + WriteIntProperty("visible", 1, 0); + + WriteStatementProperty("disabled", item->disabledExp, true); + WriteIntProperty("ownerdraw", item->window.ownerDraw, 0); + WriteFlagsProperty("ownerdrawFlag", item->window.ownerDrawFlags); + WriteIntProperty("align", item->alignment, 0); + WriteIntProperty("textalign", item->textAlignMode, 0); + WriteFloatProperty("textalignx", item->textalignx, 0.0f); + WriteFloatProperty("textaligny", item->textaligny, 0.0f); + WriteFloatProperty("textscale", item->textscale, 0.0f); + WriteIntProperty("textstyle", item->textStyle, 0); + WriteIntProperty("textfont", item->fontEnum, 0); + WriteColorProperty("backcolor", item->window.backColor, COLOR_0000); + WriteColorProperty("forecolor", item->window.foreColor, COLOR_1111); + WriteColorProperty("bordercolor", item->window.borderColor, COLOR_0000); + WriteColorProperty("outlinecolor", item->window.outlineColor, COLOR_0000); + WriteColorProperty("disablecolor", item->window.disableColor, COLOR_0000); + WriteColorProperty("glowcolor", item->glowColor, COLOR_0000); + WriteMaterialProperty("background", item->window.background); + WriteMenuEventHandlerSetProperty("onFocus", item->onFocus); + WriteMenuEventHandlerSetProperty("hasFocus", item->hasFocus); + WriteMenuEventHandlerSetProperty("leaveFocus", item->leaveFocus); + WriteMenuEventHandlerSetProperty("mouseEnter", item->mouseEnter); + WriteMenuEventHandlerSetProperty("mouseExit", item->mouseExit); + WriteMenuEventHandlerSetProperty("mouseEnterText", item->mouseEnterText); + WriteMenuEventHandlerSetProperty("mouseExitText", item->mouseExitText); + WriteMenuEventHandlerSetProperty("action", item->action); + WriteMenuEventHandlerSetProperty("accept", item->accept); + // WriteFloatProperty("special", item->special, 0.0f); + WriteSoundAliasProperty("focusSound", item->focusSound); + WriteStringProperty("dvarTest", item->dvarTest); + + if (item->dvarFlags & ITEM_DVAR_FLAG_ENABLE) + WriteMultiTokenStringProperty("enableDvar", item->enableDvar); + else if (item->dvarFlags & ITEM_DVAR_FLAG_DISABLE) + WriteMultiTokenStringProperty("disableDvar", item->enableDvar); + else if (item->dvarFlags & ITEM_DVAR_FLAG_SHOW) + WriteMultiTokenStringProperty("showDvar", item->enableDvar); + else if (item->dvarFlags & ITEM_DVAR_FLAG_HIDE) + WriteMultiTokenStringProperty("hideDvar", item->enableDvar); + else if (item->dvarFlags & ITEM_DVAR_FLAG_FOCUS) + WriteMultiTokenStringProperty("focusDvar", item->enableDvar); + + WriteItemKeyHandlerProperty(item->onKey); + WriteStatementProperty("exp text", item->textExp, false); + WriteStatementProperty("exp textaligny", item->textAlignYExp, false); + WriteStatementProperty("exp material", item->materialExp, false); + WriteFloatExpressionsProperty(item->floatExpressions, item->floatExpressionCount); + WriteIntProperty("gamemsgwindowindex", item->gameMsgWindowIndex, 0); + WriteIntProperty("gamemsgwindowmode", item->gameMsgWindowMode, 0); + WriteDecodeEffectProperty("decodeEffect", item); + + WriteListBoxProperties(item); + WriteEditFieldProperties(item); + WriteMultiProperties(item); + WriteEnumDvarProperties(item); + WriteTickerProperties(item); + } + + void WriteItemDefs(const itemDef_s* const* itemDefs, size_t itemCount) + { + for (auto i = 0u; i < itemCount; i++) + { + StartItemDefScope(); + + WriteItemData(itemDefs[i]); + + EndScope(); + } + } + + void WriteMenuData(const menuDef_t* menu) + { + WriteStringProperty("name", menu->window.name); + WriteBoolProperty("fullscreen", menu->data->fullScreen, false); + WriteKeywordProperty("screenSpace", menu->window.staticFlags & WINDOW_FLAG_SCREEN_SPACE); + WriteKeywordProperty("decoration", menu->window.staticFlags & WINDOW_FLAG_DECORATION); + WriteRectProperty("rect", menu->window.rect); + WriteIntProperty("style", menu->window.style, 0); + WriteIntProperty("border", menu->window.border, 0); + WriteFloatProperty("borderSize", menu->window.borderSize, 0.0f); + WriteColorProperty("backcolor", menu->window.backColor, COLOR_0000); + WriteColorProperty("forecolor", menu->window.foreColor, COLOR_1111); + WriteColorProperty("bordercolor", menu->window.borderColor, COLOR_0000); + WriteColorProperty("focuscolor", menu->data->focusColor, COLOR_0000); + WriteColorProperty("outlinecolor", menu->window.outlineColor, COLOR_0000); + WriteMaterialProperty("background", menu->window.background); + WriteIntProperty("ownerdraw", menu->window.ownerDraw, 0); + WriteFlagsProperty("ownerdrawFlag", menu->window.ownerDrawFlags); + WriteKeywordProperty("outOfBoundsClick", menu->window.staticFlags & WINDOW_FLAG_OUT_OF_BOUNDS_CLICK); + WriteStringProperty("soundLoop", menu->data->soundName); + WriteKeywordProperty("popup", menu->window.staticFlags & WINDOW_FLAG_POPUP); + WriteFloatProperty("fadeClamp", menu->data->fadeClamp, 0.0f); + WriteIntProperty("fadeCycle", menu->data->fadeCycle, 0); + WriteFloatProperty("fadeAmount", menu->data->fadeAmount, 0.0f); + WriteFloatProperty("fadeInAmount", menu->data->fadeInAmount, 0.0f); + WriteFloatProperty("blurWorld", menu->data->blurRadius, 0.0f); + WriteKeywordProperty("legacySplitScreenScale", menu->window.staticFlags & WINDOW_FLAG_LEGACY_SPLIT_SCREEN_SCALE); + WriteKeywordProperty("hiddenDuringScope", menu->window.staticFlags & WINDOW_FLAG_HIDDEN_DURING_SCOPE); + WriteKeywordProperty("hiddenDuringFlashbang", menu->window.staticFlags & WINDOW_FLAG_HIDDEN_DURING_FLASH_BANG); + WriteKeywordProperty("hiddenDuringUI", menu->window.staticFlags & WINDOW_FLAG_HIDDEN_DURING_UI); + WriteStringProperty("allowedBinding", menu->data->allowedBinding); + WriteKeywordProperty("textOnlyFocus", menu->window.staticFlags & WINDOW_FLAG_TEXT_ONLY_FOCUS); + + if (menu->data->visibleExp) + WriteStatementProperty("visible", menu->data->visibleExp, true); + else if (menu->window.dynamicFlags[0] & WINDOW_FLAG_VISIBLE) + WriteIntProperty("visible", 1, 0); + + WriteStatementProperty("exp rect X", menu->data->rectXExp, false); + WriteStatementProperty("exp rect Y", menu->data->rectYExp, false); + WriteStatementProperty("exp rect W", menu->data->rectWExp, false); + WriteStatementProperty("exp rect H", menu->data->rectHExp, false); + WriteStatementProperty("exp openSound", menu->data->openSoundExp, false); + WriteStatementProperty("exp closeSound", menu->data->closeSoundExp, false); + WriteStatementProperty("exp soundLoop", menu->data->soundLoopExp, false); + WriteMenuEventHandlerSetProperty("onOpen", menu->data->onOpen); + WriteMenuEventHandlerSetProperty("onClose", menu->data->onClose); + WriteMenuEventHandlerSetProperty("onRequestClose", menu->data->onCloseRequest); + WriteMenuEventHandlerSetProperty("onESC", menu->data->onESC); + WriteMenuEventHandlerSetProperty("onFocusDueToClose", menu->data->onFocusDueToClose); + WriteItemKeyHandlerProperty(menu->data->onKey); + WriteItemDefs(menu->items, menu->itemCount); + } + }; +} // namespace + +namespace menu +{ + std::unique_ptr CreateMenuWriterIW5(std::ostream& stream) + { + return std::make_unique(stream); + } +} // namespace menu diff --git a/src/ObjWriting/Game/IW5/Menu/MenuWriterIW5.h b/src/ObjWriting/Game/IW5/Menu/MenuWriterIW5.h new file mode 100644 index 00000000..dbf6428a --- /dev/null +++ b/src/ObjWriting/Game/IW5/Menu/MenuWriterIW5.h @@ -0,0 +1,19 @@ +#pragma once + +#include "Game/IW5/IW5.h" +#include "Menu/IMenuWriter.h" + +#include +#include + +namespace menu +{ + class IWriterIW5 : public IWriter + { + public: + virtual void WriteFunctionDef(const std::string& functionName, const IW5::Statement_s* statement) = 0; + virtual void WriteMenu(const IW5::menuDef_t& menu) = 0; + }; + + std::unique_ptr CreateMenuWriterIW5(std::ostream& stream); +} // namespace menu diff --git a/src/ObjWriting/Game/IW5/ObjWriterIW5.cpp b/src/ObjWriting/Game/IW5/ObjWriterIW5.cpp index 09a16378..4cbd3f31 100644 --- a/src/ObjWriting/Game/IW5/ObjWriterIW5.cpp +++ b/src/ObjWriting/Game/IW5/ObjWriterIW5.cpp @@ -1,21 +1,21 @@ #include "ObjWriterIW5.h" -#include "AssetDumpers/AssetDumperAddonMapEnts.h" -#include "AssetDumpers/AssetDumperGfxImage.h" -#include "AssetDumpers/AssetDumperLeaderboardDef.h" -#include "AssetDumpers/AssetDumperLoadedSound.h" -#include "AssetDumpers/AssetDumperLocalizeEntry.h" -#include "AssetDumpers/AssetDumperMenuDef.h" -#include "AssetDumpers/AssetDumperMenuList.h" -#include "AssetDumpers/AssetDumperRawFile.h" -#include "AssetDumpers/AssetDumperScriptFile.h" -#include "AssetDumpers/AssetDumperStringTable.h" -#include "AssetDumpers/AssetDumperWeapon.h" -#include "AssetDumpers/AssetDumperWeaponAttachment.h" -#include "AssetDumpers/AssetDumperXModel.h" #include "Game/IW5/GameAssetPoolIW5.h" -#include "Material/DumperMaterialIW5.h" +#include "Game/IW5/Material/MaterialJsonDumperIW5.h" +#include "Game/IW5/XModel/XModelDumperIW5.h" +#include "Image/ImageDumperIW5.h" +#include "Leaderboard/LeaderboardJsonDumperIW5.h" +#include "Localize/LocalizeDumperIW5.h" +#include "Maps/AddonMapEntsDumperIW5.h" +#include "Menu/MenuDumperIW5.h" +#include "Menu/MenuListDumperIW5.h" #include "ObjWriting.h" +#include "RawFile/RawFileDumperIW5.h" +#include "Script/ScriptDumperIW5.h" +#include "Sound/LoadedSoundDumperIW5.h" +#include "StringTable/StringTableDumperIW5.h" +#include "Weapon/AttachmentJsonDumperIW5.h" +#include "Weapon/WeaponDumperIW5.h" using namespace IW5; @@ -33,16 +33,16 @@ bool ObjWriter::DumpZone(AssetDumpingContext& context) const // DUMP_ASSET_POOL(AssetDumperPhysCollmap, m_phys_collmap, ASSET_TYPE_PHYSCOLLMAP) // DUMP_ASSET_POOL(AssetDumperXAnimParts, m_xanim_parts, ASSET_TYPE_XANIMPARTS) // DUMP_ASSET_POOL(AssetDumperXModelSurfs, m_xmodel_surfs, ASSET_TYPE_XMODEL_SURFS) - DUMP_ASSET_POOL(AssetDumperXModel, m_xmodel, ASSET_TYPE_XMODEL) - DUMP_ASSET_POOL(AssetDumperMaterial, m_material, ASSET_TYPE_MATERIAL) + DUMP_ASSET_POOL(xmodel::DumperIW5, m_xmodel, ASSET_TYPE_XMODEL) + DUMP_ASSET_POOL(material::JsonDumperIW5, m_material, ASSET_TYPE_MATERIAL) // DUMP_ASSET_POOL(AssetDumperMaterialPixelShader, m_material_pixel_shader, ASSET_TYPE_PIXELSHADER) // DUMP_ASSET_POOL(AssetDumperMaterialVertexShader, m_material_vertex_shader, ASSET_TYPE_VERTEXSHADER) // DUMP_ASSET_POOL(AssetDumperMaterialVertexDeclaration, m_material_vertex_decl, ASSET_TYPE_VERTEXDECL) // DUMP_ASSET_POOL(AssetDumperMaterialTechniqueSet, m_technique_set, ASSET_TYPE_TECHNIQUE_SET) - DUMP_ASSET_POOL(AssetDumperGfxImage, m_image, ASSET_TYPE_IMAGE) + DUMP_ASSET_POOL(image::DumperIW5, m_image, ASSET_TYPE_IMAGE) // DUMP_ASSET_POOL(AssetDumpersnd_alias_list_t, m_sound, ASSET_TYPE_SOUND) // DUMP_ASSET_POOL(AssetDumperSndCurve, m_sound_curve, ASSET_TYPE_SOUND_CURVE) - DUMP_ASSET_POOL(AssetDumperLoadedSound, m_loaded_sound, ASSET_TYPE_LOADED_SOUND) + DUMP_ASSET_POOL(sound::LoadedSoundDumperIW5, m_loaded_sound, ASSET_TYPE_LOADED_SOUND) // DUMP_ASSET_POOL(AssetDumperclipMap_t, m_clip_map, ASSET_TYPE_CLIPMAP) // DUMP_ASSET_POOL(AssetDumperComWorld, m_com_world, ASSET_TYPE_COMWORLD) // DUMP_ASSET_POOL(AssetDumperGlassWorld, m_glass_world, ASSET_TYPE_GLASSWORLD) @@ -53,22 +53,22 @@ bool ObjWriter::DumpZone(AssetDumpingContext& context) const // DUMP_ASSET_POOL(AssetDumperGfxWorld, m_gfx_world, ASSET_TYPE_GFXWORLD) // DUMP_ASSET_POOL(AssetDumperGfxLightDef, m_gfx_light_def, ASSET_TYPE_LIGHT_DEF) // DUMP_ASSET_POOL(AssetDumperFont_s, m_font, ASSET_TYPE_FONT) - DUMP_ASSET_POOL(AssetDumperMenuList, m_menu_list, ASSET_TYPE_MENULIST) - DUMP_ASSET_POOL(AssetDumperMenuDef, m_menu_def, ASSET_TYPE_MENU) - DUMP_ASSET_POOL(AssetDumperLocalizeEntry, m_localize, ASSET_TYPE_LOCALIZE_ENTRY) - DUMP_ASSET_POOL(AssetDumperWeaponAttachment, m_attachment, ASSET_TYPE_ATTACHMENT) - DUMP_ASSET_POOL(AssetDumperWeapon, m_weapon, ASSET_TYPE_WEAPON) + DUMP_ASSET_POOL(menu::MenuListDumperIW5, m_menu_list, ASSET_TYPE_MENULIST) + DUMP_ASSET_POOL(menu::MenuDumperIW5, m_menu_def, ASSET_TYPE_MENU) + DUMP_ASSET_POOL(localize::DumperIW5, m_localize, ASSET_TYPE_LOCALIZE_ENTRY) + DUMP_ASSET_POOL(attachment::JsonDumperIW5, m_attachment, ASSET_TYPE_ATTACHMENT) + DUMP_ASSET_POOL(weapon::DumperIW5, m_weapon, ASSET_TYPE_WEAPON) // DUMP_ASSET_POOL(AssetDumperFxEffectDef, m_fx, ASSET_TYPE_FX) // DUMP_ASSET_POOL(AssetDumperFxImpactTable, m_fx_impact_table, ASSET_TYPE_IMPACT_FX) // DUMP_ASSET_POOL(AssetDumperSurfaceFxTable, m_surface_fx_table, ASSET_TYPE_SURFACE_FX) - DUMP_ASSET_POOL(AssetDumperRawFile, m_raw_file, ASSET_TYPE_RAWFILE) - DUMP_ASSET_POOL(AssetDumperScriptFile, m_script_file, ASSET_TYPE_SCRIPTFILE) - DUMP_ASSET_POOL(AssetDumperStringTable, m_string_table, ASSET_TYPE_STRINGTABLE) - DUMP_ASSET_POOL(AssetDumperLeaderboardDef, m_leaderboard, ASSET_TYPE_LEADERBOARD) + DUMP_ASSET_POOL(raw_file::DumperIW5, m_raw_file, ASSET_TYPE_RAWFILE) + DUMP_ASSET_POOL(script::DumperIW5, m_script_file, ASSET_TYPE_SCRIPTFILE) + DUMP_ASSET_POOL(string_table::DumperIW5, m_string_table, ASSET_TYPE_STRINGTABLE) + DUMP_ASSET_POOL(leaderboard::JsonDumperIW5, m_leaderboard, ASSET_TYPE_LEADERBOARD) // DUMP_ASSET_POOL(AssetDumperStructuredDataDefSet, m_structed_data_def_set, ASSET_TYPE_STRUCTURED_DATA_DEF) // DUMP_ASSET_POOL(AssetDumperTracerDef, m_tracer, ASSET_TYPE_TRACER) // DUMP_ASSET_POOL(AssetDumperVehicleDef, m_vehicle, ASSET_TYPE_VEHICLE) - DUMP_ASSET_POOL(AssetDumperAddonMapEnts, m_addon_map_ents, ASSET_TYPE_ADDON_MAP_ENTS) + DUMP_ASSET_POOL(addon_map_ents::DumperIW5, m_addon_map_ents, ASSET_TYPE_ADDON_MAP_ENTS) return true; diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperRawFile.cpp b/src/ObjWriting/Game/IW5/RawFile/RawFileDumperIW5.cpp similarity index 61% rename from src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperRawFile.cpp rename to src/ObjWriting/Game/IW5/RawFile/RawFileDumperIW5.cpp index a1669136..71ca717b 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperRawFile.cpp +++ b/src/ObjWriting/Game/IW5/RawFile/RawFileDumperIW5.cpp @@ -1,29 +1,31 @@ -#include "AssetDumperRawFile.h" +#include "RawFileDumperIW5.h" #include #include #include -using namespace IW4; +using namespace IW5; -bool AssetDumperRawFile::ShouldDump(XAssetInfo* asset) +namespace raw_file { - return true; -} - -void AssetDumperRawFile::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* rawFile = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - if (rawFile->compressedLen > 0) + bool DumperIW5::ShouldDump(XAssetInfo* asset) { - z_stream_s zs{}; + return true; + } + void DumperIW5::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* rawFile = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name); + + if (!assetFile) + return; + + auto& stream = *assetFile; + if (rawFile->compressedLen <= 0) + return; + + z_stream_s zs{}; zs.zalloc = Z_NULL; zs.zfree = Z_NULL; zs.opaque = Z_NULL; @@ -37,7 +39,7 @@ void AssetDumperRawFile::DumpAsset(AssetDumpingContext& context, XAssetInfo(rawFile->data.compressedBuffer); + zs.next_in = reinterpret_cast(rawFile->buffer); zs.avail_in = rawFile->compressedLen; Bytef buffer[0x1000]; @@ -60,8 +62,4 @@ void AssetDumperRawFile::DumpAsset(AssetDumpingContext& context, XAssetInfolen > 0) - { - stream.write(rawFile->data.buffer, rawFile->len); - } -} +} // namespace raw_file diff --git a/src/ObjWriting/Game/IW5/RawFile/RawFileDumperIW5.h b/src/ObjWriting/Game/IW5/RawFile/RawFileDumperIW5.h new file mode 100644 index 00000000..ed2ceb4f --- /dev/null +++ b/src/ObjWriting/Game/IW5/RawFile/RawFileDumperIW5.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW5/IW5.h" + +namespace raw_file +{ + class DumperIW5 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace raw_file diff --git a/src/ObjWriting/Game/IW5/Script/ScriptDumperIW5.cpp b/src/ObjWriting/Game/IW5/Script/ScriptDumperIW5.cpp new file mode 100644 index 00000000..d334cb1c --- /dev/null +++ b/src/ObjWriting/Game/IW5/Script/ScriptDumperIW5.cpp @@ -0,0 +1,33 @@ +#include "ScriptDumperIW5.h" + +using namespace IW5; + +namespace script +{ + bool DumperIW5::ShouldDump(XAssetInfo* asset) + { + return true; + } + + // See https://github.com/xensik/gsc-tool#file-format for an in-depth explanation about the .gscbin format + void DumperIW5::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + auto* scriptFile = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name + ".gscbin"); + + if (!assetFile) + return; + + auto& stream = *assetFile; + + // Dump the name and the numeric fields + stream.write(asset->m_name.c_str(), asset->m_name.size() + 1); + stream.write(reinterpret_cast(&scriptFile->compressedLen), sizeof(scriptFile->compressedLen)); + stream.write(reinterpret_cast(&scriptFile->len), sizeof(scriptFile->len)); + stream.write(reinterpret_cast(&scriptFile->bytecodeLen), sizeof(scriptFile->bytecodeLen)); + + // Dump the buffers + stream.write(scriptFile->buffer, scriptFile->compressedLen); + stream.write(reinterpret_cast(scriptFile->bytecode), scriptFile->bytecodeLen); + } +} // namespace script diff --git a/src/ObjWriting/Game/IW5/Script/ScriptDumperIW5.h b/src/ObjWriting/Game/IW5/Script/ScriptDumperIW5.h new file mode 100644 index 00000000..e1220f5f --- /dev/null +++ b/src/ObjWriting/Game/IW5/Script/ScriptDumperIW5.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW5/IW5.h" + +namespace script +{ + class DumperIW5 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace script diff --git a/src/ObjWriting/Game/IW5/Sound/LoadedSoundDumperIW5.cpp b/src/ObjWriting/Game/IW5/Sound/LoadedSoundDumperIW5.cpp new file mode 100644 index 00000000..8deec609 --- /dev/null +++ b/src/ObjWriting/Game/IW5/Sound/LoadedSoundDumperIW5.cpp @@ -0,0 +1,52 @@ +#include "LoadedSoundDumperIW5.h" + +#include "Sound/WavTypes.h" +#include "Sound/WavWriter.h" + +#include + +using namespace IW5; + +namespace +{ + void DumpWavPcm(const LoadedSound* asset, std::ostream& stream) + { + const WavWriter writer(stream); + + const WavMetaData metaData{.channelCount = static_cast(asset->sound.info.channels), + .samplesPerSec = static_cast(asset->sound.info.rate), + .bitsPerSample = static_cast(asset->sound.info.bits)}; + + writer.WritePcmHeader(metaData, asset->sound.info.data_len); + writer.WritePcmData(asset->sound.data, asset->sound.info.data_len); + } +} // namespace + +namespace sound +{ + bool LoadedSoundDumperIW5::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void LoadedSoundDumperIW5::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* loadedSound = asset->Asset(); + const auto assetFile = context.OpenAssetFile(std::format("sound/{}", asset->m_name)); + + if (!assetFile) + return; + + auto& stream = *assetFile; + switch (static_cast(loadedSound->sound.info.format)) + { + case WavFormat::PCM: + DumpWavPcm(loadedSound, stream); + break; + + default: + std::cerr << std::format("Unknown format {} for loaded sound: {}\n", loadedSound->sound.info.format, loadedSound->name); + break; + } + } +} // namespace sound diff --git a/src/ObjWriting/Game/IW5/Sound/LoadedSoundDumperIW5.h b/src/ObjWriting/Game/IW5/Sound/LoadedSoundDumperIW5.h new file mode 100644 index 00000000..8079f27d --- /dev/null +++ b/src/ObjWriting/Game/IW5/Sound/LoadedSoundDumperIW5.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW5/IW5.h" + +namespace sound +{ + class LoadedSoundDumperIW5 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace sound diff --git a/src/ObjWriting/Game/IW5/StringTable/StringTableDumperIW5.cpp b/src/ObjWriting/Game/IW5/StringTable/StringTableDumperIW5.cpp new file mode 100644 index 00000000..2bd7fa00 --- /dev/null +++ b/src/ObjWriting/Game/IW5/StringTable/StringTableDumperIW5.cpp @@ -0,0 +1,42 @@ +#include "StringTableDumperIW5.h" + +#include "Csv/CsvStream.h" + +using namespace IW5; + +namespace string_table +{ + bool DumperIW5::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperIW5::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* stringTable = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name); + + if (!assetFile) + return; + + CsvOutputStream csv(*assetFile); + + for (auto row = 0; row < stringTable->rowCount; row++) + { + for (auto column = 0; column < stringTable->columnCount; column++) + { + const auto* cell = &stringTable->values[column + row * stringTable->columnCount]; + if (cell->string != nullptr) + { + csv.WriteColumn(cell->string); + } + else + { + csv.WriteColumn(""); + } + } + + csv.NextRow(); + } + } +} // namespace string_table diff --git a/src/ObjWriting/Game/IW5/StringTable/StringTableDumperIW5.h b/src/ObjWriting/Game/IW5/StringTable/StringTableDumperIW5.h new file mode 100644 index 00000000..e826dfd0 --- /dev/null +++ b/src/ObjWriting/Game/IW5/StringTable/StringTableDumperIW5.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW5/IW5.h" + +namespace string_table +{ + class DumperIW5 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace string_table diff --git a/src/ObjWriting/Game/IW5/Weapon/JsonWeaponAttachmentWriter.cpp b/src/ObjWriting/Game/IW5/Weapon/AttachmentJsonDumperIW5.cpp similarity index 97% rename from src/ObjWriting/Game/IW5/Weapon/JsonWeaponAttachmentWriter.cpp rename to src/ObjWriting/Game/IW5/Weapon/AttachmentJsonDumperIW5.cpp index 69f50071..c44f99a2 100644 --- a/src/ObjWriting/Game/IW5/Weapon/JsonWeaponAttachmentWriter.cpp +++ b/src/ObjWriting/Game/IW5/Weapon/AttachmentJsonDumperIW5.cpp @@ -1,7 +1,8 @@ -#include "JsonWeaponAttachmentWriter.h" +#include "AttachmentJsonDumperIW5.h" #include "Game/IW5/CommonIW5.h" #include "Game/IW5/Weapon/JsonWeaponAttachment.h" +#include "Weapon/AttachmentCommon.h" #include #include @@ -11,10 +12,10 @@ using namespace IW5; namespace { - class JsonDumper + class JsonDumperImpl { public: - JsonDumper(AssetDumpingContext& context, std::ostream& stream) + JsonDumperImpl(AssetDumpingContext& context, std::ostream& stream) : m_stream(stream) { } @@ -392,11 +393,21 @@ namespace }; } // namespace -namespace IW5 +namespace attachment { - void DumpWeaponAttachmentAsJson(std::ostream& stream, const WeaponAttachment* attachment, AssetDumpingContext& context) + bool JsonDumperIW5::ShouldDump(XAssetInfo* asset) { - const JsonDumper dumper(context, stream); - dumper.Dump(attachment); + return true; } -} // namespace IW5 + + void JsonDumperIW5::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto assetFile = context.OpenAssetFile(GetJsonFileNameForAssetName(asset->m_name)); + + if (!assetFile) + return; + + const JsonDumperImpl dumper(context, *assetFile); + dumper.Dump(asset->Asset()); + } +} // namespace attachment diff --git a/src/ObjWriting/Game/IW5/Weapon/AttachmentJsonDumperIW5.h b/src/ObjWriting/Game/IW5/Weapon/AttachmentJsonDumperIW5.h new file mode 100644 index 00000000..81088a63 --- /dev/null +++ b/src/ObjWriting/Game/IW5/Weapon/AttachmentJsonDumperIW5.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW5/IW5.h" + +namespace attachment +{ + class JsonDumperIW5 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace attachment diff --git a/src/ObjWriting/Game/IW5/Weapon/JsonWeaponAttachmentWriter.h b/src/ObjWriting/Game/IW5/Weapon/JsonWeaponAttachmentWriter.h deleted file mode 100644 index dc0a84c2..00000000 --- a/src/ObjWriting/Game/IW5/Weapon/JsonWeaponAttachmentWriter.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "Dumping/AssetDumpingContext.h" -#include "Game/IW5/IW5.h" - -#include - -namespace IW5 -{ - void DumpWeaponAttachmentAsJson(std::ostream& stream, const WeaponAttachment* attachment, AssetDumpingContext& context); -} // namespace IW5 diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperWeapon.cpp b/src/ObjWriting/Game/IW5/Weapon/WeaponDumperIW5.cpp similarity index 68% rename from src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperWeapon.cpp rename to src/ObjWriting/Game/IW5/Weapon/WeaponDumperIW5.cpp index 83e4cc93..67ab7628 100644 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperWeapon.cpp +++ b/src/ObjWriting/Game/IW5/Weapon/WeaponDumperIW5.cpp @@ -1,10 +1,11 @@ -#include "AssetDumperWeapon.h" +#include "WeaponDumperIW5.h" #include "Game/IW5/CommonIW5.h" #include "Game/IW5/InfoString/InfoStringFromStructConverter.h" #include "Game/IW5/ObjConstantsIW5.h" #include "Game/IW5/Weapon/WeaponFields.h" #include "Weapon/AccuracyGraphWriter.h" +#include "Weapon/WeaponCommon.h" #include #include @@ -15,7 +16,7 @@ using namespace IW5; -namespace IW5 +namespace { class InfoStringFromWeaponConverter final : public InfoStringFromStructConverter { @@ -551,211 +552,217 @@ namespace IW5 return graph; } -} // namespace IW5 -void AssetDumperWeapon::CopyToFullDef(const WeaponCompleteDef* weapon, WeaponFullDef* fullDef) -{ - fullDef->weapCompleteDef = *weapon; - - if (weapon->weapDef) + void CopyToFullDef(const WeaponCompleteDef* weapon, WeaponFullDef* fullDef) { - fullDef->weapDef = *weapon->weapDef; - fullDef->weapCompleteDef.weapDef = &fullDef->weapDef; + fullDef->weapCompleteDef = *weapon; + + if (weapon->weapDef) + { + fullDef->weapDef = *weapon->weapDef; + fullDef->weapCompleteDef.weapDef = &fullDef->weapDef; + } + + if (weapon->hideTags) + { + memcpy(fullDef->hideTags, weapon->hideTags, sizeof(scr_string_t) * std::extent_v); + fullDef->weapCompleteDef.hideTags = fullDef->hideTags; + } + + if (weapon->szXAnims) + { + static_assert(std::extent_v == WEAP_ANIM_COUNT); + memcpy(fullDef->szXAnims, weapon->szXAnims, sizeof(void*) * WEAP_ANIM_COUNT); + fullDef->weapCompleteDef.szXAnims = fullDef->szXAnims; + } + + if (fullDef->weapDef.gunXModel) + { + memcpy(fullDef->gunXModel, fullDef->weapDef.gunXModel, sizeof(void*) * std::extent_v); + fullDef->weapDef.gunXModel = fullDef->gunXModel; + } + + if (fullDef->weapDef.szXAnimsRightHanded) + { + static_assert(std::extent_v == WEAP_ANIM_COUNT); + memcpy(fullDef->szXAnimsRightHanded, fullDef->weapDef.szXAnimsRightHanded, sizeof(void*) * WEAP_ANIM_COUNT); + fullDef->weapDef.szXAnimsRightHanded = fullDef->szXAnimsRightHanded; + } + + if (fullDef->weapDef.szXAnimsLeftHanded) + { + static_assert(std::extent_v == WEAP_ANIM_COUNT); + memcpy(fullDef->szXAnimsLeftHanded, fullDef->weapDef.szXAnimsLeftHanded, sizeof(void*) * WEAP_ANIM_COUNT); + fullDef->weapDef.szXAnimsLeftHanded = fullDef->szXAnimsLeftHanded; + } + + if (fullDef->weapDef.notetrackSoundMapKeys) + { + memcpy(fullDef->notetrackSoundMapKeys, + fullDef->weapDef.notetrackSoundMapKeys, + sizeof(scr_string_t) * std::extent_v); + fullDef->weapDef.notetrackSoundMapKeys = fullDef->notetrackSoundMapKeys; + } + + if (fullDef->weapDef.notetrackSoundMapValues) + { + memcpy(fullDef->notetrackSoundMapValues, + fullDef->weapDef.notetrackSoundMapValues, + sizeof(scr_string_t) * std::extent_v); + fullDef->weapDef.notetrackSoundMapValues = fullDef->notetrackSoundMapValues; + } + + if (fullDef->weapDef.notetrackRumbleMapKeys) + { + memcpy(fullDef->notetrackRumbleMapKeys, + fullDef->weapDef.notetrackRumbleMapKeys, + sizeof(scr_string_t) * std::extent_v); + fullDef->weapDef.notetrackRumbleMapKeys = fullDef->notetrackRumbleMapKeys; + } + + if (fullDef->weapDef.notetrackRumbleMapValues) + { + memcpy(fullDef->notetrackRumbleMapValues, + fullDef->weapDef.notetrackRumbleMapValues, + sizeof(scr_string_t) * std::extent_v); + fullDef->weapDef.notetrackRumbleMapValues = fullDef->notetrackRumbleMapValues; + } + + if (fullDef->weapDef.worldModel) + { + memcpy(fullDef->worldModel, fullDef->weapDef.worldModel, sizeof(void*) * std::extent_v); + fullDef->weapDef.worldModel = fullDef->worldModel; + } + + if (fullDef->weapDef.parallelBounce) + { + static_assert(std::extent_v == SURF_TYPE_COUNT); + assert(sizeof(WeaponFullDef::parallelBounce) >= sizeof(float) * std::extent_v); + memcpy(fullDef->parallelBounce, fullDef->weapDef.parallelBounce, sizeof(float) * std::extent_v); + fullDef->weapDef.parallelBounce = fullDef->parallelBounce; + } + + if (fullDef->weapDef.perpendicularBounce) + { + static_assert(std::extent_v == SURF_TYPE_COUNT); + assert(sizeof(WeaponFullDef::perpendicularBounce) >= sizeof(float) * std::extent_v); + memcpy(fullDef->perpendicularBounce, + fullDef->weapDef.perpendicularBounce, + sizeof(float) * std::extent_v); + fullDef->weapDef.perpendicularBounce = fullDef->perpendicularBounce; + } + + if (fullDef->weapDef.locationDamageMultipliers) + { + static_assert(std::extent_v == HITLOC_COUNT); + assert(sizeof(WeaponFullDef::locationDamageMultipliers) >= sizeof(float) * std::extent_v); + memcpy(fullDef->locationDamageMultipliers, + fullDef->weapDef.locationDamageMultipliers, + sizeof(float) * std::extent_v); + fullDef->weapDef.locationDamageMultipliers = fullDef->locationDamageMultipliers; + } + + if (fullDef->weapCompleteDef.scopes) + { + memcpy(fullDef->scopes, fullDef->weapCompleteDef.scopes, sizeof(void*) * std::extent_v); + fullDef->weapCompleteDef.scopes = fullDef->scopes; + } + + if (fullDef->weapCompleteDef.underBarrels) + { + memcpy(fullDef->underBarrels, fullDef->weapCompleteDef.underBarrels, sizeof(void*) * std::extent_v); + fullDef->weapCompleteDef.underBarrels = fullDef->underBarrels; + } + + if (fullDef->weapCompleteDef.others) + { + memcpy(fullDef->others, fullDef->weapCompleteDef.others, sizeof(void*) * std::extent_v); + fullDef->weapCompleteDef.others = fullDef->others; + } } - if (weapon->hideTags) + InfoString CreateInfoString(XAssetInfo* asset) { - memcpy(fullDef->hideTags, weapon->hideTags, sizeof(scr_string_t) * std::extent_v); - fullDef->weapCompleteDef.hideTags = fullDef->hideTags; + const auto fullDef = std::make_unique(); + memset(fullDef.get(), 0, sizeof(WeaponFullDef)); + CopyToFullDef(asset->Asset(), fullDef.get()); + + InfoStringFromWeaponConverter converter(fullDef.get(), + weapon_fields, + std::extent_v, + [asset](const scr_string_t scrStr) -> std::string + { + assert(scrStr < asset->m_zone->m_script_strings.Count()); + if (scrStr >= asset->m_zone->m_script_strings.Count()) + return ""; + + return asset->m_zone->m_script_strings[scrStr]; + }); + + return converter.Convert(); } - if (weapon->szXAnims) + void DumpAccuracyGraphs(AssetDumpingContext& context, XAssetInfo* asset) { - static_assert(std::extent_v == WEAP_ANIM_COUNT); - memcpy(fullDef->szXAnims, weapon->szXAnims, sizeof(void*) * WEAP_ANIM_COUNT); - fullDef->weapCompleteDef.szXAnims = fullDef->szXAnims; - } + auto* accuracyGraphWriter = context.GetZoneAssetDumperState(); + const auto weapon = asset->Asset(); + const auto* weapDef = weapon->weapDef; - if (fullDef->weapDef.gunXModel) - { - memcpy(fullDef->gunXModel, fullDef->weapDef.gunXModel, sizeof(void*) * std::extent_v); - fullDef->weapDef.gunXModel = fullDef->gunXModel; - } - - if (fullDef->weapDef.szXAnimsRightHanded) - { - static_assert(std::extent_v == WEAP_ANIM_COUNT); - memcpy(fullDef->szXAnimsRightHanded, fullDef->weapDef.szXAnimsRightHanded, sizeof(void*) * WEAP_ANIM_COUNT); - fullDef->weapDef.szXAnimsRightHanded = fullDef->szXAnimsRightHanded; - } - - if (fullDef->weapDef.szXAnimsLeftHanded) - { - static_assert(std::extent_v == WEAP_ANIM_COUNT); - memcpy(fullDef->szXAnimsLeftHanded, fullDef->weapDef.szXAnimsLeftHanded, sizeof(void*) * WEAP_ANIM_COUNT); - fullDef->weapDef.szXAnimsLeftHanded = fullDef->szXAnimsLeftHanded; - } - - if (fullDef->weapDef.notetrackSoundMapKeys) - { - memcpy(fullDef->notetrackSoundMapKeys, - fullDef->weapDef.notetrackSoundMapKeys, - sizeof(scr_string_t) * std::extent_v); - fullDef->weapDef.notetrackSoundMapKeys = fullDef->notetrackSoundMapKeys; - } - - if (fullDef->weapDef.notetrackSoundMapValues) - { - memcpy(fullDef->notetrackSoundMapValues, - fullDef->weapDef.notetrackSoundMapValues, - sizeof(scr_string_t) * std::extent_v); - fullDef->weapDef.notetrackSoundMapValues = fullDef->notetrackSoundMapValues; - } - - if (fullDef->weapDef.notetrackRumbleMapKeys) - { - memcpy(fullDef->notetrackRumbleMapKeys, - fullDef->weapDef.notetrackRumbleMapKeys, - sizeof(scr_string_t) * std::extent_v); - fullDef->weapDef.notetrackRumbleMapKeys = fullDef->notetrackRumbleMapKeys; - } - - if (fullDef->weapDef.notetrackRumbleMapValues) - { - memcpy(fullDef->notetrackRumbleMapValues, - fullDef->weapDef.notetrackRumbleMapValues, - sizeof(scr_string_t) * std::extent_v); - fullDef->weapDef.notetrackRumbleMapValues = fullDef->notetrackRumbleMapValues; - } - - if (fullDef->weapDef.worldModel) - { - memcpy(fullDef->worldModel, fullDef->weapDef.worldModel, sizeof(void*) * std::extent_v); - fullDef->weapDef.worldModel = fullDef->worldModel; - } - - if (fullDef->weapDef.parallelBounce) - { - static_assert(std::extent_v == SURF_TYPE_COUNT); - assert(sizeof(WeaponFullDef::parallelBounce) >= sizeof(float) * std::extent_v); - memcpy(fullDef->parallelBounce, fullDef->weapDef.parallelBounce, sizeof(float) * std::extent_v); - fullDef->weapDef.parallelBounce = fullDef->parallelBounce; - } - - if (fullDef->weapDef.perpendicularBounce) - { - static_assert(std::extent_v == SURF_TYPE_COUNT); - assert(sizeof(WeaponFullDef::perpendicularBounce) >= sizeof(float) * std::extent_v); - memcpy(fullDef->perpendicularBounce, fullDef->weapDef.perpendicularBounce, sizeof(float) * std::extent_v); - fullDef->weapDef.perpendicularBounce = fullDef->perpendicularBounce; - } - - if (fullDef->weapDef.locationDamageMultipliers) - { - static_assert(std::extent_v == HITLOC_COUNT); - assert(sizeof(WeaponFullDef::locationDamageMultipliers) >= sizeof(float) * std::extent_v); - memcpy(fullDef->locationDamageMultipliers, - fullDef->weapDef.locationDamageMultipliers, - sizeof(float) * std::extent_v); - fullDef->weapDef.locationDamageMultipliers = fullDef->locationDamageMultipliers; - } - - if (fullDef->weapCompleteDef.scopes) - { - memcpy(fullDef->scopes, fullDef->weapCompleteDef.scopes, sizeof(void*) * std::extent_v); - fullDef->weapCompleteDef.scopes = fullDef->scopes; - } - - if (fullDef->weapCompleteDef.underBarrels) - { - memcpy(fullDef->underBarrels, fullDef->weapCompleteDef.underBarrels, sizeof(void*) * std::extent_v); - fullDef->weapCompleteDef.underBarrels = fullDef->underBarrels; - } - - if (fullDef->weapCompleteDef.others) - { - memcpy(fullDef->others, fullDef->weapCompleteDef.others, sizeof(void*) * std::extent_v); - fullDef->weapCompleteDef.others = fullDef->others; - } -} - -InfoString AssetDumperWeapon::CreateInfoString(XAssetInfo* asset) -{ - const auto fullDef = std::make_unique(); - memset(fullDef.get(), 0, sizeof(WeaponFullDef)); - CopyToFullDef(asset->Asset(), fullDef.get()); - - InfoStringFromWeaponConverter converter(fullDef.get(), - weapon_fields, - std::extent_v, - [asset](const scr_string_t scrStr) -> std::string - { - assert(scrStr < asset->m_zone->m_script_strings.Count()); - if (scrStr >= asset->m_zone->m_script_strings.Count()) - return ""; - - return asset->m_zone->m_script_strings[scrStr]; - }); - - return converter.Convert(); -} - -void AssetDumperWeapon::DumpAccuracyGraphs(AssetDumpingContext& context, XAssetInfo* asset) -{ - auto* accuracyGraphWriter = context.GetZoneAssetDumperState(); - const auto weapon = asset->Asset(); - const auto* weapDef = weapon->weapDef; - - if (!weapDef) - return; - - if (weapDef->aiVsAiAccuracyGraphName && weapDef->originalAiVsAiAccuracyGraphKnots - && accuracyGraphWriter->ShouldDumpAiVsAiGraph(weapDef->aiVsAiAccuracyGraphName)) - { - AccuracyGraphWriter::DumpAiVsAiGraph( - context, - ConvertAccuracyGraph(weapDef->aiVsAiAccuracyGraphName, weapDef->originalAiVsAiAccuracyGraphKnots, weapDef->originalAiVsAiAccuracyGraphKnotCount)); - } - - if (weapDef->aiVsPlayerAccuracyGraphName && weapDef->originalAiVsPlayerAccuracyGraphKnots - && accuracyGraphWriter->ShouldDumpAiVsPlayerGraph(weapDef->aiVsPlayerAccuracyGraphName)) - { - AccuracyGraphWriter::DumpAiVsPlayerGraph(context, - ConvertAccuracyGraph(weapDef->aiVsPlayerAccuracyGraphName, - weapDef->originalAiVsPlayerAccuracyGraphKnots, - weapDef->originalAiVsPlayerAccuracyGraphKnotCount)); - } -} - -bool AssetDumperWeapon::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperWeapon::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - // TODO: only dump infostring fields when non-default - - // Only dump raw when no gdt available - if (context.m_gdt) - { - const auto infoString = CreateInfoString(asset); - GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_WEAPON); - infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_WEAPON, gdtEntry); - context.m_gdt->WriteEntry(gdtEntry); - } - else - { - const auto assetFile = context.OpenAssetFile("weapons/" + asset->m_name); - - if (!assetFile) + if (!weapDef) return; - auto& stream = *assetFile; - const auto infoString = CreateInfoString(asset); - const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_WEAPON); - stream.write(stringValue.c_str(), stringValue.size()); + if (weapDef->aiVsAiAccuracyGraphName && weapDef->originalAiVsAiAccuracyGraphKnots + && accuracyGraphWriter->ShouldDumpAiVsAiGraph(weapDef->aiVsAiAccuracyGraphName)) + { + AccuracyGraphWriter::DumpAiVsAiGraph(context, + ConvertAccuracyGraph(weapDef->aiVsAiAccuracyGraphName, + weapDef->originalAiVsAiAccuracyGraphKnots, + weapDef->originalAiVsAiAccuracyGraphKnotCount)); + } + + if (weapDef->aiVsPlayerAccuracyGraphName && weapDef->originalAiVsPlayerAccuracyGraphKnots + && accuracyGraphWriter->ShouldDumpAiVsPlayerGraph(weapDef->aiVsPlayerAccuracyGraphName)) + { + AccuracyGraphWriter::DumpAiVsPlayerGraph(context, + ConvertAccuracyGraph(weapDef->aiVsPlayerAccuracyGraphName, + weapDef->originalAiVsPlayerAccuracyGraphKnots, + weapDef->originalAiVsPlayerAccuracyGraphKnotCount)); + } + } +} // namespace + +namespace weapon +{ + bool DumperIW5::ShouldDump(XAssetInfo* asset) + { + return true; } - DumpAccuracyGraphs(context, asset); -} + void DumperIW5::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + // TODO: only dump infostring fields when non-default + + // Only dump raw when no gdt available + if (context.m_gdt) + { + const auto infoString = CreateInfoString(asset); + GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_WEAPON); + infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_WEAPON, gdtEntry); + context.m_gdt->WriteEntry(gdtEntry); + } + else + { + const auto assetFile = context.OpenAssetFile(GetFileNameForAssetName(asset->m_name)); + + if (!assetFile) + return; + + auto& stream = *assetFile; + const auto infoString = CreateInfoString(asset); + const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_WEAPON); + stream.write(stringValue.c_str(), stringValue.size()); + } + + DumpAccuracyGraphs(context, asset); + } +} // namespace weapon diff --git a/src/ObjWriting/Game/IW5/Weapon/WeaponDumperIW5.h b/src/ObjWriting/Game/IW5/Weapon/WeaponDumperIW5.h new file mode 100644 index 00000000..3e80c669 --- /dev/null +++ b/src/ObjWriting/Game/IW5/Weapon/WeaponDumperIW5.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/IW5/IW5.h" +#include "InfoString/InfoString.h" + +namespace weapon +{ + class DumperIW5 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace weapon diff --git a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperGfxImage.h b/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperGfxImage.h deleted file mode 100644 index b9f89b36..00000000 --- a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperGfxImage.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T5/T5.h" -#include "Image/IImageWriter.h" - -#include - -namespace T5 -{ - class AssetDumperGfxImage final : public AbstractAssetDumper - { - std::unique_ptr m_writer; - - [[nodiscard]] std::string GetAssetFileName(const XAssetInfo& asset) const; - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - - public: - AssetDumperGfxImage(); - }; -} // namespace T5 diff --git a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperLocalizeEntry.cpp b/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperLocalizeEntry.cpp deleted file mode 100644 index 0377f5cf..00000000 --- a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperLocalizeEntry.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "AssetDumperLocalizeEntry.h" - -#include "Dumping/Localize/StringFileDumper.h" -#include "Localize/LocalizeCommon.h" - -#include -#include - -using namespace T5; - -void AssetDumperLocalizeEntry::DumpPool(AssetDumpingContext& context, AssetPool* pool) -{ - if (pool->m_asset_lookup.empty()) - return; - - const auto language = LocalizeCommon::GetNameOfLanguage(context.m_zone.m_language); - const auto assetFile = context.OpenAssetFile(std::format("{}/localizedstrings/{}.str", language, context.m_zone.m_name)); - - if (assetFile) - { - StringFileDumper stringFileDumper(context.m_zone, *assetFile); - - stringFileDumper.SetLanguageName(language); - - // Magic string. Original string files do have this config file. The purpose of the config file is unknown though. - stringFileDumper.SetConfigFile(R"(C:/projects/cod/t5/bin/StringEd.cfg)"); - - stringFileDumper.SetNotes(""); - - for (auto* localizeEntry : *pool) - { - stringFileDumper.WriteLocalizeEntry(localizeEntry->m_name, localizeEntry->Asset()->value); - } - - stringFileDumper.Finalize(); - } - else - { - std::cerr << std::format("Could not create string file for dumping localized strings of zone '{}'\n", context.m_zone.m_name); - } -} diff --git a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperLocalizeEntry.h b/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperLocalizeEntry.h deleted file mode 100644 index e4aec7e8..00000000 --- a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperLocalizeEntry.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T5/T5.h" - -namespace T5 -{ - class AssetDumperLocalizeEntry final : public IAssetDumper - { - public: - void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; - }; -} // namespace T5 diff --git a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperPhysConstraints.cpp b/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperPhysConstraints.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperPhysConstraints.h b/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperPhysConstraints.h deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperPhysPreset.cpp b/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperPhysPreset.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperPhysPreset.h b/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperPhysPreset.h deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperRawFile.cpp b/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperRawFile.cpp deleted file mode 100644 index 45827890..00000000 --- a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperRawFile.cpp +++ /dev/null @@ -1,114 +0,0 @@ -#include "AssetDumperRawFile.h" - -#include -#include -#include - -using namespace T5; - -namespace fs = std::filesystem; - -void AssetDumperRawFile::DumpGsc(AssetDumpingContext& context, XAssetInfo* asset, std::ostream& stream) -{ - const auto* rawFile = asset->Asset(); - - if (rawFile->len <= 8) - { - std::cout << "Invalid len of gsc file \"" << rawFile->name << "\"\n"; - return; - } - - const auto outLen = reinterpret_cast(rawFile->buffer)[0]; - const auto inLen = reinterpret_cast(rawFile->buffer)[1]; - - assert(inLen == static_cast(rawFile->len) - 8); - - if (inLen > static_cast(rawFile->len - 8) + 1) - { - std::cout << "Invalid compression of gsc file \"" << rawFile->name << "\": " << inLen << "\n"; - return; - } - - if (outLen > GSC_MAX_SIZE) - { - std::cout << "Invalid size of gsc file \"" << rawFile->name << "\": " << outLen << "\n"; - return; - } - - z_stream_s zs{}; - - zs.zalloc = Z_NULL; - zs.zfree = Z_NULL; - zs.opaque = Z_NULL; - zs.avail_in = 0; - zs.next_in = Z_NULL; - - int ret = inflateInit(&zs); - - if (ret != Z_OK) - { - throw std::runtime_error("Initializing inflate failed"); - } - - zs.next_in = reinterpret_cast(&rawFile->buffer[8]); - zs.avail_in = inLen; - - Bytef buffer[0x1000]; - - size_t writtenSize = 0; - while (zs.avail_in > 0) - { - zs.next_out = buffer; - zs.avail_out = sizeof(buffer); - ret = inflate(&zs, Z_SYNC_FLUSH); - - if (ret < 0) - { - std::cout << "Inflate failed for dumping gsc file \"" << rawFile->name << "\"\n"; - inflateEnd(&zs); - return; - } - - const auto inflateOutSize = sizeof(buffer) - zs.avail_out; - - if (writtenSize + inflateOutSize >= outLen) - { - // Last byte is a \0 byte. Skip it. - stream.write(reinterpret_cast(buffer), inflateOutSize - 1); - } - else - { - stream.write(reinterpret_cast(buffer), inflateOutSize); - } - writtenSize += inflateOutSize; - } - - inflateEnd(&zs); -} - -bool AssetDumperRawFile::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperRawFile::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* rawFile = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - const fs::path rawFilePath(rawFile->name); - const auto extension = rawFilePath.extension().string(); - - if (extension == ".gsc" || extension == ".csc") - { - DumpGsc(context, asset, stream); - } - else - { - stream.write(rawFile->buffer, rawFile->len); - } -} diff --git a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperRawFile.h b/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperRawFile.h deleted file mode 100644 index b2d10763..00000000 --- a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperRawFile.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T5/T5.h" - -namespace T5 -{ - class AssetDumperRawFile final : public AbstractAssetDumper - { - constexpr static size_t GSC_MAX_SIZE = 0xC000000; - - static void DumpGsc(AssetDumpingContext& context, XAssetInfo* asset, std::ostream& stream); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T5 diff --git a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperSndBank.cpp b/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperSndBank.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperSndBank.h b/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperSndBank.h deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperStringTable.cpp b/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperStringTable.cpp deleted file mode 100644 index 77899c6f..00000000 --- a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperStringTable.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "AssetDumperStringTable.h" - -#include "Csv/CsvStream.h" - -using namespace T5; - -bool AssetDumperStringTable::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperStringTable::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* stringTable = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name); - - if (!assetFile) - return; - - CsvOutputStream csv(*assetFile); - - for (auto row = 0; row < stringTable->rowCount; row++) - { - for (auto column = 0; column < stringTable->columnCount; column++) - { - const auto* cell = &stringTable->values[column + row * stringTable->columnCount]; - if (cell->string != nullptr) - { - csv.WriteColumn(cell->string); - } - else - { - csv.WriteColumn(""); - } - } - - csv.NextRow(); - } -} diff --git a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperStringTable.h b/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperStringTable.h deleted file mode 100644 index 64b2739c..00000000 --- a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperStringTable.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T5/T5.h" - -namespace T5 -{ - class AssetDumperStringTable final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T5 diff --git a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperWeapon.cpp b/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperWeapon.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperWeapon.h b/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperWeapon.h deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperXModel.cpp b/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperXModel.cpp deleted file mode 100644 index 8eb958bb..00000000 --- a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperXModel.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "AssetDumperXModel.h" - -#include "Game/T5/XModel/XModelDumperT5.h" - -using namespace T5; - -bool AssetDumperXModel::ShouldDump(XAssetInfo* asset) -{ - return !asset->m_name.empty() && asset->m_name[0] != ','; -} - -void AssetDumperXModel::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - DumpXModel(context, asset); -} diff --git a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperXModel.h b/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperXModel.h deleted file mode 100644 index 08a1a274..00000000 --- a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperXModel.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T5/T5.h" - -namespace T5 -{ - class AssetDumperXModel final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T5 diff --git a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperGfxImage.cpp b/src/ObjWriting/Game/T5/Image/ImageDumperT5.cpp similarity index 55% rename from src/ObjWriting/Game/T5/AssetDumpers/AssetDumperGfxImage.cpp rename to src/ObjWriting/Game/T5/Image/ImageDumperT5.cpp index 6bb99fcf..d8992797 100644 --- a/src/ObjWriting/Game/T5/AssetDumpers/AssetDumperGfxImage.cpp +++ b/src/ObjWriting/Game/T5/Image/ImageDumperT5.cpp @@ -1,7 +1,8 @@ -#include "AssetDumperGfxImage.h" +#include "ImageDumperT5.h" #include "Image/DdsWriter.h" #include "Image/Dx9TextureLoader.h" +#include "Image/ImageCommon.h" #include "Image/IwiLoader.h" #include "Image/IwiWriter13.h" #include "ObjWriting.h" @@ -35,7 +36,7 @@ namespace std::unique_ptr LoadImageFromIwi(const GfxImage& image, ISearchPath& searchPath) { - const auto imageFileName = std::format("images/{}.iwi", image.name); + const auto imageFileName = image::GetFileNameForAsset(image.name, ".iwi"); const auto filePathImage = searchPath.Open(imageFileName); if (!filePathImage.IsOpen()) { @@ -55,48 +56,43 @@ namespace } } // namespace -AssetDumperGfxImage::AssetDumperGfxImage() +namespace image { - switch (ObjWriting::Configuration.ImageOutputFormat) + DumperT5::DumperT5() { - case ObjWriting::Configuration_t::ImageOutputFormat_e::DDS: - m_writer = std::make_unique(); - break; - case ObjWriting::Configuration_t::ImageOutputFormat_e::IWI: - m_writer = std::make_unique(); - break; - default: - assert(false); - m_writer = nullptr; - break; + switch (ObjWriting::Configuration.ImageOutputFormat) + { + case ObjWriting::Configuration_t::ImageOutputFormat_e::DDS: + m_writer = std::make_unique(); + break; + case ObjWriting::Configuration_t::ImageOutputFormat_e::IWI: + m_writer = std::make_unique(); + break; + default: + assert(false); + m_writer = nullptr; + break; + } } -} -bool AssetDumperGfxImage::ShouldDump(XAssetInfo* asset) -{ - return true; -} + bool DumperT5::ShouldDump(XAssetInfo* asset) + { + return true; + } -std::string AssetDumperGfxImage::GetAssetFileName(const XAssetInfo& asset) const -{ - auto cleanAssetName = asset.m_name; - std::ranges::replace(cleanAssetName, '*', '_'); + void DumperT5::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* image = asset->Asset(); + const auto texture = LoadImageData(context.m_obj_search_path, *image); + if (!texture) + return; - return std::format("images/{}{}", cleanAssetName, m_writer->GetFileExtension()); -} + const auto assetFile = context.OpenAssetFile(GetFileNameForAsset(asset->m_name, m_writer->GetFileExtension())); -void AssetDumperGfxImage::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* image = asset->Asset(); - const auto texture = LoadImageData(context.m_obj_search_path, *image); - if (!texture) - return; + if (!assetFile) + return; - const auto assetFile = context.OpenAssetFile(GetAssetFileName(*asset)); - - if (!assetFile) - return; - - auto& stream = *assetFile; - m_writer->DumpImage(stream, texture.get()); -} + auto& stream = *assetFile; + m_writer->DumpImage(stream, texture.get()); + } +} // namespace image diff --git a/src/ObjWriting/Game/T5/Image/ImageDumperT5.h b/src/ObjWriting/Game/T5/Image/ImageDumperT5.h new file mode 100644 index 00000000..0be6b9bb --- /dev/null +++ b/src/ObjWriting/Game/T5/Image/ImageDumperT5.h @@ -0,0 +1,23 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T5/T5.h" +#include "Image/IImageWriter.h" + +#include + +namespace image +{ + class DumperT5 final : public AbstractAssetDumper + { + public: + DumperT5(); + + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + + private: + std::unique_ptr m_writer; + }; +} // namespace image diff --git a/src/ObjWriting/Game/T5/Localize/LocalizeDumperT5.cpp b/src/ObjWriting/Game/T5/Localize/LocalizeDumperT5.cpp new file mode 100644 index 00000000..60f3ca58 --- /dev/null +++ b/src/ObjWriting/Game/T5/Localize/LocalizeDumperT5.cpp @@ -0,0 +1,44 @@ +#include "LocalizeDumperT5.h" + +#include "Dumping/Localize/StringFileDumper.h" +#include "Localize/LocalizeCommon.h" + +#include +#include + +using namespace T5; + +namespace localize +{ + void DumperT5::DumpPool(AssetDumpingContext& context, AssetPool* pool) + { + if (pool->m_asset_lookup.empty()) + return; + + const auto language = LocalizeCommon::GetNameOfLanguage(context.m_zone.m_language); + const auto assetFile = context.OpenAssetFile(std::format("{}/localizedstrings/{}.str", language, context.m_zone.m_name)); + + if (assetFile) + { + StringFileDumper stringFileDumper(context.m_zone, *assetFile); + + stringFileDumper.SetLanguageName(language); + + // Magic string. Original string files do have this config file. The purpose of the config file is unknown though. + stringFileDumper.SetConfigFile(R"(C:/projects/cod/t5/bin/StringEd.cfg)"); + + stringFileDumper.SetNotes(""); + + for (auto* localizeEntry : *pool) + { + stringFileDumper.WriteLocalizeEntry(localizeEntry->m_name, localizeEntry->Asset()->value); + } + + stringFileDumper.Finalize(); + } + else + { + std::cerr << std::format("Could not create string file for dumping localized strings of zone '{}'\n", context.m_zone.m_name); + } + } +} // namespace localize diff --git a/src/ObjWriting/Game/T5/Localize/LocalizeDumperT5.h b/src/ObjWriting/Game/T5/Localize/LocalizeDumperT5.h new file mode 100644 index 00000000..321a9aef --- /dev/null +++ b/src/ObjWriting/Game/T5/Localize/LocalizeDumperT5.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T5/T5.h" + +namespace localize +{ + class DumperT5 final : public IAssetDumper + { + public: + void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; + }; +} // namespace localize diff --git a/src/ObjWriting/Game/T5/Material/DumperMaterialT5.cpp b/src/ObjWriting/Game/T5/Material/DumperMaterialT5.cpp deleted file mode 100644 index dcc6feb8..00000000 --- a/src/ObjWriting/Game/T5/Material/DumperMaterialT5.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "DumperMaterialT5.h" - -#include "Game/T5/Material/JsonMaterialWriterT5.h" -#include "Game/T5/Material/MaterialConstantZoneStateT5.h" -#include "Material/MaterialCommon.h" - -#include - -using namespace T5; - -void AssetDumperMaterial::DumpPool(AssetDumpingContext& context, AssetPool* pool) -{ - auto* materialConstantState = context.GetZoneAssetDumperState(); - materialConstantState->ExtractNamesFromZone(); - - AbstractAssetDumper::DumpPool(context, pool); -} - -bool AssetDumperMaterial::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperMaterial::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto assetFile = context.OpenAssetFile(material::GetFileNameForAssetName(asset->m_name)); - - if (!assetFile) - return; - - const auto* material = asset->Asset(); - assert(material->info.gameFlags < 0x400); - assert(material->maxStreamedMips == 0); - DumpMaterialAsJson(*assetFile, *material, context); -} diff --git a/src/ObjWriting/Game/T5/Material/DumperMaterialT5.h b/src/ObjWriting/Game/T5/Material/DumperMaterialT5.h deleted file mode 100644 index bb13565c..00000000 --- a/src/ObjWriting/Game/T5/Material/DumperMaterialT5.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T5/T5.h" - -namespace T5 -{ - class AssetDumperMaterial final : public AbstractAssetDumper - { - public: - void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T5 diff --git a/src/ObjWriting/Game/T5/ObjWriterT5.cpp b/src/ObjWriting/Game/T5/ObjWriterT5.cpp index ce6dab53..208f14ba 100644 --- a/src/ObjWriting/Game/T5/ObjWriterT5.cpp +++ b/src/ObjWriting/Game/T5/ObjWriterT5.cpp @@ -1,17 +1,13 @@ #include "ObjWriterT5.h" -#include "AssetDumpers/AssetDumperGfxImage.h" -#include "AssetDumpers/AssetDumperLocalizeEntry.h" -#include "AssetDumpers/AssetDumperPhysConstraints.h" -#include "AssetDumpers/AssetDumperPhysPreset.h" -#include "AssetDumpers/AssetDumperRawFile.h" -#include "AssetDumpers/AssetDumperSndBank.h" -#include "AssetDumpers/AssetDumperStringTable.h" -#include "AssetDumpers/AssetDumperWeapon.h" -#include "AssetDumpers/AssetDumperXModel.h" #include "Game/T5/GameAssetPoolT5.h" -#include "Material/DumperMaterialT5.h" +#include "Game/T5/Material/MaterialJsonDumperT5.h" +#include "Game/T5/XModel/XModelDumperT5.h" +#include "Image/ImageDumperT5.h" +#include "Localize/LocalizeDumperT5.h" #include "ObjWriting.h" +#include "RawFile/RawFileDumperT5.h" +#include "StringTable/StringTableDumperT5.h" using namespace T5; @@ -30,10 +26,10 @@ bool ObjWriter::DumpZone(AssetDumpingContext& context) const // DUMP_ASSET_POOL(AssetDumperPhysConstraints, m_phys_constraints, ASSET_TYPE_PHYSCONSTRAINTS) // DUMP_ASSET_POOL(AssetDumperDestructibleDef, m_destructible_def, ASSET_TYPE_DESTRUCTIBLEDEF) // DUMP_ASSET_POOL(AssetDumperXAnimParts, m_xanim_parts, ASSET_TYPE_XANIMPARTS) - DUMP_ASSET_POOL(AssetDumperXModel, m_xmodel, ASSET_TYPE_XMODEL) - DUMP_ASSET_POOL(AssetDumperMaterial, m_material, ASSET_TYPE_MATERIAL) + DUMP_ASSET_POOL(xmodel::DumperT5, m_xmodel, ASSET_TYPE_XMODEL) + DUMP_ASSET_POOL(material::JsonDumperT5, m_material, ASSET_TYPE_MATERIAL) // DUMP_ASSET_POOL(AssetDumperTechniqueSet, m_technique_set, ASSET_TYPE_TECHNIQUE_SET) - DUMP_ASSET_POOL(AssetDumperGfxImage, m_image, ASSET_TYPE_IMAGE) + DUMP_ASSET_POOL(image::DumperT5, m_image, ASSET_TYPE_IMAGE) // DUMP_ASSET_POOL(AssetDumperSndBank, m_sound_bank, ASSET_TYPE_SOUND) // DUMP_ASSET_POOL(AssetDumperSndPatch, m_sound_patch, ASSET_TYPE_SOUND_PATCH) // DUMP_ASSET_POOL(AssetDumperClipMap, m_clip_map, ASSET_TYPE_CLIPMAP_PVS) @@ -46,13 +42,13 @@ bool ObjWriter::DumpZone(AssetDumpingContext& context) const // DUMP_ASSET_POOL(AssetDumperFont, m_font, ASSET_TYPE_FONT) // DUMP_ASSET_POOL(AssetDumperMenuList, m_menu_list, ASSET_TYPE_MENULIST) // DUMP_ASSET_POOL(AssetDumperMenuDef, m_menu_def, ASSET_TYPE_MENU) - DUMP_ASSET_POOL(AssetDumperLocalizeEntry, m_localize, ASSET_TYPE_LOCALIZE_ENTRY) + DUMP_ASSET_POOL(localize::DumperT5, m_localize, ASSET_TYPE_LOCALIZE_ENTRY) // DUMP_ASSET_POOL(AssetDumperWeapon, m_weapon, ASSET_TYPE_WEAPON) // DUMP_ASSET_POOL(AssetDumperSndDriverGlobals, m_snd_driver_globals, ASSET_TYPE_SNDDRIVER_GLOBALS) // DUMP_ASSET_POOL(AssetDumperFxEffectDef, m_fx, ASSET_TYPE_FX) // DUMP_ASSET_POOL(AssetDumperFxImpactTable, m_fx_impact_table, ASSET_TYPE_IMPACT_FX) - DUMP_ASSET_POOL(AssetDumperRawFile, m_raw_file, ASSET_TYPE_RAWFILE) - DUMP_ASSET_POOL(AssetDumperStringTable, m_string_table, ASSET_TYPE_STRINGTABLE) + DUMP_ASSET_POOL(raw_file::DumperT5, m_raw_file, ASSET_TYPE_RAWFILE) + DUMP_ASSET_POOL(string_table::DumperT5, m_string_table, ASSET_TYPE_STRINGTABLE) // DUMP_ASSET_POOL(AssetDumperPackIndex, m_pack_index, ASSET_TYPE_PACK_INDEX) // DUMP_ASSET_POOL(AssetDumperXGlobals, m_xglobals, ASSET_TYPE_XGLOBALS) // DUMP_ASSET_POOL(AssetDumperDDLRoot, m_ddl, ASSET_TYPE_DDL) diff --git a/src/ObjWriting/Game/T5/RawFile/RawFileDumperT5.cpp b/src/ObjWriting/Game/T5/RawFile/RawFileDumperT5.cpp new file mode 100644 index 00000000..2043098c --- /dev/null +++ b/src/ObjWriting/Game/T5/RawFile/RawFileDumperT5.cpp @@ -0,0 +1,121 @@ +#include "RawFileDumperT5.h" + +#include "Utils/StringUtils.h" + +#include +#include +#include + +using namespace T5; + +namespace fs = std::filesystem; + +namespace +{ + constexpr static size_t GSC_MAX_SIZE = 0xC000000; + + void DumpGsc(AssetDumpingContext& context, XAssetInfo* asset, std::ostream& stream) + { + const auto* rawFile = asset->Asset(); + + if (rawFile->len <= 8) + { + std::cout << "Invalid len of gsc file \"" << rawFile->name << "\"\n"; + return; + } + + const auto outLen = reinterpret_cast(rawFile->buffer)[0]; + const auto inLen = reinterpret_cast(rawFile->buffer)[1]; + + assert(inLen == static_cast(rawFile->len) - 8); + + if (inLen > static_cast(rawFile->len - 8) + 1) + { + std::cout << "Invalid compression of gsc file \"" << rawFile->name << "\": " << inLen << "\n"; + return; + } + + if (outLen > GSC_MAX_SIZE) + { + std::cout << "Invalid size of gsc file \"" << rawFile->name << "\": " << outLen << "\n"; + return; + } + + z_stream_s zs{}; + + zs.zalloc = Z_NULL; + zs.zfree = Z_NULL; + zs.opaque = Z_NULL; + zs.avail_in = 0; + zs.next_in = Z_NULL; + + int ret = inflateInit(&zs); + + if (ret != Z_OK) + { + throw std::runtime_error("Initializing inflate failed"); + } + + zs.next_in = reinterpret_cast(&rawFile->buffer[8]); + zs.avail_in = inLen; + + Bytef buffer[0x1000]; + + size_t writtenSize = 0; + while (zs.avail_in > 0) + { + zs.next_out = buffer; + zs.avail_out = sizeof(buffer); + ret = inflate(&zs, Z_SYNC_FLUSH); + + if (ret < 0) + { + std::cout << "Inflate failed for dumping gsc file \"" << rawFile->name << "\"\n"; + inflateEnd(&zs); + return; + } + + const auto inflateOutSize = sizeof(buffer) - zs.avail_out; + + if (writtenSize + inflateOutSize >= outLen) + { + // Last byte is a \0 byte. Skip it. + stream.write(reinterpret_cast(buffer), inflateOutSize - 1); + } + else + { + stream.write(reinterpret_cast(buffer), inflateOutSize); + } + writtenSize += inflateOutSize; + } + + inflateEnd(&zs); + } +} // namespace + +namespace raw_file +{ + bool DumperT5::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperT5::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* rawFile = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name); + + if (!assetFile) + return; + + auto& stream = *assetFile; + const fs::path rawFilePath(rawFile->name); + auto extension = rawFilePath.extension().string(); + utils::MakeStringLowerCase(extension); + + if (extension == ".gsc" || extension == ".csc") + DumpGsc(context, asset, stream); + else + stream.write(rawFile->buffer, rawFile->len); + } +} // namespace raw_file diff --git a/src/ObjWriting/Game/T5/RawFile/RawFileDumperT5.h b/src/ObjWriting/Game/T5/RawFile/RawFileDumperT5.h new file mode 100644 index 00000000..056266ae --- /dev/null +++ b/src/ObjWriting/Game/T5/RawFile/RawFileDumperT5.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T5/T5.h" + +namespace raw_file +{ + class DumperT5 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace raw_file diff --git a/src/ObjWriting/Game/T5/StringTable/StringTableDumperT5.cpp b/src/ObjWriting/Game/T5/StringTable/StringTableDumperT5.cpp new file mode 100644 index 00000000..0acc3587 --- /dev/null +++ b/src/ObjWriting/Game/T5/StringTable/StringTableDumperT5.cpp @@ -0,0 +1,42 @@ +#include "StringTableDumperT5.h" + +#include "Csv/CsvStream.h" + +using namespace T5; + +namespace string_table +{ + bool DumperT5::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperT5::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* stringTable = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name); + + if (!assetFile) + return; + + CsvOutputStream csv(*assetFile); + + for (auto row = 0; row < stringTable->rowCount; row++) + { + for (auto column = 0; column < stringTable->columnCount; column++) + { + const auto* cell = &stringTable->values[column + row * stringTable->columnCount]; + if (cell->string != nullptr) + { + csv.WriteColumn(cell->string); + } + else + { + csv.WriteColumn(""); + } + } + + csv.NextRow(); + } + } +} // namespace string_table diff --git a/src/ObjWriting/Game/T5/StringTable/StringTableDumperT5.h b/src/ObjWriting/Game/T5/StringTable/StringTableDumperT5.h new file mode 100644 index 00000000..12ee953b --- /dev/null +++ b/src/ObjWriting/Game/T5/StringTable/StringTableDumperT5.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T5/T5.h" + +namespace string_table +{ + class DumperT5 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace string_table diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperGfxImage.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperGfxImage.h deleted file mode 100644 index 401aae5e..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperGfxImage.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" -#include "Image/IImageWriter.h" - -#include - -namespace T6 -{ - class AssetDumperGfxImage final : public AbstractAssetDumper - { - std::unique_ptr m_writer; - - std::string GetAssetFileName(const XAssetInfo& asset) const; - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - - public: - AssetDumperGfxImage(); - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLeaderboardDef.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLeaderboardDef.cpp deleted file mode 100644 index 2d83e5bd..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLeaderboardDef.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "AssetDumperLeaderboardDef.h" - -#include "Game/T6/Leaderboard/JsonLeaderboardDefWriter.h" - -#include -#include - -using namespace T6; - -std::string AssetDumperLeaderboardDef::GetFileNameForAsset(const std::string& assetName) -{ - return std::format("leaderboards/{}.json", assetName); -} - -bool AssetDumperLeaderboardDef::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperLeaderboardDef::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto assetFile = context.OpenAssetFile(GetFileNameForAsset(asset->m_name)); - - if (!assetFile) - return; - - DumpLeaderboardDefAsJson(*assetFile, asset->Asset()); -} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLeaderboardDef.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLeaderboardDef.h deleted file mode 100644 index 057d4252..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLeaderboardDef.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" - -namespace T6 -{ - class AssetDumperLeaderboardDef final : public AbstractAssetDumper - { - static std::string GetFileNameForAsset(const std::string& assetName); - - protected: - _NODISCARD bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.cpp deleted file mode 100644 index e9ebf735..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "AssetDumperLocalizeEntry.h" - -#include "Dumping/Localize/StringFileDumper.h" -#include "Localize/LocalizeCommon.h" - -#include -#include - -using namespace T6; - -void AssetDumperLocalizeEntry::DumpPool(AssetDumpingContext& context, AssetPool* pool) -{ - if (pool->m_asset_lookup.empty()) - return; - - const auto language = LocalizeCommon::GetNameOfLanguage(context.m_zone.m_language); - const auto assetFile = context.OpenAssetFile(std::format("{}/localizedstrings/{}.str", language, context.m_zone.m_name)); - - if (assetFile) - { - StringFileDumper stringFileDumper(context.m_zone, *assetFile); - - stringFileDumper.SetLanguageName(language); - - // Magic string. Original string files do have this config file. The purpose of the config file is unknown though. - stringFileDumper.SetConfigFile(R"(C:/projects/cod/t6/bin/StringEd.cfg)"); - - stringFileDumper.SetNotes(""); - - for (auto* localizeEntry : *pool) - { - stringFileDumper.WriteLocalizeEntry(localizeEntry->m_name, localizeEntry->Asset()->value); - } - - stringFileDumper.Finalize(); - } - else - { - std::cerr << std::format("Could not create string file for dumping localized strings of zone '{}'\n", context.m_zone.m_name); - } -} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.h deleted file mode 100644 index d85de9ac..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperLocalizeEntry.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" - -namespace T6 -{ - class AssetDumperLocalizeEntry final : public IAssetDumper - { - public: - void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperMapEnts.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperMapEnts.cpp deleted file mode 100644 index cd4a8165..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperMapEnts.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "AssetDumperMapEnts.h" - -#include - -using namespace T6; - -bool AssetDumperMapEnts::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperMapEnts::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* mapEnts = asset->Asset(); - - const auto mapEntsFile = context.OpenAssetFile(std::format("{}.ents", mapEnts->name)); - - if (!mapEntsFile) - return; - - auto& stream = *mapEntsFile; - stream.write(mapEnts->entityString, mapEnts->numEntityChars - 1); -} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperMapEnts.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperMapEnts.h deleted file mode 100644 index 98b0301a..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperMapEnts.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" - -namespace T6 -{ - class AssetDumperMapEnts final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysConstraints.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysConstraints.cpp deleted file mode 100644 index 7be1250a..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysConstraints.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include "AssetDumperPhysConstraints.h" - -#include "Game/T6/InfoString/InfoStringFromStructConverter.h" -#include "Game/T6/ObjConstantsT6.h" -#include "Game/T6/PhysConstraints/PhysConstraintsFields.h" - -#include -#include - -using namespace T6; - -namespace T6 -{ - class InfoStringFromPhysConstraintsConverter final : public InfoStringFromStructConverter - { - protected: - void FillFromExtensionField(const cspField_t& field) override - { - switch (static_cast(field.iFieldType)) - { - case CFT_TYPE: - FillFromEnumInt(std::string(field.szName), field.iOffset, s_constraintTypeNames, std::extent_v); - break; - - default: - assert(false); - break; - } - } - - public: - InfoStringFromPhysConstraintsConverter(const PhysConstraints* structure, - const cspField_t* fields, - const size_t fieldCount, - std::function scriptStringValueCallback) - : InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback)) - { - } - }; -} // namespace T6 - -InfoString AssetDumperPhysConstraints::CreateInfoString(XAssetInfo* asset) -{ - assert(asset->Asset()->count <= 4); - - InfoStringFromPhysConstraintsConverter converter(asset->Asset(), - phys_constraints_fields, - std::extent_v, - [asset](const scr_string_t scrStr) -> std::string - { - assert(scrStr < asset->m_zone->m_script_strings.Count()); - if (scrStr >= asset->m_zone->m_script_strings.Count()) - return ""; - - return asset->m_zone->m_script_strings[scrStr]; - }); - - return converter.Convert(); -} - -bool AssetDumperPhysConstraints::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperPhysConstraints::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - // Only dump raw when no gdt available - if (context.m_gdt) - { - const auto infoString = CreateInfoString(asset); - GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_PHYS_CONSTRAINTS); - infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_PHYS_CONSTRAINTS, gdtEntry); - context.m_gdt->WriteEntry(gdtEntry); - } - else - { - const auto assetFile = context.OpenAssetFile("physconstraints/" + asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - const auto infoString = CreateInfoString(asset); - const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_PHYS_CONSTRAINTS); - stream.write(stringValue.c_str(), stringValue.size()); - } -} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysConstraints.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysConstraints.h deleted file mode 100644 index 8f3d938e..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysConstraints.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" -#include "InfoString/InfoString.h" - -namespace T6 -{ - class AssetDumperPhysConstraints final : public AbstractAssetDumper - { - static InfoString CreateInfoString(XAssetInfo* asset); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysPreset.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysPreset.cpp deleted file mode 100644 index d11819f4..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysPreset.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#include "AssetDumperPhysPreset.h" - -#include "Game/T6/InfoString/InfoStringFromStructConverter.h" -#include "Game/T6/ObjConstantsT6.h" -#include "Game/T6/PhysPreset/PhysPresetFields.h" - -#include -#include -#include -#include - -using namespace T6; - -namespace T6 -{ - class InfoStringFromPhysPresetConverter final : public InfoStringFromStructConverter - { - protected: - void FillFromExtensionField(const cspField_t& field) override - { - assert(false); - } - - public: - InfoStringFromPhysPresetConverter(const PhysPresetInfo* structure, - const cspField_t* fields, - const size_t fieldCount, - std::function scriptStringValueCallback) - : InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback)) - { - } - }; -} // namespace T6 - -void AssetDumperPhysPreset::CopyToPhysPresetInfo(const PhysPreset* physPreset, PhysPresetInfo* physPresetInfo) -{ - physPresetInfo->mass = std::clamp(physPreset->mass * 1000.0f, 1.0f, 2000.0f); - physPresetInfo->bounce = physPreset->bounce; - - if (std::isinf(physPreset->friction)) - { - physPresetInfo->isFrictionInfinity = 1; - physPresetInfo->friction = 0; - } - else - { - physPresetInfo->isFrictionInfinity = 0; - physPresetInfo->friction = physPreset->friction; - } - - physPresetInfo->bulletForceScale = physPreset->bulletForceScale; - physPresetInfo->explosiveForceScale = physPreset->explosiveForceScale; - physPresetInfo->piecesSpreadFraction = physPreset->piecesSpreadFraction; - physPresetInfo->piecesUpwardVelocity = physPreset->piecesUpwardVelocity; - physPresetInfo->canFloat = physPreset->canFloat; - physPresetInfo->gravityScale = std::clamp(physPreset->gravityScale, 0.01f, 10.0f); - physPresetInfo->centerOfMassOffset = physPreset->centerOfMassOffset; - physPresetInfo->buoyancyBoxMin = physPreset->buoyancyBoxMin; - physPresetInfo->buoyancyBoxMax = physPreset->buoyancyBoxMax; -} - -InfoString AssetDumperPhysPreset::CreateInfoString(XAssetInfo* asset) -{ - auto* physPresetInfo = new PhysPresetInfo; - CopyToPhysPresetInfo(asset->Asset(), physPresetInfo); - - InfoStringFromPhysPresetConverter converter(physPresetInfo, - phys_preset_fields, - std::extent_v, - [asset](const scr_string_t scrStr) -> std::string - { - assert(scrStr < asset->m_zone->m_script_strings.Count()); - if (scrStr >= asset->m_zone->m_script_strings.Count()) - return ""; - - return asset->m_zone->m_script_strings[scrStr]; - }); - - return converter.Convert(); -} - -bool AssetDumperPhysPreset::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperPhysPreset::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - // Only dump raw when no gdt available - if (context.m_gdt) - { - const auto infoString = CreateInfoString(asset); - GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_PHYS_PRESET); - infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_PHYS_PRESET, gdtEntry); - context.m_gdt->WriteEntry(gdtEntry); - } - else - { - const auto assetFile = context.OpenAssetFile("physic/" + asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - const auto infoString = CreateInfoString(asset); - const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_PHYS_PRESET); - stream.write(stringValue.c_str(), stringValue.size()); - } -} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysPreset.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysPreset.h deleted file mode 100644 index a760ef45..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperPhysPreset.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" -#include "InfoString/InfoString.h" - -namespace T6 -{ - class AssetDumperPhysPreset final : public AbstractAssetDumper - { - static void CopyToPhysPresetInfo(const PhysPreset* physPreset, PhysPresetInfo* physPresetInfo); - static InfoString CreateInfoString(XAssetInfo* asset); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperQdb.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperQdb.cpp deleted file mode 100644 index dde4a739..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperQdb.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "AssetDumperQdb.h" - -using namespace T6; - -bool AssetDumperQdb::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperQdb::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* qdb = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - stream.write(qdb->buffer, qdb->len); -} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperQdb.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperQdb.h deleted file mode 100644 index fd6a7456..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperQdb.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" - -namespace T6 -{ - class AssetDumperQdb final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperRawFile.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperRawFile.cpp deleted file mode 100644 index 291d969e..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperRawFile.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include "AssetDumperRawFile.h" - -#include -#include -#include - -using namespace T6; - -namespace fs = std::filesystem; - -bool AssetDumperRawFile::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperRawFile::DumpAnimtree(AssetDumpingContext& context, XAssetInfo* asset, std::ostream& stream) -{ - const auto* rawFile = asset->Asset(); - - if (rawFile->len <= 4) - { - std::cerr << "Invalid len of animtree file \"" << rawFile->name << "\"\n"; - return; - } - - const auto outLen = reinterpret_cast(rawFile->buffer)[0]; - const auto inLen = rawFile->len; - - if (outLen > ANIMTREE_MAX_SIZE) - { - std::cerr << "Invalid size of animtree file \"" << rawFile->name << "\": " << outLen << "\n"; - return; - } - - z_stream_s zs{}; - - zs.zalloc = Z_NULL; - zs.zfree = Z_NULL; - zs.opaque = Z_NULL; - zs.avail_in = 0; - zs.next_in = Z_NULL; - - int ret = inflateInit2(&zs, -DEF_WBITS); - - if (ret != Z_OK) - { - throw std::runtime_error("Initializing inflate failed"); - } - - zs.next_in = reinterpret_cast(&rawFile->buffer[4]); - zs.avail_in = inLen - sizeof(uint32_t); - - Bytef buffer[0x1000]; - - while (zs.avail_in > 0) - { - zs.next_out = buffer; - zs.avail_out = sizeof(buffer); - ret = inflate(&zs, Z_SYNC_FLUSH); - - if (ret < 0) - { - std::cerr << "Inflate failed for dumping animtree file \"" << rawFile->name << "\"\n"; - inflateEnd(&zs); - return; - } - - const auto inflateOutSize = sizeof(buffer) - zs.avail_out; - - stream.write(reinterpret_cast(buffer), inflateOutSize); - } - - inflateEnd(&zs); -} - -void AssetDumperRawFile::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* rawFile = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - const fs::path rawFilePath(rawFile->name); - const auto extension = rawFilePath.extension().string(); - - if (extension == ".atr") - { - DumpAnimtree(context, asset, stream); - } - else - { - stream.write(rawFile->buffer, rawFile->len); - } -} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperRawFile.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperRawFile.h deleted file mode 100644 index 1f9f033f..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperRawFile.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" - -namespace T6 -{ - class AssetDumperRawFile final : public AbstractAssetDumper - { - constexpr static size_t ANIMTREE_MAX_SIZE = 0xC000000; - - void DumpAnimtree(AssetDumpingContext& context, XAssetInfo* asset, std::ostream& stream); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperScriptParseTree.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperScriptParseTree.cpp deleted file mode 100644 index fb1ff079..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperScriptParseTree.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "AssetDumperScriptParseTree.h" - -using namespace T6; - -bool AssetDumperScriptParseTree::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperScriptParseTree::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* scriptParseTree = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - stream.write(scriptParseTree->buffer, scriptParseTree->len); -} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperScriptParseTree.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperScriptParseTree.h deleted file mode 100644 index 8ff1db2e..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperScriptParseTree.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" - -namespace T6 -{ - class AssetDumperScriptParseTree final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSlug.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSlug.cpp deleted file mode 100644 index 09dd50a4..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSlug.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "AssetDumperSlug.h" - -using namespace T6; - -bool AssetDumperSlug::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperSlug::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* slug = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - stream.write(slug->buffer, slug->len); -} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSlug.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSlug.h deleted file mode 100644 index 01598810..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSlug.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" - -namespace T6 -{ - class AssetDumperSlug final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndBank.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndBank.h deleted file mode 100644 index 61883c58..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndBank.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" - -namespace T6 -{ - class AssetDumperSndBank final : public IAssetDumper - { - class Internal; - - public: - void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndDriverGlobals.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndDriverGlobals.cpp deleted file mode 100644 index 452858ce..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndDriverGlobals.cpp +++ /dev/null @@ -1,385 +0,0 @@ -#include "AssetDumperSndDriverGlobals.h" - -#include "Csv/CsvStream.h" -#include "ObjContainer/SoundBank/SoundBank.h" - -using namespace T6; - -class AssetDumperSndDriverGlobals::Internal -{ - AssetDumpingContext& m_context; - - inline static const std::string GROUPS_HEADERS[]{ - "name", - "attenuationSp", - "attenuationMp", - "category", - "parent", - "id", - }; - - inline static const std::string GROUPS_CATEGORIES[]{ - "sfx", - "music", - "void", - "ui", - "cinematic", - "id", - }; - - inline static const std::string CURVE_HEADERS[]{ - "name", - "x0", - "y0", - "x1", - "y1", - "x2", - "y2", - "x3", - "y3", - "x4", - "y4", - "x5", - "y5", - "x6", - "y6", - "x7", - "y7", - "id", - }; - - inline static const std::string PAN_HEADERS[]{ - "name", - "front", - "back", - "center", - "lfe", - "left", - "right", - "id", - }; - - inline static const std::string MASTER_HEADERS[]{ - "name", "lowE", "lowG", "lowF", "lowQ", "peak1E", "peak1G", "peak1F", "peak1Q", "peak2E", "peak2G", - "peak2F", "peak2Q", "hiE", "hiG", "hiF", "hiQ", "eqG", "compE", "compPG", "compMG", "compT", - "compR", "compTA", "compTR", "limitE", "limitPG", "limitMG", "limitT", "limitR", "limitTA", "limitTR", "busReverbG", - "busFxG", "busVoiceG", "busPfutzG", "busHdrfxG", "busUiG", "busMusicG", "busMovieG", "busVcsG", "busReverbE", "busFxE", "busVoiceE", - "busPfutzE", "busHdrfxE", "busUiE", "busMusicE", "busMovieE", "hdrfxCompE", "voiceEqE", "voiceCompE", "id", - }; - - inline static const std::string SIDECHAIN_HEADERS[]{ - "name", - "g", - "f", - "q", - "ta", - "tr", - "tf", - "id", - }; - - inline static const std::string FUTZ_HEADERS[]{ - "name", - "bpfF", - "bpfQ", - "lsG", - "lsF", - "lsQ", - "dist", - "preG", - "postG", - "th", - "tg", - "clippre", - "clippost", - "blend", - "startAliasId", - "stopAliasId", - "loopAliasId", - "id", - }; - - std::unique_ptr OpenAssetFile(const std::string& filename) - { - auto outputFile = this->m_context.OpenAssetFile(filename); - if (outputFile == nullptr) - { - std::cout << "Failed to open sound driver globals output file for: \"" << filename << "\"\n"; - } - - return outputFile; - } - - static void WriteFileHeader(CsvOutputStream& stream, const std::string* headers, size_t count) - { - for (auto i = 0u; i < count; i++) - { - stream.WriteColumn(headers[i]); - } - - stream.NextRow(); - } - - void DumpSndVolumesGroups(const SndVolumeGroup* groups, const size_t count) - { - const auto outputFile = this->OpenAssetFile("soundbank/globals/group.csv"); - - if (outputFile != nullptr) - { - CsvOutputStream csvStream(*outputFile); - WriteFileHeader(csvStream, GROUPS_HEADERS, std::extent_v); - - for (auto i = 0u; i < count; i++) - { - const auto& group = groups[i]; - csvStream.WriteColumn(group.name); - csvStream.WriteColumn(std::to_string(group.attenuationSp)); - csvStream.WriteColumn(std::to_string(group.attenuationMp)); - csvStream.WriteColumn(GROUPS_CATEGORIES[group.category]); - csvStream.WriteColumn(group.parentName); - csvStream.WriteColumn(std::to_string(group.id)); - csvStream.NextRow(); - } - } - } - - void DumpSndCurves(const SndCurve* curves, const size_t count) - { - const auto outputFile = this->OpenAssetFile("soundbank/globals/curves.csv"); - - if (outputFile != nullptr) - { - CsvOutputStream csvStream(*outputFile); - WriteFileHeader(csvStream, CURVE_HEADERS, std::extent_v); - - for (auto i = 0u; i < count; i++) - { - const auto& curve = curves[i]; - csvStream.WriteColumn(curve.name); - - for (auto j = 0u; j < 8; j++) - { - csvStream.WriteColumn(std::to_string(curve.points[j].x)); - csvStream.WriteColumn(std::to_string(curve.points[j].y)); - } - - csvStream.WriteColumn(std::to_string(curve.id)); - - csvStream.NextRow(); - } - } - } - - void DumpSndPans(const SndPan* pans, const size_t count) - { - const auto outputFile = this->OpenAssetFile("soundbank/globals/pan.csv"); - - if (outputFile != nullptr) - { - CsvOutputStream csvStream(*outputFile); - WriteFileHeader(csvStream, PAN_HEADERS, std::extent_v); - - for (auto i = 0u; i < count; i++) - { - const auto& pan = pans[i]; - csvStream.WriteColumn(pan.name); - csvStream.WriteColumn(std::to_string(pan.front)); - csvStream.WriteColumn(std::to_string(pan.back)); - csvStream.WriteColumn(std::to_string(pan.center)); - csvStream.WriteColumn(std::to_string(pan.lfe)); - csvStream.WriteColumn(std::to_string(pan.left)); - csvStream.WriteColumn(std::to_string(pan.right)); - csvStream.WriteColumn(std::to_string(pan.id)); - csvStream.NextRow(); - } - } - } - - void DumpSndDuckGroups(const SndDuckGroup* duckGroups, const size_t count) - { - const auto outputFile = this->OpenAssetFile("soundbank/globals/duck_groups.csv"); - - if (outputFile != nullptr) - { - CsvOutputStream csvStream(*outputFile); - csvStream.WriteColumn("name"); - csvStream.WriteColumn("id"); - csvStream.NextRow(); - - for (auto i = 0u; i < count; i++) - { - const auto& duckGroup = duckGroups[i]; - csvStream.WriteColumn(duckGroup.name); - csvStream.WriteColumn(std::to_string(duckGroup.id)); - csvStream.NextRow(); - } - } - } - - void DumpSndMasters(const SndMaster* masters, const size_t count) - { - const auto outputFile = this->OpenAssetFile("soundbank/globals/master.csv"); - - if (outputFile != nullptr) - { - CsvOutputStream csvStream(*outputFile); - WriteFileHeader(csvStream, MASTER_HEADERS, std::extent_v); - - for (auto i = 0u; i < count; i++) - { - const auto& master = masters[i]; - csvStream.WriteColumn(master.name); - csvStream.WriteColumn(std::to_string(master.lowE)); - csvStream.WriteColumn(std::to_string(master.lowG)); - csvStream.WriteColumn(std::to_string(master.lowF)); - csvStream.WriteColumn(std::to_string(master.lowQ)); - csvStream.WriteColumn(std::to_string(master.peak1E)); - csvStream.WriteColumn(std::to_string(master.peak1G)); - csvStream.WriteColumn(std::to_string(master.peak1F)); - csvStream.WriteColumn(std::to_string(master.peak1Q)); - csvStream.WriteColumn(std::to_string(master.peak2E)); - csvStream.WriteColumn(std::to_string(master.peak2G)); - csvStream.WriteColumn(std::to_string(master.peak2F)); - csvStream.WriteColumn(std::to_string(master.peak2Q)); - csvStream.WriteColumn(std::to_string(master.hiE)); - csvStream.WriteColumn(std::to_string(master.hiG)); - csvStream.WriteColumn(std::to_string(master.hiF)); - csvStream.WriteColumn(std::to_string(master.hiQ)); - csvStream.WriteColumn(std::to_string(master.eqG)); - csvStream.WriteColumn(std::to_string(master.compE)); - csvStream.WriteColumn(std::to_string(master.compPG)); - csvStream.WriteColumn(std::to_string(master.compMG)); - csvStream.WriteColumn(std::to_string(master.compT)); - csvStream.WriteColumn(std::to_string(master.compR)); - csvStream.WriteColumn(std::to_string(master.compTA)); - csvStream.WriteColumn(std::to_string(master.compTR)); - csvStream.WriteColumn(std::to_string(master.limitE)); - csvStream.WriteColumn(std::to_string(master.limitPG)); - csvStream.WriteColumn(std::to_string(master.limitMG)); - csvStream.WriteColumn(std::to_string(master.limitT)); - csvStream.WriteColumn(std::to_string(master.limitR)); - csvStream.WriteColumn(std::to_string(master.limitTA)); - csvStream.WriteColumn(std::to_string(master.limitTR)); - csvStream.WriteColumn(std::to_string(master.busReverbG)); - csvStream.WriteColumn(std::to_string(master.busFxG)); - csvStream.WriteColumn(std::to_string(master.busVoiceG)); - csvStream.WriteColumn(std::to_string(master.busPfutzG)); - csvStream.WriteColumn(std::to_string(master.busHdrfxG)); - csvStream.WriteColumn(std::to_string(master.busUiG)); - csvStream.WriteColumn(std::to_string(master.busMusicG)); - csvStream.WriteColumn(std::to_string(master.busMovieG)); - csvStream.WriteColumn(std::to_string(master.busVcsG)); - csvStream.WriteColumn(std::to_string(master.busReverbE)); - csvStream.WriteColumn(std::to_string(master.busFxE)); - csvStream.WriteColumn(std::to_string(master.busVoiceE)); - csvStream.WriteColumn(std::to_string(master.busPfutzE)); - csvStream.WriteColumn(std::to_string(master.busHdrfxE)); - csvStream.WriteColumn(std::to_string(master.busUiE)); - csvStream.WriteColumn(std::to_string(master.busMusicE)); - csvStream.WriteColumn(std::to_string(master.busMovieE)); - csvStream.WriteColumn(std::to_string(master.hdrfxCompE)); - csvStream.WriteColumn(std::to_string(master.voiceEqE)); - csvStream.WriteColumn(std::to_string(master.voiceCompE)); - csvStream.WriteColumn(std::to_string(master.id)); - csvStream.NextRow(); - } - } - } - - void DumpSndSidechainDucks(const SndSidechainDuck* sidechains, const size_t count) - { - const auto outputFile = this->OpenAssetFile("soundbank/globals/sidechain_duck.csv"); - - if (outputFile != nullptr) - { - CsvOutputStream csvStream(*outputFile); - WriteFileHeader(csvStream, SIDECHAIN_HEADERS, std::extent_v); - - for (auto i = 0u; i < count; i++) - { - const auto& sidechain = sidechains[i]; - csvStream.WriteColumn(sidechain.name); - csvStream.WriteColumn(std::to_string(sidechain.g)); - csvStream.WriteColumn(std::to_string(sidechain.f)); - csvStream.WriteColumn(std::to_string(sidechain.q)); - csvStream.WriteColumn(std::to_string(sidechain.ta)); - csvStream.WriteColumn(std::to_string(sidechain.tr)); - csvStream.WriteColumn(std::to_string(sidechain.tf)); - csvStream.WriteColumn(std::to_string(sidechain.id)); - csvStream.NextRow(); - } - } - } - - void DumpSndFutz(const SndFutz* futzes, const size_t count) - { - const auto outputFile = this->OpenAssetFile("soundbank/globals/futz.csv"); - - if (outputFile != nullptr) - { - CsvOutputStream csvStream(*outputFile); - WriteFileHeader(csvStream, FUTZ_HEADERS, std::extent_v); - - for (auto i = 0u; i < count; i++) - { - const auto& futz = futzes[i]; - csvStream.WriteColumn(futz.name); - csvStream.WriteColumn(std::to_string(futz.bpfF)); - csvStream.WriteColumn(std::to_string(futz.bpfQ)); - csvStream.WriteColumn(std::to_string(futz.lsG)); - csvStream.WriteColumn(std::to_string(futz.lsF)); - csvStream.WriteColumn(std::to_string(futz.lsQ)); - csvStream.WriteColumn(std::to_string(futz.dist)); - csvStream.WriteColumn(std::to_string(futz.preG)); - csvStream.WriteColumn(std::to_string(futz.postG)); - csvStream.WriteColumn(std::to_string(futz.th)); - csvStream.WriteColumn(std::to_string(futz.tg)); - csvStream.WriteColumn(std::to_string(futz.clippre)); - csvStream.WriteColumn(std::to_string(futz.clippost)); - csvStream.WriteColumn(std::to_string(futz.blend)); - csvStream.WriteColumn(std::to_string(futz.startAliasId)); - csvStream.WriteColumn(std::to_string(futz.stopAliasId)); - csvStream.WriteColumn(std::to_string(futz.loopAliasId)); - csvStream.WriteColumn(std::to_string(futz.id)); - csvStream.NextRow(); - } - } - } - - void DumpSndDriverGlobals(const XAssetInfo* sndDriverGlobalsInfo) - { - const auto* sndDriverGlobals = sndDriverGlobalsInfo->Asset(); - - DumpSndVolumesGroups(sndDriverGlobals->groups, sndDriverGlobals->groupCount); - DumpSndCurves(sndDriverGlobals->curves, sndDriverGlobals->curveCount); - DumpSndPans(sndDriverGlobals->pans, sndDriverGlobals->panCount); - DumpSndDuckGroups(sndDriverGlobals->duckGroups, sndDriverGlobals->duckGroupCount); - // DumpSndContexts(sndDriverGlobals->contexts, sndDriverGlobals->contextCount); - DumpSndMasters(sndDriverGlobals->masters, sndDriverGlobals->masterCount); - DumpSndSidechainDucks(sndDriverGlobals->voiceDucks, sndDriverGlobals->voiceDuckCount); - DumpSndFutz(sndDriverGlobals->futzes, sndDriverGlobals->futzCount); - } - -public: - explicit Internal(AssetDumpingContext& context) - : m_context(context) - { - } - - void DumpPool(AssetPool* pool) - { - for (const auto* assetInfo : *pool) - { - if (!assetInfo->m_name.empty() && assetInfo->m_name[0] == ',') - continue; - - DumpSndDriverGlobals(assetInfo); - } - } -}; - -void AssetDumperSndDriverGlobals::DumpPool(AssetDumpingContext& context, AssetPool* pool) -{ - Internal internal(context); - internal.DumpPool(pool); -} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndDriverGlobals.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndDriverGlobals.h deleted file mode 100644 index 18f0cf89..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndDriverGlobals.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" - -namespace T6 -{ - class AssetDumperSndDriverGlobals final : public IAssetDumper - { - class Internal; - - public: - void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperStringTable.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperStringTable.cpp deleted file mode 100644 index 2fb76cec..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperStringTable.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "AssetDumperStringTable.h" - -#include "Csv/CsvStream.h" - -using namespace T6; - -bool AssetDumperStringTable::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperStringTable::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* stringTable = asset->Asset(); - const auto assetFile = context.OpenAssetFile(asset->m_name); - - if (!assetFile) - return; - - CsvOutputStream csv(*assetFile); - - for (auto row = 0; row < stringTable->rowCount; row++) - { - for (auto column = 0; column < stringTable->columnCount; column++) - { - const auto* cell = &stringTable->values[column + row * stringTable->columnCount]; - if (cell->string != nullptr) - { - csv.WriteColumn(cell->string); - } - else - { - csv.WriteColumn(""); - } - } - - csv.NextRow(); - } -} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperStringTable.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperStringTable.h deleted file mode 100644 index 1618db88..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperStringTable.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" - -namespace T6 -{ - class AssetDumperStringTable final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTechniqueSet.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTechniqueSet.cpp deleted file mode 100644 index e5b0b142..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTechniqueSet.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include "AssetDumperTechniqueSet.h" - -#include -#include - -using namespace T6; - -class ShaderZoneState final : public IZoneAssetDumperState -{ -public: - bool ShouldDumpTechnique(const MaterialTechnique* technique) - { - const auto existingTechnique = m_dumped_techniques.find(technique); - if (existingTechnique == m_dumped_techniques.end()) - { - m_dumped_techniques.emplace(technique); - return true; - } - - return false; - } - - bool ShouldDumpPixelShader(const MaterialPixelShader* pixelShader) - { - const auto existingPixelShader = m_dumped_pixel_shaders.find(pixelShader); - if (existingPixelShader == m_dumped_pixel_shaders.end()) - { - m_dumped_pixel_shaders.emplace(pixelShader); - return true; - } - - return false; - } - - bool ShouldDumpVertexShader(const MaterialVertexShader* vertexShader) - { - const auto existingVertexShader = m_dumped_vertex_shaders.find(vertexShader); - if (existingVertexShader == m_dumped_vertex_shaders.end()) - { - m_dumped_vertex_shaders.emplace(vertexShader); - return true; - } - - return false; - } - -private: - std::unordered_set m_dumped_techniques; - std::unordered_set m_dumped_pixel_shaders; - std::unordered_set m_dumped_vertex_shaders; -}; - -bool AssetDumperTechniqueSet::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperTechniqueSet::DumpPixelShader(const AssetDumpingContext& context, const MaterialPixelShader* pixelShader) -{ - std::ostringstream ss; - ss << "shader_bin/ps_" << pixelShader->name << ".cso"; - - const auto shaderFile = context.OpenAssetFile(ss.str()); - - if (!shaderFile) - return; - - shaderFile->write(pixelShader->prog.loadDef.program, pixelShader->prog.loadDef.programSize); -} - -void AssetDumperTechniqueSet::DumpVertexShader(const AssetDumpingContext& context, const MaterialVertexShader* vertexShader) -{ - std::ostringstream ss; - ss << "shader_bin/vs_" << vertexShader->name << ".cso"; - - const auto shaderFile = context.OpenAssetFile(ss.str()); - - if (!shaderFile) - return; - - shaderFile->write(vertexShader->prog.loadDef.program, vertexShader->prog.loadDef.programSize); -} - -void AssetDumperTechniqueSet::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* techniqueSet = asset->Asset(); - auto* shaderState = context.GetZoneAssetDumperState(); - - for (const auto* technique : techniqueSet->techniques) - { - if (!technique || !shaderState->ShouldDumpTechnique(technique)) - continue; - - for (auto passIndex = 0u; passIndex < technique->passCount; passIndex++) - { - const auto* pixelShader = technique->passArray[passIndex].pixelShader; - - if (pixelShader && shaderState->ShouldDumpPixelShader(pixelShader)) - DumpPixelShader(context, pixelShader); - - const auto* vertexShader = technique->passArray[passIndex].vertexShader; - if (vertexShader && shaderState->ShouldDumpVertexShader(vertexShader)) - DumpVertexShader(context, vertexShader); - } - } -} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTechniqueSet.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTechniqueSet.h deleted file mode 100644 index 5a34305e..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTechniqueSet.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" - -namespace T6 -{ - class AssetDumperTechniqueSet final : public AbstractAssetDumper - { - static void DumpPixelShader(const AssetDumpingContext& context, const MaterialPixelShader* pixelShader); - static void DumpVertexShader(const AssetDumpingContext& context, const MaterialVertexShader* vertexShader); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTracer.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTracer.cpp deleted file mode 100644 index 0c87e4ee..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTracer.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include "AssetDumperTracer.h" - -#include "Game/T6/InfoString/InfoStringFromStructConverter.h" -#include "Game/T6/ObjConstantsT6.h" -#include "Game/T6/Tracer/TracerFields.h" - -#include -#include - -using namespace T6; - -namespace T6 -{ - class InfoStringFromTracerConverter final : public InfoStringFromStructConverter - { - protected: - void FillFromExtensionField(const cspField_t& field) override - { - switch (static_cast(field.iFieldType)) - { - case TFT_TRACERTYPE: - FillFromEnumInt(std::string(field.szName), field.iOffset, tracerTypeNames, std::extent_v); - break; - - case TFT_NUM_FIELD_TYPES: - default: - assert(false); - break; - } - } - - public: - InfoStringFromTracerConverter(const TracerDef* structure, - const cspField_t* fields, - const size_t fieldCount, - std::function scriptStringValueCallback) - : InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback)) - { - } - }; -} // namespace T6 - -InfoString AssetDumperTracer::CreateInfoString(XAssetInfo* asset) -{ - InfoStringFromTracerConverter converter(asset->Asset(), - tracer_fields, - std::extent_v, - [asset](const scr_string_t scrStr) -> std::string - { - assert(scrStr < asset->m_zone->m_script_strings.Count()); - if (scrStr >= asset->m_zone->m_script_strings.Count()) - return ""; - - return asset->m_zone->m_script_strings[scrStr]; - }); - - return converter.Convert(); -} - -bool AssetDumperTracer::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperTracer::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - // Only dump raw when no gdt available - if (context.m_gdt) - { - const auto infoString = CreateInfoString(asset); - GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_TRACER); - infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_TRACER, gdtEntry); - context.m_gdt->WriteEntry(gdtEntry); - } - else - { - const auto assetFile = context.OpenAssetFile("tracer/" + asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - const auto infoString = CreateInfoString(asset); - const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_TRACER); - stream.write(stringValue.c_str(), stringValue.size()); - } -} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTracer.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTracer.h deleted file mode 100644 index 51c25c02..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperTracer.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" -#include "InfoString/InfoString.h" - -namespace T6 -{ - class AssetDumperTracer final : public AbstractAssetDumper - { - static InfoString CreateInfoString(XAssetInfo* asset); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperVehicle.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperVehicle.h deleted file mode 100644 index a8c8421e..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperVehicle.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" -#include "InfoString/InfoString.h" - -namespace T6 -{ - class AssetDumperVehicle final : public AbstractAssetDumper - { - static InfoString CreateInfoString(XAssetInfo* asset); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeapon.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeapon.h deleted file mode 100644 index d8f9d746..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeapon.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" -#include "InfoString/InfoString.h" - -namespace T6 -{ - class AssetDumperWeapon final : public AbstractAssetDumper - { - static void CopyToFullDef(const WeaponVariantDef* weapon, WeaponFullDef* fullDef); - static InfoString CreateInfoString(XAssetInfo* asset); - static void DumpAccuracyGraphs(AssetDumpingContext& context, XAssetInfo* asset); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponAttachment.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponAttachment.cpp deleted file mode 100644 index 0c7fd032..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponAttachment.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#include "AssetDumperWeaponAttachment.h" - -#include "Game/T6/InfoString/InfoStringFromStructConverter.h" -#include "Game/T6/ObjConstantsT6.h" -#include "Game/T6/Weapon/AttachmentFields.h" -#include "Game/T6/Weapon/WeaponStrings.h" - -#include -#include - -using namespace T6; - -namespace T6 -{ - class InfoStringFromAttachmentConverter final : public InfoStringFromStructConverter - { - protected: - void FillFromExtensionField(const cspField_t& field) override - { - switch (static_cast(field.iFieldType)) - { - case AFT_ATTACHMENTTYPE: - FillFromEnumInt(std::string(field.szName), field.iOffset, szAttachmentTypeNames, std::extent_v); - break; - - case AFT_PENETRATE_TYPE: - FillFromEnumInt(std::string(field.szName), field.iOffset, penetrateTypeNames, std::extent_v); - break; - - case AFT_FIRETYPE: - FillFromEnumInt(std::string(field.szName), field.iOffset, szWeapFireTypeNames, std::extent_v); - break; - - default: - break; - } - } - - public: - InfoStringFromAttachmentConverter(const WeaponAttachment* structure, - const cspField_t* fields, - const size_t fieldCount, - std::function scriptStringValueCallback) - : InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback)) - { - } - }; -} // namespace T6 - -InfoString AssetDumperWeaponAttachment::CreateInfoString(XAssetInfo* asset) -{ - InfoStringFromAttachmentConverter converter(asset->Asset(), - attachment_fields, - std::extent_v, - [asset](const scr_string_t scrStr) -> std::string - { - assert(scrStr < asset->m_zone->m_script_strings.Count()); - if (scrStr >= asset->m_zone->m_script_strings.Count()) - return ""; - - return asset->m_zone->m_script_strings[scrStr]; - }); - - return converter.Convert(); -} - -bool AssetDumperWeaponAttachment::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperWeaponAttachment::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - // Only dump raw when no gdt available - if (context.m_gdt) - { - const auto infoString = CreateInfoString(asset); - GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_WEAPON_ATTACHMENT); - infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_WEAPON_ATTACHMENT, gdtEntry); - context.m_gdt->WriteEntry(gdtEntry); - } - else - { - const auto assetFile = context.OpenAssetFile("attachment/" + asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - const auto infoString = CreateInfoString(asset); - const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_WEAPON_ATTACHMENT); - stream.write(stringValue.c_str(), stringValue.size()); - } -} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponAttachment.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponAttachment.h deleted file mode 100644 index cde27cf5..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponAttachment.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" -#include "InfoString/InfoString.h" - -namespace T6 -{ - class AssetDumperWeaponAttachment final : public AbstractAssetDumper - { - static InfoString CreateInfoString(XAssetInfo* asset); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponAttachmentUnique.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponAttachmentUnique.cpp deleted file mode 100644 index 6730771a..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponAttachmentUnique.cpp +++ /dev/null @@ -1,158 +0,0 @@ -#include "AssetDumperWeaponAttachmentUnique.h" - -#include "Game/T6/InfoString/InfoStringFromStructConverter.h" -#include "Game/T6/ObjConstantsT6.h" -#include "Game/T6/Weapon/AttachmentUniqueFields.h" -#include "Game/T6/Weapon/WeaponStrings.h" - -#include -#include -#include -#include - -using namespace T6; - -namespace T6 -{ - class InfoStringFromWeaponAttachmentUniqueConverter final : public InfoStringFromStructConverter - { - protected: - void FillFromExtensionField(const cspField_t& field) override - { - switch (static_cast(field.iFieldType)) - { - case AUFT_ATTACHMENTTYPE: - FillFromEnumInt(std::string(field.szName), field.iOffset, szAttachmentTypeNames, std::extent_v); - break; - - case AUFT_HIDETAGS: - { - const auto* hideTags = reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset); - std::stringstream ss; - auto first = true; - - for (auto i = 0u; i < std::extent_v; i++) - { - const auto& str = m_get_scr_string(hideTags[i]); - if (!str.empty()) - { - if (!first) - ss << "\n"; - else - first = false; - - ss << str; - } - } - - m_info_string.SetValueForKey(std::string(field.szName), ss.str()); - break; - } - - case AUFT_OVERLAYRETICLE: - FillFromEnumInt(std::string(field.szName), field.iOffset, szWeapOverlayReticleNames, std::extent_v); - break; - - case AUFT_CAMO: - { - const auto* camo = *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset); - - if (camo) - m_info_string.SetValueForKey(std::string(field.szName), std::string(AssetName(camo->name))); - else - m_info_string.SetValueForKey(std::string(field.szName), ""); - break; - } - - default: - assert(false); - break; - } - } - - public: - InfoStringFromWeaponAttachmentUniqueConverter(const WeaponAttachmentUniqueFull* structure, - const cspField_t* fields, - const size_t fieldCount, - std::function scriptStringValueCallback) - : InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback)) - { - } - }; -} // namespace T6 - -void AssetDumperWeaponAttachmentUnique::CopyToFullDef(const WeaponAttachmentUnique* attachment, WeaponAttachmentUniqueFull* fullDef) -{ - fullDef->attachment = *attachment; - - if (attachment->szXAnims) - { - assert(sizeof(WeaponAttachmentUniqueFull::szXAnims) >= sizeof(void*) * NUM_WEAP_ANIMS); - memcpy(fullDef->szXAnims, attachment->szXAnims, sizeof(void*) * NUM_WEAP_ANIMS); - fullDef->attachment.szXAnims = fullDef->szXAnims; - } - - if (attachment->hideTags) - { - assert(sizeof(WeaponAttachmentUniqueFull::hideTags) >= sizeof(scr_string_t) * std::extent_v); - memcpy(fullDef->hideTags, attachment->hideTags, sizeof(scr_string_t) * std::extent_v); - fullDef->attachment.hideTags = fullDef->hideTags; - } - - if (attachment->locationDamageMultipliers) - { - assert(sizeof(WeaponAttachmentUniqueFull::locationDamageMultipliers) >= sizeof(float) * HITLOC_COUNT); - memcpy(fullDef->locationDamageMultipliers, attachment->locationDamageMultipliers, sizeof(float) * HITLOC_COUNT); - fullDef->attachment.locationDamageMultipliers = fullDef->locationDamageMultipliers; - } -} - -InfoString AssetDumperWeaponAttachmentUnique::CreateInfoString(XAssetInfo* asset) -{ - const auto fullDef = std::make_unique(); - memset(fullDef.get(), 0, sizeof(WeaponAttachmentUniqueFull)); - CopyToFullDef(asset->Asset(), fullDef.get()); - - InfoStringFromWeaponAttachmentUniqueConverter converter(fullDef.get(), - attachment_unique_fields, - std::extent_v, - [asset](const scr_string_t scrStr) -> std::string - { - assert(scrStr < asset->m_zone->m_script_strings.Count()); - if (scrStr >= asset->m_zone->m_script_strings.Count()) - return ""; - - return asset->m_zone->m_script_strings[scrStr]; - }); - - return converter.Convert(); -} - -bool AssetDumperWeaponAttachmentUnique::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperWeaponAttachmentUnique::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - // Only dump raw when no gdt available - if (context.m_gdt) - { - const auto infoString = CreateInfoString(asset); - GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_WEAPON_ATTACHMENT_UNIQUE); - infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_WEAPON_ATTACHMENT_UNIQUE, gdtEntry); - context.m_gdt->WriteEntry(gdtEntry); - } - else - { - const auto assetFile = context.OpenAssetFile("attachmentunique/" + asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - const auto infoString = CreateInfoString(asset); - const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_WEAPON_ATTACHMENT_UNIQUE); - stream.write(stringValue.c_str(), stringValue.size()); - } -} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponAttachmentUnique.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponAttachmentUnique.h deleted file mode 100644 index 4d6a9c41..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponAttachmentUnique.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" -#include "InfoString/InfoString.h" - -namespace T6 -{ - class AssetDumperWeaponAttachmentUnique final : public AbstractAssetDumper - { - static void CopyToFullDef(const WeaponAttachmentUnique* attachment, WeaponAttachmentUniqueFull* fullDef); - static InfoString CreateInfoString(XAssetInfo* asset); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponCamo.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponCamo.cpp deleted file mode 100644 index 4631e962..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponCamo.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "AssetDumperWeaponCamo.h" - -#include "Game/T6/WeaponCamo/JsonWeaponCamoWriter.h" - -#include - -using namespace T6; - -bool AssetDumperWeaponCamo::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperWeaponCamo::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto fileName = std::format("camo/{}.json", asset->m_name); - const auto assetFile = context.OpenAssetFile(fileName); - - if (!assetFile) - return; - - DumpWeaponCamoAsJson(*assetFile, asset->Asset()); -} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponCamo.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponCamo.h deleted file mode 100644 index 36b2df92..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeaponCamo.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" - -namespace T6 -{ - class AssetDumperWeaponCamo final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperXModel.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperXModel.cpp deleted file mode 100644 index 24dc56dc..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperXModel.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "AssetDumperXModel.h" - -#include "Game/T6/XModel/XModelDumperT6.h" - -using namespace T6; - -bool AssetDumperXModel::ShouldDump(XAssetInfo* asset) -{ - return !asset->m_name.empty() && asset->m_name[0] != ','; -} - -void AssetDumperXModel::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - DumpXModel(context, asset); -} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperXModel.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperXModel.h deleted file mode 100644 index 75218729..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperXModel.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" - -namespace T6 -{ - class AssetDumperXModel final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperZBarrier.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperZBarrier.cpp deleted file mode 100644 index da165648..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperZBarrier.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "AssetDumperZBarrier.h" - -#include "Game/T6/InfoString/InfoStringFromStructConverter.h" -#include "Game/T6/ObjConstantsT6.h" -#include "Game/T6/ZBarrier/ZBarrierFields.h" - -#include -#include - -using namespace T6; - -namespace T6 -{ - class InfoStringFromZBarrierConverter final : public InfoStringFromStructConverter - { - protected: - void FillFromExtensionField(const cspField_t& field) override - { - assert(false); - } - - public: - InfoStringFromZBarrierConverter(const ZBarrierDef* structure, - const cspField_t* fields, - const size_t fieldCount, - std::function scriptStringValueCallback) - : InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback)) - { - } - }; -} // namespace T6 - -InfoString AssetDumperZBarrier::CreateInfoString(XAssetInfo* asset) -{ - InfoStringFromZBarrierConverter converter(asset->Asset(), - zbarrier_fields, - std::extent_v, - [asset](const scr_string_t scrStr) -> std::string - { - assert(scrStr < asset->m_zone->m_script_strings.Count()); - if (scrStr >= asset->m_zone->m_script_strings.Count()) - return ""; - - return asset->m_zone->m_script_strings[scrStr]; - }); - - return converter.Convert(); -} - -bool AssetDumperZBarrier::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperZBarrier::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - // Only dump raw when no gdt available - if (context.m_gdt) - { - const auto infoString = CreateInfoString(asset); - GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_ZBARRIER); - infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_ZBARRIER, gdtEntry); - context.m_gdt->WriteEntry(gdtEntry); - } - else - { - const auto assetFile = context.OpenAssetFile("zbarrier/" + asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - const auto infoString = CreateInfoString(asset); - const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_ZBARRIER); - stream.write(stringValue.c_str(), stringValue.size()); - } -} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperZBarrier.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperZBarrier.h deleted file mode 100644 index 0a2ba56d..00000000 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperZBarrier.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" -#include "InfoString/InfoString.h" - -namespace T6 -{ - class AssetDumperZBarrier final : public AbstractAssetDumper - { - static InfoString CreateInfoString(XAssetInfo* asset); - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/FontIcon/DumperFontIconCsvT6.h b/src/ObjWriting/Game/T6/FontIcon/DumperFontIconCsvT6.h deleted file mode 100644 index bbdc5649..00000000 --- a/src/ObjWriting/Game/T6/FontIcon/DumperFontIconCsvT6.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" - -namespace T6 -{ - void DumpFontIconAsCsv(const AssetDumpingContext& context, const FontIcon& fontIcon); -} diff --git a/src/ObjWriting/Game/T6/FontIcon/DumperFontIconJsonT6.h b/src/ObjWriting/Game/T6/FontIcon/DumperFontIconJsonT6.h deleted file mode 100644 index 7603e35d..00000000 --- a/src/ObjWriting/Game/T6/FontIcon/DumperFontIconJsonT6.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" - -namespace T6 -{ - void DumpFontIconAsJson(const AssetDumpingContext& context, const FontIcon& fontIcon); -} diff --git a/src/ObjWriting/Game/T6/FontIcon/DumperFontIconT6.cpp b/src/ObjWriting/Game/T6/FontIcon/DumperFontIconT6.cpp deleted file mode 100644 index 91dc5946..00000000 --- a/src/ObjWriting/Game/T6/FontIcon/DumperFontIconT6.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "DumperFontIconT6.h" - -#include "DumperFontIconCsvT6.h" -#include "DumperFontIconJsonT6.h" - -using namespace T6; - -// #define DUMP_FONT_ICON_AS_CSV 1 - -bool AssetDumperFontIcon::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperFontIcon::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ -#ifdef DUMP_FONT_ICON_AS_CSV - DumpFontIconAsCsv(context, *asset->Asset()); -#else - DumpFontIconAsJson(context, *asset->Asset()); -#endif -} diff --git a/src/ObjWriting/Game/T6/FontIcon/DumperFontIconT6.h b/src/ObjWriting/Game/T6/FontIcon/DumperFontIconT6.h deleted file mode 100644 index 0581829f..00000000 --- a/src/ObjWriting/Game/T6/FontIcon/DumperFontIconT6.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" - -namespace T6 -{ - class AssetDumperFontIcon final : public AbstractAssetDumper - { - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/FontIcon/DumperFontIconCsvT6.cpp b/src/ObjWriting/Game/T6/FontIcon/FontIconCsvDumperT6.cpp similarity index 88% rename from src/ObjWriting/Game/T6/FontIcon/DumperFontIconCsvT6.cpp rename to src/ObjWriting/Game/T6/FontIcon/FontIconCsvDumperT6.cpp index a6b199ae..95c6f1cc 100644 --- a/src/ObjWriting/Game/T6/FontIcon/DumperFontIconCsvT6.cpp +++ b/src/ObjWriting/Game/T6/FontIcon/FontIconCsvDumperT6.cpp @@ -1,4 +1,4 @@ -#include "DumperFontIconCsvT6.h" +#include "FontIconCsvDumperT6.h" #include "Csv/CsvStream.h" #include "Game/T6/CommonT6.h" @@ -52,15 +52,15 @@ namespace } } - class DumperFontIconCsv + class Dumper { public: - explicit DumperFontIconCsv(std::ostream& stream) + explicit Dumper(std::ostream& stream) : m_csv(stream) { } - void DumpFontIcon(const FontIcon& fontIcon) + void Dump(const FontIcon& fontIcon) { WriteFontIconEntries(fontIcon); m_csv.NextRow(); @@ -131,16 +131,21 @@ namespace }; } // namespace -namespace T6 +namespace font_icon { - void DumpFontIconAsCsv(const AssetDumpingContext& context, const FontIcon& fontIcon) + bool CsvDumperT6::ShouldDump(XAssetInfo* asset) { - const auto assetFile = context.OpenAssetFile(fontIcon.name); + return true; + } + + void CsvDumperT6::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto assetFile = context.OpenAssetFile(asset->m_name); if (!assetFile) return; - DumperFontIconCsv dumperFontIconCsv(*assetFile); - dumperFontIconCsv.DumpFontIcon(fontIcon); + Dumper dumper(*assetFile); + dumper.Dump(*asset->Asset()); } -} // namespace T6 +} // namespace font_icon diff --git a/src/ObjWriting/Game/T6/FontIcon/FontIconCsvDumperT6.h b/src/ObjWriting/Game/T6/FontIcon/FontIconCsvDumperT6.h new file mode 100644 index 00000000..aeaa8877 --- /dev/null +++ b/src/ObjWriting/Game/T6/FontIcon/FontIconCsvDumperT6.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" + +namespace font_icon +{ + class CsvDumperT6 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace font_icon diff --git a/src/ObjWriting/Game/T6/FontIcon/FontIconDumperT6.cpp b/src/ObjWriting/Game/T6/FontIcon/FontIconDumperT6.cpp new file mode 100644 index 00000000..9f41412b --- /dev/null +++ b/src/ObjWriting/Game/T6/FontIcon/FontIconDumperT6.cpp @@ -0,0 +1,20 @@ +#include "FontIconDumperT6.h" + +#include "FontIconCsvDumperT6.h" +#include "FontIconJsonDumperT6.h" + +using namespace T6; + +// #define DUMP_FONT_ICON_AS_CSV 1 + +namespace font_icon +{ + std::unique_ptr> CreateDumperT6() + { +#ifdef DUMP_FONT_ICON_AS_CSV + return std::make_unique(); +#else + return std::make_unique(); +#endif + } +} // namespace font_icon diff --git a/src/ObjWriting/Game/T6/FontIcon/FontIconDumperT6.h b/src/ObjWriting/Game/T6/FontIcon/FontIconDumperT6.h new file mode 100644 index 00000000..55d048f9 --- /dev/null +++ b/src/ObjWriting/Game/T6/FontIcon/FontIconDumperT6.h @@ -0,0 +1,11 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" + +#include + +namespace font_icon +{ + std::unique_ptr> CreateDumperT6(); +} // namespace font_icon diff --git a/src/ObjWriting/Game/T6/FontIcon/DumperFontIconJsonT6.cpp b/src/ObjWriting/Game/T6/FontIcon/FontIconJsonDumperT6.cpp similarity index 85% rename from src/ObjWriting/Game/T6/FontIcon/DumperFontIconJsonT6.cpp rename to src/ObjWriting/Game/T6/FontIcon/FontIconJsonDumperT6.cpp index f532ebe3..e82b3b36 100644 --- a/src/ObjWriting/Game/T6/FontIcon/DumperFontIconJsonT6.cpp +++ b/src/ObjWriting/Game/T6/FontIcon/FontIconJsonDumperT6.cpp @@ -1,7 +1,7 @@ -#include "DumperFontIconJsonT6.h" +#include "FontIconJsonDumperT6.h" +#include "FontIcon/FontIconCommon.h" #include "Game/T6/CommonT6.h" -#include "Game/T6/FontIcon/FontIconCommonT6.h" #include "Game/T6/FontIcon/JsonFontIconT6.h" #include "KnownFontIconAliasesT6.h" @@ -76,15 +76,20 @@ namespace } } // namespace -namespace T6 +namespace font_icon { - void DumpFontIconAsJson(const AssetDumpingContext& context, const FontIcon& fontIcon) + bool JsonDumperT6::ShouldDump(XAssetInfo* asset) { - const auto assetFile = context.OpenAssetFile(font_icon::GetJsonFileNameForAssetName(fontIcon.name)); + return true; + } + + void JsonDumperT6::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto assetFile = context.OpenAssetFile(GetJsonFileNameForAssetName(asset->m_name)); if (!assetFile) return; - DumpFontIcon(*assetFile, fontIcon); + DumpFontIcon(*assetFile, *asset->Asset()); } -} // namespace T6 +} // namespace font_icon diff --git a/src/ObjWriting/Game/T6/FontIcon/FontIconJsonDumperT6.h b/src/ObjWriting/Game/T6/FontIcon/FontIconJsonDumperT6.h new file mode 100644 index 00000000..aa1c0017 --- /dev/null +++ b/src/ObjWriting/Game/T6/FontIcon/FontIconJsonDumperT6.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" + +namespace font_icon +{ + class JsonDumperT6 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace font_icon diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperGfxImage.cpp b/src/ObjWriting/Game/T6/Image/ImageDumperT6.cpp similarity index 62% rename from src/ObjWriting/Game/T6/AssetDumpers/AssetDumperGfxImage.cpp rename to src/ObjWriting/Game/T6/Image/ImageDumperT6.cpp index f529cca1..bb3255b2 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperGfxImage.cpp +++ b/src/ObjWriting/Game/T6/Image/ImageDumperT6.cpp @@ -1,7 +1,8 @@ -#include "AssetDumperGfxImage.h" +#include "ImageDumperT6.h" #include "Image/DdsWriter.h" #include "Image/Dx12TextureLoader.h" +#include "Image/ImageCommon.h" #include "Image/IwiLoader.h" #include "Image/IwiWriter27.h" #include "ObjContainer/IPak/IPak.h" @@ -53,7 +54,7 @@ namespace } } - const auto imageFileName = std::format("images/{}.iwi", image.name); + const auto imageFileName = image::GetFileNameForAsset(image.name, ".iwi"); const auto filePathImage = searchPath.Open(imageFileName); if (!filePathImage.IsOpen()) { @@ -73,48 +74,43 @@ namespace } } // namespace -AssetDumperGfxImage::AssetDumperGfxImage() +namespace image { - switch (ObjWriting::Configuration.ImageOutputFormat) + DumperT6::DumperT6() { - case ObjWriting::Configuration_t::ImageOutputFormat_e::DDS: - m_writer = std::make_unique(); - break; - case ObjWriting::Configuration_t::ImageOutputFormat_e::IWI: - m_writer = std::make_unique(); - break; - default: - assert(false); - m_writer = nullptr; - break; + switch (ObjWriting::Configuration.ImageOutputFormat) + { + case ObjWriting::Configuration_t::ImageOutputFormat_e::DDS: + m_writer = std::make_unique(); + break; + case ObjWriting::Configuration_t::ImageOutputFormat_e::IWI: + m_writer = std::make_unique(); + break; + default: + assert(false); + m_writer = nullptr; + break; + } } -} -bool AssetDumperGfxImage::ShouldDump(XAssetInfo* asset) -{ - return true; -} + bool DumperT6::ShouldDump(XAssetInfo* asset) + { + return true; + } -std::string AssetDumperGfxImage::GetAssetFileName(const XAssetInfo& asset) const -{ - auto cleanAssetName = asset.m_name; - std::ranges::replace(cleanAssetName, '*', '_'); + void DumperT6::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* image = asset->Asset(); + const auto texture = LoadImageData(context.m_obj_search_path, *image); + if (!texture) + return; - return std::format("images/{}{}", cleanAssetName, m_writer->GetFileExtension()); -} + const auto assetFile = context.OpenAssetFile(GetFileNameForAsset(asset->m_name, m_writer->GetFileExtension())); -void AssetDumperGfxImage::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto* image = asset->Asset(); - const auto texture = LoadImageData(context.m_obj_search_path, *image); - if (!texture) - return; + if (!assetFile) + return; - const auto assetFile = context.OpenAssetFile(GetAssetFileName(*asset)); - - if (!assetFile) - return; - - auto& stream = *assetFile; - m_writer->DumpImage(stream, texture.get()); -} + auto& stream = *assetFile; + m_writer->DumpImage(stream, texture.get()); + } +} // namespace image diff --git a/src/ObjWriting/Game/T6/Image/ImageDumperT6.h b/src/ObjWriting/Game/T6/Image/ImageDumperT6.h new file mode 100644 index 00000000..5fac0233 --- /dev/null +++ b/src/ObjWriting/Game/T6/Image/ImageDumperT6.h @@ -0,0 +1,23 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" +#include "Image/IImageWriter.h" + +#include + +namespace image +{ + class DumperT6 final : public AbstractAssetDumper + { + public: + DumperT6(); + + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + + private: + std::unique_ptr m_writer; + }; +} // namespace image diff --git a/src/ObjWriting/Game/T6/Leaderboard/JsonLeaderboardDefWriter.h b/src/ObjWriting/Game/T6/Leaderboard/JsonLeaderboardDefWriter.h deleted file mode 100644 index cdc31389..00000000 --- a/src/ObjWriting/Game/T6/Leaderboard/JsonLeaderboardDefWriter.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "Dumping/AssetDumpingContext.h" -#include "Game/T6/T6.h" - -#include - -namespace T6 -{ - void DumpLeaderboardDefAsJson(std::ostream& stream, const LeaderboardDef* leaderboardDef); -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/Leaderboard/JsonLeaderboardDefWriter.cpp b/src/ObjWriting/Game/T6/Leaderboard/LeaderboardJsonDumperT6.cpp similarity index 78% rename from src/ObjWriting/Game/T6/Leaderboard/JsonLeaderboardDefWriter.cpp rename to src/ObjWriting/Game/T6/Leaderboard/LeaderboardJsonDumperT6.cpp index a559881f..4a90d7b2 100644 --- a/src/ObjWriting/Game/T6/Leaderboard/JsonLeaderboardDefWriter.cpp +++ b/src/ObjWriting/Game/T6/Leaderboard/LeaderboardJsonDumperT6.cpp @@ -1,28 +1,30 @@ -#include "JsonLeaderboardDefWriter.h" +#include "LeaderboardJsonDumperT6.h" #include "Game/T6/CommonT6.h" #include "Game/T6/Leaderboard/JsonLeaderboardDef.h" +#include "Leaderboard/LeaderboardCommon.h" #include #include +#include using namespace nlohmann; using namespace T6; namespace { - class JsonDumper + class Dumper { public: - explicit JsonDumper(std::ostream& stream) + explicit Dumper(std::ostream& stream) : m_stream(stream) { } - void Dump(const LeaderboardDef* leaderboardDef) const + void Dump(const LeaderboardDef& leaderboardDef) const { JsonLeaderboardDef jsonLeaderboardDef; - CreateJsonLeaderboardDef(jsonLeaderboardDef, *leaderboardDef); + CreateJsonLeaderboardDef(jsonLeaderboardDef, leaderboardDef); json jRoot = jsonLeaderboardDef; @@ -94,11 +96,21 @@ namespace }; } // namespace -namespace T6 +namespace leaderboard { - void DumpLeaderboardDefAsJson(std::ostream& stream, const LeaderboardDef* leaderboardDef) + bool JsonDumperT6::ShouldDump(XAssetInfo* asset) { - JsonDumper dumper(stream); - dumper.Dump(leaderboardDef); + return true; } -} // namespace T6 + + void JsonDumperT6::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto assetFile = context.OpenAssetFile(GetJsonFileNameForAsset(asset->m_name)); + + if (!assetFile) + return; + + Dumper dumper(*assetFile); + dumper.Dump(*asset->Asset()); + } +} // namespace leaderboard diff --git a/src/ObjWriting/Game/T6/Leaderboard/LeaderboardJsonDumperT6.h b/src/ObjWriting/Game/T6/Leaderboard/LeaderboardJsonDumperT6.h new file mode 100644 index 00000000..ebbe4c9f --- /dev/null +++ b/src/ObjWriting/Game/T6/Leaderboard/LeaderboardJsonDumperT6.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" + +namespace leaderboard +{ + class JsonDumperT6 final : public AbstractAssetDumper + { + protected: + [[nodiscard]] bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace leaderboard diff --git a/src/ObjWriting/Game/T6/Localize/LocalizeDumperT6.cpp b/src/ObjWriting/Game/T6/Localize/LocalizeDumperT6.cpp new file mode 100644 index 00000000..550b92d6 --- /dev/null +++ b/src/ObjWriting/Game/T6/Localize/LocalizeDumperT6.cpp @@ -0,0 +1,44 @@ +#include "LocalizeDumperT6.h" + +#include "Dumping/Localize/StringFileDumper.h" +#include "Localize/LocalizeCommon.h" + +#include +#include + +using namespace T6; + +namespace localize +{ + void DumperT6::DumpPool(AssetDumpingContext& context, AssetPool* pool) + { + if (pool->m_asset_lookup.empty()) + return; + + const auto language = LocalizeCommon::GetNameOfLanguage(context.m_zone.m_language); + const auto assetFile = context.OpenAssetFile(std::format("{}/localizedstrings/{}.str", language, context.m_zone.m_name)); + + if (assetFile) + { + StringFileDumper stringFileDumper(context.m_zone, *assetFile); + + stringFileDumper.SetLanguageName(language); + + // Magic string. Original string files do have this config file. The purpose of the config file is unknown though. + stringFileDumper.SetConfigFile(R"(C:/projects/cod/t6/bin/StringEd.cfg)"); + + stringFileDumper.SetNotes(""); + + for (auto* localizeEntry : *pool) + { + stringFileDumper.WriteLocalizeEntry(localizeEntry->m_name, localizeEntry->Asset()->value); + } + + stringFileDumper.Finalize(); + } + else + { + std::cerr << std::format("Could not create string file for dumping localized strings of zone '{}'\n", context.m_zone.m_name); + } + } +} // namespace localize diff --git a/src/ObjWriting/Game/T6/Localize/LocalizeDumperT6.h b/src/ObjWriting/Game/T6/Localize/LocalizeDumperT6.h new file mode 100644 index 00000000..1a39defe --- /dev/null +++ b/src/ObjWriting/Game/T6/Localize/LocalizeDumperT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" + +namespace localize +{ + class DumperT6 final : public IAssetDumper + { + public: + void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; + }; +} // namespace localize diff --git a/src/ObjWriting/Game/T6/Maps/MapEntsDumperT6.cpp b/src/ObjWriting/Game/T6/Maps/MapEntsDumperT6.cpp new file mode 100644 index 00000000..caf8abd5 --- /dev/null +++ b/src/ObjWriting/Game/T6/Maps/MapEntsDumperT6.cpp @@ -0,0 +1,26 @@ +#include "MapEntsDumperT6.h" + +#include + +using namespace T6; + +namespace map_ents +{ + bool DumperT6::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperT6::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* mapEnts = asset->Asset(); + + const auto mapEntsFile = context.OpenAssetFile(std::format("{}.ents", mapEnts->name)); + + if (!mapEntsFile) + return; + + auto& stream = *mapEntsFile; + stream.write(mapEnts->entityString, mapEnts->numEntityChars - 1); + } +} // namespace map_ents diff --git a/src/ObjWriting/Game/T6/Maps/MapEntsDumperT6.h b/src/ObjWriting/Game/T6/Maps/MapEntsDumperT6.h new file mode 100644 index 00000000..9dbf36bb --- /dev/null +++ b/src/ObjWriting/Game/T6/Maps/MapEntsDumperT6.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" + +namespace map_ents +{ + class DumperT6 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace map_ents diff --git a/src/ObjWriting/Game/T6/Material/DumperMaterialT6.cpp b/src/ObjWriting/Game/T6/Material/DumperMaterialT6.cpp deleted file mode 100644 index 56e11e97..00000000 --- a/src/ObjWriting/Game/T6/Material/DumperMaterialT6.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "DumperMaterialT6.h" - -#include "Game/T6/Material/JsonMaterialWriterT6.h" -#include "Game/T6/Material/MaterialConstantZoneStateT6.h" -#include "Material/MaterialCommon.h" - -#include - -using namespace T6; - -void AssetDumperMaterial::DumpPool(AssetDumpingContext& context, AssetPool* pool) -{ - auto* materialConstantState = context.GetZoneAssetDumperState(); - materialConstantState->ExtractNamesFromZone(); - - AbstractAssetDumper::DumpPool(context, pool); -} - -bool AssetDumperMaterial::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperMaterial::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - const auto assetFile = context.OpenAssetFile(material::GetFileNameForAssetName(asset->m_name)); - - if (!assetFile) - return; - - const auto* material = asset->Asset(); - assert(material->info.gameFlags < 0x8000); - assert(material->info.hashIndex == 0); - assert(material->probeMipBits == 0); - DumpMaterialAsJson(*assetFile, *material, context); -} diff --git a/src/ObjWriting/Game/T6/Material/DumperMaterialT6.h b/src/ObjWriting/Game/T6/Material/DumperMaterialT6.h deleted file mode 100644 index 99de31e7..00000000 --- a/src/ObjWriting/Game/T6/Material/DumperMaterialT6.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T6/T6.h" - -namespace T6 -{ - class AssetDumperMaterial final : public AbstractAssetDumper - { - public: - void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; - - protected: - bool ShouldDump(XAssetInfo* asset) override; - void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; - }; -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/ObjWriterT6.cpp b/src/ObjWriting/Game/T6/ObjWriterT6.cpp index 971462b8..06c66520 100644 --- a/src/ObjWriting/Game/T6/ObjWriterT6.cpp +++ b/src/ObjWriting/Game/T6/ObjWriterT6.cpp @@ -1,31 +1,31 @@ #include "ObjWriterT6.h" -#include "AssetDumpers/AssetDumperGfxImage.h" -#include "AssetDumpers/AssetDumperLeaderboardDef.h" -#include "AssetDumpers/AssetDumperLocalizeEntry.h" -#include "AssetDumpers/AssetDumperMapEnts.h" -#include "AssetDumpers/AssetDumperPhysConstraints.h" -#include "AssetDumpers/AssetDumperPhysPreset.h" -#include "AssetDumpers/AssetDumperQdb.h" -#include "AssetDumpers/AssetDumperRawFile.h" -#include "AssetDumpers/AssetDumperScriptParseTree.h" -#include "AssetDumpers/AssetDumperSlug.h" -#include "AssetDumpers/AssetDumperSndBank.h" -#include "AssetDumpers/AssetDumperSndDriverGlobals.h" -#include "AssetDumpers/AssetDumperStringTable.h" -#include "AssetDumpers/AssetDumperTechniqueSet.h" -#include "AssetDumpers/AssetDumperTracer.h" -#include "AssetDumpers/AssetDumperVehicle.h" -#include "AssetDumpers/AssetDumperWeapon.h" -#include "AssetDumpers/AssetDumperWeaponAttachment.h" -#include "AssetDumpers/AssetDumperWeaponAttachmentUnique.h" -#include "AssetDumpers/AssetDumperWeaponCamo.h" -#include "AssetDumpers/AssetDumperXModel.h" -#include "AssetDumpers/AssetDumperZBarrier.h" -#include "FontIcon/DumperFontIconT6.h" +#include "FontIcon/FontIconDumperT6.h" #include "Game/T6/GameAssetPoolT6.h" -#include "Material/DumperMaterialT6.h" +#include "Game/T6/Material/MaterialJsonDumperT6.h" +#include "Game/T6/XModel/XModelDumperT6.h" +#include "Image/ImageDumperT6.h" +#include "Leaderboard/LeaderboardJsonDumperT6.h" +#include "Localize/LocalizeDumperT6.h" +#include "Maps/MapEntsDumperT6.h" #include "ObjWriting.h" +#include "PhysConstraints/PhysConstraintsInfoStringDumperT6.h" +#include "PhysPreset/PhysPresetInfoStringDumperT6.h" +#include "Qdb/QdbDumperT6.h" +#include "RawFile/RawFileDumperT6.h" +#include "Script/ScriptDumperT6.h" +#include "Slug/SlugDumperT6.h" +#include "Sound/SndBankDumperT6.h" +#include "Sound/SndDriverGlobalsDumperT6.h" +#include "StringTable/StringTableDumperT6.h" +#include "Techset/TechsetDumperT6.h" +#include "Tracer/TracerDumperT6.h" +#include "Vehicle/VehicleDumperT6.h" +#include "Weapon/AttachmentDumperT6.h" +#include "Weapon/AttachmentUniqueDumperT6.h" +#include "Weapon/CamoJsonDumperT6.h" +#include "Weapon/WeaponDumperT6.h" +#include "ZBarrier/ZBarrierDumperT6.h" using namespace T6; @@ -37,57 +37,63 @@ bool ObjWriter::DumpZone(AssetDumpingContext& context) const dumperType dumper; \ dumper.DumpPool(context, assetPools->poolName.get()); \ } +#define DUMP_ASSET_POOL_WITH_FACTORY(createDumper, poolName, assetType) \ + if (assetPools->poolName && ObjWriting::ShouldHandleAssetType(assetType)) \ + { \ + const auto dumper = createDumper; \ + dumper->DumpPool(context, assetPools->poolName.get()); \ + } const auto* assetPools = dynamic_cast(context.m_zone.m_pools.get()); - DUMP_ASSET_POOL(AssetDumperPhysPreset, m_phys_preset, ASSET_TYPE_PHYSPRESET) - DUMP_ASSET_POOL(AssetDumperPhysConstraints, m_phys_constraints, ASSET_TYPE_PHYSCONSTRAINTS) + DUMP_ASSET_POOL(phys_preset::InfoStringDumperT6, m_phys_preset, ASSET_TYPE_PHYSPRESET) + DUMP_ASSET_POOL(phys_constraints::InfoStringDumperT6, m_phys_constraints, ASSET_TYPE_PHYSCONSTRAINTS) // DUMP_ASSET_POOL(AssetDumperDestructibleDef, m_destructible_def, ASSET_TYPE_DESTRUCTIBLEDEF) // DUMP_ASSET_POOL(AssetDumperXAnimParts, m_xanim_parts, ASSET_TYPE_XANIMPARTS) - DUMP_ASSET_POOL(AssetDumperXModel, m_xmodel, ASSET_TYPE_XMODEL) - DUMP_ASSET_POOL(AssetDumperMaterial, m_material, ASSET_TYPE_MATERIAL) - DUMP_ASSET_POOL(AssetDumperTechniqueSet, m_technique_set, ASSET_TYPE_TECHNIQUE_SET) - DUMP_ASSET_POOL(AssetDumperGfxImage, m_image, ASSET_TYPE_IMAGE) - DUMP_ASSET_POOL(AssetDumperSndBank, m_sound_bank, ASSET_TYPE_SOUND) + DUMP_ASSET_POOL(xmodel::DumperT6, m_xmodel, ASSET_TYPE_XMODEL) + DUMP_ASSET_POOL(material::JsonDumperT6, m_material, ASSET_TYPE_MATERIAL) + DUMP_ASSET_POOL(techset::DumperT6, m_technique_set, ASSET_TYPE_TECHNIQUE_SET) + DUMP_ASSET_POOL(image::DumperT6, m_image, ASSET_TYPE_IMAGE) + DUMP_ASSET_POOL(sound::SndBankDumperT6, m_sound_bank, ASSET_TYPE_SOUND) // DUMP_ASSET_POOL(AssetDumperSndPatch, m_sound_patch, ASSET_TYPE_SOUND_PATCH) // DUMP_ASSET_POOL(AssetDumperClipMap, m_clip_map, ASSET_TYPE_CLIPMAP_PVS) // DUMP_ASSET_POOL(AssetDumperComWorld, m_com_world, ASSET_TYPE_COMWORLD) // DUMP_ASSET_POOL(AssetDumperGameWorldSp, m_game_world_sp, ASSET_TYPE_GAMEWORLD_SP) // DUMP_ASSET_POOL(AssetDumperGameWorldMp, m_game_world_mp, ASSET_TYPE_GAMEWORLD_MP) - DUMP_ASSET_POOL(AssetDumperMapEnts, m_map_ents, ASSET_TYPE_MAP_ENTS) + DUMP_ASSET_POOL(map_ents::DumperT6, m_map_ents, ASSET_TYPE_MAP_ENTS) // DUMP_ASSET_POOL(AssetDumperGfxWorld, m_gfx_world, ASSET_TYPE_GFXWORLD) // DUMP_ASSET_POOL(AssetDumperGfxLightDef, m_gfx_light_def, ASSET_TYPE_LIGHT_DEF) // DUMP_ASSET_POOL(AssetDumperFont, m_font, ASSET_TYPE_FONT) - DUMP_ASSET_POOL(AssetDumperFontIcon, m_font_icon, ASSET_TYPE_FONTICON) + DUMP_ASSET_POOL_WITH_FACTORY(font_icon::CreateDumperT6(), m_font_icon, ASSET_TYPE_FONTICON) // DUMP_ASSET_POOL(AssetDumperMenuList, m_menu_list, ASSET_TYPE_MENULIST) // DUMP_ASSET_POOL(AssetDumperMenuDef, m_menu_def, ASSET_TYPE_MENU) - DUMP_ASSET_POOL(AssetDumperLocalizeEntry, m_localize, ASSET_TYPE_LOCALIZE_ENTRY) - DUMP_ASSET_POOL(AssetDumperWeapon, m_weapon, ASSET_TYPE_WEAPON) - DUMP_ASSET_POOL(AssetDumperWeaponAttachment, m_attachment, ASSET_TYPE_ATTACHMENT) - DUMP_ASSET_POOL(AssetDumperWeaponAttachmentUnique, m_attachment_unique, ASSET_TYPE_ATTACHMENT_UNIQUE) - DUMP_ASSET_POOL(AssetDumperWeaponCamo, m_camo, ASSET_TYPE_WEAPON_CAMO) - DUMP_ASSET_POOL(AssetDumperSndDriverGlobals, m_snd_driver_globals, ASSET_TYPE_SNDDRIVER_GLOBALS) + DUMP_ASSET_POOL(localize::DumperT6, m_localize, ASSET_TYPE_LOCALIZE_ENTRY) + DUMP_ASSET_POOL(weapon::DumperT6, m_weapon, ASSET_TYPE_WEAPON) + DUMP_ASSET_POOL(attachment::DumperT6, m_attachment, ASSET_TYPE_ATTACHMENT) + DUMP_ASSET_POOL(attachment_unique::DumperT6, m_attachment_unique, ASSET_TYPE_ATTACHMENT_UNIQUE) + DUMP_ASSET_POOL(camo::JsonDumperT6, m_camo, ASSET_TYPE_WEAPON_CAMO) + DUMP_ASSET_POOL(sound::SndDriverGlobalsDumperT6, m_snd_driver_globals, ASSET_TYPE_SNDDRIVER_GLOBALS) // DUMP_ASSET_POOL(AssetDumperFxEffectDef, m_fx, ASSET_TYPE_FX) // DUMP_ASSET_POOL(AssetDumperFxImpactTable, m_fx_impact_table, ASSET_TYPE_IMPACT_FX) - DUMP_ASSET_POOL(AssetDumperRawFile, m_raw_file, ASSET_TYPE_RAWFILE) - DUMP_ASSET_POOL(AssetDumperStringTable, m_string_table, ASSET_TYPE_STRINGTABLE) - DUMP_ASSET_POOL(AssetDumperLeaderboardDef, m_leaderboard, ASSET_TYPE_LEADERBOARD) + DUMP_ASSET_POOL(raw_file::DumperT6, m_raw_file, ASSET_TYPE_RAWFILE) + DUMP_ASSET_POOL(string_table::DumperT6, m_string_table, ASSET_TYPE_STRINGTABLE) + DUMP_ASSET_POOL(leaderboard::JsonDumperT6, m_leaderboard, ASSET_TYPE_LEADERBOARD) // DUMP_ASSET_POOL(AssetDumperXGlobals, m_xglobals, ASSET_TYPE_XGLOBALS) // DUMP_ASSET_POOL(AssetDumperDDLRoot, m_ddl, ASSET_TYPE_DDL) // DUMP_ASSET_POOL(AssetDumperGlasses, m_glasses, ASSET_TYPE_GLASSES) // DUMP_ASSET_POOL(AssetDumperEmblemSet, m_emblem_set, ASSET_TYPE_EMBLEMSET) - DUMP_ASSET_POOL(AssetDumperScriptParseTree, m_script, ASSET_TYPE_SCRIPTPARSETREE) + DUMP_ASSET_POOL(script::DumperT6, m_script, ASSET_TYPE_SCRIPTPARSETREE) // DUMP_ASSET_POOL(AssetDumperKeyValuePairs, m_key_value_pairs, ASSET_TYPE_KEYVALUEPAIRS) - DUMP_ASSET_POOL(AssetDumperVehicle, m_vehicle, ASSET_TYPE_VEHICLEDEF) + DUMP_ASSET_POOL(vehicle::DumperT6, m_vehicle, ASSET_TYPE_VEHICLEDEF) // DUMP_ASSET_POOL(AssetDumperMemoryBlock, m_memory_block, ASSET_TYPE_MEMORYBLOCK) // DUMP_ASSET_POOL(AssetDumperAddonMapEnts, m_addon_map_ents, ASSET_TYPE_ADDON_MAP_ENTS) - DUMP_ASSET_POOL(AssetDumperTracer, m_tracer, ASSET_TYPE_TRACER) + DUMP_ASSET_POOL(tracer::DumperT6, m_tracer, ASSET_TYPE_TRACER) // DUMP_ASSET_POOL(AssetDumperSkinnedVertsDef, m_skinned_verts, ASSET_TYPE_SKINNEDVERTS) - DUMP_ASSET_POOL(AssetDumperQdb, m_qdb, ASSET_TYPE_QDB) - DUMP_ASSET_POOL(AssetDumperSlug, m_slug, ASSET_TYPE_SLUG) + DUMP_ASSET_POOL(qdb::DumperT6, m_qdb, ASSET_TYPE_QDB) + DUMP_ASSET_POOL(slug::DumperT6, m_slug, ASSET_TYPE_SLUG) // DUMP_ASSET_POOL(AssetDumperFootstepTableDef, m_footstep_table, ASSET_TYPE_FOOTSTEP_TABLE) // DUMP_ASSET_POOL(AssetDumperFootstepFXTableDef, m_footstep_fx_table, ASSET_TYPE_FOOTSTEPFX_TABLE) - DUMP_ASSET_POOL(AssetDumperZBarrier, m_zbarrier, ASSET_TYPE_ZBARRIER) + DUMP_ASSET_POOL(z_barrier::DumperT6, m_zbarrier, ASSET_TYPE_ZBARRIER) return true; diff --git a/src/ObjWriting/Game/T6/PhysConstraints/PhysConstraintsInfoStringDumperT6.cpp b/src/ObjWriting/Game/T6/PhysConstraints/PhysConstraintsInfoStringDumperT6.cpp new file mode 100644 index 00000000..c0c2d7ce --- /dev/null +++ b/src/ObjWriting/Game/T6/PhysConstraints/PhysConstraintsInfoStringDumperT6.cpp @@ -0,0 +1,92 @@ +#include "PhysConstraintsInfoStringDumperT6.h" + +#include "Game/T6/InfoString/InfoStringFromStructConverter.h" +#include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/PhysConstraints/PhysConstraintsFields.h" +#include "PhysConstraints/PhysConstraintsCommon.h" + +#include +#include + +using namespace T6; + +namespace +{ + class InfoStringFromPhysConstraintsConverter final : public InfoStringFromStructConverter + { + protected: + void FillFromExtensionField(const cspField_t& field) override + { + switch (static_cast(field.iFieldType)) + { + case CFT_TYPE: + FillFromEnumInt(std::string(field.szName), field.iOffset, s_constraintTypeNames, std::extent_v); + break; + + default: + assert(false); + break; + } + } + + public: + InfoStringFromPhysConstraintsConverter(const PhysConstraints* structure, + const cspField_t* fields, + const size_t fieldCount, + std::function scriptStringValueCallback) + : InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback)) + { + } + }; + + InfoString CreateInfoString(XAssetInfo* asset) + { + assert(asset->Asset()->count <= 4); + + InfoStringFromPhysConstraintsConverter converter(asset->Asset(), + phys_constraints_fields, + std::extent_v, + [asset](const scr_string_t scrStr) -> std::string + { + assert(scrStr < asset->m_zone->m_script_strings.Count()); + if (scrStr >= asset->m_zone->m_script_strings.Count()) + return ""; + + return asset->m_zone->m_script_strings[scrStr]; + }); + + return converter.Convert(); + } +} // namespace + +namespace phys_constraints +{ + bool InfoStringDumperT6::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void InfoStringDumperT6::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + // Only dump raw when no gdt available + if (context.m_gdt) + { + const auto infoString = CreateInfoString(asset); + GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_PHYS_CONSTRAINTS); + infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_PHYS_CONSTRAINTS, gdtEntry); + context.m_gdt->WriteEntry(gdtEntry); + } + else + { + const auto assetFile = context.OpenAssetFile(GetFileNameForAssetName(asset->m_name)); + + if (!assetFile) + return; + + auto& stream = *assetFile; + const auto infoString = CreateInfoString(asset); + const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_PHYS_CONSTRAINTS); + stream.write(stringValue.c_str(), stringValue.size()); + } + } +} // namespace phys_constraints diff --git a/src/ObjWriting/Game/T6/PhysConstraints/PhysConstraintsInfoStringDumperT6.h b/src/ObjWriting/Game/T6/PhysConstraints/PhysConstraintsInfoStringDumperT6.h new file mode 100644 index 00000000..4d1c5e70 --- /dev/null +++ b/src/ObjWriting/Game/T6/PhysConstraints/PhysConstraintsInfoStringDumperT6.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" + +namespace phys_constraints +{ + class InfoStringDumperT6 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace phys_constraints diff --git a/src/ObjWriting/Game/T6/PhysPreset/PhysPresetInfoStringDumperT6.cpp b/src/ObjWriting/Game/T6/PhysPreset/PhysPresetInfoStringDumperT6.cpp new file mode 100644 index 00000000..c4f5dd85 --- /dev/null +++ b/src/ObjWriting/Game/T6/PhysPreset/PhysPresetInfoStringDumperT6.cpp @@ -0,0 +1,113 @@ +#include "PhysPresetInfoStringDumperT6.h" + +#include "Game/T6/InfoString/InfoStringFromStructConverter.h" +#include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/PhysPreset/PhysPresetFields.h" +#include "PhysPreset/PhysPresetCommon.h" + +#include +#include +#include +#include + +using namespace T6; + +namespace +{ + class InfoStringFromPhysPresetConverter final : public InfoStringFromStructConverter + { + protected: + void FillFromExtensionField(const cspField_t& field) override + { + assert(false); + } + + public: + InfoStringFromPhysPresetConverter(const PhysPresetInfo* structure, + const cspField_t* fields, + const size_t fieldCount, + std::function scriptStringValueCallback) + : InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback)) + { + } + }; + + void CopyToPhysPresetInfo(const PhysPreset* physPreset, PhysPresetInfo* physPresetInfo) + { + physPresetInfo->mass = std::clamp(physPreset->mass * 1000.0f, 1.0f, 2000.0f); + physPresetInfo->bounce = physPreset->bounce; + + if (std::isinf(physPreset->friction)) + { + physPresetInfo->isFrictionInfinity = 1; + physPresetInfo->friction = 0; + } + else + { + physPresetInfo->isFrictionInfinity = 0; + physPresetInfo->friction = physPreset->friction; + } + + physPresetInfo->bulletForceScale = physPreset->bulletForceScale; + physPresetInfo->explosiveForceScale = physPreset->explosiveForceScale; + physPresetInfo->piecesSpreadFraction = physPreset->piecesSpreadFraction; + physPresetInfo->piecesUpwardVelocity = physPreset->piecesUpwardVelocity; + physPresetInfo->canFloat = physPreset->canFloat; + physPresetInfo->gravityScale = std::clamp(physPreset->gravityScale, 0.01f, 10.0f); + physPresetInfo->centerOfMassOffset = physPreset->centerOfMassOffset; + physPresetInfo->buoyancyBoxMin = physPreset->buoyancyBoxMin; + physPresetInfo->buoyancyBoxMax = physPreset->buoyancyBoxMax; + } + + InfoString CreateInfoString(XAssetInfo* asset) + { + auto* physPresetInfo = new PhysPresetInfo; + CopyToPhysPresetInfo(asset->Asset(), physPresetInfo); + + InfoStringFromPhysPresetConverter converter(physPresetInfo, + phys_preset_fields, + std::extent_v, + [asset](const scr_string_t scrStr) -> std::string + { + assert(scrStr < asset->m_zone->m_script_strings.Count()); + if (scrStr >= asset->m_zone->m_script_strings.Count()) + return ""; + + return asset->m_zone->m_script_strings[scrStr]; + }); + + return converter.Convert(); + } +} // namespace + +namespace phys_preset +{ + bool InfoStringDumperT6::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void InfoStringDumperT6::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + // Only dump raw when no gdt available + if (context.m_gdt) + { + const auto infoString = CreateInfoString(asset); + GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_PHYS_PRESET); + infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_PHYS_PRESET, gdtEntry); + context.m_gdt->WriteEntry(gdtEntry); + } + else + { + const auto assetFile = context.OpenAssetFile(GetFileNameForAssetName(asset->m_name)); + + if (!assetFile) + return; + + auto& stream = *assetFile; + const auto infoString = CreateInfoString(asset); + const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_PHYS_PRESET); + stream.write(stringValue.c_str(), stringValue.size()); + } + } +} // namespace phys_preset diff --git a/src/ObjWriting/Game/T6/PhysPreset/PhysPresetInfoStringDumperT6.h b/src/ObjWriting/Game/T6/PhysPreset/PhysPresetInfoStringDumperT6.h new file mode 100644 index 00000000..df52d539 --- /dev/null +++ b/src/ObjWriting/Game/T6/PhysPreset/PhysPresetInfoStringDumperT6.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" + +namespace phys_preset +{ + class InfoStringDumperT6 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace phys_preset diff --git a/src/ObjWriting/Game/T6/Qdb/QdbDumperT6.cpp b/src/ObjWriting/Game/T6/Qdb/QdbDumperT6.cpp new file mode 100644 index 00000000..f990de0d --- /dev/null +++ b/src/ObjWriting/Game/T6/Qdb/QdbDumperT6.cpp @@ -0,0 +1,23 @@ +#include "QdbDumperT6.h" + +using namespace T6; + +namespace qdb +{ + bool DumperT6::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperT6::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* qdb = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name); + + if (!assetFile) + return; + + auto& stream = *assetFile; + stream.write(qdb->buffer, qdb->len); + } +} // namespace qdb diff --git a/src/ObjWriting/Game/T6/Qdb/QdbDumperT6.h b/src/ObjWriting/Game/T6/Qdb/QdbDumperT6.h new file mode 100644 index 00000000..eb452510 --- /dev/null +++ b/src/ObjWriting/Game/T6/Qdb/QdbDumperT6.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" + +namespace qdb +{ + class DumperT6 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace qdb diff --git a/src/ObjWriting/Game/T6/RawFile/RawFileDumperT6.cpp b/src/ObjWriting/Game/T6/RawFile/RawFileDumperT6.cpp new file mode 100644 index 00000000..a7f29926 --- /dev/null +++ b/src/ObjWriting/Game/T6/RawFile/RawFileDumperT6.cpp @@ -0,0 +1,104 @@ +#include "RawFileDumperT6.h" + +#include +#include +#include + +using namespace T6; + +namespace fs = std::filesystem; + +namespace +{ + constexpr size_t ANIMTREE_MAX_SIZE = 0xC000000; + + void DumpAnimtree(AssetDumpingContext& context, XAssetInfo* asset, std::ostream& stream) + { + const auto* rawFile = asset->Asset(); + + if (rawFile->len <= 4) + { + std::cerr << "Invalid len of animtree file \"" << rawFile->name << "\"\n"; + return; + } + + const auto outLen = reinterpret_cast(rawFile->buffer)[0]; + const auto inLen = rawFile->len; + + if (outLen > ANIMTREE_MAX_SIZE) + { + std::cerr << "Invalid size of animtree file \"" << rawFile->name << "\": " << outLen << "\n"; + return; + } + + z_stream_s zs{}; + + zs.zalloc = Z_NULL; + zs.zfree = Z_NULL; + zs.opaque = Z_NULL; + zs.avail_in = 0; + zs.next_in = Z_NULL; + + int ret = inflateInit2(&zs, -DEF_WBITS); + + if (ret != Z_OK) + { + throw std::runtime_error("Initializing inflate failed"); + } + + zs.next_in = reinterpret_cast(&rawFile->buffer[4]); + zs.avail_in = inLen - sizeof(uint32_t); + + Bytef buffer[0x1000]; + + while (zs.avail_in > 0) + { + zs.next_out = buffer; + zs.avail_out = sizeof(buffer); + ret = inflate(&zs, Z_SYNC_FLUSH); + + if (ret < 0) + { + std::cerr << "Inflate failed for dumping animtree file \"" << rawFile->name << "\"\n"; + inflateEnd(&zs); + return; + } + + const auto inflateOutSize = sizeof(buffer) - zs.avail_out; + + stream.write(reinterpret_cast(buffer), inflateOutSize); + } + + inflateEnd(&zs); + } +} // namespace + +namespace raw_file +{ + bool DumperT6::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperT6::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* rawFile = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name); + + if (!assetFile) + return; + + auto& stream = *assetFile; + const fs::path rawFilePath(rawFile->name); + const auto extension = rawFilePath.extension().string(); + + if (extension == ".atr") + { + DumpAnimtree(context, asset, stream); + } + else + { + stream.write(rawFile->buffer, rawFile->len); + } + } +} // namespace raw_file diff --git a/src/ObjWriting/Game/T6/RawFile/RawFileDumperT6.h b/src/ObjWriting/Game/T6/RawFile/RawFileDumperT6.h new file mode 100644 index 00000000..c2faa0f9 --- /dev/null +++ b/src/ObjWriting/Game/T6/RawFile/RawFileDumperT6.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" + +namespace raw_file +{ + class DumperT6 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace raw_file diff --git a/src/ObjWriting/Game/T6/Script/ScriptDumperT6.cpp b/src/ObjWriting/Game/T6/Script/ScriptDumperT6.cpp new file mode 100644 index 00000000..2b2be090 --- /dev/null +++ b/src/ObjWriting/Game/T6/Script/ScriptDumperT6.cpp @@ -0,0 +1,23 @@ +#include "ScriptDumperT6.h" + +using namespace T6; + +namespace script +{ + bool DumperT6::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperT6::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* scriptParseTree = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name); + + if (!assetFile) + return; + + auto& stream = *assetFile; + stream.write(scriptParseTree->buffer, scriptParseTree->len); + } +} // namespace script diff --git a/src/ObjWriting/Game/T6/Script/ScriptDumperT6.h b/src/ObjWriting/Game/T6/Script/ScriptDumperT6.h new file mode 100644 index 00000000..895b55b4 --- /dev/null +++ b/src/ObjWriting/Game/T6/Script/ScriptDumperT6.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" + +namespace script +{ + class DumperT6 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace script diff --git a/src/ObjWriting/Game/T6/Slug/SlugDumperT6.cpp b/src/ObjWriting/Game/T6/Slug/SlugDumperT6.cpp new file mode 100644 index 00000000..d02a11d0 --- /dev/null +++ b/src/ObjWriting/Game/T6/Slug/SlugDumperT6.cpp @@ -0,0 +1,23 @@ +#include "SlugDumperT6.h" + +using namespace T6; + +namespace slug +{ + bool DumperT6::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperT6::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* slug = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name); + + if (!assetFile) + return; + + auto& stream = *assetFile; + stream.write(slug->buffer, slug->len); + } +} // namespace slug diff --git a/src/ObjWriting/Game/T6/Slug/SlugDumperT6.h b/src/ObjWriting/Game/T6/Slug/SlugDumperT6.h new file mode 100644 index 00000000..3dd202e5 --- /dev/null +++ b/src/ObjWriting/Game/T6/Slug/SlugDumperT6.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" + +namespace slug +{ + class DumperT6 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace slug diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndBank.cpp b/src/ObjWriting/Game/T6/Sound/SndBankDumperT6.cpp similarity index 98% rename from src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndBank.cpp rename to src/ObjWriting/Game/T6/Sound/SndBankDumperT6.cpp index 5d407b86..55d1b792 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndBank.cpp +++ b/src/ObjWriting/Game/T6/Sound/SndBankDumperT6.cpp @@ -1,4 +1,4 @@ -#include "AssetDumperSndBank.h" +#include "SndBankDumperT6.h" #include "Csv/CsvStream.h" #include "Game/T6/CommonT6.h" @@ -910,15 +910,18 @@ namespace } } // namespace -void AssetDumperSndBank::DumpPool(AssetDumpingContext& context, AssetPool* pool) +namespace sound { - LoadedSoundBankHashes soundBankHashes; - soundBankHashes.Initialize(); - for (const auto* assetInfo : *pool) + void SndBankDumperT6::DumpPool(AssetDumpingContext& context, AssetPool* pool) { - if (!assetInfo->m_name.empty() && assetInfo->m_name[0] == ',') - continue; + LoadedSoundBankHashes soundBankHashes; + soundBankHashes.Initialize(); + for (const auto* assetInfo : *pool) + { + if (!assetInfo->m_name.empty() && assetInfo->m_name[0] == ',') + continue; - DumpSndBank(context, soundBankHashes, *assetInfo); + DumpSndBank(context, soundBankHashes, *assetInfo); + } } -} +} // namespace sound diff --git a/src/ObjWriting/Game/T6/Sound/SndBankDumperT6.h b/src/ObjWriting/Game/T6/Sound/SndBankDumperT6.h new file mode 100644 index 00000000..f5d4f59d --- /dev/null +++ b/src/ObjWriting/Game/T6/Sound/SndBankDumperT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" + +namespace sound +{ + class SndBankDumperT6 final : public IAssetDumper + { + public: + void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; + }; +} // namespace sound diff --git a/src/ObjWriting/Game/T6/Sound/SndDriverGlobalsDumperT6.cpp b/src/ObjWriting/Game/T6/Sound/SndDriverGlobalsDumperT6.cpp new file mode 100644 index 00000000..02e7899e --- /dev/null +++ b/src/ObjWriting/Game/T6/Sound/SndDriverGlobalsDumperT6.cpp @@ -0,0 +1,392 @@ +#include "SndDriverGlobalsDumperT6.h" + +#include "Csv/CsvStream.h" +#include "ObjContainer/SoundBank/SoundBank.h" + +#include + +using namespace T6; + +namespace +{ + const std::string GROUPS_HEADERS[]{ + "name", + "attenuationSp", + "attenuationMp", + "category", + "parent", + "id", + }; + + const std::string GROUPS_CATEGORIES[]{ + "sfx", + "music", + "void", + "ui", + "cinematic", + "id", + }; + + const std::string CURVE_HEADERS[]{ + "name", + "x0", + "y0", + "x1", + "y1", + "x2", + "y2", + "x3", + "y3", + "x4", + "y4", + "x5", + "y5", + "x6", + "y6", + "x7", + "y7", + "id", + }; + + const std::string PAN_HEADERS[]{ + "name", + "front", + "back", + "center", + "lfe", + "left", + "right", + "id", + }; + + const std::string MASTER_HEADERS[]{ + "name", "lowE", "lowG", "lowF", "lowQ", "peak1E", "peak1G", "peak1F", "peak1Q", "peak2E", "peak2G", + "peak2F", "peak2Q", "hiE", "hiG", "hiF", "hiQ", "eqG", "compE", "compPG", "compMG", "compT", + "compR", "compTA", "compTR", "limitE", "limitPG", "limitMG", "limitT", "limitR", "limitTA", "limitTR", "busReverbG", + "busFxG", "busVoiceG", "busPfutzG", "busHdrfxG", "busUiG", "busMusicG", "busMovieG", "busVcsG", "busReverbE", "busFxE", "busVoiceE", + "busPfutzE", "busHdrfxE", "busUiE", "busMusicE", "busMovieE", "hdrfxCompE", "voiceEqE", "voiceCompE", "id", + }; + + const std::string SIDECHAIN_HEADERS[]{ + "name", + "g", + "f", + "q", + "ta", + "tr", + "tf", + "id", + }; + + const std::string FUTZ_HEADERS[]{ + "name", + "bpfF", + "bpfQ", + "lsG", + "lsF", + "lsQ", + "dist", + "preG", + "postG", + "th", + "tg", + "clippre", + "clippost", + "blend", + "startAliasId", + "stopAliasId", + "loopAliasId", + "id", + }; + + class Internal + { + public: + explicit Internal(AssetDumpingContext& context) + : m_context(context) + { + } + + void DumpPool(AssetPool* pool) + { + for (const auto* assetInfo : *pool) + { + if (!assetInfo->m_name.empty() && assetInfo->m_name[0] == ',') + continue; + + DumpSndDriverGlobals(assetInfo); + } + } + + private: + std::unique_ptr OpenAssetFile(const std::string& filename) + { + auto outputFile = this->m_context.OpenAssetFile(filename); + if (outputFile == nullptr) + std::cerr << std::format("Failed to open sound driver globals output file for: \"{}\"\n", filename); + + return outputFile; + } + + static void WriteFileHeader(CsvOutputStream& stream, const std::string* headers, size_t count) + { + for (auto i = 0u; i < count; i++) + { + stream.WriteColumn(headers[i]); + } + + stream.NextRow(); + } + + void DumpSndVolumesGroups(const SndVolumeGroup* groups, const size_t count) + { + const auto outputFile = this->OpenAssetFile("soundbank/globals/group.csv"); + + if (outputFile != nullptr) + { + CsvOutputStream csvStream(*outputFile); + WriteFileHeader(csvStream, GROUPS_HEADERS, std::extent_v); + + for (auto i = 0u; i < count; i++) + { + const auto& group = groups[i]; + csvStream.WriteColumn(group.name); + csvStream.WriteColumn(std::to_string(group.attenuationSp)); + csvStream.WriteColumn(std::to_string(group.attenuationMp)); + csvStream.WriteColumn(GROUPS_CATEGORIES[group.category]); + csvStream.WriteColumn(group.parentName); + csvStream.WriteColumn(std::to_string(group.id)); + csvStream.NextRow(); + } + } + } + + void DumpSndCurves(const SndCurve* curves, const size_t count) + { + const auto outputFile = this->OpenAssetFile("soundbank/globals/curves.csv"); + + if (outputFile != nullptr) + { + CsvOutputStream csvStream(*outputFile); + WriteFileHeader(csvStream, CURVE_HEADERS, std::extent_v); + + for (auto i = 0u; i < count; i++) + { + const auto& curve = curves[i]; + csvStream.WriteColumn(curve.name); + + for (auto j = 0u; j < 8; j++) + { + csvStream.WriteColumn(std::to_string(curve.points[j].x)); + csvStream.WriteColumn(std::to_string(curve.points[j].y)); + } + + csvStream.WriteColumn(std::to_string(curve.id)); + + csvStream.NextRow(); + } + } + } + + void DumpSndPans(const SndPan* pans, const size_t count) + { + const auto outputFile = this->OpenAssetFile("soundbank/globals/pan.csv"); + + if (outputFile != nullptr) + { + CsvOutputStream csvStream(*outputFile); + WriteFileHeader(csvStream, PAN_HEADERS, std::extent_v); + + for (auto i = 0u; i < count; i++) + { + const auto& pan = pans[i]; + csvStream.WriteColumn(pan.name); + csvStream.WriteColumn(std::to_string(pan.front)); + csvStream.WriteColumn(std::to_string(pan.back)); + csvStream.WriteColumn(std::to_string(pan.center)); + csvStream.WriteColumn(std::to_string(pan.lfe)); + csvStream.WriteColumn(std::to_string(pan.left)); + csvStream.WriteColumn(std::to_string(pan.right)); + csvStream.WriteColumn(std::to_string(pan.id)); + csvStream.NextRow(); + } + } + } + + void DumpSndDuckGroups(const SndDuckGroup* duckGroups, const size_t count) + { + const auto outputFile = this->OpenAssetFile("soundbank/globals/duck_groups.csv"); + + if (outputFile != nullptr) + { + CsvOutputStream csvStream(*outputFile); + csvStream.WriteColumn("name"); + csvStream.WriteColumn("id"); + csvStream.NextRow(); + + for (auto i = 0u; i < count; i++) + { + const auto& duckGroup = duckGroups[i]; + csvStream.WriteColumn(duckGroup.name); + csvStream.WriteColumn(std::to_string(duckGroup.id)); + csvStream.NextRow(); + } + } + } + + void DumpSndMasters(const SndMaster* masters, const size_t count) + { + const auto outputFile = this->OpenAssetFile("soundbank/globals/master.csv"); + + if (outputFile != nullptr) + { + CsvOutputStream csvStream(*outputFile); + WriteFileHeader(csvStream, MASTER_HEADERS, std::extent_v); + + for (auto i = 0u; i < count; i++) + { + const auto& master = masters[i]; + csvStream.WriteColumn(master.name); + csvStream.WriteColumn(std::to_string(master.lowE)); + csvStream.WriteColumn(std::to_string(master.lowG)); + csvStream.WriteColumn(std::to_string(master.lowF)); + csvStream.WriteColumn(std::to_string(master.lowQ)); + csvStream.WriteColumn(std::to_string(master.peak1E)); + csvStream.WriteColumn(std::to_string(master.peak1G)); + csvStream.WriteColumn(std::to_string(master.peak1F)); + csvStream.WriteColumn(std::to_string(master.peak1Q)); + csvStream.WriteColumn(std::to_string(master.peak2E)); + csvStream.WriteColumn(std::to_string(master.peak2G)); + csvStream.WriteColumn(std::to_string(master.peak2F)); + csvStream.WriteColumn(std::to_string(master.peak2Q)); + csvStream.WriteColumn(std::to_string(master.hiE)); + csvStream.WriteColumn(std::to_string(master.hiG)); + csvStream.WriteColumn(std::to_string(master.hiF)); + csvStream.WriteColumn(std::to_string(master.hiQ)); + csvStream.WriteColumn(std::to_string(master.eqG)); + csvStream.WriteColumn(std::to_string(master.compE)); + csvStream.WriteColumn(std::to_string(master.compPG)); + csvStream.WriteColumn(std::to_string(master.compMG)); + csvStream.WriteColumn(std::to_string(master.compT)); + csvStream.WriteColumn(std::to_string(master.compR)); + csvStream.WriteColumn(std::to_string(master.compTA)); + csvStream.WriteColumn(std::to_string(master.compTR)); + csvStream.WriteColumn(std::to_string(master.limitE)); + csvStream.WriteColumn(std::to_string(master.limitPG)); + csvStream.WriteColumn(std::to_string(master.limitMG)); + csvStream.WriteColumn(std::to_string(master.limitT)); + csvStream.WriteColumn(std::to_string(master.limitR)); + csvStream.WriteColumn(std::to_string(master.limitTA)); + csvStream.WriteColumn(std::to_string(master.limitTR)); + csvStream.WriteColumn(std::to_string(master.busReverbG)); + csvStream.WriteColumn(std::to_string(master.busFxG)); + csvStream.WriteColumn(std::to_string(master.busVoiceG)); + csvStream.WriteColumn(std::to_string(master.busPfutzG)); + csvStream.WriteColumn(std::to_string(master.busHdrfxG)); + csvStream.WriteColumn(std::to_string(master.busUiG)); + csvStream.WriteColumn(std::to_string(master.busMusicG)); + csvStream.WriteColumn(std::to_string(master.busMovieG)); + csvStream.WriteColumn(std::to_string(master.busVcsG)); + csvStream.WriteColumn(std::to_string(master.busReverbE)); + csvStream.WriteColumn(std::to_string(master.busFxE)); + csvStream.WriteColumn(std::to_string(master.busVoiceE)); + csvStream.WriteColumn(std::to_string(master.busPfutzE)); + csvStream.WriteColumn(std::to_string(master.busHdrfxE)); + csvStream.WriteColumn(std::to_string(master.busUiE)); + csvStream.WriteColumn(std::to_string(master.busMusicE)); + csvStream.WriteColumn(std::to_string(master.busMovieE)); + csvStream.WriteColumn(std::to_string(master.hdrfxCompE)); + csvStream.WriteColumn(std::to_string(master.voiceEqE)); + csvStream.WriteColumn(std::to_string(master.voiceCompE)); + csvStream.WriteColumn(std::to_string(master.id)); + csvStream.NextRow(); + } + } + } + + void DumpSndSidechainDucks(const SndSidechainDuck* sidechains, const size_t count) + { + const auto outputFile = this->OpenAssetFile("soundbank/globals/sidechain_duck.csv"); + + if (outputFile != nullptr) + { + CsvOutputStream csvStream(*outputFile); + WriteFileHeader(csvStream, SIDECHAIN_HEADERS, std::extent_v); + + for (auto i = 0u; i < count; i++) + { + const auto& sidechain = sidechains[i]; + csvStream.WriteColumn(sidechain.name); + csvStream.WriteColumn(std::to_string(sidechain.g)); + csvStream.WriteColumn(std::to_string(sidechain.f)); + csvStream.WriteColumn(std::to_string(sidechain.q)); + csvStream.WriteColumn(std::to_string(sidechain.ta)); + csvStream.WriteColumn(std::to_string(sidechain.tr)); + csvStream.WriteColumn(std::to_string(sidechain.tf)); + csvStream.WriteColumn(std::to_string(sidechain.id)); + csvStream.NextRow(); + } + } + } + + void DumpSndFutz(const SndFutz* futzes, const size_t count) + { + const auto outputFile = this->OpenAssetFile("soundbank/globals/futz.csv"); + + if (outputFile != nullptr) + { + CsvOutputStream csvStream(*outputFile); + WriteFileHeader(csvStream, FUTZ_HEADERS, std::extent_v); + + for (auto i = 0u; i < count; i++) + { + const auto& futz = futzes[i]; + csvStream.WriteColumn(futz.name); + csvStream.WriteColumn(std::to_string(futz.bpfF)); + csvStream.WriteColumn(std::to_string(futz.bpfQ)); + csvStream.WriteColumn(std::to_string(futz.lsG)); + csvStream.WriteColumn(std::to_string(futz.lsF)); + csvStream.WriteColumn(std::to_string(futz.lsQ)); + csvStream.WriteColumn(std::to_string(futz.dist)); + csvStream.WriteColumn(std::to_string(futz.preG)); + csvStream.WriteColumn(std::to_string(futz.postG)); + csvStream.WriteColumn(std::to_string(futz.th)); + csvStream.WriteColumn(std::to_string(futz.tg)); + csvStream.WriteColumn(std::to_string(futz.clippre)); + csvStream.WriteColumn(std::to_string(futz.clippost)); + csvStream.WriteColumn(std::to_string(futz.blend)); + csvStream.WriteColumn(std::to_string(futz.startAliasId)); + csvStream.WriteColumn(std::to_string(futz.stopAliasId)); + csvStream.WriteColumn(std::to_string(futz.loopAliasId)); + csvStream.WriteColumn(std::to_string(futz.id)); + csvStream.NextRow(); + } + } + } + + void DumpSndDriverGlobals(const XAssetInfo* sndDriverGlobalsInfo) + { + const auto* sndDriverGlobals = sndDriverGlobalsInfo->Asset(); + + DumpSndVolumesGroups(sndDriverGlobals->groups, sndDriverGlobals->groupCount); + DumpSndCurves(sndDriverGlobals->curves, sndDriverGlobals->curveCount); + DumpSndPans(sndDriverGlobals->pans, sndDriverGlobals->panCount); + DumpSndDuckGroups(sndDriverGlobals->duckGroups, sndDriverGlobals->duckGroupCount); + // DumpSndContexts(sndDriverGlobals->contexts, sndDriverGlobals->contextCount); + DumpSndMasters(sndDriverGlobals->masters, sndDriverGlobals->masterCount); + DumpSndSidechainDucks(sndDriverGlobals->voiceDucks, sndDriverGlobals->voiceDuckCount); + DumpSndFutz(sndDriverGlobals->futzes, sndDriverGlobals->futzCount); + } + + AssetDumpingContext& m_context; + }; +} // namespace + +namespace sound +{ + void SndDriverGlobalsDumperT6::DumpPool(AssetDumpingContext& context, AssetPool* pool) + { + Internal internal(context); + internal.DumpPool(pool); + } +} // namespace sound diff --git a/src/ObjWriting/Game/T6/Sound/SndDriverGlobalsDumperT6.h b/src/ObjWriting/Game/T6/Sound/SndDriverGlobalsDumperT6.h new file mode 100644 index 00000000..042de43c --- /dev/null +++ b/src/ObjWriting/Game/T6/Sound/SndDriverGlobalsDumperT6.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" + +namespace sound +{ + class SndDriverGlobalsDumperT6 final : public IAssetDumper + { + public: + void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; + }; +} // namespace sound diff --git a/src/ObjWriting/Game/T6/StringTable/StringTableDumperT6.cpp b/src/ObjWriting/Game/T6/StringTable/StringTableDumperT6.cpp new file mode 100644 index 00000000..4bd96479 --- /dev/null +++ b/src/ObjWriting/Game/T6/StringTable/StringTableDumperT6.cpp @@ -0,0 +1,42 @@ +#include "StringTableDumperT6.h" + +#include "Csv/CsvStream.h" + +using namespace T6; + +namespace string_table +{ + bool DumperT6::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperT6::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* stringTable = asset->Asset(); + const auto assetFile = context.OpenAssetFile(asset->m_name); + + if (!assetFile) + return; + + CsvOutputStream csv(*assetFile); + + for (auto row = 0; row < stringTable->rowCount; row++) + { + for (auto column = 0; column < stringTable->columnCount; column++) + { + const auto* cell = &stringTable->values[column + row * stringTable->columnCount]; + if (cell->string != nullptr) + { + csv.WriteColumn(cell->string); + } + else + { + csv.WriteColumn(""); + } + } + + csv.NextRow(); + } + } +} // namespace string_table diff --git a/src/ObjWriting/Game/T6/StringTable/StringTableDumperT6.h b/src/ObjWriting/Game/T6/StringTable/StringTableDumperT6.h new file mode 100644 index 00000000..b61a4380 --- /dev/null +++ b/src/ObjWriting/Game/T6/StringTable/StringTableDumperT6.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" + +namespace string_table +{ + class DumperT6 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace string_table diff --git a/src/ObjWriting/Game/T6/Techset/TechsetDumperT6.cpp b/src/ObjWriting/Game/T6/Techset/TechsetDumperT6.cpp new file mode 100644 index 00000000..a2d7273c --- /dev/null +++ b/src/ObjWriting/Game/T6/Techset/TechsetDumperT6.cpp @@ -0,0 +1,107 @@ +#include "TechsetDumperT6.h" + +#include "Shader/ShaderCommon.h" + +#include +#include + +using namespace T6; + +namespace +{ + class ShaderZoneState final : public IZoneAssetDumperState + { + public: + bool ShouldDumpTechnique(const MaterialTechnique* technique) + { + const auto existingTechnique = m_dumped_techniques.find(technique); + if (existingTechnique == m_dumped_techniques.end()) + { + m_dumped_techniques.emplace(technique); + return true; + } + + return false; + } + + bool ShouldDumpPixelShader(const MaterialPixelShader* pixelShader) + { + const auto existingPixelShader = m_dumped_pixel_shaders.find(pixelShader); + if (existingPixelShader == m_dumped_pixel_shaders.end()) + { + m_dumped_pixel_shaders.emplace(pixelShader); + return true; + } + + return false; + } + + bool ShouldDumpVertexShader(const MaterialVertexShader* vertexShader) + { + const auto existingVertexShader = m_dumped_vertex_shaders.find(vertexShader); + if (existingVertexShader == m_dumped_vertex_shaders.end()) + { + m_dumped_vertex_shaders.emplace(vertexShader); + return true; + } + + return false; + } + + private: + std::unordered_set m_dumped_techniques; + std::unordered_set m_dumped_pixel_shaders; + std::unordered_set m_dumped_vertex_shaders; + }; + + void DumpPixelShader(const AssetDumpingContext& context, const MaterialPixelShader& pixelShader) + { + const auto shaderFile = context.OpenAssetFile(shader::GetFileNameForPixelShaderAssetName(pixelShader.name)); + + if (!shaderFile) + return; + + shaderFile->write(pixelShader.prog.loadDef.program, pixelShader.prog.loadDef.programSize); + } + + void DumpVertexShader(const AssetDumpingContext& context, const MaterialVertexShader& vertexShader) + { + const auto shaderFile = context.OpenAssetFile(shader::GetFileNameForVertexShaderAssetName(vertexShader.name)); + + if (!shaderFile) + return; + + shaderFile->write(vertexShader.prog.loadDef.program, vertexShader.prog.loadDef.programSize); + } +} // namespace + +namespace techset +{ + bool DumperT6::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperT6::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto* techniqueSet = asset->Asset(); + auto* shaderState = context.GetZoneAssetDumperState(); + + for (const auto* technique : techniqueSet->techniques) + { + if (!technique || !shaderState->ShouldDumpTechnique(technique)) + continue; + + for (auto passIndex = 0u; passIndex < technique->passCount; passIndex++) + { + const auto* pixelShader = technique->passArray[passIndex].pixelShader; + if (pixelShader && shaderState->ShouldDumpPixelShader(pixelShader)) + DumpPixelShader(context, *pixelShader); + + const auto* vertexShader = technique->passArray[passIndex].vertexShader; + if (vertexShader && shaderState->ShouldDumpVertexShader(vertexShader)) + DumpVertexShader(context, *vertexShader); + } + } + } +} // namespace techset diff --git a/src/ObjWriting/Game/T6/Techset/TechsetDumperT6.h b/src/ObjWriting/Game/T6/Techset/TechsetDumperT6.h new file mode 100644 index 00000000..59a48f3f --- /dev/null +++ b/src/ObjWriting/Game/T6/Techset/TechsetDumperT6.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" + +namespace techset +{ + class DumperT6 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace techset diff --git a/src/ObjWriting/Game/T6/Tracer/TracerDumperT6.cpp b/src/ObjWriting/Game/T6/Tracer/TracerDumperT6.cpp new file mode 100644 index 00000000..854a45af --- /dev/null +++ b/src/ObjWriting/Game/T6/Tracer/TracerDumperT6.cpp @@ -0,0 +1,91 @@ +#include "TracerDumperT6.h" + +#include "Game/T6/InfoString/InfoStringFromStructConverter.h" +#include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/Tracer/TracerFields.h" +#include "Tracer/TracerCommon.h" + +#include +#include + +using namespace T6; + +namespace +{ + class InfoStringFromTracerConverter final : public InfoStringFromStructConverter + { + protected: + void FillFromExtensionField(const cspField_t& field) override + { + switch (static_cast(field.iFieldType)) + { + case TFT_TRACERTYPE: + FillFromEnumInt(std::string(field.szName), field.iOffset, tracerTypeNames, std::extent_v); + break; + + case TFT_NUM_FIELD_TYPES: + default: + assert(false); + break; + } + } + + public: + InfoStringFromTracerConverter(const TracerDef* structure, + const cspField_t* fields, + const size_t fieldCount, + std::function scriptStringValueCallback) + : InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback)) + { + } + }; + + InfoString CreateInfoString(XAssetInfo* asset) + { + InfoStringFromTracerConverter converter(asset->Asset(), + tracer_fields, + std::extent_v, + [asset](const scr_string_t scrStr) -> std::string + { + assert(scrStr < asset->m_zone->m_script_strings.Count()); + if (scrStr >= asset->m_zone->m_script_strings.Count()) + return ""; + + return asset->m_zone->m_script_strings[scrStr]; + }); + + return converter.Convert(); + } +} // namespace + +namespace tracer +{ + bool DumperT6::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperT6::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + // Only dump raw when no gdt available + if (context.m_gdt) + { + const auto infoString = CreateInfoString(asset); + GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_TRACER); + infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_TRACER, gdtEntry); + context.m_gdt->WriteEntry(gdtEntry); + } + else + { + const auto assetFile = context.OpenAssetFile(GetFileNameForAssetName(asset->m_name)); + + if (!assetFile) + return; + + auto& stream = *assetFile; + const auto infoString = CreateInfoString(asset); + const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_TRACER); + stream.write(stringValue.c_str(), stringValue.size()); + } + } +} // namespace tracer diff --git a/src/ObjWriting/Game/T6/Tracer/TracerDumperT6.h b/src/ObjWriting/Game/T6/Tracer/TracerDumperT6.h new file mode 100644 index 00000000..0bfb6d75 --- /dev/null +++ b/src/ObjWriting/Game/T6/Tracer/TracerDumperT6.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" + +namespace tracer +{ + class DumperT6 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace tracer diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperVehicle.cpp b/src/ObjWriting/Game/T6/Vehicle/VehicleDumperT6.cpp similarity index 61% rename from src/ObjWriting/Game/T6/AssetDumpers/AssetDumperVehicle.cpp rename to src/ObjWriting/Game/T6/Vehicle/VehicleDumperT6.cpp index cccf418a..1178b394 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperVehicle.cpp +++ b/src/ObjWriting/Game/T6/Vehicle/VehicleDumperT6.cpp @@ -1,15 +1,17 @@ -#include "AssetDumperVehicle.h" +#include "VehicleDumperT6.h" #include "Game/T6/InfoString/InfoStringFromStructConverter.h" #include "Game/T6/ObjConstantsT6.h" #include "Game/T6/Vehicle/VehicleFields.h" +#include "Vehicle/VehicleCommon.h" #include #include using namespace T6; +using namespace ::vehicle; -namespace T6 +namespace { class InfoStringFromVehicleConverter final : public InfoStringFromStructConverter { @@ -88,50 +90,53 @@ namespace T6 { } }; -} // namespace T6 -InfoString AssetDumperVehicle::CreateInfoString(XAssetInfo* asset) -{ - InfoStringFromVehicleConverter converter(asset->Asset(), - vehicle_fields, - std::extent_v, - [asset](const scr_string_t scrStr) -> std::string - { - assert(scrStr < asset->m_zone->m_script_strings.Count()); - if (scrStr >= asset->m_zone->m_script_strings.Count()) - return ""; - - return asset->m_zone->m_script_strings[scrStr]; - }); - - return converter.Convert(); -} - -bool AssetDumperVehicle::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperVehicle::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - // Only dump raw when no gdt available - if (context.m_gdt) + InfoString CreateInfoString(XAssetInfo* asset) { - const auto infoString = CreateInfoString(asset); - GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_VEHICLE); - infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_VEHICLE, gdtEntry); - context.m_gdt->WriteEntry(gdtEntry); + InfoStringFromVehicleConverter converter(asset->Asset(), + vehicle_fields, + std::extent_v, + [asset](const scr_string_t scrStr) -> std::string + { + assert(scrStr < asset->m_zone->m_script_strings.Count()); + if (scrStr >= asset->m_zone->m_script_strings.Count()) + return ""; + + return asset->m_zone->m_script_strings[scrStr]; + }); + + return converter.Convert(); } - else +} // namespace + +namespace vehicle +{ + bool DumperT6::ShouldDump(XAssetInfo* asset) { - const auto assetFile = context.OpenAssetFile("vehicles/" + asset->m_name); - - if (!assetFile) - return; - - auto& stream = *assetFile; - const auto infoString = CreateInfoString(asset); - const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_VEHICLE); - stream.write(stringValue.c_str(), stringValue.size()); + return true; } -} + + void DumperT6::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + // Only dump raw when no gdt available + if (context.m_gdt) + { + const auto infoString = CreateInfoString(asset); + GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_VEHICLE); + infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_VEHICLE, gdtEntry); + context.m_gdt->WriteEntry(gdtEntry); + } + else + { + const auto assetFile = context.OpenAssetFile(GetFileNameForAssetName(asset->m_name)); + + if (!assetFile) + return; + + auto& stream = *assetFile; + const auto infoString = CreateInfoString(asset); + const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_VEHICLE); + stream.write(stringValue.c_str(), stringValue.size()); + } + } +} // namespace vehicle diff --git a/src/ObjWriting/Game/T6/Vehicle/VehicleDumperT6.h b/src/ObjWriting/Game/T6/Vehicle/VehicleDumperT6.h new file mode 100644 index 00000000..5d328e87 --- /dev/null +++ b/src/ObjWriting/Game/T6/Vehicle/VehicleDumperT6.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" + +namespace vehicle +{ + class DumperT6 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace vehicle diff --git a/src/ObjWriting/Game/T6/Weapon/AttachmentDumperT6.cpp b/src/ObjWriting/Game/T6/Weapon/AttachmentDumperT6.cpp new file mode 100644 index 00000000..d7fcc4c7 --- /dev/null +++ b/src/ObjWriting/Game/T6/Weapon/AttachmentDumperT6.cpp @@ -0,0 +1,98 @@ +#include "AttachmentDumperT6.h" + +#include "Game/T6/InfoString/InfoStringFromStructConverter.h" +#include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/Weapon/AttachmentFields.h" +#include "Game/T6/Weapon/WeaponStrings.h" +#include "Weapon/AttachmentCommon.h" + +#include +#include + +using namespace T6; + +namespace +{ + class InfoStringFromAttachmentConverter final : public InfoStringFromStructConverter + { + protected: + void FillFromExtensionField(const cspField_t& field) override + { + switch (static_cast(field.iFieldType)) + { + case AFT_ATTACHMENTTYPE: + FillFromEnumInt(std::string(field.szName), field.iOffset, szAttachmentTypeNames, std::extent_v); + break; + + case AFT_PENETRATE_TYPE: + FillFromEnumInt(std::string(field.szName), field.iOffset, penetrateTypeNames, std::extent_v); + break; + + case AFT_FIRETYPE: + FillFromEnumInt(std::string(field.szName), field.iOffset, szWeapFireTypeNames, std::extent_v); + break; + + default: + break; + } + } + + public: + InfoStringFromAttachmentConverter(const WeaponAttachment* structure, + const cspField_t* fields, + const size_t fieldCount, + std::function scriptStringValueCallback) + : InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback)) + { + } + }; + + InfoString CreateInfoString(XAssetInfo* asset) + { + InfoStringFromAttachmentConverter converter(asset->Asset(), + attachment_fields, + std::extent_v, + [asset](const scr_string_t scrStr) -> std::string + { + assert(scrStr < asset->m_zone->m_script_strings.Count()); + if (scrStr >= asset->m_zone->m_script_strings.Count()) + return ""; + + return asset->m_zone->m_script_strings[scrStr]; + }); + + return converter.Convert(); + } +} // namespace + +namespace attachment +{ + bool DumperT6::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperT6::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + // Only dump raw when no gdt available + if (context.m_gdt) + { + const auto infoString = CreateInfoString(asset); + GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_WEAPON_ATTACHMENT); + infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_WEAPON_ATTACHMENT, gdtEntry); + context.m_gdt->WriteEntry(gdtEntry); + } + else + { + const auto assetFile = context.OpenAssetFile(GetInfoStringFileNameForAssetName(asset->m_name)); + + if (!assetFile) + return; + + auto& stream = *assetFile; + const auto infoString = CreateInfoString(asset); + const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_WEAPON_ATTACHMENT); + stream.write(stringValue.c_str(), stringValue.size()); + } + } +} // namespace attachment diff --git a/src/ObjWriting/Game/T6/Weapon/AttachmentDumperT6.h b/src/ObjWriting/Game/T6/Weapon/AttachmentDumperT6.h new file mode 100644 index 00000000..0472e2a0 --- /dev/null +++ b/src/ObjWriting/Game/T6/Weapon/AttachmentDumperT6.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" + +namespace attachment +{ + class DumperT6 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace attachment diff --git a/src/ObjWriting/Game/T6/Weapon/AttachmentUniqueDumperT6.cpp b/src/ObjWriting/Game/T6/Weapon/AttachmentUniqueDumperT6.cpp new file mode 100644 index 00000000..c10605ac --- /dev/null +++ b/src/ObjWriting/Game/T6/Weapon/AttachmentUniqueDumperT6.cpp @@ -0,0 +1,162 @@ +#include "AttachmentUniqueDumperT6.h" + +#include "Game/T6/InfoString/InfoStringFromStructConverter.h" +#include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/Weapon/AttachmentUniqueFields.h" +#include "Game/T6/Weapon/WeaponStrings.h" +#include "Weapon/AttachmentUniqueCommon.h" + +#include +#include +#include +#include + +using namespace T6; + +namespace +{ + class InfoStringFromWeaponAttachmentUniqueConverter final : public InfoStringFromStructConverter + { + protected: + void FillFromExtensionField(const cspField_t& field) override + { + switch (static_cast(field.iFieldType)) + { + case AUFT_ATTACHMENTTYPE: + FillFromEnumInt(std::string(field.szName), field.iOffset, szAttachmentTypeNames, std::extent_v); + break; + + case AUFT_HIDETAGS: + { + const auto* hideTags = reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset); + std::stringstream ss; + auto first = true; + + for (auto i = 0u; i < std::extent_v; i++) + { + const auto& str = m_get_scr_string(hideTags[i]); + if (!str.empty()) + { + if (!first) + ss << "\n"; + else + first = false; + + ss << str; + } + } + + m_info_string.SetValueForKey(std::string(field.szName), ss.str()); + break; + } + + case AUFT_OVERLAYRETICLE: + FillFromEnumInt(std::string(field.szName), field.iOffset, szWeapOverlayReticleNames, std::extent_v); + break; + + case AUFT_CAMO: + { + const auto* camo = *reinterpret_cast(reinterpret_cast(m_structure) + field.iOffset); + + if (camo) + m_info_string.SetValueForKey(std::string(field.szName), std::string(AssetName(camo->name))); + else + m_info_string.SetValueForKey(std::string(field.szName), ""); + break; + } + + default: + assert(false); + break; + } + } + + public: + InfoStringFromWeaponAttachmentUniqueConverter(const WeaponAttachmentUniqueFull* structure, + const cspField_t* fields, + const size_t fieldCount, + std::function scriptStringValueCallback) + : InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback)) + { + } + }; + + void CopyToFullDef(const WeaponAttachmentUnique* attachment, WeaponAttachmentUniqueFull* fullDef) + { + fullDef->attachment = *attachment; + + if (attachment->szXAnims) + { + assert(sizeof(WeaponAttachmentUniqueFull::szXAnims) >= sizeof(void*) * NUM_WEAP_ANIMS); + memcpy(fullDef->szXAnims, attachment->szXAnims, sizeof(void*) * NUM_WEAP_ANIMS); + fullDef->attachment.szXAnims = fullDef->szXAnims; + } + + if (attachment->hideTags) + { + assert(sizeof(WeaponAttachmentUniqueFull::hideTags) >= sizeof(scr_string_t) * std::extent_v); + memcpy(fullDef->hideTags, attachment->hideTags, sizeof(scr_string_t) * std::extent_v); + fullDef->attachment.hideTags = fullDef->hideTags; + } + + if (attachment->locationDamageMultipliers) + { + assert(sizeof(WeaponAttachmentUniqueFull::locationDamageMultipliers) >= sizeof(float) * HITLOC_COUNT); + memcpy(fullDef->locationDamageMultipliers, attachment->locationDamageMultipliers, sizeof(float) * HITLOC_COUNT); + fullDef->attachment.locationDamageMultipliers = fullDef->locationDamageMultipliers; + } + } + + InfoString CreateInfoString(XAssetInfo* asset) + { + const auto fullDef = std::make_unique(); + memset(fullDef.get(), 0, sizeof(WeaponAttachmentUniqueFull)); + CopyToFullDef(asset->Asset(), fullDef.get()); + + InfoStringFromWeaponAttachmentUniqueConverter converter(fullDef.get(), + attachment_unique_fields, + std::extent_v, + [asset](const scr_string_t scrStr) -> std::string + { + assert(scrStr < asset->m_zone->m_script_strings.Count()); + if (scrStr >= asset->m_zone->m_script_strings.Count()) + return ""; + + return asset->m_zone->m_script_strings[scrStr]; + }); + + return converter.Convert(); + } +} // namespace + +namespace attachment_unique +{ + bool DumperT6::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperT6::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + // Only dump raw when no gdt available + if (context.m_gdt) + { + const auto infoString = CreateInfoString(asset); + GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_WEAPON_ATTACHMENT_UNIQUE); + infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_WEAPON_ATTACHMENT_UNIQUE, gdtEntry); + context.m_gdt->WriteEntry(gdtEntry); + } + else + { + const auto assetFile = context.OpenAssetFile(GetFileNameForAssetName(asset->m_name)); + + if (!assetFile) + return; + + auto& stream = *assetFile; + const auto infoString = CreateInfoString(asset); + const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_WEAPON_ATTACHMENT_UNIQUE); + stream.write(stringValue.c_str(), stringValue.size()); + } + } +} // namespace attachment_unique diff --git a/src/ObjWriting/Game/T6/Weapon/AttachmentUniqueDumperT6.h b/src/ObjWriting/Game/T6/Weapon/AttachmentUniqueDumperT6.h new file mode 100644 index 00000000..b3e2ae1a --- /dev/null +++ b/src/ObjWriting/Game/T6/Weapon/AttachmentUniqueDumperT6.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" + +namespace attachment_unique +{ + class DumperT6 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace attachment_unique diff --git a/src/ObjWriting/Game/T6/WeaponCamo/JsonWeaponCamoWriter.cpp b/src/ObjWriting/Game/T6/Weapon/CamoJsonDumperT6.cpp similarity index 87% rename from src/ObjWriting/Game/T6/WeaponCamo/JsonWeaponCamoWriter.cpp rename to src/ObjWriting/Game/T6/Weapon/CamoJsonDumperT6.cpp index 3438dae8..4a68492e 100644 --- a/src/ObjWriting/Game/T6/WeaponCamo/JsonWeaponCamoWriter.cpp +++ b/src/ObjWriting/Game/T6/Weapon/CamoJsonDumperT6.cpp @@ -1,7 +1,8 @@ -#include "JsonWeaponCamoWriter.h" +#include "CamoJsonDumperT6.h" #include "Game/T6/CommonT6.h" #include "Game/T6/Json/JsonWeaponCamo.h" +#include "Weapon/CamoCommon.h" #include #include @@ -11,10 +12,10 @@ using namespace T6; namespace { - class JsonDumper + class JsonDumperImpl { public: - explicit JsonDumper(std::ostream& stream) + explicit JsonDumperImpl(std::ostream& stream) : m_stream(stream) { } @@ -101,11 +102,22 @@ namespace }; } // namespace -namespace T6 +namespace camo { - void DumpWeaponCamoAsJson(std::ostream& stream, const WeaponCamo* weaponCamo) + bool JsonDumperT6::ShouldDump(XAssetInfo* asset) { - const JsonDumper dumper(stream); - dumper.Dump(weaponCamo); + return true; } -} // namespace T6 + + void JsonDumperT6::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto fileName = GetJsonFileNameForAssetName(asset->m_name); + const auto assetFile = context.OpenAssetFile(fileName); + + if (!assetFile) + return; + + const JsonDumperImpl dumper(*assetFile); + dumper.Dump(asset->Asset()); + } +} // namespace camo diff --git a/src/ObjWriting/Game/T6/Weapon/CamoJsonDumperT6.h b/src/ObjWriting/Game/T6/Weapon/CamoJsonDumperT6.h new file mode 100644 index 00000000..8bb91f12 --- /dev/null +++ b/src/ObjWriting/Game/T6/Weapon/CamoJsonDumperT6.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" + +namespace camo +{ + class JsonDumperT6 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace camo diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeapon.cpp b/src/ObjWriting/Game/T6/Weapon/WeaponDumperT6.cpp similarity index 53% rename from src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeapon.cpp rename to src/ObjWriting/Game/T6/Weapon/WeaponDumperT6.cpp index 24223dc4..96c5bcdc 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeapon.cpp +++ b/src/ObjWriting/Game/T6/Weapon/WeaponDumperT6.cpp @@ -1,10 +1,12 @@ -#include "AssetDumperWeapon.h" +#include "WeaponDumperT6.h" #include "Game/T6/InfoString/InfoStringFromStructConverter.h" #include "Game/T6/ObjConstantsT6.h" #include "Game/T6/Weapon/WeaponFields.h" #include "Game/T6/Weapon/WeaponStrings.h" +#include "InfoString/InfoString.h" #include "Weapon/AccuracyGraphWriter.h" +#include "Weapon/WeaponCommon.h" #include #include @@ -13,7 +15,7 @@ using namespace T6; -namespace T6 +namespace { class InfoStringFromWeaponConverter final : public InfoStringFromStructConverter { @@ -281,208 +283,212 @@ namespace T6 return graph; } -} // namespace T6 -void AssetDumperWeapon::CopyToFullDef(const WeaponVariantDef* weapon, WeaponFullDef* fullDef) -{ - fullDef->weapVariantDef = *weapon; - - if (weapon->weapDef) + void CopyToFullDef(const WeaponVariantDef* weapon, WeaponFullDef* fullDef) { - fullDef->weapDef = *weapon->weapDef; - fullDef->weapVariantDef.weapDef = &fullDef->weapDef; + fullDef->weapVariantDef = *weapon; + + if (weapon->weapDef) + { + fullDef->weapDef = *weapon->weapDef; + fullDef->weapVariantDef.weapDef = &fullDef->weapDef; + } + + if (weapon->attachments) + { + assert(sizeof(WeaponFullDef::attachments) >= sizeof(void*) * std::extent_v); + memcpy(fullDef->attachments, weapon->attachments, sizeof(void*) * std::extent_v); + fullDef->weapVariantDef.attachments = fullDef->attachments; + } + + if (weapon->attachmentUniques) + { + assert(sizeof(WeaponFullDef::attachmentUniques) >= sizeof(void*) * std::extent_v); + memcpy(fullDef->attachmentUniques, weapon->attachmentUniques, sizeof(void*) * std::extent_v); + fullDef->weapVariantDef.attachmentUniques = fullDef->attachmentUniques; + } + + if (fullDef->weapDef.gunXModel) + { + assert(sizeof(WeaponFullDef::gunXModel) >= sizeof(void*) * std::extent_v); + memcpy(fullDef->gunXModel, fullDef->weapDef.gunXModel, sizeof(void*) * std::extent_v); + fullDef->weapDef.gunXModel = fullDef->gunXModel; + } + + if (weapon->szXAnims) + { + assert(sizeof(WeaponFullDef::szXAnims) >= sizeof(void*) * NUM_WEAP_ANIMS); + memcpy(fullDef->szXAnims, weapon->szXAnims, sizeof(void*) * NUM_WEAP_ANIMS); + fullDef->weapVariantDef.szXAnims = fullDef->szXAnims; + } + + if (weapon->hideTags) + { + assert(sizeof(WeaponFullDef::hideTags) >= sizeof(scr_string_t) * std::extent_v); + memcpy(fullDef->hideTags, weapon->hideTags, sizeof(scr_string_t) * std::extent_v); + fullDef->weapVariantDef.hideTags = fullDef->hideTags; + } + + if (fullDef->weapDef.notetrackSoundMapKeys) + { + assert(sizeof(WeaponFullDef::notetrackSoundMapKeys) >= sizeof(scr_string_t) * std::extent_v); + memcpy(fullDef->notetrackSoundMapKeys, + fullDef->weapDef.notetrackSoundMapKeys, + sizeof(scr_string_t) * std::extent_v); + fullDef->weapDef.notetrackSoundMapKeys = fullDef->notetrackSoundMapKeys; + } + + if (fullDef->weapDef.notetrackSoundMapValues) + { + assert(sizeof(WeaponFullDef::notetrackSoundMapValues) >= sizeof(scr_string_t) * std::extent_v); + memcpy(fullDef->notetrackSoundMapValues, + fullDef->weapDef.notetrackSoundMapValues, + sizeof(scr_string_t) * std::extent_v); + fullDef->weapDef.notetrackSoundMapValues = fullDef->notetrackSoundMapValues; + } + + if (fullDef->weapDef.worldModel) + { + assert(sizeof(WeaponFullDef::worldModel) >= sizeof(void*) * std::extent_v); + memcpy(fullDef->worldModel, fullDef->weapDef.worldModel, sizeof(void*) * std::extent_v); + fullDef->weapDef.worldModel = fullDef->worldModel; + } + + if (weapon->attachViewModel) + { + assert(sizeof(WeaponFullDef::attachViewModel) >= sizeof(void*) * std::extent_v); + memcpy(fullDef->attachViewModel, weapon->attachViewModel, sizeof(void*) * std::extent_v); + fullDef->weapVariantDef.attachViewModel = fullDef->attachViewModel; + } + + if (weapon->attachWorldModel) + { + assert(sizeof(WeaponFullDef::attachWorldModel) >= sizeof(void*) * std::extent_v); + memcpy(fullDef->attachWorldModel, weapon->attachWorldModel, sizeof(void*) * std::extent_v); + fullDef->weapVariantDef.attachWorldModel = fullDef->attachWorldModel; + } + + if (weapon->attachViewModelTag) + { + assert(sizeof(WeaponFullDef::attachViewModelTag) >= sizeof(void*) * std::extent_v); + memcpy(fullDef->attachViewModelTag, weapon->attachViewModelTag, sizeof(void*) * std::extent_v); + fullDef->weapVariantDef.attachViewModelTag = fullDef->attachViewModelTag; + } + + if (weapon->attachWorldModelTag) + { + assert(sizeof(WeaponFullDef::attachWorldModelTag) >= sizeof(void*) * std::extent_v); + memcpy(fullDef->attachWorldModelTag, weapon->attachWorldModelTag, sizeof(void*) * std::extent_v); + fullDef->weapVariantDef.attachWorldModelTag = fullDef->attachWorldModelTag; + } + + if (fullDef->weapDef.parallelBounce) + { + assert(sizeof(WeaponFullDef::parallelBounce) >= sizeof(float) * SURF_TYPE_NUM); + memcpy(fullDef->parallelBounce, fullDef->weapDef.parallelBounce, sizeof(float) * SURF_TYPE_NUM); + fullDef->weapDef.parallelBounce = fullDef->parallelBounce; + } + + if (fullDef->weapDef.perpendicularBounce) + { + assert(sizeof(WeaponFullDef::perpendicularBounce) >= sizeof(float) * SURF_TYPE_NUM); + memcpy(fullDef->perpendicularBounce, fullDef->weapDef.perpendicularBounce, sizeof(float) * SURF_TYPE_NUM); + fullDef->weapDef.perpendicularBounce = fullDef->perpendicularBounce; + } + + if (fullDef->weapDef.locationDamageMultipliers) + { + assert(sizeof(WeaponFullDef::locationDamageMultipliers) >= sizeof(float) * HITLOC_COUNT); + memcpy(fullDef->locationDamageMultipliers, fullDef->weapDef.locationDamageMultipliers, sizeof(float) * HITLOC_COUNT); + fullDef->weapDef.locationDamageMultipliers = fullDef->locationDamageMultipliers; + } + + if (fullDef->weapDef.weaponCamo && fullDef->weapDef.weaponCamo->name) + { + strncpy(fullDef->weaponCamo, fullDef->weapDef.weaponCamo->name, std::extent_v); + } } - if (weapon->attachments) + InfoString CreateInfoString(XAssetInfo* asset) { - assert(sizeof(WeaponFullDef::attachments) >= sizeof(void*) * std::extent_v); - memcpy(fullDef->attachments, weapon->attachments, sizeof(void*) * std::extent_v); - fullDef->weapVariantDef.attachments = fullDef->attachments; + const auto fullDef = std::make_unique(); + memset(fullDef.get(), 0, sizeof(WeaponFullDef)); + CopyToFullDef(asset->Asset(), fullDef.get()); + + InfoStringFromWeaponConverter converter(fullDef.get(), + weapon_fields, + std::extent_v, + [asset](const scr_string_t scrStr) -> std::string + { + assert(scrStr < asset->m_zone->m_script_strings.Count()); + if (scrStr >= asset->m_zone->m_script_strings.Count()) + return ""; + + return asset->m_zone->m_script_strings[scrStr]; + }); + + return converter.Convert(); } - if (weapon->attachmentUniques) + void DumpAccuracyGraphs(AssetDumpingContext& context, XAssetInfo* asset) { - assert(sizeof(WeaponFullDef::attachmentUniques) >= sizeof(void*) * std::extent_v); - memcpy(fullDef->attachmentUniques, weapon->attachmentUniques, sizeof(void*) * std::extent_v); - fullDef->weapVariantDef.attachmentUniques = fullDef->attachmentUniques; - } + auto* accuracyGraphWriter = context.GetZoneAssetDumperState(); + const auto weapon = asset->Asset(); + const auto* weapDef = weapon->weapDef; - if (fullDef->weapDef.gunXModel) - { - assert(sizeof(WeaponFullDef::gunXModel) >= sizeof(void*) * std::extent_v); - memcpy(fullDef->gunXModel, fullDef->weapDef.gunXModel, sizeof(void*) * std::extent_v); - fullDef->weapDef.gunXModel = fullDef->gunXModel; - } - - if (weapon->szXAnims) - { - assert(sizeof(WeaponFullDef::szXAnims) >= sizeof(void*) * NUM_WEAP_ANIMS); - memcpy(fullDef->szXAnims, weapon->szXAnims, sizeof(void*) * NUM_WEAP_ANIMS); - fullDef->weapVariantDef.szXAnims = fullDef->szXAnims; - } - - if (weapon->hideTags) - { - assert(sizeof(WeaponFullDef::hideTags) >= sizeof(scr_string_t) * std::extent_v); - memcpy(fullDef->hideTags, weapon->hideTags, sizeof(scr_string_t) * std::extent_v); - fullDef->weapVariantDef.hideTags = fullDef->hideTags; - } - - if (fullDef->weapDef.notetrackSoundMapKeys) - { - assert(sizeof(WeaponFullDef::notetrackSoundMapKeys) >= sizeof(scr_string_t) * std::extent_v); - memcpy(fullDef->notetrackSoundMapKeys, - fullDef->weapDef.notetrackSoundMapKeys, - sizeof(scr_string_t) * std::extent_v); - fullDef->weapDef.notetrackSoundMapKeys = fullDef->notetrackSoundMapKeys; - } - - if (fullDef->weapDef.notetrackSoundMapValues) - { - assert(sizeof(WeaponFullDef::notetrackSoundMapValues) >= sizeof(scr_string_t) * std::extent_v); - memcpy(fullDef->notetrackSoundMapValues, - fullDef->weapDef.notetrackSoundMapValues, - sizeof(scr_string_t) * std::extent_v); - fullDef->weapDef.notetrackSoundMapValues = fullDef->notetrackSoundMapValues; - } - - if (fullDef->weapDef.worldModel) - { - assert(sizeof(WeaponFullDef::worldModel) >= sizeof(void*) * std::extent_v); - memcpy(fullDef->worldModel, fullDef->weapDef.worldModel, sizeof(void*) * std::extent_v); - fullDef->weapDef.worldModel = fullDef->worldModel; - } - - if (weapon->attachViewModel) - { - assert(sizeof(WeaponFullDef::attachViewModel) >= sizeof(void*) * std::extent_v); - memcpy(fullDef->attachViewModel, weapon->attachViewModel, sizeof(void*) * std::extent_v); - fullDef->weapVariantDef.attachViewModel = fullDef->attachViewModel; - } - - if (weapon->attachWorldModel) - { - assert(sizeof(WeaponFullDef::attachWorldModel) >= sizeof(void*) * std::extent_v); - memcpy(fullDef->attachWorldModel, weapon->attachWorldModel, sizeof(void*) * std::extent_v); - fullDef->weapVariantDef.attachWorldModel = fullDef->attachWorldModel; - } - - if (weapon->attachViewModelTag) - { - assert(sizeof(WeaponFullDef::attachViewModelTag) >= sizeof(void*) * std::extent_v); - memcpy(fullDef->attachViewModelTag, weapon->attachViewModelTag, sizeof(void*) * std::extent_v); - fullDef->weapVariantDef.attachViewModelTag = fullDef->attachViewModelTag; - } - - if (weapon->attachWorldModelTag) - { - assert(sizeof(WeaponFullDef::attachWorldModelTag) >= sizeof(void*) * std::extent_v); - memcpy(fullDef->attachWorldModelTag, weapon->attachWorldModelTag, sizeof(void*) * std::extent_v); - fullDef->weapVariantDef.attachWorldModelTag = fullDef->attachWorldModelTag; - } - - if (fullDef->weapDef.parallelBounce) - { - assert(sizeof(WeaponFullDef::parallelBounce) >= sizeof(float) * SURF_TYPE_NUM); - memcpy(fullDef->parallelBounce, fullDef->weapDef.parallelBounce, sizeof(float) * SURF_TYPE_NUM); - fullDef->weapDef.parallelBounce = fullDef->parallelBounce; - } - - if (fullDef->weapDef.perpendicularBounce) - { - assert(sizeof(WeaponFullDef::perpendicularBounce) >= sizeof(float) * SURF_TYPE_NUM); - memcpy(fullDef->perpendicularBounce, fullDef->weapDef.perpendicularBounce, sizeof(float) * SURF_TYPE_NUM); - fullDef->weapDef.perpendicularBounce = fullDef->perpendicularBounce; - } - - if (fullDef->weapDef.locationDamageMultipliers) - { - assert(sizeof(WeaponFullDef::locationDamageMultipliers) >= sizeof(float) * HITLOC_COUNT); - memcpy(fullDef->locationDamageMultipliers, fullDef->weapDef.locationDamageMultipliers, sizeof(float) * HITLOC_COUNT); - fullDef->weapDef.locationDamageMultipliers = fullDef->locationDamageMultipliers; - } - - if (fullDef->weapDef.weaponCamo && fullDef->weapDef.weaponCamo->name) - { - strncpy(fullDef->weaponCamo, fullDef->weapDef.weaponCamo->name, std::extent_v); - } -} - -InfoString AssetDumperWeapon::CreateInfoString(XAssetInfo* asset) -{ - const auto fullDef = std::make_unique(); - memset(fullDef.get(), 0, sizeof(WeaponFullDef)); - CopyToFullDef(asset->Asset(), fullDef.get()); - - InfoStringFromWeaponConverter converter(fullDef.get(), - weapon_fields, - std::extent_v, - [asset](const scr_string_t scrStr) -> std::string - { - assert(scrStr < asset->m_zone->m_script_strings.Count()); - if (scrStr >= asset->m_zone->m_script_strings.Count()) - return ""; - - return asset->m_zone->m_script_strings[scrStr]; - }); - - return converter.Convert(); -} - -void AssetDumperWeapon::DumpAccuracyGraphs(AssetDumpingContext& context, XAssetInfo* asset) -{ - auto* accuracyGraphWriter = context.GetZoneAssetDumperState(); - const auto weapon = asset->Asset(); - const auto* weapDef = weapon->weapDef; - - if (!weapDef) - return; - - if (weapDef->aiVsAiAccuracyGraphName && weapDef->originalAiVsAiAccuracyGraphKnots - && accuracyGraphWriter->ShouldDumpAiVsAiGraph(weapDef->aiVsAiAccuracyGraphName)) - { - AccuracyGraphWriter::DumpAiVsAiGraph( - context, - ConvertAccuracyGraph(weapDef->aiVsAiAccuracyGraphName, weapDef->originalAiVsAiAccuracyGraphKnots, weapDef->originalAiVsAiAccuracyGraphKnotCount)); - } - - if (weapDef->aiVsPlayerAccuracyGraphName && weapDef->originalAiVsPlayerAccuracyGraphKnots - && accuracyGraphWriter->ShouldDumpAiVsPlayerGraph(weapDef->aiVsPlayerAccuracyGraphName)) - { - AccuracyGraphWriter::DumpAiVsPlayerGraph(context, - ConvertAccuracyGraph(weapDef->aiVsPlayerAccuracyGraphName, - weapDef->originalAiVsPlayerAccuracyGraphKnots, - weapDef->originalAiVsPlayerAccuracyGraphKnotCount)); - } -} - -bool AssetDumperWeapon::ShouldDump(XAssetInfo* asset) -{ - return true; -} - -void AssetDumperWeapon::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) -{ - // Only dump raw when no gdt available - if (context.m_gdt) - { - const auto infoString = CreateInfoString(asset); - GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_WEAPON); - infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_WEAPON, gdtEntry); - context.m_gdt->WriteEntry(gdtEntry); - } - else - { - const auto assetFile = context.OpenAssetFile("weapons/" + asset->m_name); - - if (!assetFile) + if (!weapDef) return; - auto& stream = *assetFile; - const auto infoString = CreateInfoString(asset); - const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_WEAPON); - stream.write(stringValue.c_str(), stringValue.size()); + if (weapDef->aiVsAiAccuracyGraphName && weapDef->originalAiVsAiAccuracyGraphKnots + && accuracyGraphWriter->ShouldDumpAiVsAiGraph(weapDef->aiVsAiAccuracyGraphName)) + { + AccuracyGraphWriter::DumpAiVsAiGraph(context, + ConvertAccuracyGraph(weapDef->aiVsAiAccuracyGraphName, + weapDef->originalAiVsAiAccuracyGraphKnots, + weapDef->originalAiVsAiAccuracyGraphKnotCount)); + } + + if (weapDef->aiVsPlayerAccuracyGraphName && weapDef->originalAiVsPlayerAccuracyGraphKnots + && accuracyGraphWriter->ShouldDumpAiVsPlayerGraph(weapDef->aiVsPlayerAccuracyGraphName)) + { + AccuracyGraphWriter::DumpAiVsPlayerGraph(context, + ConvertAccuracyGraph(weapDef->aiVsPlayerAccuracyGraphName, + weapDef->originalAiVsPlayerAccuracyGraphKnots, + weapDef->originalAiVsPlayerAccuracyGraphKnotCount)); + } + } +} // namespace + +namespace weapon +{ + bool DumperT6::ShouldDump(XAssetInfo* asset) + { + return true; } - DumpAccuracyGraphs(context, asset); -} + void DumperT6::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + // Only dump raw when no gdt available + if (context.m_gdt) + { + const auto infoString = CreateInfoString(asset); + GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_WEAPON); + infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_WEAPON, gdtEntry); + context.m_gdt->WriteEntry(gdtEntry); + } + else + { + const auto assetFile = context.OpenAssetFile(GetFileNameForAssetName(asset->m_name)); + + if (!assetFile) + return; + + auto& stream = *assetFile; + const auto infoString = CreateInfoString(asset); + const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_WEAPON); + stream.write(stringValue.c_str(), stringValue.size()); + } + + DumpAccuracyGraphs(context, asset); + } +} // namespace weapon diff --git a/src/ObjWriting/Game/T6/Weapon/WeaponDumperT6.h b/src/ObjWriting/Game/T6/Weapon/WeaponDumperT6.h new file mode 100644 index 00000000..4b3b500f --- /dev/null +++ b/src/ObjWriting/Game/T6/Weapon/WeaponDumperT6.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" + +namespace weapon +{ + class DumperT6 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace weapon diff --git a/src/ObjWriting/Game/T6/WeaponCamo/JsonWeaponCamoWriter.h b/src/ObjWriting/Game/T6/WeaponCamo/JsonWeaponCamoWriter.h deleted file mode 100644 index 0da45568..00000000 --- a/src/ObjWriting/Game/T6/WeaponCamo/JsonWeaponCamoWriter.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "Dumping/AssetDumpingContext.h" -#include "Game/T6/T6.h" - -#include - -namespace T6 -{ - void DumpWeaponCamoAsJson(std::ostream& stream, const WeaponCamo* weaponCamo); -} // namespace T6 diff --git a/src/ObjWriting/Game/T6/ZBarrier/ZBarrierDumperT6.cpp b/src/ObjWriting/Game/T6/ZBarrier/ZBarrierDumperT6.cpp new file mode 100644 index 00000000..1a7edb80 --- /dev/null +++ b/src/ObjWriting/Game/T6/ZBarrier/ZBarrierDumperT6.cpp @@ -0,0 +1,81 @@ +#include "ZBarrierDumperT6.h" + +#include "Game/T6/InfoString/InfoStringFromStructConverter.h" +#include "Game/T6/ObjConstantsT6.h" +#include "Game/T6/ZBarrier/ZBarrierFields.h" +#include "ZBarrier/ZBarrierCommon.h" + +#include +#include + +using namespace T6; + +namespace +{ + class InfoStringFromZBarrierConverter final : public InfoStringFromStructConverter + { + protected: + void FillFromExtensionField(const cspField_t& field) override + { + assert(false); + } + + public: + InfoStringFromZBarrierConverter(const ZBarrierDef* structure, + const cspField_t* fields, + const size_t fieldCount, + std::function scriptStringValueCallback) + : InfoStringFromStructConverter(structure, fields, fieldCount, std::move(scriptStringValueCallback)) + { + } + }; + + InfoString CreateInfoString(XAssetInfo* asset) + { + InfoStringFromZBarrierConverter converter(asset->Asset(), + zbarrier_fields, + std::extent_v, + [asset](const scr_string_t scrStr) -> std::string + { + assert(scrStr < asset->m_zone->m_script_strings.Count()); + if (scrStr >= asset->m_zone->m_script_strings.Count()) + return ""; + + return asset->m_zone->m_script_strings[scrStr]; + }); + + return converter.Convert(); + } +} // namespace + +namespace z_barrier +{ + bool DumperT6::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void DumperT6::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + // Only dump raw when no gdt available + if (context.m_gdt) + { + const auto infoString = CreateInfoString(asset); + GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_ZBARRIER); + infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_ZBARRIER, gdtEntry); + context.m_gdt->WriteEntry(gdtEntry); + } + else + { + const auto assetFile = context.OpenAssetFile(GetFileNameForAssetName(asset->m_name)); + + if (!assetFile) + return; + + auto& stream = *assetFile; + const auto infoString = CreateInfoString(asset); + const auto stringValue = infoString.ToString(ObjConstants::INFO_STRING_PREFIX_ZBARRIER); + stream.write(stringValue.c_str(), stringValue.size()); + } + } +} // namespace z_barrier diff --git a/src/ObjWriting/Game/T6/ZBarrier/ZBarrierDumperT6.h b/src/ObjWriting/Game/T6/ZBarrier/ZBarrierDumperT6.h new file mode 100644 index 00000000..9e60f414 --- /dev/null +++ b/src/ObjWriting/Game/T6/ZBarrier/ZBarrierDumperT6.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" +#include "InfoString/InfoString.h" + +namespace z_barrier +{ + class DumperT6 final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace z_barrier diff --git a/src/ObjWriting/Material/JsonMaterialWriter.h.template b/src/ObjWriting/Material/JsonMaterialWriter.h.template deleted file mode 100644 index 277c5420..00000000 --- a/src/ObjWriting/Material/JsonMaterialWriter.h.template +++ /dev/null @@ -1,20 +0,0 @@ -#options GAME (IW3, IW4, IW5, T5, T6) - -#filename "Game/" + GAME + "/Material/JsonMaterialWriter" + GAME + ".h" - -// This file was templated. -// See JsonMaterialWriter.h.template. -// Do not modify, changes will be lost. - -#pragma once - -#include "Dumping/AssetDumpingContext.h" -#set GAME_HEADER "\"Game/" + GAME + "/" + GAME + ".h\"" -#include GAME_HEADER - -#include - -namespace GAME -{ - void DumpMaterialAsJson(std::ostream& stream, const Material& material, AssetDumpingContext& context); -} // namespace GAME diff --git a/src/ObjWriting/Material/JsonMaterialWriter.cpp.template b/src/ObjWriting/Material/MaterialJsonDumper.cpp.template similarity index 90% rename from src/ObjWriting/Material/JsonMaterialWriter.cpp.template rename to src/ObjWriting/Material/MaterialJsonDumper.cpp.template index 4cce4829..7eb8ad51 100644 --- a/src/ObjWriting/Material/JsonMaterialWriter.cpp.template +++ b/src/ObjWriting/Material/MaterialJsonDumper.cpp.template @@ -1,6 +1,6 @@ #options GAME (IW3, IW4, IW5, T5, T6) -#filename "Game/" + GAME + "/Material/JsonMaterialWriter" + GAME + ".cpp" +#filename "Game/" + GAME + "/Material/MaterialJsonDumper" + GAME + ".cpp" #if GAME == "IW3" #define FEATURE_IW3 @@ -24,16 +24,17 @@ #endif // This file was templated. -// See JsonMaterialWriter.cpp.template. +// See MaterialJsonDumper.cpp.template. // Do not modify, changes will be lost. -#set WRITER_HEADER "\"JsonMaterialWriter" + GAME + ".h\"" +#set WRITER_HEADER "\"MaterialJsonDumper" + GAME + ".h\"" #include WRITER_HEADER #ifdef HAS_WATER #include "Base64.h" #endif +#include "Material/MaterialCommon.h" #set COMMON_HEADER "\"Game/" + GAME + "/Common" + GAME + ".h\"" #include COMMON_HEADER #set JSON_HEADER "\"Game/" + GAME + "/Material/JsonMaterial" + GAME + ".h\"" @@ -41,18 +42,21 @@ #set CONSTANTS_HEADER "\"Game/" + GAME + "/Material/MaterialConstantZoneState" + GAME + ".h\"" #include CONSTANTS_HEADER +#include #include #include using namespace nlohmann; using namespace GAME; +#set CLASS_NAME "JsonDumper" + GAME + namespace { - class JsonDumper + class JsonDumperImpl { public: - JsonDumper(AssetDumpingContext& context, std::ostream& stream) + JsonDumperImpl(AssetDumpingContext& context, std::ostream& stream) : m_stream(stream), m_material_constants(*context.GetZoneAssetDumperState()) { @@ -355,11 +359,40 @@ namespace }; } // namespace -namespace GAME +namespace material { - void DumpMaterialAsJson(std::ostream& stream, const Material& material, AssetDumpingContext& context) + void CLASS_NAME::DumpPool(AssetDumpingContext& context, AssetPool* pool) { - const JsonDumper dumper(context, stream); - dumper.Dump(material); + auto* materialConstantState = context.GetZoneAssetDumperState(); + materialConstantState->ExtractNamesFromZone(); + + AbstractAssetDumper::DumpPool(context, pool); } -} // namespace GAME + + bool CLASS_NAME::ShouldDump(XAssetInfo* asset) + { + return true; + } + + void CLASS_NAME::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) + { + const auto assetFile = context.OpenAssetFile(GetFileNameForAssetName(asset->m_name)); + + if (!assetFile) + return; + + const auto* material = asset->Asset(); +#if defined(FEATURE_T5) + assert(material->info.gameFlags < 0x400); + assert(material->maxStreamedMips == 0); +#elif defined(FEATURE_T6) + assert(material->info.gameFlags < 0x8000); + assert(material->info.hashIndex == 0); + assert(material->probeMipBits == 0); +#endif + + JsonDumperImpl dumper(context, *assetFile); + dumper.Dump(*material); + } +} // namespace material + diff --git a/src/ObjWriting/Material/MaterialJsonDumper.h.template b/src/ObjWriting/Material/MaterialJsonDumper.h.template new file mode 100644 index 00000000..f8a41515 --- /dev/null +++ b/src/ObjWriting/Material/MaterialJsonDumper.h.template @@ -0,0 +1,29 @@ +#options GAME(IW3, IW4, IW5, T5, T6) + +#filename "Game/" + GAME + "/Material/MaterialJsonDumper" + GAME + ".h" + +// This file was templated. +// See MaterialJsonDumper.h.template. +// Do not modify, changes will be lost. + +#pragma once + +#include "Dumping/AbstractAssetDumper.h" +#include "Dumping/AssetDumpingContext.h" +#set GAME_HEADER "\"Game/" + GAME + "/" + GAME + ".h\"" +#include GAME_HEADER + +#set CLASS_NAME "JsonDumper" + GAME + +namespace material +{ + class CLASS_NAME final : public AbstractAssetDumper + { + public: + void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; + + protected: + [[nodiscard]] bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace material diff --git a/src/ObjWriting/Menu/AbstractMenuDumper.cpp b/src/ObjWriting/Menu/AbstractMenuDumper.cpp deleted file mode 100644 index 5b00b40b..00000000 --- a/src/ObjWriting/Menu/AbstractMenuDumper.cpp +++ /dev/null @@ -1,298 +0,0 @@ -#include "AbstractMenuDumper.h" - -#include "Parsing/Impl/ParserSingleInputStream.h" -#include "Parsing/Simple/SimpleLexer.h" - -#include -#include -#include - -AbstractMenuDumper::AbstractMenuDumper(std::ostream& stream) - : m_stream(stream), - m_indent(0u) -{ -} - -void AbstractMenuDumper::IncIndent() -{ - m_indent++; -} - -void AbstractMenuDumper::DecIndent() -{ - if (m_indent > 0) - m_indent--; -} - -void AbstractMenuDumper::Indent() const -{ - for (auto i = 0u; i < m_indent; i++) - m_stream << " "; -} - -void AbstractMenuDumper::StartScope(const std::string& scopeName) -{ - Indent(); - m_stream << scopeName << "\n"; - Indent(); - m_stream << "{\n"; - IncIndent(); -} - -void AbstractMenuDumper::StartMenuDefScope() -{ - StartScope("menuDef"); -} - -void AbstractMenuDumper::StartItemDefScope() -{ - StartScope("itemDef"); -} - -void AbstractMenuDumper::StartFunctionDefScope() -{ - StartScope("functionDef"); -} - -void AbstractMenuDumper::EndScope() -{ - DecIndent(); - Indent(); - m_stream << "}\n"; -} - -std::vector AbstractMenuDumper::CreateScriptTokenList(const char* script) -{ - const std::string scriptString(script); - std::istringstream stringStream(scriptString); - ParserSingleInputStream inputStream(stringStream, "MenuScript"); - - SimpleLexer::Config lexerConfig; - lexerConfig.m_emit_new_line_tokens = false; - lexerConfig.m_read_strings = true; - lexerConfig.m_string_escape_sequences = true; - lexerConfig.m_read_integer_numbers = false; - lexerConfig.m_read_floating_point_numbers = false; - SimpleLexer lexer(&inputStream, std::move(lexerConfig)); - - std::vector result; - auto hasLexerTokens = true; - while (hasLexerTokens) - { - const auto& token = lexer.GetToken(0); - switch (token.m_type) - { - case SimpleParserValueType::IDENTIFIER: - result.emplace_back(token.IdentifierValue()); - break; - - case SimpleParserValueType::STRING: - result.emplace_back(token.StringValue()); - break; - - case SimpleParserValueType::CHARACTER: - result.emplace_back(1, token.CharacterValue()); - break; - - case SimpleParserValueType::INVALID: - case SimpleParserValueType::END_OF_FILE: - hasLexerTokens = false; - break; - - default: - assert(false); - break; - } - - lexer.PopTokens(1); - } - - return result; -} - -bool AbstractMenuDumper::DoesTokenNeedQuotationMarks(const std::string& token) -{ - if (token.empty()) - return true; - - const auto hasAlNumCharacter = std::ranges::any_of(token, - [](const char& c) - { - return isalnum(c); - }); - - if (!hasAlNumCharacter) - return false; - - const auto hasNonIdentifierCharacter = std::ranges::any_of(token, - [](const char& c) - { - return !isalnum(c) && c != '_'; - }); - - return hasNonIdentifierCharacter; -} - -void AbstractMenuDumper::WriteEscapedString(const std::string_view& str) const -{ - m_stream << "\""; - - for (const auto& c : str) - { - switch (c) - { - case '\r': - m_stream << "\\r"; - break; - case '\n': - m_stream << "\\n"; - break; - case '\t': - m_stream << "\\t"; - break; - case '\f': - m_stream << "\\f"; - break; - case '"': - m_stream << "\\\""; - break; - default: - m_stream << c; - break; - } - } - - m_stream << "\""; -} - -const std::string& AbstractMenuDumper::BoolValue(const bool value) -{ - return value ? BOOL_VALUE_TRUE : BOOL_VALUE_FALSE; -} - -void AbstractMenuDumper::WriteKey(const std::string& keyName) const -{ - m_stream << keyName; - - if (keyName.size() < MENU_KEY_SPACING) - { - const auto spacingLength = MENU_KEY_SPACING - keyName.size(); - for (auto i = 0u; i < spacingLength; i++) - m_stream << " "; - } -} - -void AbstractMenuDumper::WriteStringProperty(const std::string& propertyKey, const std::string& propertyValue) const -{ - if (propertyValue.empty()) - return; - - Indent(); - WriteKey(propertyKey); - - WriteEscapedString(propertyValue); - m_stream << "\n"; -} - -void AbstractMenuDumper::WriteStringProperty(const std::string& propertyKey, const char* propertyValue) const -{ - if (propertyValue == nullptr || propertyValue[0] == '\0') - return; - - Indent(); - WriteKey(propertyKey); - - WriteEscapedString(propertyValue); - m_stream << "\n"; -} - -void AbstractMenuDumper::WriteBoolProperty(const std::string& propertyKey, const bool propertyValue, const bool defaultValue) const -{ - if (propertyValue == defaultValue) - return; - - Indent(); - WriteKey(propertyKey); - m_stream << BoolValue(propertyValue) << "\n"; -} - -void AbstractMenuDumper::WriteIntProperty(const std::string& propertyKey, const int propertyValue, const int defaultValue) const -{ - if (propertyValue == defaultValue) - return; - - Indent(); - WriteKey(propertyKey); - m_stream << propertyValue << "\n"; -} - -void AbstractMenuDumper::WriteFloatProperty(const std::string& propertyKey, const float propertyValue, const float defaultValue) const -{ - if (std::fabs(propertyValue - defaultValue) < std::numeric_limits::epsilon()) - return; - - Indent(); - WriteKey(propertyKey); - m_stream << propertyValue << "\n"; -} - -void AbstractMenuDumper::WriteColorProperty(const std::string& propertyKey, const float (&propertyValue)[4], const float (&defaultValue)[4]) const -{ - if (std::fabs(propertyValue[0] - defaultValue[0]) < std::numeric_limits::epsilon() - && std::fabs(propertyValue[1] - defaultValue[1]) < std::numeric_limits::epsilon() - && std::fabs(propertyValue[2] - defaultValue[2]) < std::numeric_limits::epsilon() - && std::fabs(propertyValue[3] - defaultValue[3]) < std::numeric_limits::epsilon()) - { - return; - } - - Indent(); - WriteKey(propertyKey); - m_stream << propertyValue[0] << " " << propertyValue[1] << " " << propertyValue[2] << " " << propertyValue[3] << "\n"; -} - -void AbstractMenuDumper::WriteKeywordProperty(const std::string& propertyKey, const bool shouldWrite) const -{ - if (!shouldWrite) - return; - - Indent(); - WriteKey(propertyKey); - m_stream << "\n"; -} - -void AbstractMenuDumper::WriteFlagsProperty(const std::string& propertyKey, const int flagsValue) const -{ - for (auto i = 0u; i < sizeof(flagsValue) * 8; i++) - { - if (flagsValue & (1 << i)) - { - Indent(); - WriteKey(propertyKey); - m_stream << i << "\n"; - } - } -} - -void AbstractMenuDumper::Start() -{ - Indent(); - m_stream << "{\n"; - IncIndent(); -} - -void AbstractMenuDumper::End() -{ - for (auto i = 0u; i < m_indent; i++) - { - DecIndent(); - Indent(); - m_stream << "}\n"; - } -} - -void AbstractMenuDumper::IncludeMenu(const std::string& menuPath) const -{ - Indent(); - m_stream << "loadMenu { \"" << menuPath << "\" }\n"; -} diff --git a/src/ObjWriting/Menu/AbstractMenuDumper.h b/src/ObjWriting/Menu/AbstractMenuDumper.h deleted file mode 100644 index 10494684..00000000 --- a/src/ObjWriting/Menu/AbstractMenuDumper.h +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -class AbstractMenuDumper -{ -protected: - static constexpr auto MENU_KEY_SPACING = 28u; - static const inline std::string BOOL_VALUE_TRUE = "1"; - static const inline std::string BOOL_VALUE_FALSE = "0"; - static constexpr inline float COLOR_0000[4]{0.0f, 0.0f, 0.0f, 0.0f}; - static constexpr inline float COLOR_1111[4]{1.0f, 1.0f, 1.0f, 1.0f}; - - std::ostream& m_stream; - size_t m_indent; - - void IncIndent(); - void DecIndent(); - void Indent() const; - - void StartScope(const std::string& scopeName); - void StartMenuDefScope(); - void StartItemDefScope(); - void StartFunctionDefScope(); - void EndScope(); - - static std::vector CreateScriptTokenList(const char* script); - static bool DoesTokenNeedQuotationMarks(const std::string& token); - - void WriteEscapedString(const std::string_view& str) const; - - static const std::string& BoolValue(bool value); - void WriteKey(const std::string& keyName) const; - void WriteStringProperty(const std::string& propertyKey, const std::string& propertyValue) const; - void WriteStringProperty(const std::string& propertyKey, const char* propertyValue) const; - void WriteBoolProperty(const std::string& propertyKey, bool propertyValue, bool defaultValue) const; - void WriteIntProperty(const std::string& propertyKey, int propertyValue, int defaultValue) const; - void WriteFloatProperty(const std::string& propertyKey, float propertyValue, float defaultValue) const; - void WriteColorProperty(const std::string& propertyKey, const float (&propertyValue)[4], const float (&defaultValue)[4]) const; - void WriteKeywordProperty(const std::string& propertyKey, bool shouldWrite) const; - void WriteFlagsProperty(const std::string& propertyKey, int flagsValue) const; - - explicit AbstractMenuDumper(std::ostream& stream); - -public: - void Start(); - void End(); - - void IncludeMenu(const std::string& menuPath) const; -}; diff --git a/src/ObjWriting/Menu/AbstractMenuWriter.cpp b/src/ObjWriting/Menu/AbstractMenuWriter.cpp new file mode 100644 index 00000000..34c1b567 --- /dev/null +++ b/src/ObjWriting/Menu/AbstractMenuWriter.cpp @@ -0,0 +1,301 @@ +#include "AbstractMenuWriter.h" + +#include "Parsing/Impl/ParserSingleInputStream.h" +#include "Parsing/Simple/SimpleLexer.h" + +#include +#include +#include + +namespace menu +{ + AbstractBaseWriter::AbstractBaseWriter(std::ostream& stream) + : m_stream(stream), + m_indent(0u) + { + } + + void AbstractBaseWriter::IncIndent() + { + m_indent++; + } + + void AbstractBaseWriter::DecIndent() + { + if (m_indent > 0) + m_indent--; + } + + void AbstractBaseWriter::Indent() const + { + for (auto i = 0u; i < m_indent; i++) + m_stream << " "; + } + + void AbstractBaseWriter::StartScope(const std::string& scopeName) + { + Indent(); + m_stream << scopeName << "\n"; + Indent(); + m_stream << "{\n"; + IncIndent(); + } + + void AbstractBaseWriter::StartMenuDefScope() + { + StartScope("menuDef"); + } + + void AbstractBaseWriter::StartItemDefScope() + { + StartScope("itemDef"); + } + + void AbstractBaseWriter::StartFunctionDefScope() + { + StartScope("functionDef"); + } + + void AbstractBaseWriter::EndScope() + { + DecIndent(); + Indent(); + m_stream << "}\n"; + } + + std::vector AbstractBaseWriter::CreateScriptTokenList(const char* script) + { + const std::string scriptString(script); + std::istringstream stringStream(scriptString); + ParserSingleInputStream inputStream(stringStream, "MenuScript"); + + SimpleLexer::Config lexerConfig; + lexerConfig.m_emit_new_line_tokens = false; + lexerConfig.m_read_strings = true; + lexerConfig.m_string_escape_sequences = true; + lexerConfig.m_read_integer_numbers = false; + lexerConfig.m_read_floating_point_numbers = false; + SimpleLexer lexer(&inputStream, std::move(lexerConfig)); + + std::vector result; + auto hasLexerTokens = true; + while (hasLexerTokens) + { + const auto& token = lexer.GetToken(0); + switch (token.m_type) + { + case SimpleParserValueType::IDENTIFIER: + result.emplace_back(token.IdentifierValue()); + break; + + case SimpleParserValueType::STRING: + result.emplace_back(token.StringValue()); + break; + + case SimpleParserValueType::CHARACTER: + result.emplace_back(1, token.CharacterValue()); + break; + + case SimpleParserValueType::INVALID: + case SimpleParserValueType::END_OF_FILE: + hasLexerTokens = false; + break; + + default: + assert(false); + break; + } + + lexer.PopTokens(1); + } + + return result; + } + + bool AbstractBaseWriter::DoesTokenNeedQuotationMarks(const std::string& token) + { + if (token.empty()) + return true; + + const auto hasAlNumCharacter = std::ranges::any_of(token, + [](const char& c) + { + return isalnum(c); + }); + + if (!hasAlNumCharacter) + return false; + + const auto hasNonIdentifierCharacter = std::ranges::any_of(token, + [](const char& c) + { + return !isalnum(c) && c != '_'; + }); + + return hasNonIdentifierCharacter; + } + + void AbstractBaseWriter::WriteEscapedString(const std::string_view& str) const + { + m_stream << "\""; + + for (const auto& c : str) + { + switch (c) + { + case '\r': + m_stream << "\\r"; + break; + case '\n': + m_stream << "\\n"; + break; + case '\t': + m_stream << "\\t"; + break; + case '\f': + m_stream << "\\f"; + break; + case '"': + m_stream << "\\\""; + break; + default: + m_stream << c; + break; + } + } + + m_stream << "\""; + } + + const std::string& AbstractBaseWriter::BoolValue(const bool value) + { + return value ? BOOL_VALUE_TRUE : BOOL_VALUE_FALSE; + } + + void AbstractBaseWriter::WriteKey(const std::string& keyName) const + { + m_stream << keyName; + + if (keyName.size() < MENU_KEY_SPACING) + { + const auto spacingLength = MENU_KEY_SPACING - keyName.size(); + for (auto i = 0u; i < spacingLength; i++) + m_stream << " "; + } + } + + void AbstractBaseWriter::WriteStringProperty(const std::string& propertyKey, const std::string& propertyValue) const + { + if (propertyValue.empty()) + return; + + Indent(); + WriteKey(propertyKey); + + WriteEscapedString(propertyValue); + m_stream << "\n"; + } + + void AbstractBaseWriter::WriteStringProperty(const std::string& propertyKey, const char* propertyValue) const + { + if (propertyValue == nullptr || propertyValue[0] == '\0') + return; + + Indent(); + WriteKey(propertyKey); + + WriteEscapedString(propertyValue); + m_stream << "\n"; + } + + void AbstractBaseWriter::WriteBoolProperty(const std::string& propertyKey, const bool propertyValue, const bool defaultValue) const + { + if (propertyValue == defaultValue) + return; + + Indent(); + WriteKey(propertyKey); + m_stream << BoolValue(propertyValue) << "\n"; + } + + void AbstractBaseWriter::WriteIntProperty(const std::string& propertyKey, const int propertyValue, const int defaultValue) const + { + if (propertyValue == defaultValue) + return; + + Indent(); + WriteKey(propertyKey); + m_stream << propertyValue << "\n"; + } + + void AbstractBaseWriter::WriteFloatProperty(const std::string& propertyKey, const float propertyValue, const float defaultValue) const + { + if (std::fabs(propertyValue - defaultValue) < std::numeric_limits::epsilon()) + return; + + Indent(); + WriteKey(propertyKey); + m_stream << propertyValue << "\n"; + } + + void AbstractBaseWriter::WriteColorProperty(const std::string& propertyKey, const float (&propertyValue)[4], const float (&defaultValue)[4]) const + { + if (std::fabs(propertyValue[0] - defaultValue[0]) < std::numeric_limits::epsilon() + && std::fabs(propertyValue[1] - defaultValue[1]) < std::numeric_limits::epsilon() + && std::fabs(propertyValue[2] - defaultValue[2]) < std::numeric_limits::epsilon() + && std::fabs(propertyValue[3] - defaultValue[3]) < std::numeric_limits::epsilon()) + { + return; + } + + Indent(); + WriteKey(propertyKey); + m_stream << propertyValue[0] << " " << propertyValue[1] << " " << propertyValue[2] << " " << propertyValue[3] << "\n"; + } + + void AbstractBaseWriter::WriteKeywordProperty(const std::string& propertyKey, const bool shouldWrite) const + { + if (!shouldWrite) + return; + + Indent(); + WriteKey(propertyKey); + m_stream << "\n"; + } + + void AbstractBaseWriter::WriteFlagsProperty(const std::string& propertyKey, const int flagsValue) const + { + for (auto i = 0u; i < sizeof(flagsValue) * 8; i++) + { + if (flagsValue & (1 << i)) + { + Indent(); + WriteKey(propertyKey); + m_stream << i << "\n"; + } + } + } + + void AbstractBaseWriter::Start() + { + Indent(); + m_stream << "{\n"; + IncIndent(); + } + + void AbstractBaseWriter::End() + { + for (auto i = 0u; i < m_indent; i++) + { + DecIndent(); + Indent(); + m_stream << "}\n"; + } + } + + void AbstractBaseWriter::IncludeMenu(const std::string& menuPath) const + { + Indent(); + m_stream << "loadMenu { \"" << menuPath << "\" }\n"; + } +} // namespace menu diff --git a/src/ObjWriting/Menu/AbstractMenuWriter.h b/src/ObjWriting/Menu/AbstractMenuWriter.h new file mode 100644 index 00000000..3127a3e8 --- /dev/null +++ b/src/ObjWriting/Menu/AbstractMenuWriter.h @@ -0,0 +1,59 @@ +#pragma once + +#include "IMenuWriter.h" + +#include +#include +#include +#include + +namespace menu +{ + class AbstractBaseWriter : public IWriter + { + protected: + static constexpr auto MENU_KEY_SPACING = 28u; + static const inline std::string BOOL_VALUE_TRUE = "1"; + static const inline std::string BOOL_VALUE_FALSE = "0"; + static constexpr inline float COLOR_0000[4]{0.0f, 0.0f, 0.0f, 0.0f}; + static constexpr inline float COLOR_1111[4]{1.0f, 1.0f, 1.0f, 1.0f}; + + public: + void Start() override; + void End() override; + + void IncludeMenu(const std::string& menuPath) const override; + + protected: + explicit AbstractBaseWriter(std::ostream& stream); + + void IncIndent(); + void DecIndent(); + void Indent() const; + + void StartScope(const std::string& scopeName); + void StartMenuDefScope(); + void StartItemDefScope(); + void StartFunctionDefScope(); + void EndScope(); + + static std::vector CreateScriptTokenList(const char* script); + static bool DoesTokenNeedQuotationMarks(const std::string& token); + + void WriteEscapedString(const std::string_view& str) const; + + static const std::string& BoolValue(bool value); + void WriteKey(const std::string& keyName) const; + void WriteStringProperty(const std::string& propertyKey, const std::string& propertyValue) const; + void WriteStringProperty(const std::string& propertyKey, const char* propertyValue) const; + void WriteBoolProperty(const std::string& propertyKey, bool propertyValue, bool defaultValue) const; + void WriteIntProperty(const std::string& propertyKey, int propertyValue, int defaultValue) const; + void WriteFloatProperty(const std::string& propertyKey, float propertyValue, float defaultValue) const; + void WriteColorProperty(const std::string& propertyKey, const float (&propertyValue)[4], const float (&defaultValue)[4]) const; + void WriteKeywordProperty(const std::string& propertyKey, bool shouldWrite) const; + void WriteFlagsProperty(const std::string& propertyKey, int flagsValue) const; + + std::ostream& m_stream; + size_t m_indent; + }; +} // namespace menu diff --git a/src/ObjWriting/Menu/IMenuWriter.h b/src/ObjWriting/Menu/IMenuWriter.h new file mode 100644 index 00000000..393fc33f --- /dev/null +++ b/src/ObjWriting/Menu/IMenuWriter.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +namespace menu +{ + class IWriter + { + public: + IWriter() = default; + virtual ~IWriter() = default; + + virtual void Start() = 0; + virtual void End() = 0; + + virtual void IncludeMenu(const std::string& menuPath) const = 0; + }; +} // namespace menu diff --git a/src/ObjWriting/Dumping/SndCurve/SndCurveDumper.cpp b/src/ObjWriting/Sound/SndCurveDumper.cpp similarity index 100% rename from src/ObjWriting/Dumping/SndCurve/SndCurveDumper.cpp rename to src/ObjWriting/Sound/SndCurveDumper.cpp diff --git a/src/ObjWriting/Dumping/SndCurve/SndCurveDumper.h b/src/ObjWriting/Sound/SndCurveDumper.h similarity index 100% rename from src/ObjWriting/Dumping/SndCurve/SndCurveDumper.h rename to src/ObjWriting/Sound/SndCurveDumper.h diff --git a/src/ObjWriting/XModel/XModelDumper.cpp.template b/src/ObjWriting/XModel/XModelDumper.cpp.template index 812e4c31..85dce85b 100644 --- a/src/ObjWriting/XModel/XModelDumper.cpp.template +++ b/src/ObjWriting/XModel/XModelDumper.cpp.template @@ -48,6 +48,8 @@ using namespace GAME; +#set CLASS_NAME "Dumper" + GAME + namespace { std::string GetFileNameForLod(const std::string& modelName, const unsigned lod, const std::string& extension) @@ -830,7 +832,7 @@ namespace void DumpXModelJson(AssetDumpingContext& context, XAssetInfo* asset) { - const auto assetFile = context.OpenAssetFile(std::format("xmodel/{}.json", asset->m_name)); + const auto assetFile = context.OpenAssetFile(xmodel::GetJsonFileNameForAssetName(asset->m_name)); if (!assetFile) return; @@ -839,11 +841,16 @@ namespace } } // namespace -namespace GAME +namespace xmodel { - void DumpXModel(AssetDumpingContext& context, XAssetInfo* asset) + bool CLASS_NAME::ShouldDump(XAssetInfo* asset) + { + return !asset->m_name.empty() && asset->m_name[0] != ','; + } + + void CLASS_NAME::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) { DumpXModelJson(context, asset); DumpXModelSurfs(context, asset); } -} // namespace GAME +} diff --git a/src/ObjWriting/XModel/XModelDumper.h.template b/src/ObjWriting/XModel/XModelDumper.h.template index 5c4cecb2..5483e209 100644 --- a/src/ObjWriting/XModel/XModelDumper.h.template +++ b/src/ObjWriting/XModel/XModelDumper.h.template @@ -10,10 +10,17 @@ #pragma once -#include "Dumping/AssetDumpingContext.h" +#include "Dumping/AbstractAssetDumper.h" #include GAME_HEADER -namespace GAME +#set CLASS_NAME "Dumper" + GAME + +namespace xmodel { - void DumpXModel(AssetDumpingContext& context, XAssetInfo* asset); -} + class CLASS_NAME final : public AbstractAssetDumper + { + protected: + bool ShouldDump(XAssetInfo* asset) override; + void DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) override; + }; +} // namespace xmodel diff --git a/test/ObjCompilingTests/Game/T6/KeyValuePairs/KeyValuePairsCompilerT6Test.cpp b/test/ObjCompilingTests/Game/T6/KeyValuePairs/KeyValuePairsCompilerT6Test.cpp index b25715b9..3a94a2df 100644 --- a/test/ObjCompilingTests/Game/T6/KeyValuePairs/KeyValuePairsCompilerT6Test.cpp +++ b/test/ObjCompilingTests/Game/T6/KeyValuePairs/KeyValuePairsCompilerT6Test.cpp @@ -26,13 +26,13 @@ namespace m_creators(m_zone), m_ignored_assets(), m_context(m_zone, &m_creators, &m_ignored_assets), - m_kvp_creator(m_zone_states.GetZoneAssetCreationState()) + m_kvp_creator(m_zone_states.GetZoneAssetCreationState()) { } std::unique_ptr CreateSut() { - return CreateKeyValuePairsCompiler(m_memory, m_zone, m_zone_definition, m_zone_states); + return key_value_pairs::CreateCompilerT6(m_memory, m_zone, m_zone_definition, m_zone_states); } TestMemoryManager m_memory; @@ -43,7 +43,7 @@ namespace IgnoredAssetLookup m_ignored_assets; AssetCreationContext m_context; - KeyValuePairsCreator& m_kvp_creator; + key_value_pairs::Creator& m_kvp_creator; }; } // namespace @@ -81,7 +81,7 @@ namespace test::game::t6::keyvaluepairs TestContext testContext; const auto sut = testContext.CreateSut(); - testContext.m_kvp_creator.AddKeyValuePair(CommonKeyValuePair("ipak_read", "test_ipak")); + testContext.m_kvp_creator.AddKeyValuePair(key_value_pairs::CommonKeyValuePair("ipak_read", "test_ipak")); sut->FinalizeZone(testContext.m_context); @@ -107,7 +107,7 @@ namespace test::game::t6::keyvaluepairs TestContext testContext; const auto sut = testContext.CreateSut(); - testContext.m_kvp_creator.AddKeyValuePair(CommonKeyValuePair(0xDDEEFFAA, "hello_there")); + testContext.m_kvp_creator.AddKeyValuePair(key_value_pairs::CommonKeyValuePair(0xDDEEFFAA, "hello_there")); sut->FinalizeZone(testContext.m_context); diff --git a/test/ObjCompilingTests/Image/IPak/IPakCreatorTest.cpp b/test/ObjCompilingTests/Image/IPak/IPakCreatorTest.cpp index bd49745f..4b4fcd9f 100644 --- a/test/ObjCompilingTests/Image/IPak/IPakCreatorTest.cpp +++ b/test/ObjCompilingTests/Image/IPak/IPakCreatorTest.cpp @@ -26,9 +26,9 @@ namespace { } - IPakCreator& CreateSut() + image::IPakCreator& CreateSut() { - return m_zone_states.GetZoneAssetCreationState(); + return m_zone_states.GetZoneAssetCreationState(); } Zone m_zone; diff --git a/test/ObjCompilingTests/Image/ImageIPakPostProcessorTest.cpp b/test/ObjCompilingTests/Image/ImageIPakPostProcessorTest.cpp index 29dd627f..3955146d 100644 --- a/test/ObjCompilingTests/Image/ImageIPakPostProcessorTest.cpp +++ b/test/ObjCompilingTests/Image/ImageIPakPostProcessorTest.cpp @@ -28,13 +28,13 @@ namespace m_ignored_assets(), m_out_dir(), m_context(m_zone, &m_creators, &m_ignored_assets), - m_ipak_creator(m_zone_states.GetZoneAssetCreationState()) + m_ipak_creator(m_zone_states.GetZoneAssetCreationState()) { } std::unique_ptr CreateSut() { - return std::make_unique>(m_zone_definition_context, m_search_path, m_zone_states, m_out_dir); + return std::make_unique>(m_zone_definition_context, m_search_path, m_zone_states, m_out_dir); } Zone m_zone; @@ -47,7 +47,7 @@ namespace MockOutputPath m_out_dir; AssetCreationContext m_context; - IPakCreator& m_ipak_creator; + image::IPakCreator& m_ipak_creator; }; } // namespace diff --git a/test/ObjCompilingTests/Image/ImageIwdPostProcessorTest.cpp b/test/ObjCompilingTests/Image/ImageIwdPostProcessorTest.cpp index 8e971524..a357e550 100644 --- a/test/ObjCompilingTests/Image/ImageIwdPostProcessorTest.cpp +++ b/test/ObjCompilingTests/Image/ImageIwdPostProcessorTest.cpp @@ -33,7 +33,7 @@ namespace std::unique_ptr CreateSut() { - return std::make_unique>(m_zone_definition_context, m_search_path, m_zone_states, m_out_dir); + return std::make_unique>(m_zone_definition_context, m_search_path, m_zone_states, m_out_dir); } Zone m_zone; diff --git a/test/ObjCompilingTests/KeyValuePairs/KeyValuePairsCreatorTest.cpp b/test/ObjCompilingTests/KeyValuePairs/KeyValuePairsCreatorTest.cpp index 48bffd61..42c21fb1 100644 --- a/test/ObjCompilingTests/KeyValuePairs/KeyValuePairsCreatorTest.cpp +++ b/test/ObjCompilingTests/KeyValuePairs/KeyValuePairsCreatorTest.cpp @@ -13,7 +13,7 @@ namespace test::keyvaluepairs { TEST_CASE("KeyValuePairsCreator: ZoneDefinition with no properties produces no KeyValuePairs", "[keyvaluepairs]") { - KeyValuePairsCreator sut; + key_value_pairs::Creator sut; ZoneDefinition zoneDefinition; sut.Finalize(zoneDefinition); @@ -25,7 +25,7 @@ namespace test::keyvaluepairs TEST_CASE("KeyValuePairsCreator: ZoneDefinition with unrelated properties produce no KeyValuePairs", "[keyvaluepairs]") { - KeyValuePairsCreator sut; + key_value_pairs::Creator sut; ZoneDefinition zoneDefinition; zoneDefinition.m_properties.AddProperty("linker.test", "yes"); @@ -38,7 +38,7 @@ namespace test::keyvaluepairs TEST_CASE("KeyValuePairsCreator: ZoneDefinition with level properties produce KeyValuePairs", "[keyvaluepairs]") { - KeyValuePairsCreator sut; + key_value_pairs::Creator sut; ZoneDefinition zoneDefinition; zoneDefinition.m_properties.AddProperty("linker.test", "yes"); @@ -56,7 +56,7 @@ namespace test::keyvaluepairs TEST_CASE("KeyValuePairsCreator: ZoneDefinition can have level properties with hash", "[keyvaluepairs]") { - KeyValuePairsCreator sut; + key_value_pairs::Creator sut; ZoneDefinition zoneDefinition; zoneDefinition.m_properties.AddProperty("level.@D34DB33F", "yes"); @@ -77,7 +77,7 @@ namespace test::keyvaluepairs TEST_CASE("KeyValuePairsCreator: ZoneDefinition can have level properties with name and/or hash", "[keyvaluepairs]") { - KeyValuePairsCreator sut; + key_value_pairs::Creator sut; ZoneDefinition zoneDefinition; zoneDefinition.m_properties.AddProperty("level.ipak_read", "asdf"); diff --git a/test/ObjLoadingTests/Game/IW3/Material/LoaderMaterialIW3Test.cpp b/test/ObjLoadingTests/Game/IW3/Material/LoaderMaterialIW3Test.cpp index 1a469c62..7f36ca46 100644 --- a/test/ObjLoadingTests/Game/IW3/Material/LoaderMaterialIW3Test.cpp +++ b/test/ObjLoadingTests/Game/IW3/Material/LoaderMaterialIW3Test.cpp @@ -286,7 +286,7 @@ namespace GivenImage("ch_plasterwall_long_col", context, memory); GivenTechset("wc_l_sm_r0c0n0s0", context, memory); - auto loader = CreateMaterialLoader(memory, searchPath); + auto loader = material::CreateLoaderIW3(memory, searchPath); auto result = loader->CreateAsset("wc/ch_plasterwall_long", context); REQUIRE(result.HasBeenSuccessful()); diff --git a/test/ObjLoadingTests/Game/IW3/StringTable/AssetLoaderStringTableIW3Test.cpp b/test/ObjLoadingTests/Game/IW3/StringTable/AssetLoaderStringTableIW3Test.cpp index 36ee0347..84894dd3 100644 --- a/test/ObjLoadingTests/Game/IW3/StringTable/AssetLoaderStringTableIW3Test.cpp +++ b/test/ObjLoadingTests/Game/IW3/StringTable/AssetLoaderStringTableIW3Test.cpp @@ -27,7 +27,7 @@ namespace IgnoredAssetLookup ignoredAssetLookup; AssetCreationContext context(zone, &creatorCollection, &ignoredAssetLookup); - auto loader = CreateStringTableLoader(memory, searchPath); + auto loader = string_table::CreateLoaderIW3(memory, searchPath); auto result = loader->CreateAsset("mp/cooltable.csv", context); REQUIRE(result.HasBeenSuccessful()); diff --git a/test/ObjLoadingTests/Game/IW4/AssetLoaders/LoaderStringTableIW4Test.cpp b/test/ObjLoadingTests/Game/IW4/AssetLoaders/LoaderStringTableIW4Test.cpp index 88fbe000..d311f141 100644 --- a/test/ObjLoadingTests/Game/IW4/AssetLoaders/LoaderStringTableIW4Test.cpp +++ b/test/ObjLoadingTests/Game/IW4/AssetLoaders/LoaderStringTableIW4Test.cpp @@ -27,7 +27,7 @@ namespace IgnoredAssetLookup ignoredAssetLookup; AssetCreationContext context(zone, &creatorCollection, &ignoredAssetLookup); - auto loader = CreateStringTableLoader(memory, searchPath); + auto loader = string_table::CreateLoaderIW4(memory, searchPath); auto result = loader->CreateAsset("mp/cooltable.csv", context); REQUIRE(result.HasBeenSuccessful()); diff --git a/test/ObjLoadingTests/Game/IW4/Material/LoaderMaterialIW4Test.cpp b/test/ObjLoadingTests/Game/IW4/Material/LoaderMaterialIW4Test.cpp index 0860550b..bde4133c 100644 --- a/test/ObjLoadingTests/Game/IW4/Material/LoaderMaterialIW4Test.cpp +++ b/test/ObjLoadingTests/Game/IW4/Material/LoaderMaterialIW4Test.cpp @@ -289,7 +289,7 @@ namespace GivenImage("ch_rubble01_col", context, memory); GivenTechset("mc_l_sm_r0c0n0s0", context, memory); - auto loader = CreateMaterialLoader(memory, searchPath); + auto loader = material::CreateLoaderIW4(memory, searchPath); auto result = loader->CreateAsset("mc/ch_rubble01", context); REQUIRE(result.HasBeenSuccessful()); diff --git a/test/ObjLoadingTests/Game/IW4/Menu/LoaderMenuListIW4Test.cpp b/test/ObjLoadingTests/Game/IW4/Menu/LoaderMenuListIW4Test.cpp index 69021fe5..f55bf421 100644 --- a/test/ObjLoadingTests/Game/IW4/Menu/LoaderMenuListIW4Test.cpp +++ b/test/ObjLoadingTests/Game/IW4/Menu/LoaderMenuListIW4Test.cpp @@ -11,7 +11,6 @@ #include #include -using namespace menu; using namespace IW4; using namespace std::literals; using namespace Catch::Matchers; @@ -36,7 +35,7 @@ namespace test::game::iw4::menu::parsing::it m_ignored_asset_lookup(), m_context(m_zone, &m_creator_collection, &m_ignored_asset_lookup) { - m_asset_creator = CreateMenuListLoader(m_zone.Memory(), m_search_path); + m_asset_creator = ::menu::CreateMenuListLoaderIW4(m_zone.Memory(), m_search_path); } void AddFile(std::string fileName, std::string data) diff --git a/test/ObjLoadingTests/Game/IW5/AssetLoaders/LoaderStringTableIW5Test.cpp b/test/ObjLoadingTests/Game/IW5/AssetLoaders/LoaderStringTableIW5Test.cpp index ab5ac734..32546c9c 100644 --- a/test/ObjLoadingTests/Game/IW5/AssetLoaders/LoaderStringTableIW5Test.cpp +++ b/test/ObjLoadingTests/Game/IW5/AssetLoaders/LoaderStringTableIW5Test.cpp @@ -26,7 +26,7 @@ namespace IgnoredAssetLookup ignoredAssetLookup; AssetCreationContext context(zone, &creatorCollection, &ignoredAssetLookup); - auto loader = CreateStringTableLoader(memory, searchPath); + auto loader = string_table::CreateLoaderIW5(memory, searchPath); auto result = loader->CreateAsset("mp/cooltable.csv", context); REQUIRE(result.HasBeenSuccessful()); diff --git a/test/ObjLoadingTests/Game/IW5/Material/LoaderMaterialIW5Test.cpp b/test/ObjLoadingTests/Game/IW5/Material/LoaderMaterialIW5Test.cpp index 5de6912b..de7b30c1 100644 --- a/test/ObjLoadingTests/Game/IW5/Material/LoaderMaterialIW5Test.cpp +++ b/test/ObjLoadingTests/Game/IW5/Material/LoaderMaterialIW5Test.cpp @@ -313,7 +313,7 @@ namespace GivenImage("me_metal_rusty02_col", context, memory); GivenTechset("wc_l_sm_r0c0n0s0", context, memory); - auto loader = CreateMaterialLoader(memory, searchPath); + auto loader = material::CreateLoaderIW5(memory, searchPath); auto result = loader->CreateAsset("wc/me_metal_rust_02", context); REQUIRE(result.HasBeenSuccessful()); diff --git a/test/ObjLoadingTests/Game/T5/AssetLoaders/LoaderStringTableT5Test.cpp b/test/ObjLoadingTests/Game/T5/AssetLoaders/LoaderStringTableT5Test.cpp index 8dca092f..43e9c481 100644 --- a/test/ObjLoadingTests/Game/T5/AssetLoaders/LoaderStringTableT5Test.cpp +++ b/test/ObjLoadingTests/Game/T5/AssetLoaders/LoaderStringTableT5Test.cpp @@ -26,7 +26,7 @@ namespace IgnoredAssetLookup ignoredAssetLookup; AssetCreationContext context(zone, &creatorCollection, &ignoredAssetLookup); - auto loader = CreateStringTableLoader(memory, searchPath); + auto loader = string_table::CreateLoaderT5(memory, searchPath); auto result = loader->CreateAsset("mp/cooltable.csv", context); REQUIRE(result.HasBeenSuccessful()); diff --git a/test/ObjLoadingTests/Game/T5/Material/LoaderMaterialT5Test.cpp b/test/ObjLoadingTests/Game/T5/Material/LoaderMaterialT5Test.cpp index 90f8283d..9e183566 100644 --- a/test/ObjLoadingTests/Game/T5/Material/LoaderMaterialT5Test.cpp +++ b/test/ObjLoadingTests/Game/T5/Material/LoaderMaterialT5Test.cpp @@ -370,7 +370,7 @@ namespace GivenImage("~-gjun_art_brick_foundation_c", context, memory); GivenTechset("mc_l_sm_r0c0n0s0", context, memory); - auto loader = CreateMaterialLoader(memory, searchPath); + auto loader = material::CreateLoaderT5(memory, searchPath); auto result = loader->CreateAsset("mc/jun_art_brick_foundation", context); REQUIRE(result.HasBeenSuccessful()); diff --git a/test/ObjLoadingTests/Game/T6/AssetLoaders/LoaderStringTableT6Test.cpp b/test/ObjLoadingTests/Game/T6/AssetLoaders/LoaderStringTableT6Test.cpp index 87004412..2e075e9f 100644 --- a/test/ObjLoadingTests/Game/T6/AssetLoaders/LoaderStringTableT6Test.cpp +++ b/test/ObjLoadingTests/Game/T6/AssetLoaders/LoaderStringTableT6Test.cpp @@ -26,7 +26,7 @@ namespace IgnoredAssetLookup ignoredAssetLookup; AssetCreationContext context(zone, &creatorCollection, &ignoredAssetLookup); - auto loader = CreateStringTableLoader(memory, searchPath); + auto loader = string_table::CreateLoaderT6(memory, searchPath); auto result = loader->CreateAsset("mp/cooltable.csv", context); REQUIRE(result.HasBeenSuccessful()); diff --git a/test/ObjLoadingTests/Game/T6/FontIcon/JsonLoaderFontIconT6Test.cpp b/test/ObjLoadingTests/Game/T6/FontIcon/JsonLoaderFontIconT6Test.cpp index f99d761f..a92851d6 100644 --- a/test/ObjLoadingTests/Game/T6/FontIcon/JsonLoaderFontIconT6Test.cpp +++ b/test/ObjLoadingTests/Game/T6/FontIcon/JsonLoaderFontIconT6Test.cpp @@ -90,7 +90,7 @@ namespace GivenMaterial("ui_button_xenon_lstick_anim_d", context, memory); GivenMaterial("xenonbutton_ls", context, memory); - auto loader = CreateJsonFontIconLoader(memory, searchPath); + auto loader = font_icon::CreateJsonLoaderT6(memory, searchPath); auto result = loader->CreateAsset("fonticon/test.csv", context); REQUIRE(result.HasBeenSuccessful()); diff --git a/test/ObjLoadingTests/Game/T6/Material/LoaderMaterialT6Test.cpp b/test/ObjLoadingTests/Game/T6/Material/LoaderMaterialT6Test.cpp index 454054a6..94ee5b62 100644 --- a/test/ObjLoadingTests/Game/T6/Material/LoaderMaterialT6Test.cpp +++ b/test/ObjLoadingTests/Game/T6/Material/LoaderMaterialT6Test.cpp @@ -253,7 +253,7 @@ namespace GivenImage("~-gmetal_ac_duct_c", context, memory); GivenTechset("wpc_lit_sm_r0c0n0s0_1zzj1138", context, memory); - auto loader = CreateMaterialLoader(memory, searchPath); + auto loader = material::CreateLoaderT6(memory, searchPath); auto result = loader->CreateAsset("wpc/metal_ac_duct", context); REQUIRE(result.HasBeenSuccessful()); diff --git a/test/ObjWritingTests.lua b/test/ObjWritingTests.lua index 8afcba6c..cda98707 100644 --- a/test/ObjWritingTests.lua +++ b/test/ObjWritingTests.lua @@ -3,6 +3,7 @@ ObjWritingTests = {} function ObjWritingTests:include(includes) if includes:handle(self:name()) then includedirs { + "%{wks.location}/src/ObjWriting", path.join(TestFolder(), "ObjWritingTests") } end diff --git a/test/ObjWritingTests/Game/IW3/Material/DumperMaterialIW3Test.cpp b/test/ObjWritingTests/Game/IW3/Material/MaterialJsonDumperIW3Test.cpp similarity index 99% rename from test/ObjWritingTests/Game/IW3/Material/DumperMaterialIW3Test.cpp rename to test/ObjWritingTests/Game/IW3/Material/MaterialJsonDumperIW3Test.cpp index 077cbe13..44980cdc 100644 --- a/test/ObjWritingTests/Game/IW3/Material/DumperMaterialIW3Test.cpp +++ b/test/ObjWritingTests/Game/IW3/Material/MaterialJsonDumperIW3Test.cpp @@ -1,4 +1,4 @@ -#include "Game/IW3/Material/DumperMaterialIW3.h" +#include "Game/IW3/Material/MaterialJsonDumperIW3.h" #include "Asset/AssetRegistration.h" #include "Game/IW3/CommonIW3.h" @@ -562,7 +562,7 @@ namespace GivenMaterial("wc/ch_plasterwall_long", materialPool, memory); - AssetDumperMaterial dumper; + material::JsonDumperIW3 dumper; dumper.DumpPool(context, &materialPool); const auto* file = mockOutput.GetMockedFile("materials/wc/ch_plasterwall_long.json"); diff --git a/test/ObjWritingTests/Game/IW4/Material/DumperMaterialIW4Test.cpp b/test/ObjWritingTests/Game/IW4/Material/MaterialJsonDumperIW4Test.cpp similarity index 99% rename from test/ObjWritingTests/Game/IW4/Material/DumperMaterialIW4Test.cpp rename to test/ObjWritingTests/Game/IW4/Material/MaterialJsonDumperIW4Test.cpp index 39b264a7..c16ec19d 100644 --- a/test/ObjWritingTests/Game/IW4/Material/DumperMaterialIW4Test.cpp +++ b/test/ObjWritingTests/Game/IW4/Material/MaterialJsonDumperIW4Test.cpp @@ -1,4 +1,4 @@ -#include "Game/IW4/Material/DumperMaterialIW4.h" +#include "Game/IW4/Material/MaterialJsonDumperIW4.h" #include "Asset/AssetRegistration.h" #include "Game/IW4/CommonIW4.h" @@ -543,7 +543,7 @@ namespace GivenMaterial("mc/ch_rubble01", materialPool, memory); - AssetDumperMaterial dumper; + material::JsonDumperIW4 dumper; dumper.DumpPool(context, &materialPool); const auto* file = mockOutput.GetMockedFile("materials/mc/ch_rubble01.json"); diff --git a/test/ObjWritingTests/Game/IW5/Material/DumperMaterialIW5Test.cpp b/test/ObjWritingTests/Game/IW5/Material/MaterialJsonDumperIW5Test.cpp similarity index 99% rename from test/ObjWritingTests/Game/IW5/Material/DumperMaterialIW5Test.cpp rename to test/ObjWritingTests/Game/IW5/Material/MaterialJsonDumperIW5Test.cpp index f8c15582..f70a9daf 100644 --- a/test/ObjWritingTests/Game/IW5/Material/DumperMaterialIW5Test.cpp +++ b/test/ObjWritingTests/Game/IW5/Material/MaterialJsonDumperIW5Test.cpp @@ -1,4 +1,4 @@ -#include "Game/IW5/Material/DumperMaterialIW5.h" +#include "Game/IW5/Material/MaterialJsonDumperIW5.h" #include "Asset/AssetRegistration.h" #include "Game/IW5/CommonIW5.h" @@ -596,7 +596,7 @@ namespace GivenMaterial("wc/me_metal_rust_02", materialPool, memory); - AssetDumperMaterial dumper; + material::JsonDumperIW5 dumper; dumper.DumpPool(context, &materialPool); const auto* file = mockOutput.GetMockedFile("materials/wc/me_metal_rust_02.json"); diff --git a/test/ObjWritingTests/Game/T5/Material/DumperMaterialT5Test.cpp b/test/ObjWritingTests/Game/T5/Material/MaterialJsonDumperT5Test.cpp similarity index 99% rename from test/ObjWritingTests/Game/T5/Material/DumperMaterialT5Test.cpp rename to test/ObjWritingTests/Game/T5/Material/MaterialJsonDumperT5Test.cpp index 4cc56013..5513c96f 100644 --- a/test/ObjWritingTests/Game/T5/Material/DumperMaterialT5Test.cpp +++ b/test/ObjWritingTests/Game/T5/Material/MaterialJsonDumperT5Test.cpp @@ -1,4 +1,4 @@ -#include "Game/T5/Material/DumperMaterialT5.h" +#include "Game/T5/Material/MaterialJsonDumperT5.h" #include "Asset/AssetRegistration.h" #include "Game/T5/CommonT5.h" @@ -625,7 +625,7 @@ namespace GivenMaterial("mc/ch_rubble01", materialPool, memory); - AssetDumperMaterial dumper; + material::JsonDumperT5 dumper; dumper.DumpPool(context, &materialPool); const auto* file = mockOutput.GetMockedFile("materials/mc/ch_rubble01.json"); diff --git a/test/ObjWritingTests/Game/T6/FontIcon/DumperFontIconJsonT6Test.cpp b/test/ObjWritingTests/Game/T6/FontIcon/FontIconJsonDumperT6Test.cpp similarity index 77% rename from test/ObjWritingTests/Game/T6/FontIcon/DumperFontIconJsonT6Test.cpp rename to test/ObjWritingTests/Game/T6/FontIcon/FontIconJsonDumperT6Test.cpp index c8837e7b..1755ff9d 100644 --- a/test/ObjWritingTests/Game/T6/FontIcon/DumperFontIconJsonT6Test.cpp +++ b/test/ObjWritingTests/Game/T6/FontIcon/FontIconJsonDumperT6Test.cpp @@ -1,4 +1,4 @@ -#include "Game/T6/FontIcon/DumperFontIconJsonT6.h" +#include "Game/T6/FontIcon/FontIconJsonDumperT6.h" #include "Asset/AssetRegistration.h" #include "Game/T6/CommonT6.h" @@ -27,14 +27,15 @@ namespace return material; } - void GivenFontIcon(const std::string& name, FontIcon& fontIcon, MemoryManager& memory) + void GivenFontIcon(const std::string& name, AssetPool& pool, MemoryManager& memory) { - fontIcon.name = memory.Dup(name.c_str()); + auto* fontIcon = memory.Alloc(); + fontIcon->name = memory.Dup(name.c_str()); - fontIcon.numEntries = 3; - fontIcon.fontIconEntry = memory.Alloc(fontIcon.numEntries); + fontIcon->numEntries = 3; + fontIcon->fontIconEntry = memory.Alloc(fontIcon->numEntries); - auto& entry0 = fontIcon.fontIconEntry[0]; + auto& entry0 = fontIcon->fontIconEntry[0]; entry0.fontIconName.string = "XenonButtondpadAll"; entry0.fontIconName.hash = Common::Com_HashString(entry0.fontIconName.string); entry0.fontIconMaterialHandle = GivenMaterial("xenonbutton_dpad_all", memory); @@ -42,7 +43,7 @@ namespace entry0.xScale = 1.0f; entry0.yScale = 1.0f; - auto& entry1 = fontIcon.fontIconEntry[1]; + auto& entry1 = fontIcon->fontIconEntry[1]; entry1.fontIconName.string = "XenonButtonLStickAnimatedD"; entry1.fontIconName.hash = Common::Com_HashString(entry1.fontIconName.string); entry1.fontIconMaterialHandle = GivenMaterial("ui_button_xenon_lstick_anim_d", memory); @@ -50,7 +51,7 @@ namespace entry1.xScale = 1.5f; entry1.yScale = 1.5f; - auto& entry2 = fontIcon.fontIconEntry[2]; + auto& entry2 = fontIcon->fontIconEntry[2]; entry2.fontIconName.string = "XenonButtonStickAnimatedL"; entry2.fontIconName.hash = Common::Com_HashString(entry2.fontIconName.string); entry2.fontIconMaterialHandle = GivenMaterial("xenonbutton_ls", memory); @@ -58,32 +59,34 @@ namespace entry2.xScale = 1.0f; entry2.yScale = 1.0f; - fontIcon.numAliasEntries = 6; - fontIcon.fontIconAlias = memory.Alloc(fontIcon.numAliasEntries); + fontIcon->numAliasEntries = 6; + fontIcon->fontIconAlias = memory.Alloc(fontIcon->numAliasEntries); - auto& alias0 = fontIcon.fontIconAlias[0]; + auto& alias0 = fontIcon->fontIconAlias[0]; alias0.aliasHash = Common::Com_HashString("BUTTON_LUI_DPAD_ALL"); alias0.buttonHash = entry0.fontIconName.hash; - auto& alias1 = fontIcon.fontIconAlias[1]; + auto& alias1 = fontIcon->fontIconAlias[1]; alias1.aliasHash = static_cast(0xCE7211DA); alias1.buttonHash = entry1.fontIconName.hash; - auto& alias2 = fontIcon.fontIconAlias[2]; + auto& alias2 = fontIcon->fontIconAlias[2]; alias2.aliasHash = Common::Com_HashString("BUTTON_MOVE"); alias2.buttonHash = entry2.fontIconName.hash; - auto& alias3 = fontIcon.fontIconAlias[3]; + auto& alias3 = fontIcon->fontIconAlias[3]; alias3.aliasHash = Common::Com_HashString("BUTTON_EMBLEM_MOVE"); alias3.buttonHash = entry2.fontIconName.hash; - auto& alias4 = fontIcon.fontIconAlias[4]; + auto& alias4 = fontIcon->fontIconAlias[4]; alias4.aliasHash = Common::Com_HashString("BUTTON_LUI_LEFT_STICK_UP"); alias4.buttonHash = entry2.fontIconName.hash; - auto& alias5 = fontIcon.fontIconAlias[5]; + auto& alias5 = fontIcon->fontIconAlias[5]; alias5.aliasHash = Common::Com_HashString("BUTTON_MOVESTICK"); alias5.buttonHash = entry2.fontIconName.hash; + + pool.AddAsset(std::make_unique>(ASSET_TYPE_FONTICON, name, fontIcon)); } TEST_CASE("DumperFontIconJson(T6): Can dump font icon", "[t6][font-icon][assetdumper]") @@ -145,12 +148,11 @@ namespace MockOutputPath mockOutput; AssetDumpingContext context(zone, "", mockOutput, mockObjPath); - AssetPoolDynamic materialPool(0); + AssetPoolDynamic fontIconPool(0); + GivenFontIcon("fonticon/test.csv", fontIconPool, memory); - FontIcon asset; - GivenFontIcon("fonticon/test.csv", asset, memory); - - DumpFontIconAsJson(context, asset); + font_icon::JsonDumperT6 dumper; + dumper.DumpPool(context, &fontIconPool); const auto* file = mockOutput.GetMockedFile("fonticon/test.json"); REQUIRE(file); diff --git a/test/ObjWritingTests/Game/T6/Material/DumperMaterialT6Test.cpp b/test/ObjWritingTests/Game/T6/Material/MaterialJsonDumperT6Test.cpp similarity index 99% rename from test/ObjWritingTests/Game/T6/Material/DumperMaterialT6Test.cpp rename to test/ObjWritingTests/Game/T6/Material/MaterialJsonDumperT6Test.cpp index 30c83ec1..c75d73be 100644 --- a/test/ObjWritingTests/Game/T6/Material/DumperMaterialT6Test.cpp +++ b/test/ObjWritingTests/Game/T6/Material/MaterialJsonDumperT6Test.cpp @@ -1,4 +1,4 @@ -#include "Game/T6/Material/DumperMaterialT6.h" +#include "Game/T6/Material/MaterialJsonDumperT6.h" #include "Asset/AssetRegistration.h" #include "Game/T6/CommonT6.h" @@ -470,10 +470,9 @@ namespace AssetDumpingContext context(zone, "", mockOutput, mockObjPath); AssetPoolDynamic materialPool(0); - GivenMaterial("wpc/metal_ac_duct", materialPool, memory); - AssetDumperMaterial dumper; + material::JsonDumperT6 dumper; dumper.DumpPool(context, &materialPool); const auto* file = mockOutput.GetMockedFile("materials/wpc/metal_ac_duct.json");