From 20401bee45ad13a11a3015d9b55dbd0c8f7b563a Mon Sep 17 00:00:00 2001 From: lisyarus Date: Fri, 28 Oct 2022 23:36:04 +0300 Subject: [PATCH] Implement ecs constructors & destructors --- libs/util/include/psemek/util/ecs.hpp | 117 +++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) diff --git a/libs/util/include/psemek/util/ecs.hpp b/libs/util/include/psemek/util/ecs.hpp index 8cf6ec17..a0debede 100644 --- a/libs/util/include/psemek/util/ecs.hpp +++ b/libs/util/include/psemek/util/ecs.hpp @@ -95,6 +95,14 @@ namespace psemek::util apply_impl(behavior, static_cast(nullptr), std::make_index_sequence>{}, args...); } + template + void apply_single(Behavior & behavior, entity_id entity, Args const & ... args) + { + if (!check_forbidden(behavior, 0)) + return; + apply_single_impl(behavior, entity, static_cast(nullptr), std::make_index_sequence>{}, args...); + } + virtual ~species_base() {} virtual entity_id const * get_free_list() const = 0; @@ -202,6 +210,44 @@ namespace psemek::util } } } + + template + void apply_single_impl(Behavior & behavior, entity_id entity, std::tuple *, std::index_sequence, Args const & ... args) + { + std::tuple cptrs; + + ((std::get(cptrs) = get_entity_component()), ...); + + auto all_nonzero = [](auto * ... ptrs) + { + return ((ptrs != nullptr) && ...); + }; + + if (!std::apply(all_nonzero, cptrs)) + return; + + ((std::get(cptrs) += entity), ...); + + typename Behavior::context ctx; + + ((std::get(ctx.components) = get_species_component()), ...); + + behavior.begin({id_}, *std::get(ctx.components)...); + + auto visit = [&](auto * ... ptrs) + { + if constexpr (std::is_invocable_v) + { + behavior(*ptrs..., ctx, args...); + } + else + { + behavior(*ptrs..., args...); + } + }; + + std::apply(visit, cptrs); + } }; template @@ -539,6 +585,9 @@ namespace psemek::util template void apply(Behavior && behavior, species_handle species, Args const & ... args); + template + void apply(Behavior && behavior, entity_handle entity, Args const & ... args); + template void register_processor(Processor && processor); @@ -548,6 +597,18 @@ namespace psemek::util template void register_behavior(Behavior && behavior, species_handle species); + template + void register_constructor(Behavior && behavior); + + template + void register_constructor(Behavior && behavior, species_handle species); + + template + void register_destructor(Behavior && behavior); + + template + void register_destructor(Behavior && behavior, species_handle species); + template void event(Event const & event); @@ -555,6 +616,12 @@ namespace psemek::util std::vector> species_; std::unordered_map>> event_subscribers_; + + std::vector> constructors_; + std::unordered_map>> species_constructors_; + + std::vector> destructors_; + std::unordered_map>> species_destructors_; }; template @@ -570,7 +637,12 @@ namespace psemek::util inline ecs::entity_handle ecs::add_entity(species_handle species) { - return {species_[species.value]->add_entity()}; + entity_handle entity{species_[species.value]->add_entity()}; + for (auto const & ctor : constructors_) + ctor(entity); + for (auto const & ctor : species_constructors_[species.value]) + ctor(entity); + return entity; } inline ecs_detail::entity_id ecs::entity_count(species_handle species) const @@ -580,6 +652,10 @@ namespace psemek::util inline void ecs::remove_entity(entity_handle entity) { + for (auto const & dtor : destructors_) + dtor(entity); + for (auto const & dtor : species_destructors_[ecs_detail::unpack(entity.value).species]) + dtor(entity); species_[ecs_detail::unpack(entity.value).species]->remove_entity(entity.value); } @@ -660,6 +736,13 @@ namespace psemek::util species_[species.value]->apply(behavior, args...); } + template + void ecs::apply(Behavior && behavior, entity_handle entity, Args const & ... args) + { + auto id = ecs_detail::unpack(entity.value); + species_[id.species]->apply_single(behavior, id.entity, args...); + } + template void ecs::register_processor(Processor && processor) { @@ -684,6 +767,38 @@ namespace psemek::util }); } + template + void ecs::register_constructor(Behavior && behavior) + { + constructors_.push_back([this, behavior = std::move(behavior)](entity_handle entity) mutable { + apply(behavior, entity); + }); + } + + template + void ecs::register_constructor(Behavior && behavior, species_handle species) + { + species_constructors_[species.value].push_back([this, behavior = std::move(behavior)](entity_handle entity) mutable { + apply(behavior, entity); + }); + } + + template + void ecs::register_destructor(Behavior && behavior) + { + destructors_.push_back([this, behavior = std::move(behavior)](entity_handle entity) mutable { + apply(behavior, entity); + }); + } + + template + void ecs::register_destructor(Behavior && behavior, species_handle species) + { + species_destructors_[species.value].push_back([this, behavior = std::move(behavior)](entity_handle entity) mutable { + apply(behavior, entity); + }); + } + template void ecs::event(Event const & event) {