#include "ZoneMarkTemplate.h" #include "Domain/Computations/MemberComputations.h" #include "Domain/Computations/StructureComputations.h" #include "Internal/BaseTemplate.h" #include "Utils/StringUtils.h" #include #include #include namespace { constexpr int TAG_HEADER = 1; constexpr int TAG_SOURCE = 2; class Template final : BaseTemplate { public: Template(std::ostream& stream, RenderingContext* context) : BaseTemplate(stream, context) { } void Header() { LINE("// ====================================================================") LINE("// This file has been generated by ZoneCodeGenerator.") LINE("// Do not modify.") LINE("// Any changes will be discarded when regenerating.") LINE("// ====================================================================") LINE("") LINE("#pragma once") LINE("") LINE("#include \"Loading/AssetMarker.h\"") LINEF("#include \"Game/{0}/{0}.h\"", m_env.m_game) LINE("") LINE("#include ") LINE("") LINEF("namespace {0}", m_env.m_game) LINE("{") m_intendation++; LINEF("class {0} final : public AssetMarker", MarkerClassName(m_env.m_asset)) LINE("{") m_intendation++; LINE(VariableDecl(m_env.m_asset->m_definition)) LINE(PointerVariableDecl(m_env.m_asset->m_definition)) LINE("") m_intendation--; LINE("public:") m_intendation++; // Variable Declarations: type varType; for (const auto* type : m_env.m_used_types) { if (type->m_info && !type->m_info->m_definition->m_anonymous && !type->m_info->m_is_leaf && !StructureComputations(type->m_info).IsAsset()) { LINE(VariableDecl(type->m_type)) } } for (const auto* type : m_env.m_used_types) { if (type->m_pointer_array_reference_exists && !type->m_is_context_asset) { LINE(PointerVariableDecl(type->m_type)) } } LINE("") // Method Declarations for (const auto* type : m_env.m_used_types) { if (type->m_pointer_array_reference_exists && type->m_info->m_requires_marking) { PrintHeaderPtrArrayMarkMethodDeclaration(type->m_type); } } for (const auto* type : m_env.m_used_types) { if (type->m_array_reference_exists && type->m_info && !type->m_info->m_is_leaf && type->m_info->m_requires_marking && type->m_non_runtime_reference_exists) { PrintHeaderArrayMarkMethodDeclaration(type->m_type); } } for (const auto* type : m_env.m_used_structures) { if (type->m_non_runtime_reference_exists && !type->m_info->m_is_leaf && type->m_info->m_requires_marking && !StructureComputations(type->m_info).IsAsset()) { PrintHeaderMarkMethodDeclaration(type->m_info); } } PrintHeaderMarkMethodDeclaration(m_env.m_asset); LINE("") PrintHeaderGetNameMethodDeclaration(m_env.m_asset); PrintHeaderGetAssetInfoMethodDeclaration(m_env.m_asset); LINE("") PrintHeaderConstructor(); PrintHeaderMainMarkMethodDeclaration(m_env.m_asset); m_intendation--; LINE("};") m_intendation--; LINE("}") } void Source() { LINE("// ====================================================================") LINE("// This file has been generated by ZoneCodeGenerator.") LINE("// Do not modify.") LINE("// Any changes will be discarded when regenerating.") LINE("// ====================================================================") LINE("") LINEF("#include \"{0}_mark_db.h\"", Lower(m_env.m_asset->m_definition->m_name)) LINE("") LINE("#include ") LINE("") if (!m_env.m_referenced_assets.empty()) { LINE("// Referenced Assets:") for (const auto* type : m_env.m_referenced_assets) { LINEF("#include \"../{0}/{0}_mark_db.h\"", Lower(type->m_type->m_name)) } LINE("") } LINEF("using namespace {0};", m_env.m_game) LINE("") PrintConstructorMethod(); for (const auto* type : m_env.m_used_types) { if (type->m_pointer_array_reference_exists && type->m_info->m_requires_marking) { LINE("") PrintMarkPtrArrayMethod(type->m_type, type->m_info, type->m_pointer_array_reference_is_reusable); } } for (const auto* type : m_env.m_used_types) { if (type->m_array_reference_exists && type->m_info && !type->m_info->m_is_leaf && type->m_info->m_requires_marking && type->m_non_runtime_reference_exists) { LINE("") PrintMarkArrayMethod(type->m_type, type->m_info); } } for (const auto* type : m_env.m_used_structures) { if (type->m_non_runtime_reference_exists && !type->m_info->m_is_leaf && type->m_info->m_requires_marking && !StructureComputations(type->m_info).IsAsset()) { LINE("") PrintMarkMethod(type->m_info); } } LINE("") PrintMarkMethod(m_env.m_asset); LINE("") PrintMainMarkMethod(); LINE("") PrintGetNameMethod(); PrintGetAssetInfoMethod(); } private: enum class MemberLoadType : std::uint8_t { ARRAY_POINTER, DYNAMIC_ARRAY, EMBEDDED, EMBEDDED_ARRAY, POINTER_ARRAY, SINGLE_POINTER }; static std::string MarkerClassName(const StructureInformation* asset) { return std::format("Marker_{0}", asset->m_definition->m_name); } static std::string VariableDecl(const DataDefinition* def) { return std::format("{0}* var{1};", def->GetFullName(), MakeSafeTypeName(def)); } static std::string PointerVariableDecl(const DataDefinition* def) { return std::format("{0}** var{1}Ptr;", def->GetFullName(), MakeSafeTypeName(def)); } void PrintHeaderPtrArrayMarkMethodDeclaration(const DataDefinition* def) const { LINEF("void MarkPtrArray_{0}(size_t count);", MakeSafeTypeName(def)) } void PrintHeaderArrayMarkMethodDeclaration(const DataDefinition* def) const { LINEF("void MarkArray_{0}(size_t count);", MakeSafeTypeName(def)) } void PrintHeaderMarkMethodDeclaration(const StructureInformation* info) const { 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 PrintHeaderGetNameMethodDeclaration(const StructureInformation* info) const { LINEF("static std::string GetAssetName({0}* pAsset);", info->m_definition->GetFullName()) } void PrintHeaderConstructor() const { LINEF("{0}(Zone* zone);", MarkerClassName(m_env.m_asset)) } void PrintHeaderMainMarkMethodDeclaration(const StructureInformation* info) const { LINEF("void Mark({0}* pAsset);", info->m_definition->GetFullName()) } void PrintVariableInitialization(const DataDefinition* def) const { LINEF("var{0} = nullptr;", def->m_name) } void PrintPointerVariableInitialization(const DataDefinition* def) const { LINEF("var{0}Ptr = nullptr;", def->m_name) } void PrintConstructorMethod() { LINEF("{0}::{0}(Zone* zone)", MarkerClassName(m_env.m_asset)) m_intendation++; LINEF(": AssetMarker({0}, zone)", m_env.m_asset->m_asset_enum_entry->m_name) m_intendation--; LINE("{") m_intendation++; PrintVariableInitialization(m_env.m_asset->m_definition); PrintPointerVariableInitialization(m_env.m_asset->m_definition); LINE("") for (const auto* type : m_env.m_used_types) { if (type->m_info && !type->m_info->m_definition->m_anonymous && !type->m_info->m_is_leaf && !StructureComputations(type->m_info).IsAsset()) { PrintVariableInitialization(type->m_type); } } for (const auto* type : m_env.m_used_types) { if (type->m_info && type->m_pointer_array_reference_exists && !type->m_is_context_asset) { PrintPointerVariableInitialization(type->m_type); } } m_intendation--; LINE("}") } void PrintMarkPtrArrayMethod_Loading(const DataDefinition* def, const StructureInformation* info) const { if (info && !info->m_is_leaf) { LINEF("{0} = *{1};", MakeTypeVarName(info->m_definition), MakeTypePtrVarName(def)) LINEF("Mark_{0}();", MakeSafeTypeName(def)) } } void PrintMarkPtrArrayMethod_PointerCheck(const DataDefinition* def, StructureInformation* info, const bool reusable) { LINEF("if (*{0})", MakeTypePtrVarName(def)) LINE("{") m_intendation++; if (info && StructureComputations(info).IsAsset()) { LINEF("AddDependency({0}(m_zone).GetAssetInfo(*{1}));", MarkerClassName(info), MakeTypePtrVarName(def)) } else { PrintMarkPtrArrayMethod_Loading(def, info); } m_intendation--; LINE("}") } void PrintMarkPtrArrayMethod(const DataDefinition* def, StructureInformation* info, const bool reusable) { LINEF("void {0}::MarkPtrArray_{1}(const size_t count)", MarkerClassName(m_env.m_asset), MakeSafeTypeName(def)) LINE("{") m_intendation++; LINEF("assert({0} != nullptr);", MakeTypePtrVarName(def)) LINE("") LINEF("{0}** var = {1};", def->GetFullName(), MakeTypePtrVarName(def)) LINE("for (size_t index = 0; index < count; index++)") LINE("{") m_intendation++; LINEF("{0} = var;", MakeTypePtrVarName(def)) PrintMarkPtrArrayMethod_PointerCheck(def, info, reusable); LINE("") LINE("var++;") m_intendation--; LINE("}") m_intendation--; LINE("}") } void PrintMarkArrayMethod(const DataDefinition* def, const StructureInformation* info) { LINEF("void {0}::MarkArray_{1}(const size_t count)", MarkerClassName(m_env.m_asset), MakeSafeTypeName(def)) LINE("{") m_intendation++; LINEF("assert({0} != nullptr);", MakeTypeVarName(def)) LINE("") LINEF("{0}* var = {1};", def->GetFullName(), MakeTypeVarName(def)) LINE("for (size_t index = 0; index < count; index++)") LINE("{") m_intendation++; LINEF("{0} = var;", MakeTypeVarName(info->m_definition)) LINEF("Mark_{0}();", info->m_definition->m_name) LINE("var++;") m_intendation--; LINE("}") m_intendation--; LINE("}") } void MarkMember_ScriptString(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier, const MemberLoadType loadType) const { if (loadType == MemberLoadType::ARRAY_POINTER) { LINEF("MarkArray_ScriptString({0}, {1});", MakeMemberAccess(info, member, modifier), MakeEvaluation(modifier.GetArrayPointerCountEvaluation())) } else if (loadType == MemberLoadType::EMBEDDED_ARRAY) { LINEF("MarkArray_ScriptString({0}, {1});", MakeMemberAccess(info, member, modifier), MakeArrayCount(dynamic_cast(modifier.GetDeclarationModifier()))) } else if (loadType == MemberLoadType::EMBEDDED) { LINEF("Mark_ScriptString({0});", MakeMemberAccess(info, member, modifier)) } else { assert(false); LINEF("#error unsupported loadType {0} for script string", static_cast(loadType)) } } void MarkMember_AssetRef(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier, const MemberLoadType loadType) const { if (loadType == MemberLoadType::POINTER_ARRAY) { if (modifier.IsArray()) { LINEF("MarkArray_IndirectAssetRef({0}, {1}, {2});", member->m_asset_ref->m_name, MakeMemberAccess(info, member, modifier), modifier.GetArraySize()) } else { LINEF("MarkArray_IndirectAssetRef({0}, {1}, {2});", member->m_asset_ref->m_name, MakeMemberAccess(info, member, modifier), MakeEvaluation(modifier.GetPointerArrayCountEvaluation())) } } else if (loadType == MemberLoadType::SINGLE_POINTER) { LINEF("Mark_IndirectAssetRef({0}, {1});", member->m_asset_ref->m_name, MakeMemberAccess(info, member, modifier)) } else { assert(false); LINEF("#error unsupported loadType {0} for script string", static_cast(loadType)) } } void MarkMember_Asset(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier, const MemberLoadType loadType) const { if (loadType == MemberLoadType::SINGLE_POINTER) { LINEF("AddDependency({0}(m_zone).GetAssetInfo({1}));", MarkerClassName(member->m_type), MakeMemberAccess(info, member, modifier)) } else if (loadType == MemberLoadType::POINTER_ARRAY) { MarkMember_PointerArray(info, member, modifier); } else { assert(false); LINEF("#error unsupported loadType {0} for asset", static_cast(loadType)) } } void MarkMember_ArrayPointer(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) const { LINEF("{0} = {1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) LINEF("MarkArray_{0}({1});", MakeSafeTypeName(member->m_member->m_type_declaration->m_type), MakeEvaluation(modifier.GetArrayPointerCountEvaluation())) } void MarkMember_PointerArray(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) const { LINEF("{0} = {1};", MakeTypePtrVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) if (modifier.IsArray()) { LINEF("MarkPtrArray_{0}({1});", MakeSafeTypeName(member->m_member->m_type_declaration->m_type), modifier.GetArraySize()) } else { LINEF("MarkPtrArray_{0}({1});", MakeSafeTypeName(member->m_member->m_type_declaration->m_type), MakeEvaluation(modifier.GetPointerArrayCountEvaluation())) } } void MarkMember_EmbeddedArray(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) const { std::string arraySizeStr; if (modifier.HasDynamicArrayCount()) arraySizeStr = MakeEvaluation(modifier.GetDynamicArrayCountEvaluation()); else arraySizeStr = std::to_string(modifier.GetArraySize()); LINEF("{0} = {1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) LINEF("MarkArray_{0}({1});", MakeSafeTypeName(member->m_member->m_type_declaration->m_type), arraySizeStr) } void MarkMember_DynamicArray(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) const { LINEF("{0} = {1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) LINEF( "MarkArray_{0}({1});", MakeSafeTypeName(member->m_member->m_type_declaration->m_type), MakeEvaluation(modifier.GetDynamicArraySizeEvaluation())) } void MarkMember_Embedded(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) const { LINEF("{0} = &{1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) LINEF("Mark_{0}();", MakeSafeTypeName(member->m_member->m_type_declaration->m_type)) } void MarkMember_SinglePointer(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) const { LINEF("{0} = {1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) LINEF("Mark_{0}();", MakeSafeTypeName(member->m_type->m_definition)) } void MarkMember_TypeCheck(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier, const MemberLoadType loadType) const { if (member->m_is_script_string) { MarkMember_ScriptString(info, member, modifier, loadType); } else if (member->m_asset_ref) { MarkMember_AssetRef(info, member, modifier, loadType); } else if (member->m_type && StructureComputations(member->m_type).IsAsset()) { MarkMember_Asset(info, member, modifier, loadType); } else { switch (loadType) { case MemberLoadType::ARRAY_POINTER: MarkMember_ArrayPointer(info, member, modifier); break; case MemberLoadType::SINGLE_POINTER: MarkMember_SinglePointer(info, member, modifier); break; case MemberLoadType::EMBEDDED: MarkMember_Embedded(info, member, modifier); break; case MemberLoadType::POINTER_ARRAY: MarkMember_PointerArray(info, member, modifier); break; case MemberLoadType::DYNAMIC_ARRAY: MarkMember_DynamicArray(info, member, modifier); break; case MemberLoadType::EMBEDDED_ARRAY: MarkMember_EmbeddedArray(info, member, modifier); break; default: LINEF("// t={0}", static_cast(loadType)) break; } } } static bool MarkMember_ShouldMakePointerCheck(const MemberInformation* member, const DeclarationModifierComputations& modifier, MemberLoadType loadType) { if (loadType != MemberLoadType::ARRAY_POINTER && loadType != MemberLoadType::POINTER_ARRAY && loadType != MemberLoadType::SINGLE_POINTER) { return false; } if (loadType == MemberLoadType::POINTER_ARRAY) { return !modifier.IsArray(); } if (member->m_is_string) { return false; } return true; } void MarkMember_PointerCheck(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier, const MemberLoadType loadType) { if (MarkMember_ShouldMakePointerCheck(member, modifier, loadType)) { LINEF("if ({0})", MakeMemberAccess(info, member, modifier)) LINE("{") m_intendation++; MarkMember_TypeCheck(info, member, modifier, loadType); m_intendation--; LINE("}") } else { MarkMember_TypeCheck(info, member, modifier, loadType); } } void MarkMember_ReferenceArray(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) { auto first = true; for (const auto& entry : modifier.GetArrayEntries()) { if (first) { first = false; } else { LINE("") } MarkMember_Reference(info, member, entry); } } void MarkMember_Reference(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) { if (modifier.IsDynamicArray()) { MarkMember_PointerCheck(info, member, modifier, MemberLoadType::DYNAMIC_ARRAY); } else if (modifier.IsSinglePointer()) { MarkMember_PointerCheck(info, member, modifier, MemberLoadType::SINGLE_POINTER); } else if (modifier.IsArrayPointer()) { MarkMember_PointerCheck(info, member, modifier, MemberLoadType::ARRAY_POINTER); } else if (modifier.IsPointerArray()) { MarkMember_PointerCheck(info, member, modifier, MemberLoadType::POINTER_ARRAY); } else if (modifier.IsArray() && modifier.GetNextDeclarationModifier() == nullptr) { MarkMember_PointerCheck(info, member, modifier, MemberLoadType::EMBEDDED_ARRAY); } else if (modifier.GetDeclarationModifier() == nullptr) { MarkMember_PointerCheck(info, member, modifier, MemberLoadType::EMBEDDED); } else if (modifier.IsArray()) { MarkMember_ReferenceArray(info, member, modifier); } else { assert(false); LINEF("#error MarkMemberReference failed @ {0}", member->m_member->m_name) } } void MarkMember_Condition_Struct(const StructureInformation* info, const MemberInformation* member) { LINE("") if (member->m_condition) { LINEF("if ({0})", MakeEvaluation(member->m_condition.get())) LINE("{") m_intendation++; MarkMember_Reference(info, member, DeclarationModifierComputations(member)); m_intendation--; LINE("}") } else { MarkMember_Reference(info, member, DeclarationModifierComputations(member)); } } void MarkMember_Condition_Union(const StructureInformation* info, const MemberInformation* member) { const MemberComputations computations(member); if (computations.IsFirstMember()) { LINE("") if (member->m_condition) { LINEF("if ({0})", MakeEvaluation(member->m_condition.get())) LINE("{") m_intendation++; MarkMember_Reference(info, member, DeclarationModifierComputations(member)); m_intendation--; LINE("}") } else { MarkMember_Reference(info, member, DeclarationModifierComputations(member)); } } else if (computations.IsLastMember()) { if (member->m_condition) { LINEF("else if ({0})", MakeEvaluation(member->m_condition.get())) LINE("{") m_intendation++; MarkMember_Reference(info, member, DeclarationModifierComputations(member)); m_intendation--; LINE("}") } else { LINE("else") LINE("{") m_intendation++; MarkMember_Reference(info, member, DeclarationModifierComputations(member)); m_intendation--; LINE("}") } } else { if (member->m_condition) { LINEF("else if ({0})", MakeEvaluation(member->m_condition.get())) LINE("{") m_intendation++; MarkMember_Reference(info, member, DeclarationModifierComputations(member)); m_intendation--; LINE("}") } else { LINEF("#error Middle member of union must have condition ({0})", member->m_member->m_name) } } } void PrintMarkMemberIfNeedsTreatment(const StructureInformation* info, const MemberInformation* member) { const MemberComputations computations(member); if (computations.ShouldIgnore() || computations.IsInRuntimeBlock()) return; if (member->m_is_script_string || member->m_asset_ref || member->m_type && (member->m_type->m_requires_marking || StructureComputations(member->m_type).IsAsset())) { if (info->m_definition->GetType() == DataDefinitionType::UNION) MarkMember_Condition_Union(info, member); else MarkMember_Condition_Struct(info, member); } } void PrintMarkMethod(const StructureInformation* info) { LINEF("void {0}::Mark_{1}()", MarkerClassName(m_env.m_asset), info->m_definition->m_name) LINE("{") m_intendation++; LINEF("assert({0} != nullptr);", MakeTypeVarName(info->m_definition)) for (const auto& member : info->m_ordered_members) { PrintMarkMemberIfNeedsTreatment(info, member.get()); } m_intendation--; LINE("}") } void PrintGetNameMethod() { LINEF("std::string {0}::GetAssetName({1}* pAsset)", MarkerClassName(m_env.m_asset), m_env.m_asset->m_definition->GetFullName()) LINE("{") m_intendation++; if (!m_env.m_asset->m_name_chain.empty()) { LINE_START("return pAsset") auto first = true; for (auto* member : m_env.m_asset->m_name_chain) { if (first) { first = false; LINE_MIDDLEF("->{0}", member->m_member->m_name) } else { LINE_MIDDLEF(".{0}", member->m_member->m_name) } } LINE_END(";") } else { LINEF("return \"{0}\";", m_env.m_asset->m_definition->m_name) } m_intendation--; 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(GetAssetName(pAsset)));", m_env.m_asset->m_definition->GetFullName()) m_intendation--; LINE("}") } void PrintMainMarkMethod() { LINEF("void {0}::Mark({1}* pAsset)", MarkerClassName(m_env.m_asset), m_env.m_asset->m_definition->GetFullName()) LINE("{") m_intendation++; LINE("assert(pAsset != nullptr);") LINE("") LINEF("{0} = pAsset;", MakeTypeVarName(m_env.m_asset->m_definition)) LINEF("Mark_{0}();", MakeSafeTypeName(m_env.m_asset->m_definition)) m_intendation--; LINE("}") } }; } // namespace std::vector ZoneMarkTemplate::GetFilesToRender(RenderingContext* context) { std::vector files; auto assetName = context->m_asset->m_definition->m_name; utils::MakeStringLowerCase(assetName); files.emplace_back(std::format("{0}/{0}_mark_db.h", assetName), TAG_HEADER); files.emplace_back(std::format("{0}/{0}_mark_db.cpp", assetName), TAG_SOURCE); return files; } void ZoneMarkTemplate::RenderFile(std::ostream& stream, const int fileTag, RenderingContext* context) { Template t(stream, context); if (fileTag == TAG_HEADER) { t.Header(); } else { assert(fileTag == TAG_SOURCE); t.Source(); } }