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