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...);
|
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 ~species_base() {}
|
||||||
|
|
||||||
virtual entity_id const * get_free_list() const = 0;
|
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>
|
template <typename ... Components>
|
||||||
|
|
@ -539,6 +585,9 @@ namespace psemek::util
|
||||||
template <typename Behavior, typename ... Args>
|
template <typename Behavior, typename ... Args>
|
||||||
void apply(Behavior && behavior, species_handle species, Args const & ... 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>
|
template <typename Event, typename Processor>
|
||||||
void register_processor(Processor && processor);
|
void register_processor(Processor && processor);
|
||||||
|
|
||||||
|
|
@ -548,6 +597,18 @@ namespace psemek::util
|
||||||
template <typename Event, typename Behavior>
|
template <typename Event, typename Behavior>
|
||||||
void register_behavior(Behavior && behavior, species_handle species);
|
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>
|
template <typename Event>
|
||||||
void event(Event const & event);
|
void event(Event const & event);
|
||||||
|
|
||||||
|
|
@ -555,6 +616,12 @@ namespace psemek::util
|
||||||
std::vector<std::unique_ptr<ecs_detail::species_base>> species_;
|
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::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>
|
template <typename ... Components>
|
||||||
|
|
@ -570,7 +637,12 @@ namespace psemek::util
|
||||||
|
|
||||||
inline ecs::entity_handle ecs::add_entity(species_handle species)
|
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
|
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)
|
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);
|
species_[ecs_detail::unpack(entity.value).species]->remove_entity(entity.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -660,6 +736,13 @@ namespace psemek::util
|
||||||
species_[species.value]->apply(behavior, args...);
|
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>
|
template <typename Event, typename Processor>
|
||||||
void ecs::register_processor(Processor && 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>
|
template <typename Event>
|
||||||
void ecs::event(Event const & event)
|
void ecs::event(Event const & event)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue