EnTT 3.14.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 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 + 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]) {
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
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 common_type = base_type;
303 using iterator = typename common_type::iterator;
305 using reverse_iterator = typename common_type::reverse_iterator;
309 using handler = internal::group_handler<common_type, 0u, sizeof...(Get), sizeof...(Exclude)>;
310
318
320 basic_group() noexcept
321 : descriptor{} {}
322
327 basic_group(handler &ref) noexcept
328 : descriptor{&ref} {}
329
334 [[nodiscard]] const common_type &handle() const noexcept {
335 return descriptor->handle();
336 }
337
343 template<typename Type>
344 [[nodiscard]] auto *storage() const noexcept {
345 return storage<index_of<Type>>();
346 }
347
353 template<std::size_t Index>
354 [[nodiscard]] auto *storage() const noexcept {
355 using type = type_list_element_t<Index, type_list<Get..., Exclude...>>;
356 return *this ? static_cast<type *>(descriptor->template storage<Index>()) : nullptr;
357 }
358
363 [[nodiscard]] size_type size() const noexcept {
364 return *this ? handle().size() : size_type{};
365 }
366
372 [[nodiscard]] size_type capacity() const noexcept {
373 return *this ? handle().capacity() : size_type{};
374 }
375
378 if(*this) {
379 descriptor->handle().shrink_to_fit();
380 }
381 }
382
387 [[nodiscard]] bool empty() const noexcept {
388 return !*this || handle().empty();
389 }
390
398 [[nodiscard]] iterator begin() const noexcept {
399 return *this ? handle().begin() : iterator{};
400 }
401
407 [[nodiscard]] iterator end() const noexcept {
408 return *this ? handle().end() : iterator{};
409 }
410
418 [[nodiscard]] reverse_iterator rbegin() const noexcept {
419 return *this ? handle().rbegin() : reverse_iterator{};
420 }
421
428 [[nodiscard]] reverse_iterator rend() const noexcept {
429 return *this ? handle().rend() : reverse_iterator{};
430 }
431
437 [[nodiscard]] entity_type front() const noexcept {
438 const auto it = begin();
439 return it != end() ? *it : null;
440 }
441
447 [[nodiscard]] entity_type back() const noexcept {
448 const auto it = rbegin();
449 return it != rend() ? *it : null;
450 }
451
458 [[nodiscard]] iterator find(const entity_type entt) const noexcept {
459 return *this ? handle().find(entt) : iterator{};
460 }
461
467 [[nodiscard]] entity_type operator[](const size_type pos) const {
468 return begin()[pos];
469 }
470
475 [[nodiscard]] explicit operator bool() const noexcept {
476 return descriptor != nullptr;
477 }
478
484 [[nodiscard]] bool contains(const entity_type entt) const noexcept {
485 return *this && handle().contains(entt);
486 }
487
495 template<typename Type, typename... Other>
496 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
497 return get<index_of<Type>, index_of<Other>...>(entt);
498 }
499
506 template<std::size_t... Index>
507 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
508 const auto cpools = pools_for(std::index_sequence_for<Get...>{});
509
510 if constexpr(sizeof...(Index) == 0) {
511 return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, cpools);
512 } else if constexpr(sizeof...(Index) == 1) {
513 return (std::get<Index>(cpools)->get(entt), ...);
514 } else {
515 return std::tuple_cat(std::get<Index>(cpools)->get_as_tuple(entt)...);
516 }
517 }
518
541 template<typename Func>
542 void each(Func func) const {
543 for(const auto entt: *this) {
544 if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_group>().get({})))>) {
545 std::apply(func, std::tuple_cat(std::make_tuple(entt), get(entt)));
546 } else {
547 std::apply(func, get(entt));
548 }
549 }
550 }
551
565 [[nodiscard]] iterable each() const noexcept {
566 const auto cpools = pools_for(std::index_sequence_for<Get...>{});
567 return iterable{{begin(), cpools}, {end(), cpools}};
568 }
569
603 template<typename Type, typename... Other, typename Compare, typename Sort = std_sort, typename... Args>
604 void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
605 sort<index_of<Type>, index_of<Other>...>(std::move(compare), std::move(algo), std::forward<Args>(args)...);
606 }
607
621 template<std::size_t... Index, typename Compare, typename Sort = std_sort, typename... Args>
622 void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
623 if(*this) {
624 if constexpr(sizeof...(Index) == 0) {
625 static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
626 descriptor->handle().sort(std::move(compare), std::move(algo), std::forward<Args>(args)...);
627 } else {
628 auto comp = [&compare, cpools = pools_for(std::index_sequence_for<Get...>{})](const entity_type lhs, const entity_type rhs) {
629 if constexpr(sizeof...(Index) == 1) {
630 return compare((std::get<Index>(cpools)->get(lhs), ...), (std::get<Index>(cpools)->get(rhs), ...));
631 } else {
632 return compare(std::forward_as_tuple(std::get<Index>(cpools)->get(lhs)...), std::forward_as_tuple(std::get<Index>(cpools)->get(rhs)...));
633 }
634 };
635
636 descriptor->handle().sort(std::move(comp), std::move(algo), std::forward<Args>(args)...);
637 }
638 }
639 }
640
651 template<typename It>
652 void sort_as(It first, It last) const {
653 if(*this) {
654 descriptor->handle().sort_as(first, last);
655 }
656 }
657
658private:
659 handler *descriptor;
660};
661
693template<typename... Owned, typename... Get, typename... Exclude>
694class basic_group<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> {
695 static_assert(((Owned::storage_policy != deletion_policy::in_place) && ...), "Groups do not support in-place delete");
696
697 using base_type = std::common_type_t<typename Owned::base_type..., typename Get::base_type..., typename Exclude::base_type...>;
698 using underlying_type = typename base_type::entity_type;
699
700 template<typename Type>
701 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...>>;
702
703 template<std::size_t... Index, std::size_t... Other>
704 [[nodiscard]] auto pools_for(std::index_sequence<Index...>, std::index_sequence<Other...>) const noexcept {
705 using return_type = std::tuple<Owned *..., Get *...>;
706 return descriptor ? return_type{static_cast<Owned *>(descriptor->template storage<Index>())..., static_cast<Get *>(descriptor->template storage<sizeof...(Owned) + Other>())...} : return_type{};
707 }
708
709public:
711 using entity_type = underlying_type;
713 using size_type = std::size_t;
715 using common_type = base_type;
717 using iterator = typename common_type::iterator;
719 using reverse_iterator = typename common_type::reverse_iterator;
721 using iterable = iterable_adaptor<internal::extended_group_iterator<iterator, owned_t<Owned...>, get_t<Get...>>>;
723 using handler = internal::group_handler<common_type, sizeof...(Owned), sizeof...(Get), sizeof...(Exclude)>;
724
732
734 basic_group() noexcept
735 : descriptor{} {}
736
741 basic_group(handler &ref) noexcept
742 : descriptor{&ref} {}
743
748 [[nodiscard]] const common_type &handle() const noexcept {
749 return *storage<0>();
750 }
751
757 template<typename Type>
758 [[nodiscard]] auto *storage() const noexcept {
759 return storage<index_of<Type>>();
760 }
761
767 template<std::size_t Index>
768 [[nodiscard]] auto *storage() const noexcept {
769 using type = type_list_element_t<Index, type_list<Owned..., Get..., Exclude...>>;
770 return *this ? static_cast<type *>(descriptor->template storage<Index>()) : nullptr;
771 }
772
777 [[nodiscard]] size_type size() const noexcept {
778 return *this ? descriptor->length() : size_type{};
779 }
780
785 [[nodiscard]] bool empty() const noexcept {
786 return !*this || !descriptor->length();
787 }
788
796 [[nodiscard]] iterator begin() const noexcept {
797 return *this ? (handle().end() - descriptor->length()) : iterator{};
798 }
799
805 [[nodiscard]] iterator end() const noexcept {
806 return *this ? handle().end() : iterator{};
807 }
808
816 [[nodiscard]] reverse_iterator rbegin() const noexcept {
817 return *this ? handle().rbegin() : reverse_iterator{};
818 }
819
826 [[nodiscard]] reverse_iterator rend() const noexcept {
827 return *this ? (handle().rbegin() + descriptor->length()) : reverse_iterator{};
828 }
829
835 [[nodiscard]] entity_type front() const noexcept {
836 const auto it = begin();
837 return it != end() ? *it : null;
838 }
839
845 [[nodiscard]] entity_type back() const noexcept {
846 const auto it = rbegin();
847 return it != rend() ? *it : null;
848 }
849
856 [[nodiscard]] iterator find(const entity_type entt) const noexcept {
857 const auto it = *this ? handle().find(entt) : iterator{};
858 return it >= begin() ? it : iterator{};
859 }
860
866 [[nodiscard]] entity_type operator[](const size_type pos) const {
867 return begin()[pos];
868 }
869
874 [[nodiscard]] explicit operator bool() const noexcept {
875 return descriptor != nullptr;
876 }
877
883 [[nodiscard]] bool contains(const entity_type entt) const noexcept {
884 return *this && handle().contains(entt) && (handle().index(entt) < (descriptor->length()));
885 }
886
894 template<typename Type, typename... Other>
895 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
896 return get<index_of<Type>, index_of<Other>...>(entt);
897 }
898
905 template<std::size_t... Index>
906 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
907 const auto cpools = pools_for(std::index_sequence_for<Owned...>{}, std::index_sequence_for<Get...>{});
908
909 if constexpr(sizeof...(Index) == 0) {
910 return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, cpools);
911 } else if constexpr(sizeof...(Index) == 1) {
912 return (std::get<Index>(cpools)->get(entt), ...);
913 } else {
914 return std::tuple_cat(std::get<Index>(cpools)->get_as_tuple(entt)...);
915 }
916 }
917
940 template<typename Func>
941 void each(Func func) const {
942 for(auto args: each()) {
943 if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_group>().get({})))>) {
944 std::apply(func, args);
945 } else {
946 std::apply([&func](auto, auto &&...less) { func(std::forward<decltype(less)>(less)...); }, args);
947 }
948 }
949 }
950
964 [[nodiscard]] iterable each() const noexcept {
965 const auto cpools = pools_for(std::index_sequence_for<Owned...>{}, std::index_sequence_for<Get...>{});
966 return iterable{{begin(), cpools}, {end(), cpools}};
967 }
968
1003 template<typename Type, typename... Other, typename Compare, typename Sort = std_sort, typename... Args>
1004 void sort(Compare compare, Sort algo = Sort{}, Args &&...args) const {
1005 sort<index_of<Type>, index_of<Other>...>(std::move(compare), std::move(algo), std::forward<Args>(args)...);
1006 }
1007
1021 template<std::size_t... Index, typename Compare, typename Sort = std_sort, typename... Args>
1022 void sort(Compare compare, Sort algo = Sort{}, Args &&...args) const {
1023 const auto cpools = pools_for(std::index_sequence_for<Owned...>{}, std::index_sequence_for<Get...>{});
1024
1025 if constexpr(sizeof...(Index) == 0) {
1026 static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
1027 storage<0>()->sort_n(descriptor->length(), std::move(compare), std::move(algo), std::forward<Args>(args)...);
1028 } else {
1029 auto comp = [&compare, &cpools](const entity_type lhs, const entity_type rhs) {
1030 if constexpr(sizeof...(Index) == 1) {
1031 return compare((std::get<Index>(cpools)->get(lhs), ...), (std::get<Index>(cpools)->get(rhs), ...));
1032 } else {
1033 return compare(std::forward_as_tuple(std::get<Index>(cpools)->get(lhs)...), std::forward_as_tuple(std::get<Index>(cpools)->get(rhs)...));
1034 }
1035 };
1036
1037 storage<0>()->sort_n(descriptor->length(), std::move(comp), std::move(algo), std::forward<Args>(args)...);
1038 }
1039
1040 auto cb = [this](auto *head, auto *...other) {
1041 for(auto next = descriptor->length(); next; --next) {
1042 const auto pos = next - 1;
1043 [[maybe_unused]] const auto entt = head->data()[pos];
1044 (other->swap_elements(other->data()[pos], entt), ...);
1045 }
1046 };
1047
1048 std::apply(cb, cpools);
1049 }
1050
1051private:
1052 handler *descriptor;
1053};
1054
1055} // namespace entt
1056
1057#endif
const common_type & handle() const noexcept
Returns the leading storage of a group.
Definition group.hpp:748
void each(Func func) const
Iterates entities and elements and applies the given function object to them.
Definition group.hpp:941
decltype(auto) get(const entity_type entt) const
Returns the elements assigned to the given entity.
Definition group.hpp:895
basic_group() noexcept
Default constructor to use to create empty, invalid groups.
Definition group.hpp:734
entity_type back() const noexcept
Returns the last entity of the group, if any.
Definition group.hpp:845
iterator begin() const noexcept
Returns an iterator to the first entity of the group.
Definition group.hpp:796
auto * storage() const noexcept
Returns the storage for a given element type, if any.
Definition group.hpp:758
internal::group_handler< common_type, sizeof...(Owned), sizeof...(Get), sizeof...(Exclude)> handler
Group handler type.
Definition group.hpp:723
typename common_type::iterator iterator
Random access iterator type.
Definition group.hpp:717
iterator find(const entity_type entt) const noexcept
Finds an entity.
Definition group.hpp:856
bool contains(const entity_type entt) const noexcept
Checks if a group contains an entity.
Definition group.hpp:883
entity_type front() const noexcept
Returns the first entity of the group, if any.
Definition group.hpp:835
basic_group(handler &ref) noexcept
Constructs a group from a set of storage classes.
Definition group.hpp:741
iterator end() const noexcept
Returns an iterator that is past the last entity of the group.
Definition group.hpp:805
typename common_type::reverse_iterator reverse_iterator
Reverse iterator type.
Definition group.hpp:719
entity_type operator[](const size_type pos) const
Returns the identifier that occupies the given position.
Definition group.hpp:866
size_type size() const noexcept
Returns the number of entities that that are part of the group.
Definition group.hpp:777
iterable each() const noexcept
Returns an iterable object to use to visit a group.
Definition group.hpp:964
reverse_iterator rend() const noexcept
Returns an iterator that is past the last entity of the reversed group.
Definition group.hpp:826
void sort(Compare compare, Sort algo=Sort{}, Args &&...args) const
Sort a group according to the given comparison function.
Definition group.hpp:1004
decltype(auto) get(const entity_type entt) const
Returns the elements assigned to the given entity.
Definition group.hpp:906
reverse_iterator rbegin() const noexcept
Returns an iterator to the first entity of the reversed group.
Definition group.hpp:816
bool empty() const noexcept
Checks whether a group is empty.
Definition group.hpp:785
void sort(Compare compare, Sort algo=Sort{}, Args &&...args) const
Sort a group according to the given comparison function.
Definition group.hpp:1022
iterator begin() const noexcept
Returns an iterator to the first entity of the group.
Definition group.hpp:398
void sort_as(It first, It last) const
Sort entities according to their order in a range.
Definition group.hpp:652
static id_type group_id() noexcept
Group opaque identifier.
Definition group.hpp:315
auto * storage() const noexcept
Returns the storage for a given element type, if any.
Definition group.hpp:344
typename common_type::reverse_iterator reverse_iterator
Reverse iterator type.
Definition group.hpp:305
basic_group(handler &ref) noexcept
Constructs a group from a set of storage classes.
Definition group.hpp:327
entity_type operator[](const size_type pos) const
Returns the identifier that occupies the given position.
Definition group.hpp:467
bool contains(const entity_type entt) const noexcept
Checks if a group contains an entity.
Definition group.hpp:484
void sort(Compare compare, Sort algo=Sort{}, Args &&...args)
Sort a group according to the given comparison function.
Definition group.hpp:622
reverse_iterator rbegin() const noexcept
Returns an iterator to the first entity of the reversed group.
Definition group.hpp:418
const common_type & handle() const noexcept
Returns the leading storage of a group.
Definition group.hpp:334
void sort(Compare compare, Sort algo=Sort{}, Args &&...args)
Sort a group according to the given comparison function.
Definition group.hpp:604
decltype(auto) get(const entity_type entt) const
Returns the elements assigned to the given entity.
Definition group.hpp:496
bool empty() const noexcept
Checks whether a group is empty.
Definition group.hpp:387
void each(Func func) const
Iterates entities and elements and applies the given function object to them.
Definition group.hpp:542
decltype(auto) get(const entity_type entt) const
Returns the elements assigned to the given entity.
Definition group.hpp:507
size_type capacity() const noexcept
Returns the number of elements that a group has currently allocated space for.
Definition group.hpp:372
void shrink_to_fit()
Requests the removal of unused capacity.
Definition group.hpp:377
entity_type front() const noexcept
Returns the first entity of the group, if any.
Definition group.hpp:437
reverse_iterator rend() const noexcept
Returns an iterator that is past the last entity of the reversed group.
Definition group.hpp:428
internal::group_handler< common_type, 0u, sizeof...(Get), sizeof...(Exclude)> handler
Group handler type.
Definition group.hpp:309
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:458
iterator end() const noexcept
Returns an iterator that is past the last entity of the group.
Definition group.hpp:407
typename common_type::iterator iterator
Random access iterator type.
Definition group.hpp:303
entity_type back() const noexcept
Returns the last entity of the group, if any.
Definition group.hpp:447
iterable each() const noexcept
Returns an iterable object to use to visit a group.
Definition group.hpp:565
base_type common_type
Common type among all storage types.
Definition group.hpp:301
basic_group() noexcept
Default constructor to use to create empty, invalid groups.
Definition group.hpp:320
size_type size() const noexcept
Returns the number of entities that are part of the group.
Definition group.hpp:363
Non-owning handle to an entity.
Definition handle.hpp:98
Storage implementation.
Definition storage.hpp:230
EnTT default namespace.
Definition dense_map.hpp:22
entity
Default entity identifier.
Definition fwd.hpp:14
constexpr Type make_obj_using_allocator(const Allocator &allocator, Args &&...args)
Uses-allocator construction utility (waiting for C++20).
Definition memory.hpp:219
constexpr null_t null
Compile-time constant for null entities.
Definition entity.hpp:375
basic_handle< registry > handle
Alias declaration for the most common use case.
Definition fwd.hpp:102
constexpr bool is_applicable_v
Helper variable template.
std::uint32_t id_type
Alias declaration for type identifiers.
Definition fwd.hpp:14
constexpr get_t< Type... > get
Variable template for lists of observed elements.
Definition fwd.hpp:168
typename type_list_element< Index, List >::type type_list_element_t
Helper type.
constexpr owned_t< Type... > owned
Variable template for lists of owned elements.
Definition fwd.hpp:185
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.
basic_storage< Type > storage
Alias declaration for the most common use case.
Definition fwd.hpp:76
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:141
Alias for lists of owned elements.
Definition fwd.hpp:175
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.