|
- #pragma once
-
- #include <ecs/config.h>
- #include <ecs/core/utils/scope_guard.h>
-
- #include "./context.fwd.h"
- #include "./step_proxy.h"
-
- namespace ecs {
- namespace context {
-
- namespace detail
- {
- template<typename T_settings>
- struct context_t
- : public step_proxy_t<T_settings>
- {
- private:
- using settings_type = T_settings;
- using this_type = context_t<settings_type>;
- using step_proxy = step_proxy_t<settings_type>;
- using defer_proxy = defer_proxy_t<settings_type>;
- using base_type = step_proxy;
-
- private:
- inline void refresh()
- {
- refresh_execute_deferred();
- refresh_kill_entities();
- refresh_match_entities();
- }
-
- inline void refresh_match_entities()
- {
- /* match new/changed entities to system instances */
- for_systems_dispatch([this](auto& instance){
- auto& system_bitset = instance.bitset();
- for (const auto& handle : this->_to_match)
- {
- auto& entity_bitset = this->entity_meta_data(handle).bitset();
- if (entity_bitset.contains(system_bitset))
- {
- if (instance.subscribe(handle))
- {
- // TODO send event
- }
- }
- else if (instance.unsubscribe(handle))
- {
- // TODO send event
- }
- }
- });
-
- this->_to_match.clear();
- }
-
- inline void refresh_kill_entities()
- {
- /* copy entities to kill to the main vector */
- for_systems_sequential([this](auto& instance){
- instance.for_states([this](auto& state){
- for (auto& handle : state.to_kill)
- {
- this->_to_kill.insert(handle);
- }
- });
- });
-
- /* unsubscribe dead entities */
- for_systems_dispatch([this](auto& instance){
- for (const auto& handle : this->_to_kill)
- {
- if (instance.unsubscribe(handle))
- {
- // TODO send event
- }
- }
- });
-
- /* reclaim all killed entities */
- for (const auto& handle : this->_to_kill)
- {
- destroy_entity(handle);
- }
-
- this->_to_kill.clear();
- }
-
- inline void refresh_execute_deferred()
- {
- defer_proxy& proxy = *this;
- for_systems_sequential([&proxy](auto& instance){
- instance.for_states([&proxy](auto& state){
- state.deferred_functions.execute_all(proxy);
- });
- });
- }
-
- public:
- ecs_context_proxy_func(this_type, destroy_entity)
- ecs_context_proxy_func(this_type, post_in_thread_pool)
- ecs_context_proxy_func(this_type, for_systems_sequential)
- ecs_context_proxy_func(this_type, for_systems_parallel)
- ecs_context_proxy_func(this_type, for_systems_dispatch)
-
- public:
- inline context_t()
- : base_type(*this)
- { }
-
- template<typename T_step_func>
- inline decltype(auto) step(T_step_func&& step_func)
- {
- ecs_make_scope_guard([this]{
- this->refresh();
- });
-
- std::forward<T_step_func>(step_func)(static_cast<base_type&>(*this));
- }
- };
-
- struct make_t
- {
- template<typename T_settings>
- constexpr decltype(auto) operator()(T_settings) const noexcept
- { return context_t<T_settings> { }; }
- };
-
- struct make_uptr_t
- {
- template<typename T_settings>
- constexpr decltype(auto) operator()(T_settings) const noexcept
- { return std::make_unique<context_t<T_settings>>(); }
- };
- }
-
- constexpr decltype(auto) make = detail::make_t { };
-
- constexpr decltype(auto) make_uptr = detail::make_uptr_t { };
-
- } }
|