Support adding arbitrary arguments to ECS behavior call

This commit is contained in:
Nikita Lisitsa 2022-08-16 10:14:21 +03:00
parent f22b45c5e8
commit 2482a8c224

View file

@ -85,10 +85,10 @@ namespace psemek::util
virtual bool entity_active(entity_handle h) const = 0; virtual bool entity_active(entity_handle h) const = 0;
template <typename Behavior> template <typename Behavior, typename ... Args>
void apply(Behavior & behavior) void apply(Behavior & behavior, Args const & ... args)
{ {
apply_impl(behavior, static_cast<typename Behavior::component_types *>(nullptr), std::make_index_sequence<std::tuple_size_v<typename Behavior::component_types>>{}); apply_impl(behavior, 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() {}
@ -102,8 +102,8 @@ namespace psemek::util
std::string name_; std::string name_;
species_handle id_; species_handle id_;
template <typename Behavior, typename ... Components, std::size_t ... Is> template <typename Behavior, typename ... Components, std::size_t ... Is, typename ... Args>
void apply_impl(Behavior & behavior, std::tuple<Components...> *, std::index_sequence<Is...>) void apply_impl(Behavior & behavior, std::tuple<Components...> *, std::index_sequence<Is...>, Args const & ... args)
{ {
std::tuple<typename Components::data * ...> cptrs; std::tuple<typename Components::data * ...> cptrs;
@ -123,13 +123,13 @@ namespace psemek::util
auto visit = [&](auto * ... ptrs) auto visit = [&](auto * ... ptrs)
{ {
if constexpr (std::is_invocable_v<Behavior, typename Components::data & ..., typename Behavior::context const &>) if constexpr (std::is_invocable_v<Behavior, typename Components::data & ..., typename Behavior::context const &, Args const & ...>)
{ {
behavior(*ptrs..., ctx); behavior(*ptrs..., ctx, args...);
} }
else else
{ {
behavior(*ptrs...); behavior(*ptrs..., args...);
} }
}; };
@ -460,11 +460,11 @@ namespace psemek::util
template <typename Component> template <typename Component>
typename Component::data const * get_if(entity_handle entity) const; typename Component::data const * get_if(entity_handle entity) const;
template <typename Behavior> template <typename Behavior, typename ... Args>
void apply(Behavior && behavior); void apply(Behavior && behavior, Args const & ... args);
template <typename Behavior> template <typename Behavior, typename ... Args>
void apply(Behavior && behavior, species_handle species); void apply(Behavior && behavior, species_handle species, Args const & ... args);
private: private:
std::vector<std::unique_ptr<ecs_detail::species_base>> species_; std::vector<std::unique_ptr<ecs_detail::species_base>> species_;
@ -560,17 +560,17 @@ namespace psemek::util
return const_cast<typename Component::data const *>(const_cast<ecs *>(this)->get_if<Component>(entity)); return const_cast<typename Component::data const *>(const_cast<ecs *>(this)->get_if<Component>(entity));
} }
template <typename Behavior> template <typename Behavior, typename ... Args>
void ecs::apply(Behavior && behavior) void ecs::apply(Behavior && behavior, Args const & ... args)
{ {
for (auto & s : species_) for (auto & s : species_)
s->apply(behavior); s->apply(behavior, args...);
} }
template <typename Behavior> template <typename Behavior, typename ... Args>
void ecs::apply(Behavior && behavior, species_handle species) void ecs::apply(Behavior && behavior, species_handle species, Args const & ... args)
{ {
species_[species.value]->apply(behavior); species_[species.value]->apply(behavior, args...);
} }
} }