Skip to content

Commit 02cb091

Browse files
authored
fix: generates missing internal sorting (#115)
1 parent fa98277 commit 02cb091

File tree

9 files changed

+149
-52
lines changed

9 files changed

+149
-52
lines changed

ecsact/entt/wrapper/dynamic.hh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ auto context_generate_add(
188188

189189
const auto& component = *static_cast<const C*>(component_data);
190190
registry.template emplace<pending_add<C>>(entity, component);
191+
detail::add_system_markers_if_needed<C>(registry, entity);
191192
}
192193

193194
} // namespace ecsact::entt::wrapper::dynamic

rt_entt_codegen/core/print_sys_exec.cc

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,8 @@ static auto print_sys_exec_ctx_generate(
392392
using ecsact::cc_lang_support::cpp_identifier;
393393
using ecsact::cpp_codegen_plugin_util::block;
394394
using ecsact::meta::decl_full_name;
395+
using ecsact::rt_entt_codegen::ecsact_entt_system_details;
396+
using ecsact::rt_entt_codegen::get_all_sorted_systems;
395397
using ecsact::rt_entt_codegen::util::method_printer;
396398

397399
auto printer = //
@@ -543,6 +545,9 @@ static auto print_apply_pendings(
543545
}
544546

545547
template<typename SystemLikeID>
548+
requires(!std::is_same_v<
549+
ecsact_system_like_id,
550+
std::remove_cvref_t<SystemLikeID>>)
546551
struct print_ecsact_entt_system_details_options {
547552
SystemLikeID sys_like_id;
548553
std::string system_name;
@@ -609,8 +614,14 @@ static auto print_ecsact_entt_system_details(
609614
additional_view_components.push_back(pending_lazy_exec_struct);
610615
}
611616

612-
if(system_needs_sorted_entities(options.sys_like_id, details)) {
613-
additional_view_components.push_back(system_sorting_struct_name);
617+
constexpr auto is_system = std::is_same_v<
618+
std::remove_cvref_t<decltype(options.sys_like_id)>,
619+
ecsact_system_id>;
620+
621+
if constexpr(is_system) {
622+
if(system_needs_sorted_entities(options.sys_like_id)) {
623+
additional_view_components.push_back(system_sorting_struct_name);
624+
}
614625
}
615626

616627
if(is_notify_system(options.sys_like_id)) {
@@ -633,8 +644,10 @@ static auto print_ecsact_entt_system_details(
633644
additional_view_components
634645
);
635646

636-
if(system_needs_sorted_entities(options.sys_like_id, details)) {
637-
ctx.write("view.use<", system_sorting_struct_name, ">();\n");
647+
if constexpr(is_system) {
648+
if(system_needs_sorted_entities(options.sys_like_id)) {
649+
ctx.write("view.use<", system_sorting_struct_name, ">();\n");
650+
}
638651
}
639652

640653
block(ctx, "struct : ecsact_system_execution_context ", [&] {
@@ -825,6 +838,18 @@ static auto print_ecsact_entt_system_details(
825838
ctx,
826839
"for(ecsact::entt::entity_id entity : view_no_pending_lazy_)",
827840
[&] {
841+
ctx.write(
842+
"// If this assertion triggers this is an indicator of a codegen "
843+
"failure.\n"
844+
"// Please report to https://github.com/ecsact-dev/ecsact_rt_entt\n"
845+
);
846+
ctx.write(
847+
"assert(",
848+
options.registry_var_name,
849+
".all_of<",
850+
system_sorting_struct_name,
851+
">(entity));\n"
852+
);
828853
ctx.write("view_no_pending_lazy_count_ += 1;\n");
829854
ctx.write(
830855
options.registry_var_name,

rt_entt_codegen/core/sorting_components.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ auto ecsact::rt_entt_codegen::core::print_entity_sorting_components(
118118
auto sys_details =
119119
ecsact_entt_system_details::from_system_like(sys_like_id);
120120

121-
if(system_needs_sorted_entities(sys_id, sys_details)) {
121+
if(system_needs_sorted_entities(sys_id)) {
122122
auto sys_like_id = ecsact_id_cast<ecsact_system_like_id>(sys_id);
123123
auto sys_details =
124124
ecsact_entt_system_details::from_system_like(sys_like_id);

rt_entt_codegen/core/system_markers.cc

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,25 +45,18 @@ auto ecsact::rt_entt_codegen::core::print_system_marker_add_fn(
4545
continue;
4646
}
4747

48-
if(system_needs_sorted_entities(system_id, sys_details)) {
48+
if(system_needs_sorted_entities(system_id)) {
4949
auto system_name = ecsact::meta::decl_full_name(system_id);
5050
auto system_cpp_ident =
5151
"::" + cc_lang_support::cpp_identifier(system_name);
5252

5353
auto system_sorting_struct_name =
5454
std::format("system_sorted<{}>", system_cpp_ident);
5555

56-
block(
57-
ctx,
58-
"if(::ecsact::entt::entity_matches_system<" + system_cpp_ident +
59-
">(reg, entity))",
60-
[&] {
61-
ctx.write(
62-
"reg.emplace_or_replace<",
63-
system_sorting_struct_name,
64-
">(entity);"
65-
);
66-
}
56+
ctx.write(
57+
"reg.emplace_or_replace<",
58+
system_sorting_struct_name,
59+
">(entity);"
6760
);
6861
}
6962
}

rt_entt_codegen/shared/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ cc_library(
2020
cc_library(
2121
name = "sorting",
2222
hdrs = ["sorting.hh"],
23+
srcs = ["sorting.cc"],
2324
copts = copts,
2425
deps = [
2526
":ecsact_entt_details",

rt_entt_codegen/shared/sorting.cc

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#include "rt_entt_codegen/shared/sorting.hh"
2+
3+
#include "ecsact/runtime/meta.hh"
4+
5+
auto ecsact::rt_entt_codegen::system_needs_sorted_entities( //
6+
ecsact_system_id id
7+
) -> bool {
8+
auto needs_sorted_entities = false;
9+
10+
auto lazy_rate = ecsact_meta_get_lazy_iteration_rate(id);
11+
if(lazy_rate > 0) {
12+
needs_sorted_entities = true;
13+
}
14+
15+
return needs_sorted_entities;
16+
}
17+
18+
auto ecsact::rt_entt_codegen::get_all_sorted_systems()
19+
-> std::vector<ecsact_system_like_id> {
20+
auto sys_like_ids = std::vector<ecsact_system_like_id>{};
21+
for(auto pkg_id : ecsact::meta::get_package_ids()) {
22+
auto pkg_sys_ids = ecsact::meta::get_system_ids(pkg_id);
23+
24+
for(auto sys_id : pkg_sys_ids) {
25+
if(system_needs_sorted_entities(sys_id)) {
26+
sys_like_ids.push_back(ecsact_id_cast<ecsact_system_like_id>(sys_id));
27+
}
28+
}
29+
}
30+
31+
return sys_like_ids;
32+
}

rt_entt_codegen/shared/sorting.hh

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,10 @@
11
#pragma once
22

3-
#include <type_traits>
3+
#include <vector>
4+
45
#include "ecsact/runtime/common.h"
5-
#include "ecsact/runtime/meta.h"
6-
#include "rt_entt_codegen/shared/ecsact_entt_details.hh"
76

87
namespace ecsact::rt_entt_codegen {
9-
10-
template<typename SystemLikeID>
11-
requires(std::is_same_v<std::remove_cvref_t<SystemLikeID>, ecsact_system_id> ||
12-
std::is_same_v<std::remove_cvref_t<SystemLikeID>, ecsact_action_id>)
13-
ECSACT_ALWAYS_INLINE auto system_needs_sorted_entities(
14-
SystemLikeID id,
15-
const ecsact_entt_system_details& details
16-
) -> bool {
17-
auto sys_like_id = ecsact_id_cast<ecsact_system_like_id>(id);
18-
auto needs_sorted_entities = false;
19-
20-
if constexpr(std::is_same_v<
21-
std::remove_cvref_t<SystemLikeID>,
22-
ecsact_system_id>) {
23-
auto lazy_rate = ecsact_meta_get_lazy_iteration_rate(
24-
static_cast<ecsact_system_id>(sys_like_id)
25-
);
26-
27-
if(lazy_rate > 0) {
28-
needs_sorted_entities = true;
29-
}
30-
}
31-
32-
return needs_sorted_entities;
33-
}
8+
auto system_needs_sorted_entities(ecsact_system_id id) -> bool;
9+
auto get_all_sorted_systems() -> std::vector<ecsact_system_like_id>;
3410
} // namespace ecsact::rt_entt_codegen

test/runtime_test.cc

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,12 @@ void runtime_test::LazyParentSystem::LazyParentNestedSystem::impl( //
144144
ctx.update(comp);
145145
}
146146

147+
auto runtime_test::LazyUpdateGeneratedEntity::impl(context& ctx) -> void {
148+
auto comp = ctx.get<ComponentA>();
149+
comp.a += 1;
150+
ctx.update(comp);
151+
}
152+
147153
static std::atomic_bool AddAssocTest_ran = false;
148154

149155
void runtime_test::AddAssocTest::impl(context& ctx) {
@@ -312,8 +318,8 @@ TEST(Core, AddComponentError) {
312318
// invalid entity error.
313319
EXPECT_EQ(add_err, ECSACT_ADD_ERR_ENTITY_INVALID);
314320

315-
// When we receive an error when adding a component our component will not be
316-
// added to the registry.
321+
// When we receive an error when adding a component our component will not
322+
// be added to the registry.
317323
EXPECT_FALSE(reg.has_component<OtherEntityComponent>(entity));
318324
}
319325

@@ -761,10 +767,7 @@ TEST(Core, DynamicSystemImpl) {
761767
}
762768

763769
TEST(Core, GeneratesCreateEvent) {
764-
ecsact_set_system_execution_impl(
765-
ecsact_id_cast<ecsact_system_like_id>(runtime_test::MakeAnother::id),
766-
&runtime_test__MakeAnother
767-
);
770+
SET_SYSTEM_IMPL(MakeAnother);
768771

769772
auto reg = ecsact::core::registry("GeneratesCreateEvent");
770773

@@ -1184,6 +1187,67 @@ TEST(Core, LazyParentSystem) {
11841187
#undef CALC_CHANGED_INDEX
11851188
}
11861189

1190+
TEST(Core, LazyUpdateGeneratedEntity) {
1191+
using runtime_test::ComponentA;
1192+
using runtime_test::ComponentB;
1193+
using runtime_test::MakeAnother;
1194+
1195+
// these systems mess with ComponentA
1196+
CLEAR_SYSTEM_IMPL(AddsAutoRemovedTag);
1197+
CLEAR_SYSTEM_IMPL(SimpleSystem);
1198+
CLEAR_SYSTEM_IMPL(OtherEntitySystem);
1199+
CLEAR_SYSTEM_IMPL(AssocTestAction);
1200+
CLEAR_SYSTEM_IMPL(TestAction);
1201+
1202+
auto reg = ecsact::core::registry{"Core_LazyUpdateGeneratedEntity"};
1203+
1204+
auto test_entity = reg.create_entity();
1205+
reg.add_component(test_entity, ComponentA{});
1206+
reg.add_component(test_entity, ComponentB{});
1207+
1208+
auto exec_opts = ecsact::core::execution_options{};
1209+
auto make_another_action = MakeAnother{};
1210+
exec_opts.push_action(&make_another_action);
1211+
1212+
// generate 7 more entities from MakeAnother system impl
1213+
SET_SYSTEM_IMPL(MakeAnother);
1214+
auto err = reg.execute_systems(std::array{exec_opts, exec_opts, exec_opts});
1215+
ASSERT_EQ(err, ECSACT_EXEC_SYS_OK);
1216+
ASSERT_EQ(reg.count_entities(), 8);
1217+
CLEAR_SYSTEM_IMPL(MakeAnother);
1218+
1219+
auto count_entities_with_value = [&](int num) -> int {
1220+
auto count = 0;
1221+
for(auto entity : reg.get_entities()) {
1222+
auto comp = reg.get_component<ComponentA>(entity);
1223+
1224+
if(comp.a == num) {
1225+
count += 1;
1226+
}
1227+
}
1228+
1229+
return count;
1230+
};
1231+
1232+
// this system should increment ComponentA::a one by one
1233+
SET_SYSTEM_IMPL(LazyUpdateGeneratedEntity);
1234+
1235+
reg.execute_systems();
1236+
EXPECT_EQ(count_entities_with_value(1), 1);
1237+
1238+
reg.execute_systems();
1239+
EXPECT_EQ(count_entities_with_value(1), 2);
1240+
1241+
reg.execute_systems();
1242+
EXPECT_EQ(count_entities_with_value(1), 3);
1243+
1244+
reg.execute_systems();
1245+
EXPECT_EQ(count_entities_with_value(1), 4);
1246+
1247+
reg.execute_systems();
1248+
EXPECT_EQ(count_entities_with_value(1), 5);
1249+
}
1250+
11871251
#ifdef ECSACT_ENTT_TEST_STATIC_SYSTEM_IMPL
11881252
TEST(Core, StaticSystemImpl) {
11891253
auto reg_id = ecsact_create_registry("StaticSystemImpl");
@@ -1200,7 +1264,8 @@ TEST(Core, StaticSystemImpl) {
12001264
// Sanity check
12011265
ASSERT_EQ(comp_get->a, comp.a);
12021266

1203-
// Clear any system impls that may already be set so we can use the static one
1267+
// Clear any system impls that may already be set so we can use the static
1268+
// one
12041269
ecsact_set_system_execution_impl(
12051270
ecsact_id_cast<ecsact_system_like_id>(runtime_test::SimpleSystem::id),
12061271
nullptr

test/runtime_test.ecsact

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,10 @@ system LazyParentSystem(lazy) {
198198
}
199199
}
200200

201+
system LazyUpdateGeneratedEntity(lazy) {
202+
readwrite ComponentA;
203+
}
204+
201205
// Notify systems
202206

203207
component NotifyComponentA {

0 commit comments

Comments
 (0)