EnTT 4.0.0
Loading...
Searching...
No Matches
group.hpp
1#ifndef ENTT_ENTITY_GROUP_HPP
2#define ENTT_ENTITY_GROUP_HPP
3
4#include "../config/config.h"
5#include "../core/algorithm.hpp"
6#include "../core/fwd.hpp"
7#include "../core/iterator.hpp"
8#include "../core/type_info.hpp"
9#include "../core/type_traits.hpp"
10#include "../stl/array.hpp"
11#include "../stl/concepts.hpp"
12#include "../stl/cstddef.hpp"
13#include "../stl/iterator.hpp"
14#include "../stl/tuple.hpp"
15#include "../stl/type_traits.hpp"
16#include "../stl/utility.hpp"
17#include "entity.hpp"
18#include "fwd.hpp"
19
20namespace entt {
21
23namespace internal {
24
25template<typename, typename, typename>
26class extended_group_iterator;
27
28template<typename It, typename... Owned, typename... Get>
29class extended_group_iterator<It, owned_t<Owned...>, get_t<Get...>> {
30 template<typename Type>
31 [[nodiscard]] auto index_to_element([[maybe_unused]] Type &cpool) const {
32 if constexpr(stl::is_void_v<typename Type::value_type>) {
33 return stl::make_tuple();
34 } else {
35 return stl::forward_as_tuple(cpool.rbegin()[it.index()]);
36 }
37 }
38
39public:
40 using iterator_type = It;
41 using value_type = decltype(stl::tuple_cat(stl::make_tuple(*stl::declval<It>()), stl::declval<Owned>().get_as_tuple({})..., stl::declval<Get>().get_as_tuple({})...));
42 using pointer = input_iterator_pointer<value_type>;
43 using reference = value_type;
44 using difference_type = stl::ptrdiff_t;
45 using iterator_category = stl::input_iterator_tag;
46 using iterator_concept = stl::forward_iterator_tag;
47
48 constexpr extended_group_iterator()
49 : it{},
50 pools{} {}
51
52 extended_group_iterator(iterator_type from, stl::tuple<Owned *..., Get *...> cpools)
53 : it{from},
54 pools{stl::move(cpools)} {}
55
56 extended_group_iterator &operator++() noexcept {
57 return ++it, *this;
58 }
59
60 extended_group_iterator operator++(int) noexcept {
61 const extended_group_iterator orig = *this;
62 return ++(*this), orig;
63 }
64
65 [[nodiscard]] reference operator*() const noexcept {
66 return stl::tuple_cat(stl::make_tuple(*it), index_to_element(*stl::get<Owned *>(pools))..., stl::get<Get *>(pools)->get_as_tuple(*it)...);
67 }
68
69 [[nodiscard]] pointer operator->() const noexcept {
70 return operator*();
71 }
72
73 [[nodiscard]] constexpr iterator_type base() const noexcept {
74 return it;
75 }
76
77 template<typename... Args>
78 [[nodiscard]] constexpr bool operator==(const extended_group_iterator<Args...> &other) const noexcept {
79 return it == other.it;
80 }
81
82private:
83 It it;
84 stl::tuple<Owned *..., Get *...> pools;
85};
86
87struct group_descriptor {
88 using size_type = stl::size_t;
89 virtual ~group_descriptor() = default;
90 [[nodiscard]] virtual bool owned(const id_type) const noexcept {
91 return false;
92 }
93};
94
95template<typename Type, stl::size_t Owned, stl::size_t Get, stl::size_t Exclude>
96class group_handler final: public group_descriptor {
97 using entity_type = Type::entity_type;
98
99 void swap_elements(const stl::size_t pos, const entity_type entt) {
100 for(size_type next{}; next < Owned; ++next) {
101 pools[next]->swap_elements((*pools[next])[pos], entt);
102 }
103 }
104
105 void push_on_construct(const entity_type entt) {
106 if(stl::apply([entt, pos = len](auto *cpool, auto *...other) { return cpool->contains(entt) && !(cpool->index(entt) < pos) && (other->contains(entt) && ...); }, pools)
107 && stl::apply([entt](auto *...cpool) { return (!cpool->contains(entt) && ...); }, filter)) {
108 swap_elements(len++, entt);
109 }
110 }
111
112 void push_on_destroy(const entity_type entt) {
113 if(stl::apply([entt, pos = len](auto *cpool, auto *...other) { return cpool->contains(entt) && !(cpool->index(entt) < pos) && (other->contains(entt) && ...); }, pools)
114 && stl::apply([entt](auto *...cpool) { return (0u + ... + cpool->contains(entt)) == 1u; }, filter)) {
115 swap_elements(len++, entt);
116 }
117 }
118
119 void remove_if(const entity_type entt) {
120 if(pools[0u]->contains(entt) && (pools[0u]->index(entt) < len)) {
121 swap_elements(--len, entt);
122 }
123 }
124
125 void common_setup() {
126 // we cannot iterate backwards because we want to leave behind valid entities in case of owned types
127 for(auto first = pools[0u]->rbegin(), last = first + static_cast<decltype(pools)::difference_type>(pools[0u]->size()); first != last; ++first) {
128 push_on_construct(*first);
129 }
130 }
131
132public:
133 using common_type = Type;
134 using size_type = Type::size_type;
135
136 template<typename... OGType, typename... EType>
137 group_handler(stl::tuple<OGType &...> ogpool, stl::tuple<EType &...> epool)
138 : pools{stl::apply([](auto &&...cpool) { return stl::array<common_type *, (Owned + Get)>{&cpool...}; }, ogpool)},
139 filter{stl::apply([](auto &&...cpool) { return stl::array<common_type *, Exclude>{&cpool...}; }, epool)} {
140 stl::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)), ...); }, ogpool);
141 stl::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)), ...); }, epool);
142 common_setup();
143 }
144
145 [[nodiscard]] bool owned(const id_type hash) const noexcept override {
146 for(size_type pos{}; pos < Owned; ++pos) {
147 if(pools[pos]->info().hash() == hash) {
148 return true;
149 }
150 }
151
152 return false;
153 }
154
155 [[nodiscard]] size_type length() const noexcept {
156 return len;
157 }
158
159 template<stl::size_t Index>
160 [[nodiscard]] common_type *storage() const noexcept {
161 if constexpr(Index < (Owned + Get)) {
162 return pools[Index];
163 } else {
164 return filter[Index - (Owned + Get)];
165 }
166 }
167
168private:
169 stl::array<common_type *, (Owned + Get)> pools;
170 stl::array<common_type *, Exclude> filter;
171 stl::size_t len{};
172};
173
174template<typename Type, stl::size_t Get, stl::size_t Exclude>
175class group_handler<Type, 0u, Get, Exclude> final: public group_descriptor {
176 using entity_type = Type::entity_type;
177
178 void push_on_construct(const entity_type entt) {
179 if(!elem.contains(entt)
180 && stl::apply([entt](auto *...cpool) { return (cpool->contains(entt) && ...); }, pools)
181 && stl::apply([entt](auto *...cpool) { return (!cpool->contains(entt) && ...); }, filter)) {
182 elem.push(entt);
183 }
184 }
185
186 void push_on_destroy(const entity_type entt) {
187 if(!elem.contains(entt)
188 && stl::apply([entt](auto *...cpool) { return (cpool->contains(entt) && ...); }, pools)
189 && stl::apply([entt](auto *...cpool) { return (0u + ... + cpool->contains(entt)) == 1u; }, filter)) {
190 elem.push(entt);
191 }
192 }
193
194 void remove_if(const entity_type entt) {
195 elem.remove(entt);
196 }
197
198 void common_setup() {
199 for(const auto entity: *pools[0u]) {
200 push_on_construct(entity);
201 }
202 }
203
204public:
205 using common_type = Type;
206
207 template<typename Allocator, typename... GType, typename... EType>
208 group_handler(const Allocator &allocator, stl::tuple<GType &...> gpool, stl::tuple<EType &...> epool)
209 : pools{stl::apply([](auto &&...cpool) { return stl::array<common_type *, Get>{&cpool...}; }, gpool)},
210 filter{stl::apply([](auto &&...cpool) { return stl::array<common_type *, Exclude>{&cpool...}; }, epool)},
211 elem{allocator} {
212 stl::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)), ...); }, gpool);
213 stl::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)), ...); }, epool);
214 common_setup();
215 }
216
217 [[nodiscard]] common_type &handle() noexcept {
218 return elem;
219 }
220
221 [[nodiscard]] const common_type &handle() const noexcept {
222 return elem;
223 }
224
225 template<stl::size_t Index>
226 [[nodiscard]] common_type *storage() const noexcept {
227 if constexpr(Index < Get) {
228 return pools[Index];
229 } else {
230 return filter[Index - Get];
231 }
232 }
233
234private:
235 stl::array<common_type *, Get> pools;
236 stl::array<common_type *, Exclude> filter;
237 common_type elem;
238};
239
240} // namespace internal
242
249template<typename, typename, typename>
250class basic_group;
251
274template<typename... Get, typename... Exclude>
275class basic_group<owned_t<>, get_t<Get...>, exclude_t<Exclude...>> {
276 using base_type = stl::common_type_t<typename Get::base_type..., typename Exclude::base_type...>;
277 using underlying_type = base_type::entity_type;
278
279 template<typename Type>
280 static constexpr stl::size_t index_of = type_list_index_v<stl::remove_const_t<Type>, type_list<typename Get::element_type..., typename Exclude::element_type...>>;
281
282 template<stl::size_t... Index>
283 [[nodiscard]] auto pools_for(stl::index_sequence<Index...>) const noexcept {
284 using return_type = stl::tuple<Get *...>;
285 return descriptor ? return_type{static_cast<Get *>(descriptor->template storage<Index>())...} : return_type{};
286 }
287
288public:
290 using entity_type = underlying_type;
292 using size_type = stl::size_t;
294 using difference_type = stl::ptrdiff_t;
296 using common_type = base_type;
298 using iterator = common_type::iterator;
300 using reverse_iterator = common_type::reverse_iterator;
304 using handler = internal::group_handler<common_type, 0u, sizeof...(Get), sizeof...(Exclude)>;
305
313
315 basic_group() noexcept
316 : descriptor{} {}
317
323 : descriptor{&ref} {}
324
329 [[nodiscard]] const common_type &handle() const noexcept {
330 return descriptor->handle();
331 }
332
338 template<typename Type>
339 [[nodiscard]] auto *storage() const noexcept {
340 return storage<index_of<Type>>();
341 }
342
348 template<stl::size_t Index>
349 [[nodiscard]] auto *storage() const noexcept {
350 using type = type_list_element_t<Index, type_list<Get..., Exclude...>>;
351 return *this ? static_cast<type *>(descriptor->template storage<Index>()) : nullptr;
352 }
353
358 [[nodiscard]] size_type size() const noexcept {
359 return *this ? handle().size() : size_type{};
360 }
361
367 [[nodiscard]] size_type capacity() const noexcept {
368 return *this ? handle().capacity() : size_type{};
369 }
370
373 if(*this) {
374 descriptor->handle().shrink_to_fit();
375 }
376 }
377
382 [[nodiscard]] bool empty() const noexcept {
383 return !*this || handle().empty();
384 }
385
393 [[nodiscard]] iterator begin() const noexcept {
394 return *this ? handle().begin() : iterator{};
395 }
396
402 [[nodiscard]] iterator end() const noexcept {
403 return *this ? handle().end() : iterator{};
404 }
405
413 [[nodiscard]] reverse_iterator rbegin() const noexcept {
414 return *this ? handle().rbegin() : reverse_iterator{};
415 }
416
423 [[nodiscard]] reverse_iterator rend() const noexcept {
424 return *this ? handle().rend() : reverse_iterator{};
425 }
426
432 [[nodiscard]] entity_type front() const noexcept {
433 const auto it = begin();
434 return it != end() ? *it : null;
435 }
436
442 [[nodiscard]] entity_type back() const noexcept {
443 const auto it = rbegin();
444 return it != rend() ? *it : null;
445 }
446
453 [[nodiscard]] iterator find(const entity_type entt) const noexcept {
454 return *this ? handle().find(entt) : iterator{};
455 }
456
462 [[nodiscard]] entity_type operator[](const size_type pos) const {
463 return begin()[static_cast<difference_type>(pos)];
464 }
465
470 [[nodiscard]] explicit operator bool() const noexcept {
471 return descriptor != nullptr;
472 }
473
479 [[nodiscard]] bool contains(const entity_type entt) const noexcept {
480 return *this && handle().contains(entt);
481 }
482
490 template<typename Type, typename... Other>
491 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
492 return get<index_of<Type>, index_of<Other>...>(entt);
493 }
494
501 template<stl::size_t... Index>
502 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
503 const auto cpools = pools_for(stl::index_sequence_for<Get...>{});
504
505 if constexpr(sizeof...(Index) == 0) {
506 return stl::apply([entt](auto *...curr) { return stl::tuple_cat(curr->get_as_tuple(entt)...); }, cpools);
507 } else if constexpr(sizeof...(Index) == 1) {
508 return (stl::get<Index>(cpools)->get(entt), ...);
509 } else {
510 return stl::tuple_cat(stl::get<Index>(cpools)->get_as_tuple(entt)...);
511 }
512 }
513
536 template<typename Func>
537 void each(Func func) const {
538 for(const auto entt: *this) {
539 if constexpr(is_applicable_v<Func, decltype(stl::tuple_cat(stl::tuple<entity_type>{}, stl::declval<basic_group>().get({})))>) {
540 stl::apply(func, stl::tuple_cat(stl::make_tuple(entt), get(entt)));
541 } else {
542 stl::apply(func, get(entt));
543 }
544 }
545 }
546
560 [[nodiscard]] iterable each() const noexcept {
561 const auto cpools = pools_for(stl::index_sequence_for<Get...>{});
562 return iterable{{begin(), cpools}, {end(), cpools}};
563 }
564
598 template<typename Type, typename... Other, typename Compare, typename Sort = std_sort, typename... Args>
599 void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
600 sort<index_of<Type>, index_of<Other>...>(stl::move(compare), stl::move(algo), stl::forward<Args>(args)...);
601 }
602
616 template<stl::size_t... Index, typename Compare, typename Sort = std_sort, typename... Args>
617 void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
618 if(*this) {
619 if constexpr(sizeof...(Index) == 0) {
620 static_assert(stl::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
621 descriptor->handle().sort(stl::move(compare), stl::move(algo), stl::forward<Args>(args)...);
622 } else {
623 auto comp = [&compare, cpools = pools_for(stl::index_sequence_for<Get...>{})](const entity_type lhs, const entity_type rhs) {
624 if constexpr(sizeof...(Index) == 1) {
625 return compare((stl::get<Index>(cpools)->get(lhs), ...), (stl::get<Index>(cpools)->get(rhs), ...));
626 } else {
627 return compare(stl::forward_as_tuple(stl::get<Index>(cpools)->get(lhs)...), stl::forward_as_tuple(stl::get<Index>(cpools)->get(rhs)...));
628 }
629 };
630
631 descriptor->handle().sort(stl::move(comp), stl::move(algo), stl::forward<Args>(args)...);
632 }
633 }
634 }
635
645 void sort_as(stl::input_iterator auto first, stl::input_iterator auto last) const {
646 if(*this) {
647 descriptor->handle().sort_as(first, last);
648 }
649 }
650
651private:
652 handler *descriptor;
653};
654
686template<typename... Owned, typename... Get, typename... Exclude>
687class basic_group<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> {
688 static_assert(((Owned::storage_policy != deletion_policy::in_place) && ...), "Groups do not support in-place delete");
689
690 using base_type = stl::common_type_t<typename Owned::base_type..., typename Get::base_type..., typename Exclude::base_type...>;
691 using underlying_type = base_type::entity_type;
692
693 template<typename Type>
694 static constexpr stl::size_t index_of = type_list_index_v<stl::remove_const_t<Type>, type_list<typename Owned::element_type..., typename Get::element_type..., typename Exclude::element_type...>>;
695
696 template<stl::size_t... Index, stl::size_t... Other>
697 [[nodiscard]] auto pools_for(stl::index_sequence<Index...>, stl::index_sequence<Other...>) const noexcept {
698 using return_type = stl::tuple<Owned *..., Get *...>;
699 return descriptor ? return_type{static_cast<Owned *>(descriptor->template storage<Index>())..., static_cast<Get *>(descriptor->template storage<sizeof...(Owned) + Other>())...} : return_type{};
700 }
701
702public:
704 using entity_type = underlying_type;
706 using size_type = stl::size_t;
708 using difference_type = stl::ptrdiff_t;
710 using common_type = base_type;
712 using iterator = common_type::iterator;
714 using reverse_iterator = common_type::reverse_iterator;
716 using iterable = iterable_adaptor<internal::extended_group_iterator<iterator, owned_t<Owned...>, get_t<Get...>>>;
718 using handler = internal::group_handler<common_type, sizeof...(Owned), sizeof...(Get), sizeof...(Exclude)>;
719
727
729 basic_group() noexcept
730 : descriptor{} {}
731
737 : descriptor{&ref} {}
738
743 [[nodiscard]] const common_type &handle() const noexcept {
744 return *storage<0>();
745 }
746
752 template<typename Type>
753 [[nodiscard]] auto *storage() const noexcept {
754 return storage<index_of<Type>>();
755 }
756
762 template<stl::size_t Index>
763 [[nodiscard]] auto *storage() const noexcept {
764 using type = type_list_element_t<Index, type_list<Owned..., Get..., Exclude...>>;
765 return *this ? static_cast<type *>(descriptor->template storage<Index>()) : nullptr;
766 }
767
772 [[nodiscard]] size_type size() const noexcept {
773 return *this ? descriptor->length() : size_type{};
774 }
775
780 [[nodiscard]] bool empty() const noexcept {
781 return !*this || !descriptor->length();
782 }
783
791 [[nodiscard]] iterator begin() const noexcept {
792 return *this ? (handle().end() - static_cast<difference_type>(descriptor->length())) : iterator{};
793 }
794
800 [[nodiscard]] iterator end() const noexcept {
801 return *this ? handle().end() : iterator{};
802 }
803
811 [[nodiscard]] reverse_iterator rbegin() const noexcept {
812 return *this ? handle().rbegin() : reverse_iterator{};
813 }
814
821 [[nodiscard]] reverse_iterator rend() const noexcept {
822 return *this ? (handle().rbegin() + static_cast<difference_type>(descriptor->length())) : reverse_iterator{};
823 }
824
830 [[nodiscard]] entity_type front() const noexcept {
831 const auto it = begin();
832 return it != end() ? *it : null;
833 }
834
840 [[nodiscard]] entity_type back() const noexcept {
841 const auto it = rbegin();
842 return it != rend() ? *it : null;
843 }
844
851 [[nodiscard]] iterator find(const entity_type entt) const noexcept {
852 const auto it = *this ? handle().find(entt) : iterator{};
853 return it >= begin() ? it : iterator{};
854 }
855
861 [[nodiscard]] entity_type operator[](const size_type pos) const {
862 return begin()[static_cast<difference_type>(pos)];
863 }
864
869 [[nodiscard]] explicit operator bool() const noexcept {
870 return descriptor != nullptr;
871 }
872
878 [[nodiscard]] bool contains(const entity_type entt) const noexcept {
879 return *this && handle().contains(entt) && (handle().index(entt) < (descriptor->length()));
880 }
881
889 template<typename Type, typename... Other>
890 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
891 return get<index_of<Type>, index_of<Other>...>(entt);
892 }
893
900 template<stl::size_t... Index>
901 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
902 const auto cpools = pools_for(stl::index_sequence_for<Owned...>{}, stl::index_sequence_for<Get...>{});
903
904 if constexpr(sizeof...(Index) == 0) {
905 return stl::apply([entt](auto *...curr) { return stl::tuple_cat(curr->get_as_tuple(entt)...); }, cpools);
906 } else if constexpr(sizeof...(Index) == 1) {
907 return (stl::get<Index>(cpools)->get(entt), ...);
908 } else {
909 return stl::tuple_cat(stl::get<Index>(cpools)->get_as_tuple(entt)...);
910 }
911 }
912
935 template<typename Func>
936 void each(Func func) const {
937 for(auto args: each()) {
938 if constexpr(is_applicable_v<Func, decltype(stl::tuple_cat(stl::tuple<entity_type>{}, stl::declval<basic_group>().get({})))>) {
939 stl::apply(func, args);
940 } else {
941 stl::apply([&func](auto, auto &&...less) { func(stl::forward<decltype(less)>(less)...); }, args);
942 }
943 }
944 }
945
959 [[nodiscard]] iterable each() const noexcept {
960 const auto cpools = pools_for(stl::index_sequence_for<Owned...>{}, stl::index_sequence_for<Get...>{});
961 return iterable{{begin(), cpools}, {end(), cpools}};
962 }
963
998 template<typename Type, typename... Other, typename Compare, typename Sort = std_sort, typename... Args>
999 void sort(Compare compare, Sort algo = Sort{}, Args &&...args) const {
1000 sort<index_of<Type>, index_of<Other>...>(stl::move(compare), stl::move(algo), stl::forward<Args>(args)...);
1001 }
1002
1016 template<stl::size_t... Index, typename Compare, typename Sort = std_sort, typename... Args>
1017 void sort(Compare compare, Sort algo = Sort{}, Args &&...args) const {
1018 const auto cpools = pools_for(stl::index_sequence_for<Owned...>{}, stl::index_sequence_for<Get...>{});
1019
1020 if constexpr(sizeof...(Index) == 0) {
1021 static_assert(stl::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
1022 storage<0>()->sort_n(descriptor->length(), stl::move(compare), stl::move(algo), stl::forward<Args>(args)...);
1023 } else {
1024 auto comp = [&compare, &cpools](const entity_type lhs, const entity_type rhs) {
1025 if constexpr(sizeof...(Index) == 1) {
1026 return compare((stl::get<Index>(cpools)->get(lhs), ...), (stl::get<Index>(cpools)->get(rhs), ...));
1027 } else {
1028 return compare(stl::forward_as_tuple(stl::get<Index>(cpools)->get(lhs)...), stl::forward_as_tuple(stl::get<Index>(cpools)->get(rhs)...));
1029 }
1030 };
1031
1032 storage<0>()->sort_n(descriptor->length(), stl::move(comp), stl::move(algo), stl::forward<Args>(args)...);
1033 }
1034
1035 auto cb = [this](auto *head, auto *...other) {
1036 for(auto next = descriptor->length(); next; --next) {
1037 const auto pos = next - 1;
1038 [[maybe_unused]] const auto entt = head->data()[pos];
1039 (other->swap_elements(other->data()[pos], entt), ...);
1040 }
1041 };
1042
1043 stl::apply(cb, cpools);
1044 }
1045
1046private:
1047 handler *descriptor;
1048};
1049
1050} // namespace entt
1051
1052#endif
const common_type & handle() const noexcept
Returns the leading storage of a group.
Definition group.hpp:743
void each(Func func) const
Iterates entities and elements and applies the given function object to them.
Definition group.hpp:936
decltype(auto) get(const entity_type entt) const
Returns the elements assigned to the given entity.
Definition group.hpp:890
basic_group() noexcept
Default constructor to use to create empty, invalid groups.
Definition group.hpp:729
entity_type back() const noexcept
Returns the last entity of the group, if any.
Definition group.hpp:840
iterator begin() const noexcept
Returns an iterator to the first entity of the group.
Definition group.hpp:791
auto * storage() const noexcept
Returns the storage for a given element type, if any.
Definition group.hpp:753
internal::group_handler< common_type, sizeof...(Owned), sizeof...(Get), sizeof...(Exclude)> handler
Group handler type.
Definition group.hpp:718
iterator find(const entity_type entt) const noexcept
Finds an entity.
Definition group.hpp:851
bool contains(const entity_type entt) const noexcept
Checks if a group contains an entity.
Definition group.hpp:878
common_type::reverse_iterator reverse_iterator
Reverse iterator type.
Definition group.hpp:714
entity_type front() const noexcept
Returns the first entity of the group, if any.
Definition group.hpp:830
basic_group(handler &ref) noexcept
Constructs a group from a set of storage classes.
Definition group.hpp:736
iterator end() const noexcept
Returns an iterator that is past the last entity of the group.
Definition group.hpp:800
entity_type operator[](const size_type pos) const
Returns the identifier that occupies the given position.
Definition group.hpp:861
size_type size() const noexcept
Returns the number of entities that that are part of the group.
Definition group.hpp:772
iterable each() const noexcept
Returns an iterable object to use to visit a group.
Definition group.hpp:959
reverse_iterator rend() const noexcept
Returns an iterator that is past the last entity of the reversed group.
Definition group.hpp:821
void sort(Compare compare, Sort algo=Sort{}, Args &&...args) const
Sort a group according to the given comparison function.
Definition group.hpp:999
decltype(auto) get(const entity_type entt) const
Returns the elements assigned to the given entity.
Definition group.hpp:901
reverse_iterator rbegin() const noexcept
Returns an iterator to the first entity of the reversed group.
Definition group.hpp:811
bool empty() const noexcept
Checks whether a group is empty.
Definition group.hpp:780
iterable_adaptor< internal::extended_group_iterator< iterator, owned_t< Owned... >, get_t< Get... > > > iterable
Iterable group type.
Definition group.hpp:716
void sort(Compare compare, Sort algo=Sort{}, Args &&...args) const
Sort a group according to the given comparison function.
Definition group.hpp:1017
iterator begin() const noexcept
Returns an iterator to the first entity of the group.
Definition group.hpp:393
static id_type group_id() noexcept
Group opaque identifier.
Definition group.hpp:310
auto * storage() const noexcept
Returns the storage for a given element type, if any.
Definition group.hpp:339
basic_group(handler &ref) noexcept
Constructs a group from a set of storage classes.
Definition group.hpp:322
entity_type operator[](const size_type pos) const
Returns the identifier that occupies the given position.
Definition group.hpp:462
bool contains(const entity_type entt) const noexcept
Checks if a group contains an entity.
Definition group.hpp:479
void sort(Compare compare, Sort algo=Sort{}, Args &&...args)
Sort a group according to the given comparison function.
Definition group.hpp:617
reverse_iterator rbegin() const noexcept
Returns an iterator to the first entity of the reversed group.
Definition group.hpp:413
iterable_adaptor< internal::extended_group_iterator< iterator, owned_t<>, get_t< Get... > > > iterable
Iterable group type.
Definition group.hpp:302
const common_type & handle() const noexcept
Returns the leading storage of a group.
Definition group.hpp:329
void sort(Compare compare, Sort algo=Sort{}, Args &&...args)
Sort a group according to the given comparison function.
Definition group.hpp:599
decltype(auto) get(const entity_type entt) const
Returns the elements assigned to the given entity.
Definition group.hpp:491
common_type::iterator iterator
Random access iterator type.
Definition group.hpp:298
bool empty() const noexcept
Checks whether a group is empty.
Definition group.hpp:382
void each(Func func) const
Iterates entities and elements and applies the given function object to them.
Definition group.hpp:537
common_type::reverse_iterator reverse_iterator
Reverse iterator type.
Definition group.hpp:300
decltype(auto) get(const entity_type entt) const
Returns the elements assigned to the given entity.
Definition group.hpp:502
size_type capacity() const noexcept
Returns the number of elements that a group has currently allocated space for.
Definition group.hpp:367
void shrink_to_fit()
Requests the removal of unused capacity.
Definition group.hpp:372
entity_type front() const noexcept
Returns the first entity of the group, if any.
Definition group.hpp:432
reverse_iterator rend() const noexcept
Returns an iterator that is past the last entity of the reversed group.
Definition group.hpp:423
internal::group_handler< common_type, 0u, sizeof...(Get), sizeof...(Exclude)> handler
Group handler type.
Definition group.hpp:304
underlying_type entity_type
Underlying entity identifier.
Definition group.hpp:290
iterator find(const entity_type entt) const noexcept
Finds an entity.
Definition group.hpp:453
iterator end() const noexcept
Returns an iterator that is past the last entity of the group.
Definition group.hpp:402
entity_type back() const noexcept
Returns the last entity of the group, if any.
Definition group.hpp:442
void sort_as(stl::input_iterator auto first, stl::input_iterator auto last) const
Sort entities according to their order in a range.
Definition group.hpp:645
iterable each() const noexcept
Returns an iterable object to use to visit a group.
Definition group.hpp:560
base_type common_type
Common type among all storage types.
Definition group.hpp:296
basic_group() noexcept
Default constructor to use to create empty, invalid groups.
Definition group.hpp:315
size_type size() const noexcept
Returns the number of entities that are part of the group.
Definition group.hpp:358
EnTT default namespace.
Definition dense_map.hpp:25
@ in_place
In-place deletion policy.
Definition fwd.hpp:22
type_list_element< Index, List >::type type_list_element_t
Helper type.
constexpr null_t null
Compile-time constant for null entities.
Definition entity.hpp:299
basic_handle< registry > handle
Alias declaration for the most common use case.
Definition fwd.hpp:102
constexpr bool is_applicable_v
Helper variable template.
constexpr stl::size_t type_list_index_v
Helper variable template.
constexpr get_t< Type... > get
Variable template for lists of observed elements.
Definition fwd.hpp:168
constexpr owned_t< Type... > owned
Variable template for lists of owned elements.
Definition fwd.hpp:185
@ ref
Aliasing mode, non-const reference.
Definition fwd.hpp:19
stl::uint32_t id_type
Alias declaration for type identifiers.
Definition fwd.hpp:29
basic_storage< Type > storage
Alias declaration for the most common use case.
Definition fwd.hpp:79
Alias for exclusion lists.
Definition fwd.hpp:141
Alias for lists of observed elements.
Definition fwd.hpp:158
Utility class to create an iterable object from a pair of iterators.
Definition iterator.hpp:125
Alias for lists of owned elements.
Definition fwd.hpp:175
Function object to wrap stl::sort in a class type.
Definition algorithm.hpp:22
A class to use to push around lists of types, nothing more.