Skip to content

Commit 115874a

Browse files
committed
feat: add onchange for systems
1 parent fa98277 commit 115874a

File tree

13 files changed

+419
-26
lines changed

13 files changed

+419
-26
lines changed

ecsact/entt/detail/apply_pending.hh

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ auto apply_pending_add(::entt::registry& registry) -> void {
1313
registry.emplace<C>(entity);
1414
});
1515
} else {
16-
registry.view<pending_add<C>>().each(
16+
registry.view<pending_add<C>>().each( //
1717
[&](auto entity, const pending_add<C>& comp) {
1818
registry.emplace<C>(entity, comp.value);
19-
registry.emplace<beforechange_storage<C>>(entity, comp.value, false);
19+
registry
20+
.emplace<exec_beforechange_storage<C>>(entity, comp.value, false);
2021
}
2122
);
2223
}
@@ -27,7 +28,7 @@ template<typename C>
2728
auto apply_pending_remove(::entt::registry& registry) -> void {
2829
registry.view<pending_remove<C>>().each([&](auto entity) {
2930
if constexpr(!std::is_empty_v<C>) {
30-
registry.erase<beforechange_storage<C>>(entity);
31+
registry.erase<exec_beforechange_storage<C>>(entity);
3132
}
3233
registry.erase<C>(entity);
3334
});

ecsact/entt/detail/internal_markers.hh

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,17 @@ struct beforeremove_storage<C> {
3737

3838
template<typename C>
3939
requires(!std::is_empty_v<C>)
40-
struct beforechange_storage {
40+
struct exec_beforechange_storage {
4141
C value;
4242
bool has_update_occurred = false;
4343
};
4444

45+
template<typename C>
46+
requires(!std::is_empty_v<C>)
47+
struct exec_itr_beforechange_storage {
48+
C value;
49+
};
50+
4551
template<typename C>
4652
struct pending_add;
4753

@@ -107,4 +113,18 @@ auto remove_system_markers_if_needed( //
107113
)");
108114
}
109115

116+
template<typename C>
117+
auto add_exec_itr_beforechange_if_needed( //
118+
::entt::registry&,
119+
ecsact::entt::entity_id
120+
) -> void {
121+
static_assert(system_markers_unimplemented_by_codegen<C>, R"(
122+
-----------------------------------------------------------------------------
123+
| (!) CODEGEN ERROR |
124+
| `add_exec_itr_beforechange_if_needed<>` template specialization cannot be found |
125+
| This is typically generated by ecsact_rt_entt_codegen. |
126+
-----------------------------------------------------------------------------
127+
)");
128+
}
129+
110130
} // namespace ecsact::entt::detail

ecsact/entt/wrapper/core.hh

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ inline auto add_component( //
5959
if constexpr(std::is_empty_v<C>) {
6060
reg.emplace<C>(entity);
6161
} else {
62-
reg.emplace<detail::beforechange_storage<C>>(
62+
reg.emplace<detail::exec_beforechange_storage<C>>(
6363
entity,
6464
*static_cast<const C*>(component_data),
6565
false
@@ -68,6 +68,7 @@ inline auto add_component( //
6868
}
6969

7070
ecsact::entt::detail::add_system_markers_if_needed<C>(reg, entity);
71+
ecsact::entt::detail::add_exec_itr_beforechange_if_needed<C>(reg, entity);
7172
}
7273

7374
return err;
@@ -96,14 +97,15 @@ inline auto add_component_exec_options( //
9697
if constexpr(std::is_empty_v<C>) {
9798
reg.emplace<C>(entity);
9899
} else {
99-
reg.emplace<detail::beforechange_storage<C>>(
100+
reg.emplace<detail::exec_beforechange_storage<C>>(
100101
entity,
101102
*static_cast<const C*>(component_data)
102103
);
103104
reg.emplace<C>(entity, *static_cast<const C*>(component_data));
104105
}
105106
reg.template emplace_or_replace<component_added<C>>(entity);
106107
ecsact::entt::detail::add_system_markers_if_needed<C>(reg, entity);
108+
ecsact::entt::detail::add_exec_itr_beforechange_if_needed<C>(reg, entity);
107109
}
108110

109111
return err;
@@ -172,7 +174,7 @@ auto remove_component(
172174

173175
reg.remove<C>(entity);
174176
if constexpr(!std::is_empty_v<C>) {
175-
reg.remove<detail::beforechange_storage<C>>(entity);
177+
reg.remove<detail::exec_beforechange_storage<C>>(entity);
176178
}
177179
reg.template remove<component_added<C>>(entity);
178180
reg.template remove<component_updated<C>>(entity);
@@ -205,7 +207,7 @@ auto remove_component_exec_options(
205207
reg.template emplace_or_replace<component_removed<C>>(entity);
206208

207209
if constexpr(!std::is_empty_v<C>) {
208-
reg.template remove<detail::beforechange_storage<C>>(entity);
210+
reg.template remove<detail::exec_beforechange_storage<C>>(entity);
209211
}
210212

211213
ecsact::entt::detail::remove_system_markers_if_needed<C>(reg, entity);
@@ -294,7 +296,7 @@ auto _trigger_update_component_event(
294296
ecsact::entt::detail::execution_events_collector& events_collector
295297
) -> void {
296298
using ecsact::entt::component_updated;
297-
using ecsact::entt::detail::beforechange_storage;
299+
using ecsact::entt::detail::exec_beforechange_storage;
298300

299301
if(!events_collector.has_update_callback()) {
300302
return;
@@ -304,12 +306,13 @@ auto _trigger_update_component_event(
304306
if constexpr(!C::transient && !std::is_empty_v<C>) {
305307
::entt::basic_view changed_view{
306308
reg.template storage<C>(),
307-
reg.template storage<beforechange_storage<C>>(),
309+
reg.template storage<exec_beforechange_storage<C>>(),
308310
reg.template storage<component_updated<C>>(),
309311
};
310312

311313
for(ecsact::entt::entity_id entity : changed_view) {
312-
auto& before = changed_view.template get<beforechange_storage<C>>(entity);
314+
auto& before =
315+
changed_view.template get<exec_beforechange_storage<C>>(entity);
313316
auto& current = changed_view.template get<C>(entity);
314317
before.has_update_occurred = false;
315318

@@ -403,9 +406,33 @@ inline auto prepare_component(ecsact_registry_id registry_id) -> void {
403406
reg.template storage<component_removed<C>>();
404407

405408
if constexpr(!std::is_empty_v<C>) {
406-
reg.storage<detail::beforechange_storage<C>>();
409+
reg.storage<detail::exec_beforechange_storage<C>>();
407410
reg.template storage<component_updated<C>>();
408411
}
409412
}
410413

414+
template<typename C, typename V>
415+
auto has_component_changed(entt::entity_id entity, V& view) -> bool {
416+
using detail::exec_itr_beforechange_storage;
417+
418+
const auto& current_comp = view.template get<C>(entity);
419+
const auto& before_comp =
420+
view.template get<exec_itr_beforechange_storage<C>>(entity);
421+
422+
if(before_comp.value != current_comp) {
423+
return true;
424+
}
425+
return false;
426+
}
427+
428+
template<typename C>
429+
auto update_exec_itr_beforechange(entt::entity_id entity, ::entt::registry& reg)
430+
-> void {
431+
auto comp = reg.get<C>(entity);
432+
auto& beforechange_comp =
433+
reg.get<detail::exec_itr_beforechange_storage<C>>(entity);
434+
435+
beforechange_comp.value = comp;
436+
}
437+
411438
} // namespace ecsact::entt::wrapper::core

ecsact/entt/wrapper/dynamic.hh

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ auto context_add(
2020
) -> void {
2121
using ecsact::entt::component_added;
2222
using ecsact::entt::component_removed;
23-
using ecsact::entt::detail::beforechange_storage;
2423
using ecsact::entt::detail::beforeremove_storage;
24+
using ecsact::entt::detail::exec_beforechange_storage;
2525
using ecsact::entt::detail::pending_add;
2626

2727
assert(ecsact_id_cast<ecsact_component_like_id>(C::id) == component_id);
@@ -34,7 +34,6 @@ auto context_add(
3434
} else {
3535
const C* component = static_cast<const C*>(component_data);
3636
registry.template emplace_or_replace<pending_add<C>>(entity, *component);
37-
3837
registry.template remove<beforeremove_storage<C>>(entity);
3938
}
4039

@@ -54,8 +53,6 @@ auto component_add_trivial(
5453
) -> void {
5554
using ecsact::entt::component_added;
5655
using ecsact::entt::component_removed;
57-
using ecsact::entt::detail::beforechange_storage;
58-
using ecsact::entt::detail::beforeremove_storage;
5956
using ecsact::entt::detail::pending_add;
6057

6158
registry.template emplace_or_replace<pending_add<C>>(entity_id);
@@ -146,7 +143,7 @@ auto context_update(
146143
const void* in_component_data
147144
) -> void {
148145
using ecsact::entt::component_updated;
149-
using ecsact::entt::detail::beforechange_storage;
146+
using ecsact::entt::detail::exec_beforechange_storage;
150147
// TODO(Kelwan): for remove, beforeremove_storage
151148

152149
auto entity = context->entity;
@@ -155,7 +152,8 @@ auto context_update(
155152
const auto& in_component = *static_cast<const C*>(in_component_data);
156153

157154
auto& current_component = registry.template get<C>(entity);
158-
auto& beforechange = registry.template get<beforechange_storage<C>>(entity);
155+
auto& beforechange =
156+
registry.template get<exec_beforechange_storage<C>>(entity);
159157
if(!beforechange.has_update_occurred) {
160158
beforechange.value = current_component;
161159
beforechange.has_update_occurred = true;

rt_entt_codegen/core/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ _CORE_CODEGEN_METHODS = {
3232
],
3333
"system_markers": [
3434
"//rt_entt_codegen/shared:sorting",
35+
"//rt_entt_codegen/shared:system_util",
3536
],
3637
"system_notify": ["//rt_entt_codegen/shared:system_util"],
38+
"update_beforechange": [],
3739
}
3840

3941
[cc_library(

rt_entt_codegen/core/core.hh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ auto print_system_marker_remove_fn(
6666
const ecsact_entt_details& details
6767
) -> void;
6868

69+
auto print_add_sys_beforestorage_fn(
70+
codegen_plugin_context& ctx,
71+
const ecsact_entt_details& details
72+
) -> void;
73+
6974
auto print_cleanup_system_notifies(
7075
codegen_plugin_context& ctx,
7176
const ecsact_entt_details& details
@@ -76,4 +81,9 @@ auto print_entity_match_fn(
7681
const ecsact_entt_details& details
7782
) -> void;
7883

84+
auto print_update_all_beforechange_storage(
85+
codegen_plugin_context& ctx,
86+
const ecsact_entt_details& details
87+
) -> void;
88+
7989
} // namespace ecsact::rt_entt_codegen::core

rt_entt_codegen/core/execute_systems.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ auto ecsact::rt_entt_codegen::core::print_execute_systems( //
6767
}
6868
}
6969

70+
ctx.write("\nupdate_all_beforechange_storage(registry_id);\n");
71+
ctx.write("cleanup_system_notifies(registry_id);\n");
72+
7073
ctx.indentation -= 1;
7174
ctx.write("\n}\n\n");
7275

@@ -88,9 +91,9 @@ auto ecsact::rt_entt_codegen::core::print_execute_systems( //
8891
"trigger_component_events_all(registry_id, events_collector);\n\n"
8992
);
9093
});
91-
ctx.write("cleanup_component_events(registry_id);\n");
92-
ctx.write("cleanup_system_notifies(registry_id);\n");
9394
});
9495

96+
ctx.write("cleanup_component_events(registry_id);\n");
97+
9598
ctx.write("return ECSACT_EXEC_SYS_OK;");
9699
}

rt_entt_codegen/core/system_markers.cc

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "ecsact/lang-support/lang-cc.hh"
77
#include "ecsact/cpp_codegen_plugin_util.hh"
88
#include "rt_entt_codegen/shared/sorting.hh"
9+
#include "rt_entt_codegen/shared/system_util.hh"
910

1011
using ecsact::cpp_codegen_plugin_util::block;
1112
using ecsact::cpp_codegen_plugin_util::method_printer;
@@ -93,3 +94,50 @@ auto ecsact::rt_entt_codegen::core::print_system_marker_remove_fn(
9394
ctx.write("//TODO\n");
9495
}
9596
}
97+
98+
auto ecsact::rt_entt_codegen::core::print_add_sys_beforestorage_fn(
99+
codegen_plugin_context& ctx,
100+
const ecsact_entt_details& details
101+
) -> void {
102+
using cc_lang_support::cpp_identifier;
103+
using ecsact::meta::decl_full_name;
104+
105+
auto already_printed_ = std::set<ecsact_component_id>{};
106+
107+
for(auto comp_id : details.all_components) {
108+
auto comp_name = cpp_identifier(decl_full_name(comp_id));
109+
110+
ctx.write("template<>\n");
111+
auto printer =
112+
method_printer{
113+
ctx,
114+
std::format(
115+
"ecsact::entt::detail::add_exec_itr_beforechange_if_needed< {}>",
116+
comp_name
117+
)
118+
}
119+
.parameter("::entt::registry&", "reg")
120+
.parameter("ecsact::entt::entity_id", "entity")
121+
.return_type("void");
122+
123+
for(auto system_id : details.all_systems) {
124+
auto notify_settings = ecsact::meta::system_notify_settings(system_id);
125+
126+
for(auto const [comp_id_to_compare, notify_setting] : notify_settings) {
127+
if(comp_id == static_cast<ecsact_component_id>(comp_id_to_compare)) {
128+
if(notify_setting == ECSACT_SYS_NOTIFY_ONCHANGE) {
129+
if(already_printed_.contains(comp_id)) {
130+
break;
131+
}
132+
already_printed_.insert(comp_id);
133+
ctx.write(std::format( //
134+
"reg.emplace<exec_itr_beforechange_storage<{}>>(entity);\n",
135+
comp_name
136+
));
137+
break;
138+
}
139+
}
140+
}
141+
}
142+
}
143+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#include "core.hh"
2+
3+
#include <format>
4+
5+
#include "ecsact/lang-support/lang-cc.hh"
6+
#include "rt_entt_codegen/shared/util.hh"
7+
#include "ecsact/runtime/common.h"
8+
#include "ecsact/cpp_codegen_plugin_util.hh"
9+
10+
auto ecsact::rt_entt_codegen::core::print_update_all_beforechange_storage(
11+
codegen_plugin_context& ctx,
12+
const ecsact_entt_details& details
13+
) -> void {
14+
using ecsact::cc_lang_support::c_identifier;
15+
using ecsact::cc_lang_support::cpp_identifier;
16+
using ecsact::cpp_codegen_plugin_util::block;
17+
using ecsact::cpp_codegen_plugin_util::method_printer;
18+
using ecsact::meta::decl_full_name;
19+
20+
auto printer = //
21+
method_printer{ctx, "update_all_beforechange_storage"}
22+
.parameter("ecsact_registry_id", "registry_id")
23+
.return_type("void");
24+
25+
ctx.write("auto& reg = ecsact::entt::get_registry(registry_id);\n\n");
26+
27+
for(auto comp_id : details.all_components) {
28+
if(ecsact::meta::get_field_ids(comp_id).empty()) {
29+
continue;
30+
}
31+
32+
auto comp_name = c_identifier(decl_full_name((comp_id)));
33+
auto cpp_comp_name = cpp_identifier(decl_full_name(comp_id));
34+
auto comp_change_name = std::format( //
35+
"ecsact::entt::detail::exec_itr_beforechange_storage<{}>",
36+
cpp_comp_name
37+
);
38+
39+
auto view_name = std::format("{}_view", comp_name);
40+
auto comp_list = std::format("{}, {}", cpp_comp_name, comp_change_name);
41+
42+
ctx.write( //
43+
std::format("auto {} = reg.view<{}>();\n", view_name, comp_list)
44+
);
45+
46+
block(ctx, std::format("for(auto entity: {})", view_name), [&]() {
47+
ctx.write(std::format(
48+
"ecsact::entt::wrapper::core::update_exec_itr_beforechange<{}>(entity, "
49+
"reg);\n",
50+
cpp_comp_name
51+
));
52+
});
53+
}
54+
}

0 commit comments

Comments
 (0)