1 #ifndef ENTT_ENTITY_VIEW_HPP
2 #define ENTT_ENTITY_VIEW_HPP
10 #include <type_traits>
11 #include "../config/config.h"
12 #include "../core/type_traits.hpp"
16 #include "sparse_set.hpp"
17 #include "utility.hpp"
66 template<
typename Entity,
typename... Exclude,
typename... Component>
71 template<
typename Comp>
74 template<
typename Comp>
75 using component_iterator = decltype(std::declval<pool_type<Comp>>().begin());
77 using unchecked_type = std::array<const sparse_set<Entity> *, (
sizeof...(Component) - 1)>;
78 using filter_type = std::array<const sparse_set<Entity> *,
sizeof...(Exclude)>;
81 class view_iterator final {
84 view_iterator(It from, It to, It curr, unchecked_type other, filter_type ignore) ENTT_NOEXCEPT
91 if(it != last && !valid()) {
96 [[nodiscard]]
bool valid()
const {
97 return std::all_of(unchecked.cbegin(), unchecked.cend(), [
entt = *it](
const sparse_set<Entity> *curr) { return curr->contains(entt); })
98 && (
sizeof...(Exclude) == 0 || std::none_of(filter.cbegin(), filter.cend(), [
entt = *it](
const sparse_set<Entity> *cpool) {
return cpool->contains(
entt); }));
102 using difference_type =
typename std::iterator_traits<It>::difference_type;
103 using value_type =
typename std::iterator_traits<It>::value_type;
104 using pointer =
typename std::iterator_traits<It>::pointer;
105 using reference =
typename std::iterator_traits<It>::reference;
106 using iterator_category = std::bidirectional_iterator_tag;
108 view_iterator() ENTT_NOEXCEPT =
default;
110 view_iterator & operator++() {
111 while(++it != last && !valid());
115 view_iterator operator++(
int) {
116 view_iterator orig = *
this;
117 return ++(*this), orig;
120 view_iterator & operator--() ENTT_NOEXCEPT {
121 while(--it != first && !valid());
125 view_iterator operator--(
int) ENTT_NOEXCEPT {
126 view_iterator orig = *
this;
127 return operator--(), orig;
130 [[nodiscard]]
bool operator==(
const view_iterator &other)
const ENTT_NOEXCEPT {
131 return other.it == it;
134 [[nodiscard]]
bool operator!=(
const view_iterator &other)
const ENTT_NOEXCEPT {
135 return !(*
this == other);
138 [[nodiscard]] pointer operator->()
const {
142 [[nodiscard]] reference operator*()
const {
143 return *operator->();
150 unchecked_type unchecked;
157 using proxy_view_iterator = view_iterator<typename sparse_set<Entity>::iterator>;
159 class proxy_iterator {
160 friend class view_proxy;
162 using ref_type = decltype(std::tuple_cat(std::declval<std::conditional_t<is_eto_eligible_v<Component>, std::tuple<>, std::tuple<pool_type<Component> *>>>()...));
164 proxy_iterator(proxy_view_iterator from, ref_type ref) ENTT_NOEXCEPT
170 using difference_type = std::ptrdiff_t;
171 using value_type = decltype(std::tuple_cat(
172 std::declval<std::tuple<Entity>>(),
173 std::declval<std::conditional_t<is_eto_eligible_v<Component>, std::tuple<>, std::tuple<Component>>>()...
175 using pointer = void;
176 using reference = decltype(std::tuple_cat(
177 std::declval<std::tuple<Entity>>(),
178 std::declval<std::conditional_t<is_eto_eligible_v<Component>, std::tuple<>, std::tuple<Component &>>>()...
180 using iterator_category = std::input_iterator_tag;
182 proxy_iterator & operator++() ENTT_NOEXCEPT {
186 proxy_iterator operator++(
int) ENTT_NOEXCEPT {
187 proxy_iterator orig = *
this;
188 return ++(*this), orig;
191 [[nodiscard]] reference operator*()
const ENTT_NOEXCEPT {
192 return std::apply([
entt = *it](
auto *... cpool) {
return reference{
entt, cpool->get(
entt)...}; }, pools);
195 [[nodiscard]]
bool operator==(
const proxy_iterator &other)
const ENTT_NOEXCEPT {
196 return other.it == it;
199 [[nodiscard]]
bool operator!=(
const proxy_iterator &other)
const ENTT_NOEXCEPT {
200 return !(*
this == other);
204 proxy_view_iterator it{};
205 const ref_type pools{};
208 view_proxy(proxy_view_iterator from, proxy_view_iterator to, std::tuple<pool_type<Component> *...> ref)
215 using iterator = proxy_iterator;
217 [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
218 return proxy_iterator{first, std::tuple_cat([](
auto *cpool) {
219 if constexpr(
is_eto_eligible_v<
typename std::decay_t<decltype(*cpool)>::object_type>) {
220 return std::make_tuple();
222 return std::make_tuple(cpool);
224 }(std::get<pool_type<Component> *>(pools))...)};
227 [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
228 return proxy_iterator{last, std::tuple_cat([](
auto *cpool) {
229 if constexpr(
is_eto_eligible_v<
typename std::decay_t<decltype(*cpool)>::object_type>) {
230 return std::make_tuple();
232 return std::make_tuple(cpool);
234 }(std::get<pool_type<Component> *>(pools))...)};
238 proxy_view_iterator first;
239 proxy_view_iterator last;
240 const std::tuple<pool_type<Component> *...> pools;
243 basic_view(pool_type<Component> &... component,
unpack_as_t<
const sparse_set<Entity>, Exclude> &... epool) ENTT_NOEXCEPT
244 : pools{&component...},
249 [[nodiscard]]
const sparse_set<Entity> * candidate() const ENTT_NOEXCEPT {
250 return (std::min)({
static_cast<const sparse_set<Entity> *
>(std::get<pool_type<Component> *>(pools))... }, [](
const auto *lhs,
const auto *rhs) {
251 return lhs->size() < rhs->size();
255 [[nodiscard]] unchecked_type unchecked(
const sparse_set<Entity> *cpool)
const {
257 unchecked_type other{};
258 ((std::get<pool_type<Component> *>(pools) == cpool ?
nullptr : (other[pos] = std::get<pool_type<Component> *>(pools), other[pos++])), ...);
262 template<
typename Comp,
typename Other>
263 [[nodiscard]] decltype(
auto)
get([[maybe_unused]] component_iterator<Comp> &it, [[maybe_unused]] pool_type<Other> *cpool, [[maybe_unused]] const Entity
entt)
const {
264 if constexpr(std::is_same_v<Comp, Other>) {
267 return cpool->get(
entt);
271 template<
typename Comp,
typename Func,
typename... Type>
272 void traverse(Func func, type_list<Type...>)
const {
273 if constexpr(std::disjunction_v<std::is_same<Comp, Type>...>) {
274 auto it = std::get<pool_type<Comp> *>(pools)->begin();
276 for(
const auto entt:
static_cast<const sparse_set<entity_type> &
>(*std::get<pool_type<Comp> *>(pools))) {
277 if(((std::is_same_v<Comp, Component> || std::get<pool_type<Component> *>(pools)->contains(
entt)) && ...)
278 && (
sizeof...(Exclude) == 0 || std::none_of(filter.cbegin(), filter.cend(), [
entt](
const sparse_set<Entity> *cpool) { return cpool->contains(entt); })))
280 if constexpr(std::is_invocable_v<Func, decltype(get<Type>({}))...>) {
281 func(get<Comp, Type>(it, std::get<pool_type<Type> *>(pools),
entt)...);
283 func(
entt, get<Comp, Type>(it, std::get<pool_type<Type> *>(pools),
entt)...);
290 for(
const auto entt:
static_cast<const sparse_set<entity_type> &
>(*std::get<pool_type<Comp> *>(pools))) {
291 if(((std::is_same_v<Comp, Component> || std::get<pool_type<Component> *>(pools)->contains(
entt)) && ...)
292 && (
sizeof...(Exclude) == 0 || std::none_of(filter.cbegin(), filter.cend(), [
entt](
const sparse_set<Entity> *cpool) { return cpool->contains(entt); })))
294 if constexpr(std::is_invocable_v<Func, decltype(get<Type>({}))...>) {
295 func(std::get<pool_type<Type> *>(pools)->
get(
entt)...);
297 func(
entt, std::get<pool_type<Type> *>(pools)->
get(
entt)...);
304 template<
typename Func,
typename... Type>
305 void iterate(Func func, type_list<Type...>)
const {
306 const auto last =
view->data() +
view->size();
307 auto first =
view->data();
309 while(first != last) {
310 if((std::get<pool_type<Component> *>(pools)->contains(*first) && ...)
311 && (
sizeof...(Exclude) == 0 || std::none_of(filter.cbegin(), filter.cend(), [
entt = *first](
const sparse_set<Entity> *cpool) { return cpool->contains(entt); })))
313 const auto base = *(first++);
314 const auto chunk = (std::min)({ (std::get<pool_type<Component> *>(pools)->size() - std::get<pool_type<Component> *>(pools)->index(base))... });
319 && ((*(std::get<pool_type<Component> *>(pools)->data() + std::get<pool_type<Component> *>(pools)->index(base) + length) == *first) && ...)
320 && (
sizeof...(Exclude) == 0 || std::none_of(filter.cbegin(), filter.cend(), [
entt = *first](
const sparse_set<Entity> *cpool) {
return cpool->contains(
entt); }));
323 func(
view->data() +
view->index(base), (std::get<pool_type<Type> *>(pools)->raw() + std::get<pool_type<Type> *>(pools)->index(base))..., length);
336 using iterator = view_iterator<typename sparse_set<entity_type>::iterator>;
338 using reverse_iterator = view_iterator<typename sparse_set<entity_type>::reverse_iterator>;
348 template<
typename Comp>
350 return std::get<pool_type<Comp> *>(pools)->size();
358 return (std::min)({ std::get<pool_type<Component> *>(pools)->size()... });
371 template<
typename... Comp>
372 [[nodiscard]]
bool empty() const ENTT_NOEXCEPT {
373 if constexpr(
sizeof...(Comp) == 0) {
374 return (std::get<pool_type<Component> *>(pools)->empty() || ...);
376 return (std::get<pool_type<Comp> *>(pools)->empty() && ...);
394 template<
typename Comp>
395 [[nodiscard]] Comp *
raw() const ENTT_NOEXCEPT {
396 return std::get<pool_type<Comp> *>(pools)->raw();
413 template<
typename Comp>
415 return std::get<pool_type<Comp> *>(pools)->data();
492 const auto it = begin();
493 return it != end() ? *it :
null;
502 const auto it = rbegin();
503 return it != rend() ? *it :
null;
514 return (it != end() && *it ==
entt) ? it : end();
523 return (std::get<pool_type<Component> *>(pools)->contains(
entt) && ...)
524 && (
sizeof...(Exclude) == 0 || std::none_of(filter.begin(), filter.end(), [
entt](
const auto *cpool) {
return cpool->contains(
entt); }));
544 template<
typename... Comp>
546 ENTT_ASSERT(contains(
entt));
548 if constexpr(
sizeof...(Comp) == 0) {
549 static_assert(
sizeof...(Component) == 1,
"Invalid component type");
550 return (std::get<pool_type<Component> *>(pools)->
get(
entt), ...);
551 }
else if constexpr(
sizeof...(Comp) == 1) {
552 return (std::get<pool_type<Comp> *>(pools)->
get(
entt), ...);
554 return std::tuple<decltype(get<Comp>({}))...>{get<Comp>(
entt)...};
580 template<
typename Func>
583 ((std::get<pool_type<Component> *>(pools) ==
view ? each<Component>(std::move(func)) :
void()), ...);
602 template<
typename Comp,
typename Func>
605 traverse<Comp>(std::move(func), non_empty_type{});
621 [[nodiscard]]
auto proxy() const ENTT_NOEXCEPT {
623 return view_proxy{begin(), end(), pools};
640 template<
typename Comp>
641 [[nodiscard]]
auto proxy() const ENTT_NOEXCEPT {
645 return view_proxy{std::move(first), std::move(last), pools};
680 template<
typename Func>
684 iterate(std::move(func), non_empty_type{});
688 const std::tuple<pool_type<Component> *...> pools;
725 template<
typename Entity,
typename Component>
735 class proxy_iterator {
736 friend class view_proxy;
738 using it_type = std::conditional_t<
739 is_eto_eligible_v<Component>,
740 std::tuple<typename sparse_set<Entity>::iterator>,
741 std::tuple<typename sparse_set<Entity>::iterator, decltype(std::declval<pool_type>().begin())>
744 proxy_iterator(it_type from) ENTT_NOEXCEPT
749 using difference_type = std::ptrdiff_t;
750 using value_type = std::conditional_t<is_eto_eligible_v<Component>, std::tuple<Entity>, std::tuple<Entity, Component>>;
751 using pointer = void;
752 using reference = std::conditional_t<is_eto_eligible_v<Component>, std::tuple<Entity>, std::tuple<Entity, Component &>>;
753 using iterator_category = std::input_iterator_tag;
755 proxy_iterator & operator++() ENTT_NOEXCEPT {
756 return std::apply([](
auto &&... curr) { (++curr, ...); }, it), *
this;
759 proxy_iterator operator++(
int) ENTT_NOEXCEPT {
760 proxy_iterator orig = *
this;
761 return ++(*this), orig;
764 [[nodiscard]] reference operator*()
const ENTT_NOEXCEPT {
765 return std::apply([](
auto &&... curr) {
return reference{*curr...}; }, it);
768 [[nodiscard]]
bool operator==(
const proxy_iterator &other)
const ENTT_NOEXCEPT {
769 return std::get<0>(other.it) == std::get<0>(it);
772 [[nodiscard]]
bool operator!=(
const proxy_iterator &other)
const ENTT_NOEXCEPT {
773 return !(*
this == other);
780 view_proxy(pool_type &ref)
787 [[nodiscard]]
iterator begin()
const ENTT_NOEXCEPT {
788 if constexpr(is_eto_eligible_v<Component>) {
789 return proxy_iterator{std::make_tuple(
pool->sparse_set<entity_type>::begin())};
791 return proxy_iterator{std::make_tuple(
pool->sparse_set<entity_type>::begin(),
pool->begin())};
795 [[nodiscard]]
iterator end()
const ENTT_NOEXCEPT {
796 if constexpr(is_eto_eligible_v<Component>) {
797 return proxy_iterator{std::make_tuple(
pool->sparse_set<entity_type>::end())};
799 return proxy_iterator{std::make_tuple(
pool->sparse_set<entity_type>::end(),
pool->end())};
835 [[nodiscard]]
bool empty() const ENTT_NOEXCEPT {
836 return pool->empty();
884 return pool->sparse_set<Entity>::begin();
901 return pool->sparse_set<Entity>::end();
917 return pool->sparse_set<Entity>::rbegin();
936 return pool->sparse_set<Entity>::rend();
945 const auto it = begin();
946 return it != end() ? *it :
null;
955 const auto it = rbegin();
956 return it != rend() ? *it :
null;
967 return it != end() && *it ==
entt ? it : end();
1003 template<
typename Comp = Component>
1005 static_assert(std::is_same_v<Comp, Component>,
"Invalid component type");
1006 ENTT_ASSERT(contains(
entt));
1032 template<
typename Func>
1034 if constexpr(is_eto_eligible_v<Component>) {
1035 if constexpr(std::is_invocable_v<Func>) {
1036 for(
auto pos =
pool->size(); pos; --pos) {
1040 for(
const auto entt: *
this) {
1045 if constexpr(std::is_invocable_v<Func, decltype(
get({}))>) {
1046 for(
auto &&component: *
pool) {
1050 auto raw =
pool->begin();
1052 for(
const auto entt: *
this) {
1053 func(
entt, *(raw++));
1072 [[nodiscard]]
auto proxy() const ENTT_NOEXCEPT {
1073 return view_proxy{*
pool};