diff --git a/MODULE.bazel b/MODULE.bazel index e2f94ab..c47f50d 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -7,12 +7,12 @@ module( bazel_dep(name = "rules_cc", version = "0.0.9") bazel_dep(name = "bazel_skylib", version = "1.6.1") bazel_dep(name = "rules_ecsact", version = "0.5.2") -bazel_dep(name = "ecsact_runtime", version = "0.6.2") -bazel_dep(name = "ecsact_lang_cpp", version = "0.4.1") +bazel_dep(name = "ecsact_runtime", version = "0.6.7") +bazel_dep(name = "ecsact_lang_cpp", version = "0.4.5") bazel_dep(name = "boost.mp11", version = "1.83.0.bzl.1") bazel_dep(name = "entt", version = "3.12.2") -bazel_dep(name = "ecsact_codegen", version = "0.2.0") -bazel_dep(name = "ecsact_cli", version = "0.3.9") +bazel_dep(name = "ecsact_codegen", version = "0.3.1") +bazel_dep(name = "ecsact_cli", version = "0.3.12") bazel_dep(name = "xxhash", version = "0.8.2") bazel_dep(name = "googletest", version = "1.14.0.bcr.1") diff --git a/README.md b/README.md index 79b826b..8f0711c 100644 --- a/README.md +++ b/README.md @@ -33,25 +33,3 @@ entt::basic_view, entt::exclude_t, entt::exclude_t<>> ``` - -As soon as system association occurs there now requires multiple views to be iterated at the same time. - -```ecsact -package example; -component Health { f32 value; } -component Attacking { entity target; } -action Attack { - entity target; - adds Attacking; -} -system AttackDamage { - readonly Attacking with target { - readwrite Health; - } -} -``` - -```cpp -entt::basic_view, entt::exclude_t<>> -entt::basic_view>, entt::exclude_t<>> -``` diff --git a/ecsact/entt/detail/globals.hh b/ecsact/entt/detail/globals.hh index 791da4c..defbb14 100644 --- a/ecsact/entt/detail/globals.hh +++ b/ecsact/entt/detail/globals.hh @@ -91,76 +91,6 @@ extern const std::unordered_map< // decltype(&ecsact_has_component)> has_component_fns; -/** - * ecsact_system_execution_context_get fn pointers - * - * NOTE: This gets is filled in by ecsact_rt_entt_codegen - */ -extern const std::unordered_map< // - ecsact_system_like_id, - std::unordered_map< - ecsact::entt::assoc_index, - std::unordered_map< // - ecsact_component_like_id, - decltype(&ecsact_system_execution_context_get)>>> - exec_ctx_get_fns; - -/** - * ecsact_system_execution_context_add fn pointers - * - * NOTE: This adds is filled in by ecsact_rt_entt_codegen - */ -extern const std::unordered_map< // - ecsact_system_like_id, - std::unordered_map< - ecsact::entt::assoc_index, - std::unordered_map< // - ecsact_component_like_id, - decltype(&ecsact_system_execution_context_add)>>> - exec_ctx_add_fns; - -/** - * ecsact_system_execution_context_update fn pointers - * - * NOTE: This updates is filled in by ecsact_rt_entt_codegen - */ -extern const std::unordered_map< // - ecsact_system_like_id, - std::unordered_map< - ecsact::entt::assoc_index, - std::unordered_map< // - ecsact_component_like_id, - decltype(&ecsact_system_execution_context_update)>>> - exec_ctx_update_fns; - -/** - * ecsact_system_execution_context_remove fn pointers - * - * NOTE: This removes is filled in by ecsact_rt_entt_codegen - */ -extern const std::unordered_map< // - ecsact_system_like_id, - std::unordered_map< - ecsact::entt::assoc_index, - std::unordered_map< // - ecsact_component_like_id, - decltype(&ecsact_system_execution_context_remove)>>> - exec_ctx_remove_fns; - -/** - * ecsact_system_execution_context_has fn pointers - * - * NOTE: This has is filled in by ecsact_rt_entt_codegen - */ -extern const std::unordered_map< // - ecsact_system_like_id, - std::unordered_map< - ecsact::entt::assoc_index, - std::unordered_map< // - ecsact_component_like_id, - decltype(&ecsact_system_execution_context_has)>>> - exec_ctx_has_fns; - /** * ecsact_system_execution_context_action fn pointers * diff --git a/ecsact/entt/detail/internal_markers.hh b/ecsact/entt/detail/internal_markers.hh index 453918c..6218ce8 100644 --- a/ecsact/entt/detail/internal_markers.hh +++ b/ecsact/entt/detail/internal_markers.hh @@ -8,20 +8,6 @@ namespace ecsact::entt::detail { -template -struct association { - using component = C; - static constexpr auto field_offset = FieldOffset; - std::int_fast16_t ref_count = 0; -}; - -template -concept association_concept = // - requires { - { typename Assoc::component_type{} }; - { Assoc::field_offset } -> std::convertible_to; - }; - template struct beforeremove_storage; diff --git a/ecsact/entt/detail/system_execution_context.hh b/ecsact/entt/detail/system_execution_context.hh index 16272fb..638683e 100644 --- a/ecsact/entt/detail/system_execution_context.hh +++ b/ecsact/entt/detail/system_execution_context.hh @@ -12,24 +12,6 @@ #include "ecsact/entt/entity.hh" #include "ecsact/entt/detail/registry.hh" -namespace ecsact::entt { -/** - * Opaque index representing a system-likes association where `0` means no - * association. - */ -enum class assoc_index : unsigned; - -constexpr auto empty_assoc_index(assoc_index n) -> bool { - return n == assoc_index{}; -} - -constexpr auto underlying_assoc_index(assoc_index n) -> unsigned { - assert(!empty_assoc_index(n)); - return static_cast(n); -} - -} // namespace ecsact::entt - struct ecsact_system_execution_context { ecsact_system_like_id id; ecsact::entt::entity_id entity; @@ -81,6 +63,6 @@ struct ecsact_system_execution_context { virtual auto parent() -> const ecsact_system_execution_context* = 0; virtual auto other( // - ecsact_entity_id entity + ecsact_system_assoc_id assoc_id ) -> ecsact_system_execution_context* = 0; }; diff --git a/ecsact/entt/wrapper/core.hh b/ecsact/entt/wrapper/core.hh index 901cd1d..b326d8e 100644 --- a/ecsact/entt/wrapper/core.hh +++ b/ecsact/entt/wrapper/core.hh @@ -16,7 +16,8 @@ template inline auto has_component( // ecsact_registry_id registry_id, ecsact_entity_id entity_id, - [[maybe_unused]] ecsact_component_id component_id + [[maybe_unused]] ecsact_component_id component_id, + ... ) -> bool { auto& reg = ecsact::entt::get_registry(registry_id); auto entity = ecsact::entt::entity_id{entity_id}; @@ -28,7 +29,8 @@ template inline auto get_component( ecsact_registry_id registry_id, ecsact_entity_id entity_id, - [[maybe_unused]] ecsact_component_id component_id + [[maybe_unused]] ecsact_component_id component_id, + ... ) -> const void* { auto& reg = ecsact::entt::get_registry(registry_id); auto entity = ecsact::entt::entity_id{entity_id}; @@ -116,7 +118,8 @@ inline auto update_component( // ecsact_registry_id registry_id, ecsact_entity_id entity_id, [[maybe_unused]] ecsact_component_id component_id, - const void* component_data + const void* component_data, + ... ) -> ecsact_update_error { using ecsact::entt::detail::exec_beforechange_storage; @@ -148,7 +151,8 @@ inline auto update_component_exec_options( // ecsact_registry_id registry_id, ecsact_entity_id entity_id, [[maybe_unused]] ecsact_component_id component_id, - const void* component_data + const void* component_data, + ... ) -> ecsact_update_error { using ecsact::entt::detail::exec_beforechange_storage; @@ -184,7 +188,8 @@ template auto remove_component( ecsact_registry_id registry_id, ecsact_entity_id entity_id, - [[maybe_unused]] ecsact_component_id component_id + [[maybe_unused]] ecsact_component_id component_id, + ... ) -> void { auto& reg = ecsact::entt::get_registry(registry_id); auto entity = ecsact::entt::entity_id{entity_id}; @@ -203,7 +208,8 @@ template auto remove_component_exec_options( ecsact_registry_id registry_id, ecsact_entity_id entity_id, - [[maybe_unused]] ecsact_component_id component_id + [[maybe_unused]] ecsact_component_id component_id, + ... ) -> void { using ecsact::entt::detail::pending_remove; diff --git a/ecsact/entt/wrapper/dynamic.hh b/ecsact/entt/wrapper/dynamic.hh index 7cd6c3e..f8a2e79 100644 --- a/ecsact/entt/wrapper/dynamic.hh +++ b/ecsact/entt/wrapper/dynamic.hh @@ -70,7 +70,8 @@ template auto context_remove( ecsact_system_execution_context* context, [[maybe_unused]] ecsact_component_like_id component_id, - auto& view + auto& view, + ... ) -> void { assert(ecsact_id_cast(C::id) == component_id); @@ -125,7 +126,8 @@ auto context_get( ecsact_system_execution_context* context, [[maybe_unused]] ecsact_component_like_id component_id, void* out_component_data, - auto& view + auto& view, + ... ) -> void { auto entity = context->entity; @@ -158,7 +160,8 @@ auto context_update( template auto context_has( ecsact_system_execution_context* context, - [[maybe_unused]] ecsact_component_like_id component_id + [[maybe_unused]] ecsact_component_like_id component_id, + ... ) -> bool { auto entity = context->entity; auto& registry = *context->registry; diff --git a/rt_entt_codegen/core/print_sys_exec.cc b/rt_entt_codegen/core/print_sys_exec.cc index 846d7d6..af94143 100644 --- a/rt_entt_codegen/core/print_sys_exec.cc +++ b/rt_entt_codegen/core/print_sys_exec.cc @@ -62,7 +62,7 @@ static auto print_sys_exec_ctx_action( }); if(result == system_providers.end()) { - throw std::logic_error("print context action was not handled by providers"); + ctx.fatal("INTERNAL: print context action was not handled by providers"); } } @@ -83,7 +83,7 @@ static auto print_sys_exec_ctx_add( }); if(result == system_providers.end()) { - throw std::logic_error("print context add was not handled by providers"); + ctx.fatal("INTERNAL: print context add was not handled by providers"); } } @@ -103,7 +103,7 @@ static auto print_sys_exec_ctx_remove( }); if(result == system_providers.end()) { - throw std::logic_error("print context remove was not handled by providers"); + ctx.fatal("INTERNAL: print context remove was not handled by providers"); } } @@ -124,7 +124,7 @@ static auto print_sys_exec_ctx_get( }); if(result == system_providers.end()) { - throw std::logic_error("print context get was not handled by providers"); + ctx.fatal("INTERNAL: print context get was not handled by providers"); } } @@ -145,7 +145,7 @@ static auto print_sys_exec_ctx_update( }); if(result == system_providers.end()) { - throw std::logic_error("print context update was not handled by providers"); + ctx.fatal("INTERNAL: print context update was not handled by providers"); } } @@ -165,7 +165,7 @@ static auto print_sys_exec_ctx_has( }); if(result == system_providers.end()) { - throw std::logic_error("print context has was not handled by providers"); + ctx.fatal("INTERNAL: print context has was not handled by providers"); } } @@ -187,8 +187,7 @@ static auto print_sys_exec_ctx_generate( }); if(result == system_providers.end()) { - throw std::logic_error("print context generate was not handled by providers" - ); + ctx.fatal("INTERNAL: print context generate was not handled by providers"); } } @@ -207,7 +206,7 @@ static auto print_sys_exec_ctx_parent( // }); if(result == system_providers.end()) { - throw std::logic_error("print context parent was not handled by providers"); + ctx.fatal("INTERNAL: print context parent was not handled by providers"); } } @@ -218,7 +217,7 @@ auto print_sys_exec_ctx_other( ) -> void { auto printer = // method_printer{ctx, "other"} - .parameter("ecsact_entity_id", "entity") + .parameter("ecsact_system_assoc_id", "assoc_id") .return_type("ecsact_system_execution_context* final"); auto result = std::ranges::find_if(system_providers, [&](auto provider) { @@ -227,7 +226,7 @@ auto print_sys_exec_ctx_other( }); if(result == system_providers.end()) { - throw std::logic_error("print context other was not handled by providers"); + ctx.fatal("INTERNAL: print context other was not handled by providers"); } } @@ -353,10 +352,6 @@ static auto setup_system_providers(system_like_id_variant sys_like_id system_providers.push_back(std::make_shared(sys_like_id)); } - if(!sys_details.association_details.empty()) { - system_providers.push_back(std::make_shared(sys_like_id)); - } - if(can_entities_parallel(sys_like_id)) { system_providers.push_back(std::make_shared(sys_like_id)); } @@ -443,7 +438,7 @@ static auto print_execute_systems( }); if(result == system_providers.end()) { - throw std::logic_error("system_impl was not handled by providers"); + ctx.fatal("INTERNAL: system_impl was not handled by providers"); } } diff --git a/rt_entt_codegen/core/system_provider/association/association.cc b/rt_entt_codegen/core/system_provider/association/association.cc index 7cb084d..df0df29 100644 --- a/rt_entt_codegen/core/system_provider/association/association.cc +++ b/rt_entt_codegen/core/system_provider/association/association.cc @@ -17,11 +17,6 @@ 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( @@ -49,173 +44,19 @@ 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()) + - ")", - [&] { - auto child_ids = ecsact::meta::get_child_system_ids(sys_like_id); - if(child_ids.empty()) { - ctx.write("system_impl(&context);\n"); - } - } - ); - - return HANDLED; + return NOT_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; @@ -223,12 +64,6 @@ 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( @@ -236,13 +71,6 @@ auto provider::association::print_other_ctx_add( 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( @@ -251,12 +79,6 @@ auto provider::association::print_other_ctx_remove( 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( @@ -264,13 +86,6 @@ auto provider::association::print_other_ctx_get( 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( @@ -278,60 +93,28 @@ auto provider::association::print_other_ctx_update( 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/system_ctx_functions.cc b/rt_entt_codegen/core/system_provider/system_ctx_functions.cc index 3e40980..8844c7d 100644 --- a/rt_entt_codegen/core/system_provider/system_ctx_functions.cc +++ b/rt_entt_codegen/core/system_provider/system_ctx_functions.cc @@ -196,7 +196,7 @@ auto ecsact::rt_entt_codegen::core::provider::context_get_impl( ctx.write(std::format( "using get_fn_t = void (*)(ecsact_system_execution_context*, " - "ecsact_component_like_id, void *, {}_t&);\n", + "ecsact_component_like_id, void *, {}_t&, ...);\n", view_type_name )); @@ -394,18 +394,4 @@ auto ecsact::rt_entt_codegen::core::provider::context_other_impl( 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/rt_entt_codegen.cc b/rt_entt_codegen/rt_entt_codegen.cc index a97ee07..3464ac1 100644 --- a/rt_entt_codegen/rt_entt_codegen.cc +++ b/rt_entt_codegen/rt_entt_codegen.cc @@ -1,4 +1,5 @@ #include +#include #include "core/core.hh" #include "ecsact/runtime/meta.hh" #include "ecsact/codegen/plugin.h" @@ -20,9 +21,83 @@ constexpr auto MAIN_PACKAGE_ONLY_DISCLAIMER = R"( // Purposely empty. ecsact_rt_entt_codegen is only for the 'main' package )"; +/*** + * @returns true if detected unsupported features + */ +static auto check_unsupported_features( // + ecsact::codegen_plugin_context& ctx, + const ecsact::rt_entt_codegen::ecsact_entt_details& details +) -> bool { + auto found_assoc_feature = false; + for(auto comp_id : details.all_components) { + for(auto field_id : ecsact::meta::get_field_ids(comp_id)) { + auto field_type = ecsact::meta::get_field_type(comp_id, field_id); + if(field_type.kind == ECSACT_TYPE_KIND_BUILTIN && + field_type.type.builtin == ECSACT_ENTITY_TYPE) { + auto comp_name = ecsact::meta::decl_full_name(comp_id); + auto field_name = ecsact::meta::field_name(comp_id, field_id); + ctx.error("Assoc field found {}.{}", comp_name, field_name); + found_assoc_feature = true; + } else if(field_type.kind == ECSACT_TYPE_KIND_FIELD_INDEX) { + auto comp_name = ecsact::meta::decl_full_name(comp_id); + auto field_name = ecsact::meta::field_name(comp_id, field_id); + ctx.error("Assoc field found {}.{}", comp_name, field_name); + found_assoc_feature = true; + } + } + } + + for(auto sys_id : details.all_systems) { + auto assoc_ids = ecsact::meta::system_assoc_ids(sys_id); + if(!assoc_ids.empty()) { + found_assoc_feature = true; + auto system_name = ecsact::meta::decl_full_name(sys_id); + ctx.error("Assoc system found {}", system_name); + found_assoc_feature = true; + } + } + + for(auto act_id : details.all_actions) { + auto assoc_ids = ecsact::meta::system_assoc_ids(act_id); + if(!assoc_ids.empty()) { + found_assoc_feature = true; + auto system_name = ecsact::meta::decl_full_name(act_id); + ctx.error("Assoc action found {}", system_name); + found_assoc_feature = true; + } + + for(auto field_id : ecsact::meta::get_field_ids(act_id)) { + auto field_type = ecsact::meta::get_field_type(act_id, field_id); + if(field_type.kind == ECSACT_TYPE_KIND_BUILTIN && + field_type.type.builtin == ECSACT_ENTITY_TYPE) { + auto act_name = ecsact::meta::decl_full_name(act_id); + auto field_name = ecsact::meta::field_name(act_id, field_id); + ctx.error("Assoc field found {}.{}", act_name, field_name); + found_assoc_feature = true; + } else if(field_type.kind == ECSACT_TYPE_KIND_FIELD_INDEX) { + auto act_name = ecsact::meta::decl_full_name(act_id); + auto field_name = ecsact::meta::field_name(act_id, field_id); + ctx.error("Assoc field found {}.{}", act_name, field_name); + found_assoc_feature = true; + } + } + } + + if(found_assoc_feature) { + ctx.fatal( + "Association currently unsupported " + "https://github.com/ecsact-dev/ecsact_rt_entt/issues/138" + ); + return true; + } + + return false; +} + void ecsact_codegen_plugin( - ecsact_package_id package_id, - ecsact_codegen_write_fn_t write_fn + ecsact_package_id package_id, + ecsact_codegen_write_fn_t write_fn, + ecsact_codegen_report_fn_t report_fn ) { using ecsact::cc_lang_support::c_identifier; using ecsact::cc_lang_support::cpp_identifier; @@ -34,7 +109,7 @@ void ecsact_codegen_plugin( using ecsact::rt_entt_codegen::util::inc_package_header; using ecsact::rt_entt_codegen::util::init_global; - ecsact::codegen_plugin_context ctx{package_id, write_fn}; + ecsact::codegen_plugin_context ctx{package_id, write_fn, report_fn}; ctx.write(GENERATED_FILE_DISCLAIMER); @@ -45,6 +120,10 @@ void ecsact_codegen_plugin( auto details = ecsact_entt_details::from_package(package_id); + if(check_unsupported_features(ctx, details)) { + return; + } + inc_header(ctx, "ecsact/entt/entity.hh"); inc_header(ctx, "ecsact/entt/event_markers.hh"); inc_header(ctx, "ecsact/entt/execution.hh"); diff --git a/rt_entt_codegen/shared/comps_with_caps.hh b/rt_entt_codegen/shared/comps_with_caps.hh index 087f9cb..5ee20d8 100644 --- a/rt_entt_codegen/shared/comps_with_caps.hh +++ b/rt_entt_codegen/shared/comps_with_caps.hh @@ -21,22 +21,6 @@ auto get_all_deep_capabilities( // all_capabilities[comp_id] = static_cast( capability | all_capabilities[comp_id] ); - - auto fields = - ecsact::meta::system_association_fields(system_like_id, comp_id); - for(auto field_id : fields) { - auto assoc_comps = ecsact::meta::system_association_capabilities( - system_like_id, - comp_id, - field_id - ); - - for(auto&& [assoc_comp_id, assoc_comp_cap] : assoc_comps) { - all_capabilities[assoc_comp_id] = static_cast( - assoc_comp_cap | all_capabilities[assoc_comp_id] - ); - } - } } return all_capabilities; diff --git a/rt_entt_codegen/shared/ecsact_entt_details.cc b/rt_entt_codegen/shared/ecsact_entt_details.cc index 219d02c..28a1cd9 100644 --- a/rt_entt_codegen/shared/ecsact_entt_details.cc +++ b/rt_entt_codegen/shared/ecsact_entt_details.cc @@ -140,26 +140,6 @@ auto ecsact_entt_system_details::from_system_like( // fill_system_details(details, caps); - for(auto comp_id : details.readable_comps) { - auto fields = ecsact::meta::system_association_fields(sys_like_id, comp_id); - for(auto field_id : fields) { - auto assoc_comps = ecsact::meta::system_association_capabilities( - sys_like_id, - comp_id, - field_id - ); - - details.association_details.insert( - details.association_details.end(), - association_info{ - .component_id = comp_id, - .field_id = field_id, - .capabilities = assoc_comps, - } - ); - } - } - auto generate_ids = ecsact::meta::get_system_generates_ids(sys_like_id); for(auto gen_id : generate_ids) { auto gen_id_map = diff --git a/rt_entt_codegen/shared/ecsact_entt_details.hh b/rt_entt_codegen/shared/ecsact_entt_details.hh index cdcd316..a53fc51 100644 --- a/rt_entt_codegen/shared/ecsact_entt_details.hh +++ b/rt_entt_codegen/shared/ecsact_entt_details.hh @@ -7,13 +7,6 @@ namespace ecsact::rt_entt_codegen { -struct association_info { - ecsact_component_like_id component_id; - ecsact_field_id field_id; - std::unordered_map - capabilities; -}; - struct other_key { ecsact_component_like_id component_like_id; ecsact_field_id field_id; @@ -24,8 +17,6 @@ struct other_key { using generate_t = std::vector>; -using association_t = std::vector; - struct ecsact_entt_system_details { /** Components/transients included in EnTT view/group */ std::unordered_set get_comps; @@ -45,9 +36,6 @@ struct ecsact_entt_system_details { /** Components this system is allowed to remove */ std::unordered_set removable_comps; - /** Components with an entity association*/ - association_t association_details; - /** A map containing this system's generated component ids and its * requirements*/ generate_t generate_comps; diff --git a/rt_entt_codegen/shared/parallel.cc b/rt_entt_codegen/shared/parallel.cc index 7caa4d5..477202d 100644 --- a/rt_entt_codegen/shared/parallel.cc +++ b/rt_entt_codegen/shared/parallel.cc @@ -162,27 +162,6 @@ auto ecsact::rt_entt_codegen::parallel::can_entities_parallel( return false; } - auto other_fields = - ecsact::meta::system_association_fields(sys_like_id, comp_id); - - for(auto field_id : other_fields) { - auto other_capabilities = ecsact::meta::system_association_capabilities( - sys_like_id, - comp_id, - field_id - ); - - // NOTE(Kelwan): Association is currently not compatible with executing - // entities in parallel. - for([[maybe_unused]] const auto [other_comp_id, other_capability] : - other_capabilities) { - return false; - // if(!is_capability_safe_entities(sys_like_id, other_capability)) { - // return false; - // } - } - } - if(sys_like_id.is_system()) { int lazy_iteration_rate = ecsact_meta_get_lazy_iteration_rate(sys_like_id.as_system()); @@ -280,30 +259,6 @@ static auto loop_iterator( return; } } - - auto other_fields = - ecsact::meta::system_association_fields(sys_like_id, comp_id); - - for(auto field_id : other_fields) { - auto other_capabilities = ecsact::meta::system_association_capabilities( - sys_like_id, - comp_id, - field_id - ); - - for(const auto [other_comp_id, other_capability] : other_capabilities) { - auto cpp_name = decl_full_name(other_comp_id); - if(!is_capability_safe(other_capability)) { - if(!unsafe_comps.contains(other_comp_id)) { - unsafe_comps.insert(other_comp_id); - } else { - parallel_system_cluster.push_back(parallel_system_list); - loop_iterator(system_list, iterator, parallel_system_cluster); - return; - } - } - } - } } for(auto unsafe_comp : child_unsafe_comps) { diff --git a/runtime/ecsact_rt_entt_core.cc b/runtime/ecsact_rt_entt_core.cc index 8418c56..7dea449 100644 --- a/runtime/ecsact_rt_entt_core.cc +++ b/runtime/ecsact_rt_entt_core.cc @@ -109,7 +109,8 @@ ecsact_add_error ecsact_add_component( bool ecsact_has_component( ecsact_registry_id reg_id, ecsact_entity_id entity_id, - ecsact_component_id component_id + ecsact_component_id component_id, + ... ) { using ecsact::entt::detail::globals::has_component_fns; auto fn_itr = has_component_fns.find(component_id); @@ -120,7 +121,8 @@ bool ecsact_has_component( const void* ecsact_get_component( ecsact_registry_id reg_id, ecsact_entity_id entity_id, - ecsact_component_id component_id + ecsact_component_id component_id, + ... ) { using ecsact::entt::detail::globals::get_component_fns; auto fn_itr = get_component_fns.find(component_id); @@ -195,7 +197,8 @@ ecsact_update_error ecsact_update_component( ecsact_registry_id reg_id, ecsact_entity_id entity_id, ecsact_component_id component_id, - const void* component_data + const void* component_data, + ... ) { using ecsact::entt::detail::globals::update_component_fns; auto fn_itr = update_component_fns.find(component_id); @@ -206,7 +209,8 @@ ecsact_update_error ecsact_update_component( void ecsact_remove_component( ecsact_registry_id reg_id, ecsact_entity_id entity_id, - ecsact_component_id component_id + ecsact_component_id component_id, + ... ) { using ecsact::entt::detail::globals::remove_component_fns; auto fn_itr = remove_component_fns.find(component_id); diff --git a/runtime/ecsact_rt_entt_dynamic.cc b/runtime/ecsact_rt_entt_dynamic.cc index 8b5b829..f334e0b 100644 --- a/runtime/ecsact_rt_entt_dynamic.cc +++ b/runtime/ecsact_rt_entt_dynamic.cc @@ -60,10 +60,10 @@ ecsact_system_like_id ecsact_system_execution_context_id( ecsact_system_execution_context* ecsact_system_execution_context_other( ecsact_system_execution_context* context, - ecsact_entity_id entity_id + ecsact_system_assoc_id assoc_id ) { assert(context != nullptr); - return context->other(entity_id); + return context->other(assoc_id); } void ecsact_system_execution_context_add( @@ -77,7 +77,8 @@ void ecsact_system_execution_context_add( void ecsact_system_execution_context_remove( ecsact_system_execution_context* context, - ecsact_component_like_id comp_id + ecsact_component_like_id comp_id, + ... ) { assert(context != nullptr); return context->remove(comp_id); @@ -86,7 +87,8 @@ void ecsact_system_execution_context_remove( void ecsact_system_execution_context_get( ecsact_system_execution_context* context, ecsact_component_like_id comp_id, - void* out_component_data + void* out_component_data, + ... ) { assert(context != nullptr); return context->get(comp_id, out_component_data); @@ -95,7 +97,8 @@ void ecsact_system_execution_context_get( void ecsact_system_execution_context_update( ecsact_system_execution_context* context, ecsact_component_like_id comp_id, - const void* component_data + const void* component_data, + ... ) { assert(context != nullptr); return context->update(comp_id, component_data); @@ -103,7 +106,8 @@ void ecsact_system_execution_context_update( bool ecsact_system_execution_context_has( ecsact_system_execution_context* context, - ecsact_component_like_id comp_id + ecsact_component_like_id comp_id, + ... ) { assert(context != nullptr); return context->has(comp_id); diff --git a/runtime/index.bzl b/runtime/index.bzl index 238b050..648fe05 100644 --- a/runtime/index.bzl +++ b/runtime/index.bzl @@ -28,7 +28,6 @@ def ecsact_entt_runtime(name, srcs = [], deps = [], system_impls = [], tags = [] "@ecsact_lang_cpp//cpp_header_codegen", "@ecsact_lang_cpp//cpp_systems_header_codegen", "@ecsact_lang_cpp//systems_header_codegen", - "@ecsact_lang_cpp//cpp_meta_header_codegen", ], output_directory = "_%s__public_hdrs" % name, **kwargs @@ -42,7 +41,6 @@ def ecsact_entt_runtime(name, srcs = [], deps = [], system_impls = [], tags = [] strip_include_prefix = "_%s__public_hdrs" % name, deps = [ "@ecsact_lang_cpp//:execution_context", - "@ecsact_lang_cpp//:type_info", ], **kwargs ) diff --git a/test/MODULE.bazel b/test/MODULE.bazel index 5c51c23..c5f167f 100644 --- a/test/MODULE.bazel +++ b/test/MODULE.bazel @@ -4,12 +4,12 @@ bazel_dep(name = "rules_cc", version = "0.0.9") bazel_dep(name = "bazel_skylib", version = "1.5.0") bazel_dep(name = "googletest", version = "1.14.0") bazel_dep(name = "rules_ecsact", version = "0.5.2") -bazel_dep(name = "ecsact_lang_cpp", version = "0.4.1") -bazel_dep(name = "ecsact_runtime", version = "0.6.1") +bazel_dep(name = "ecsact_lang_cpp", version = "0.4.5") +bazel_dep(name = "ecsact_runtime", version = "0.6.7") bazel_dep(name = "boost.mp11", version = "1.83.0.bzl.1") bazel_dep(name = "boost.dll", version = "1.83.0.bzl.2") bazel_dep(name = "entt", version = "3.12.2") -bazel_dep(name = "ecsact_cli", version = "0.3.9") +bazel_dep(name = "ecsact_cli", version = "0.3.12") bazel_dep(name = "boost.process", version = "1.83.0.bzl.2") bazel_dep(name = "toolchains_llvm", version = "1.0.0", dev_dependency = True) diff --git a/test/parallel/parallel_test.cc b/test/parallel/parallel_test.cc index 0a6aaed..7c34bb8 100644 --- a/test/parallel/parallel_test.cc +++ b/test/parallel/parallel_test.cc @@ -11,9 +11,6 @@ void parallel_test::ActionParallelA::impl(context& ctx) { } -void parallel_test::EntityAssociationConflictA::impl(context& ctx) { -} - void parallel_test::ParentSystemConflictA::impl(context& ctx) { } diff --git a/test/parallel/parallel_test.ecsact b/test/parallel/parallel_test.ecsact index 36fa64b..2b0c312 100644 --- a/test/parallel/parallel_test.ecsact +++ b/test/parallel/parallel_test.ecsact @@ -6,20 +6,11 @@ component ParallelA { component ParallelB { i32 val; } -component ParallelC { - entity target; -} action ActionParallelA { readonly ParallelA; } -system EntityAssociationConflictA { - readonly ParallelC with target { - readwrite ParallelA; - } -} - system ParentSystemConflictA { readonly ParallelA; system NestedSystemConflictA { diff --git a/test/runtime_test.cc b/test/runtime_test.cc index 0aaaae4..4a43896 100644 --- a/test/runtime_test.cc +++ b/test/runtime_test.cc @@ -14,7 +14,6 @@ #include "runtime_test.ecsact.systems.hh" using runtime_test::ComponentA; -using runtime_test::OtherEntityComponent; #define SET_SYSTEM_IMPL(SystemName) \ ASSERT_TRUE(ecsact_set_system_execution_impl( \ @@ -33,17 +32,6 @@ void runtime_test::SimpleSystem::impl(context& ctx) { ctx.update(comp); } -void runtime_test::OtherEntitySystem::impl(context& ctx) { - auto comp = ctx.get(); - auto other = ctx._ctx.other(comp.target); - auto other_comp = other.get(); - - comp.num += -other_comp.a; - - ctx.update(comp); - other.update(other_comp); -} - void runtime_test::MakeAnother::impl(context& ctx) { ctx._ctx.generate(ctx.get(), ctx.get()); } @@ -81,33 +69,6 @@ void imported::test_pkg::ImportedSystem::impl(context& ctx) { ctx.update(comp); } -static std::atomic_bool AssocTestAction_ran = false; - -void runtime_test::AssocTestAction::impl(context& ctx) { - AssocTestAction_ran = true; - ctx.add(OtherEntityComponent{ - .num = 42, - .target = ctx.action().assoc_entity, - }); -} - -void runtime_test::AttackDamage::impl(context& ctx) { - // auto attacking = ctx.get(); - // auto target_ctx = ctx._ctx.other(attacking.target); - // auto target_health = target_ctx.get(); - // target_health.value -= 1.f; - // target_ctx.update(target_health); -} - -void runtime_test::AttackDamageWeakened::impl(context& ctx) { - // auto attacking = ctx.get(); - // auto target_ctx = ctx._ctx.other(attacking.target); - // auto target_health = target_ctx.get(); - // auto target_weakened = target_ctx.get(); - // target_health.value -= 1.f * target_weakened.value; - // target_ctx.update(target_health); -} - void runtime_test::AddsAutoRemovedTag::impl(context& ctx) { } @@ -150,29 +111,6 @@ auto runtime_test::LazyUpdateGeneratedEntity::impl(context& ctx) -> void { ctx.update(comp); } -static std::atomic_bool AddAssocTest_ran = false; - -void runtime_test::AddAssocTest::impl(context& ctx) { - AddAssocTest_ran = true; - auto other_entity = ctx.get(); - - // Get Target other context from OtherEntityComponent - auto target_ctx = ctx._ctx.other(other_entity.target); - assert(target_ctx._ctx != nullptr); - target_ctx.add(AddAssocTestComponent{.num = 10}); -} - -static std::atomic_bool RemoveAssocTest_ran = false; - -void runtime_test::RemoveAssocTest::impl(context& ctx) { - RemoveAssocTest_ran = true; - auto other_entity = ctx.get(); - - // Get Target other context from OtherEntityComponent - auto target_ctx = ctx._ctx.other(other_entity.target); - target_ctx.remove(); -} - void runtime_test::TestTwoAdds::impl(context& ctx) { } @@ -317,24 +255,6 @@ TEST(Core, AddComponent) { EXPECT_TRUE(ecsact_has_component(reg_id, entity, comp_id)); } -TEST(Core, AddComponentError) { - auto reg = ecsact::core::registry("AddComponentError"); - auto entity = reg.create_entity(); - ecsact_entity_id invalid_entity = - static_cast((int)entity + 1); - - OtherEntityComponent comp{.num = 42, .target = invalid_entity}; - - auto add_err = reg.add_component(entity, comp); - // We tried to add a component with an invalid entity ID. We should get an - // invalid entity error. - EXPECT_EQ(add_err, ECSACT_ADD_ERR_ENTITY_INVALID); - - // When we receive an error when adding a component our component will not - // be added to the registry. - EXPECT_FALSE(reg.has_component(entity)); -} - TEST(Core, HasComponent) { auto reg_id = ecsact_create_registry("HasComponent"); auto entity = ecsact_create_entity(reg_id); @@ -379,27 +299,6 @@ TEST(Core, UpdateComponent) { EXPECT_EQ(*comp_get, upped_comp); } -TEST(Core, UpdateComponentError) { - auto reg = ecsact::core::registry("UpdateComponentError"); - auto entity = reg.create_entity(); - auto other_entity = reg.create_entity(); - ecsact_entity_id invalid_entity = - static_cast((int)other_entity + 1); - - OtherEntityComponent comp{.num = 42, .target = other_entity}; - - auto add_err = reg.add_component(entity, comp); - ASSERT_EQ(add_err, ECSACT_ADD_OK); - - comp.num = 43; - comp.target = invalid_entity; - auto update_err = reg.update_component(entity, comp); - - // We tried to update the component with an invalid entity ID. We should get - // an invalid entity error. - EXPECT_EQ(update_err, ECSACT_UPDATE_ERR_ENTITY_INVALID); -} - TEST(Core, RemoveComponent) { auto reg_id = ecsact_create_registry("RemoveComponent"); auto entity = ecsact_create_entity(reg_id); @@ -496,274 +395,22 @@ TEST(Core, EventCollector) { } } -TEST(Core, ExecuteSystemsErrors) { - auto reg = ecsact::core::registry("ExecuteSystemsErrors"); - auto options = ecsact::core::execution_options{}; - auto test_action = runtime_test::AssocTestAction{ - .assoc_entity = static_cast(4000), - }; - options.push_action(&test_action); - - auto exec_err = reg.execute_systems(std::array{options}); - - EXPECT_EQ(exec_err, ECSACT_EXEC_SYS_ERR_ACTION_ENTITY_INVALID); -} - -TEST(Core, ExecuteSystemsAssocActionOk) { - auto reg = ecsact::core::registry("ExecuteSystemsErrors"); - auto test_entity = reg.create_entity(); - - auto options = ecsact::core::execution_options{}; - auto test_action = runtime_test::AssocTestAction{ - .assoc_entity = test_entity, - }; - - options.push_action(&test_action); - - auto exec_err = reg.execute_systems(std::array{options}); - EXPECT_EQ(exec_err, ECSACT_EXEC_SYS_OK); -} - -TEST(Core, AddAssocOk) { - ecsact_set_system_execution_impl( - ecsact_id_cast(runtime_test::AssocTestAction::id), - &runtime_test__AssocTestAction - ); - ecsact_set_system_execution_impl( - ecsact_id_cast(runtime_test::AddAssocTest::id), - &runtime_test__AddAssocTest - ); - - auto reg = ecsact::core::registry("AddAssocOk"); - auto test_entity1 = reg.create_entity(); - reg.add_component( - test_entity1, - runtime_test::ComponentA{ - .a = 42, - } - ); - - auto test_entity2 = reg.create_entity(); - reg.add_component(test_entity2); - - auto options = ecsact::core::execution_options{}; - auto test_action = runtime_test::AssocTestAction{ - .assoc_entity = test_entity2, - }; - - options.push_action(&test_action); - AddAssocTest_ran = false; - AssocTestAction_ran = false; - auto exec_err = reg.execute_systems(std::array{options}); - EXPECT_TRUE(AddAssocTest_ran) << "AddAssocTest Impl Didn't Execute"; - EXPECT_TRUE(AssocTestAction_ran) << "AssocTestAction Impl Didn't Execute"; - EXPECT_EQ(exec_err, ECSACT_EXEC_SYS_OK); - - exec_err = ecsact_execute_systems(reg.id(), 1, nullptr, nullptr); - EXPECT_EQ(exec_err, ECSACT_EXEC_SYS_OK); -} - -TEST(Core, RemoveAssocOk) { - ecsact_set_system_execution_impl( - ecsact_id_cast(runtime_test::AssocTestAction::id), - &runtime_test__AssocTestAction - ); - ecsact_set_system_execution_impl( - ecsact_id_cast(runtime_test::RemoveAssocTest::id), - &runtime_test__RemoveAssocTest - ); - - auto reg = ecsact::core::registry("RemoveAssocOk"); - auto test_entity2 = reg.create_entity(); - reg.add_component(test_entity2); - reg.add_component( - test_entity2, - runtime_test::RemoveAssocTestComponent{ - .num = 42, - } - ); - - auto test_entity1 = reg.create_entity(); - reg.add_component( - test_entity1, - runtime_test::OtherEntityComponent{ - .target = test_entity2, - } - ); - - auto test_entity3 = reg.create_entity(); - reg.add_component( - test_entity3, - runtime_test::OtherEntityComponent{ - .target = test_entity2, - } - ); - - RemoveAssocTest_ran = false; - reg.execute_systems(); - EXPECT_TRUE(RemoveAssocTest_ran) << "RemoveAssocTest Impl Didn't Executed"; - - ASSERT_FALSE( - reg.has_component(test_entity2) - ); - - reg.execute_systems(); - - reg.add_component( - test_entity2, - runtime_test::RemoveAssocTestComponent{ - .num = 42, - } - ); - - reg.execute_systems(); - - ASSERT_FALSE( - reg.has_component(test_entity2) - ); -} - -TEST(Core, AssociationEntityCorrectness) { - using runtime_test::AttackDamage; - using runtime_test::AttackDamageWeakened; - - static auto reg = ecsact::core::registry("AssociationEntityCorrectness"); - static auto attacker_entities = std::unordered_set{ - reg.create_entity(), - reg.create_entity(), - reg.create_entity(), - }; - static auto weakened_target_entities = std::unordered_set{ - reg.create_entity(), - reg.create_entity(), - }; - static auto target_entities = std::unordered_set{ - reg.create_entity(), - }; - - static auto all_target_entities = []() { - std::unordered_set all_target_entities( - weakened_target_entities.begin(), - weakened_target_entities.end() - ); - all_target_entities.insert(target_entities.begin(), target_entities.end()); - return all_target_entities; - }(); - - for(auto target : all_target_entities) { - ASSERT_EQ( - ECSACT_ADD_OK, - reg.add_component(target, runtime_test::Health{0.5f}) - ); - } - - for(auto target : weakened_target_entities) { - ASSERT_EQ( - ECSACT_ADD_OK, - reg.add_component(target, runtime_test::Weakened{0.5f}) - ); - } - - { - assert(attacker_entities.size() == all_target_entities.size()); - auto attacker_itr = attacker_entities.begin(); - auto target_itr = all_target_entities.begin(); - for(; attacker_itr != attacker_entities.end(); - ++attacker_itr, ++target_itr) { - ASSERT_EQ( - ECSACT_ADD_OK, - reg.add_component(*attacker_itr, runtime_test::Attacking{*target_itr}) - ); - } - } - - auto print_attack_targets = [&] { - for(auto attacker : attacker_entities) { - auto attacking = reg.get_component(attacker); - std::cout << (int)attacker << " is attacking " << (int)attacking.target - << "\n"; - } - }; - - print_attack_targets(); - - static std::atomic_int attack_damage_exec_count = 0; - static std::atomic_int attack_damage_weakened_exec_count = 0; - - ecsact_set_system_execution_impl( - ecsact_id_cast(AttackDamageWeakened::id), - [](ecsact_system_execution_context* cctx) { - ++attack_damage_weakened_exec_count; - ecsact::execution_context ctx{cctx}; - ASSERT_TRUE(attacker_entities.contains(ctx.entity())); - auto target_ctx = ctx.other(ctx.get().target); - ASSERT_TRUE(weakened_target_entities.contains(target_ctx.entity())); - } - ); - - ecsact_set_system_execution_impl( - ecsact_id_cast(AttackDamage::id), - [](ecsact_system_execution_context* cctx) { - ++attack_damage_exec_count; - ecsact::execution_context ctx{cctx}; - ASSERT_TRUE(attacker_entities.contains(ctx.entity())); - - // Sanity check - no exception - ctx.other(ctx.get().target); - } - ); - - attack_damage_exec_count = 0; - attack_damage_weakened_exec_count = 0; - reg.execute_systems(); - EXPECT_EQ(attack_damage_exec_count, all_target_entities.size()); - EXPECT_EQ(attack_damage_weakened_exec_count, weakened_target_entities.size()); - - for(auto target_entity : target_entities) { - for(auto attack_entity : attacker_entities) { - reg.update_component( - attack_entity, - runtime_test::Attacking{target_entity} - ); - } - - attack_damage_exec_count = 0; - attack_damage_weakened_exec_count = 0; - reg.execute_systems(); - EXPECT_EQ(attack_damage_exec_count, attacker_entities.size()); - } -} - TEST(Core, DynamicSystemImpl) { auto reg = ecsact::core::registry("DynamicSystemImpl"); auto entity = reg.create_entity(); - auto other_entity = reg.create_entity(); ComponentA comp{.a = 42}; reg.add_component(entity, comp); - reg.add_component(other_entity, comp); - - OtherEntityComponent other_comp{.num = 3, .target = other_entity}; - ASSERT_EQ(reg.add_component(entity, other_comp), ECSACT_ADD_OK); // Sanity check ASSERT_TRUE(reg.has_component(entity)); ASSERT_EQ(reg.get_component(entity), comp); - ASSERT_TRUE(reg.has_component(other_entity)); - ASSERT_EQ(reg.get_component(other_entity), comp); - ASSERT_TRUE(reg.has_component(entity)); - ASSERT_EQ(reg.get_component(entity), other_comp); ecsact_set_system_execution_impl( ecsact_id_cast(runtime_test::SimpleSystem::id), &runtime_test__SimpleSystem ); - ecsact_set_system_execution_impl( - ecsact_id_cast(runtime_test::OtherEntitySystem::id), - &runtime_test__OtherEntitySystem - ); - reg.execute_systems(); // Sanity check @@ -1216,8 +863,6 @@ TEST(Core, LazyUpdateGeneratedEntity) { // these systems mess with ComponentA CLEAR_SYSTEM_IMPL(AddsAutoRemovedTag); CLEAR_SYSTEM_IMPL(SimpleSystem); - CLEAR_SYSTEM_IMPL(OtherEntitySystem); - CLEAR_SYSTEM_IMPL(AssocTestAction); CLEAR_SYSTEM_IMPL(TestAction); auto reg = ecsact::core::registry{"Core_LazyUpdateGeneratedEntity"}; diff --git a/test/runtime_test.ecsact b/test/runtime_test.ecsact index a2b71f3..b92a30a 100644 --- a/test/runtime_test.ecsact +++ b/test/runtime_test.ecsact @@ -10,23 +10,10 @@ component ComponentB { i32 b; } -component OtherEntityComponent { - i32 num; - entity target; -} - component Health { f32 value; } -component Weakened { - f32 value; -} - -component Attacking { - entity target; -} - component EmptyComponent; component AlwaysRemoveMe; @@ -44,12 +31,6 @@ system TrivialRemove { removes TrivialRemoveComponent; } -system OtherEntitySystem { - readwrite OtherEntityComponent with target { - readwrite ComponentA; - } -} - system AlwaysRemove { removes AlwaysRemoveMe; } @@ -63,56 +44,10 @@ action MakeAnother { } } -action AssocTestAction { - entity assoc_entity; - readwrite ComponentA; - adds OtherEntityComponent; -} - action TestAction { readwrite ComponentA; } -component AddAssocTestComponent { - i32 num; -} - -component AddAssocTestTag; - -system AddAssocTest { - readwrite ComponentA; - readwrite OtherEntityComponent with target { - include AddAssocTestTag; - adds AddAssocTestComponent; - } -} - -component RemoveAssocTestComponent { - i32 num; -} - -component RemoveAssocTestTag; - -system RemoveAssocTest { - readwrite OtherEntityComponent with target { - include RemoveAssocTestTag; - removes RemoveAssocTestComponent; - } -} - -system AttackDamage { - readwrite Attacking with target { - readwrite Health; - } -} - -system AttackDamageWeakened { - readwrite Attacking with target { - readwrite Health; - readonly Weakened; - } -} - component EntityTesting { i32 a; }