EnTT 3.15.0
Loading...
Searching...
No Matches
group.hpp
1#ifndef ENTT_ENTITY_GROUP_HPP
2#define ENTT_ENTITY_GROUP_HPP
3
4#include <array>
5#include <cstddef>
6#include <iterator>
7#include <tuple>
8#include <type_traits>
9#include <utility>
10#include "../config/config.h"
11#include "../core/algorithm.hpp"
12#include "../core/fwd.hpp"
13#include "../core/iterator.hpp"
14#include "../core/type_info.hpp"
15#include "../core/type_traits.hpp"
16#include "entity.hpp"
17#include "fwd.hpp"
18
19namespace entt {
20
22namespace internal {
23
24template<typename, typename, typename>
25class extended_group_iterator;
26
27template<typename It, typename... Owned, typename... Get>
28class extended_group_iterator<It, owned_t<Owned...>, get_t<Get...>> {
29 template<typename Type>
30 [[nodiscard]] auto index_to_element([[maybe_unused]] Type &cpool) const {
31 if constexpr(std::is_void_v<typename Type::value_type>) {
32 return std::make_tuple();
33 } else {
34 return std::forward_as_tuple(cpool.rbegin()[it.index()]);
35 }
36 }
37
38public:
39 using iterator_type = It;
40 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({})...));
41 using pointer = input_iterator_pointer<value_type>;
42 using reference = value_type;
43 using difference_type = std::ptrdiff_t;
44 using iterator_category = std::input_iterator_tag;
45 using iterator_concept = std::forward_iterator_tag;
46
47 constexpr extended_group_iterator()
48 : it{},
49 pools{} {}
50
51 extended_group_iterator(iterator_type from, std::tuple<Owned *..., Get *...> cpools)
52 : it{from},
53 pools{std::move(cpools)} {}
54
55 extended_group_iterator &operator++() noexcept {
56 return ++it, *this;
57 }
58
59 extended_group_iterator operator++(int) noexcept {
60 const extended_group_iterator orig = *this;
61 return ++(*this), orig;
62 }
63
64 [[nodiscard]] reference operator*() const noexcept {
65 return std::tuple_cat(std::make_tuple(*it), index_to_element(*std::get<Owned *>(pools))..., std::get<Get *>(pools)->get_as_tuple(*it)...);
66 }
67
68 [[nodiscard]] pointer operator->() const noexcept {
69 return operator*();
70 }
71
72 [[nodiscard]] constexpr iterator_type base() const noexcept {
73 return it;
74 }
75
76 template<typename... Lhs, typename... Rhs>
77 friend constexpr bool operator==(const extended_group_iterator<Lhs...> &, const extended_group_iterator<Rhs...> &) noexcept;
78
79private:
80 It it;
81 std::tuple<Owned *..., Get *...> pools;
82};
83
84template<typename... Lhs, typename... Rhs>
85[[nodiscard]] constexpr bool operator==(const extended_group_iterator<Lhs...> &lhs, const extended_group_iterator<Rhs...> &rhs) noexcept {
86 return lhs.it == rhs.it;
87}
88
89template<typename... Lhs, typename... Rhs>
90[[nodiscard]] constexpr bool operator!=(const extended_group_iterator<Lhs...> &lhs, const extended_group_iterator<Rhs...> &rhs) noexcept {
91 return !(lhs == rhs);
92}
93
94struct group_descriptor {
95 using size_type = std::size_t;
96 virtual ~group_descriptor() = default;
97 [[nodiscard]] virtual bool owned(const id_type) const noexcept {
98 return false;
99 }
100};
101
102template<typename Type, std::size_t Owned, std::size_t Get, std::size_t Exclude>
103class group_handler final: public group_descriptor {
104 using entity_type = typename Type::entity_type;
105
106 void swap_elements(const std::size_t pos, const entity_type entt) {
107 for(size_type next{}; next < Owned; ++next) {
108 pools[next]->swap_elements((*pools[next])[pos], entt);
109 }
110 }
111
112 void push_on_construct(const entity_type entt) {
113 if(std::apply([entt, pos = len](auto *cpool, auto *...other) { return cpool->contains(entt) && !(cpool->index(entt) < pos) && (other->contains(entt) && ...); }, pools)
114 && std::apply([entt](auto *...cpool) { return (!cpool->contains(entt) && ...); }, filter)) {
115 swap_elements(len++, entt);
116 }
117 }
118
119 void push_on_destroy(const entity_type entt) {
120 if(std::apply([entt, pos = len](auto *cpool, auto *...other) { return cpool->contains(entt) && !(cpool->index(entt) < pos) && (other->contains(entt) && ...); }, pools)
121 && std::apply([entt](auto *...cpool) { return (0u + ... + cpool->contains(entt)) == 1u; }, filter)) {
122 swap_elements(len++, entt);
123 }
124 }
125
126 void remove_if(const entity_type entt) {
127 if(pools[0u]->contains(entt) && (pools[0u]->index(entt) < len)) {
128 swap_elements(--len, entt);
129 }
130 }
131
132 void common_setup() {
133 // we cannot iterate backwards because we want to leave behind valid entities in case of owned types
134 for(auto first = pools[0u]->rbegin(), last = first + static_cast<typename decltype(pools)::difference_type>(pools[0u]->size()); first != last; ++first) {
135 push_on_construct(*first);
136 }
137 }
138
139public:
140 using common_type = Type;
141 using size_type = typename Type::size_type;
142
143 template<typename... OGType, typename... EType>
144 group_handler(std::tuple<OGType &...> ogpool, std::tuple<EType &...> epool)
145 : pools{std::apply([](auto &&...cpool) { return std::array<common_type *, (Owned + Get)>{&cpool...}; }, ogpool)},
146 filter{std::apply([](auto &&...cpool) { return std::array<common_type *, Exclude>{&cpool...}; }, epool)} {
147 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)), ...); }, ogpool);
148 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)), ...); }, epool);
149 common_setup();
150 }
151
152 [[nodiscard]] bool owned(const id_type hash) const noexcept override {
153 for(size_type pos{}; pos < Owned; ++pos) {
154 if(pools[pos]->type().hash() == hash) {
155 return true;
156 }
157 }
158
159 return false;
160 }
161
162 [[nodiscard]] size_type length() const noexcept {
163 return len;
164 }
165
166 template<std::size_t Index>
167 [[nodiscard]] common_type *storage() const noexcept {
168 if constexpr(Index < (Owned + Get)) {
169 return pools[Index];
170 } else {
171 return filter[Index - (Owned + Get)];
172 }
173 }
174
175private:
176 std::array<common_type *, (Owned + Get)> pools;
177 std::array<common_type *, Exclude> filter;
178 std::size_t len{};
179};
180
181template<typename Type, std::size_t Get, std::size_t Exclude>
182class group_handler<Type, 0u, Get, Exclude> final: public group_descriptor {
183 using entity_type = typename Type::entity_type;
184
185 void push_on_construct(const entity_type entt) {
186 if(!elem.contains(entt)
187 && std::apply([entt](auto *...cpool) { return (cpool->contains(entt) && ...); }, pools)
188 && std::apply([entt](auto *...cpool) { return (!cpool->contains(entt) && ...); }, filter)) {
189 elem.push(entt);
190 }
191 }
192
193 void push_on_destroy(const entity_type entt) {
194 if(!elem.contains(entt)
195 && std::apply([entt](auto *...cpool) { return (cpool->contains(entt) && ...); }, pools)
196 && std::apply([entt](auto *...cpool) { return (0u + ... + cpool->contains(entt)) == 1u; }, filter)) {
197 elem.push(entt);
198 }
199 }
200
201 void remove_if(const entity_type entt) {
202 elem.remove(entt);
203 }
204
205 void common_setup() {
206 for(const auto entity: *pools[0u]) {
207 push_on_construct(entity);
208 }
209 }
210
211public:
212 using common_type = Type;
213
214 template<typename Allocator, typename... GType, typename... EType>
215 group_handler(const Allocator &allocator, std::tuple<GType &...> gpool, std::tuple<EType &...> epool)
216 : pools{std::apply([](auto &&...cpool) { return std::array<common_type *, Get>{&cpool...}; }, gpool)},
217 filter{std::apply([](auto &&...cpool) { return std::array<common_type *, Exclude>{&cpool...}; }, epool)},
218 elem{allocator} {
219 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)), ...); }, gpool);
220 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)), ...); }, epool);
221 common_setup();
222 }
223
224 [[nodiscard]] common_type &handle() noexcept {
225 return elem;
226 }
227
228 [[nodiscard]] const common_type &handle() const noexcept {
229 return elem;
230 }
231
232 template<std::size_t Index>
233 [[nodiscard]] common_type *storage() const noexcept {
234 if constexpr(Index < Get) {
235 return pools[Index];
236 } else {
237 return filter[Index - Get];
238 }
239 }
240
241private:
242 std::array<common_type *, Get> pools;
243 std::array<common_type *, Exclude> filter;
244 common_type elem;
245};
246
247} // namespace internal
249
256template<typename, typename, typename>
257class basic_group;
258
281template<typename... Get, typename... Exclude>
282class basic_group<owned_t<>, get_t<Get...>, exclude_t<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::element_type..., typename Exclude::element_type...>>;
288
289 template<std::size_t... Index>
290 [[nodiscard]] auto pools_for(std::index_sequence<Index...>) const noexcept {
291 using return_type = std::tuple<Get *...>;
292 return descriptor ? return_type{static_cast<Get *>(descriptor->template storage<Index>())...} : return_type{};
293 }
294
295public:
297 using entity_type = underlying_type;
299 using size_type = std::size_t;
301 using difference_type = std::ptrdiff_t;
303 using common_type = base_type;
305 using iterator = typename common_type::iterator;
307 using reverse_iterator = typename common_type::reverse_iterator;
311 using handler = internal::group_handler<common_type, 0u, sizeof...(Get), sizeof...(Exclude)>;
312
320
322 basic_group() noexcept
323 : descriptor{} {}
324
330 : descriptor{&ref} {}
331
336 [[nodiscard]] const common_type &handle() const noexcept {
337 return descriptor->handle();
338 }
339
345 template<typename Type>
346 [[nodiscard]] auto *storage() const noexcept {
347 return storage<index_of<Type>>();
348 }
349
355 template<std::size_t Index>
356 [[nodiscard]] auto *storage() const noexcept {
357 using type = type_list_element_t<Index, type_list<Get..., Exclude...>>;
358 return *this ? static_cast<type *>(descriptor->template storage<Index>()) : nullptr;
359 }
360
365 [[nodiscard]] size_type size() const noexcept {
366 return *this ? handle().size() : size_type{};
367 }
368
374 [[nodiscard]] size_type capacity() const noexcept {
375 return *this ? handle().capacity() : size_type{};
376 }
377
380 if(*this) {
381 descriptor->handle().shrink_to_fit();
382 }
383 }
384
389 [[nodiscard]] bool empty() const noexcept {
390 return !*this || handle().empty();
391 }
392
400 [[nodiscard]] iterator begin() const noexcept {
401 return *this ? handle().begin() : iterator{};
402 }
403
409 [[nodiscard]] iterator end() const noexcept {
410 return *this ? handle().end() : iterator{};
411 }
412
420 [[nodiscard]] reverse_iterator rbegin() const noexcept {
421 return *this ? handle().rbegin() : reverse_iterator{};
422 }
423
430 [[nodiscard]] reverse_iterator rend() const noexcept {
431 return *this ? handle().rend() : reverse_iterator{};
432 }
433
439 [[nodiscard]] entity_type front() const noexcept {
440 const auto it = begin();
441 return it != end() ? *it : null;
442 }
443
449 [[nodiscard]] entity_type back() const noexcept {
450 const auto it = rbegin();
451 return it != rend() ? *it : null;
452 }
453
460 [[nodiscard]] iterator find(const entity_type entt) const noexcept {
461 return *this ? handle().find(entt) : iterator{};
462 }
463
469 [[nodiscard]] entity_type operator[](const size_type pos) const {
470 return begin()[static_cast<difference_type>(pos)];
471 }
472
477 [[nodiscard]] explicit operator bool() const noexcept {
478 return descriptor != nullptr;
479 }
480
486 [[nodiscard]] bool contains(const entity_type entt) const noexcept {
487 return *this && handle().contains(entt);
488 }
489
497 template<typename Type, typename... Other>
498 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
499 return get<index_of<Type>, index_of<Other>...>(entt);
500 }
501
508 template<std::size_t... Index>
509 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
510 const auto cpools = pools_for(std::index_sequence_for<Get...>{});
511
512 if constexpr(sizeof...(Index) == 0) {
513 return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, cpools);
514 } else if constexpr(sizeof...(Index) == 1) {
515 return (std::get<Index>(cpools)->get(entt), ...);
516 } else {
517 return std::tuple_cat(std::get<Index>(cpools)->get_as_tuple(entt)...);
518 }
519 }
520
543 template<typename Func>
544 void each(Func func) const {
545 for(const auto entt: *this) {
546 if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_group>().get({})))>) {
547 std::apply(func, std::tuple_cat(std::make_tuple(entt), get(entt)));
548 } else {
549 std::apply(func, get(entt));
550 }
551 }
552 }
553
567 [[nodiscard]] iterable each() const noexcept {
568 const auto cpools = pools_for(std::index_sequence_for<Get...>{});
569 return iterable{{begin(), cpools}, {end(), cpools}};
570 }
571
605 template<typename Type, typename... Other, typename Compare, typename Sort = std_sort, typename... Args>
606 void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
607 sort<index_of<Type>, index_of<Other>...>(std::move(compare), std::move(algo), std::forward<Args>(args)...);
608 }
609
623 template<std::size_t... Index, typename Compare, typename Sort = std_sort, typename... Args>
624 void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
625 if(*this) {
626 if constexpr(sizeof...(Index) == 0) {
627 static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
628 descriptor->handle().sort(std::move(compare), std::move(algo), std::forward<Args>(args)...);
629 } else {
630 auto comp = [&compare, cpools = pools_for(std::index_sequence_for<Get...>{})](const entity_type lhs, const entity_type rhs) {
631 if constexpr(sizeof...(Index) == 1) {
632 return compare((std::get<Index>(cpools)->get(lhs), ...), (std::get<Index>(cpools)->get(rhs), ...));
633 } else {
634 return compare(std::forward_as_tuple(std::get<Index>(cpools)->get(lhs)...), std::forward_as_tuple(std::get<Index>(cpools)->get(rhs)...));
635 }
636 };
637
638 descriptor->handle().sort(std::move(comp), std::move(algo), std::forward<Args>(args)...);
639 }
640 }
641 }
642
653 template<typename It>
654 void sort_as(It first, It last) const {
655 if(*this) {
656 descriptor->handle().sort_as(first, last);
657 }
658 }
659
660private:
661 handler *descriptor;
662};
663
695template<typename... Owned, typename... Get, typename... Exclude>
696class basic_group<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> {
697 static_assert(((Owned::storage_policy != deletion_policy::in_place) && ...), "Groups do not support in-place delete");
698
699 using base_type = std::common_type_t<typename Owned::base_type..., typename Get::base_type..., typename Exclude::base_type...>;
700 using underlying_type = typename base_type::entity_type;
701
702 template<typename Type>
703 static constexpr std::size_t index_of = type_list_index_v<std::remove_const_t<Type>, type_list<typename Owned::element_type..., typename Get::element_type..., typename Exclude::element_type...>>;
704
705 template<std::size_t... Index, std::size_t... Other>
706 [[nodiscard]] auto pools_for(std::index_sequence<Index...>, std::index_sequence<Other...>) const noexcept {
707 using return_type = std::tuple<Owned *..., Get *...>;
708 return descriptor ? return_type{static_cast<Owned *>(descriptor->template storage<Index>())..., static_cast<Get *>(descriptor->template storage<sizeof...(Owned) + Other>())...} : return_type{};
709 }
710
711public:
713 using entity_type = underlying_type;
715 using size_type = std::size_t;
717 using difference_type = std::ptrdiff_t;
719 using common_type = base_type;
721 using iterator = typename common_type::iterator;
723 using reverse_iterator = typename common_type::reverse_iterator;
725 using iterable = iterable_adaptor<internal::extended_group_iterator<iterator, owned_t<Owned...>, get_t<Get...>>>;
727 using handler = internal::group_handler<common_type, sizeof...(Owned), sizeof...(Get), sizeof...(Exclude)>;
728
736
738 basic_group() noexcept
739 : descriptor{} {}
740
746 : descriptor{&ref} {}
747
752 [[nodiscard]] const common_type &handle() const noexcept {
753 return *storage<0>();
754 }
755
761 template<typename Type>
762 [[nodiscard]] auto *storage() const noexcept {
763 return storage<index_of<Type>>();
764 }
765
771 template<std::size_t Index>
772 [[nodiscard]] auto *storage() const noexcept {
773 using type = type_list_element_t<Index, type_list<Owned..., Get..., Exclude...>>;
774 return *this ? static_cast<type *>(descriptor->template storage<Index>()) : nullptr;
775 }
776
781 [[nodiscard]] size_type size() const noexcept {
782 return *this ? descriptor->length() : size_type{};
783 }
784
789 [[nodiscard]] bool empty() const noexcept {
790 return !*this || !descriptor->length();
791 }
792
800 [[nodiscard]] iterator begin() const noexcept {
801 return *this ? (handle().end() - static_cast<difference_type>(descriptor->length())) : iterator{};
802 }
803
809 [[nodiscard]] iterator end() const noexcept {
810 return *this ? handle().end() : iterator{};
811 }
812
820 [[nodiscard]] reverse_iterator rbegin() const noexcept {
821 return *this ? handle().rbegin() : reverse_iterator{};
822 }
823
830 [[nodiscard]] reverse_iterator rend() const noexcept {
831 return *this ? (handle().rbegin() + static_cast<difference_type>(descriptor->length())) : reverse_iterator{};
832 }
833
839 [[nodiscard]] entity_type front() const noexcept {
840 const auto it = begin();
841 return it != end() ? *it : null;
842 }
843
849 [[nodiscard]] entity_type back() const noexcept {
850 const auto it = rbegin();
851 return it != rend() ? *it : null;
852 }
853
860 [[nodiscard]] iterator find(const entity_type entt) const noexcept {
861 const auto it = *this ? handle().find(entt) : iterator{};
862 return it >= begin() ? it : iterator{};
863 }
864
870 [[nodiscard]] entity_type operator[](const size_type pos) const {
871 return begin()[static_cast<difference_type>(pos)];
872 }
873
878 [[nodiscard]] explicit operator bool() const noexcept {
879 return descriptor != nullptr;
880 }
881
887 [[nodiscard]] bool contains(const entity_type entt) const noexcept {
888 return *this && handle().contains(entt) && (handle().index(entt) < (descriptor->length()));
889 }
890
898 template<typename Type, typename... Other>
899 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
900 return get<index_of<Type>, index_of<Other>...>(entt);
901 }
902
909 template<std::size_t... Index>
910 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
911 const auto cpools = pools_for(std::index_sequence_for<Owned...>{}, std::index_sequence_for<Get...>{});
912
913 if constexpr(sizeof...(Index) == 0) {
914 return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, cpools);
915 } else if constexpr(sizeof...(Index) == 1) {
916 return (std::get<Index>(cpools)->get(entt), ...);
917 } else {
918 return std::tuple_cat(std::get<Index>(cpools)->get_as_tuple(entt)...);
919 }
920 }
921
944 template<typename Func>
945 void each(Func func) const {
946 for(auto args: each()) {
947 if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_group>().get({})))>) {
948 std::apply(func, args);
949 } else {
950 std::apply([&func](auto, auto &&...less) { func(std::forward<decltype(less)>(less)...); }, args);
951 }
952 }
953 }
954
968 [[nodiscard]] iterable each() const noexcept {
969 const auto cpools = pools_for(std::index_sequence_for<Owned...>{}, std::index_sequence_for<Get...>{});
970 return iterable{{begin(), cpools}, {end(), cpools}};
971 }
972
1007 template<typename Type, typename... Other, typename Compare, typename Sort = std_sort, typename... Args>
1008 void sort(Compare compare, Sort algo = Sort{}, Args &&...args) const {
1009 sort<index_of<Type>, index_of<Other>...>(std::move(compare), std::move(algo), std::forward<Args>(args)...);
1010 }
1011
1025 template<std::size_t... Index, typename Compare, typename Sort = std_sort, typename... Args>
1026 void sort(Compare compare, Sort algo = Sort{}, Args &&...args) const {
1027 const auto cpools = pools_for(std::index_sequence_for<Owned...>{}, std::index_sequence_for<Get...>{});
1028
1029 if constexpr(sizeof...(Index) == 0) {
1030 static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
1031 storage<0>()->sort_n(descriptor->length(), std::move(compare), std::move(algo), std::forward<Args>(args)...);
1032 } else {
1033 auto comp = [&compare, &cpools](const entity_type lhs, const entity_type rhs) {
1034 if constexpr(sizeof...(Index) == 1) {
1035 return compare((std::get<Index>(cpools)->get(lhs), ...), (std::get<Index>(cpools)->get(rhs), ...));
1036 } else {
1037 return compare(std::forward_as_tuple(std::get<Index>(cpools)->get(lhs)...), std::forward_as_tuple(std::get<Index>(cpools)->get(rhs)...));
1038 }
1039 };
1040
1041 storage<0>()->sort_n(descriptor->length(), std::move(comp), std::move(algo), std::forward<Args>(args)...);
1042 }
1043
1044 auto cb = [this](auto *head, auto *...other) {
1045 for(auto next = descriptor->length(); next; --next) {
1046 const auto pos = next - 1;
1047 [[maybe_unused]] const auto entt = head->data()[pos];
1048 (other->swap_elements(other->data()[pos], entt), ...);
1049 }
1050 };
1051
1052 std::apply(cb, cpools);
1053 }
1054
1055private:
1056 handler *descriptor;
1057};
1058
1059} // namespace entt
1060
1061#endif
const common_type & handle() const noexcept
Returns the leading storage of a group.
Definition group.hpp:752
void each(Func func) const
Iterates entities and elements and applies the given function object to them.
Definition group.hpp:945
decltype(auto) get(const entity_type entt) const
Returns the elements assigned to the given entity.
Definition group.hpp:899
basic_group() noexcept
Default constructor to use to create empty, invalid groups.
Definition group.hpp:738
entity_type back() const noexcept
Returns the last entity of the group, if any.
Definition group.hpp:849
iterator begin() const noexcept
Returns an iterator to the first entity of the group.
Definition group.hpp:800
auto * storage() const noexcept
Returns the storage for a given element type, if any.
Definition group.hpp:762
internal::group_handler< common_type, sizeof...(Owned), sizeof...(Get), sizeof...(Exclude)> handler
Group handler type.
Definition group.hpp:727
typename common_type::iterator iterator
Random access iterator type.
Definition group.hpp:721
iterator find(const entity_type entt) const noexcept
Finds an entity.
Definition group.hpp:860
bool contains(const entity_type entt) const noexcept
Checks if a group contains an entity.
Definition group.hpp:887
entity_type front() const noexcept
Returns the first entity of the group, if any.
Definition group.hpp:839
basic_group(handler &ref) noexcept
Constructs a group from a set of storage classes.
Definition group.hpp:745
iterator end() const noexcept
Returns an iterator that is past the last entity of the group.
Definition group.hpp:809
typename common_type::reverse_iterator reverse_iterator
Reverse iterator type.
Definition group.hpp:723
entity_type operator[](const size_type pos) const
Returns the identifier that occupies the given position.
Definition group.hpp:870
size_type size() const noexcept
Returns the number of entities that that are part of the group.
Definition group.hpp:781
iterable each() const noexcept
Returns an iterable object to use to visit a group.
Definition group.hpp:968
reverse_iterator rend() const noexcept
Returns an iterator that is past the last entity of the reversed group.
Definition group.hpp:830
void sort(Compare compare, Sort algo=Sort{}, Args &&...args) const
Sort a group according to the given comparison function.
Definition group.hpp:1008
decltype(auto) get(const entity_type entt) const
Returns the elements assigned to the given entity.
Definition group.hpp:910
reverse_iterator rbegin() const noexcept
Returns an iterator to the first entity of the reversed group.
Definition group.hpp:820
bool empty() const noexcept
Checks whether a group is empty.
Definition group.hpp:789
iterable_adaptor< internal::extended_group_iterator< iterator, owned_t< Owned... >, get_t< Get... > > > iterable
Iterable group type.
Definition group.hpp:725
void sort(Compare compare, Sort algo=Sort{}, Args &&...args) const
Sort a group according to the given comparison function.
Definition group.hpp:1026
iterator begin() const noexcept
Returns an iterator to the first entity of the group.
Definition group.hpp:400
void sort_as(It first, It last) const
Sort entities according to their order in a range.
Definition group.hpp:654
static id_type group_id() noexcept
Group opaque identifier.
Definition group.hpp:317
auto * storage() const noexcept
Returns the storage for a given element type, if any.
Definition group.hpp:346
typename common_type::reverse_iterator reverse_iterator
Reverse iterator type.
Definition group.hpp:307
basic_group(handler &ref) noexcept
Constructs a group from a set of storage classes.
Definition group.hpp:329
entity_type operator[](const size_type pos) const
Returns the identifier that occupies the given position.
Definition group.hpp:469
bool contains(const entity_type entt) const noexcept
Checks if a group contains an entity.
Definition group.hpp:486
void sort(Compare compare, Sort algo=Sort{}, Args &&...args)
Sort a group according to the given comparison function.
Definition group.hpp:624
reverse_iterator rbegin() const noexcept
Returns an iterator to the first entity of the reversed group.
Definition group.hpp:420
iterable_adaptor< internal::extended_group_iterator< iterator, owned_t<>, get_t< Get... > > > iterable
Iterable group type.
Definition group.hpp:309
const common_type & handle() const noexcept
Returns the leading storage of a group.
Definition group.hpp:336
void sort(Compare compare, Sort algo=Sort{}, Args &&...args)
Sort a group according to the given comparison function.
Definition group.hpp:606
decltype(auto) get(const entity_type entt) const
Returns the elements assigned to the given entity.
Definition group.hpp:498
bool empty() const noexcept
Checks whether a group is empty.
Definition group.hpp:389
void each(Func func) const
Iterates entities and elements and applies the given function object to them.
Definition group.hpp:544
decltype(auto) get(const entity_type entt) const
Returns the elements assigned to the given entity.
Definition group.hpp:509
size_type capacity() const noexcept
Returns the number of elements that a group has currently allocated space for.
Definition group.hpp:374
void shrink_to_fit()
Requests the removal of unused capacity.
Definition group.hpp:379
entity_type front() const noexcept
Returns the first entity of the group, if any.
Definition group.hpp:439
reverse_iterator rend() const noexcept
Returns an iterator that is past the last entity of the reversed group.
Definition group.hpp:430
internal::group_handler< common_type, 0u, sizeof...(Get), sizeof...(Exclude)> handler
Group handler type.
Definition group.hpp:311
underlying_type entity_type
Underlying entity identifier.
Definition group.hpp:297
iterator find(const entity_type entt) const noexcept
Finds an entity.
Definition group.hpp:460
iterator end() const noexcept
Returns an iterator that is past the last entity of the group.
Definition group.hpp:409
typename common_type::iterator iterator
Random access iterator type.
Definition group.hpp:305
entity_type back() const noexcept
Returns the last entity of the group, if any.
Definition group.hpp:449
iterable each() const noexcept
Returns an iterable object to use to visit a group.
Definition group.hpp:567
base_type common_type
Common type among all storage types.
Definition group.hpp:303
basic_group() noexcept
Default constructor to use to create empty, invalid groups.
Definition group.hpp:322
size_type size() const noexcept
Returns the number of entities that are part of the group.
Definition group.hpp:365
EnTT default namespace.
Definition dense_map.hpp:22
constexpr null_t null
Compile-time constant for null entities.
Definition entity.hpp:375
constexpr std::size_t type_list_index_v
Helper variable template.
basic_handle< registry > handle
Alias declaration for the most common use case.
Definition fwd.hpp:101
constexpr bool is_applicable_v
Helper variable template.
std::uint32_t id_type
Alias declaration for type identifiers.
Definition fwd.hpp:29
constexpr get_t< Type... > get
Variable template for lists of observed elements.
Definition fwd.hpp:167
typename type_list_element< Index, List >::type type_list_element_t
Helper type.
@ in_place
In-place deletion policy.
Definition fwd.hpp:21
constexpr owned_t< Type... > owned
Variable template for lists of owned elements.
Definition fwd.hpp:184
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.
Definition fwd.hpp:19
constexpr bool operator==(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
basic_storage< Type > storage
Alias declaration for the most common use case.
Definition fwd.hpp:78
Alias for exclusion lists.
Definition fwd.hpp:140
Alias for lists of observed elements.
Definition fwd.hpp:157
Utility class to create an iterable object from a pair of iterators.
Definition iterator.hpp:141
Alias for lists of owned elements.
Definition fwd.hpp:174
Function object to wrap std::sort in a class type.
Definition algorithm.hpp:21
Type hash.
Definition type_info.hpp:92
A class to use to push around lists of types, nothing more.