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...);
|
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 ~species_base() {}
|
||||||
|
|
||||||
virtual entity_id const * get_free_list() const = 0;
|
virtual entity_id const * get_free_list() const = 0;
|
||||||
|
|
@ -257,6 +265,39 @@ namespace psemek::util
|
||||||
|
|
||||||
std::apply(visit, cptrs);
|
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>
|
template <typename ... Components>
|
||||||
|
|
@ -516,6 +557,23 @@ namespace psemek::util
|
||||||
void begin(species_handle, Components const & ...) {}
|
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
|
struct species_iterator
|
||||||
{
|
{
|
||||||
species_iterator(ecs_detail::species_handle h)
|
species_iterator(ecs_detail::species_handle h)
|
||||||
|
|
@ -604,6 +662,12 @@ namespace psemek::util
|
||||||
template <typename Behavior, typename ... Args>
|
template <typename Behavior, typename ... Args>
|
||||||
void apply(Behavior && behavior, entity_handle entity, Args const & ... 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>
|
template <typename Event, typename Processor>
|
||||||
void register_processor(Processor && processor);
|
void register_processor(Processor && processor);
|
||||||
|
|
||||||
|
|
@ -613,12 +677,21 @@ 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 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>
|
template <typename Behavior>
|
||||||
void register_constructor(Behavior && behavior);
|
void register_constructor(Behavior && behavior);
|
||||||
|
|
||||||
template <typename Behavior>
|
template <typename Behavior>
|
||||||
void register_constructor(Behavior && behavior, species_handle species);
|
void register_constructor(Behavior && behavior, species_handle species);
|
||||||
|
|
||||||
|
template <typename Behavior>
|
||||||
|
void register_species_constructor(Behavior && behavior);
|
||||||
|
|
||||||
template <typename Behavior>
|
template <typename Behavior>
|
||||||
void register_destructor(Behavior && 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::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::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::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>
|
template <typename ... Components>
|
||||||
ecs::species_handle ecs::register_species(std::string name, policy p, Components && ... 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)
|
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
|
else
|
||||||
species_.push_back(std::make_unique<ecs_detail::packed_species_impl<Components...>>(this, std::move(name), result, std::move(components)...));
|
species_.push_back(std::make_unique<ecs_detail::packed_species_impl<Components...>>(this, std::move(name), result.value, std::move(components)...));
|
||||||
return {result};
|
for (auto const & ctor : species_constructors_)
|
||||||
|
ctor(result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ... Components>
|
template <typename ... Components>
|
||||||
|
|
@ -658,7 +735,7 @@ namespace psemek::util
|
||||||
((get<Components>(entity) = std::move(components)), ...);
|
((get<Components>(entity) = std::move(components)), ...);
|
||||||
for (auto const & ctor : constructors_)
|
for (auto const & ctor : constructors_)
|
||||||
ctor(entity);
|
ctor(entity);
|
||||||
for (auto const & ctor : species_constructors_[species.value])
|
for (auto const & ctor : private_constructors_[species.value])
|
||||||
ctor(entity);
|
ctor(entity);
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
@ -672,7 +749,7 @@ namespace psemek::util
|
||||||
{
|
{
|
||||||
for (auto const & dtor : destructors_)
|
for (auto const & dtor : destructors_)
|
||||||
dtor(entity);
|
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);
|
dtor(entity);
|
||||||
species_[ecs_detail::unpack(entity.value).species]->remove_entity(entity.value);
|
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...);
|
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>
|
template <typename Event, typename Processor>
|
||||||
void ecs::register_processor(Processor && 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>
|
template <typename Behavior>
|
||||||
void ecs::register_constructor(Behavior && behavior)
|
void ecs::register_constructor(Behavior && behavior)
|
||||||
{
|
{
|
||||||
|
|
@ -796,11 +902,19 @@ namespace psemek::util
|
||||||
template <typename Behavior>
|
template <typename Behavior>
|
||||||
void ecs::register_constructor(Behavior && behavior, species_handle species)
|
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);
|
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>
|
template <typename Behavior>
|
||||||
void ecs::register_destructor(Behavior && behavior)
|
void ecs::register_destructor(Behavior && behavior)
|
||||||
{
|
{
|
||||||
|
|
@ -812,7 +926,7 @@ namespace psemek::util
|
||||||
template <typename Behavior>
|
template <typename Behavior>
|
||||||
void ecs::register_destructor(Behavior && behavior, species_handle species)
|
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);
|
apply(behavior, entity);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue