🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
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.

272 lines
8.8 KiB

  1. #ifndef ENTT_ENTITY_RUNTIME_VIEW_HPP
  2. #define ENTT_ENTITY_RUNTIME_VIEW_HPP
  3. #include <algorithm>
  4. #include <iterator>
  5. #include <type_traits>
  6. #include <utility>
  7. #include <vector>
  8. #include "../config/config.h"
  9. #include "entity.hpp"
  10. #include "fwd.hpp"
  11. #include "sparse_set.hpp"
  12. namespace entt {
  13. /**
  14. * @cond TURN_OFF_DOXYGEN
  15. * Internal details not to be documented.
  16. */
  17. namespace internal {
  18. template<typename Set>
  19. class runtime_view_iterator final {
  20. using iterator_type = typename Set::iterator;
  21. [[nodiscard]] bool valid() const {
  22. return (!tombstone_check || *it != tombstone)
  23. && std::all_of(++pools->begin(), pools->end(), [entt = *it](const auto *curr) { return curr->contains(entt); })
  24. && std::none_of(filter->cbegin(), filter->cend(), [entt = *it](const auto *curr) { return curr && curr->contains(entt); });
  25. }
  26. public:
  27. using difference_type = typename iterator_type::difference_type;
  28. using value_type = typename iterator_type::value_type;
  29. using pointer = typename iterator_type::pointer;
  30. using reference = typename iterator_type::reference;
  31. using iterator_category = std::bidirectional_iterator_tag;
  32. runtime_view_iterator() ENTT_NOEXCEPT
  33. : pools{},
  34. filter{},
  35. it{},
  36. tombstone_check{} {}
  37. runtime_view_iterator(const std::vector<const Set *> &cpools, const std::vector<const Set *> &ignore, iterator_type curr) ENTT_NOEXCEPT
  38. : pools{&cpools},
  39. filter{&ignore},
  40. it{curr},
  41. tombstone_check{pools->size() == 1u && (*pools)[0u]->policy() == deletion_policy::in_place} {
  42. if(it != (*pools)[0]->end() && !valid()) {
  43. ++(*this);
  44. }
  45. }
  46. runtime_view_iterator &operator++() {
  47. while(++it != (*pools)[0]->end() && !valid()) {}
  48. return *this;
  49. }
  50. runtime_view_iterator operator++(int) {
  51. runtime_view_iterator orig = *this;
  52. return ++(*this), orig;
  53. }
  54. runtime_view_iterator &operator--() {
  55. while(--it != (*pools)[0]->begin() && !valid()) {}
  56. return *this;
  57. }
  58. runtime_view_iterator operator--(int) {
  59. runtime_view_iterator orig = *this;
  60. return operator--(), orig;
  61. }
  62. [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
  63. return it.operator->();
  64. }
  65. [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
  66. return *operator->();
  67. }
  68. [[nodiscard]] bool operator==(const runtime_view_iterator &other) const ENTT_NOEXCEPT {
  69. return it == other.it;
  70. }
  71. [[nodiscard]] bool operator!=(const runtime_view_iterator &other) const ENTT_NOEXCEPT {
  72. return !(*this == other);
  73. }
  74. private:
  75. const std::vector<const Set *> *pools;
  76. const std::vector<const Set *> *filter;
  77. iterator_type it;
  78. bool tombstone_check;
  79. };
  80. } // namespace internal
  81. /**
  82. * Internal details not to be documented.
  83. * @endcond
  84. */
  85. /**
  86. * @brief Runtime view implementation.
  87. *
  88. * Primary template isn't defined on purpose. All the specializations give a
  89. * compile-time error, but for a few reasonable cases.
  90. */
  91. template<typename>
  92. struct basic_runtime_view;
  93. /**
  94. * @brief Generic runtime view.
  95. *
  96. * Runtime views iterate over those entities that have at least all the given
  97. * components in their bags. During initialization, a runtime view looks at the
  98. * number of entities available for each component and picks up a reference to
  99. * the smallest set of candidate entities in order to get a performance boost
  100. * when iterate.<br/>
  101. * Order of elements during iterations are highly dependent on the order of the
  102. * underlying data structures. See sparse_set and its specializations for more
  103. * details.
  104. *
  105. * @b Important
  106. *
  107. * Iterators aren't invalidated if:
  108. *
  109. * * New instances of the given components are created and assigned to entities.
  110. * * The entity currently pointed is modified (as an example, if one of the
  111. * given components is removed from the entity to which the iterator points).
  112. * * The entity currently pointed is destroyed.
  113. *
  114. * In all the other cases, modifying the pools of the given components in any
  115. * way invalidates all the iterators and using them results in undefined
  116. * behavior.
  117. *
  118. * @note
  119. * Views share references to the underlying data structures of the registry that
  120. * generated them. Therefore any change to the entities and to the components
  121. * made by means of the registry are immediately reflected by the views, unless
  122. * a pool was missing when the view was built (in this case, the view won't
  123. * have a valid reference and won't be updated accordingly).
  124. *
  125. * @warning
  126. * Lifetime of a view must not overcome that of the registry that generated it.
  127. * In any other case, attempting to use a view results in undefined behavior.
  128. *
  129. * @tparam Entity A valid entity type (see entt_traits for more details).
  130. * @tparam Allocator Type of allocator used to manage memory and elements.
  131. */
  132. template<typename Entity, typename Allocator>
  133. struct basic_runtime_view<basic_sparse_set<Entity, Allocator>> {
  134. /*! @brief Underlying entity identifier. */
  135. using entity_type = Entity;
  136. /*! @brief Unsigned integer type. */
  137. using size_type = std::size_t;
  138. /*! @brief Common type among all storage types. */
  139. using base_type = basic_sparse_set<Entity, Allocator>;
  140. /*! @brief Bidirectional iterator type. */
  141. using iterator = internal::runtime_view_iterator<base_type>;
  142. /*! @brief Default constructor to use to create empty, invalid views. */
  143. basic_runtime_view() ENTT_NOEXCEPT
  144. : pools{},
  145. filter{} {}
  146. /**
  147. * @brief Appends an opaque storage object to a runtime view.
  148. * @param base An opaque reference to a storage object.
  149. * @return This runtime view.
  150. */
  151. basic_runtime_view &iterate(const base_type &base) {
  152. if(pools.empty() || !(base.size() < pools[0u]->size())) {
  153. pools.push_back(&base);
  154. } else {
  155. pools.push_back(std::exchange(pools[0u], &base));
  156. }
  157. return *this;
  158. }
  159. /**
  160. * @brief Adds an opaque storage object as a filter of a runtime view.
  161. * @param base An opaque reference to a storage object.
  162. * @return This runtime view.
  163. */
  164. basic_runtime_view &exclude(const base_type &base) {
  165. filter.push_back(&base);
  166. return *this;
  167. }
  168. /**
  169. * @brief Estimates the number of entities iterated by the view.
  170. * @return Estimated number of entities iterated by the view.
  171. */
  172. [[nodiscard]] size_type size_hint() const {
  173. return pools.empty() ? size_type{} : pools.front()->size();
  174. }
  175. /**
  176. * @brief Returns an iterator to the first entity that has the given
  177. * components.
  178. *
  179. * The returned iterator points to the first entity that has the given
  180. * components. If the view is empty, the returned iterator will be equal to
  181. * `end()`.
  182. *
  183. * @return An iterator to the first entity that has the given components.
  184. */
  185. [[nodiscard]] iterator begin() const {
  186. return pools.empty() ? iterator{} : iterator{pools, filter, pools[0]->begin()};
  187. }
  188. /**
  189. * @brief Returns an iterator that is past the last entity that has the
  190. * given components.
  191. *
  192. * The returned iterator points to the entity following the last entity that
  193. * has the given components. Attempting to dereference the returned iterator
  194. * results in undefined behavior.
  195. *
  196. * @return An iterator to the entity following the last entity that has the
  197. * given components.
  198. */
  199. [[nodiscard]] iterator end() const {
  200. return pools.empty() ? iterator{} : iterator{pools, filter, pools[0]->end()};
  201. }
  202. /**
  203. * @brief Checks if a view contains an entity.
  204. * @param entt A valid identifier.
  205. * @return True if the view contains the given entity, false otherwise.
  206. */
  207. [[nodiscard]] bool contains(const entity_type entt) const {
  208. return !pools.empty()
  209. && std::all_of(pools.cbegin(), pools.cend(), [entt](const auto *curr) { return curr->contains(entt); })
  210. && std::none_of(filter.cbegin(), filter.cend(), [entt](const auto *curr) { return curr && curr->contains(entt); });
  211. }
  212. /**
  213. * @brief Iterates entities and applies the given function object to them.
  214. *
  215. * The function object is invoked for each entity. It is provided only with
  216. * the entity itself. To get the components, users can use the registry with
  217. * which the view was built.<br/>
  218. * The signature of the function should be equivalent to the following:
  219. *
  220. * @code{.cpp}
  221. * void(const entity_type);
  222. * @endcode
  223. *
  224. * @tparam Func Type of the function object to invoke.
  225. * @param func A valid function object.
  226. */
  227. template<typename Func>
  228. void each(Func func) const {
  229. for(const auto entity: *this) {
  230. func(entity);
  231. }
  232. }
  233. private:
  234. std::vector<const base_type *> pools;
  235. std::vector<const base_type *> filter;
  236. };
  237. } // namespace entt
  238. #endif