You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

225 lines
6.8 KiB

  1. #pragma once
  2. #include <ecs/context/base.h>
  3. namespace ecs {
  4. namespace context {
  5. namespace detail {
  6. /* constructor */
  7. template<typename T_settings>
  8. inline base_t<T_settings>
  9. ::base_t(context_type& p_context)
  10. : _context (p_context)
  11. , _components ()
  12. , _entities ((settings_type { }).entity_storage()(settings_type { }, hana::type_c<storage_meta_data_type>))
  13. , _systems ((settings_type { }).system_storage()(settings_type { }, hana::type_c<entity_handle_type>))
  14. , _scheduler ((settings_type { }).scheduler()(settings_type { }, p_context))
  15. , _thread_pool (std::thread::hardware_concurrency() != 0
  16. ? std::thread::hardware_concurrency()
  17. : 8 )
  18. { }
  19. /* misc */
  20. template<typename T_settings>
  21. template<typename T_func>
  22. inline void base_t<T_settings>
  23. ::_post_in_thread_pool(T_func&& func, ssize_t thread_id)
  24. {
  25. _thread_pool.post(std::forward<T_func>(func), thread_id);
  26. }
  27. /* entity */
  28. template<typename T_settings>
  29. template<typename... T_args>
  30. inline decltype(auto) base_t<T_settings>
  31. ::_create_entity(T_args&&... args)
  32. {
  33. auto handle = _entities.claim(std::forward<T_args>(args)...);
  34. _to_match.insert(handle);
  35. return handle;
  36. }
  37. template<typename T_settings>
  38. inline void base_t<T_settings>
  39. ::_kill_entity(const handle_type& handle)
  40. {
  41. _to_kill.insert(handle);
  42. }
  43. template<typename T_settings>
  44. inline bool base_t<T_settings>
  45. ::_is_alive(const handle_type& handle) const
  46. {
  47. return _entities.is_valid(handle);
  48. }
  49. template<typename T_settings>
  50. inline void base_t<T_settings>
  51. ::_destroy_entity(const handle_type& handle)
  52. {
  53. _entities.reclaim(handle);
  54. }
  55. template<typename T_settings>
  56. inline const auto& base_t<T_settings>
  57. ::_entity_meta_data(const handle_type& handle)
  58. {
  59. return _entities.meta_data(handle);
  60. }
  61. /* components */
  62. template<typename T_settings>
  63. template<typename T_component_tag>
  64. inline decltype(auto) base_t<T_settings>
  65. ::_add_component(const handle_type& handle, T_component_tag ct)
  66. {
  67. _to_match.insert(handle);
  68. auto& meta = _entities.meta_data(handle);
  69. auto& cmd = meta.storage_meta_data();
  70. auto& c = _components.add(ct, handle, cmd);
  71. auto& bitset = meta.bitset();
  72. bitset.set_component(ct, true);
  73. return c;
  74. }
  75. template<typename T_settings>
  76. template<typename T_component_tag>
  77. inline decltype(auto) base_t<T_settings>
  78. ::_has_component(const handle_type& handle, T_component_tag ct)
  79. {
  80. auto& meta = _entities.meta_data(handle);
  81. auto& bitset = meta.bitset();
  82. return bitset.has_component(ct);
  83. }
  84. template<typename T_settings>
  85. template<typename T_component_tag>
  86. inline decltype(auto) base_t<T_settings>
  87. ::_get_component(const handle_type& handle, T_component_tag ct)
  88. {
  89. auto& meta = _entities.meta_data(handle);
  90. auto& bitset = meta.bitset();
  91. auto& cmd = meta.storage_meta_data();
  92. if (!bitset.has_component(ct))
  93. throw std::invalid_argument("entity does not contain the requested component");
  94. return _components.get(ct, handle, cmd);
  95. }
  96. template<typename T_settings>
  97. template<typename T_component_tag>
  98. inline void base_t<T_settings>
  99. ::_remove_component(const handle_type& handle, T_component_tag ct)
  100. {
  101. _to_match.emplace_back(handle);
  102. auto& meta = _entities.meta_data(handle);
  103. auto& bitset = meta.bitset();
  104. bitset.set_component(ct, false);
  105. }
  106. /* systems */
  107. template<typename T_settings>
  108. template<typename T_system_tag>
  109. inline auto& base_t<T_settings>
  110. ::_instance_by_tag(T_system_tag st)
  111. {
  112. return _systems.instance_by_tag(st);
  113. }
  114. template<typename T_settings>
  115. template<typename T_index>
  116. inline auto& base_t<T_settings>
  117. ::_instance_by_index(T_index index)
  118. {
  119. return _systems.instance_by_index(T_index { });
  120. }
  121. template<typename T_settings>
  122. template<typename T_system_tag>
  123. inline auto& base_t<T_settings>
  124. ::_system_by_tag(T_system_tag st)
  125. {
  126. return _systems.instance_by_tag(st).system();
  127. }
  128. template<typename T_settings>
  129. template<typename T_index>
  130. inline auto& base_t<T_settings>
  131. ::_system_by_index(T_index)
  132. {
  133. return _systems.instance_by_index(T_index { }).system();
  134. }
  135. template<typename T_settings>
  136. template<typename T_func>
  137. inline void base_t<T_settings>
  138. ::_for_systems_sequential(T_func&& func)
  139. {
  140. _systems.for_each(std::forward<T_func>(func));
  141. }
  142. template<typename T_settings>
  143. template<typename T_func>
  144. inline void base_t<T_settings>
  145. ::_for_systems_parallel(T_func&& func)
  146. {
  147. core::utils::counter_blocker counter(_systems.size());
  148. counter.execute_and_wait([this, &counter, func = std::forward<T_func>(func)]{
  149. _systems.for_each([this, &counter, &func](auto& instance){
  150. this->_post_in_thread_pool([&counter, &func, &instance]{
  151. ecs_make_scope_guard([&counter](){
  152. counter.decrement();
  153. });
  154. func(instance);
  155. });
  156. });
  157. });
  158. }
  159. template<typename T_settings>
  160. template<typename T_func>
  161. inline void base_t<T_settings>
  162. ::_for_systems_dispatch(T_func&& func)
  163. {
  164. hana::eval_if(
  165. (settings_type { }).refresh_parallelism(),
  166. [this, func=std::forward<T_func>(func)](auto _) {
  167. _(this)->_for_systems_parallel(func);
  168. },
  169. [this, func=std::forward<T_func>(func)](auto _) {
  170. _(this)->_for_systems_sequential(func);
  171. });
  172. }
  173. template<typename T_settings>
  174. template<typename... T_system_tags>
  175. inline decltype(auto) base_t<T_settings>
  176. ::_execute_systems(T_system_tags&&... sts) noexcept
  177. {
  178. auto tags = make_system_tag_list(std::forward<T_system_tags>(sts)...);
  179. return [tags, this](auto&&... fns) {
  180. auto os = hana::overload_linearly(std::forward<decltype(fns)>(fns)...);
  181. this->_scheduler.execute(tags, os);
  182. };
  183. }
  184. /* static */
  185. template<typename T_settings>
  186. template<typename... T_system_tags>
  187. constexpr decltype(auto) base_t<T_settings>
  188. ::make_system_tag_list(T_system_tags&&... tags) noexcept
  189. {
  190. auto list = core::mp::list::make(std::forward<T_system_tags>(tags)...);
  191. return hana::if_(
  192. hana::equal(hana::size(list), hana::size_c<0>),
  193. (settings_type { }).system_signatures().tags(),
  194. list);
  195. }
  196. } } }