EnTT 3.13.1
Loading...
Searching...
No Matches
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/fwd.hpp"
9#include "../core/iterator.hpp"
10#include "../core/type_info.hpp"
11#include "../core/type_traits.hpp"
12#include "entity.hpp"
13#include "fwd.hpp"
14#include "sparse_set.hpp"
15#include "storage.hpp"
16
17namespace entt {
18
20namespace internal {
21
22template<typename, typename, typename>
23class extended_group_iterator;
24
25template<typename It, typename... Owned, typename... Get>
26class extended_group_iterator<It, owned_t<Owned...>, get_t<Get...>> {
27 template<typename Type>
28 auto index_to_element([[maybe_unused]] Type &cpool) const {
29 if constexpr(Type::traits_type::page_size == 0u) {
30 return std::make_tuple();
31 } else {
32 return std::forward_as_tuple(cpool.rbegin()[it.index()]);
33 }
34 }
35
36public:
37 using iterator_type = It;
38 using difference_type = std::ptrdiff_t;
39 using value_type = decltype(std::tuple_cat(std::make_tuple(*std::declval<It>()), std::declval<Owned>().get_as_tuple({})..., std::declval<Get>().get_as_tuple({})...));
40 using pointer = input_iterator_pointer<value_type>;
41 using reference = value_type;
42 using iterator_category = std::input_iterator_tag;
43 using iterator_concept = std::forward_iterator_tag;
44
45 constexpr extended_group_iterator()
46 : it{},
47 pools{} {}
48
49 extended_group_iterator(iterator_type from, const std::tuple<Owned *..., Get *...> &cpools)
50 : it{from},
51 pools{cpools} {}
52
53 extended_group_iterator &operator++() noexcept {
54 return ++it, *this;
55 }
56
57 extended_group_iterator operator++(int) noexcept {
58 extended_group_iterator orig = *this;
59 return ++(*this), orig;
60 }
61
62 [[nodiscard]] reference operator*() const noexcept {
63 return std::tuple_cat(std::make_tuple(*it), index_to_element(*std::get<Owned *>(pools))..., std::get<Get *>(pools)->get_as_tuple(*it)...);
64 }
65
66 [[nodiscard]] pointer operator->() const noexcept {
67 return operator*();
68 }
69
70 [[nodiscard]] constexpr iterator_type base() const noexcept {
71 return it;
72 }
73
74 template<typename... Lhs, typename... Rhs>
75 friend constexpr bool operator==(const extended_group_iterator<Lhs...> &, const extended_group_iterator<Rhs...> &) noexcept;
76
77private:
78 It it;
79 std::tuple<Owned *..., Get *...> pools;
80};
81
82template<typename... Lhs, typename... Rhs>
83[[nodiscard]] constexpr bool operator==(const extended_group_iterator<Lhs...> &lhs, const extended_group_iterator<Rhs...> &rhs) noexcept {
84 return lhs.it == rhs.it;
85}
86
87template<typename... Lhs, typename... Rhs>
88[[nodiscard]] constexpr bool operator!=(const extended_group_iterator<Lhs...> &lhs, const extended_group_iterator<Rhs...> &rhs) noexcept {
89 return !(lhs == rhs);
90}
91
92struct group_descriptor {
93 using size_type = std::size_t;
94 virtual ~group_descriptor() = default;
95 virtual size_type owned(const id_type *, const size_type) const noexcept {
96 return 0u;
97 }
98};
99
100template<typename, typename, typename>
101class group_handler;
102
103template<typename... Owned, typename... Get, typename... Exclude>
104class group_handler<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> final: public group_descriptor {
105 // nasty workaround for an issue with the toolset v141 that doesn't accept a fold expression here
106 static_assert(!std::disjunction_v<std::bool_constant<Owned::traits_type::in_place_delete>...>, "Groups do not support in-place delete");
107 static_assert(!std::disjunction_v<std::is_const<Owned>..., std::is_const<Get>..., std::is_const<Exclude>...>, "Const storage type not allowed");
108
109 using base_type = std::common_type_t<typename Owned::base_type..., typename Get::base_type..., typename Exclude::base_type...>;
110 using entity_type = typename base_type::entity_type;
111
112 template<std::size_t... Index>
113 void swap_elements(const std::size_t pos, const entity_type entt, std::index_sequence<Index...>) {
114 (std::get<Index>(pools)->swap_elements(std::get<Index>(pools)->data()[pos], entt), ...);
115 }
116
117 void push_on_construct(const entity_type entt) {
118 if(std::apply([entt, len = len](auto *cpool, auto *...other) { return cpool->contains(entt) && !(cpool->index(entt) < len) && (other->contains(entt) && ...); }, pools)
119 && std::apply([entt](auto *...cpool) { return (!cpool->contains(entt) && ...); }, filter)) {
120 swap_elements(len++, entt, std::index_sequence_for<Owned...>{});
121 }
122 }
123
124 void push_on_destroy(const entity_type entt) {
125 if(std::apply([entt, len = len](auto *cpool, auto *...other) { return cpool->contains(entt) && !(cpool->index(entt) < len) && (other->contains(entt) && ...); }, pools)
126 && std::apply([entt](auto *...cpool) { return (0u + ... + cpool->contains(entt)) == 1u; }, filter)) {
127 swap_elements(len++, entt, std::index_sequence_for<Owned...>{});
128 }
129 }
130
131 void remove_if(const entity_type entt) {
132 if(std::get<0>(pools)->contains(entt) && (std::get<0>(pools)->index(entt) < len)) {
133 swap_elements(--len, entt, std::index_sequence_for<Owned...>{});
134 }
135 }
136
137public:
138 using size_type = typename base_type::size_type;
139
140 group_handler(Owned &...opool, Get &...gpool, Exclude &...epool)
141 : pools{&opool..., &gpool...},
142 filter{&epool...},
143 len{} {
144 std::apply([this](auto *...cpool) { ((cpool->on_construct().template connect<&group_handler::push_on_construct>(*this), cpool->on_destroy().template connect<&group_handler::remove_if>(*this)), ...); }, pools);
145 std::apply([this](auto *...cpool) { ((cpool->on_construct().template connect<&group_handler::remove_if>(*this), cpool->on_destroy().template connect<&group_handler::push_on_destroy>(*this)), ...); }, filter);
146
147 // we cannot iterate backwards because we want to leave behind valid entities in case of owned types
148 for(auto *first = std::get<0>(pools)->data(), *last = first + std::get<0>(pools)->size(); first != last; ++first) {
149 push_on_construct(*first);
150 }
151 }
152
153 size_type owned(const id_type *elem, const size_type length) const noexcept final {
154 size_type cnt = 0u;
155
156 for(auto pos = 0u; pos < length; ++pos) {
157 cnt += ((elem[pos] == entt::type_hash<typename Owned::value_type>::value()) || ...);
158 }
159
160 return cnt;
161 }
162
163 [[nodiscard]] size_type length() const noexcept {
164 return len;
165 }
166
167 auto pools_as_tuple() const noexcept {
168 return pools;
169 }
170
171 auto filter_as_tuple() const noexcept {
172 return filter;
173 }
174
175private:
176 std::tuple<Owned *..., Get *...> pools;
177 std::tuple<Exclude *...> filter;
178 std::size_t len;
179};
180
181template<typename... Get, typename... Exclude>
182class group_handler<owned_t<>, get_t<Get...>, exclude_t<Exclude...>> final: public group_descriptor {
183 // nasty workaround for an issue with the toolset v141 that doesn't accept a fold expression here
184 static_assert(!std::disjunction_v<std::is_const<Get>..., std::is_const<Exclude>...>, "Const storage type not allowed");
185
186 using base_type = std::common_type_t<typename Get::base_type..., typename Exclude::base_type...>;
187 using entity_type = typename base_type::entity_type;
188
189 void push_on_construct(const entity_type entt) {
190 if(!elem.contains(entt)
191 && std::apply([entt](auto *...cpool) { return (cpool->contains(entt) && ...); }, pools)
192 && std::apply([entt](auto *...cpool) { return (!cpool->contains(entt) && ...); }, filter)) {
193 elem.push(entt);
194 }
195 }
196
197 void push_on_destroy(const entity_type entt) {
198 if(!elem.contains(entt)
199 && std::apply([entt](auto *...cpool) { return (cpool->contains(entt) && ...); }, pools)
200 && std::apply([entt](auto *...cpool) { return (0u + ... + cpool->contains(entt)) == 1u; }, filter)) {
201 elem.push(entt);
202 }
203 }
204
205 void remove_if(const entity_type entt) {
206 elem.remove(entt);
207 }
208
209public:
210 using common_type = base_type;
211
212 template<typename Alloc>
213 group_handler(const Alloc &alloc, Get &...gpool, Exclude &...epool)
214 : pools{&gpool...},
215 filter{&epool...},
216 elem{alloc} {
217 std::apply([this](auto *...cpool) { ((cpool->on_construct().template connect<&group_handler::push_on_construct>(*this), cpool->on_destroy().template connect<&group_handler::remove_if>(*this)), ...); }, pools);
218 std::apply([this](auto *...cpool) { ((cpool->on_construct().template connect<&group_handler::remove_if>(*this), cpool->on_destroy().template connect<&group_handler::push_on_destroy>(*this)), ...); }, filter);
219
220 for(const auto entity: static_cast<base_type &>(*std::get<0>(pools))) {
221 push_on_construct(entity);
222 }
223 }
224
225 common_type &handle() noexcept {
226 return elem;
227 }
228
229 const common_type &handle() const noexcept {
230 return elem;
231 }
232
233 auto pools_as_tuple() const noexcept {
234 return pools;
235 }
236
237 auto filter_as_tuple() const noexcept {
238 return filter;
239 }
240
241private:
242 std::tuple<Get *...> pools;
243 std::tuple<Exclude *...> filter;
244 base_type elem;
245};
246
247} // namespace internal
256template<typename, typename, typename>
257class basic_group;
258
281template<typename... Get, typename... Exclude>
283 using base_type = std::common_type_t<typename Get::base_type..., typename Exclude::base_type...>;
284 using underlying_type = typename base_type::entity_type;
285
286 template<typename Type>
287 static constexpr std::size_t index_of = type_list_index_v<std::remove_const_t<Type>, type_list<typename Get::value_type..., typename Exclude::value_type...>>;
288
289 auto pools() const noexcept {
290 using return_type = std::tuple<Get *...>;
291 return descriptor ? descriptor->pools_as_tuple() : return_type{};
292 }
293
294 auto filter() const noexcept {
295 using return_type = std::tuple<Exclude *...>;
296 return descriptor ? descriptor->filter_as_tuple() : return_type{};
297 }
298
299public:
301 using entity_type = underlying_type;
303 using size_type = std::size_t;
305 using common_type = base_type;
307 using iterator = typename common_type::iterator;
309 using reverse_iterator = typename common_type::reverse_iterator;
313 using handler = internal::group_handler<owned_t<>, get_t<std::remove_const_t<Get>...>, exclude_t<std::remove_const_t<Exclude>...>>;
314
317 : descriptor{} {}
318
324 : descriptor{&ref} {}
325
331 return descriptor->handle();
332 }
333
339 template<typename Type>
341 return storage<index_of<Type>>();
342 }
343
349 template<std::size_t Index>
351 constexpr auto offset = sizeof...(Get);
352
353 if constexpr(Index < offset) {
354 return std::get<Index>(pools());
355 } else {
356 return std::get<Index - offset>(filter());
357 }
358 }
359
365 return *this ? handle().size() : size_type{};
366 }
367
374 return *this ? handle().capacity() : size_type{};
375 }
376
379 if(*this) {
380 descriptor->handle().shrink_to_fit();
381 }
382 }
383
389 return !*this || handle().empty();
390 }
391
400 return *this ? handle().begin() : iterator{};
401 }
402
409 return *this ? handle().end() : iterator{};
410 }
411
420 return *this ? handle().rbegin() : reverse_iterator{};
421 }
422
430 return *this ? handle().rend() : reverse_iterator{};
431 }
432
439 const auto it = begin();
440 return it != end() ? *it : null;
441 }
442
449 const auto it = rbegin();
450 return it != rend() ? *it : null;
451 }
452
459 [[nodiscard]] iterator find(const entity_type entt) const noexcept {
460 return *this ? handle().find(entt) : iterator{};
461 }
462
469 return begin()[pos];
470 }
471
476 [[nodiscard]] explicit operator bool() const noexcept {
477 return descriptor != nullptr;
478 }
479
485 [[nodiscard]] bool contains(const entity_type entt) const noexcept {
486 return *this && handle().contains(entt);
487 }
488
496 template<typename Type, typename... Other>
497 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
499 }
500
507 template<std::size_t... Index>
508 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
509 const auto cpools = pools();
510
511 if constexpr(sizeof...(Index) == 0) {
512 return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, cpools);
513 } else if constexpr(sizeof...(Index) == 1) {
514 return (std::get<Index>(cpools)->get(entt), ...);
515 } else {
516 return std::tuple_cat(std::get<Index>(cpools)->get_as_tuple(entt)...);
517 }
518 }
519
542 template<typename Func>
543 void each(Func func) const {
544 for(const auto entt: *this) {
545 if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_group>().get({})))>) {
546 std::apply(func, std::tuple_cat(std::make_tuple(entt), get(entt)));
547 } else {
548 std::apply(func, get(entt));
549 }
550 }
551 }
552
567 const auto cpools = pools();
568 return iterable{{begin(), cpools}, {end(), cpools}};
569 }
570
604 template<typename Type, typename... Other, typename Compare, typename Sort = std_sort, typename... Args>
605 void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
606 sort<index_of<Type>, index_of<Other>...>(std::move(compare), std::move(algo), std::forward<Args>(args)...);
607 }
608
622 template<std::size_t... Index, typename Compare, typename Sort = std_sort, typename... Args>
623 void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
624 if(*this) {
625 if constexpr(sizeof...(Index) == 0) {
626 static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
627 descriptor->handle().sort(std::move(compare), std::move(algo), std::forward<Args>(args)...);
628 } else {
629 auto comp = [&compare, cpools = pools()](const entity_type lhs, const entity_type rhs) {
630 if constexpr(sizeof...(Index) == 1) {
631 return compare((std::get<Index>(cpools)->get(lhs), ...), (std::get<Index>(cpools)->get(rhs), ...));
632 } else {
633 return compare(std::forward_as_tuple(std::get<Index>(cpools)->get(lhs)...), std::forward_as_tuple(std::get<Index>(cpools)->get(rhs)...));
634 }
635 };
636
637 descriptor->handle().sort(std::move(comp), std::move(algo), std::forward<Args>(args)...);
638 }
639 }
640 }
641
652 template<typename It>
653 void sort_as(It first, It last) const {
654 if(*this) {
655 descriptor->handle().sort_as(first, last);
656 }
657 }
658
663 [[deprecated("use iterator based sort_as instead")]] void sort_as(const common_type &other) const {
664 sort_as(other.begin(), other.end());
665 }
666
667private:
668 handler *descriptor;
669};
670
702template<typename... Owned, typename... Get, typename... Exclude>
704 using base_type = std::common_type_t<typename Owned::base_type..., typename Get::base_type..., typename Exclude::base_type...>;
705 using underlying_type = typename base_type::entity_type;
706
707 template<typename Type>
708 static constexpr std::size_t index_of = type_list_index_v<std::remove_const_t<Type>, type_list<typename Owned::value_type..., typename Get::value_type..., typename Exclude::value_type...>>;
709
710 auto pools() const noexcept {
711 using return_type = std::tuple<Owned *..., Get *...>;
712 return descriptor ? descriptor->pools_as_tuple() : return_type{};
713 }
714
715 auto filter() const noexcept {
716 using return_type = std::tuple<Exclude *...>;
717 return descriptor ? descriptor->filter_as_tuple() : return_type{};
718 }
719
720public:
722 using entity_type = underlying_type;
724 using size_type = std::size_t;
726 using common_type = base_type;
728 using iterator = typename common_type::iterator;
730 using reverse_iterator = typename common_type::reverse_iterator;
732 using iterable = iterable_adaptor<internal::extended_group_iterator<iterator, owned_t<Owned...>, get_t<Get...>>>;
734 using handler = internal::group_handler<owned_t<std::remove_const_t<Owned>...>, get_t<std::remove_const_t<Get>...>, exclude_t<std::remove_const_t<Exclude>...>>;
735
738 : descriptor{} {}
739
745 : descriptor{&ref} {}
746
752 return *storage<0>();
753 }
754
760 template<typename Type>
762 return storage<index_of<Type>>();
763 }
764
770 template<std::size_t Index>
772 constexpr auto offset = sizeof...(Owned) + sizeof...(Get);
773
774 if constexpr(Index < offset) {
775 return std::get<Index>(pools());
776 } else {
777 return std::get<Index - offset>(filter());
778 }
779 }
780
786 return *this ? descriptor->length() : size_type{};
787 }
788
794 return !*this || !descriptor->length();
795 }
796
805 return *this ? (handle().end() - descriptor->length()) : iterator{};
806 }
807
814 return *this ? handle().end() : iterator{};
815 }
816
825 return *this ? handle().rbegin() : reverse_iterator{};
826 }
827
835 return *this ? (handle().rbegin() + descriptor->length()) : reverse_iterator{};
836 }
837
844 const auto it = begin();
845 return it != end() ? *it : null;
846 }
847
854 const auto it = rbegin();
855 return it != rend() ? *it : null;
856 }
857
864 [[nodiscard]] iterator find(const entity_type entt) const noexcept {
865 const auto it = *this ? handle().find(entt) : iterator{};
866 return it >= begin() ? it : iterator{};
867 }
868
875 return begin()[pos];
876 }
877
882 [[nodiscard]] explicit operator bool() const noexcept {
883 return descriptor != nullptr;
884 }
885
891 [[nodiscard]] bool contains(const entity_type entt) const noexcept {
892 return *this && handle().contains(entt) && (handle().index(entt) < (descriptor->length()));
893 }
894
902 template<typename Type, typename... Other>
903 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
905 }
906
913 template<std::size_t... Index>
914 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
915 const auto cpools = pools();
916
917 if constexpr(sizeof...(Index) == 0) {
918 return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, cpools);
919 } else if constexpr(sizeof...(Index) == 1) {
920 return (std::get<Index>(cpools)->get(entt), ...);
921 } else {
922 return std::tuple_cat(std::get<Index>(cpools)->get_as_tuple(entt)...);
923 }
924 }
925
948 template<typename Func>
949 void each(Func func) const {
950 for(auto args: each()) {
951 if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_group>().get({})))>) {
952 std::apply(func, args);
953 } else {
954 std::apply([&func](auto, auto &&...less) { func(std::forward<decltype(less)>(less)...); }, args);
955 }
956 }
957 }
958
973 const auto cpools = pools();
974 return {{begin(), cpools}, {end(), cpools}};
975 }
976
1011 template<typename Type, typename... Other, typename Compare, typename Sort = std_sort, typename... Args>
1012 void sort(Compare compare, Sort algo = Sort{}, Args &&...args) const {
1013 sort<index_of<Type>, index_of<Other>...>(std::move(compare), std::move(algo), std::forward<Args>(args)...);
1014 }
1015
1029 template<std::size_t... Index, typename Compare, typename Sort = std_sort, typename... Args>
1030 void sort(Compare compare, Sort algo = Sort{}, Args &&...args) const {
1031 const auto cpools = pools();
1032
1033 if constexpr(sizeof...(Index) == 0) {
1034 static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
1035 storage<0>()->sort_n(descriptor->length(), std::move(compare), std::move(algo), std::forward<Args>(args)...);
1036 } else {
1037 auto comp = [&compare, &cpools](const entity_type lhs, const entity_type rhs) {
1038 if constexpr(sizeof...(Index) == 1) {
1039 return compare((std::get<Index>(cpools)->get(lhs), ...), (std::get<Index>(cpools)->get(rhs), ...));
1040 } else {
1041 return compare(std::forward_as_tuple(std::get<Index>(cpools)->get(lhs)...), std::forward_as_tuple(std::get<Index>(cpools)->get(rhs)...));
1042 }
1043 };
1044
1045 storage<0>()->sort_n(descriptor->length(), std::move(comp), std::move(algo), std::forward<Args>(args)...);
1046 }
1047
1048 auto cb = [this](auto *head, auto *...other) {
1049 for(auto next = descriptor->length(); next; --next) {
1050 const auto pos = next - 1;
1051 [[maybe_unused]] const auto entt = head->data()[pos];
1052 (other->swap_elements(other->data()[pos], entt), ...);
1053 }
1054 };
1055
1056 std::apply(cb, cpools);
1057 }
1058
1059private:
1060 handler *descriptor;
1061};
1062
1063} // namespace entt
1064
1065#endif
const common_type & handle() const noexcept
Returns the leading storage of a group.
Definition group.hpp:751
void each(Func func) const
Iterates entities and components and applies the given function object to them.
Definition group.hpp:949
decltype(auto) get(const entity_type entt) const
Returns the components assigned to the given entity.
Definition group.hpp:903
basic_group() noexcept
Default constructor to use to create empty, invalid groups.
Definition group.hpp:737
entity_type back() const noexcept
Returns the last entity of the group, if any.
Definition group.hpp:853
iterator begin() const noexcept
Returns an iterator to the first entity of the group.
Definition group.hpp:804
auto * storage() const noexcept
Returns the storage for a given component type, if any.
Definition group.hpp:761
typename common_type::iterator iterator
Random access iterator type.
Definition group.hpp:728
iterator find(const entity_type entt) const noexcept
Finds an entity.
Definition group.hpp:864
bool contains(const entity_type entt) const noexcept
Checks if a group contains an entity.
Definition group.hpp:891
entity_type front() const noexcept
Returns the first entity of the group, if any.
Definition group.hpp:843
basic_group(handler &ref) noexcept
Constructs a group from a set of storage classes.
Definition group.hpp:744
iterator end() const noexcept
Returns an iterator that is past the last entity of the group.
Definition group.hpp:813
typename common_type::reverse_iterator reverse_iterator
Reversed iterator type.
Definition group.hpp:730
entity_type operator[](const size_type pos) const
Returns the identifier that occupies the given position.
Definition group.hpp:874
size_type size() const noexcept
Returns the number of entities that that are part of the group.
Definition group.hpp:785
iterable each() const noexcept
Returns an iterable object to use to visit a group.
Definition group.hpp:972
reverse_iterator rend() const noexcept
Returns an iterator that is past the last entity of the reversed group.
Definition group.hpp:834
void sort(Compare compare, Sort algo=Sort{}, Args &&...args) const
Sort a group according to the given comparison function.
Definition group.hpp:1012
decltype(auto) get(const entity_type entt) const
Returns the components assigned to the given entity.
Definition group.hpp:914
reverse_iterator rbegin() const noexcept
Returns an iterator to the first entity of the reversed group.
Definition group.hpp:824
internal::group_handler< owned_t< std::remove_const_t< Owned >... >, get_t< std::remove_const_t< Get >... >, exclude_t< std::remove_const_t< Exclude >... > > handler
Group handler type.
Definition group.hpp:734
bool empty() const noexcept
Checks whether a group is empty.
Definition group.hpp:793
void sort(Compare compare, Sort algo=Sort{}, Args &&...args) const
Sort a group according to the given comparison function.
Definition group.hpp:1030
iterator begin() const noexcept
Returns an iterator to the first entity of the group.
Definition group.hpp:399
void sort_as(It first, It last) const
Sort entities according to their order in a range.
Definition group.hpp:653
auto * storage() const noexcept
Returns the storage for a given component type, if any.
Definition group.hpp:340
typename common_type::reverse_iterator reverse_iterator
Reversed iterator type.
Definition group.hpp:309
basic_group(handler &ref) noexcept
Constructs a group from a set of storage classes.
Definition group.hpp:323
entity_type operator[](const size_type pos) const
Returns the identifier that occupies the given position.
Definition group.hpp:468
bool contains(const entity_type entt) const noexcept
Checks if a group contains an entity.
Definition group.hpp:485
void sort(Compare compare, Sort algo=Sort{}, Args &&...args)
Sort a group according to the given comparison function.
Definition group.hpp:623
reverse_iterator rbegin() const noexcept
Returns an iterator to the first entity of the reversed group.
Definition group.hpp:419
const common_type & handle() const noexcept
Returns the leading storage of a group.
Definition group.hpp:330
void sort(Compare compare, Sort algo=Sort{}, Args &&...args)
Sort a group according to the given comparison function.
Definition group.hpp:605
decltype(auto) get(const entity_type entt) const
Returns the components assigned to the given entity.
Definition group.hpp:497
bool empty() const noexcept
Checks whether a group is empty.
Definition group.hpp:388
void sort_as(const common_type &other) const
Sort entities according to their order in a range.
Definition group.hpp:663
void each(Func func) const
Iterates entities and components and applies the given function object to them.
Definition group.hpp:543
internal::group_handler< owned_t<>, get_t< std::remove_const_t< Get >... >, exclude_t< std::remove_const_t< Exclude >... > > handler
Group handler type.
Definition group.hpp:313
decltype(auto) get(const entity_type entt) const
Returns the components assigned to the given entity.
Definition group.hpp:508
size_type capacity() const noexcept
Returns the number of elements that a group has currently allocated space for.
Definition group.hpp:373
void shrink_to_fit()
Requests the removal of unused capacity.
Definition group.hpp:378
entity_type front() const noexcept
Returns the first entity of the group, if any.
Definition group.hpp:438
reverse_iterator rend() const noexcept
Returns an iterator that is past the last entity of the reversed group.
Definition group.hpp:429
underlying_type entity_type
Underlying entity identifier.
Definition group.hpp:301
iterator find(const entity_type entt) const noexcept
Finds an entity.
Definition group.hpp:459
iterator end() const noexcept
Returns an iterator that is past the last entity of the group.
Definition group.hpp:408
typename common_type::iterator iterator
Random access iterator type.
Definition group.hpp:307
entity_type back() const noexcept
Returns the last entity of the group, if any.
Definition group.hpp:448
iterable each() const noexcept
Returns an iterable object to use to visit a group.
Definition group.hpp:566
base_type common_type
Common type among all storage types.
Definition group.hpp:305
basic_group() noexcept
Default constructor to use to create empty, invalid groups.
Definition group.hpp:316
size_type size() const noexcept
Returns the number of entities that are part of the group.
Definition group.hpp:364
Basic storage implementation.
Definition storage.hpp:229
EnTT default namespace.
Definition dense_map.hpp:21
constexpr Type make_obj_using_allocator(const Allocator &allocator, Args &&...args)
Uses-allocator construction utility (waiting for C++20).
Definition memory.hpp:258
constexpr null_t null
Compile-time constant for null entities.
Definition entity.hpp:363
basic_handle< registry > handle
Alias declaration for the most common use case.
Definition fwd.hpp:91
constexpr bool is_applicable_v
Helper variable template.
constexpr get_t< Type... > get
Variable template for lists of observed components.
Definition fwd.hpp:157
constexpr owned_t< Type... > owned
Variable template for lists of owned components.
Definition fwd.hpp:174
constexpr bool operator!=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
@ ref
Aliasing mode, the object points to a non-const element.
constexpr bool operator==(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
Alias for exclusion lists.
Definition fwd.hpp:130
Alias for lists of observed components.
Definition fwd.hpp:147
Utility class to create an iterable object from a pair of iterators.
Definition iterator.hpp:141
Alias for lists of owned components.
Definition fwd.hpp:164
Function object to wrap std::sort in a class type.
Definition algorithm.hpp:21
static constexpr id_type value() noexcept
Returns the numeric representation of a given type.
A class to use to push around lists of types, nothing more.