Support ecs species behaviors
This commit is contained in:
parent
9489c1caef
commit
07804bdeda
1 changed files with 124 additions and 10 deletions
|
|
@ -106,6 +106,14 @@ namespace psemek::util
|
|||
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...);
|
||||
}
|
||||
|
||||
template <typename Behavior, typename ... Args>
|
||||
void apply_species(Behavior & behavior, Args const & ... args)
|
||||
{
|
||||
if (!check_forbidden(behavior, 0))
|
||||
return;
|
||||
apply_species_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 entity_id const * get_free_list() const = 0;
|
||||
|
|
@ -257,6 +265,39 @@ namespace psemek::util
|
|||
|
||||
std::apply(visit, cptrs);
|
||||
}
|
||||
|
||||
template <typename Behavior, typename ... Components, std::size_t ... Is, typename ... Args>
|
||||
void apply_species_impl(Behavior & behavior, std::tuple<Components...> *, std::index_sequence<Is...>, Args const & ... args)
|
||||
{
|
||||
std::tuple<Components * ...> cptrs;
|
||||
|
||||
((std::get<Is>(cptrs) = get_species_component<Components>()), ...);
|
||||
|
||||
auto all_nonzero = [](auto * ... ptrs)
|
||||
{
|
||||
return ((ptrs != nullptr) && ...);
|
||||
};
|
||||
|
||||
if (!std::apply(all_nonzero, cptrs))
|
||||
return;
|
||||
|
||||
typename Behavior::context ctx{*ecs_};
|
||||
ctx.species.value = id_;
|
||||
|
||||
auto visit = [&](auto * ... ptrs)
|
||||
{
|
||||
if constexpr (std::is_invocable_v<Behavior, Components & ..., typename Behavior::context const &, Args const & ...>)
|
||||
{
|
||||
behavior(*ptrs..., ctx, args...);
|
||||
}
|
||||
else
|
||||
{
|
||||
behavior(*ptrs..., args...);
|
||||
}
|
||||
};
|
||||
|
||||
std::apply(visit, cptrs);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ... Components>
|
||||
|
|
@ -516,6 +557,23 @@ namespace psemek::util
|
|||
void begin(species_handle, Components const & ...) {}
|
||||
};
|
||||
|
||||
template <typename ... Components>
|
||||
struct species_behavior
|
||||
{
|
||||
using component_types = std::tuple<Components...>;
|
||||
using component_ptrs = std::tuple<Components *...>;
|
||||
|
||||
struct context
|
||||
{
|
||||
struct ecs & ecs;
|
||||
species_handle species;
|
||||
|
||||
context(struct ecs & ecs)
|
||||
: ecs(ecs)
|
||||
{}
|
||||
};
|
||||
};
|
||||
|
||||
struct species_iterator
|
||||
{
|
||||
species_iterator(ecs_detail::species_handle h)
|
||||
|
|
@ -604,6 +662,12 @@ namespace psemek::util
|
|||
template <typename Behavior, typename ... Args>
|
||||
void apply(Behavior && behavior, entity_handle entity, Args const & ... args);
|
||||
|
||||
template <typename Behavior, typename ... Args>
|
||||
void apply_species(Behavior && behavior, Args const & ... args);
|
||||
|
||||
template <typename Behavior, typename ... Args>
|
||||
void apply_species(Behavior && behavior, species_handle species, Args const & ... args);
|
||||
|
||||
template <typename Event, typename Processor>
|
||||
void register_processor(Processor && processor);
|
||||
|
||||
|
|
@ -613,12 +677,21 @@ namespace psemek::util
|
|||
template <typename Event, typename Behavior>
|
||||
void register_behavior(Behavior && behavior, species_handle species);
|
||||
|
||||
template <typename Event, typename Behavior>
|
||||
void register_species_behavior(Behavior && behavior);
|
||||
|
||||
template <typename Event, typename Behavior>
|
||||
void register_species_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_species_constructor(Behavior && behavior);
|
||||
|
||||
template <typename Behavior>
|
||||
void register_destructor(Behavior && behavior);
|
||||
|
||||
|
|
@ -633,22 +706,26 @@ namespace psemek::util
|
|||
|
||||
std::unordered_map<std::type_index, std::vector<util::function<void(void const *)>>> event_subscribers_;
|
||||
|
||||
std::vector<util::function<void(species_handle)>> species_constructors_;
|
||||
|
||||
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::unordered_map<ecs_detail::species_handle, std::vector<util::function<void(entity_handle)>>> private_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_;
|
||||
std::unordered_map<ecs_detail::species_handle, std::vector<util::function<void(entity_handle)>>> private_destructors_;
|
||||
};
|
||||
|
||||
template <typename ... Components>
|
||||
ecs::species_handle ecs::register_species(std::string name, policy p, Components && ... components)
|
||||
{
|
||||
auto result = species_.size();
|
||||
species_handle result{species_.size()};
|
||||
if (p == policy::sparse)
|
||||
species_.push_back(std::make_unique<ecs_detail::sparse_species_impl<Components...>>(this, std::move(name), result, std::move(components)...));
|
||||
species_.push_back(std::make_unique<ecs_detail::sparse_species_impl<Components...>>(this, std::move(name), result.value, std::move(components)...));
|
||||
else
|
||||
species_.push_back(std::make_unique<ecs_detail::packed_species_impl<Components...>>(this, std::move(name), result, std::move(components)...));
|
||||
return {result};
|
||||
species_.push_back(std::make_unique<ecs_detail::packed_species_impl<Components...>>(this, std::move(name), result.value, std::move(components)...));
|
||||
for (auto const & ctor : species_constructors_)
|
||||
ctor(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename ... Components>
|
||||
|
|
@ -658,7 +735,7 @@ namespace psemek::util
|
|||
((get<Components>(entity) = std::move(components)), ...);
|
||||
for (auto const & ctor : constructors_)
|
||||
ctor(entity);
|
||||
for (auto const & ctor : species_constructors_[species.value])
|
||||
for (auto const & ctor : private_constructors_[species.value])
|
||||
ctor(entity);
|
||||
return entity;
|
||||
}
|
||||
|
|
@ -672,7 +749,7 @@ namespace psemek::util
|
|||
{
|
||||
for (auto const & dtor : destructors_)
|
||||
dtor(entity);
|
||||
for (auto const & dtor : species_destructors_[ecs_detail::unpack(entity.value).species])
|
||||
for (auto const & dtor : private_destructors_[ecs_detail::unpack(entity.value).species])
|
||||
dtor(entity);
|
||||
species_[ecs_detail::unpack(entity.value).species]->remove_entity(entity.value);
|
||||
}
|
||||
|
|
@ -761,6 +838,19 @@ namespace psemek::util
|
|||
species_[id.species]->apply_single(behavior, id.entity, args...);
|
||||
}
|
||||
|
||||
template <typename Behavior, typename ... Args>
|
||||
void ecs::apply_species(Behavior && behavior, Args const & ... args)
|
||||
{
|
||||
for (auto & s : species_)
|
||||
s->apply_species(behavior, args...);
|
||||
}
|
||||
|
||||
template <typename Behavior, typename ... Args>
|
||||
void ecs::apply_species(Behavior && behavior, species_handle species, Args const & ... args)
|
||||
{
|
||||
species_[species.value]->apply_species(behavior, args...);
|
||||
}
|
||||
|
||||
template <typename Event, typename Processor>
|
||||
void ecs::register_processor(Processor && processor)
|
||||
{
|
||||
|
|
@ -785,6 +875,22 @@ namespace psemek::util
|
|||
});
|
||||
}
|
||||
|
||||
template <typename Event, typename Behavior>
|
||||
void ecs::register_species_behavior(Behavior && behavior)
|
||||
{
|
||||
event_subscribers_[typeid(Event)].push_back([this, behavior = std::move(behavior)](void const * event) mutable {
|
||||
apply_species(behavior, *static_cast<Event const *>(event));
|
||||
});
|
||||
}
|
||||
|
||||
template <typename Event, typename Behavior>
|
||||
void ecs::register_species_behavior(Behavior && behavior, species_handle species)
|
||||
{
|
||||
event_subscribers_[typeid(Event)].push_back([this, species, behavior = std::move(behavior)](void const * event) mutable {
|
||||
apply_species(behavior, species, *static_cast<Event const *>(event));
|
||||
});
|
||||
}
|
||||
|
||||
template <typename Behavior>
|
||||
void ecs::register_constructor(Behavior && behavior)
|
||||
{
|
||||
|
|
@ -796,11 +902,19 @@ namespace psemek::util
|
|||
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 {
|
||||
private_constructors_[species.value].push_back([this, behavior = std::move(behavior)](entity_handle entity) mutable {
|
||||
apply(behavior, entity);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename Behavior>
|
||||
void ecs::register_species_constructor(Behavior && behavior)
|
||||
{
|
||||
species_constructors_.push_back([this, behavior = std::move(behavior)](species_handle species) mutable {
|
||||
apply_species(behavior, species);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename Behavior>
|
||||
void ecs::register_destructor(Behavior && behavior)
|
||||
{
|
||||
|
|
@ -812,7 +926,7 @@ namespace psemek::util
|
|||
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 {
|
||||
private_destructors_[species.value].push_back([this, behavior = std::move(behavior)](entity_handle entity) mutable {
|
||||
apply(behavior, entity);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue