diff --git a/cpp_header_codegen/cpp_header_codegen.cc b/cpp_header_codegen/cpp_header_codegen.cc index 4ab63a5..e4368cf 100644 --- a/cpp_header_codegen/cpp_header_codegen.cc +++ b/cpp_header_codegen/cpp_header_codegen.cc @@ -5,6 +5,7 @@ #include "ecsact/codegen/plugin.h" #include "ecsact/codegen/plugin.hh" #include "ecsact/lang-support/lang-cc.hh" +#include "ecsact/cpp_codegen_plugin_util.hh" constexpr auto GENERATED_FILE_DISCLAIMER = R"(// GENERATED FILE - DO NOT EDIT )"; @@ -67,21 +68,23 @@ static auto cpp_field_type_name(ecsact_field_type field_type) -> std::string { } static void write_fields( - ecsact::codegen_plugin_context& ctx, - ecsact_composite_id compo_id, - std::string_view indentation + ecsact::codegen_plugin_context& ctx, + ecsact_composite_id compo_id, + std::predicate auto&& filter, + std::string_view indentation ) { using ecsact::cc_lang_support::cpp_identifier; using ecsact::cc_lang_support::cpp_type_str; using namespace std::string_literals; - auto full_name = - ecsact_meta_decl_full_name(ecsact_id_cast(compo_id)); - for(auto field_id : get_field_ids(compo_id)) { auto field_type = ecsact_meta_field_type(compo_id, field_id); auto field_name = ecsact_meta_field_name(compo_id, field_id); + if(!filter(field_type, field_name)) { + continue; + } + ctx.writef( "{}{} {}", indentation, @@ -94,7 +97,34 @@ static void write_fields( } ctx.writef(";\n"); } +} + +static void for_each_field( + ecsact_composite_id compo_id, + std::invocable auto&& fn +) { + using ecsact::cc_lang_support::cpp_identifier; + using ecsact::cc_lang_support::cpp_type_str; + using namespace std::string_literals; + + for(auto field_id : get_field_ids(compo_id)) { + auto field_type = ecsact_meta_field_type(compo_id, field_id); + auto field_name = ecsact_meta_field_name(compo_id, field_id); + fn(field_type, field_name); + } +} +static auto write_operators( + ecsact::codegen_plugin_context& ctx, + ecsact_composite_id compo_id, + std::string_view indentation +) -> void { + using ecsact::cc_lang_support::cpp_identifier; + using ecsact::cc_lang_support::cpp_type_str; + using namespace std::string_literals; + + auto full_name = + ecsact_meta_decl_full_name(ecsact_id_cast(compo_id)); ctx.writef( "{}auto operator<=>(const {}&) const = default;\n", indentation, @@ -158,6 +188,49 @@ static auto has_assoc_fields(CompositeID compo_id) -> bool { return false; } +template +static auto write_indexed_fields_struct( + ecsact::codegen_plugin_context& ctx, + CompositeID compo_id +) -> void { + using ecsact::cpp_codegen_plugin_util::block; + using ecsact::cpp_codegen_plugin_util::method_printer; + + ctx.writef("\n"); + block(ctx, "struct IndexedFields", [&] { + write_fields( + ctx, + ecsact_id_cast(compo_id), + [](ecsact_field_type type, const char*) -> bool { + return type.kind == ECSACT_TYPE_KIND_FIELD_INDEX; + }, + "\t" + ); + + { + ctx.writef("constexpr static "); + auto _ = method_printer(ctx, "from_composite") + .parameter("const auto&", "composite") + .return_type("IndexedFields"); + + block(ctx, "return", [&] { + for_each_field( + ecsact_id_cast(compo_id), + [&](ecsact_field_type type, const char* field_name) { + if(type.kind != ECSACT_TYPE_KIND_FIELD_INDEX) { + return; + } + + ctx.writef("\t.{0} = composite.{0},\n", field_name); + } + ); + }); + ctx.writef(";\n"); + } + }); + ctx.writef(";\n"); +} + void ecsact_codegen_plugin( ecsact_package_id package_id, ecsact_codegen_write_fn_t write_fn, @@ -209,7 +282,12 @@ void ecsact_codegen_plugin( has_assoc_fields(comp_id) ? "true" : "false" ); write_constexpr_id(ctx, "ecsact_component_id", comp_id, "\t"); - write_fields(ctx, compo_id, "\t"s); + ctx.indentation += 1; + write_indexed_fields_struct(ctx, comp_id); + ctx.indentation -= 1; + ctx.writef("\n"); + write_fields(ctx, compo_id, [](auto, auto) { return true; }, "\t"s); + write_operators(ctx, compo_id, "\t"s); ctx.writef("}};\n"); } @@ -222,7 +300,12 @@ void ecsact_codegen_plugin( has_assoc_fields(comp_id) ? "true" : "false" ); write_constexpr_id(ctx, "ecsact_transient_id", comp_id, "\t"); - write_fields(ctx, compo_id, "\t"s); + ctx.indentation += 1; + write_indexed_fields_struct(ctx, comp_id); + ctx.indentation -= 1; + ctx.writef("\n"); + write_fields(ctx, compo_id, [](auto, auto) { return true; }, "\t"s); + write_operators(ctx, compo_id, "\t"s); ctx.writef("}};\n"); } @@ -238,7 +321,12 @@ void ecsact_codegen_plugin( write_system_struct(ctx, child_system_id, "\t"); } write_system_impl_decl(ctx, "\t"); - write_fields(ctx, compo_id, "\t"); + ctx.indentation += 1; + write_indexed_fields_struct(ctx, compo_id); + ctx.indentation -= 1; + ctx.writef("\n"); + write_fields(ctx, compo_id, [](auto, auto) { return true; }, "\t"); + write_operators(ctx, compo_id, "\t"s); ctx.writef("}};\n"); }