EnTT 3.13.0
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 void swap_elements(const std::size_t pos, const entity_type entt) {
113 std::apply([pos, entt](auto *...cpool) { (cpool->swap_elements(cpool->data()[pos], entt), ...); }, pools);
114 }
115
116 void push_on_construct(const entity_type entt) {
117 if(std::apply([entt, len = len](auto *cpool, auto *...other) { return cpool->contains(entt) && !(cpool->index(entt) < len) && (other->contains(entt) && ...); }, pools)
118 && std::apply([entt](auto *...cpool) { return (!cpool->contains(entt) && ...); }, filter)) {
119 swap_elements(len++, entt);
120 }
121 }
122
123 void push_on_destroy(const entity_type entt) {
124 if(std::apply([entt, len = len](auto *cpool, auto *...other) { return cpool->contains(entt) && !(cpool->index(entt) < len) && (other->contains(entt) && ...); }, pools)
125 && std::apply([entt](auto *...cpool) { return (0u + ... + cpool->contains(entt)) == 1u; }, filter)) {
126 swap_elements(len++, entt);
127 }
128 }
129
130 void remove_if(const entity_type entt) {
131 if(std::get<0>(pools)->contains(entt) && (std::get<0>(pools)->index(entt) < len)) {
132 swap_elements(--len, entt);
133 }
134 }
135
136public:
137 using size_type = typename base_type::size_type;
138
139 group_handler(Owned &...opool, Get &...gpool, Exclude &...epool)
140 : pools{&opool..., &gpool...},
141 filter{&epool...},
142 len{} {
143 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);
144 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);
145
146 // we cannot iterate backwards because we want to leave behind valid entities in case of owned types
147 for(auto *first = std::get<0>(pools)->data(), *last = first + std::get<0>(pools)->size(); first != last; ++first) {
148 push_on_construct(*first);
149 }
150 }
151
152 size_type owned(const id_type *elem, const size_type length) const noexcept final {
153 size_type cnt = 0u;
154
155 for(auto pos = 0u; pos < length; ++pos) {
156 cnt += ((elem[pos] == entt::type_hash<typename Owned::value_type>::value()) || ...);
157 }
158
159 return cnt;
160 }
161
162 [[nodiscard]] size_type length() const noexcept {
163 return len;
164 }
165
166 template<typename Type>
167 Type pools_as() const noexcept {
168 return pools;
169 }
170
171 template<typename Type>
172 Type filter_as() const noexcept {
173 return filter;
174 }
175
176private:
177 std::tuple<Owned *..., Get *...> pools;
178 std::tuple<Exclude *...> filter;
179 std::size_t len;
180};
181
182template<typename... Get, typename... Exclude>
183class group_handler<owned_t<>, get_t<Get...>, exclude_t<Exclude...>> final: public group_descriptor {
184 // nasty workaround for an issue with the toolset v141 that doesn't accept a fold expression here
185 static_assert(!std::disjunction_v<std::is_const<Get>..., std::is_const<Exclude>...>, "Const storage type not allowed");
186
187 using base_type = std::common_type_t<typename Get::base_type..., typename Exclude::base_type...>;
188 using entity_type = typename base_type::entity_type;
189
190 void push_on_construct(const entity_type entt) {
191 if(!elem.contains(entt)
192 && std::apply([entt](auto *...cpool) { return (cpool->contains(entt) && ...); }, pools)
193 && std::apply([entt](auto *...cpool) { return (!cpool->contains(entt) && ...); }, filter)) {
194 elem.push(entt);
195 }
196 }
197
198 void push_on_destroy(const entity_type entt) {
199 if(!elem.contains(entt)
200 && std::apply([entt](auto *...cpool) { return (cpool->contains(entt) && ...); }, pools)
201 && std::apply([entt](auto *...cpool) { return (0u + ... + cpool->contains(entt)) == 1u; }, filter)) {
202 elem.push(entt);
203 }
204 }
205
206 void remove_if(const entity_type entt) {
207 elem.remove(entt);
208 }
209
210public:
211 using common_type = base_type;
212
213 template<typename Alloc>
214 group_handler(const Alloc &alloc, Get &...gpool, Exclude &...epool)
215 : pools{&gpool...},
216 filter{&epool...},
217 elem{alloc} {
218 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);
219 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);
220
221 for(const auto entity: static_cast<base_type &>(*std::get<0>(pools))) {
222 push_on_construct(entity);
223 }
224 }
225
226 common_type &handle() noexcept {
227 return elem;
228 }
229
230 const common_type &handle() const noexcept {
231 return elem;
232 }
233
234 template<typename Type>
235 Type pools_as() const noexcept {
236 return pools;
237 }
238
239 template<typename Type>
240 Type filter_as() const noexcept {
241 return filter;
242 }
243
244private:
245 std::tuple<Get *...> pools;
246 std::tuple<Exclude *...> filter;
247 base_type elem;
248};
249
250} // namespace internal
259template<typename, typename, typename>
260class basic_group;
261
284template<typename... Get, typename... Exclude>
285class basic_group<owned_t<>, get_t<Get...>, exclude_t<Exclude...>> {
286 using base_type = std::common_type_t<typename Get::base_type..., typename Exclude::base_type...>;
287 using underlying_type = typename base_type::entity_type;
288
289 template<typename Type>
290 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...>>;
291
292 auto pools() const noexcept {
293 using return_type = std::tuple<Get *...>;
294 return descriptor ? descriptor->template pools_as<return_type>() : return_type{};
295 }
296
297 auto filter() const noexcept {
298 using return_type = std::tuple<Exclude *...>;
299 return descriptor ? descriptor->template filter_as<return_type>() : return_type{};
300 }
301
302public:
304 using entity_type = underlying_type;
306 using size_type = std::size_t;
308 using common_type = base_type;
310 using iterator = typename common_type::iterator;
312 using reverse_iterator = typename common_type::reverse_iterator;
316 using handler = internal::group_handler<owned_t<>, get_t<std::remove_const_t<Get>...>, exclude_t<std::remove_const_t<Exclude>...>>;
317
319 basic_group() noexcept
320 : descriptor{} {}
321
327 : descriptor{&ref} {}
328
333 [[nodiscard]] const common_type &handle() const noexcept {
334 return descriptor->handle();
335 }
336
342 template<typename Type>
343 [[nodiscard]] auto *storage() const noexcept {
344 return storage<index_of<Type>>();
345 }
346
352 template<std::size_t Index>
353 [[nodiscard]] auto *storage() const noexcept {
354 constexpr auto offset = sizeof...(Get);
355
356 if constexpr(Index < offset) {
357 return std::get<Index>(pools());
358 } else {
359 return std::get<Index - offset>(filter());
360 }
361 }
362
367 [[nodiscard]] size_type size() const noexcept {
368 return *this ? handle().size() : size_type{};
369 }
370
376 [[nodiscard]] size_type capacity() const noexcept {
377 return *this ? handle().capacity() : size_type{};
378 }
379
382 if(*this) {
383 descriptor->handle().shrink_to_fit();
384 }
385 }
386
391 [[nodiscard]] bool empty() const noexcept {
392 return !*this || handle().empty();
393 }
394
402 [[nodiscard]] iterator begin() const noexcept {
403 return *this ? handle().begin() : iterator{};
404 }
405
411 [[nodiscard]] iterator end() const noexcept {
412 return *this ? handle().end() : iterator{};
413 }
414
422 [[nodiscard]] reverse_iterator rbegin() const noexcept {
423 return *this ? handle().rbegin() : reverse_iterator{};
424 }
425
432 [[nodiscard]] reverse_iterator rend() const noexcept {
433 return *this ? handle().rend() : reverse_iterator{};
434 }
435
441 [[nodiscard]] entity_type front() const noexcept {
442 const auto it = begin();
443 return it != end() ? *it : null;
444 }
445
451 [[nodiscard]] entity_type back() const noexcept {
452 const auto it = rbegin();
453 return it != rend() ? *it : null;
454 }
455
462 [[nodiscard]] iterator find(const entity_type entt) const noexcept {
463 return *this ? handle().find(entt) : iterator{};
464 }
465
471 [[nodiscard]] entity_type operator[](const size_type pos) const {
472 return begin()[pos];
473 }
474
479 [[nodiscard]] explicit operator bool() const noexcept {
480 return descriptor != nullptr;
481 }
482
488 [[nodiscard]] bool contains(const entity_type entt) const noexcept {
489 return *this && handle().contains(entt);
490 }
491
499 template<typename Type, typename... Other>
500 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
501 return get<index_of<Type>, index_of<Other>...>(entt);
502 }
503
510 template<std::size_t... Index>
511 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
512 const auto cpools = pools();
513
514 if constexpr(sizeof...(Index) == 0) {
515 return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, cpools);
516 } else if constexpr(sizeof...(Index) == 1) {
517 return (std::get<Index>(cpools)->get(entt), ...);
518 } else {
519 return std::tuple_cat(std::get<Index>(cpools)->get_as_tuple(entt)...);
520 }
521 }
522
545 template<typename Func>
546 void each(Func func) const {
547 for(const auto entt: *this) {
548 if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_group>().get({})))>) {
549 std::apply(func, std::tuple_cat(std::make_tuple(entt), get(entt)));
550 } else {
551 std::apply(func, get(entt));
552 }
553 }
554 }
555
569 [[nodiscard]] iterable each() const noexcept {
570 const auto cpools = pools();
571 return iterable{{begin(), cpools}, {end(), cpools}};
572 }
573
607 template<typename Type, typename... Other, typename Compare, typename Sort = std_sort, typename... Args>
608 void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
609 sort<index_of<Type>, index_of<Other>...>(std::move(compare), std::move(algo), std::forward<Args>(args)...);
610 }
611
625 template<std::size_t... Index, typename Compare, typename Sort = std_sort, typename... Args>
626 void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
627 if(*this) {
628 if constexpr(sizeof...(Index) == 0) {
629 static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
630 descriptor->handle().sort(std::move(compare), std::move(algo), std::forward<Args>(args)...);
631 } else {
632 auto comp = [&compare, cpools = pools()](const entity_type lhs, const entity_type rhs) {
633 if constexpr(sizeof...(Index) == 1) {
634 return compare((std::get<Index>(cpools)->get(lhs), ...), (std::get<Index>(cpools)->get(rhs), ...));
635 } else {
636 return compare(std::forward_as_tuple(std::get<Index>(cpools)->get(lhs)...), std::forward_as_tuple(std::get<Index>(cpools)->get(rhs)...));
637 }
638 };
639
640 descriptor->handle().sort(std::move(comp), std::move(algo), std::forward<Args>(args)...);
641 }
642 }
643 }
644
655 template<typename It>
656 void sort_as(It first, It last) const {
657 if(*this) {
658 descriptor->handle().sort_as(first, last);
659 }
660 }
661
666 [[deprecated("use iterator based sort_as instead")]] void sort_as(const common_type &other) const {
667 sort_as(other.begin(), other.end());
668 }
669
670private:
671 handler *descriptor;
672};
673
705template<typename... Owned, typename... Get, typename... Exclude>
706class basic_group<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> {
707 using base_type = std::common_type_t<typename Owned::base_type..., typename Get::base_type..., typename Exclude::base_type...>;
708 using underlying_type = typename base_type::entity_type;
709
710 template<typename Type>
711 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...>>;
712
713 auto pools() const noexcept {
714 using return_type = std::tuple<Owned *..., Get *...>;
715 return descriptor ? descriptor->template pools_as<return_type>() : return_type{};
716 }
717
718 auto filter() const noexcept {
719 using return_type = std::tuple<Exclude *...>;
720 return descriptor ? descriptor->template filter_as<return_type>() : return_type{};
721 }
722
723public:
725 using entity_type = underlying_type;
727 using size_type = std::size_t;
729 using common_type = base_type;
731 using iterator = typename common_type::iterator;
733 using reverse_iterator = typename common_type::reverse_iterator;
735 using iterable = iterable_adaptor<internal::extended_group_iterator<iterator, owned_t<Owned...>, get_t<Get...>>>;
737 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>...>>;
738
740 basic_group() noexcept
741 : descriptor{} {}
742
748 : descriptor{&ref} {}
749
754 [[nodiscard]] const common_type &handle() const noexcept {
755 return *storage<0>();
756 }
757
763 template<typename Type>
764 [[nodiscard]] auto *storage() const noexcept {
765 return storage<index_of<Type>>();
766 }
767
773 template<std::size_t Index>
774 [[nodiscard]] auto *storage() const noexcept {
775 constexpr auto offset = sizeof...(Owned) + sizeof...(Get);
776
777 if constexpr(Index < offset) {
778 return std::get<Index>(pools());
779 } else {
780 return std::get<Index - offset>(filter());
781 }
782 }
783
788 [[nodiscard]] size_type size() const noexcept {
789 return *this ? descriptor->length() : size_type{};
790 }
791
796 [[nodiscard]] bool empty() const noexcept {
797 return !*this || !descriptor->length();
798 }
799
807 [[nodiscard]] iterator begin() const noexcept {
808 return *this ? (handle().end() - descriptor->length()) : iterator{};
809 }
810
816 [[nodiscard]] iterator end() const noexcept {
817 return *this ? handle().end() : iterator{};
818 }
819
827 [[nodiscard]] reverse_iterator rbegin() const noexcept {
828 return *this ? handle().rbegin() : reverse_iterator{};
829 }
830
837 [[nodiscard]] reverse_iterator rend() const noexcept {
838 return *this ? (handle().rbegin() + descriptor->length()) : reverse_iterator{};
839 }
840
846 [[nodiscard]] entity_type front() const noexcept {
847 const auto it = begin();
848 return it != end() ? *it : null;
849 }
850
856 [[nodiscard]] entity_type back() const noexcept {
857 const auto it = rbegin();
858 return it != rend() ? *it : null;
859 }
860
867 [[nodiscard]] iterator find(const entity_type entt) const noexcept {
868 const auto it = *this ? handle().find(entt) : iterator{};
869 return it >= begin() ? it : iterator{};
870 }
871
877 [[nodiscard]] entity_type operator[](const size_type pos) const {
878 return begin()[pos];
879 }
880
885 [[nodiscard]] explicit operator bool() const noexcept {
886 return descriptor != nullptr;
887 }
888
894 [[nodiscard]] bool contains(const entity_type entt) const noexcept {
895 return *this && handle().contains(entt) && (handle().index(entt) < (descriptor->length()));
896 }
897
905 template<typename Type, typename... Other>
906 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
907 return get<index_of<Type>, index_of<Other>...>(entt);
908 }
909
916 template<std::size_t... Index>
917 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
918 const auto cpools = pools();
919
920 if constexpr(sizeof...(Index) == 0) {
921 return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, cpools);
922 } else if constexpr(sizeof...(Index) == 1) {
923 return (std::get<Index>(cpools)->get(entt), ...);
924 } else {
925 return std::tuple_cat(std::get<Index>(cpools)->get_as_tuple(entt)...);
926 }
927 }
928
951 template<typename Func>
952 void each(Func func) const {
953 for(auto args: each()) {
954 if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_group>().get({})))>) {
955 std::apply(func, args);
956 } else {
957 std::apply([&func](auto, auto &&...less) { func(std::forward<decltype(less)>(less)...); }, args);
958 }
959 }
960 }
961
975 [[nodiscard]] iterable each() const noexcept {
976 const auto cpools = pools();
977 return {{begin(), cpools}, {end(), cpools}};
978 }
979
1014 template<typename Type, typename... Other, typename Compare, typename Sort = std_sort, typename... Args>
1015 void sort(Compare compare, Sort algo = Sort{}, Args &&...args) const {
1016 sort<index_of<Type>, index_of<Other>...>(std::move(compare), std::move(algo), std::forward<Args>(args)...);
1017 }
1018
1032 template<std::size_t... Index, typename Compare, typename Sort = std_sort, typename... Args>
1033 void sort(Compare compare, Sort algo = Sort{}, Args &&...args) const {
1034 const auto cpools = pools();
1035
1036 if constexpr(sizeof...(Index) == 0) {
1037 static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
1038 storage<0>()->sort_n(descriptor->length(), std::move(compare), std::move(algo), std::forward<Args>(args)...);
1039 } else {
1040 auto comp = [&compare, &cpools](const entity_type lhs, const entity_type rhs) {
1041 if constexpr(sizeof...(Index) == 1) {
1042 return compare((std::get<Index>(cpools)->get(lhs), ...), (std::get<Index>(cpools)->get(rhs), ...));
1043 } else {
1044 return compare(std::forward_as_tuple(std::get<Index>(cpools)->get(lhs)...), std::forward_as_tuple(std::get<Index>(cpools)->get(rhs)...));
1045 }
1046 };
1047
1048 storage<0>()->sort_n(descriptor->length(), std::move(comp), std::move(algo), std::forward<Args>(args)...);
1049 }
1050
1051 auto cb = [this](auto *head, auto *...other) {
1052 for(auto next = descriptor->length(); next; --next) {
1053 const auto pos = next - 1;
1054 [[maybe_unused]] const auto entt = head->data()[pos];
1055 (other->swap_elements(other->data()[pos], entt), ...);
1056 }
1057 };
1058
1059 std::apply(cb, cpools);
1060 }
1061
1062private:
1063 handler *descriptor;
1064};
1065
1066} // namespace entt
1067
1068#endif
const common_type & handle() const noexcept
Returns the leading storage of a group.
Definition group.hpp:754
void each(Func func) const
Iterates entities and components and applies the given function object to them.
Definition group.hpp:952
decltype(auto) get(const entity_type entt) const
Returns the components assigned to the given entity.
Definition group.hpp:906
basic_group() noexcept
Default constructor to use to create empty, invalid groups.
Definition group.hpp:740
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:737
entity_type back() const noexcept
Returns the last entity of the group, if any.
Definition group.hpp:856
iterator begin() const noexcept
Returns an iterator to the first entity of the group.
Definition group.hpp:807
auto * storage() const noexcept
Returns the storage for a given component type, if any.
Definition group.hpp:764
typename common_type::iterator iterator
Random access iterator type.
Definition group.hpp:731
iterator find(const entity_type entt) const noexcept
Finds an entity.
Definition group.hpp:867
bool contains(const entity_type entt) const noexcept
Checks if a group contains an entity.
Definition group.hpp:894
entity_type front() const noexcept
Returns the first entity of the group, if any.
Definition group.hpp:846
basic_group(handler &ref) noexcept
Constructs a group from a set of storage classes.
Definition group.hpp:747
iterator end() const noexcept
Returns an iterator that is past the last entity of the group.
Definition group.hpp:816
typename common_type::reverse_iterator reverse_iterator
Reversed iterator type.
Definition group.hpp:733
entity_type operator[](const size_type pos) const
Returns the identifier that occupies the given position.
Definition group.hpp:877
size_type size() const noexcept
Returns the number of entities that that are part of the group.
Definition group.hpp:788
iterable each() const noexcept
Returns an iterable object to use to visit a group.
Definition group.hpp:975
reverse_iterator rend() const noexcept
Returns an iterator that is past the last entity of the reversed group.
Definition group.hpp:837
void sort(Compare compare, Sort algo=Sort{}, Args &&...args) const
Sort a group according to the given comparison function.
Definition group.hpp:1015
decltype(auto) get(const entity_type entt) const
Returns the components assigned to the given entity.
Definition group.hpp:917
reverse_iterator rbegin() const noexcept
Returns an iterator to the first entity of the reversed group.
Definition group.hpp:827
bool empty() const noexcept
Checks whether a group is empty.
Definition group.hpp:796
void sort(Compare compare, Sort algo=Sort{}, Args &&...args) const
Sort a group according to the given comparison function.
Definition group.hpp:1033
iterator begin() const noexcept
Returns an iterator to the first entity of the group.
Definition group.hpp:402
void sort_as(It first, It last) const
Sort entities according to their order in a range.
Definition group.hpp:656
auto * storage() const noexcept
Returns the storage for a given component type, if any.
Definition group.hpp:343
typename common_type::reverse_iterator reverse_iterator
Reversed iterator type.
Definition group.hpp:312
basic_group(handler &ref) noexcept
Constructs a group from a set of storage classes.
Definition group.hpp:326
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:316
entity_type operator[](const size_type pos) const
Returns the identifier that occupies the given position.
Definition group.hpp:471
bool contains(const entity_type entt) const noexcept
Checks if a group contains an entity.
Definition group.hpp:488
void sort(Compare compare, Sort algo=Sort{}, Args &&...args)
Sort a group according to the given comparison function.
Definition group.hpp:626
reverse_iterator rbegin() const noexcept
Returns an iterator to the first entity of the reversed group.
Definition group.hpp:422
const common_type & handle() const noexcept
Returns the leading storage of a group.
Definition group.hpp:333
void sort(Compare compare, Sort algo=Sort{}, Args &&...args)
Sort a group according to the given comparison function.
Definition group.hpp:608
decltype(auto) get(const entity_type entt) const
Returns the components assigned to the given entity.
Definition group.hpp:500
bool empty() const noexcept
Checks whether a group is empty.
Definition group.hpp:391
void sort_as(const common_type &other) const
Sort entities according to their order in a range.
Definition group.hpp:666
void each(Func func) const
Iterates entities and components and applies the given function object to them.
Definition group.hpp:546
decltype(auto) get(const entity_type entt) const
Returns the components assigned to the given entity.
Definition group.hpp:511
size_type capacity() const noexcept
Returns the number of elements that a group has currently allocated space for.
Definition group.hpp:376
void shrink_to_fit()
Requests the removal of unused capacity.
Definition group.hpp:381
entity_type front() const noexcept
Returns the first entity of the group, if any.
Definition group.hpp:441
reverse_iterator rend() const noexcept
Returns an iterator that is past the last entity of the reversed group.
Definition group.hpp:432
underlying_type entity_type
Underlying entity identifier.
Definition group.hpp:304
iterator find(const entity_type entt) const noexcept
Finds an entity.
Definition group.hpp:462
iterator end() const noexcept
Returns an iterator that is past the last entity of the group.
Definition group.hpp:411
typename common_type::iterator iterator
Random access iterator type.
Definition group.hpp:310
entity_type back() const noexcept
Returns the last entity of the group, if any.
Definition group.hpp:451
iterable each() const noexcept
Returns an iterable object to use to visit a group.
Definition group.hpp:569
base_type common_type
Common type among all storage types.
Definition group.hpp:308
basic_group() noexcept
Default constructor to use to create empty, invalid groups.
Definition group.hpp:319
size_type size() const noexcept
Returns the number of entities that are part of the group.
Definition group.hpp:367
void sort_n(const size_type length, Compare compare, Sort algo=Sort{}, Args &&...args)
Sort the first count elements according to the given comparison function.
Basic storage implementation.
Definition storage.hpp:229
EnTT default namespace.
Definition dense_map.hpp:21
basic_handle< registry > handle
Alias declaration for the most common use case.
Definition fwd.hpp:91
constexpr null_t null
Compile-time constant for null entities.
Definition entity.hpp:363
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.