diff --git a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp index c3b7f438..29592f6a 100644 --- a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp @@ -146,6 +146,8 @@ namespace LINEF("#include \"{0}_load_db.h\"", Lower(m_env.m_asset->m_definition->m_name)) LINE("") LINEF("#include \"{0}_mark_db.h\"", Lower(m_env.m_asset->m_definition->m_name)) + LINE("") + LINE("#include \"Loading/AssetInfoCollector.h\"") if (!m_env.m_referenced_assets.empty()) { @@ -2155,14 +2157,16 @@ namespace LINE("assert(pAsset != nullptr);") LINE("") - LINEF("{0} marker(m_zone);", MarkerClassName(m_env.m_asset)) + LINE("AssetInfoCollector assetInfo(m_zone);") + LINEF("{0} marker(assetInfo);", MarkerClassName(m_env.m_asset)) LINE("marker.Mark(*pAsset);") LINE("") LINEF("auto* reallocatedAsset = m_zone.Memory().Alloc<{0}>();", info->m_definition->GetFullName()) LINEF("std::memcpy(reallocatedAsset, *pAsset, sizeof({0}));", info->m_definition->GetFullName()) LINE("") - LINEF("m_asset_info = reinterpret_cast*>(LinkAsset(AssetNameAccessor<{1}>()(**pAsset), reallocatedAsset, marker.GetDependencies(), " - "marker.GetUsedScriptStrings(), marker.GetIndirectAssetReferences()));", + LINEF("m_asset_info = reinterpret_cast*>(LinkAsset(AssetNameAccessor<{1}>()(**pAsset), reallocatedAsset, " + "assetInfo.GetDependencies(), " + "assetInfo.GetUsedScriptStrings(), assetInfo.GetIndirectAssetReferences()));", info->m_definition->GetFullName(), info->m_asset_name) LINE("*pAsset = m_asset_info->Asset();") diff --git a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneMarkTemplate.cpp b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneMarkTemplate.cpp index c6a45bc2..c7696689 100644 --- a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneMarkTemplate.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneMarkTemplate.cpp @@ -33,6 +33,7 @@ namespace LINE("") LINEF("#include \"Game/{0}/{0}.h\"", m_env.m_game) LINE("#include \"Marking/AssetMarker.h\"") + LINE("#include \"Marking/AssetVisitor.h\"") LINE("") LINE("#include ") LINE("") @@ -48,7 +49,6 @@ namespace m_intendation++; PrintHeaderConstructor(); PrintHeaderMainMarkMethodDeclaration(m_env.m_asset); - PrintHeaderGetAssetInfoMethodDeclaration(m_env.m_asset); LINE("") m_intendation--; @@ -136,8 +136,6 @@ namespace PrintConstructorMethod(); LINE("") PrintMainMarkMethod(); - LINE("") - PrintGetAssetInfoMethod(); for (const auto* type : m_env.m_used_types) { @@ -210,14 +208,9 @@ namespace LINEF("void Mark_{0}();", MakeSafeTypeName(info->m_definition)) } - void PrintHeaderGetAssetInfoMethodDeclaration(const StructureInformation* info) const - { - LINEF("XAssetInfo<{0}>* GetAssetInfo({0}* pAsset) const;", info->m_definition->GetFullName()) - } - void PrintHeaderConstructor() const { - LINEF("{0}(Zone& zone);", MarkerClassName(m_env.m_asset)) + LINEF("explicit {0}(AssetVisitor& visitor);", MarkerClassName(m_env.m_asset)) } void PrintHeaderMainMarkMethodDeclaration(const StructureInformation* info) const @@ -237,10 +230,10 @@ namespace void PrintConstructorMethod() { - LINEF("{0}::{0}(Zone& zone)", MarkerClassName(m_env.m_asset)) + LINEF("{0}::{0}(AssetVisitor& visitor)", MarkerClassName(m_env.m_asset)) m_intendation++; - LINEF(": AssetMarker({0}::EnumEntry, zone)", m_env.m_asset->m_asset_name) + LINE(": AssetMarker(visitor)") m_intendation--; LINE("{") @@ -286,7 +279,7 @@ namespace if (info && StructureComputations(info).IsAsset()) { - LINEF("AddDependency({0}(m_zone).GetAssetInfo(*{1}));", MarkerClassName(info), MakeTypePtrVarName(def)) + LINEF("Mark_Dependency<{0}>(*{1});", info->m_asset_name, MakeTypePtrVarName(def)) } else { @@ -413,7 +406,7 @@ namespace { if (loadType == MemberLoadType::SINGLE_POINTER) { - LINEF("AddDependency({0}(m_zone).GetAssetInfo({1}));", MarkerClassName(member->m_type), MakeMemberAccess(info, member, modifier)) + LINEF("Mark_Dependency<{0}>({1});", member->m_type->m_asset_name, MakeMemberAccess(info, member, modifier)) } else if (loadType == MemberLoadType::POINTER_ARRAY) { @@ -752,20 +745,6 @@ namespace LINE("}") } - void PrintGetAssetInfoMethod() - { - LINEF("XAssetInfo<{0}>* {1}::GetAssetInfo({0}* pAsset) const", m_env.m_asset->m_definition->GetFullName(), MarkerClassName(m_env.m_asset)) - LINE("{") - m_intendation++; - - LINEF("return reinterpret_cast*>(GetAssetInfoByName(AssetNameAccessor<{1}>()(*pAsset)));", - m_env.m_asset->m_definition->GetFullName(), - m_env.m_asset->m_asset_name) - - m_intendation--; - LINE("}") - } - void PrintMainMarkMethod() { LINEF("void {0}::Mark({1}* pAsset)", MarkerClassName(m_env.m_asset), m_env.m_asset->m_definition->GetFullName()) diff --git a/src/ZoneCommon/Marking/AssetMarker.cpp b/src/ZoneCommon/Marking/AssetMarker.cpp index c215c7cf..06949005 100644 --- a/src/ZoneCommon/Marking/AssetMarker.cpp +++ b/src/ZoneCommon/Marking/AssetMarker.cpp @@ -3,100 +3,35 @@ #include #include -AssetMarker::AssetMarker(const asset_type_t assetType, Zone& zone) - : m_zone(zone), - m_asset_type(assetType) +AssetMarker::AssetMarker(AssetVisitor& visitor) + : m_visitor(visitor) { } -void AssetMarker::AddDependency(XAssetInfoGeneric* assetInfo) +void AssetMarker::Mark_ScriptString(scr_string_t& scriptString) const { - if (assetInfo == nullptr) - return; - - const auto existingEntry = m_dependencies.find(assetInfo); - if (existingEntry != m_dependencies.end()) - return; - - m_dependencies.emplace(assetInfo); + const auto result = m_visitor.Visit_ScriptString(scriptString); + if (result.has_value()) + scriptString = *result; } -void AssetMarker::Mark_ScriptString(const scr_string_t scrString) +void AssetMarker::MarkArray_ScriptString(scr_string_t* scriptStringArray, const size_t count) const { - assert(scrString < m_zone.m_script_strings.Count()); - - if (scrString >= m_zone.m_script_strings.Count()) - return; - - m_used_script_strings.emplace(scrString); -} - -void AssetMarker::MarkArray_ScriptString(const scr_string_t* scrStringArray, const size_t count) -{ - assert(scrStringArray != nullptr); + assert(scriptStringArray != nullptr); for (size_t index = 0; index < count; index++) - Mark_ScriptString(scrStringArray[index]); + Mark_ScriptString(scriptStringArray[index]); } -void AssetMarker::Mark_IndirectAssetRef(asset_type_t type, const char* assetRefName) +void AssetMarker::Mark_IndirectAssetRef(const asset_type_t assetType, const char* assetName) const { - if (!assetRefName || !assetRefName[0]) - return; - - m_indirect_asset_references.emplace(type, assetRefName); + m_visitor.Visit_IndirectAssetRef(assetType, assetName); } -void AssetMarker::MarkArray_IndirectAssetRef(const asset_type_t type, const char** assetRefNames, const size_t count) +void AssetMarker::MarkArray_IndirectAssetRef(const asset_type_t assetType, const char** assetNames, const size_t count) const { - assert(assetRefNames != nullptr); + assert(assetNames != nullptr); for (size_t index = 0; index < count; index++) - Mark_IndirectAssetRef(type, assetRefNames[index]); -} - -XAssetInfoGeneric* AssetMarker::GetAssetInfoByName(const std::string& name) const -{ - return m_zone.m_pools->GetAsset(m_asset_type, name); -} - -std::vector AssetMarker::GetDependencies() const -{ - std::vector dependencies; - if (!m_dependencies.empty()) - { - dependencies.reserve(m_dependencies.size()); - for (auto dependency : m_dependencies) - dependencies.push_back(dependency); - } - - return dependencies; -} - -std::vector AssetMarker::GetUsedScriptStrings() const -{ - std::vector usedScriptStrings; - if (!m_used_script_strings.empty()) - { - usedScriptStrings.reserve(m_used_script_strings.size()); - for (auto scrString : m_used_script_strings) - usedScriptStrings.push_back(scrString); - - std::ranges::sort(usedScriptStrings); - } - - return usedScriptStrings; -} - -std::vector AssetMarker::GetIndirectAssetReferences() const -{ - std::vector assetReferences; - if (!m_indirect_asset_references.empty()) - { - assetReferences.reserve(m_indirect_asset_references.size()); - for (const auto& assetReference : m_indirect_asset_references) - assetReferences.emplace_back(assetReference); - } - - return assetReferences; + Mark_IndirectAssetRef(assetType, assetNames[index]); } diff --git a/src/ZoneCommon/Marking/AssetMarker.h b/src/ZoneCommon/Marking/AssetMarker.h index c38073b8..a66adca0 100644 --- a/src/ZoneCommon/Marking/AssetMarker.h +++ b/src/ZoneCommon/Marking/AssetMarker.h @@ -1,36 +1,30 @@ #pragma once -#include "Pool/XAssetInfo.h" +#include "Game/IAsset.h" +#include "Marking/AssetVisitor.h" #include "Zone/ZoneTypes.h" -#include +#include class AssetMarker { -public: - [[nodiscard]] std::vector GetDependencies() const; - [[nodiscard]] std::vector GetUsedScriptStrings() const; - [[nodiscard]] std::vector GetIndirectAssetReferences() const; - protected: - AssetMarker(asset_type_t assetType, Zone& zone); + explicit AssetMarker(AssetVisitor& visitor); - void AddDependency(XAssetInfoGeneric* assetInfo); + template void Mark_Dependency(std::add_lvalue_reference_t> asset) + { + static_assert(std::is_base_of_v); - void Mark_ScriptString(scr_string_t scrString); - void MarkArray_ScriptString(const scr_string_t* scrStringArray, size_t count); + const auto result = m_visitor.Visit_Dependency(AssetType::EnumEntry, AssetNameAccessor()(*asset)); + if (result.has_value()) + asset = static_cast>(result->m_ptr); + } - void Mark_IndirectAssetRef(asset_type_t type, const char* assetRefName); - void MarkArray_IndirectAssetRef(asset_type_t type, const char** assetRefNames, size_t count); + void Mark_ScriptString(scr_string_t& scriptString) const; + void MarkArray_ScriptString(scr_string_t* scriptStringArray, size_t count) const; - [[nodiscard]] XAssetInfoGeneric* GetAssetInfoByName(const std::string& name) const; + void Mark_IndirectAssetRef(asset_type_t assetType, const char* assetName) const; + void MarkArray_IndirectAssetRef(asset_type_t assetType, const char** assetNames, size_t count) const; - Zone& m_zone; - -private: - asset_type_t m_asset_type; - - std::unordered_set m_dependencies; - std::unordered_set m_used_script_strings; - std::unordered_set m_indirect_asset_references; + AssetVisitor& m_visitor; }; diff --git a/src/ZoneCommon/Marking/AssetVisitor.h b/src/ZoneCommon/Marking/AssetVisitor.h new file mode 100644 index 00000000..5d708783 --- /dev/null +++ b/src/ZoneCommon/Marking/AssetVisitor.h @@ -0,0 +1,29 @@ +#pragma once + +#include "Pool/XAssetInfo.h" +#include "Zone/ZoneTypes.h" + +#include + +class AssetVisitor +{ +public: + virtual ~AssetVisitor() = default; + + virtual std::optional Visit_Dependency(asset_type_t assetType, const char* assetName) + { + // Do nothing by default + return std::nullopt; + } + + virtual std::optional Visit_ScriptString(scr_string_t scriptString) + { + // Do nothing by default + return std::nullopt; + } + + virtual void Visit_IndirectAssetRef(asset_type_t assetType, const char* assetName) + { + // Do nothing by default + } +}; diff --git a/src/ZoneLoading/Loading/AssetInfoCollector.cpp b/src/ZoneLoading/Loading/AssetInfoCollector.cpp new file mode 100644 index 00000000..c7bc50df --- /dev/null +++ b/src/ZoneLoading/Loading/AssetInfoCollector.cpp @@ -0,0 +1,85 @@ +#include "AssetInfoCollector.h" + +#include +#include + +AssetInfoCollector::AssetInfoCollector(Zone& zone) + : m_zone(zone) +{ +} + +std::vector AssetInfoCollector::GetDependencies() const +{ + std::vector dependencies; + if (!m_dependencies.empty()) + { + dependencies.reserve(m_dependencies.size()); + for (auto dependency : m_dependencies) + dependencies.push_back(dependency); + } + + return dependencies; +} + +std::vector AssetInfoCollector::GetUsedScriptStrings() const +{ + std::vector usedScriptStrings; + if (!m_used_script_strings.empty()) + { + usedScriptStrings.reserve(m_used_script_strings.size()); + for (auto scrString : m_used_script_strings) + usedScriptStrings.push_back(scrString); + + std::ranges::sort(usedScriptStrings); + } + + return usedScriptStrings; +} + +std::vector AssetInfoCollector::GetIndirectAssetReferences() const +{ + std::vector assetReferences; + if (!m_indirect_asset_references.empty()) + { + assetReferences.reserve(m_indirect_asset_references.size()); + for (const auto& assetReference : m_indirect_asset_references) + assetReferences.emplace_back(assetReference); + } + + return assetReferences; +} + +std::optional AssetInfoCollector::Visit_Dependency(const asset_type_t assetType, const char* assetName) +{ + auto* assetInfo = m_zone.m_pools->GetAsset(assetType, assetName); + if (assetInfo == nullptr) + return std::nullopt; + + const auto existingEntry = m_dependencies.find(assetInfo); + if (existingEntry != m_dependencies.end()) + return std::nullopt; + + m_dependencies.emplace(assetInfo); + + return std::nullopt; +} + +std::optional AssetInfoCollector::Visit_ScriptString(scr_string_t scriptString) +{ + assert(scriptString < m_zone.m_script_strings.Count()); + + if (scriptString >= m_zone.m_script_strings.Count()) + return std::nullopt; + + m_used_script_strings.emplace(scriptString); + + return std::nullopt; +} + +void AssetInfoCollector::Visit_IndirectAssetRef(asset_type_t assetType, const char* assetName) +{ + if (!assetName || !assetName[0]) + return; + + m_indirect_asset_references.emplace(assetType, assetName); +} diff --git a/src/ZoneLoading/Loading/AssetInfoCollector.h b/src/ZoneLoading/Loading/AssetInfoCollector.h new file mode 100644 index 00000000..bd2234aa --- /dev/null +++ b/src/ZoneLoading/Loading/AssetInfoCollector.h @@ -0,0 +1,31 @@ +#pragma once + +#include "Marking/AssetVisitor.h" +#include "Pool/XAssetInfo.h" +#include "Zone/ZoneTypes.h" + +#include +#include +#include + +class AssetInfoCollector : public AssetVisitor +{ +public: + explicit AssetInfoCollector(Zone& zone); + ~AssetInfoCollector() override = default; + + [[nodiscard]] std::vector GetDependencies() const; + [[nodiscard]] std::vector GetUsedScriptStrings() const; + [[nodiscard]] std::vector GetIndirectAssetReferences() const; + + std::optional Visit_Dependency(asset_type_t assetType, const char* assetName) override; + std::optional Visit_ScriptString(scr_string_t scriptString) override; + void Visit_IndirectAssetRef(asset_type_t assetType, const char* assetName) override; + +private: + std::unordered_set m_dependencies; + std::unordered_set m_used_script_strings; + std::unordered_set m_indirect_asset_references; + + Zone& m_zone; +};