Skip to content

feat: adding onchange for systems #114

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions ecsact/entt/detail/apply_pending.hh
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ auto apply_pending_add(::entt::registry& registry) -> void {
registry.emplace<C>(entity);
});
} else {
registry.view<pending_add<C>>().each(
registry.view<pending_add<C>>().each( //
[&](auto entity, const pending_add<C>& comp) {
registry.emplace<C>(entity, comp.value);
registry.emplace<beforechange_storage<C>>(entity, comp.value, false);
registry
.emplace<exec_beforechange_storage<C>>(entity, comp.value, false);
}
);
}
Expand All @@ -27,7 +28,7 @@ template<typename C>
auto apply_pending_remove(::entt::registry& registry) -> void {
registry.view<pending_remove<C>>().each([&](auto entity) {
if constexpr(!std::is_empty_v<C>) {
registry.erase<beforechange_storage<C>>(entity);
registry.erase<exec_beforechange_storage<C>>(entity);
}
registry.erase<C>(entity);
});
Expand Down
22 changes: 21 additions & 1 deletion ecsact/entt/detail/internal_markers.hh
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,17 @@ struct beforeremove_storage<C> {

template<typename C>
requires(!std::is_empty_v<C>)
struct beforechange_storage {
struct exec_beforechange_storage {
C value;
bool has_update_occurred = false;
};

template<typename C>
requires(!std::is_empty_v<C>)
struct exec_itr_beforechange_storage {
C value;
};

template<typename C>
struct pending_add;

Expand Down Expand Up @@ -107,4 +113,18 @@ auto remove_system_markers_if_needed( //
)");
}

template<typename C>
auto add_exec_itr_beforechange_if_needed( //
::entt::registry&,
ecsact::entt::entity_id
) -> void {
static_assert(system_markers_unimplemented_by_codegen<C>, R"(
-----------------------------------------------------------------------------
| (!) CODEGEN ERROR |
| `add_exec_itr_beforechange_if_needed<>` template specialization cannot be found |
| This is typically generated by ecsact_rt_entt_codegen. |
-----------------------------------------------------------------------------
)");
}

} // namespace ecsact::entt::detail
43 changes: 35 additions & 8 deletions ecsact/entt/wrapper/core.hh
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ inline auto add_component( //
if constexpr(std::is_empty_v<C>) {
reg.emplace<C>(entity);
} else {
reg.emplace<detail::beforechange_storage<C>>(
reg.emplace<detail::exec_beforechange_storage<C>>(
entity,
*static_cast<const C*>(component_data),
false
Expand All @@ -68,6 +68,7 @@ inline auto add_component( //
}

ecsact::entt::detail::add_system_markers_if_needed<C>(reg, entity);
ecsact::entt::detail::add_exec_itr_beforechange_if_needed<C>(reg, entity);
}

return err;
Expand Down Expand Up @@ -96,14 +97,15 @@ inline auto add_component_exec_options( //
if constexpr(std::is_empty_v<C>) {
reg.emplace<C>(entity);
} else {
reg.emplace<detail::beforechange_storage<C>>(
reg.emplace<detail::exec_beforechange_storage<C>>(
entity,
*static_cast<const C*>(component_data)
);
reg.emplace<C>(entity, *static_cast<const C*>(component_data));
}
reg.template emplace_or_replace<component_added<C>>(entity);
ecsact::entt::detail::add_system_markers_if_needed<C>(reg, entity);
ecsact::entt::detail::add_exec_itr_beforechange_if_needed<C>(reg, entity);
}

return err;
Expand Down Expand Up @@ -172,7 +174,7 @@ auto remove_component(

reg.remove<C>(entity);
if constexpr(!std::is_empty_v<C>) {
reg.remove<detail::beforechange_storage<C>>(entity);
reg.remove<detail::exec_beforechange_storage<C>>(entity);
}
reg.template remove<component_added<C>>(entity);
reg.template remove<component_updated<C>>(entity);
Expand Down Expand Up @@ -205,7 +207,7 @@ auto remove_component_exec_options(
reg.template emplace_or_replace<component_removed<C>>(entity);

if constexpr(!std::is_empty_v<C>) {
reg.template remove<detail::beforechange_storage<C>>(entity);
reg.template remove<detail::exec_beforechange_storage<C>>(entity);
}

ecsact::entt::detail::remove_system_markers_if_needed<C>(reg, entity);
Expand Down Expand Up @@ -294,7 +296,7 @@ auto _trigger_update_component_event(
ecsact::entt::detail::execution_events_collector& events_collector
) -> void {
using ecsact::entt::component_updated;
using ecsact::entt::detail::beforechange_storage;
using ecsact::entt::detail::exec_beforechange_storage;

if(!events_collector.has_update_callback()) {
return;
Expand All @@ -304,12 +306,13 @@ auto _trigger_update_component_event(
if constexpr(!C::transient && !std::is_empty_v<C>) {
::entt::basic_view changed_view{
reg.template storage<C>(),
reg.template storage<beforechange_storage<C>>(),
reg.template storage<exec_beforechange_storage<C>>(),
reg.template storage<component_updated<C>>(),
};

for(ecsact::entt::entity_id entity : changed_view) {
auto& before = changed_view.template get<beforechange_storage<C>>(entity);
auto& before =
changed_view.template get<exec_beforechange_storage<C>>(entity);
auto& current = changed_view.template get<C>(entity);
before.has_update_occurred = false;

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

if constexpr(!std::is_empty_v<C>) {
reg.storage<detail::beforechange_storage<C>>();
reg.storage<detail::exec_beforechange_storage<C>>();
reg.template storage<component_updated<C>>();
}
}

template<typename C, typename V>
auto has_component_changed(entt::entity_id entity, V& view) -> bool {
using detail::exec_itr_beforechange_storage;

const auto& current_comp = view.template get<C>(entity);
const auto& before_comp =
view.template get<exec_itr_beforechange_storage<C>>(entity);

if(before_comp.value != current_comp) {
return true;
}
return false;
}

template<typename C>
auto update_exec_itr_beforechange(entt::entity_id entity, ::entt::registry& reg)
-> void {
auto comp = reg.get<C>(entity);
auto& beforechange_comp =
reg.get<detail::exec_itr_beforechange_storage<C>>(entity);

beforechange_comp.value = comp;
}

} // namespace ecsact::entt::wrapper::core
10 changes: 4 additions & 6 deletions ecsact/entt/wrapper/dynamic.hh
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ auto context_add(
) -> void {
using ecsact::entt::component_added;
using ecsact::entt::component_removed;
using ecsact::entt::detail::beforechange_storage;
using ecsact::entt::detail::beforeremove_storage;
using ecsact::entt::detail::exec_beforechange_storage;
using ecsact::entt::detail::pending_add;

assert(ecsact_id_cast<ecsact_component_like_id>(C::id) == component_id);
Expand All @@ -34,7 +34,6 @@ auto context_add(
} else {
const C* component = static_cast<const C*>(component_data);
registry.template emplace_or_replace<pending_add<C>>(entity, *component);

registry.template remove<beforeremove_storage<C>>(entity);
}

Expand All @@ -54,8 +53,6 @@ auto component_add_trivial(
) -> void {
using ecsact::entt::component_added;
using ecsact::entt::component_removed;
using ecsact::entt::detail::beforechange_storage;
using ecsact::entt::detail::beforeremove_storage;
using ecsact::entt::detail::pending_add;

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

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

auto& current_component = registry.template get<C>(entity);
auto& beforechange = registry.template get<beforechange_storage<C>>(entity);
auto& beforechange =
registry.template get<exec_beforechange_storage<C>>(entity);
if(!beforechange.has_update_occurred) {
beforechange.value = current_component;
beforechange.has_update_occurred = true;
Expand Down
2 changes: 2 additions & 0 deletions rt_entt_codegen/core/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ _CORE_CODEGEN_METHODS = {
],
"system_markers": [
"//rt_entt_codegen/shared:sorting",
"//rt_entt_codegen/shared:system_util",
],
"system_notify": ["//rt_entt_codegen/shared:system_util"],
"update_beforechange": [],
}

[cc_library(
Expand Down
10 changes: 10 additions & 0 deletions rt_entt_codegen/core/core.hh
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ auto print_system_marker_remove_fn(
const ecsact_entt_details& details
) -> void;

auto print_add_sys_beforestorage_fn(
codegen_plugin_context& ctx,
const ecsact_entt_details& details
) -> void;

auto print_cleanup_system_notifies(
codegen_plugin_context& ctx,
const ecsact_entt_details& details
Expand All @@ -76,4 +81,9 @@ auto print_entity_match_fn(
const ecsact_entt_details& details
) -> void;

auto print_update_all_beforechange_storage(
codegen_plugin_context& ctx,
const ecsact_entt_details& details
) -> void;

} // namespace ecsact::rt_entt_codegen::core
7 changes: 5 additions & 2 deletions rt_entt_codegen/core/execute_systems.cc
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ auto ecsact::rt_entt_codegen::core::print_execute_systems( //
}
}

ctx.write("\nupdate_all_beforechange_storage(registry_id);\n");
ctx.write("cleanup_system_notifies(registry_id);\n");

ctx.indentation -= 1;
ctx.write("\n}\n\n");

Expand All @@ -88,9 +91,9 @@ auto ecsact::rt_entt_codegen::core::print_execute_systems( //
"trigger_component_events_all(registry_id, events_collector);\n\n"
);
});
ctx.write("cleanup_component_events(registry_id);\n");
ctx.write("cleanup_system_notifies(registry_id);\n");
});

ctx.write("cleanup_component_events(registry_id);\n");

ctx.write("return ECSACT_EXEC_SYS_OK;");
}
48 changes: 48 additions & 0 deletions rt_entt_codegen/core/system_markers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "ecsact/lang-support/lang-cc.hh"
#include "ecsact/cpp_codegen_plugin_util.hh"
#include "rt_entt_codegen/shared/sorting.hh"
#include "rt_entt_codegen/shared/system_util.hh"

using ecsact::cpp_codegen_plugin_util::block;
using ecsact::cpp_codegen_plugin_util::method_printer;
Expand Down Expand Up @@ -93,3 +94,50 @@ auto ecsact::rt_entt_codegen::core::print_system_marker_remove_fn(
ctx.write("//TODO\n");
}
}

auto ecsact::rt_entt_codegen::core::print_add_sys_beforestorage_fn(
codegen_plugin_context& ctx,
const ecsact_entt_details& details
) -> void {
using cc_lang_support::cpp_identifier;
using ecsact::meta::decl_full_name;

auto already_printed_ = std::set<ecsact_component_id>{};

for(auto comp_id : details.all_components) {
auto comp_name = cpp_identifier(decl_full_name(comp_id));

ctx.write("template<>\n");
auto printer =
method_printer{
ctx,
std::format(
"ecsact::entt::detail::add_exec_itr_beforechange_if_needed< {}>",
comp_name
)
}
.parameter("::entt::registry&", "reg")
.parameter("ecsact::entt::entity_id", "entity")
.return_type("void");

for(auto system_id : details.all_systems) {
auto notify_settings = ecsact::meta::system_notify_settings(system_id);

for(auto const [comp_id_to_compare, notify_setting] : notify_settings) {
if(comp_id == static_cast<ecsact_component_id>(comp_id_to_compare)) {
if(notify_setting == ECSACT_SYS_NOTIFY_ONCHANGE) {
if(already_printed_.contains(comp_id)) {
break;
}
already_printed_.insert(comp_id);
ctx.write(std::format( //
"reg.emplace<exec_itr_beforechange_storage<{}>>(entity);\n",
comp_name
));
break;
}
}
}
}
}
}
54 changes: 54 additions & 0 deletions rt_entt_codegen/core/update_beforechange.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include "core.hh"

#include <format>

#include "ecsact/lang-support/lang-cc.hh"
#include "rt_entt_codegen/shared/util.hh"
#include "ecsact/runtime/common.h"
#include "ecsact/cpp_codegen_plugin_util.hh"

auto ecsact::rt_entt_codegen::core::print_update_all_beforechange_storage(
codegen_plugin_context& ctx,
const ecsact_entt_details& details
) -> void {
using ecsact::cc_lang_support::c_identifier;
using ecsact::cc_lang_support::cpp_identifier;
using ecsact::cpp_codegen_plugin_util::block;
using ecsact::cpp_codegen_plugin_util::method_printer;
using ecsact::meta::decl_full_name;

auto printer = //
method_printer{ctx, "update_all_beforechange_storage"}
.parameter("ecsact_registry_id", "registry_id")
.return_type("void");

ctx.write("auto& reg = ecsact::entt::get_registry(registry_id);\n\n");

for(auto comp_id : details.all_components) {
if(ecsact::meta::get_field_ids(comp_id).empty()) {
continue;
}

auto comp_name = c_identifier(decl_full_name((comp_id)));
auto cpp_comp_name = cpp_identifier(decl_full_name(comp_id));
auto comp_change_name = std::format( //
"ecsact::entt::detail::exec_itr_beforechange_storage<{}>",
cpp_comp_name
);

auto view_name = std::format("{}_view", comp_name);
auto comp_list = std::format("{}, {}", cpp_comp_name, comp_change_name);

ctx.write( //
std::format("auto {} = reg.view<{}>();\n", view_name, comp_list)
);

block(ctx, std::format("for(auto entity: {})", view_name), [&]() {
ctx.write(std::format(
"ecsact::entt::wrapper::core::update_exec_itr_beforechange<{}>(entity, "
"reg);\n",
cpp_comp_name
));
});
}
}
Loading