Implement ecs constructors & destructors
This commit is contained in:
parent
55c3266343
commit
20401bee45
1 changed files with 116 additions and 1 deletions
|
|
@ -95,6 +95,14 @@ namespace psemek::util
|
|||
apply_impl(behavior, static_cast<typename Behavior::component_types *>(nullptr), std::make_index_sequence<std::tuple_size_v<typename Behavior::component_types>>{}, args...);
|
||||
}
|
||||
|
||||
template <typename Behavior, typename ... Args>
|
||||
void apply_single(Behavior & behavior, entity_id entity, Args const & ... args)
|
||||
{
|
||||
if (!check_forbidden(behavior, 0))
|
||||
return;
|
||||
apply_single_impl(behavior, entity, static_cast<typename Behavior::component_types *>(nullptr), std::make_index_sequence<std::tuple_size_v<typename Behavior::component_types>>{}, args...);
|
||||
}
|
||||
|
||||
virtual ~species_base() {}
|
||||
|
||||
virtual entity_id const * get_free_list() const = 0;
|
||||
|
|
@ -202,6 +210,44 @@ namespace psemek::util
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Behavior, typename ... Components, std::size_t ... Is, typename ... Args>
|
||||
void apply_single_impl(Behavior & behavior, entity_id entity, std::tuple<Components...> *, std::index_sequence<Is...>, Args const & ... args)
|
||||
{
|
||||
std::tuple<typename Components::data * ...> cptrs;
|
||||
|
||||
((std::get<Is>(cptrs) = get_entity_component<Components>()), ...);
|
||||
|
||||
auto all_nonzero = [](auto * ... ptrs)
|
||||
{
|
||||
return ((ptrs != nullptr) && ...);
|
||||
};
|
||||
|
||||
if (!std::apply(all_nonzero, cptrs))
|
||||
return;
|
||||
|
||||
((std::get<Is>(cptrs) += entity), ...);
|
||||
|
||||
typename Behavior::context ctx;
|
||||
|
||||
((std::get<Components *>(ctx.components) = get_species_component<Components>()), ...);
|
||||
|
||||
behavior.begin({id_}, *std::get<Components *>(ctx.components)...);
|
||||
|
||||
auto visit = [&](auto * ... ptrs)
|
||||
{
|
||||
if constexpr (std::is_invocable_v<Behavior, typename Components::data & ..., typename Behavior::context const &, Args const & ...>)
|
||||
{
|
||||
behavior(*ptrs..., ctx, args...);
|
||||
}
|
||||
else
|
||||
{
|
||||
behavior(*ptrs..., args...);
|
||||
}
|
||||
};
|
||||
|
||||
std::apply(visit, cptrs);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ... Components>
|
||||
|
|
@ -539,6 +585,9 @@ namespace psemek::util
|
|||
template <typename Behavior, typename ... Args>
|
||||
void apply(Behavior && behavior, species_handle species, Args const & ... args);
|
||||
|
||||
template <typename Behavior, typename ... Args>
|
||||
void apply(Behavior && behavior, entity_handle entity, Args const & ... args);
|
||||
|
||||
template <typename Event, typename Processor>
|
||||
void register_processor(Processor && processor);
|
||||
|
||||
|
|
@ -548,6 +597,18 @@ namespace psemek::util
|
|||
template <typename Event, typename Behavior>
|
||||
void register_behavior(Behavior && behavior, species_handle species);
|
||||
|
||||
template <typename Behavior>
|
||||
void register_constructor(Behavior && behavior);
|
||||
|
||||
template <typename Behavior>
|
||||
void register_constructor(Behavior && behavior, species_handle species);
|
||||
|
||||
template <typename Behavior>
|
||||
void register_destructor(Behavior && behavior);
|
||||
|
||||
template <typename Behavior>
|
||||
void register_destructor(Behavior && behavior, species_handle species);
|
||||
|
||||
template <typename Event>
|
||||
void event(Event const & event);
|
||||
|
||||
|
|
@ -555,6 +616,12 @@ namespace psemek::util
|
|||
std::vector<std::unique_ptr<ecs_detail::species_base>> species_;
|
||||
|
||||
std::unordered_map<std::type_index, std::vector<util::function<void(void const *)>>> event_subscribers_;
|
||||
|
||||
std::vector<util::function<void(entity_handle)>> constructors_;
|
||||
std::unordered_map<ecs_detail::species_handle, std::vector<util::function<void(entity_handle)>>> species_constructors_;
|
||||
|
||||
std::vector<util::function<void(entity_handle)>> destructors_;
|
||||
std::unordered_map<ecs_detail::species_handle, std::vector<util::function<void(entity_handle)>>> species_destructors_;
|
||||
};
|
||||
|
||||
template <typename ... Components>
|
||||
|
|
@ -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 <typename Behavior, typename ... Args>
|
||||
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 <typename Event, typename Processor>
|
||||
void ecs::register_processor(Processor && processor)
|
||||
{
|
||||
|
|
@ -684,6 +767,38 @@ namespace psemek::util
|
|||
});
|
||||
}
|
||||
|
||||
template <typename Behavior>
|
||||
void ecs::register_constructor(Behavior && behavior)
|
||||
{
|
||||
constructors_.push_back([this, behavior = std::move(behavior)](entity_handle entity) mutable {
|
||||
apply(behavior, entity);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename Behavior>
|
||||
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 <typename Behavior>
|
||||
void ecs::register_destructor(Behavior && behavior)
|
||||
{
|
||||
destructors_.push_back([this, behavior = std::move(behavior)](entity_handle entity) mutable {
|
||||
apply(behavior, entity);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename Behavior>
|
||||
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 <typename Event>
|
||||
void ecs::event(Event const & event)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue