1 #ifndef ENTT_ENTITY_GROUP_HPP
2 #define ENTT_ENTITY_GROUP_HPP
8 #include "../config/config.h"
9 #include "../core/type_traits.hpp"
13 #include "sparse_set.hpp"
14 #include "utility.hpp"
66 template<
typename Entity,
typename... Exclude,
typename... Get>
71 template<
typename Component>
77 class proxy_iterator {
78 friend class group_proxy;
81 using ref_type = decltype(std::tuple_cat(std::declval<std::conditional_t<is_eto_eligible_v<Get>, std::tuple<>, std::tuple<pool_type<Get> *>>>()...));
83 proxy_iterator(it_type from, ref_type ref) ENTT_NOEXCEPT
89 using difference_type = std::ptrdiff_t;
90 using value_type = decltype(std::tuple_cat(
91 std::declval<std::tuple<Entity>>(),
92 std::declval<std::conditional_t<is_eto_eligible_v<Get>, std::tuple<>, std::tuple<Get>>>()...
95 using reference = decltype(std::tuple_cat(
96 std::declval<std::tuple<Entity>>(),
97 std::declval<std::conditional_t<is_eto_eligible_v<Get>, std::tuple<>, std::tuple<Get &>>>()...
99 using iterator_category = std::input_iterator_tag;
101 proxy_iterator & operator++() ENTT_NOEXCEPT {
105 proxy_iterator operator++(
int) ENTT_NOEXCEPT {
106 proxy_iterator orig = *
this;
107 return ++(*this), orig;
110 [[nodiscard]] reference operator*()
const ENTT_NOEXCEPT {
111 return std::apply([
entt = *it](
auto *... cpool) {
return reference{
entt, cpool->get(
entt)...}; }, pools);
114 [[nodiscard]]
bool operator==(
const proxy_iterator &other)
const ENTT_NOEXCEPT {
115 return other.it == it;
118 [[nodiscard]]
bool operator!=(
const proxy_iterator &other)
const ENTT_NOEXCEPT {
119 return !(*
this == other);
127 group_proxy(
const sparse_set<Entity> &ref, std::tuple<pool_type<Get> *...> gpools)
133 using iterator = proxy_iterator;
135 [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
136 return proxy_iterator{handler->begin(), std::tuple_cat([](
auto *cpool) {
137 if constexpr(
is_eto_eligible_v<
typename std::decay_t<decltype(*cpool)>::object_type>) {
138 return std::make_tuple();
140 return std::make_tuple(cpool);
142 }(std::get<pool_type<Get> *>(pools))...)};
145 [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
146 return proxy_iterator{handler->end(), std::tuple_cat([](
auto *cpool) {
147 if constexpr(
is_eto_eligible_v<
typename std::decay_t<decltype(*cpool)>::object_type>) {
148 return std::make_tuple();
150 return std::make_tuple(cpool);
152 }(std::get<pool_type<Get> *>(pools))...)};
156 const sparse_set<Entity> *handler;
157 std::tuple<pool_type<Get> *...> pools;
160 basic_group(sparse_set<Entity> &ref, pool_type<Get> &... gpool) ENTT_NOEXCEPT
165 template<
typename Func,
typename... Weak>
166 void traverse(Func func, type_list<Weak...>)
const {
167 for(
const auto entt: *handler) {
168 if constexpr(std::is_invocable_v<Func, decltype(get<Weak>({}))...>) {
169 func(std::get<pool_type<Weak> *>(pools)->
get(
entt)...);
171 func(
entt, std::get<pool_type<Weak> *>(pools)->
get(
entt)...);
191 template<
typename Component>
193 return std::get<pool_type<Component> *>(pools)->size();
201 return handler->size();
210 return handler->capacity();
215 handler->shrink_to_fit();
223 template<
typename... Component>
224 [[nodiscard]]
bool empty() const ENTT_NOEXCEPT {
225 if constexpr(
sizeof...(Component) == 0) {
226 return handler->empty();
228 return (std::get<pool_type<Component> *>(pools)->empty() && ...);
246 template<
typename Component>
247 [[nodiscard]] Component *
raw() const ENTT_NOEXCEPT {
248 return std::get<pool_type<Component> *>(pools)->raw();
265 template<
typename Component>
267 return std::get<pool_type<Component> *>(pools)->data();
283 return handler->data();
299 return handler->begin();
317 return handler->end();
333 return handler->rbegin();
352 return handler->rend();
361 const auto it = begin();
362 return it != end() ? *it :
null;
371 const auto it = rbegin();
372 return it != rend() ? *it :
null;
382 const auto it = handler->find(
entt);
383 return it != end() && *it ==
entt ? it : end();
401 return handler->contains(
entt);
421 template<
typename... Component>
423 ENTT_ASSERT(contains(
entt));
425 if constexpr(
sizeof...(Component) == 1) {
426 return (std::get<pool_type<Component> *>(pools)->
get(
entt), ...);
428 return std::tuple<decltype(get<Component>({}))...>{get<Component>(
entt)...};
454 template<
typename Func>
457 traverse(std::move(func), get_type_list{});
473 [[nodiscard]]
auto proxy() const ENTT_NOEXCEPT {
474 return group_proxy{*handler, pools};
513 template<
typename... Component,
typename Compare,
typename Sort =
std_sort,
typename... Args>
514 void sort(Compare compare, Sort algo = Sort{}, Args &&... args) {
515 if constexpr(
sizeof...(Component) == 0) {
516 static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>,
"Invalid comparison function");
517 handler->sort(handler->begin(), handler->end(), std::move(compare), std::move(algo), std::forward<Args>(args)...);
518 }
else if constexpr(
sizeof...(Component) == 1) {
519 handler->sort(handler->begin(), handler->end(), [
this, compare = std::move(compare)](
const entity_type lhs,
const entity_type rhs) {
520 return compare((std::get<pool_type<Component> *>(pools)->get(lhs), ...), (std::get<pool_type<Component> *>(pools)->get(rhs), ...));
521 }, std::move(algo), std::forward<Args>(args)...);
523 handler->sort(handler->begin(), handler->end(), [
this, compare = std::move(compare)](
const entity_type lhs,
const entity_type rhs) {
524 return compare(std::tuple<decltype(get<Component>({}))...>{std::get<pool_type<Component> *>(pools)->
get(lhs)...}, std::tuple<decltype(get<Component>({}))...>{std::get<pool_type<Component> *>(pools)->
get(rhs)...});
525 }, std::move(algo), std::forward<Args>(args)...);
545 template<
typename Component>
547 handler->respect(*std::get<pool_type<Component> *>(pools));
552 const std::tuple<pool_type<Get> *...> pools;
602 template<
typename Entity,
typename... Exclude,
typename... Get,
typename... Owned>
607 template<
typename Component>
610 template<
typename Component>
611 using component_iterator = decltype(std::declval<pool_type<Component>>().begin());
616 class proxy_iterator {
617 friend class group_proxy;
620 using owned_type = decltype(std::tuple_cat(std::declval<std::conditional_t<is_eto_eligible_v<Owned>, std::tuple<>, std::tuple<component_iterator<Owned>>>>()...));
621 using get_type = decltype(std::tuple_cat(std::declval<std::conditional_t<is_eto_eligible_v<Get>, std::tuple<>, std::tuple<pool_type<Get> *>>>()...));
623 proxy_iterator(it_type from, owned_type oref, get_type gref) ENTT_NOEXCEPT
630 using difference_type = std::ptrdiff_t;
631 using value_type = decltype(std::tuple_cat(
632 std::declval<std::tuple<Entity>>(),
633 std::declval<std::conditional_t<is_eto_eligible_v<Owned>, std::tuple<>, std::tuple<Owned>>>()...,
634 std::declval<std::conditional_t<is_eto_eligible_v<Get>, std::tuple<>, std::tuple<Get>>>()...
636 using pointer = void;
637 using reference = decltype(std::tuple_cat(
638 std::declval<std::tuple<Entity>>(),
639 std::declval<std::conditional_t<is_eto_eligible_v<Owned>, std::tuple<>, std::tuple<Owned &>>>()...,
640 std::declval<std::conditional_t<is_eto_eligible_v<Get>, std::tuple<>, std::tuple<Get &>>>()...
642 using iterator_category = std::input_iterator_tag;
644 proxy_iterator & operator++() ENTT_NOEXCEPT {
645 return ++it, std::apply([](
auto &&... curr) { (++curr, ...); }, owned), *
this;
648 proxy_iterator operator++(
int) ENTT_NOEXCEPT {
649 proxy_iterator orig = *
this;
650 return ++(*this), orig;
653 [[nodiscard]] reference operator*()
const ENTT_NOEXCEPT {
654 return std::tuple_cat(
655 std::make_tuple(*it),
656 std::apply([](
auto &&... curr) {
return std::forward_as_tuple(*curr...); }, owned),
657 std::apply([
entt = *it](
auto &&... curr) {
return std::forward_as_tuple(curr->get(
entt)...); },
get)
661 [[nodiscard]]
bool operator==(
const proxy_iterator &other)
const ENTT_NOEXCEPT {
662 return other.it == it;
665 [[nodiscard]]
bool operator!=(
const proxy_iterator &other)
const ENTT_NOEXCEPT {
666 return !(*
this == other);
675 group_proxy(std::tuple<pool_type<Owned> *..., pool_type<Get> *...> cpools,
const std::size_t &extent)
683 [[nodiscard]]
iterator begin()
const ENTT_NOEXCEPT {
684 return proxy_iterator{
685 std::get<0>(pools)->sparse_set<Entity>::end() - *length,
686 std::tuple_cat([length = *length](
auto *cpool) {
687 if constexpr(
is_eto_eligible_v<
typename std::decay_t<decltype(*cpool)>::object_type>) {
688 return std::make_tuple();
690 return std::make_tuple(cpool->end() - length);
692 }(std::get<pool_type<Owned> *>(pools))...),
693 std::tuple_cat([](
auto *cpool) {
694 if constexpr(
is_eto_eligible_v<
typename std::decay_t<decltype(*cpool)>::object_type>) {
695 return std::make_tuple();
697 return std::make_tuple(cpool);
699 }(std::get<pool_type<Get> *>(pools))...)
703 [[nodiscard]]
iterator end()
const ENTT_NOEXCEPT {
704 return proxy_iterator{
705 std::get<0>(pools)->sparse_set<Entity>::end(),
706 std::tuple_cat([](
auto *cpool) {
707 if constexpr(
is_eto_eligible_v<
typename std::decay_t<decltype(*cpool)>::object_type>) {
708 return std::make_tuple();
710 return std::make_tuple(cpool->end());
712 }(std::get<pool_type<Owned> *>(pools))...),
713 std::tuple_cat([](
auto *cpool) {
714 if constexpr(
is_eto_eligible_v<
typename std::decay_t<decltype(*cpool)>::object_type>) {
715 return std::make_tuple();
717 return std::make_tuple(cpool);
719 }(std::get<pool_type<Get> *>(pools))...)
724 const std::tuple<pool_type<Owned> *..., pool_type<Get> *...> pools;
725 const std::size_t *length;
728 basic_group(
const std::size_t &extent, pool_type<Owned> &... opool, pool_type<Get> &... gpool) ENTT_NOEXCEPT
729 : pools{&opool..., &gpool...},
733 template<
typename Func,
typename... Strong,
typename... Weak>
735 [[maybe_unused]]
auto it = std::make_tuple((std::get<pool_type<Strong> *>(pools)->end() - *length)...);
736 [[maybe_unused]]
auto data = std::get<0>(pools)->sparse_set<entity_type>::end() - *length;
738 for(
auto next = *length; next; --next) {
739 if constexpr(std::is_invocable_v<Func, decltype(get<Strong>({}))..., decltype(get<Weak>({}))...>) {
740 if constexpr(
sizeof...(Weak) == 0) {
741 func(*(std::get<component_iterator<Strong>>(it)++)...);
743 const auto entt = *(data++);
744 func(*(std::get<component_iterator<Strong>>(it)++)..., std::get<pool_type<Weak> *>(pools)->
get(
entt)...);
747 const auto entt = *(data++);
748 func(
entt, *(std::get<component_iterator<Strong>>(it)++)..., std::get<pool_type<Weak> *>(pools)->
get(
entt)...);
768 template<
typename Component>
770 return std::get<pool_type<Component> *>(pools)->size();
786 template<
typename... Component>
787 [[nodiscard]]
bool empty() const ENTT_NOEXCEPT {
788 if constexpr(
sizeof...(Component) == 0) {
791 return (std::get<pool_type<Component> *>(pools)->empty() && ...);
812 template<
typename Component>
813 [[nodiscard]] Component *
raw() const ENTT_NOEXCEPT {
814 return std::get<pool_type<Component> *>(pools)->raw();
834 template<
typename Component>
836 return std::get<pool_type<Component> *>(pools)->data();
852 return std::get<0>(pools)->data();
868 return std::get<0>(pools)->sparse_set<entity_type>::end() - *length;
886 return std::get<0>(pools)->sparse_set<entity_type>::end();
902 return std::get<0>(pools)->sparse_set<entity_type>::rbegin();
921 return std::get<0>(pools)->sparse_set<entity_type>::rbegin() + *length;
930 const auto it = begin();
931 return it != end() ? *it :
null;
940 const auto it = rbegin();
941 return it != rend() ? *it :
null;
951 const auto it = std::get<0>(pools)->find(
entt);
952 return it != end() && it >= begin() && *it ==
entt ? it : end();
970 return std::get<0>(pools)->contains(
entt) && (std::get<0>(pools)->index(
entt) < (*length));
990 template<
typename... Component>
992 ENTT_ASSERT(contains(
entt));
994 if constexpr(
sizeof...(Component) == 1) {
995 return (std::get<pool_type<Component> *>(pools)->
get(
entt), ...);
997 return std::tuple<decltype(get<Component>({}))...>{get<Component>(
entt)...};
1023 template<
typename Func>
1027 traverse(std::move(func), owned_type_list{}, get_type_list{});
1043 [[nodiscard]]
auto proxy() const ENTT_NOEXCEPT {
1044 return group_proxy{pools, *length};
1084 template<
typename... Component,
typename Compare,
typename Sort =
std_sort,
typename... Args>
1085 void sort(Compare compare, Sort algo = Sort{}, Args &&... args) {
1086 auto *cpool = std::get<0>(pools);
1088 if constexpr(
sizeof...(Component) == 0) {
1089 static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>,
"Invalid comparison function");
1090 cpool->sort(cpool->end()-*length, cpool->end(), std::move(compare), std::move(algo), std::forward<Args>(args)...);
1091 }
else if constexpr(
sizeof...(Component) == 1) {
1092 cpool->sort(cpool->end()-*length, cpool->end(), [
this, compare = std::move(compare)](
const entity_type lhs,
const entity_type rhs) {
1093 return compare((std::get<pool_type<Component> *>(pools)->get(lhs), ...), (std::get<pool_type<Component> *>(pools)->get(rhs), ...));
1094 }, std::move(algo), std::forward<Args>(args)...);
1096 cpool->sort(cpool->end()-*length, cpool->end(), [
this, compare = std::move(compare)](
const entity_type lhs,
const entity_type rhs) {
1097 return compare(std::tuple<decltype(get<Component>({}))...>{std::get<pool_type<Component> *>(pools)->
get(lhs)...}, std::tuple<decltype(get<Component>({}))...>{std::get<pool_type<Component> *>(pools)->
get(rhs)...});
1098 }, std::move(algo), std::forward<Args>(args)...);
1101 [
this](
auto *head,
auto *... other) {
1102 for(
auto next = *length; next; --next) {
1103 const auto pos = next - 1;
1104 [[maybe_unused]]
const auto entt = head->data()[pos];
1105 (other->swap(other->data()[pos],
entt), ...);
1107 }(std::get<pool_type<Owned> *>(pools)...);
1111 const std::tuple<pool_type<Owned> *..., pool_type<Get> *...> pools;
1112 const size_type *length;