Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

142 rader
4.5 KiB

  1. #pragma once
  2. #include <ecs/config.h>
  3. #include <ecs/core/utils/scope_guard.h>
  4. #include "./context.fwd.h"
  5. #include "./step_proxy.h"
  6. namespace ecs {
  7. namespace context {
  8. namespace detail
  9. {
  10. template<typename T_settings>
  11. struct context_t
  12. : public step_proxy_t<T_settings>
  13. {
  14. private:
  15. using settings_type = T_settings;
  16. using this_type = context_t<settings_type>;
  17. using step_proxy = step_proxy_t<settings_type>;
  18. using defer_proxy = defer_proxy_t<settings_type>;
  19. using base_type = step_proxy;
  20. private:
  21. inline void refresh()
  22. {
  23. refresh_execute_deferred();
  24. refresh_kill_entities();
  25. refresh_match_entities();
  26. }
  27. inline void refresh_match_entities()
  28. {
  29. /* match new/changed entities to system instances */
  30. for_systems_dispatch([this](auto& instance){
  31. auto& system_bitset = instance.bitset();
  32. for (const auto& handle : this->_to_match)
  33. {
  34. auto& entity_bitset = this->entity_meta_data(handle).bitset();
  35. if (entity_bitset.contains(system_bitset))
  36. {
  37. if (instance.subscribe(handle))
  38. {
  39. // TODO send event
  40. }
  41. }
  42. else if (instance.unsubscribe(handle))
  43. {
  44. // TODO send event
  45. }
  46. }
  47. });
  48. this->_to_match.clear();
  49. }
  50. inline void refresh_kill_entities()
  51. {
  52. /* copy entities to kill to the main vector */
  53. for_systems_sequential([this](auto& instance){
  54. instance.for_states([this](auto& state){
  55. for (auto& handle : state.to_kill)
  56. {
  57. this->_to_kill.insert(handle);
  58. }
  59. });
  60. });
  61. /* unsubscribe dead entities */
  62. for_systems_dispatch([this](auto& instance){
  63. for (const auto& handle : this->_to_kill)
  64. {
  65. if (instance.unsubscribe(handle))
  66. {
  67. // TODO send event
  68. }
  69. }
  70. });
  71. /* reclaim all killed entities */
  72. for (const auto& handle : this->_to_kill)
  73. {
  74. destroy_entity(handle);
  75. }
  76. this->_to_kill.clear();
  77. }
  78. inline void refresh_execute_deferred()
  79. {
  80. defer_proxy& proxy = *this;
  81. for_systems_sequential([&proxy](auto& instance){
  82. instance.for_states([&proxy](auto& state){
  83. state.deferred_functions.execute_all(proxy);
  84. });
  85. });
  86. }
  87. public:
  88. ecs_context_proxy_func(this_type, destroy_entity)
  89. ecs_context_proxy_func(this_type, post_in_thread_pool)
  90. ecs_context_proxy_func(this_type, for_systems_sequential)
  91. ecs_context_proxy_func(this_type, for_systems_parallel)
  92. ecs_context_proxy_func(this_type, for_systems_dispatch)
  93. public:
  94. inline context_t()
  95. : base_type(*this)
  96. { }
  97. template<typename T_step_func>
  98. inline decltype(auto) step(T_step_func&& step_func)
  99. {
  100. ecs_make_scope_guard([this]{
  101. this->refresh();
  102. });
  103. std::forward<T_step_func>(step_func)(static_cast<base_type&>(*this));
  104. }
  105. };
  106. struct make_t
  107. {
  108. template<typename T_settings>
  109. constexpr decltype(auto) operator()(T_settings) const noexcept
  110. { return context_t<T_settings> { }; }
  111. };
  112. struct make_uptr_t
  113. {
  114. template<typename T_settings>
  115. constexpr decltype(auto) operator()(T_settings) const noexcept
  116. { return std::make_unique<context_t<T_settings>>(); }
  117. };
  118. }
  119. constexpr decltype(auto) make = detail::make_t { };
  120. constexpr decltype(auto) make_uptr = detail::make_uptr_t { };
  121. } }