1 #ifndef EAGINE_ECS_BASIC_MANAGER_HPP 
    9 #define EAGINE_ECS_BASIC_MANAGER_HPP 
   11 #include "../mp_list.hpp" 
   12 #include "../type_name.hpp" 
   17 #include <type_traits> 
   19 namespace eagine::ecs {
 
   21 template <
typename Entity>
 
   24 template <
typename Entity, 
typename PL>
 
   25 class component_relation;
 
   27 template <
typename Entity, 
typename... PL>
 
   28 class component_relation<Entity, mp_list<PL...>> {
 
   30     basic_manager<Entity>& _m;
 
   32     template <
typename F, 
typename... C, 
typename... X>
 
   33     static inline auto _apply(
 
   34       basic_manager<Entity>& m,
 
   36       mp_list<mp_list<C...>>,
 
   38         const auto wrap = [&func, &x...](
 
   39                             entity_param_t<Entity> e, manipulator<C>&... c) {
 
   40             func(std::forward<X>(x)..., e, c...);
 
   43           callable_ref<
void(entity_param_t<Entity>, manipulator<C> & ...)>{
 
   47     template <
typename F, 
typename... C, 
typename L, 
typename... Ls, 
typename... X>
 
   48     static inline auto _apply(
 
   49       basic_manager<Entity>& m,
 
   51       mp_list<mp_list<C...>, L, Ls...>,
 
   53         const auto wrap = [&m, &func, &x...](
 
   54                             entity_param_t<Entity> e, manipulator<C>&... c) {
 
   56               m, func, mp_list<L, Ls...>(), std::forward<X>(x)..., e, c...);
 
   60           callable_ref<
void(entity_param_t<Entity>, manipulator<C> & ...)>{
 
   65     component_relation(basic_manager<Entity>& m)
 
   68     template <
typename... C>
 
   69     auto cross() -> component_relation<Entity, mp_list<PL..., mp_list<C...>>> {
 
   73     template <
typename Func>
 
   74     void for_each(
const Func& func) {
 
   75         _apply(_m, func, mp_list<PL...>());
 
   79 template <
typename Entity>
 
   82     using entity_param = entity_param_t<Entity>;
 
   85     using _base_cmp_storage_t = base_component_storage<Entity>;
 
   86     using _base_cmp_storage_ptr_t = std::unique_ptr<_base_cmp_storage_t>;
 
   88     component_uid_map<_base_cmp_storage_ptr_t> _cmp_storages{};
 
   90     auto _get_storages(std::false_type) noexcept -> 
auto& {
 
   94     auto _get_storages(std::false_type) 
const noexcept -> 
auto& {
 
   98     using _base_rel_storage_t = base_relation_storage<Entity>;
 
   99     using _base_rel_storage_ptr_t = std::unique_ptr<_base_rel_storage_t>;
 
  101     component_uid_map<_base_rel_storage_ptr_t> _rel_storages{};
 
  103     auto _get_storages(std::true_type) noexcept -> 
auto& {
 
  104         return _rel_storages;
 
  107     auto _get_storages(std::true_type) 
const noexcept -> 
auto& {
 
  108         return _rel_storages;
 
  112     auto _get_storages() noexcept -> auto& {
 
  113         return _get_storages(std::integral_constant<bool, IsR>());
 
  117     auto _get_storages() const noexcept -> auto& {
 
  118         return _get_storages(std::integral_constant<bool, IsR>());
 
  121     template <
typename C>
 
  122     using _bare_t = std::remove_const_t<std::remove_reference_t<C>>;
 
  124     static constexpr 
auto _count_true() -> 
unsigned {
 
  128     template <
typename T, 
typename... P>
 
  129     static constexpr 
auto _count_true(T v, P... p) -> 
unsigned {
 
  130         return (
bool(v) ? 1U : 0U) + _count_true(p...);
 
  133     template <
typename C>
 
  134     static auto _cmp_name_getter() -> std::string (*)() {
 
  135         return &type_name<C>;
 
  138     template <
typename Data, 
bool IsR>
 
  139     auto _find_storage() -> storage<Entity, Data, IsR>&;
 
  141     template <
typename C>
 
  142     auto _find_cmp_storage() -> 
auto& {
 
  143         return _find_storage<C, false>();
 
  146     template <
typename R>
 
  147     auto _find_rel_storage() -> 
auto& {
 
  148         return _find_storage<R, true>();
 
  152     void _do_reg_stg_type(
 
  153       std::unique_ptr<base_storage<Entity, IsR>>&&,
 
  158     void _do_unr_stg_type(component_uid_t, std::string (*)());
 
  161     auto _does_know_stg_type(component_uid_t) 
const -> bool;
 
  163     template <
bool IsR, 
typename Result, 
typename Func>
 
  165     _apply_on_base_stg(Result, 
const Func&, component_uid_t, std::string (*)())
 
  168     template <typename D, 
bool IsR, typename Result, typename Func>
 
  169     auto _apply_on_stg(Result, const Func&) const -> Result;
 
  172     auto _get_stg_type_caps(component_uid_t, std::
string (*)()) const
 
  175     auto _does_have_c(entity_param, component_uid_t, std::
string (*)()) -> 
bool;
 
  181       std::
string (*)()) -> 
bool;
 
  183     auto _is_hidn(entity_param, component_uid_t, std::
string (*)()) -> 
bool;
 
  185     auto _do_show(entity_param, component_uid_t, std::
string (*)()) -> 
bool;
 
  187     auto _do_hide(entity_param, component_uid_t, std::
string (*)()) -> 
bool;
 
  189     template <typename Component>
 
  190     auto _do_add_c(entity_param, Component&& component) -> 
bool;
 
  192     template <typename Relation>
 
  193     auto _do_add_r(entity_param, entity_param, Relation&& relation) -> 
bool;
 
  196       _do_add_r(entity_param, entity_param, component_uid_t, std::
string (*)())
 
  200     _do_cpy(entity_param f, entity_param t, component_uid_t, std::
string (*)())
 
  204     _do_swp(entity_param f, entity_param t, component_uid_t, std::
string (*)())
 
  207     auto _do_rem_c(entity_param, component_uid_t, std::
string (*)()) -> 
bool;
 
  210       _do_rem_r(entity_param, entity_param, component_uid_t, std::
string (*)())
 
  213     template <typename C, typename Func>
 
  214     auto _call_for_single_c(entity_param, const Func&) -> 
bool;
 
  216     template <typename C, typename Func>
 
  217     void _call_for_each_c(const Func&);
 
  219     template <typename R, typename Func>
 
  220     void _call_for_each_r(const Func&);
 
  222     template <typename... C, typename Func>
 
  223     void _call_for_each_c_m_p(const Func&);
 
  225     template <typename... C, typename Func>
 
  226     void _call_for_each_c_m_r(const Func&);
 
  228     template <typename T, typename C>
 
  229     auto _do_get_c(T C::*, entity_param, T) -> T;
 
  232     basic_manager() = default;
 
  234     template <typename Component>
 
  235     auto register_component_type(
 
  236       std::unique_ptr<component_storage<Entity, Component>>&& storage)
 
  238         _do_reg_stg_type<false>(
 
  239           _base_cmp_storage_ptr_t(std::move(storage)),
 
  241           _cmp_name_getter<Component>());
 
  245     template <
typename Relation>
 
  246     auto register_relation_type(
 
  247       std::unique_ptr<relation_storage<Entity, Relation>>&& storage) -> 
auto& {
 
  248         _do_reg_stg_type<true>(
 
  249           _base_rel_storage_ptr_t(std::move(storage)),
 
  251           _cmp_name_getter<Relation>());
 
  256       template <
class, 
class>
 
  260     auto register_component_storage(P&&... p) -> 
auto& {
 
  261         register_component_type<Component>(
 
  262           std::make_unique<Storage<Entity, Component>>(std::forward<P>(p)...));
 
  267       template <
class, 
class>
 
  271     auto register_relation_storage(P&&... p) -> 
auto& {
 
  272         register_relation_type<Relation>(
 
  273           std::make_unique<Storage<Entity, Relation>>(std::forward<P>(p)...));
 
  277     template <
typename Component>
 
  278     auto unregister_component_type() -> 
auto& {
 
  279         _do_unr_stg_type<false>(
 
  280           Component::uid(), _cmp_name_getter<Component>());
 
  284     template <
typename Relation>
 
  285     auto unregister_relation_type() -> 
auto& {
 
  286         _do_unr_stg_type<true>(Relation::uid(), _cmp_name_getter<Relation>());
 
  290     template <
typename Component>
 
  291     auto knows_component_type() const -> 
bool {
 
  292         return _does_know_stg_type<false>(Component::uid());
 
  295     template <
typename Relation>
 
  296     auto knows_relation_type() const -> 
bool {
 
  297         return _does_know_stg_type<true>(Relation::uid());
 
  300     template <
typename Component>
 
  301     auto component_storage_caps() const -> storage_caps {
 
  302         return _get_stg_type_caps<false>(
 
  303           Component::uid(), _cmp_name_getter<Component>());
 
  306     template <
typename Relation>
 
  307     auto relation_storage_caps() const -> storage_caps {
 
  308         return _get_stg_type_caps<true>(
 
  309           Relation::uid(), _cmp_name_getter<Relation>());
 
  312     template <
typename Component>
 
  313     auto component_storage_can(storage_cap_bit cap) 
const -> 
bool {
 
  314         return _get_stg_type_caps<false>(
 
  315                  Component::uid(), _cmp_name_getter<Component>())
 
  319     template <
typename Relation>
 
  320     auto relation_storage_can(storage_cap_bit cap) 
const -> 
bool {
 
  321         return _get_stg_type_caps<true>(
 
  322                  Relation::uid(), _cmp_name_getter<Relation>())
 
  326     void forget(entity_param ent);
 
  328     template <
typename Component>
 
  329     auto has(entity_param ent) -> 
bool {
 
  331           ent, Component::uid(), _cmp_name_getter<Component>());
 
  334     template <
typename Relation>
 
  335     auto has(entity_param subject, entity_param 
object) -> 
bool {
 
  337           subject, 
object, Relation::uid(), _cmp_name_getter<Relation>());
 
  340     template <
typename... Components>
 
  341     auto has_all(entity_param ent) -> 
bool {
 
  342         return _count_true(_does_have_c(
 
  343                  ent, Components::uid(), _cmp_name_getter<Components>())...) ==
 
  344                (
sizeof...(Components));
 
  347     template <
typename Relation>
 
  348     auto is(entity_param 
object, entity_param subject) -> 
bool {
 
  350           subject, 
object, Relation::uid(), _cmp_name_getter<Relation>());
 
  353     template <
typename Component>
 
  354     auto hidden(entity_param ent) -> 
bool {
 
  355         return _is_hidn(ent, Component::uid(), _cmp_name_getter<Component>());
 
  358     template <
typename... Components>
 
  359     auto all_hidden(entity_param ent) -> 
bool {
 
  360         return _count_true(_is_hidn(
 
  361                  ent, Components::uid(), _cmp_name_getter<Components>())...) ==
 
  362                (
sizeof...(Components));
 
  365     template <
typename... Components>
 
  366     auto show(entity_param ent) -> 
auto& {
 
  367         (..., _do_show(ent, Components::uid(), _cmp_name_getter<Components>()));
 
  371     template <
typename... Components>
 
  372     auto hide(entity_param ent) -> 
auto& {
 
  373         (..., _do_hide(ent, Components::uid(), _cmp_name_getter<Components>()));
 
  377     template <
typename... Components>
 
  378     auto add(entity_param ent, Components&&... components) -> 
auto& {
 
  379         (..., _do_add_c(ent, std::move(components)));
 
  383     template <
typename Relation>
 
  384     auto add_relation(entity_param subject, entity_param 
object, Relation&& rel)
 
  386         _do_add_r(subject, 
object, std::forward<Relation>(rel));
 
  390     template <
typename Relation>
 
  391     auto add_relation(entity_param subject, entity_param 
object) -> 
auto& {
 
  393           subject, 
object, Relation::uid(), _cmp_name_getter<Relation>());
 
  397     template <
typename... Components>
 
  398     auto copy(entity_param from, entity_param to) -> 
auto& {
 
  400          _do_cpy(from, to, Components::uid(), _cmp_name_getter<Components>()));
 
  404     template <
typename... Components>
 
  405     auto swap(entity_param e1, entity_param e2) -> 
auto& {
 
  407          _do_swp(e1, e2, Components::uid(), _cmp_name_getter<Components>()));
 
  411     template <
typename... Components>
 
  412     auto remove(entity_param ent) -> 
auto& {
 
  414          _do_rem_c(ent, Components::uid(), _cmp_name_getter<Components>()));
 
  418     template <
typename Relation>
 
  419     auto remove_relation(entity_param subject, entity_param 
object) -> 
auto& {
 
  421           subject, 
object, Relation::uid(), _cmp_name_getter<Relation>());
 
  425     template <
typename T, 
typename Component>
 
  426     auto get(T Component::*mvp, entity_param ent, T res = T()) -> T {
 
  427         return _do_get_c(mvp, ent, res);
 
  430     template <
typename Component>
 
  433       const callable_ref<
void(entity_param, manipulator<const Component>&)>&
 
  435         _call_for_single_c<Component>(ent, func);
 
  439     template <
typename Component>
 
  441       const callable_ref<
void(entity_param, manipulator<Component>&)>& func,
 
  442       entity_param ent) -> 
auto& {
 
  443         _call_for_single_c<Component>(func, ent);
 
  447     template <
typename Component>
 
  449       const callable_ref<
void(entity_param, manipulator<const Component>&)>&
 
  451         _call_for_each_c<Component>(func);
 
  455     template <
typename Component>
 
  457       const callable_ref<
void(entity_param, manipulator<Component>&)>& func)
 
  459         _call_for_each_c<Component>(func);
 
  463     template <
typename Relation>
 
  464     auto for_each(
const callable_ref<
void(entity_param, entity_param)>& func)
 
  466         _call_for_each_r<Relation>(func);
 
  470     template <
typename Relation>
 
  473         void(entity_param, entity_param, manipulator<const Relation>&)>& func)
 
  475         _call_for_each_r<Relation>(func);
 
  479     template <
typename Relation>
 
  482              void(entity_param, entity_param, manipulator<Relation>&)>& func)
 
  484         _call_for_each_r<Relation>(func);
 
  488     template <
typename... Components>
 
  490       const callable_ref<
void(entity_param, manipulator<Components>&...)>& func)
 
  492         _call_for_each_c_m_p<Components...>(func);
 
  496     template <
typename... Components, 
typename Func>
 
  497     auto for_each_with_opt(
const Func& func) -> 
auto& {
 
  498         callable_ref<void(entity_param, manipulator<Components> & ...)> wrap(
 
  500         return for_each_opt<Components...>(wrap);
 
  503     template <
typename... Components>
 
  505       const callable_ref<
void(entity_param, manipulator<Components>&...)>& func)
 
  506       -> std::enable_if_t<(
sizeof...(Components) > 1), basic_manager&> {
 
  507         _call_for_each_c_m_r<Components...>(func);
 
  511     template <
typename... Components, 
typename Func>
 
  512     auto for_each_with(
const Func& func) -> 
auto& {
 
  513         return for_each<Components...>(
 
  514           callable_ref<void(entity_param, manipulator<Components> & ...)>{
 
  518     template <
typename... Components>
 
  520       -> component_relation<Entity, mp_list<mp_list<Components...>>> {
 
  527 #include <eagine/ecs/basic_manager.inl> 
  529 #endif // EAGINE_ECS_BASIC_MANAGER_HPP