diff --git a/rt_entt_codegen/core/BUILD.bazel b/rt_entt_codegen/core/BUILD.bazel index e8d9c8d..4691826 100644 --- a/rt_entt_codegen/core/BUILD.bazel +++ b/rt_entt_codegen/core/BUILD.bazel @@ -13,6 +13,7 @@ cc_library( _CORE_CODEGEN_METHODS = { "execute_systems": [ "//rt_entt_codegen/shared:parallel", + "//rt_entt_codegen/shared:system_variant", ], "create_registry": [], "entity_matches": [ @@ -26,6 +27,11 @@ _CORE_CODEGEN_METHODS = { "//rt_entt_codegen/shared:system_util", "//rt_entt_codegen/shared:parallel", "//rt_entt_codegen/core/sys_exec", + "//rt_entt_codegen/core/system_provider:lazy", + "//rt_entt_codegen/core/system_provider:association", + "//rt_entt_codegen/core/system_provider:notify", + "//rt_entt_codegen/core/system_provider:basic", + "//rt_entt_codegen/core/system_provider", "@entt//:entt", "@ecsact_rt_entt//:lib", ], diff --git a/rt_entt_codegen/core/execute_systems.cc b/rt_entt_codegen/core/execute_systems.cc index 5b076c6..4e216f0 100644 --- a/rt_entt_codegen/core/execute_systems.cc +++ b/rt_entt_codegen/core/execute_systems.cc @@ -4,6 +4,7 @@ #include "ecsact/lang-support/lang-cc.hh" #include "rt_entt_codegen/shared/util.hh" #include "ecsact/cpp_codegen_plugin_util.hh" +#include "rt_entt_codegen/shared/system_variant.hh" constexpr auto METHOD_BODY_TOP = R"( auto& registry = ecsact::entt::get_registry(registry_id); @@ -77,66 +78,28 @@ auto ecsact::rt_entt_codegen::core::print_execute_systems( // }); }); + std::vector system_like_variants; + + for(const auto sys_like_id : details.top_execution_order) { + if(details.is_system(sys_like_id)) { + system_like_variants.push_back(static_cast(sys_like_id) + ); + } else if(details.is_action(sys_like_id)) { + system_like_variants.push_back(static_cast(sys_like_id) + ); + } + } + auto parallel_system_cluster = ecsact::rt_entt_codegen::parallel::get_parallel_execution_cluster( ctx, - details, - details.top_execution_order + system_like_variants ); - for(const auto& systems_to_parallel : parallel_system_cluster) { - if(systems_to_parallel.size() == 1) { - auto sync_sys_id = systems_to_parallel[0]; - - auto sync_sys_name = - cpp_identifier(ecsact::meta::decl_full_name(sync_sys_id)); - - if(details.is_action(sync_sys_id)) { - ctx.write(std::format( - "ecsact::entt::execute_actions<{}>(registry, {}, " - "actions_map);\n", - sync_sys_name, - "nullptr" - )); - } - if(details.is_system(sync_sys_id)) { - ctx.write(std::format( - "ecsact::entt::execute_system<{}>(registry, {}, " - "actions_map);\n", - sync_sys_name, - "nullptr" - )); - } - continue; - } - - ctx.write("execute_parallel_cluster(registry, nullptr, "); - ctx.write(std::format( - "std::array {{\n", - systems_to_parallel.size() - )); - for(const auto system_like_id : systems_to_parallel) { - auto cpp_decl_name = - cpp_identifier(ecsact::meta::decl_full_name(system_like_id)); - - if(details.is_action(system_like_id)) { - ctx.write( - "\texec_entry_t{&ecsact::entt::execute_actions<", - cpp_decl_name, - ">, actions_map},\n" - ); - } else if(details.is_system(system_like_id)) { - ctx.write( - "\texec_entry_t{&ecsact::entt::execute_system<", - cpp_decl_name, - ">, actions_map},\n" - ); - } else { - ctx.write("// ??? unhandled ??? ", cpp_decl_name, "\n"); - } - } - ctx.write("});\n"); - } + ecsact::rt_entt_codegen::parallel::print_parallel_execution_cluster( + ctx, + parallel_system_cluster + ); ctx.write("\nupdate_all_beforechange_storage(registry_id);\n"); ctx.write("cleanup_system_notifies(registry_id);\n"); diff --git a/rt_entt_codegen/core/print_sys_exec.cc b/rt_entt_codegen/core/print_sys_exec.cc index db0ec30..2c756d9 100644 --- a/rt_entt_codegen/core/print_sys_exec.cc +++ b/rt_entt_codegen/core/print_sys_exec.cc @@ -1,13 +1,11 @@ #include "core.hh" -#include +#include #include -#include +#include +#include #include -#include -#include -#include -#include + #include "ecsact/runtime/meta.hh" #include "ecsact/runtime/common.h" #include "ecsact/lang-support/lang-cc.hh" @@ -16,10 +14,14 @@ #include "rt_entt_codegen/shared/ecsact_entt_details.hh" #include "rt_entt_codegen/shared/util.hh" #include "rt_entt_codegen/shared/comps_with_caps.hh" -#include "rt_entt_codegen/shared/sorting.hh" #include "rt_entt_codegen/shared/system_util.hh" -#include "rt_entt_codegen/shared/parallel.hh" #include "rt_entt_codegen/core/sys_exec/sys_exec.hh" +#include "system_provider/system_provider.hh" +#include "rt_entt_codegen/core/system_provider/lazy/lazy.hh" +#include "system_provider/lazy/lazy.hh" +#include "system_provider/association/association.hh" +#include "system_provider/notify/notify.hh" +#include "system_provider/basic/basic.hh" using capability_t = std::unordered_map; @@ -28,408 +30,148 @@ template concept system_or_action = std::same_as || std::same_as; +using ecsact::cc_lang_support::cpp_identifier; +using ecsact::cpp_codegen_plugin_util::block; +using ecsact::meta::decl_full_name; +using ecsact::rt_entt_codegen::ecsact_entt_system_details; using ecsact::rt_entt_codegen::system_comps_with_caps; -using ecsact::rt_entt_codegen::system_needs_sorted_entities; +using ecsact::rt_entt_codegen::system_like_id_variant; +using ecsact::rt_entt_codegen::core::provider::handle_exclusive_provide; +using ecsact::rt_entt_codegen::core::provider::system_provider; +using ecsact::rt_entt_codegen::system_util::is_trivial_system; +using ecsact::rt_entt_codegen::util::method_printer; +using namespace ecsact::rt_entt_codegen::core; + +using system_provider_t = std::vector>; static auto print_sys_exec_ctx_action( - ecsact::codegen_plugin_context& ctx, - const ecsact::rt_entt_codegen::ecsact_entt_system_details& details, - const ecsact::rt_entt_codegen::core::print_execute_systems_options options + ecsact::codegen_plugin_context& ctx, + const common_vars names, + system_provider_t system_providers ) -> void { - using ecsact::cc_lang_support::cpp_identifier; - using ecsact::meta::decl_full_name; - using ecsact::rt_entt_codegen::util::method_printer; - auto printer = // method_printer{ctx, "action"} .parameter("void*", "out_action_data") .return_type("void final"); - if(options.is_action()) { - auto action_name = - cpp_identifier(decl_full_name(options.get_sys_like_id())); + auto result = std::ranges::find_if(system_providers, [&](auto provider) { + return provider->context_function_action(ctx, names) == + handle_exclusive_provide::HANDLED; + }); - ctx.write( - "*static_cast<", - action_name, - "*>(out_action_data) = *static_cast(action_data);\n" - ); - } else { - // TODO(Kelwan): Trying to access .action() without a valid action - ctx.write("\n"); + if(result == system_providers.end()) { + throw std::logic_error("print context action was not handled by providers"); } } static auto print_sys_exec_ctx_add( - ecsact::codegen_plugin_context& ctx, - const ecsact::rt_entt_codegen::ecsact_entt_system_details& details, - capability_t sys_caps + ecsact::codegen_plugin_context& ctx, + const common_vars names, + system_provider_t system_providers ) -> void { - using ecsact::cc_lang_support::cpp_identifier; - using ecsact::cpp_codegen_plugin_util::block; - using ecsact::meta::decl_full_name; - using ecsact::rt_entt_codegen::util::is_transient_component; - using ecsact::rt_entt_codegen::util::method_printer; - auto printer = // method_printer{ctx, "add"} .parameter("ecsact_component_like_id", "component_id") .parameter("const void*", "component_data") .return_type("void final"); - auto adds_comps = std::vector{}; - - for(auto&& [comp_id, sys_cap] : sys_caps) { - if(is_transient_component(ctx.package_id, comp_id)) { - continue; - } - if((ECSACT_SYS_CAP_ADDS & sys_cap) == ECSACT_SYS_CAP_ADDS) { - adds_comps.push_back(comp_id); - } - } + auto result = std::ranges::find_if(system_providers, [&](auto provider) { + return provider->context_function_add(ctx, names) == + handle_exclusive_provide::HANDLED; + }); - if(adds_comps.empty()) { - // TODO(Kelwan): Handle unexpected behaviour - return; - } else if(adds_comps.size() == 1) { - const auto& comp_id = adds_comps.front(); - auto type_name = cpp_identifier(decl_full_name(comp_id)); - ctx.write( - "wrapper::dynamic::context_add<::", - type_name, - ">(this, ecsact_id_cast(", - type_name, - "::id),", - "component_data); \n" - ); - return; + if(result == system_providers.end()) { + throw std::logic_error("print context add was not handled by providers"); } - block( - ctx, - "static const auto add_fns = " - "std::unordered_map", - [&] { - for(int i = 0; i < adds_comps.size(); ++i) { - const auto comp_id = adds_comps[i]; - auto type_name = cpp_identifier(decl_full_name(comp_id)); - ctx.write( - "{", - "ecsact_id_cast(", - type_name, - "::id), ", - "&wrapper::dynamic::context_add<::", - type_name, - "> }," - ); - } - } - ); - - ctx.write(";\n"); - - ctx.write("add_fns.at(component_id)(this, component_id, component_data);\n"); } static auto print_sys_exec_ctx_remove( - ecsact::codegen_plugin_context& ctx, - const ecsact::rt_entt_codegen::ecsact_entt_system_details& details, - capability_t sys_caps, - const std::string& view_type_name + ecsact::codegen_plugin_context& ctx, + const common_vars names, + system_provider_t system_providers ) -> void { - using ecsact::cc_lang_support::cpp_identifier; - using ecsact::cpp_codegen_plugin_util::block; - using ecsact::meta::decl_full_name; - using ecsact::rt_entt_codegen::util::is_transient_component; - using ecsact::rt_entt_codegen::util::method_printer; - auto printer = // method_printer{ctx, "remove"} .parameter("ecsact_component_like_id", "component_id") .return_type("void final"); - auto remove_comps = std::vector{}; - - for(auto&& [comp_id, sys_cap] : sys_caps) { - if(is_transient_component(ctx.package_id, comp_id)) { - continue; - } - if((ECSACT_SYS_CAP_REMOVES & sys_cap) == ECSACT_SYS_CAP_REMOVES) { - remove_comps.push_back(comp_id); - } - } - - ctx.write("// Size: ", remove_comps.size(), "\n"); - - if(remove_comps.size() == 0) { - // TODO(Kelwan): Handle unexpected behaviour - return; - } - if(remove_comps.size() == 1) { - const auto& comp_id = remove_comps.front(); + auto result = std::ranges::find_if(system_providers, [&](auto provider) { + return provider->context_function_remove(ctx, names) == + handle_exclusive_provide::HANDLED; + }); - auto type_name = cpp_identifier(decl_full_name(comp_id)); - ctx.write( - "wrapper::dynamic::context_remove<::", - type_name, - ">(this, ecsact_id_cast(", - type_name, - "::id), *view);\n" - ); - return; + if(result == system_providers.end()) { + throw std::logic_error("print context remove was not handled by providers"); } - ctx.write(std::format( - "using remove_fn_t = void (*)(ecsact_system_execution_context*, " - "ecsact_component_like_id, {}_t&);\n", - view_type_name - )); - - ctx.write("static const auto remove_fns = []()\n"); - - block(ctx, "", [&] { - ctx.write( - "auto result = std::unordered_map{};\n" - ); - for(const auto comp_id : details.removable_comps) { - auto type_name = cpp_identifier(decl_full_name(comp_id)); - ctx.write( - "result[ecsact_id_cast(", - type_name, - "::id)] = &wrapper::dynamic::context_remove<", - type_name, - ">;\n" - ); - } - - ctx.write("return result;\n"); - }); - ctx.write("();\n"); } static auto print_sys_exec_ctx_get( - ecsact::codegen_plugin_context& ctx, - const ecsact::rt_entt_codegen::ecsact_entt_system_details& details, - const std::string& view_type_name + ecsact::codegen_plugin_context& ctx, + const common_vars names, + system_provider_t system_providers ) -> void { - using ecsact::cc_lang_support::cpp_identifier; - using ecsact::cpp_codegen_plugin_util::block; - using ecsact::meta::decl_full_name; - using ecsact::rt_entt_codegen::util::is_transient_component; - using ecsact::rt_entt_codegen::util::method_printer; - auto printer = // method_printer{ctx, "get"} .parameter("ecsact_component_like_id", "component_id") .parameter("void*", "out_component_data") .return_type("void final"); - if(details.readable_comps.size() == 0) { - return; - } - - std::vector get_components; - - for(auto comp_id : details.readable_comps) { - if(is_transient_component(ctx.package_id, comp_id)) { - continue; - } - get_components.insert(get_components.end(), comp_id); - } - - if(get_components.size() == 0) { - return; - } - - // Shortcut - ignore component ID because we only have 1 - if(details.get_comps.size() == 1 && details.readable_comps.size() == 1) { - auto comp_id = *details.get_comps.begin(); - auto cpp_comp_full_name = cpp_identifier(decl_full_name(comp_id)); - - ctx.write( - "assert(ecsact_id_cast(::", - cpp_comp_full_name, - "::id) == component_id);\n" - ); - ctx.write( - "*static_cast<::", - cpp_comp_full_name, - "*>(out_component_data) = view->get<::", - cpp_comp_full_name, - ">(entity);" - ); - return; - } - - ctx.write(std::format( - "using get_fn_t = void (*)(ecsact_system_execution_context*, " - "ecsact_component_like_id, void *, {}_t&);\n", - view_type_name - )); - - ctx.write("static const auto get_fns = []()\n"); - - block(ctx, "", [&] { - ctx.write( - "auto result = std::unordered_map{};\n" - ); - for(const auto comp_id : details.readable_comps) { - auto type_name = cpp_identifier(decl_full_name(comp_id)); - ctx.write( - "result[ecsact_id_cast(", - type_name, - "::id)] = &wrapper::dynamic::context_get<", - type_name, - ">;\n" - ); - } - - ctx.write("return result;\n"); + auto result = std::ranges::find_if(system_providers, [&](auto provider) { + return provider->context_function_get(ctx, names) == + handle_exclusive_provide::HANDLED; }); - ctx.write("();\n"); - ctx.write( - "get_fns.at(component_id)(this, component_id, out_component_data, *view);\n" - ); + if(result == system_providers.end()) { + throw std::logic_error("print context get was not handled by providers"); + } } static auto print_sys_exec_ctx_update( - ecsact::codegen_plugin_context& ctx, - const ecsact::rt_entt_codegen::ecsact_entt_system_details& details, - const std::string& view_type_name + ecsact::codegen_plugin_context& ctx, + const common_vars names, + system_provider_t system_providers ) -> void { - using ecsact::cc_lang_support::cpp_identifier; - using ecsact::cpp_codegen_plugin_util::block; - using ecsact::meta::decl_full_name; - using ecsact::rt_entt_codegen::util::method_printer; - auto printer = // method_printer{ctx, "update"} .parameter("ecsact_component_like_id", "component_id") .parameter("const void*", "component_data") .return_type("void final"); - if(details.writable_comps.size() == 0) { - return; - } - - if(details.writable_comps.size() == 1) { - const auto& comp_id = *details.writable_comps.begin(); - auto type_name = cpp_identifier(decl_full_name(comp_id)); - ctx.write( - "wrapper::dynamic::context_update<::", - type_name, - ">(this, ecsact_id_cast(", - type_name, - "::id),", - "component_data, *view); \n" - ); - return; - } - - ctx.write(std::format( - "using update_fn_t = void (*)(ecsact_system_execution_context*, " - "ecsact_component_like_id, const void *, {}_t&);\n", - view_type_name - )); - - ctx.write("static const auto update_fns = []()\n"); - - block(ctx, "", [&] { - ctx.write( - "auto result = std::unordered_map{};\n" - ); - for(const auto comp_id : details.writable_comps) { - auto type_name = cpp_identifier(decl_full_name(comp_id)); - ctx.write( - "result[ecsact_id_cast(", - type_name, - "::id)] = &wrapper::dynamic::context_update<", - type_name, - ">;\n" - ); - } - - ctx.write("return result;\n"); + auto result = std::ranges::find_if(system_providers, [&](auto provider) { + return provider->context_function_update(ctx, names) == + handle_exclusive_provide::HANDLED; }); - ctx.write("();\n"); - ctx.write( - "update_fns.at(component_id)(this, component_id, component_data, " - "*view);\n" - ); + if(result == system_providers.end()) { + throw std::logic_error("print context update was not handled by providers"); + } } static auto print_sys_exec_ctx_has( - ecsact::codegen_plugin_context& ctx, - const ecsact::rt_entt_codegen::ecsact_entt_system_details& details + ecsact::codegen_plugin_context& ctx, + const common_vars names, + system_provider_t system_providers ) -> void { - using ecsact::cc_lang_support::cpp_identifier; - using ecsact::cpp_codegen_plugin_util::block; - using ecsact::meta::decl_full_name; - using ecsact::rt_entt_codegen::util::method_printer; - - // use optional_comps - auto printer = // method_printer{ctx, "has"} .parameter("ecsact_component_like_id", "component_id") .return_type("bool final"); - if(details.writable_comps.size() == 0) { - ctx.write("return false;"); - return; - } + auto result = std::ranges::find_if(system_providers, [&](auto provider) { + return provider->context_function_has(ctx, names) == + handle_exclusive_provide::HANDLED; + }); - if(details.writable_comps.size() == 1) { - const auto& comp_id = *details.writable_comps.begin(); - auto type_name = cpp_identifier(decl_full_name(comp_id)); - ctx.write( - "return wrapper::dynamic::context_has<::", - type_name, - ">(this, ecsact_id_cast(", - type_name, - "::id));\n" - ); + if(result == system_providers.end()) { + throw std::logic_error("print context has was not handled by providers"); } - block( - ctx, - "static const auto has_fns = " - "std::unordered_map", - [&] { - for(const auto comp_id : details.readable_comps) { - auto type_name = cpp_identifier(decl_full_name(comp_id)); - ctx.write( - "{ecsact_id_cast(", - type_name, - "::id), &wrapper::dynamic::context_has<", - type_name, - "> }," - ); - } - } - ); - ctx.write(";\n"); - - ctx.write("return has_fns.at(component_id)(this, component_id);\n"); } static auto print_sys_exec_ctx_generate( - ecsact::codegen_plugin_context& ctx, - const ecsact::rt_entt_codegen::ecsact_entt_system_details& details + ecsact::codegen_plugin_context& ctx, + const common_vars names, + system_provider_t system_providers ) -> void { - using ecsact::cc_lang_support::cpp_identifier; - using ecsact::cpp_codegen_plugin_util::block; - using ecsact::meta::decl_full_name; - using ecsact::rt_entt_codegen::ecsact_entt_system_details; - using ecsact::rt_entt_codegen::get_all_sorted_systems; - using ecsact::rt_entt_codegen::util::method_printer; - auto printer = // method_printer{ctx, "generate"} .parameter("int", "component_count") @@ -437,91 +179,54 @@ static auto print_sys_exec_ctx_generate( .parameter("const void**", "components_data") .return_type("void final"); - if(details.generate_comps.size() == 0) { - // TODO (Kelwan): Handle undefined behaviour - return; - } - block( - ctx, - "static const auto generate_fns = " - "std::unordered_map", - [&] { - for(const auto& component : details.generate_comps) { - for(const auto& [comp_id, requirements] : component) { - auto type_name = cpp_identifier(decl_full_name(comp_id)); - ctx.write( - "{", - type_name, - "::id, &wrapper::dynamic::context_generate_add<", - type_name, - "> }," - ); - } - } - } - ); - ctx.write(";\n"); - - // NOTE(Kelwan): Multiple generates blocks are allowed in Ecsact systems but - // currently the interpreter won't allow this. More testing required after the - // issue is resolved https://github.com/ecsact-dev/ecsact_interpret/issues/185 - ctx.write("auto entity = registry->create();\n"); - - ctx.write( - "registry->template emplace(entity, " - "ecsact_generated_entity);\n" - ); - - block(ctx, "for(int i = 0; i < component_count; ++i)", [&] { - ctx.write("const auto component_id = component_ids[i];\n"); - ctx.write("const void* component_data = components_data[i];\n"); + auto result = std::ranges::find_if(system_providers, [&](auto provider) { + return provider->context_function_generate(ctx, names) == + handle_exclusive_provide::HANDLED; + }); - ctx.write( - "generate_fns.at(component_id)(this, component_id, " - "component_data, entity);\n" + if(result == system_providers.end()) { + throw std::logic_error("print context generate was not handled by providers" ); - }); + } } static auto print_sys_exec_ctx_parent( // - ecsact::codegen_plugin_context& ctx + ecsact::codegen_plugin_context& ctx, + const common_vars names, + system_provider_t system_providers ) -> void { - using ecsact::rt_entt_codegen::util::method_printer; - auto printer = // method_printer{ctx, "parent"} // .return_type("const ecsact_system_execution_context* final"); - ctx.write("return this->parent_ctx;\n"); + auto result = std::ranges::find_if(system_providers, [&](auto provider) { + return provider->context_function_parent(ctx, names) == + handle_exclusive_provide::HANDLED; + }); + + if(result == system_providers.end()) { + throw std::logic_error("print context parent was not handled by providers"); + } } -static auto print_sys_exec_ctx_other( - ecsact::codegen_plugin_context& ctx, - const ecsact::rt_entt_codegen::ecsact_entt_system_details& details +auto print_sys_exec_ctx_other( + ecsact::codegen_plugin_context& ctx, + const common_vars names, + system_provider_t system_providers ) -> void { - using ecsact::rt_entt_codegen::util::method_printer; - auto printer = // method_printer{ctx, "other"} .parameter("ecsact_entity_id", "entity") .return_type("ecsact_system_execution_context* final"); - if(details.association_details.size() == 0) { - // TODO(Kelwan): Handle undefined behaviour - // Attempt to access other without association + auto result = std::ranges::find_if(system_providers, [&](auto provider) { + return provider->context_function_other(ctx, names) == + handle_exclusive_provide::HANDLED; + }); - ctx.write("return nullptr;"); - return; + if(result == system_providers.end()) { + throw std::logic_error("print context other was not handled by providers"); } - - ctx.write( - "if(other_contexts.contains(entity)) {\n", - "return other_contexts.at(entity);\n}\n" - ); - // NOTE(Kelwan): Maybe we handle undefined behaviour here too - ctx.write("return nullptr;"); } template @@ -531,9 +236,6 @@ static auto print_apply_pendings( SystemLikeID sys_like_id, std::string registry_name ) -> void { - using ecsact::cc_lang_support::cpp_identifier; - using ecsact::meta::decl_full_name; - auto add_comps = system_comps_with_caps(sys_like_id, ECSACT_SYS_CAP_ADDS); for(auto comp_id : add_comps) { @@ -578,393 +280,155 @@ static auto print_apply_pendings( } } -static auto print_other_contexts( - ecsact::codegen_plugin_context& ctx, - const ecsact::rt_entt_codegen::ecsact_entt_system_details& details, - const ecsact::rt_entt_codegen::core::print_execute_systems_options options -) -> std::map { - using ecsact::cc_lang_support::cpp_identifier; - using ecsact::cpp_codegen_plugin_util::block; - using ecsact::meta::component_name; - using ecsact::meta::decl_full_name; - using ecsact::meta::get_child_system_ids; - using ecsact::rt_entt_codegen::ecsact_entt_system_details; - using ecsact::rt_entt_codegen::other_key; - using ecsact::rt_entt_codegen::system_util::create_context_struct_name; - using ecsact::rt_entt_codegen::system_util::create_context_var_name; - using ecsact::rt_entt_codegen::system_util::get_unique_view_name; - using ecsact::rt_entt_codegen::util::method_printer; - - std::map other_views; - - for(auto& assoc_detail : details.association_details) { - auto struct_name = create_context_struct_name(assoc_detail.component_id); - auto struct_header = struct_name + " : ecsact_system_execution_context "; - - auto view_name = get_unique_view_name(); - other_views.insert( - other_views.end(), - std::pair( - other_key{ - .component_like_id = assoc_detail.component_id, - .field_id = assoc_detail.field_id // - }, - view_name - ) - ); - - auto other_details = - ecsact_entt_system_details::from_capabilities(assoc_detail.capabilities); - - ecsact::rt_entt_codegen::util::make_view( - ctx, - view_name, - "registry", - other_details - ); - - ctx.write(std::format("using {}_t = decltype({});\n", view_name, view_name) - ); - - block(ctx, "struct " + struct_header, [&] { - using namespace std::string_literals; - using ecsact::rt_entt_codegen::util::decl_cpp_ident; - using std::views::transform; +static auto print_system_execution_context( + ecsact::codegen_plugin_context& ctx, + system_like_id_variant sys_like_id, + const common_vars names, + system_provider_t system_providers +) -> void { + auto system_name = cpp_identifier(decl_full_name(sys_like_id)); - ctx.write(std::format("{}_t* view;\n", view_name)); - ctx.write("\n"); - print_sys_exec_ctx_action(ctx, other_details, options); - print_sys_exec_ctx_add(ctx, other_details, assoc_detail.capabilities); - print_sys_exec_ctx_remove( - ctx, - other_details, - assoc_detail.capabilities, - view_name - ); - print_sys_exec_ctx_get(ctx, other_details, view_name); - print_sys_exec_ctx_update(ctx, other_details, view_name); - print_sys_exec_ctx_has(ctx, other_details); - print_sys_exec_ctx_generate(ctx, other_details); - print_sys_exec_ctx_parent(ctx); - print_sys_exec_ctx_other(ctx, other_details); - }); - ctx.write(";\n\n"); + block(ctx, "struct : ecsact_system_execution_context ", [&] { + ctx.write("view_t* view;\n"); - auto type_name = cpp_identifier(decl_full_name(assoc_detail.component_id)); - auto context_name = create_context_var_name(assoc_detail.component_id); + for(const auto& provider : system_providers) { + provider->context_function_header(ctx, names); + } - ctx.write(struct_name, " ", context_name, ";\n\n"); + ctx.write("\n"); + print_sys_exec_ctx_action(ctx, names, system_providers); + print_sys_exec_ctx_add(ctx, names, system_providers); + print_sys_exec_ctx_remove(ctx, names, system_providers); + print_sys_exec_ctx_get(ctx, names, system_providers); + print_sys_exec_ctx_update(ctx, names, system_providers); + print_sys_exec_ctx_has(ctx, names, system_providers); + print_sys_exec_ctx_generate(ctx, names, system_providers); + print_sys_exec_ctx_parent(ctx, names, system_providers); + print_sys_exec_ctx_other(ctx, names, system_providers); + }); + ctx.write("context;\n\n"); - ctx.write(context_name, ".view = &", view_name, ";\n"); - ctx.write(context_name, ".parent_ctx = nullptr;\n\n"); - ctx.write(context_name, ".registry = &", options.registry_var_name, ";\n"); + ctx.write("context.registry = &", names.registry_var_name, ";\n"); + if(names.action_var_name) { + ctx.write("context.action_data = ", *names.action_var_name, ";\n\n"); } - return other_views; + ctx.write( + "context.id = ecsact_id_cast(::", + system_name, + "::id);\n" + ); + ctx.write("context.parent_ctx = ", names.parent_context_var_name, ";\n"); + ctx.write("context.view = &view;\n\n"); } -static auto print_execute_systems( - ecsact::codegen_plugin_context& ctx, - const ecsact::rt_entt_codegen::ecsact_entt_details& details, - const ecsact::rt_entt_codegen::ecsact_entt_system_details& sys_details, - const ecsact::rt_entt_codegen::core::print_execute_systems_options options -) -> void { - using ecsact::cc_lang_support::cpp_identifier; - using ecsact::cpp_codegen_plugin_util::block; - using ecsact::meta::decl_full_name; - using ecsact::rt_entt_codegen::ecsact_entt_system_details; - using ecsact::rt_entt_codegen::system_util::create_context_struct_name; - using ecsact::rt_entt_codegen::system_util::create_context_var_name; +static auto setup_system_providers(system_like_id_variant sys_like_id +) -> system_provider_t { + using ecsact::rt_entt_codegen::core::provider::association; + using ecsact::rt_entt_codegen::core::provider::basic; + using ecsact::rt_entt_codegen::core::provider::lazy; + using ecsact::rt_entt_codegen::core::provider::notify; using ecsact::rt_entt_codegen::system_util::is_notify_system; - using ecsact::rt_entt_codegen::system_util::print_system_notify_views; - using ecsact::rt_entt_codegen::util::method_printer; - auto sys_caps = ecsact::meta::system_capabilities(options.get_sys_like_id()); - auto lazy_iteration_rate = 0; + assert(sys_like_id != system_like_id_variant{}); - auto exec_start_label_name = - std::format("exec_start_{}_", static_cast(options.get_sys_like_id())); + system_provider_t system_providers{}; - auto pending_lazy_exec_struct = std::format( - "::ecsact::entt::detail::pending_lazy_execution<::{}>", - options.system_name - ); + auto sys_details = ecsact_entt_system_details::from_system_like(sys_like_id); - auto system_sorting_struct_name = std::format( - "::ecsact::entt::detail::system_sorted<{}>", - options.system_name - ); + int lazy_iteration_rate = 0; - auto additional_view_components = std::vector{}; + if(sys_like_id.is_system()) { + lazy_iteration_rate = + ecsact_meta_get_lazy_iteration_rate(sys_like_id.as_system()); + } - if(options.is_system()) { - lazy_iteration_rate = ecsact_meta_get_lazy_iteration_rate( - static_cast(options.get_sys_like_id()) - ); + if(is_notify_system(sys_like_id)) { + system_providers.push_back(std::make_shared(sys_like_id)); } if(lazy_iteration_rate > 0) { - ctx.write( - "constexpr auto lazy_iteration_rate_ = ", - lazy_iteration_rate, - ";\n\n" - ); - ctx.write("auto iteration_count_ = 0;\n\n"); - ctx.write(exec_start_label_name, ":\n"); - additional_view_components.push_back(pending_lazy_exec_struct); + system_providers.push_back(std::make_shared(sys_like_id)); } - if(options.is_system()) { - if(system_needs_sorted_entities(options.as_system())) { - additional_view_components.push_back(system_sorting_struct_name); - } + if(!sys_details.association_details.empty()) { + system_providers.push_back(std::make_shared(sys_like_id)); } - if(is_notify_system(options.get_sys_like_id())) { - additional_view_components.push_back( - std::format("ecsact::entt::detail::run_system<{}>", options.system_name) - ); - print_system_notify_views( - ctx, - sys_details, - options.get_sys_like_id(), - options.registry_var_name - ); + system_providers.push_back(std::make_shared(sys_like_id)); + + return system_providers; +} + +static auto print_execute_systems( + ecsact::codegen_plugin_context& ctx, + system_like_id_variant sys_like_id, + const common_vars names +) -> void { + auto sys_caps = ecsact::meta::system_capabilities(sys_like_id); + auto system_providers = setup_system_providers(sys_like_id); + + for(const auto& provider : system_providers) { + provider->initialization(ctx, names); + } + + auto additional_view_components = std::vector{}; + for(const auto& provider : system_providers) { + provider->before_make_view_or_group(ctx, names, additional_view_components); } + auto sys_details = ecsact_entt_system_details::from_system_like(sys_like_id); + ecsact::rt_entt_codegen::util::make_view( ctx, "view", - options.registry_var_name, + names.registry_var_name, sys_details, additional_view_components ); ctx.write("using view_t = decltype(view);\n"); - if(options.is_system()) { - if(system_needs_sorted_entities(options.as_system())) { - ctx.write("view.use<", system_sorting_struct_name, ">();\n"); - } - } + print_system_execution_context(ctx, sys_like_id, names, system_providers); - block(ctx, "struct : ecsact_system_execution_context ", [&] { - ctx.write("view_t* view;\n"); - - ctx.write( - "std::unordered_map " - "other_contexts;\n\n" - ); - - if(options.action_var_name) { - ctx.write("const void* action_data = nullptr;\n"); - } - - ctx.write("\n"); - print_sys_exec_ctx_action(ctx, sys_details, options); - print_sys_exec_ctx_add(ctx, sys_details, sys_caps); - print_sys_exec_ctx_remove(ctx, sys_details, sys_caps, "view"); - print_sys_exec_ctx_get(ctx, sys_details, "view"); - print_sys_exec_ctx_update(ctx, sys_details, "view"); - print_sys_exec_ctx_has(ctx, sys_details); - print_sys_exec_ctx_generate(ctx, sys_details); - print_sys_exec_ctx_parent(ctx); - print_sys_exec_ctx_other(ctx, sys_details); - }); - ctx.write("context;\n\n"); - - ctx.write("context.registry = &", options.registry_var_name, ";\n"); - if(options.action_var_name) { - ctx.write("context.action_data = ", *options.action_var_name, ";\n\n"); + for(const auto& provider : system_providers) { + provider->after_make_view_or_group(ctx, names); } - ctx.write( - "context.id = ecsact_id_cast(::", - options.system_name, - "::id);\n" - ); - ctx.write("context.parent_ctx = ", options.parent_context_var_name, ";\n"); - ctx.write("context.view = &view;\n\n"); - - auto other_view_names = print_other_contexts(ctx, sys_details, options); + for(const auto& provider : system_providers) { + provider->pre_entity_iteration(ctx, names); + } block(ctx, "for(ecsact::entt::entity_id entity : view)", [&] { - if(lazy_iteration_rate > 0) { - block(ctx, "if(iteration_count_ == lazy_iteration_rate_)", [&] { - ctx.write("break;\n"); - }); - - ctx.write("++iteration_count_;\n"); - ctx.write( - options.registry_var_name, - ".erase<", - pending_lazy_exec_struct, - ">(entity);\n" - ); - } - - // value = comp var name - auto components_with_entity_fields = - std::map{}; - - int comp_iter = 0; - - for(auto [ids, view_name] : other_view_names) { - if(!components_with_entity_fields.contains(ids.component_like_id)) { - components_with_entity_fields[ids.component_like_id] = - "assoc_comp_" + std::to_string(comp_iter++); - } - } - - for(auto&& [comp_like_id, comp_var] : components_with_entity_fields) { - auto comp_name = cpp_identifier(decl_full_name(comp_like_id)); - ctx.write("auto ", comp_var, " = view.get<", comp_name, ">(entity);\n"); - } - ctx.write("context.entity = entity;\n"); - ecsact::rt_entt_codegen::core::print_child_systems( - ctx, - details, - sys_details, - options - ); + ecsact::rt_entt_codegen::core::print_child_systems(ctx, names, sys_like_id); - if(!other_view_names.empty()) { - ctx.write("auto found_assoc_entities = 0;\n"); + for(const auto& provider : system_providers) { + provider->pre_exec_system_impl(ctx, names); } - for(auto [ids, view_name] : other_view_names) { - auto field_name = ecsact_meta_field_name( - ecsact_id_cast(ids.component_like_id), - ids.field_id - ); - - auto entity_field_access = - components_with_entity_fields.at(ids.component_like_id) + "." + - field_name; - - auto view_itr_name = view_name + "_itr"; - ctx.write( - "auto ", - view_itr_name, - " = ", - view_name, - ".find(ecsact::entt::entity_id{", - entity_field_access, - "});\n" - ); - - ctx.write( - "if(", - view_itr_name, - " == ", - view_name, - ".end()) { continue; }\n" - ); - - ctx.write("found_assoc_entities += 1;\n"); - - auto context_name = create_context_var_name(ids.component_like_id); - ctx.write(context_name, ".entity = ", entity_field_access, ";\n"); + auto result = std::ranges::find_if(system_providers, [&](auto provider) { + return provider->system_impl(ctx, names) == + handle_exclusive_provide::HANDLED; + }); - ctx.write( - "context.other_contexts.insert(context.other_contexts.end(), " - "std::pair(", - context_name, - ".entity, &", - context_name, - "));\n" - ); + if(result == system_providers.end()) { + throw std::logic_error("system_impl was not handled by providers"); } - if(other_view_names.empty()) { - ctx.write("system_impl(&context);\n"); - } else { - // we need to check if we found any invalid associations - block( - ctx, - "if(found_assoc_entities == " + - std::to_string(other_view_names.size()) + ")", - [&] { ctx.write("system_impl(&context);\n"); } - ); + for(const auto& provider : system_providers) { + provider->post_exec_system_impl(ctx, names); } ctx.write("\n"); }); - if(lazy_iteration_rate > 0) { - ctx.write( - "// If this assertion triggers that's a ecsact_rt_entt codegen " - "failure\n" - ); - ctx.write("assert(iteration_count_ <= lazy_iteration_rate_);\n"); - block(ctx, "if(iteration_count_ < lazy_iteration_rate_)", [&] { - ctx.write( - "_recalc_sorting_hash<", - options.system_name, - ">(", - options.registry_var_name, - ");\n" - ); - ctx.write( - options.registry_var_name, - ".sort<", - system_sorting_struct_name, - ">([](const auto& a, const auto& b) { return a.hash < b.hash; });\n" - ); - - ecsact::rt_entt_codegen::util::make_view( - ctx, - "view_no_pending_lazy_", - options.registry_var_name, - sys_details - ); - - ctx.write("auto view_no_pending_lazy_count_ = 0;\n"); - - block( - ctx, - "for(ecsact::entt::entity_id entity : view_no_pending_lazy_)", - [&] { - ctx.write( - "// If this assertion triggers this is an indicator of a codegen " - "failure.\n" - "// Please report to " - "https://github.com/ecsact-dev/ecsact_rt_entt\n" - ); - ctx.write( - "assert(", - options.registry_var_name, - ".all_of<", - system_sorting_struct_name, - ">(entity));\n" - ); - ctx.write("view_no_pending_lazy_count_ += 1;\n"); - ctx.write( - options.registry_var_name, - ".emplace<", - pending_lazy_exec_struct, - ">(entity);\n" - ); - } - ); - - block( - ctx, - "if(view_no_pending_lazy_count_ >= lazy_iteration_rate_)", - [&] { ctx.write("goto ", exec_start_label_name, ";\n"); } - ); - }); + for(const auto& provider : system_providers) { + provider->post_iteration(ctx, names); } - print_apply_pendings( - ctx, - sys_details, - options.get_sys_like_id(), - options.registry_var_name - ); + print_apply_pendings(ctx, sys_details, sys_like_id, names.registry_var_name); } static auto print_trivial_system_like( @@ -972,17 +436,10 @@ static auto print_trivial_system_like( const ecsact::rt_entt_codegen::ecsact_entt_system_details& details, ecsact_system_like_id system_like_id ) -> void { - using ecsact::cc_lang_support::cpp_identifier; - using ecsact::cpp_codegen_plugin_util::block; - - using ecsact::meta::decl_full_name; using ecsact::meta::get_field_ids; using ecsact::meta::system_capabilities; - using ecsact::rt_entt_codegen::util::method_printer; - auto system_name = cpp_identifier(decl_full_name(system_like_id)); - auto sys_capabilities = system_capabilities(system_like_id); ctx.write("template<>\n"); @@ -1022,18 +479,13 @@ static auto print_trivial_system_like( } static auto print_execute_system_template_specialization( - ecsact::codegen_plugin_context& ctx, - const ecsact::rt_entt_codegen::ecsact_entt_details& details, - const ecsact::rt_entt_codegen::ecsact_entt_system_details& sys_details, - ecsact_system_id system_id + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::ecsact_entt_details& details, + ecsact_system_id system_id ) -> void { - using ecsact::cc_lang_support::cpp_identifier; - using ecsact::cpp_codegen_plugin_util::block; - using ecsact::meta::decl_full_name; - using ecsact::rt_entt_codegen::core::system_like_id_variant_t; - using ecsact::rt_entt_codegen::system_util::is_trivial_system; - - using ecsact::rt_entt_codegen::util::method_printer; + auto sys_details = ecsact_entt_system_details::from_system_like( + ecsact_id_cast(system_id) + ); if(is_trivial_system(ecsact_id_cast(system_id))) { print_trivial_system_like( @@ -1063,11 +515,8 @@ static auto print_execute_system_template_specialization( print_execute_systems( ctx, - details, - sys_details, + system_id, { - .sys_like_id = system_id, - .system_name = system_name, .registry_var_name = "registry", .parent_context_var_name = "parent_context", .action_var_name = std::nullopt, @@ -1076,16 +525,13 @@ static auto print_execute_system_template_specialization( } static auto print_execute_actions_template_specialization( - ecsact::codegen_plugin_context& ctx, - const ecsact::rt_entt_codegen::ecsact_entt_details& details, - const ecsact::rt_entt_codegen::ecsact_entt_system_details& sys_details, - ecsact_action_id action_id + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::ecsact_entt_details& details, + ecsact_action_id action_id ) -> void { - using ecsact::cc_lang_support::cpp_identifier; - using ecsact::cpp_codegen_plugin_util::block; - using ecsact::meta::decl_full_name; - using ecsact::rt_entt_codegen::system_util::is_trivial_system; - using ecsact::rt_entt_codegen::util::method_printer; + auto sys_details = ecsact_entt_system_details::from_system_like( + ecsact_id_cast(action_id) + ); if(is_trivial_system(ecsact_id_cast(action_id))) { print_trivial_system_like( @@ -1126,11 +572,8 @@ static auto print_execute_actions_template_specialization( block(ctx, "for(auto action : actions)", [&] { print_execute_systems( ctx, - details, - sys_details, + action_id, { - .sys_like_id = action_id, - .system_name = cpp_system_name, .registry_var_name = "registry", .parent_context_var_name = "nullptr", .action_var_name = "action", @@ -1145,17 +588,10 @@ static auto print_child_execution_system_like_template_specializations( const ecsact::rt_entt_codegen::ecsact_entt_details& details, SystemLikeID sys_like_id ) -> void { - using ecsact::rt_entt_codegen::ecsact_entt_system_details; - for(auto child_sys_id : ecsact::meta::get_child_system_ids(sys_like_id)) { - auto child_sys_details = ecsact_entt_system_details::from_system_like( - static_cast(child_sys_id) - ); - print_execute_system_template_specialization( ctx, details, - child_sys_details, static_cast(child_sys_id) ); @@ -1172,14 +608,7 @@ auto ecsact::rt_entt_codegen::core:: codegen_plugin_context& ctx, const ecsact_entt_details& details ) -> void { - using ecsact::cc_lang_support::cpp_identifier; - using ecsact::rt_entt_codegen::ecsact_entt_system_details; - using ecsact::rt_entt_codegen::util::method_printer; - for(auto sys_like_id : details.top_execution_order) { - auto sys_details = - ecsact_entt_system_details::from_system_like(sys_like_id); - print_child_execution_system_like_template_specializations( ctx, details, @@ -1190,14 +619,12 @@ auto ecsact::rt_entt_codegen::core:: print_execute_system_template_specialization( ctx, details, - sys_details, static_cast(sys_like_id) ); } else if(details.is_action(sys_like_id)) { print_execute_actions_template_specialization( ctx, details, - sys_details, static_cast(sys_like_id) ); } diff --git a/rt_entt_codegen/core/sys_exec/BUILD.bazel b/rt_entt_codegen/core/sys_exec/BUILD.bazel index 8ed692a..b781386 100644 --- a/rt_entt_codegen/core/sys_exec/BUILD.bazel +++ b/rt_entt_codegen/core/sys_exec/BUILD.bazel @@ -10,6 +10,7 @@ cc_library( deps = [ "//rt_entt_codegen/shared:ecsact_entt_details", "//rt_entt_codegen/shared:parallel", + "//rt_entt_codegen/shared:system_variant", "//rt_entt_codegen/shared:util", "@ecsact_lang_cpp//:cpp_codegen_plugin_util", ], diff --git a/rt_entt_codegen/core/sys_exec/sys_exec.cc b/rt_entt_codegen/core/sys_exec/sys_exec.cc index 2c62bd2..c6b3ec0 100644 --- a/rt_entt_codegen/core/sys_exec/sys_exec.cc +++ b/rt_entt_codegen/core/sys_exec/sys_exec.cc @@ -1,42 +1,29 @@ #include "sys_exec.hh" -#include "rt_entt_codegen/shared/util.hh" #include "rt_entt_codegen/shared/ecsact_entt_details.hh" - -static auto exec_start_label_name = std::string{}; +#include "ecsact/lang-support/lang-cc.hh" +#include "ecsact/runtime/meta.hh" +#include "rt_entt_codegen/shared/parallel.hh" auto ecsact::rt_entt_codegen::core::print_child_systems( - ecsact::codegen_plugin_context& ctx, - const ecsact::rt_entt_codegen::ecsact_entt_details& details, - const ecsact::rt_entt_codegen::ecsact_entt_system_details& sys_details, - const ecsact::rt_entt_codegen::core::print_execute_systems_options options + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names, + const ecsact::rt_entt_codegen::system_like_id_variant& sys_like_id + ) -> void { using ecsact::cc_lang_support::cpp_identifier; using ecsact::meta::decl_full_name; using ecsact::meta::get_child_system_ids; using ecsact::rt_entt_codegen::ecsact_entt_system_details; + using ecsact::rt_entt_codegen::system_like_id_variant; - auto child_system_ids = - ecsact::meta::get_child_system_ids(options.get_sys_like_id()); - - std::vector child_system_like_ids{}; - - child_system_like_ids.resize(child_system_ids.size()); - - std::transform( - child_system_ids.begin(), - child_system_ids.end(), - child_system_like_ids.begin(), - [](auto system_id) { - return ecsact_id_cast(system_id); - } - ); + auto child_system_ids = ecsact::meta::get_child_system_ids(sys_like_id); if(child_system_ids.size() == 1) { // TODO(Kelwan): Make use case system agnostic when we support // nested Action systems // Issue: https://github.com/ecsact-dev/ecsact_parse/issues/154 - for(auto child_sys_id : get_child_system_ids(options.get_sys_like_id())) { + for(auto child_sys_id : get_child_system_ids(sys_like_id)) { auto child_details = ecsact_entt_system_details::from_system_like( ecsact_id_cast(child_sys_id) ); @@ -45,7 +32,7 @@ auto ecsact::rt_entt_codegen::core::print_child_systems( ctx.write( "ecsact::entt::execute_system<::" + child_system_name + ">(", - options.registry_var_name, + names.registry_var_name, ", &context, {});\n" ); } @@ -53,63 +40,16 @@ auto ecsact::rt_entt_codegen::core::print_child_systems( auto parallel_system_cluster = ecsact::rt_entt_codegen::parallel::get_parallel_execution_cluster( ctx, - details, - child_system_like_ids - ); - - for(const auto& systems_to_parallel : parallel_system_cluster) { - if(systems_to_parallel.size() == 1) { - auto sync_sys_id = systems_to_parallel[0]; - - auto sync_sys_name = - cpp_identifier(ecsact::meta::decl_full_name(sync_sys_id)); - - if(details.is_action(sync_sys_id)) { - ctx.write(std::format( - "ecsact::entt::execute_actions<{}>(registry, {}, " - "actions_map);\n", - sync_sys_name, - "parent_context" - )); + std::vector{ + child_system_ids.begin(), + child_system_ids.end() } - if(details.is_system(sync_sys_id)) { - ctx.write(std::format( - "ecsact::entt::execute_system<{}>(registry, {}, " - "actions_map);\n", - sync_sys_name, - "parent_context" - )); - } - continue; - } - - ctx.write("execute_parallel_cluster(registry, parent_context, "); - ctx.write(std::format( - "std::array {{\n", - systems_to_parallel.size() - )); - for(const auto system_like_id : systems_to_parallel) { - auto cpp_decl_name = - cpp_identifier(ecsact::meta::decl_full_name(system_like_id)); + ); - if(details.is_action(system_like_id)) { - ctx.write( - "\texec_entry_t{&ecsact::entt::execute_actions<", - cpp_decl_name, - ">, actions_map},\n" - ); - } else if(details.is_system(system_like_id)) { - ctx.write( - "\texec_entry_t{&ecsact::entt::execute_system<", - cpp_decl_name, - ">, actions_map},\n" - ); - } else { - ctx.write("// ??? unhandled ??? ", cpp_decl_name, "\n"); - } - } - ctx.write("});\n"); - } + ecsact::rt_entt_codegen::parallel::print_parallel_execution_cluster( + ctx, + parallel_system_cluster + ); } ctx.write("\n"); diff --git a/rt_entt_codegen/core/sys_exec/sys_exec.hh b/rt_entt_codegen/core/sys_exec/sys_exec.hh index e1cd738..9cb8cf4 100644 --- a/rt_entt_codegen/core/sys_exec/sys_exec.hh +++ b/rt_entt_codegen/core/sys_exec/sys_exec.hh @@ -2,57 +2,22 @@ #include #include -#include -#include -#include "rt_entt_codegen/shared/ecsact_entt_details.hh" -#include "ecsact/lang-support/lang-cc.hh" -#include "rt_entt_codegen/shared/parallel.hh" -#include "ecsact/cpp_codegen_plugin_util.hh" +#include "rt_entt_codegen/shared/system_variant.hh" #include "ecsact/codegen/plugin.hh" -#include "ecsact/runtime/meta.hh" namespace ecsact::rt_entt_codegen::core { -using system_like_id_variant_t = - std::variant; - -struct print_execute_systems_options { - system_like_id_variant_t sys_like_id; - std::string system_name; - std::string registry_var_name; - std::string parent_context_var_name; +struct common_vars { + std::string registry_var_name; + std::string parent_context_var_name; /// only set if system is an action std::optional action_var_name; - - auto as_system() const -> ecsact_system_id { - return std::get(sys_like_id); - } - - auto as_action() const -> ecsact_action_id { - return std::get(sys_like_id); - } - - auto is_system() const -> bool { - return std::holds_alternative(sys_like_id); - } - - auto is_action() const -> bool { - return std::holds_alternative(sys_like_id); - } - - auto get_sys_like_id() const -> ecsact_system_like_id { - return std::visit( - [](auto&& arg) { return static_cast(arg); }, - sys_like_id - ); - } }; auto print_child_systems( - ecsact::codegen_plugin_context& ctx, - const ecsact::rt_entt_codegen::ecsact_entt_details& details, - const ecsact::rt_entt_codegen::ecsact_entt_system_details& sys_details, - const ecsact::rt_entt_codegen::core::print_execute_systems_options options + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names, + const system_like_id_variant& sys_like_id ) -> void; } // namespace ecsact::rt_entt_codegen::core diff --git a/rt_entt_codegen/core/system_notify.cc b/rt_entt_codegen/core/system_notify.cc index b116f94..782a89d 100644 --- a/rt_entt_codegen/core/system_notify.cc +++ b/rt_entt_codegen/core/system_notify.cc @@ -2,6 +2,7 @@ #include "ecsact/lang-support/lang-cc.hh" #include "ecsact/cpp_codegen_plugin_util.hh" #include "rt_entt_codegen/shared/system_util.hh" +#include "rt_entt_codegen/shared/util.hh" auto ecsact::rt_entt_codegen::core::print_cleanup_system_notifies( codegen_plugin_context& ctx, diff --git a/rt_entt_codegen/core/system_provider/BUILD.bazel b/rt_entt_codegen/core/system_provider/BUILD.bazel new file mode 100644 index 0000000..daf2852 --- /dev/null +++ b/rt_entt_codegen/core/system_provider/BUILD.bazel @@ -0,0 +1,85 @@ +load("@rules_cc//cc:defs.bzl", "cc_library") +load("//bazel:copts.bzl", "copts") + +cc_library( + name = "system_provider", + srcs = ["system_provider.cc"], + hdrs = ["system_provider.hh"], + copts = copts, + visibility = ["//rt_entt_codegen/core:__pkg__"], + deps = [ + "//rt_entt_codegen/core/sys_exec", + "//rt_entt_codegen/shared:ecsact_entt_details", + "//rt_entt_codegen/shared:system_variant", + ], +) + +cc_library( + name = "association", + srcs = ["association/association.cc"], + hdrs = ["association/association.hh"], + copts = copts, + visibility = ["//rt_entt_codegen/core:__pkg__"], + deps = [ + ":system_ctx_functions", + ":system_provider", + "//rt_entt_codegen/core/sys_exec", + "//rt_entt_codegen/shared:ecsact_entt_details", + "//rt_entt_codegen/shared:system_util", + ], +) + +cc_library( + name = "basic", + srcs = ["basic/basic.cc"], + hdrs = ["basic/basic.hh"], + copts = copts, + visibility = ["//rt_entt_codegen/core:__pkg__"], + deps = [ + ":system_ctx_functions", + ":system_provider", + "//rt_entt_codegen/core/sys_exec", + "//rt_entt_codegen/shared:ecsact_entt_details", + "//rt_entt_codegen/shared:util", + ], +) + +cc_library( + name = "notify", + srcs = ["notify/notify.cc"], + hdrs = ["notify/notify.hh"], + copts = copts, + visibility = ["//rt_entt_codegen/core:__pkg__"], + deps = [ + ":system_provider", + "//rt_entt_codegen/core/sys_exec", + "//rt_entt_codegen/shared:system_util", + ], +) + +cc_library( + name = "lazy", + srcs = ["lazy/lazy.cc"], + hdrs = ["lazy/lazy.hh"], + copts = copts, + visibility = ["//rt_entt_codegen/core:__pkg__"], + deps = [ + ":system_provider", + "//rt_entt_codegen/core/sys_exec", + "//rt_entt_codegen/shared:ecsact_entt_details", + "//rt_entt_codegen/shared:sorting", + ], +) + +cc_library( + name = "system_ctx_functions", + srcs = ["system_ctx_functions.cc"], + hdrs = ["system_ctx_functions.hh"], + copts = copts, + visibility = ["//rt_entt_codegen/core:__pkg__"], + deps = [ + "//rt_entt_codegen/core/sys_exec", + "//rt_entt_codegen/shared:ecsact_entt_details", + "//rt_entt_codegen/shared:system_variant", + ], +) diff --git a/rt_entt_codegen/core/system_provider/association/association.cc b/rt_entt_codegen/core/system_provider/association/association.cc new file mode 100644 index 0000000..2a99ff7 --- /dev/null +++ b/rt_entt_codegen/core/system_provider/association/association.cc @@ -0,0 +1,331 @@ +#include "association.hh" + +#include + +#include "ecsact/lang-support/lang-cc.hh" +#include "rt_entt_codegen/shared/system_util.hh" +#include "rt_entt_codegen/shared/util.hh" +#include "ecsact/runtime/meta.hh" +#include "ecsact/cpp_codegen_plugin_util.hh" + +using capability_t = + std::unordered_map; + +using namespace ecsact::rt_entt_codegen::core; + +auto provider::association::context_function_header( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names +) -> void { + ctx.write( + "std::unordered_map " + "other_contexts;\n\n" + ); +} + +auto provider::association::after_make_view_or_group( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names +) -> void { +} + +auto provider::association::context_function_other( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names +) -> handle_exclusive_provide { + context_other_impl(ctx, sys_like_id, system_details); + return HANDLED; +} + +auto provider::association::pre_entity_iteration( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names +) -> void { + print_other_contexts(ctx, names); +} + +auto provider::association::pre_exec_system_impl( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names +) -> void { + using ecsact::cc_lang_support::cpp_identifier; + using ecsact::meta::decl_full_name; + using ecsact::rt_entt_codegen::system_util::create_context_var_name; + + int comp_iter = 0; + + for(auto [ids, view_name] : other_view_names) { + if(!components_with_entity_fields.contains(ids.component_like_id)) { + components_with_entity_fields[ids.component_like_id] = + "assoc_comp_" + std::to_string(comp_iter++); + } + } + + for(auto&& [comp_like_id, comp_var] : components_with_entity_fields) { + auto comp_name = cpp_identifier(decl_full_name(comp_like_id)); + ctx.write("auto ", comp_var, " = view.get<", comp_name, ">(entity);\n"); + } + + ctx.write("auto found_assoc_entities = 0;\n"); + + for(auto [ids, view_name] : other_view_names) { + auto field_name = ecsact_meta_field_name( + ecsact_id_cast(ids.component_like_id), + ids.field_id + ); + + auto entity_field_access = + components_with_entity_fields.at(ids.component_like_id) + "." + + field_name; + + auto view_itr_name = view_name + "_itr"; + ctx.write( + "auto ", + view_itr_name, + " = ", + view_name, + ".find(ecsact::entt::entity_id{", + entity_field_access, + "});\n" + ); + + ctx.write( + "if(", + view_itr_name, + " == ", + view_name, + ".end()) { continue; }\n" + ); + + ctx.write("found_assoc_entities += 1;\n"); + + auto context_name = create_context_var_name(ids.component_like_id); + ctx.write(context_name, ".entity = ", entity_field_access, ";\n"); + + ctx.write( + "context.other_contexts.insert(context.other_contexts.end(), " + "std::pair(", + context_name, + ".entity, &", + context_name, + "));\n" + ); + } +} + +auto provider::association::system_impl( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names +) -> handle_exclusive_provide { + using ecsact::cpp_codegen_plugin_util::block; + + // we need to check if we found any invalid associations + block( + ctx, + "if(found_assoc_entities == " + std::to_string(other_view_names.size()) + + ")", + [&] { ctx.write("system_impl(&context);\n"); } + ); + return HANDLED; +} + +auto provider::association::print_other_contexts( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names +) -> void { + using ecsact::cc_lang_support::cpp_identifier; + using ecsact::cpp_codegen_plugin_util::block; + using ecsact::meta::component_name; + using ecsact::meta::decl_full_name; + using ecsact::meta::get_child_system_ids; + using ecsact::rt_entt_codegen::ecsact_entt_system_details; + using ecsact::rt_entt_codegen::other_key; + using ecsact::rt_entt_codegen::system_util::create_context_struct_name; + using ecsact::rt_entt_codegen::system_util::create_context_var_name; + using ecsact::rt_entt_codegen::system_util::get_unique_view_name; + using ecsact::rt_entt_codegen::util::method_printer; + + for(auto& assoc_detail : system_details.association_details) { + auto struct_name = create_context_struct_name(assoc_detail.component_id); + auto context_name = create_context_var_name(assoc_detail.component_id); + + auto struct_header = struct_name + " : ecsact_system_execution_context "; + + auto view_type_name = get_unique_view_name(); + other_view_names.insert( + other_view_names.end(), + std::pair( + other_key{ + .component_like_id = assoc_detail.component_id, + .field_id = assoc_detail.field_id // + }, + view_type_name + ) + ); + + auto other_details = + ecsact_entt_system_details::from_capabilities(assoc_detail.capabilities); + + ecsact::rt_entt_codegen::util::make_view( + ctx, + view_type_name, + "registry", + other_details + ); + + ctx.write(std::format( + "using {}_t = decltype({});\n", + view_type_name, + view_type_name + )); + + block(ctx, "struct " + struct_header, [&] { + using namespace std::string_literals; + using ecsact::rt_entt_codegen::util::decl_cpp_ident; + using std::views::transform; + + ctx.write(std::format("{}_t* view;\n", view_type_name)); + ctx.write("\n"); + print_other_ctx_action(ctx); + print_other_ctx_add(ctx, assoc_detail.capabilities, other_details); + print_other_ctx_remove( + ctx, + assoc_detail.capabilities, + other_details, + view_type_name + ); + print_other_ctx_get(ctx, other_details, view_type_name); + print_other_ctx_update(ctx, other_details, view_type_name); + print_other_ctx_has(ctx, other_details); + print_other_ctx_generate(ctx, other_details); + print_other_ctx_parent(ctx, sys_like_id); + print_other_ctx_other(ctx, other_details); + }); + ctx.write(";\n\n"); + + ctx.write(struct_name, " ", context_name, ";\n\n"); + + ctx.write(context_name, ".view = &", view_type_name, ";\n"); + ctx.write(context_name, ".parent_ctx = nullptr;\n\n"); + ctx.write(context_name, ".registry = &", names.registry_var_name, ";\n"); + } +} + +using ecsact::rt_entt_codegen::util::method_printer; + +auto provider::association::print_other_ctx_action( + ecsact::codegen_plugin_context& ctx +) -> void { + auto printer = // + method_printer{ctx, "action"} + .parameter("void*", "out_action_data") + .return_type("void final"); + + context_action_impl(ctx, sys_like_id); +} + +auto provider::association::print_other_ctx_add( + ecsact::codegen_plugin_context& ctx, + const capability_t& other_caps, + const ecsact::rt_entt_codegen::ecsact_entt_system_details& details +) -> void { + auto printer = // + method_printer{ctx, "add"} + .parameter("ecsact_component_like_id", "component_id") + .parameter("const void*", "component_data") + .return_type("void final"); + + context_add_impl(ctx, other_caps); +} + +auto provider::association::print_other_ctx_remove( + ecsact::codegen_plugin_context& ctx, + const capability_t& other_caps, + const ecsact::rt_entt_codegen::ecsact_entt_system_details& details, + const std::string& view_type_name +) -> void { + auto printer = // + method_printer{ctx, "remove"} + .parameter("ecsact_component_like_id", "component_id") + .return_type("void final"); + + context_remove_impl(ctx, other_caps, details, view_type_name); +} + +auto provider::association::print_other_ctx_get( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::ecsact_entt_system_details& details, + const std::string& view_type_name +) -> void { + auto printer = // + method_printer{ctx, "get"} + .parameter("ecsact_component_like_id", "component_id") + .parameter("void*", "out_component_data") + .return_type("void final"); + + context_get_impl(ctx, sys_like_id, details, view_type_name); +} + +auto provider::association::print_other_ctx_update( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::ecsact_entt_system_details& details, + const std::string& view_type_name +) -> void { + auto printer = // + method_printer{ctx, "update"} + .parameter("ecsact_component_like_id", "component_id") + .parameter("const void*", "component_data") + .return_type("void final"); + + context_update_impl(ctx, sys_like_id, details, view_type_name); +} + +auto provider::association::print_other_ctx_has( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::ecsact_entt_system_details& details +) -> void { + auto printer = // + method_printer{ctx, "has"} + .parameter("ecsact_component_like_id", "component_id") + .return_type("bool final"); + + context_has_impl(ctx, sys_like_id, details); +} + +auto provider::association::print_other_ctx_generate( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::ecsact_entt_system_details& details +) -> void { + auto printer = // + method_printer{ctx, "generate"} + .parameter("int", "component_count") + .parameter("ecsact_component_id*", "component_ids") + .parameter("const void**", "components_data") + .return_type("void final"); + + context_generate_impl(ctx, sys_like_id, details); +} + +auto provider::association::print_other_ctx_parent( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::system_like_id_variant& sys_like_id +) -> void { + auto printer = // + method_printer{ctx, "parent"} // + .return_type("const ecsact_system_execution_context* final"); + + context_parent_impl(ctx, sys_like_id); +} + +auto provider::association::print_other_ctx_other( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::ecsact_entt_system_details& details +) -> void { + auto printer = // + method_printer{ctx, "other"} + .parameter("ecsact_entity_id", "entity") + .return_type("ecsact_system_execution_context* final"); + + context_other_impl(ctx, sys_like_id, details); +} diff --git a/rt_entt_codegen/core/system_provider/association/association.hh b/rt_entt_codegen/core/system_provider/association/association.hh new file mode 100644 index 0000000..834098e --- /dev/null +++ b/rt_entt_codegen/core/system_provider/association/association.hh @@ -0,0 +1,100 @@ +#pragma once + +#include +#include +#include "rt_entt_codegen/core/system_provider/system_provider.hh" +#include "rt_entt_codegen/core/sys_exec/sys_exec.hh" +#include "rt_entt_codegen/core/system_provider/system_ctx_functions.hh" + +namespace ecsact::rt_entt_codegen::core::provider { +class association final : public system_provider { +public: + using system_provider::system_provider; + + auto after_make_view_or_group( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> void final; + + auto context_function_header( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> void final; + + auto context_function_other( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> handle_exclusive_provide final; + + auto pre_entity_iteration( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> void final; + + auto pre_exec_system_impl( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> void final; + + auto system_impl( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> handle_exclusive_provide final; + +private: + std::map other_view_names; + + std::map components_with_entity_fields; + + auto print_other_contexts( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> void; + + auto print_other_ctx_action(ecsact::codegen_plugin_context& ctx) -> void; + auto print_other_ctx_add( + ecsact::codegen_plugin_context& ctx, + const capability_t& other_caps, + const ecsact_entt_system_details& details + ) -> void; + + auto print_other_ctx_remove( + ecsact::codegen_plugin_context& ctx, + const capability_t& other_caps, + const ecsact_entt_system_details& details, + const std::string& view_type_name + ) -> void; + + auto print_other_ctx_get( + ecsact::codegen_plugin_context& ctx, + const ecsact_entt_system_details& details, + const std::string& view_type_name + ) -> void; + + auto print_other_ctx_update( + ecsact::codegen_plugin_context& ctx, + const ecsact_entt_system_details& details, + const std::string& view_type_name + ) -> void; + + auto print_other_ctx_has( + ecsact::codegen_plugin_context& ctx, + const ecsact_entt_system_details& details + ) -> void; + + auto print_other_ctx_generate( + ecsact::codegen_plugin_context& ctx, + const ecsact_entt_system_details& details + ) -> void; + + auto print_other_ctx_parent( + ecsact::codegen_plugin_context& ctx, + const system_like_id_variant& sys_like_id + ) -> void; + + auto print_other_ctx_other( + ecsact::codegen_plugin_context& ctx, + const ecsact_entt_system_details& details + ) -> void; +}; +} // namespace ecsact::rt_entt_codegen::core::provider diff --git a/rt_entt_codegen/core/system_provider/basic/basic.cc b/rt_entt_codegen/core/system_provider/basic/basic.cc new file mode 100644 index 0000000..5b6432b --- /dev/null +++ b/rt_entt_codegen/core/system_provider/basic/basic.cc @@ -0,0 +1,108 @@ +#include "basic.hh" + +#include "ecsact/runtime/meta.hh" +#include "rt_entt_codegen/core/system_provider/system_ctx_functions.hh" + +using namespace ecsact::rt_entt_codegen::core; + +auto provider::basic::initialization( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> void { + sys_caps = ecsact::meta::system_capabilities(sys_like_id); + + view_type_name = "view"; +} + +auto provider::basic::context_function_header( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> void { + if(names.action_var_name) { + ctx.write("const void* action_data = nullptr;\n"); + } +} + +auto provider::basic::context_function_action( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> handle_exclusive_provide { + context_action_impl(ctx, sys_like_id); + return HANDLED; +} + +auto provider::basic::context_function_add( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> handle_exclusive_provide { + auto sys_caps = ecsact::meta::system_capabilities(sys_like_id); + + context_add_impl(ctx, sys_caps); + return HANDLED; +} + +auto provider::basic::context_function_remove( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> handle_exclusive_provide { + auto sys_caps = ecsact::meta::system_capabilities(sys_like_id); + + context_remove_impl(ctx, sys_caps, system_details, view_type_name); + return HANDLED; +} + +auto provider::basic::context_function_get( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> handle_exclusive_provide { + context_get_impl(ctx, sys_like_id, system_details, view_type_name); + return HANDLED; +} + +auto provider::basic::context_function_update( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> handle_exclusive_provide { + context_update_impl(ctx, sys_like_id, system_details, view_type_name); + return HANDLED; +} + +auto provider::basic::context_function_has( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> handle_exclusive_provide { + context_has_impl(ctx, sys_like_id, system_details); + return HANDLED; +} + +auto provider::basic::context_function_generate( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> handle_exclusive_provide { + context_generate_impl(ctx, sys_like_id, system_details); + return HANDLED; +} + +auto provider::basic::context_function_parent( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> handle_exclusive_provide { + context_parent_impl(ctx, sys_like_id); + return HANDLED; +} + +auto provider::basic::context_function_other( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> handle_exclusive_provide { + ctx.write("return nullptr;"); + return HANDLED; +} + +auto provider::basic::system_impl( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> handle_exclusive_provide { + ctx.write("system_impl(&context);\n"); + return HANDLED; +} diff --git a/rt_entt_codegen/core/system_provider/basic/basic.hh b/rt_entt_codegen/core/system_provider/basic/basic.hh new file mode 100644 index 0000000..1236c9e --- /dev/null +++ b/rt_entt_codegen/core/system_provider/basic/basic.hh @@ -0,0 +1,80 @@ +#pragma once + +#include +#include +#include "rt_entt_codegen/core/system_provider/system_provider.hh" +#include "rt_entt_codegen/core/sys_exec/sys_exec.hh" + +namespace ecsact::rt_entt_codegen::core::provider { + +class basic final : public system_provider { +public: + using system_provider::system_provider; + + auto initialization( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> void final; + + auto context_function_header( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> void final; + + auto context_function_action( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> handle_exclusive_provide final; + + auto context_function_add( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> handle_exclusive_provide final; + + auto context_function_remove( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> handle_exclusive_provide final; + + auto context_function_get( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> handle_exclusive_provide final; + + auto context_function_update( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> handle_exclusive_provide final; + + auto context_function_has( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> handle_exclusive_provide final; + + auto context_function_generate( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> handle_exclusive_provide final; + + auto context_function_parent( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> handle_exclusive_provide final; + + auto context_function_other( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> handle_exclusive_provide final; + + auto system_impl( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> handle_exclusive_provide final; + +private: + std::unordered_map + sys_caps; + + std::string view_type_name; +}; +} // namespace ecsact::rt_entt_codegen::core::provider diff --git a/rt_entt_codegen/core/system_provider/lazy/lazy.cc b/rt_entt_codegen/core/system_provider/lazy/lazy.cc new file mode 100644 index 0000000..e5e9c89 --- /dev/null +++ b/rt_entt_codegen/core/system_provider/lazy/lazy.cc @@ -0,0 +1,160 @@ +#include "lazy.hh" + +#include + +#include "ecsact/lang-support/lang-cc.hh" +#include "rt_entt_codegen/shared/sorting.hh" +#include "rt_entt_codegen/shared/util.hh" +#include "ecsact/runtime/meta.hh" +#include "ecsact/cpp_codegen_plugin_util.hh" + +using ecsact::cc_lang_support::cpp_identifier; +using ecsact::meta::decl_full_name; + +using namespace ecsact::rt_entt_codegen::core; + +auto provider::lazy::initialization( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> void { + auto system_name = cpp_identifier(decl_full_name(sys_like_id)); + + if(sys_like_id.is_system()) { + lazy_iteration_rate = + ecsact_meta_get_lazy_iteration_rate(sys_like_id.as_system()); + } + + exec_start_label_name = std::format( + "exec_start_{}_", + static_cast(sys_like_id.get_sys_like_id()) + ); + + pending_lazy_exec_struct = std::format( + "::ecsact::entt::detail::pending_lazy_execution<::{}>", + system_name + ); + + system_sorting_struct_name = + std::format("::ecsact::entt::detail::system_sorted<{}>", system_name); +} + +auto provider::lazy::before_make_view_or_group( + ecsact::codegen_plugin_context& ctx, + const common_vars& names, + std::vector& additional_view_components +) -> void { + ctx.write( + "constexpr auto lazy_iteration_rate_ = ", + lazy_iteration_rate, + ";\n\n" + ); + ctx.write("auto iteration_count_ = 0;\n\n"); + ctx.write(exec_start_label_name, ":\n"); + additional_view_components.push_back(pending_lazy_exec_struct); + + if(sys_like_id.is_system()) { + if(system_needs_sorted_entities(sys_like_id.as_system())) { + additional_view_components.push_back(system_sorting_struct_name); + } + } +} + +auto provider::lazy::after_make_view_or_group( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> void { + if(sys_like_id.is_system()) { + if(system_needs_sorted_entities(sys_like_id.as_system())) { + ctx.write("view.use<", system_sorting_struct_name, ">();\n"); + } + } +} + +auto provider::lazy::pre_exec_system_impl( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> void { + using ecsact::cpp_codegen_plugin_util::block; + + block(ctx, "if(iteration_count_ == lazy_iteration_rate_)", [&] { + ctx.write("break;\n"); + }); + + ctx.write("++iteration_count_;\n"); + ctx.write( + names.registry_var_name, + ".erase<", + pending_lazy_exec_struct, + ">(entity);\n" + ); +} + +auto provider::lazy::post_iteration( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> void { + using ecsact::cpp_codegen_plugin_util::block; + + auto system_name = cpp_identifier(decl_full_name(sys_like_id)); + + ctx.write( + "// If this assertion triggers that's a ecsact_rt_entt codegen " + "failure\n" + ); + ctx.write("assert(iteration_count_ <= lazy_iteration_rate_);\n"); + block(ctx, "if(iteration_count_ < lazy_iteration_rate_)", [&] { + ctx.write( + "_recalc_sorting_hash<", + system_name, + ">(", + names.registry_var_name, + ");\n" + ); + ctx.write( + names.registry_var_name, + ".sort<", + system_sorting_struct_name, + ">([](const auto& a, const auto& b) { return a.hash < b.hash; });\n" + ); + + ecsact::rt_entt_codegen::util::make_view( + ctx, + "view_no_pending_lazy_", + names.registry_var_name, + system_details + ); + + ctx.write("auto view_no_pending_lazy_count_ = 0;\n"); + + block( + ctx, + "for(ecsact::entt::entity_id entity : view_no_pending_lazy_)", + [&] { + ctx.write( + "// If this assertion triggers this is an indicator of a codegen " + "failure.\n" + "// Please report to " + "https://github.com/ecsact-dev/ecsact_rt_entt\n" + ); + ctx.write( + "assert(", + names.registry_var_name, + ".all_of<", + system_sorting_struct_name, + ">(entity));\n" + ); + ctx.write("view_no_pending_lazy_count_ += 1;\n"); + ctx.write( + names.registry_var_name, + ".emplace<", + pending_lazy_exec_struct, + ">(entity);\n" + ); + } + ); + + block(ctx, "if(view_no_pending_lazy_count_ >= lazy_iteration_rate_)", [&] { + ctx.write("goto ", exec_start_label_name, ";\n"); + }); + }); +} diff --git a/rt_entt_codegen/core/system_provider/lazy/lazy.hh b/rt_entt_codegen/core/system_provider/lazy/lazy.hh new file mode 100644 index 0000000..1f09e32 --- /dev/null +++ b/rt_entt_codegen/core/system_provider/lazy/lazy.hh @@ -0,0 +1,47 @@ +#pragma once + +#include +#include +#include "rt_entt_codegen/core/sys_exec/sys_exec.hh" +#include "rt_entt_codegen/core/system_provider/system_provider.hh" + +namespace ecsact::rt_entt_codegen::core::provider { + +class lazy final : public system_provider { +public: + using system_provider::system_provider; + + auto initialization( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> void final; + + auto before_make_view_or_group( + ecsact::codegen_plugin_context& ctx, + const common_vars& names, + std::vector& additional_view_components + ) -> void final; + + auto after_make_view_or_group( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> void final; + + auto pre_exec_system_impl( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> void final; + + auto post_iteration( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> void final; + +private: + std::string exec_start_label_name; + std::string pending_lazy_exec_struct; + std::string system_sorting_struct_name; + + int32_t lazy_iteration_rate; +}; +} // namespace ecsact::rt_entt_codegen::core::provider diff --git a/rt_entt_codegen/core/system_provider/notify/notify.cc b/rt_entt_codegen/core/system_provider/notify/notify.cc new file mode 100644 index 0000000..1ec0b1e --- /dev/null +++ b/rt_entt_codegen/core/system_provider/notify/notify.cc @@ -0,0 +1,187 @@ +#include "notify.hh" + +#include + +#include "ecsact/lang-support/lang-cc.hh" +#include "rt_entt_codegen/shared/util.hh" +#include "rt_entt_codegen/shared/system_util.hh" +#include "ecsact/runtime/meta.hh" +#include "ecsact/cpp_codegen_plugin_util.hh" + +using namespace ecsact::rt_entt_codegen::core; + +auto provider::notify::before_make_view_or_group( + ecsact::codegen_plugin_context& ctx, + const common_vars& names, + std::vector& additional_view_components +) -> void { + using ecsact::cc_lang_support::cpp_identifier; + using ecsact::meta::decl_full_name; + using ecsact::rt_entt_codegen::system_util::is_notify_system; + + auto system_name = cpp_identifier(decl_full_name(sys_like_id)); + + if(is_notify_system(sys_like_id)) { + additional_view_components.push_back( + std::format("ecsact::entt::detail::run_system<{}>", system_name) + ); + print_system_notify_views(ctx, sys_like_id, names.registry_var_name); + } +} + +auto provider::notify::print_system_notify_views( + ecsact::codegen_plugin_context& ctx, + ecsact_system_like_id system_id, + std::string registry_name +) -> void { + using ecsact::cc_lang_support::c_identifier; + using ecsact::cc_lang_support::cpp_identifier; + using ecsact::cpp_codegen_plugin_util::block; + using ecsact::meta::decl_full_name; + + auto notify_settings = ecsact::meta::system_notify_settings(system_id); + + using notify_settings_pair_t = + std::pair; + + auto notify_settings_vec = std::vector( + notify_settings.begin(), + notify_settings.end() + ); + + const auto notify_settings_ranking = + std::map{ + {ECSACT_SYS_NOTIFY_ALWAYS, 99}, // unused + {ECSACT_SYS_NOTIFY_NONE, 99}, // unused + + // We prioritize everything except onchange due to onchange having the + // most overhead. + {ECSACT_SYS_NOTIFY_ONINIT, 10}, + {ECSACT_SYS_NOTIFY_ONREMOVE, 9}, + {ECSACT_SYS_NOTIFY_ONUPDATE, 8}, + {ECSACT_SYS_NOTIFY_ONCHANGE, 0}, + }; + + std::sort( + notify_settings_vec.begin(), + notify_settings_vec.end(), + [&](notify_settings_pair_t a, notify_settings_pair_t b) -> bool { + return notify_settings_ranking.at(a.second) > + notify_settings_ranking.at(b.second); + } + ); + + auto system_name = cpp_identifier(decl_full_name(system_id)); + + for(auto const& [comp_id, notify_setting] : notify_settings_vec) { + if(notify_setting == ECSACT_SYS_NOTIFY_ALWAYS || + notify_setting == ECSACT_SYS_NOTIFY_NONE) { + break; + } + auto cpp_comp_name = cpp_identifier(decl_full_name(comp_id)); + auto comp_name = c_identifier(decl_full_name((comp_id))); + + auto run_system_comp = + std::format("ecsact::entt::detail::run_system<{}>", system_name); + + if(notify_setting == ECSACT_SYS_NOTIFY_ONINIT) { + auto pending_add_str = + std::format("ecsact::entt::component_added<{}>", cpp_comp_name); + + auto view_name = std::format("{}_init_view", comp_name); + + ecsact::rt_entt_codegen::util::make_view( + ctx, + view_name, + registry_name, + system_details, + std::vector{pending_add_str}, + std::vector{run_system_comp} + ); + + block(ctx, std::format("for(auto entity: {})", view_name), [&]() { + ctx.write( + std::format("registry.emplace<{}>(entity);\n", run_system_comp) + ); + }); + } + + if(notify_setting == ECSACT_SYS_NOTIFY_ONREMOVE) { + auto pending_remove_str = + std::format("ecsact::entt::component_removed<{}>", cpp_comp_name); + + auto view_name = std::format("{}_remove_view", comp_name); + + ecsact::rt_entt_codegen::util::make_view( + ctx, + view_name, + registry_name, + system_details, + std::vector{pending_remove_str}, + std::vector{run_system_comp} + ); + + block(ctx, std::format("for(auto entity: {})", view_name), [&]() { + ctx.write( + std::format("registry.emplace<{}>(entity);\n", run_system_comp) + ); + }); + } + + if(notify_setting == ECSACT_SYS_NOTIFY_ONUPDATE) { + auto component_updated_str = + std::format("ecsact::entt::component_updated<{}>", cpp_comp_name); + + auto view_name = std::format("{}_update_view", comp_name); + + ecsact::rt_entt_codegen::util::make_view( + ctx, + view_name, + registry_name, + system_details, + std::vector{component_updated_str}, + std::vector{run_system_comp} + ); + + block(ctx, std::format("for(auto entity: {})", view_name), [&]() { + ctx.write( + std::format("registry.emplace<{}>(entity);\n", run_system_comp) + ); + }); + } + + if(notify_setting == ECSACT_SYS_NOTIFY_ONCHANGE) { + auto exec_itr_onchange_str = std::format( + "ecsact::entt::detail::exec_itr_beforechange_storage<{}>", + cpp_comp_name + ); + + auto view_name = std::format("{}_change_view", comp_name); + + ecsact::rt_entt_codegen::util::make_view( + ctx, + view_name, + registry_name, + system_details, + std::vector{exec_itr_onchange_str}, + std::vector{run_system_comp} + ); + + block(ctx, std::format("for(auto entity: {})", view_name), [&]() { + block( + ctx, + std::format( + "if(!ecsact::entt::wrapper::core::has_component_changed<{}>(entity," + " registry))", + cpp_comp_name + ), + [&] { ctx.write("continue;\n"); } + ); + + ctx.write( + std::format("registry.emplace<{}>(entity);\n", run_system_comp) + ); + }); + } + } +} diff --git a/rt_entt_codegen/core/system_provider/notify/notify.hh b/rt_entt_codegen/core/system_provider/notify/notify.hh new file mode 100644 index 0000000..0ff4f1e --- /dev/null +++ b/rt_entt_codegen/core/system_provider/notify/notify.hh @@ -0,0 +1,33 @@ +#pragma once + +#include "rt_entt_codegen/core/system_provider/system_provider.hh" +#include "rt_entt_codegen/core/sys_exec/sys_exec.hh" + +namespace ecsact::rt_entt_codegen::core::provider { +class notify final : public system_provider { +public: + using system_provider::system_provider; + + auto initialization( + ecsact::codegen_plugin_context& ctx, + const common_vars& names + ) -> void { + } + + auto before_make_view_or_group( + ecsact::codegen_plugin_context& ctx, + const common_vars& names, + std::vector& additional_view_components + ) -> void final; + +private: + /* + * Prints the specialized views for ecsact_system_notify_settings components + */ + auto print_system_notify_views( + ecsact::codegen_plugin_context& ctx, + ecsact_system_like_id system_id, + std::string registry_name + ) -> void; +}; +} // namespace ecsact::rt_entt_codegen::core::provider diff --git a/rt_entt_codegen/core/system_provider/system_ctx_functions.cc b/rt_entt_codegen/core/system_provider/system_ctx_functions.cc new file mode 100644 index 0000000..3e40980 --- /dev/null +++ b/rt_entt_codegen/core/system_provider/system_ctx_functions.cc @@ -0,0 +1,411 @@ +#include "system_ctx_functions.hh" + +#include "ecsact/runtime/meta.hh" +#include "ecsact/lang-support/lang-cc.hh" +#include "ecsact/cpp_codegen_plugin_util.hh" +#include "rt_entt_codegen/shared/util.hh" + +using ecsact::cc_lang_support::cpp_identifier; +using ecsact::cpp_codegen_plugin_util::block; +using ecsact::meta::decl_full_name; +using ecsact::rt_entt_codegen::util::is_transient_component; + +auto ecsact::rt_entt_codegen::core::provider::context_action_impl( + ecsact::codegen_plugin_context& ctx, + const system_like_id_variant& sys_like_id +) -> void { + if(sys_like_id.is_action()) { + auto action_name = cpp_identifier(decl_full_name(sys_like_id)); + + ctx.write( + "*static_cast<", + action_name, + "*>(out_action_data) = *static_cast(action_data);\n" + ); + } else { + // TODO(Kelwan): Trying to access .action() without a valid action + ctx.write("\n"); + } +} + +auto ecsact::rt_entt_codegen::core::provider::context_add_impl( + ecsact::codegen_plugin_context& ctx, + const capability_t& sys_caps +) -> void { + auto adds_comps = std::vector{}; + + for(auto&& [comp_id, sys_cap] : sys_caps) { + if(is_transient_component(ctx.package_id, comp_id)) { + continue; + } + if((ECSACT_SYS_CAP_ADDS & sys_cap) == ECSACT_SYS_CAP_ADDS) { + adds_comps.push_back(comp_id); + } + } + + if(adds_comps.empty()) { + // TODO(Kelwan): Handle unexpected behaviour + return; + } else if(adds_comps.size() == 1) { + const auto& comp_id = adds_comps.front(); + auto type_name = cpp_identifier(decl_full_name(comp_id)); + ctx.write( + "wrapper::dynamic::context_add<::", + type_name, + ">(this, ecsact_id_cast(", + type_name, + "::id),", + "component_data); \n" + ); + return; + } + block( + ctx, + "static const auto add_fns = " + "std::unordered_map", + [&] { + for(int i = 0; i < adds_comps.size(); ++i) { + const auto comp_id = adds_comps[i]; + auto type_name = cpp_identifier(decl_full_name(comp_id)); + ctx.write( + "{", + "ecsact_id_cast(", + type_name, + "::id), ", + "&wrapper::dynamic::context_add<::", + type_name, + "> }," + ); + } + } + ); + + ctx.write(";\n"); + + ctx.write("add_fns.at(component_id)(this, component_id, component_data);\n"); +} + +auto ecsact::rt_entt_codegen::core::provider::context_remove_impl( + ecsact::codegen_plugin_context& ctx, + const capability_t& sys_caps, + const ecsact::rt_entt_codegen::ecsact_entt_system_details& details, + const std::string& view_type_name +) -> void { + auto remove_comps = std::vector{}; + + for(auto&& [comp_id, sys_cap] : sys_caps) { + if(is_transient_component(ctx.package_id, comp_id)) { + continue; + } + if((ECSACT_SYS_CAP_REMOVES & sys_cap) == ECSACT_SYS_CAP_REMOVES) { + remove_comps.push_back(comp_id); + } + } + + if(remove_comps.size() == 0) { + // TODO(Kelwan): Handle unexpected behaviour + return; + } + if(remove_comps.size() == 1) { + const auto& comp_id = remove_comps.front(); + + auto type_name = cpp_identifier(decl_full_name(comp_id)); + ctx.write( + "wrapper::dynamic::context_remove<::", + type_name, + ">(this, ecsact_id_cast(", + type_name, + "::id), *view);\n" + ); + return; + } + ctx.write(std::format( + "using remove_fn_t = void (*)(ecsact_system_execution_context*, " + "ecsact_component_like_id, {}_t&);\n", + view_type_name + )); + + ctx.write("static const auto remove_fns = []()\n"); + + block(ctx, "", [&] { + ctx.write( + "auto result = std::unordered_map{};\n" + ); + for(const auto comp_id : details.removable_comps) { + auto type_name = cpp_identifier(decl_full_name(comp_id)); + ctx.write( + "result[ecsact_id_cast(", + type_name, + "::id)] = &wrapper::dynamic::context_remove<", + type_name, + ">;\n" + ); + } + + ctx.write("return result;\n"); + }); + ctx.write("();\n"); +} + +auto ecsact::rt_entt_codegen::core::provider::context_get_impl( + ecsact::codegen_plugin_context& ctx, + const system_like_id_variant& sys_like_id, + const ecsact::rt_entt_codegen::ecsact_entt_system_details& details, + const std::string& view_type_name +) -> void { + if(details.readable_comps.size() == 0) { + return; + } + + std::vector get_components; + + for(auto comp_id : details.readable_comps) { + if(is_transient_component(ctx.package_id, comp_id)) { + continue; + } + get_components.insert(get_components.end(), comp_id); + } + + if(get_components.size() == 0) { + return; + } + + // Shortcut - ignore component ID because we only have 1 + if(details.get_comps.size() == 1 && details.readable_comps.size() == 1) { + auto comp_id = *details.get_comps.begin(); + auto cpp_comp_full_name = cpp_identifier(decl_full_name(comp_id)); + + ctx.write( + "assert(ecsact_id_cast(::", + cpp_comp_full_name, + "::id) == component_id);\n" + ); + ctx.write( + "*static_cast<::", + cpp_comp_full_name, + "*>(out_component_data) = view->get<::", + cpp_comp_full_name, + ">(entity);" + ); + return; + } + + ctx.write(std::format( + "using get_fn_t = void (*)(ecsact_system_execution_context*, " + "ecsact_component_like_id, void *, {}_t&);\n", + view_type_name + )); + + ctx.write("static const auto get_fns = []()\n"); + + block(ctx, "", [&] { + ctx.write( + "auto result = std::unordered_map{};\n" + ); + for(const auto comp_id : details.readable_comps) { + auto type_name = cpp_identifier(decl_full_name(comp_id)); + ctx.write( + "result[ecsact_id_cast(", + type_name, + "::id)] = &wrapper::dynamic::context_get<", + type_name, + ">;\n" + ); + } + + ctx.write("return result;\n"); + }); + ctx.write("();\n"); + + ctx.write( + "get_fns.at(component_id)(this, component_id, out_component_data, *view);\n" + ); +} + +auto ecsact::rt_entt_codegen::core::provider::context_update_impl( + ecsact::codegen_plugin_context& ctx, + const system_like_id_variant& sys_like_id, + const ecsact::rt_entt_codegen::ecsact_entt_system_details& details, + const std::string& view_type_name +) -> void { + if(details.writable_comps.size() == 0) { + return; + } + + if(details.writable_comps.size() == 1) { + const auto& comp_id = *details.writable_comps.begin(); + auto type_name = cpp_identifier(decl_full_name(comp_id)); + ctx.write( + "wrapper::dynamic::context_update<::", + type_name, + ">(this, ecsact_id_cast(", + type_name, + "::id),", + "component_data, *view); \n" + ); + return; + } + + ctx.write(std::format( + "using update_fn_t = void (*)(ecsact_system_execution_context*, " + "ecsact_component_like_id, const void *, {}_t&);\n", + view_type_name + )); + + ctx.write("static const auto update_fns = []()\n"); + + block(ctx, "", [&] { + ctx.write( + "auto result = std::unordered_map{};\n" + ); + for(const auto comp_id : details.writable_comps) { + auto type_name = cpp_identifier(decl_full_name(comp_id)); + ctx.write( + "result[ecsact_id_cast(", + type_name, + "::id)] = &wrapper::dynamic::context_update<", + type_name, + ">;\n" + ); + } + + ctx.write("return result;\n"); + }); + ctx.write("();\n"); + + ctx.write( + "update_fns.at(component_id)(this, component_id, component_data, " + "*view);\n" + ); +} + +auto ecsact::rt_entt_codegen::core::provider::context_has_impl( + ecsact::codegen_plugin_context& ctx, + const system_like_id_variant& sys_like_id, + const ecsact::rt_entt_codegen::ecsact_entt_system_details& details +) -> void { + if(details.writable_comps.size() == 0) { + ctx.write("return false;"); + return; + } + + if(details.writable_comps.size() == 1) { + const auto& comp_id = *details.writable_comps.begin(); + auto type_name = cpp_identifier(decl_full_name(comp_id)); + ctx.write( + "return wrapper::dynamic::context_has<::", + type_name, + ">(this, ecsact_id_cast(", + type_name, + "::id));\n" + ); + } + block( + ctx, + "static const auto has_fns = " + "std::unordered_map", + [&] { + for(const auto comp_id : details.readable_comps) { + auto type_name = cpp_identifier(decl_full_name(comp_id)); + ctx.write( + "{ecsact_id_cast(", + type_name, + "::id), &wrapper::dynamic::context_has<", + type_name, + "> }," + ); + } + } + ); + ctx.write(";\n"); + + ctx.write("return has_fns.at(component_id)(this, component_id);\n"); +} + +auto ecsact::rt_entt_codegen::core::provider::context_generate_impl( + ecsact::codegen_plugin_context& ctx, + const system_like_id_variant& sys_like_id, + const ecsact::rt_entt_codegen::ecsact_entt_system_details& details +) -> void { + if(details.generate_comps.size() == 0) { + // TODO (Kelwan): Handle undefined behaviour + return; + } + block( + ctx, + "static const auto generate_fns = " + "std::unordered_map", + [&] { + for(const auto& component : details.generate_comps) { + for(const auto& [comp_id, requirements] : component) { + auto type_name = cpp_identifier(decl_full_name(comp_id)); + ctx.write( + "{", + type_name, + "::id, &wrapper::dynamic::context_generate_add<", + type_name, + "> }," + ); + } + } + } + ); + ctx.write(";\n"); + + // NOTE(Kelwan): Multiple generates blocks are allowed in Ecsact systems but + // currently the interpreter won't allow this. More testing required after the + // issue is resolved https://github.com/ecsact-dev/ecsact_interpret/issues/185 + ctx.write("auto entity = registry->create();\n"); + + ctx.write( + "registry->template emplace(entity, " + "ecsact_generated_entity);\n" + ); + + block(ctx, "for(int i = 0; i < component_count; ++i)", [&] { + ctx.write("const auto component_id = component_ids[i];\n"); + ctx.write("const void* component_data = components_data[i];\n"); + + ctx.write( + "generate_fns.at(component_id)(this, component_id, " + "component_data, entity);\n" + ); + }); +} + +auto ecsact::rt_entt_codegen::core::provider::context_parent_impl( + ecsact::codegen_plugin_context& ctx, + const system_like_id_variant& sys_like_id +) -> void { + ctx.write("return this->parent_ctx;\n"); +} + +auto ecsact::rt_entt_codegen::core::provider::context_other_impl( + ecsact::codegen_plugin_context& ctx, + const system_like_id_variant& sys_like_id, + const ecsact::rt_entt_codegen::ecsact_entt_system_details& details +) -> void { + if(details.association_details.size() == 0) { + // TODO(Kelwan): Handle undefined behaviour + // Attempt to access other without association + + ctx.write("return nullptr;\n"); + return; + } + + ctx.write( + "if(other_contexts.contains(entity)) {\n", + "return other_contexts.at(entity);\n}\n" + ); + + ctx.write("return nullptr;\n"); +} diff --git a/rt_entt_codegen/core/system_provider/system_ctx_functions.hh b/rt_entt_codegen/core/system_provider/system_ctx_functions.hh new file mode 100644 index 0000000..8d1005c --- /dev/null +++ b/rt_entt_codegen/core/system_provider/system_ctx_functions.hh @@ -0,0 +1,56 @@ +#pragma once + +#include "rt_entt_codegen/core/sys_exec/sys_exec.hh" +#include "rt_entt_codegen/shared/ecsact_entt_details.hh" +#include "rt_entt_codegen/shared/system_variant.hh" + +namespace ecsact::rt_entt_codegen::core::provider { +using capability_t = + std::unordered_map; + +auto context_action_impl( + ecsact::codegen_plugin_context& ctx, + const system_like_id_variant& sys_like_id +) -> void; +auto context_add_impl( + ecsact::codegen_plugin_context& ctx, + const capability_t& sys_caps +) -> void; +auto context_remove_impl( + ecsact::codegen_plugin_context& ctx, + const capability_t& sys_caps, + const ecsact::rt_entt_codegen::ecsact_entt_system_details& details, + const std::string& view_type_name +) -> void; +auto context_get_impl( + ecsact::codegen_plugin_context& ctx, + const system_like_id_variant& sys_like_id, + const ecsact::rt_entt_codegen::ecsact_entt_system_details& details, + const std::string& view_type_name +) -> void; +auto context_update_impl( + ecsact::codegen_plugin_context& ctx, + const system_like_id_variant& sys_like_id, + const ecsact::rt_entt_codegen::ecsact_entt_system_details& details, + const std::string& view_type_name +) -> void; +auto context_has_impl( + ecsact::codegen_plugin_context& ctx, + const system_like_id_variant& sys_like_id, + const ecsact::rt_entt_codegen::ecsact_entt_system_details& details +) -> void; +auto context_generate_impl( + ecsact::codegen_plugin_context& ctx, + const system_like_id_variant& sys_like_id, + const ecsact::rt_entt_codegen::ecsact_entt_system_details& details +) -> void; +auto context_parent_impl( + ecsact::codegen_plugin_context& ctx, + const system_like_id_variant& sys_like_id +) -> void; +auto context_other_impl( + ecsact::codegen_plugin_context& ctx, + const system_like_id_variant& sys_like_id, + const ecsact::rt_entt_codegen::ecsact_entt_system_details& details +) -> void; +} // namespace ecsact::rt_entt_codegen::core::provider diff --git a/rt_entt_codegen/core/system_provider/system_provider.cc b/rt_entt_codegen/core/system_provider/system_provider.cc new file mode 100644 index 0000000..5fa3a7d --- /dev/null +++ b/rt_entt_codegen/core/system_provider/system_provider.cc @@ -0,0 +1,131 @@ +#include "system_provider.hh" + +using namespace ecsact::rt_entt_codegen::core::provider; + +system_provider::system_provider(system_like_id_variant id) + : sys_like_id(id) + , system_details(ecsact_entt_system_details::from_system_like(sys_like_id)) { + assert(sys_like_id != system_like_id_variant{}); +} + +ecsact::rt_entt_codegen::core::provider::system_provider::~system_provider() = + default; + +auto system_provider::initialization( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> void { +} + +auto system_provider::before_make_view_or_group( + ecsact::codegen_plugin_context& ctx, + const common_vars& names, + std::vector& additional_view_components +) -> void { +} + +auto system_provider::after_make_view_or_group( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> void { +} + +auto system_provider::context_function_header( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> void { +} + +auto system_provider::context_function_action( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> handle_exclusive_provide { + return NOT_HANDLED; +} + +auto system_provider::context_function_add( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> handle_exclusive_provide { + return NOT_HANDLED; +} + +auto system_provider::context_function_remove( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> handle_exclusive_provide { + return NOT_HANDLED; +} + +auto system_provider::context_function_get( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> handle_exclusive_provide { + return NOT_HANDLED; +} + +auto system_provider::context_function_update( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> handle_exclusive_provide { + return NOT_HANDLED; +} + +auto system_provider::context_function_has( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> handle_exclusive_provide { + return NOT_HANDLED; +} + +auto system_provider::context_function_generate( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> handle_exclusive_provide { + return NOT_HANDLED; +} + +auto system_provider::context_function_parent( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> handle_exclusive_provide { + return NOT_HANDLED; +} + +auto system_provider::context_function_other( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> handle_exclusive_provide { + return NOT_HANDLED; +} + +auto system_provider::pre_entity_iteration( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> void { +} + +auto system_provider::pre_exec_system_impl( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> void { +} + +auto system_provider::system_impl( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> handle_exclusive_provide { + return NOT_HANDLED; +} + +auto system_provider::post_exec_system_impl( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> void { +} + +auto system_provider::post_iteration( + ecsact::codegen_plugin_context& ctx, + const common_vars& names +) -> void { +} diff --git a/rt_entt_codegen/core/system_provider/system_provider.hh b/rt_entt_codegen/core/system_provider/system_provider.hh new file mode 100644 index 0000000..4b8599d --- /dev/null +++ b/rt_entt_codegen/core/system_provider/system_provider.hh @@ -0,0 +1,104 @@ +#pragma once + +#include +#include +#include + +#include "rt_entt_codegen/core/sys_exec/sys_exec.hh" +#include "rt_entt_codegen/shared/system_variant.hh" +#include "rt_entt_codegen/shared/ecsact_entt_details.hh" + +namespace ecsact::rt_entt_codegen::core::provider { +enum handle_exclusive_provide { + HANDLED = 0, + NOT_HANDLED = 1, +}; + +class system_provider { +public: + system_provider(system_like_id_variant sys_like_id); + virtual ~system_provider(); + + virtual auto initialization( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names + ) -> void; + + virtual auto before_make_view_or_group( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names, + std::vector& additional_view_components + ) -> void; + + virtual auto after_make_view_or_group( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names + ) -> void; + + virtual auto context_function_header( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names + ) -> void; + [[nodiscard]] virtual auto context_function_action( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names + ) -> handle_exclusive_provide; + [[nodiscard]] virtual auto context_function_add( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names + ) -> handle_exclusive_provide; + [[nodiscard]] virtual auto context_function_remove( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names + ) -> handle_exclusive_provide; + [[nodiscard]] virtual auto context_function_get( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names + ) -> handle_exclusive_provide; + [[nodiscard]] virtual auto context_function_update( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names + ) -> handle_exclusive_provide; + [[nodiscard]] virtual auto context_function_has( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names + ) -> handle_exclusive_provide; + [[nodiscard]] virtual auto context_function_generate( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names + ) -> handle_exclusive_provide; + [[nodiscard]] virtual auto context_function_parent( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names + ) -> handle_exclusive_provide; + [[nodiscard]] virtual auto context_function_other( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names + ) -> handle_exclusive_provide; + + virtual auto pre_entity_iteration( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names + ) -> void; + virtual auto pre_exec_system_impl( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names + ) -> void; + virtual auto system_impl( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names + ) -> handle_exclusive_provide; + virtual auto post_exec_system_impl( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names + ) -> void; + virtual auto post_iteration( + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::core::common_vars& names + ) -> void; + +protected: + const system_like_id_variant sys_like_id; + const ecsact_entt_system_details system_details; +}; +} // namespace ecsact::rt_entt_codegen::core::provider diff --git a/rt_entt_codegen/shared/BUILD.bazel b/rt_entt_codegen/shared/BUILD.bazel index 68501bd..0147e6b 100644 --- a/rt_entt_codegen/shared/BUILD.bazel +++ b/rt_entt_codegen/shared/BUILD.bazel @@ -62,6 +62,7 @@ cc_library( deps = [ ":ecsact_entt_details", ":util", + "//rt_entt_codegen/core/sys_exec", "@ecsact_codegen//:plugin", "@ecsact_lang_cpp//:cpp_codegen_plugin_util", "@ecsact_lang_cpp//:support", @@ -76,6 +77,16 @@ cc_library( copts = copts, deps = [ ":ecsact_entt_details", + "//rt_entt_codegen/shared:system_variant", "@ecsact_lang_cpp//:cpp_codegen_plugin_util", ], ) + +cc_library( + name = "system_variant", + hdrs = ["system_variant.hh"], + copts = copts, + deps = [ + "@ecsact_runtime//:common", + ], +) diff --git a/rt_entt_codegen/shared/ecsact_entt_details.cc b/rt_entt_codegen/shared/ecsact_entt_details.cc index ea271eb..219d02c 100644 --- a/rt_entt_codegen/shared/ecsact_entt_details.cc +++ b/rt_entt_codegen/shared/ecsact_entt_details.cc @@ -123,7 +123,7 @@ auto ecsact_entt_system_details::fill_system_details( } } - for(auto&& [comp_id, _] : caps) { + for([[maybe_unused]] auto&& [comp_id, _] : caps) { // Sanity check to make sure we've not missing any system comp IDs assert( out_details.get_comps.contains(comp_id) || diff --git a/rt_entt_codegen/shared/parallel.cc b/rt_entt_codegen/shared/parallel.cc index 627a3c9..7e71005 100644 --- a/rt_entt_codegen/shared/parallel.cc +++ b/rt_entt_codegen/shared/parallel.cc @@ -3,27 +3,28 @@ #include #include #include +#include #include "ecsact/lang-support/lang-cc.hh" -#include "ecsact/cpp_codegen_plugin_util.hh" +#include "rt_entt_codegen/shared/system_variant.hh" +#include "system_variant.hh" +#include "ecsact/runtime/meta.hh" + +using ecsact::rt_entt_codegen::system_like_id_variant; static auto loop_iterator( - const std::vector& system_list, - const std::vector::iterator begin, - std::vector>& parallel_system_cluster + const std::vector& system_list, + const std::vector::iterator begin, + std::vector>& parallel_system_cluster ) -> void; auto ecsact::rt_entt_codegen::parallel::get_parallel_execution_cluster( - ecsact::codegen_plugin_context& ctx, - const ecsact::rt_entt_codegen::ecsact_entt_details& details, - std::vector system_list, - std::string parent_context -) -> std::vector> { - using ecsact::cc_lang_support::cpp_identifier; - using ecsact::cpp_codegen_plugin_util::block; - + ecsact::codegen_plugin_context& ctx, + std::vector system_list, + std::string parent_context +) -> std::vector> { auto parallel_system_cluster = - std::vector>{}; + std::vector>{}; loop_iterator(system_list, system_list.begin(), parallel_system_cluster); @@ -39,11 +40,11 @@ static auto is_capability_safe(ecsact_system_capability capability) -> bool { } static auto loop_iterator( - const std::vector& system_list, - const std::vector::iterator begin, - std::vector>& parallel_system_cluster + const std::vector& system_list, + const std::vector::iterator begin, + std::vector>& parallel_system_cluster ) -> void { - std::vector parallel_system_list; + std::vector parallel_system_list; auto unsafe_comps = std::set{}; using ecsact::meta::decl_full_name; @@ -51,7 +52,6 @@ static auto loop_iterator( for(auto iterator = begin; iterator != system_list.end(); iterator++) { auto sys_like_id = *iterator; auto capabilities = ecsact::meta::system_capabilities(sys_like_id); - auto generate_ids = ecsact::meta::get_system_generates_ids(sys_like_id); if(!generate_ids.empty()) { @@ -60,7 +60,7 @@ static auto loop_iterator( } parallel_system_cluster.push_back( - std::vector{sys_like_id} + std::vector{sys_like_id} ); loop_iterator( system_list, @@ -156,3 +156,66 @@ static auto loop_iterator( } parallel_system_cluster.push_back(parallel_system_list); } + +auto ecsact::rt_entt_codegen::parallel::print_parallel_execution_cluster( + ecsact::codegen_plugin_context& ctx, + const std::vector>& + parallel_system_cluster +) -> void { + using ecsact::cc_lang_support::cpp_identifier; + + for(const auto& systems_to_parallel : parallel_system_cluster) { + if(systems_to_parallel.size() == 1) { + auto single_system_like_variant = systems_to_parallel.begin(); + + auto sync_sys_name = cpp_identifier(ecsact::meta::decl_full_name( + single_system_like_variant->get_sys_like_id() + )); + + if(single_system_like_variant->is_action()) { + ctx.write(std::format( + "ecsact::entt::execute_actions<{}>(registry, {}, " + "actions_map);\n", + sync_sys_name, + "nullptr" + )); + } + if(single_system_like_variant->is_system()) { + ctx.write(std::format( + "ecsact::entt::execute_system<{}>(registry, {}, " + "actions_map);\n", + sync_sys_name, + "nullptr" + )); + } + continue; + } + + ctx.write("execute_parallel_cluster(registry, nullptr, "); + ctx.write(std::format( + "std::array {{\n", + systems_to_parallel.size() + )); + for(const auto system_like_id_variant : systems_to_parallel) { + auto cpp_decl_name = + cpp_identifier(ecsact::meta::decl_full_name(system_like_id_variant)); + + if(system_like_id_variant.is_action()) { + ctx.write( + "\texec_entry_t{&ecsact::entt::execute_actions<", + cpp_decl_name, + ">, actions_map},\n" + ); + } else if(system_like_id_variant.is_system()) { + ctx.write( + "\texec_entry_t{&ecsact::entt::execute_system<", + cpp_decl_name, + ">, actions_map},\n" + ); + } else { + ctx.write("// ??? unhandled ??? ", cpp_decl_name, "\n"); + } + } + ctx.write("});\n"); + } +} diff --git a/rt_entt_codegen/shared/parallel.hh b/rt_entt_codegen/shared/parallel.hh index 13d39f8..e50d8e4 100644 --- a/rt_entt_codegen/shared/parallel.hh +++ b/rt_entt_codegen/shared/parallel.hh @@ -2,12 +2,18 @@ #include "ecsact/codegen/plugin.hh" #include "rt_entt_codegen/shared/ecsact_entt_details.hh" +#include "system_variant.hh" namespace ecsact::rt_entt_codegen::parallel { auto get_parallel_execution_cluster( - ecsact::codegen_plugin_context& ctx, - const ecsact::rt_entt_codegen::ecsact_entt_details& details, - std::vector system_list, - std::string parent_context = "nullptr" -) -> std::vector>; -} + ecsact::codegen_plugin_context& ctx, + std::vector system_list, + std::string parent_context = "nullptr" +) -> std::vector>; + +auto print_parallel_execution_cluster( + ecsact::codegen_plugin_context& ctx, + const std::vector>& + parallel_system_cluster +) -> void; +} // namespace ecsact::rt_entt_codegen::parallel diff --git a/rt_entt_codegen/shared/system_execution.cc b/rt_entt_codegen/shared/system_execution.cc new file mode 100644 index 0000000..e69de29 diff --git a/rt_entt_codegen/shared/system_execution.hh b/rt_entt_codegen/shared/system_execution.hh new file mode 100644 index 0000000..e69de29 diff --git a/rt_entt_codegen/shared/system_util.cc b/rt_entt_codegen/shared/system_util.cc index 27b8114..1dc8da3 100644 --- a/rt_entt_codegen/shared/system_util.cc +++ b/rt_entt_codegen/shared/system_util.cc @@ -1,13 +1,12 @@ #include "system_util.hh" #include -#include -#include -#include #include #include "ecsact/runtime/common.h" -#include "rt_entt_codegen/shared/util.hh" + +using capability_t = + std::unordered_map; auto ecsact::rt_entt_codegen::system_util::is_notify_system( ecsact_system_like_id system_id @@ -30,164 +29,6 @@ auto ecsact::rt_entt_codegen::system_util::is_notify_system( return true; } -auto ecsact::rt_entt_codegen::system_util::print_system_notify_views( - ecsact::codegen_plugin_context& ctx, - const ecsact::rt_entt_codegen::ecsact_entt_system_details& details, - ecsact_system_like_id system_id, - std::string registry_name -) -> void { - using ecsact::cc_lang_support::c_identifier; - using ecsact::cc_lang_support::cpp_identifier; - using ecsact::cpp_codegen_plugin_util::block; - using ecsact::meta::decl_full_name; - - auto notify_settings = ecsact::meta::system_notify_settings(system_id); - - using notify_settings_pair_t = - std::pair; - - auto notify_settings_vec = std::vector( - notify_settings.begin(), - notify_settings.end() - ); - - const auto notify_settings_ranking = - std::map{ - {ECSACT_SYS_NOTIFY_ALWAYS, 99}, // unused - {ECSACT_SYS_NOTIFY_NONE, 99}, // unused - - // We prioritize everything except onchange due to onchange having the - // most overhead. - {ECSACT_SYS_NOTIFY_ONINIT, 10}, - {ECSACT_SYS_NOTIFY_ONREMOVE, 9}, - {ECSACT_SYS_NOTIFY_ONUPDATE, 8}, - {ECSACT_SYS_NOTIFY_ONCHANGE, 0}, - }; - - std::sort( - notify_settings_vec.begin(), - notify_settings_vec.end(), - [&](notify_settings_pair_t a, notify_settings_pair_t b) -> bool { - return notify_settings_ranking.at(a.second) > - notify_settings_ranking.at(b.second); - } - ); - - auto system_name = cpp_identifier(decl_full_name(system_id)); - - for(auto const& [comp_id, notify_setting] : notify_settings_vec) { - if(notify_setting == ECSACT_SYS_NOTIFY_ALWAYS || - notify_setting == ECSACT_SYS_NOTIFY_NONE) { - break; - } - auto cpp_comp_name = cpp_identifier(decl_full_name(comp_id)); - auto comp_name = c_identifier(decl_full_name((comp_id))); - - auto run_system_comp = - std::format("ecsact::entt::detail::run_system<{}>", system_name); - - if(notify_setting == ECSACT_SYS_NOTIFY_ONINIT) { - auto pending_add_str = - std::format("ecsact::entt::component_added<{}>", cpp_comp_name); - - auto view_name = std::format("{}_init_view", comp_name); - - ecsact::rt_entt_codegen::util::make_view( - ctx, - view_name, - registry_name, - details, - std::vector{pending_add_str}, - std::vector{run_system_comp} - ); - - block(ctx, std::format("for(auto entity: {})", view_name), [&]() { - ctx.write( - std::format("registry.emplace<{}>(entity);\n", run_system_comp) - ); - }); - } - - if(notify_setting == ECSACT_SYS_NOTIFY_ONREMOVE) { - auto pending_remove_str = - std::format("ecsact::entt::component_removed<{}>", cpp_comp_name); - - auto view_name = std::format("{}_remove_view", comp_name); - - ecsact::rt_entt_codegen::util::make_view( - ctx, - view_name, - registry_name, - details, - std::vector{pending_remove_str}, - std::vector{run_system_comp} - ); - - block(ctx, std::format("for(auto entity: {})", view_name), [&]() { - ctx.write( - std::format("registry.emplace<{}>(entity);\n", run_system_comp) - ); - }); - } - - if(notify_setting == ECSACT_SYS_NOTIFY_ONUPDATE) { - auto component_updated_str = - std::format("ecsact::entt::component_updated<{}>", cpp_comp_name); - - auto view_name = std::format("{}_update_view", comp_name); - - ecsact::rt_entt_codegen::util::make_view( - ctx, - view_name, - registry_name, - details, - std::vector{component_updated_str}, - std::vector{run_system_comp} - ); - - block(ctx, std::format("for(auto entity: {})", view_name), [&]() { - ctx.write( - std::format("registry.emplace<{}>(entity);\n", run_system_comp) - ); - }); - } - - if(notify_setting == ECSACT_SYS_NOTIFY_ONCHANGE) { - auto exec_itr_onchange_str = std::format( - "ecsact::entt::detail::exec_itr_beforechange_storage<{}>", - cpp_comp_name - ); - - auto view_name = std::format("{}_change_view", comp_name); - - ecsact::rt_entt_codegen::util::make_view( - ctx, - view_name, - registry_name, - details, - std::vector{exec_itr_onchange_str}, - std::vector{run_system_comp} - ); - - block(ctx, std::format("for(auto entity: {})", view_name), [&]() { - block( - ctx, - std::format( - "if(!ecsact::entt::wrapper::core::has_component_changed<{}>(entity," - " registry))", - cpp_comp_name - ), - [&] { ctx.write("continue;\n"); } - ); - - ctx.write( - std::format("registry.emplace<{}>(entity);\n", run_system_comp) - ); - }); - } - } -} - auto ecsact::rt_entt_codegen::system_util::is_trivial_system( ecsact_system_like_id system_id ) -> bool { diff --git a/rt_entt_codegen/shared/system_util.hh b/rt_entt_codegen/shared/system_util.hh index 7c5db14..410ad8f 100644 --- a/rt_entt_codegen/shared/system_util.hh +++ b/rt_entt_codegen/shared/system_util.hh @@ -1,29 +1,19 @@ #pragma once #include "ecsact/runtime/meta.hh" -#include "ecsact/cpp_codegen_plugin_util.hh" #include "ecsact/lang-support/lang-cc.hh" -#include "rt_entt_codegen/shared/util.hh" -#include "rt_entt_codegen/shared/ecsact_entt_details.hh" namespace ecsact::rt_entt_codegen::system_util { +using capability_t = + std::unordered_map; + /* * Checks if a system uses notify and should implement the run_system * component in its execution */ auto is_notify_system(ecsact_system_like_id system_id) -> bool; -/* - * Prints the specialized views for ecsact_system_notify_settings components - */ -auto print_system_notify_views( - ecsact::codegen_plugin_context& ctx, - const ecsact::rt_entt_codegen::ecsact_entt_system_details& details, - ecsact_system_like_id system_id, - std::string registry_name -) -> void; - auto is_trivial_system(ecsact_system_like_id system_id) -> bool; auto get_unique_view_name() -> std::string; diff --git a/rt_entt_codegen/shared/system_variant.hh b/rt_entt_codegen/shared/system_variant.hh new file mode 100644 index 0000000..1c2db02 --- /dev/null +++ b/rt_entt_codegen/shared/system_variant.hh @@ -0,0 +1,58 @@ +#pragma once + +#include +#include +#include "ecsact/runtime/common.h" + +namespace ecsact::rt_entt_codegen { +struct system_like_id_variant + : std::variant { + using variant::variant; + + operator ecsact_system_like_id() const { + return get_sys_like_id(); + } + + inline auto as_system() const -> ecsact_system_id { + assert(is_system()); + return std::get(*this); + } + + inline auto as_action() const -> ecsact_action_id { + assert(is_action()); + return std::get(*this); + } + + inline auto is_system() const -> bool { + return std::holds_alternative(*this); + } + + inline auto is_action() const -> bool { + return std::holds_alternative(*this); + } + + inline auto get_sys_like_id() const -> ecsact_system_like_id { + return std::visit( + [](auto&& arg) { return ecsact_id_cast(arg); }, + *this + ); + } +}; +} // namespace ecsact::rt_entt_codegen + +template<> +ECSACT_ALWAYS_INLINE ecsact_system_like_id ecsact_id_cast< + ecsact_system_like_id, + ecsact::rt_entt_codegen::system_like_id_variant>( + ecsact::rt_entt_codegen::system_like_id_variant v +) { + return v.get_sys_like_id(); +} + +template<> +ECSACT_ALWAYS_INLINE ecsact_decl_id +ecsact_id_cast( + ecsact::rt_entt_codegen::system_like_id_variant v +) { + return ecsact_id_cast(v.get_sys_like_id()); +} diff --git a/test/runtime_test.cc b/test/runtime_test.cc index 57f1c84..13ee741 100644 --- a/test/runtime_test.cc +++ b/test/runtime_test.cc @@ -1145,7 +1145,8 @@ TEST(Core, LazyParentSystem) { ASSERT_NE(changed_index, -1); auto initial_changed_component = test_components_c[changed_index]; - for(auto i : std::views::iota(0U, test_entities.size() - 1)) { + for([[maybe_unused]] auto i : + std::views::iota(0U, test_entities.size() - 1)) { reg.execute_systems(); } @@ -1191,7 +1192,8 @@ TEST(Core, LazyParentSystem) { ) << "different component was changed with same set of data\nindex=" << changed_index; - for(auto _ : std::views::iota(0U, test_entities.size() - 1)) { + for([[maybe_unused]] auto _ : + std::views::iota(0U, test_entities.size() - 1)) { reg.execute_systems(); } }