EnTT  3.10.0
group.hpp
1 #ifndef ENTT_ENTITY_GROUP_HPP
2 #define ENTT_ENTITY_GROUP_HPP
3 
4 #include <tuple>
5 #include <type_traits>
6 #include <utility>
7 #include "../config/config.h"
8 #include "../core/iterator.hpp"
9 #include "../core/type_traits.hpp"
10 #include "component.hpp"
11 #include "entity.hpp"
12 #include "fwd.hpp"
13 #include "sparse_set.hpp"
14 #include "storage.hpp"
15 #include "utility.hpp"
16 
17 namespace entt {
18 
25 template<typename, typename, typename, typename>
26 class basic_group;
27 
64 template<typename Entity, typename... Get, typename... Exclude>
65 class basic_group<Entity, owned_t<>, get_t<Get...>, exclude_t<Exclude...>> {
67  friend class basic_registry<Entity>;
68 
69  template<typename Comp>
70  using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Comp>>::storage_type, Comp>;
71 
72  using basic_common_type = std::common_type_t<typename storage_type<Get>::base_type...>;
73 
74  struct extended_group_iterator final {
75  using difference_type = std::ptrdiff_t;
76  using value_type = decltype(std::tuple_cat(std::tuple<Entity>{}, std::declval<basic_group>().get({})));
77  using pointer = input_iterator_pointer<value_type>;
78  using reference = value_type;
79  using iterator_category = std::input_iterator_tag;
80 
81  extended_group_iterator() = default;
82 
83  extended_group_iterator(typename basic_common_type::iterator from, const std::tuple<storage_type<Get> *...> &args)
84  : it{from},
85  pools{args} {}
86 
87  extended_group_iterator &operator++() ENTT_NOEXCEPT {
88  return ++it, *this;
89  }
90 
91  extended_group_iterator operator++(int) ENTT_NOEXCEPT {
92  extended_group_iterator orig = *this;
93  return ++(*this), orig;
94  }
95 
96  [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
97  const auto entt = *it;
98  return std::tuple_cat(std::make_tuple(entt), std::get<storage_type<Get> *>(pools)->get_as_tuple(entt)...);
99  }
100 
101  [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
102  return operator*();
103  }
104 
105  [[nodiscard]] bool operator==(const extended_group_iterator &other) const ENTT_NOEXCEPT {
106  return other.it == it;
107  }
108 
109  [[nodiscard]] bool operator!=(const extended_group_iterator &other) const ENTT_NOEXCEPT {
110  return !(*this == other);
111  }
112 
113  private:
114  typename basic_common_type::iterator it;
115  std::tuple<storage_type<Get> *...> pools;
116  };
117 
118  basic_group(basic_common_type &ref, storage_type<Get> &...gpool) ENTT_NOEXCEPT
119  : handler{&ref},
120  pools{&gpool...} {}
121 
122 public:
124  using entity_type = Entity;
126  using size_type = std::size_t;
128  using base_type = basic_common_type;
130  using iterator = typename base_type::iterator;
132  using reverse_iterator = typename base_type::reverse_iterator;
135 
137  basic_group() ENTT_NOEXCEPT
138  : handler{} {}
139 
144  const base_type &handle() const ENTT_NOEXCEPT {
145  return *handler;
146  }
147 
153  template<typename Comp>
154  [[nodiscard]] decltype(auto) storage() const ENTT_NOEXCEPT {
155  return *std::get<storage_type<Comp> *>(pools);
156  }
157 
163  template<std::size_t Comp>
164  [[nodiscard]] decltype(auto) storage() const ENTT_NOEXCEPT {
165  return *std::get<Comp>(pools);
166  }
167 
172  [[nodiscard]] size_type size() const ENTT_NOEXCEPT {
173  return *this ? handler->size() : size_type{};
174  }
175 
181  [[nodiscard]] size_type capacity() const ENTT_NOEXCEPT {
182  return *this ? handler->capacity() : size_type{};
183  }
184 
186  void shrink_to_fit() {
187  if(*this) {
188  handler->shrink_to_fit();
189  }
190  }
191 
196  [[nodiscard]] bool empty() const ENTT_NOEXCEPT {
197  return !*this || handler->empty();
198  }
199 
208  [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
209  return *this ? handler->begin() : iterator{};
210  }
211 
222  [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
223  return *this ? handler->end() : iterator{};
224  }
225 
234  [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT {
235  return *this ? handler->rbegin() : reverse_iterator{};
236  }
237 
249  [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
250  return *this ? handler->rend() : reverse_iterator{};
251  }
252 
258  [[nodiscard]] entity_type front() const ENTT_NOEXCEPT {
259  const auto it = begin();
260  return it != end() ? *it : null;
261  }
262 
268  [[nodiscard]] entity_type back() const ENTT_NOEXCEPT {
269  const auto it = rbegin();
270  return it != rend() ? *it : null;
271  }
272 
279  [[nodiscard]] iterator find(const entity_type entt) const ENTT_NOEXCEPT {
280  const auto it = *this ? handler->find(entt) : iterator{};
281  return it != end() && *it == entt ? it : end();
282  }
283 
289  [[nodiscard]] entity_type operator[](const size_type pos) const {
290  return begin()[pos];
291  }
292 
297  [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
298  return handler != nullptr;
299  }
300 
306  [[nodiscard]] bool contains(const entity_type entt) const ENTT_NOEXCEPT {
307  return *this && handler->contains(entt);
308  }
309 
325  template<typename... Comp>
326  [[nodiscard]] decltype(auto) get(const entity_type entt) const {
327  ENTT_ASSERT(contains(entt), "Group does not contain entity");
328 
329  if constexpr(sizeof...(Comp) == 0) {
330  return std::tuple_cat(std::get<storage_type<Get> *>(pools)->get_as_tuple(entt)...);
331  } else if constexpr(sizeof...(Comp) == 1) {
332  return (std::get<storage_type<Comp> *>(pools)->get(entt), ...);
333  } else {
334  return std::tuple_cat(std::get<storage_type<Comp> *>(pools)->get_as_tuple(entt)...);
335  }
336  }
337 
360  template<typename Func>
361  void each(Func func) const {
362  for(const auto entt: *this) {
363  if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_group>().get({})))>) {
364  std::apply(func, std::tuple_cat(std::make_tuple(entt), get(entt)));
365  } else {
366  std::apply(func, get(entt));
367  }
368  }
369  }
370 
384  [[nodiscard]] iterable each() const ENTT_NOEXCEPT {
385  return handler ? iterable{extended_group_iterator{handler->begin(), pools}, extended_group_iterator{handler->end(), pools}}
386  : iterable{extended_group_iterator{{}, pools}, extended_group_iterator{{}, pools}};
387  }
388 
425  template<typename... Comp, typename Compare, typename Sort = std_sort, typename... Args>
426  void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
427  if(*this) {
428  if constexpr(sizeof...(Comp) == 0) {
429  static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
430  handler->sort(std::move(compare), std::move(algo), std::forward<Args>(args)...);
431  } else {
432  auto comp = [this, &compare](const entity_type lhs, const entity_type rhs) {
433  if constexpr(sizeof...(Comp) == 1) {
434  return compare((std::get<storage_type<Comp> *>(pools)->get(lhs), ...), (std::get<storage_type<Comp> *>(pools)->get(rhs), ...));
435  } else {
436  return compare(std::forward_as_tuple(std::get<storage_type<Comp> *>(pools)->get(lhs)...), std::forward_as_tuple(std::get<storage_type<Comp> *>(pools)->get(rhs)...));
437  }
438  };
439 
440  handler->sort(std::move(comp), std::move(algo), std::forward<Args>(args)...);
441  }
442  }
443  }
444 
461  template<typename Comp>
462  void sort() const {
463  if(*this) {
464  handler->respect(*std::get<storage_type<Comp> *>(pools));
465  }
466  }
467 
468 private:
469  base_type *const handler;
470  const std::tuple<storage_type<Get> *...> pools;
471 };
472 
519 template<typename Entity, typename... Owned, typename... Get, typename... Exclude>
520 class basic_group<Entity, owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> {
522  friend class basic_registry<Entity>;
523 
524  template<typename Comp>
525  using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Comp>>::storage_type, Comp>;
526 
527  using basic_common_type = std::common_type_t<typename storage_type<Owned>::base_type..., typename storage_type<Get>::base_type...>;
528 
529  class extended_group_iterator final {
530  template<typename Type>
531  auto index_to_element(storage_type<Type> &cpool) const {
532  if constexpr(ignore_as_empty_v<std::remove_const_t<Type>>) {
533  return std::make_tuple();
534  } else {
535  return std::forward_as_tuple(cpool.rbegin()[it.index()]);
536  }
537  }
538 
539  public:
540  using difference_type = std::ptrdiff_t;
541  using value_type = decltype(std::tuple_cat(std::tuple<Entity>{}, std::declval<basic_group>().get({})));
542  using pointer = input_iterator_pointer<value_type>;
543  using reference = value_type;
544  using iterator_category = std::input_iterator_tag;
545 
546  extended_group_iterator() = default;
547 
548  template<typename... Other>
549  extended_group_iterator(typename basic_common_type::iterator from, const std::tuple<storage_type<Owned> *..., storage_type<Get> *...> &cpools)
550  : it{from},
551  pools{cpools} {}
552 
553  extended_group_iterator &operator++() ENTT_NOEXCEPT {
554  return ++it, *this;
555  }
556 
557  extended_group_iterator operator++(int) ENTT_NOEXCEPT {
558  extended_group_iterator orig = *this;
559  return ++(*this), orig;
560  }
561 
562  [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
563  return std::tuple_cat(
564  std::make_tuple(*it),
565  index_to_element<Owned>(*std::get<storage_type<Owned> *>(pools))...,
566  std::get<storage_type<Get> *>(pools)->get_as_tuple(*it)...);
567  }
568 
569  [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
570  return operator*();
571  }
572 
573  [[nodiscard]] bool operator==(const extended_group_iterator &other) const ENTT_NOEXCEPT {
574  return other.it == it;
575  }
576 
577  [[nodiscard]] bool operator!=(const extended_group_iterator &other) const ENTT_NOEXCEPT {
578  return !(*this == other);
579  }
580 
581  private:
582  typename basic_common_type::iterator it;
583  std::tuple<storage_type<Owned> *..., storage_type<Get> *...> pools;
584  };
585 
586  basic_group(const std::size_t &extent, storage_type<Owned> &...opool, storage_type<Get> &...gpool) ENTT_NOEXCEPT
587  : pools{&opool..., &gpool...},
588  length{&extent} {}
589 
590 public:
592  using entity_type = Entity;
594  using size_type = std::size_t;
596  using base_type = basic_common_type;
598  using iterator = typename base_type::iterator;
600  using reverse_iterator = typename base_type::reverse_iterator;
603 
605  basic_group() ENTT_NOEXCEPT
606  : length{} {}
607 
613  template<typename Comp>
614  [[nodiscard]] decltype(auto) storage() const ENTT_NOEXCEPT {
615  return *std::get<storage_type<Comp> *>(pools);
616  }
617 
623  template<std::size_t Comp>
624  [[nodiscard]] decltype(auto) storage() const ENTT_NOEXCEPT {
625  return *std::get<Comp>(pools);
626  }
627 
632  [[nodiscard]] size_type size() const ENTT_NOEXCEPT {
633  return *this ? *length : size_type{};
634  }
635 
640  [[nodiscard]] bool empty() const ENTT_NOEXCEPT {
641  return !*this || !*length;
642  }
643 
652  [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
653  return *this ? (std::get<0>(pools)->base_type::end() - *length) : iterator{};
654  }
655 
666  [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
667  return *this ? std::get<0>(pools)->base_type::end() : iterator{};
668  }
669 
678  [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT {
679  return *this ? std::get<0>(pools)->base_type::rbegin() : reverse_iterator{};
680  }
681 
693  [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
694  return *this ? (std::get<0>(pools)->base_type::rbegin() + *length) : reverse_iterator{};
695  }
696 
702  [[nodiscard]] entity_type front() const ENTT_NOEXCEPT {
703  const auto it = begin();
704  return it != end() ? *it : null;
705  }
706 
712  [[nodiscard]] entity_type back() const ENTT_NOEXCEPT {
713  const auto it = rbegin();
714  return it != rend() ? *it : null;
715  }
716 
723  [[nodiscard]] iterator find(const entity_type entt) const ENTT_NOEXCEPT {
724  const auto it = *this ? std::get<0>(pools)->find(entt) : iterator{};
725  return it != end() && it >= begin() && *it == entt ? it : end();
726  }
727 
733  [[nodiscard]] entity_type operator[](const size_type pos) const {
734  return begin()[pos];
735  }
736 
741  [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
742  return length != nullptr;
743  }
744 
750  [[nodiscard]] bool contains(const entity_type entt) const ENTT_NOEXCEPT {
751  return *this && std::get<0>(pools)->contains(entt) && (std::get<0>(pools)->index(entt) < (*length));
752  }
753 
769  template<typename... Comp>
770  [[nodiscard]] decltype(auto) get(const entity_type entt) const {
771  ENTT_ASSERT(contains(entt), "Group does not contain entity");
772 
773  if constexpr(sizeof...(Comp) == 0) {
774  return std::tuple_cat(std::get<storage_type<Owned> *>(pools)->get_as_tuple(entt)..., std::get<storage_type<Get> *>(pools)->get_as_tuple(entt)...);
775  } else if constexpr(sizeof...(Comp) == 1) {
776  return (std::get<storage_type<Comp> *>(pools)->get(entt), ...);
777  } else {
778  return std::tuple_cat(std::get<storage_type<Comp> *>(pools)->get_as_tuple(entt)...);
779  }
780  }
781 
804  template<typename Func>
805  void each(Func func) const {
806  for(auto args: each()) {
807  if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_group>().get({})))>) {
808  std::apply(func, args);
809  } else {
810  std::apply([&func](auto, auto &&...less) { func(std::forward<decltype(less)>(less)...); }, args);
811  }
812  }
813  }
814 
828  [[nodiscard]] iterable each() const ENTT_NOEXCEPT {
829  iterator last = length ? std::get<0>(pools)->basic_common_type::end() : iterator{};
830  return {extended_group_iterator{last - *length, pools}, extended_group_iterator{last, pools}};
831  }
832 
870  template<typename... Comp, typename Compare, typename Sort = std_sort, typename... Args>
871  void sort(Compare compare, Sort algo = Sort{}, Args &&...args) const {
872  auto *cpool = std::get<0>(pools);
873 
874  if constexpr(sizeof...(Comp) == 0) {
875  static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
876  cpool->sort_n(*length, std::move(compare), std::move(algo), std::forward<Args>(args)...);
877  } else {
878  auto comp = [this, &compare](const entity_type lhs, const entity_type rhs) {
879  if constexpr(sizeof...(Comp) == 1) {
880  return compare((std::get<storage_type<Comp> *>(pools)->get(lhs), ...), (std::get<storage_type<Comp> *>(pools)->get(rhs), ...));
881  } else {
882  return compare(std::forward_as_tuple(std::get<storage_type<Comp> *>(pools)->get(lhs)...), std::forward_as_tuple(std::get<storage_type<Comp> *>(pools)->get(rhs)...));
883  }
884  };
885 
886  cpool->sort_n(*length, std::move(comp), std::move(algo), std::forward<Args>(args)...);
887  }
888 
889  [this](auto *head, auto *...other) {
890  for(auto next = *length; next; --next) {
891  const auto pos = next - 1;
892  [[maybe_unused]] const auto entt = head->data()[pos];
893  (other->swap_elements(other->data()[pos], entt), ...);
894  }
895  }(std::get<storage_type<Owned> *>(pools)...);
896  }
897 
898 private:
899  const std::tuple<storage_type<Owned> *..., storage_type<Get> *...> pools;
900  const size_type *const length;
901 };
902 
903 } // namespace entt
904 
905 #endif
entity_type front() const
Returns the first entity of the group, if any.
Definition: group.hpp:702
size_type size() const
Returns the number of entities that have the given components.
Definition: group.hpp:632
typename base_type::iterator iterator
Random access iterator type.
Definition: group.hpp:598
iterator begin() const
Returns an iterator to the first entity of the group.
Definition: group.hpp:652
iterator end() const
Returns an iterator that is past the last entity of the group.
Definition: group.hpp:666
void each(Func func) const
Iterates entities and components and applies the given function object to them.
Definition: group.hpp:805
iterable each() const
Returns an iterable object to use to visit a group.
Definition: group.hpp:828
entity_type back() const
Returns the last entity of the group, if any.
Definition: group.hpp:712
typename base_type::reverse_iterator reverse_iterator
Reversed iterator type.
Definition: group.hpp:600
reverse_iterator rbegin() const
Returns an iterator to the first entity of the reversed group.
Definition: group.hpp:678
bool contains(const entity_type entt) const
Checks if a group contains an entity.
Definition: group.hpp:750
reverse_iterator rend() const
Returns an iterator that is past the last entity of the reversed group.
Definition: group.hpp:693
void sort(Compare compare, Sort algo=Sort{}, Args &&...args) const
Sort a group according to the given comparison function.
Definition: group.hpp:871
basic_group()
Default constructor to use to create empty, invalid groups.
Definition: group.hpp:605
entity_type operator[](const size_type pos) const
Returns the identifier that occupies the given position.
Definition: group.hpp:733
entity_type back() const
Returns the last entity of the group, if any.
Definition: group.hpp:268
iterable each() const
Returns an iterable object to use to visit a group.
Definition: group.hpp:384
basic_common_type base_type
Common type among all storage types.
Definition: group.hpp:128
basic_group()
Default constructor to use to create empty, invalid groups.
Definition: group.hpp:137
reverse_iterator rend() const
Returns an iterator that is past the last entity of the reversed group.
Definition: group.hpp:249
size_type size() const
Returns the number of entities that have the given components.
Definition: group.hpp:172
void shrink_to_fit()
Requests the removal of unused capacity.
Definition: group.hpp:186
const base_type & handle() const
Returns a const reference to the underlying handler.
Definition: group.hpp:144
bool contains(const entity_type entt) const
Checks if a group contains an entity.
Definition: group.hpp:306
entity_type front() const
Returns the first entity of the group, if any.
Definition: group.hpp:258
void sort(Compare compare, Sort algo=Sort{}, Args &&...args)
Sort a group according to the given comparison function.
Definition: group.hpp:426
typename base_type::iterator iterator
Random access iterator type.
Definition: group.hpp:130
entity_type operator[](const size_type pos) const
Returns the identifier that occupies the given position.
Definition: group.hpp:289
iterator end() const
Returns an iterator that is past the last entity of the group.
Definition: group.hpp:222
iterator find(const entity_type entt) const
Finds an entity.
Definition: group.hpp:279
void sort() const
Sort the shared pool of entities according to the given component.
Definition: group.hpp:462
reverse_iterator rbegin() const
Returns an iterator to the first entity of the reversed group.
Definition: group.hpp:234
size_type capacity() const
Returns the number of elements that a group has currently allocated space for.
Definition: group.hpp:181
iterator begin() const
Returns an iterator to the first entity of the group.
Definition: group.hpp:208
void each(Func func) const
Iterates entities and components and applies the given function object to them.
Definition: group.hpp:361
typename base_type::reverse_iterator reverse_iterator
Reversed iterator type.
Definition: group.hpp:132
Group.
Definition: fwd.hpp:26
Fast and reliable entity-component system.
Definition: registry.hpp:221
Basic storage implementation.
Definition: storage.hpp:234
EnTT default namespace.
Definition: dense_map.hpp:22
constexpr bool operator==(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs)
Compares two hashed strings.
constexpr bool is_applicable_v
Helper variable template.
typename constness_as< To, From >::type constness_as_t
Alias template to facilitate the transcription of the constness.
constexpr get_t< Type... > get
Variable template for lists of observed components.
Definition: utility.hpp:34
constexpr bool ignore_as_empty_v
Helper variable template.
Definition: component.hpp:57
bool operator!=(const basic_any< Len, Align > &lhs, const basic_any< Len, Align > &rhs)
Checks if two wrappers differ in their content.
Definition: any.hpp:402
Alias for exclusion lists.
Definition: utility.hpp:13
Alias for lists of observed components.
Definition: utility.hpp:27
Helper type to use as pointer with input iterators.
Definition: iterator.hpp:16
Utility class to create an iterable object from a pair of iterators.
Definition: iterator.hpp:63
iterator begin() const
Returns an iterator to the beginning.
Definition: iterator.hpp:87
Alias for lists of owned components.
Definition: utility.hpp:41
Function object to wrap std::sort in a class type.
Definition: algorithm.hpp:21