1 #ifndef ENTT_ENTITY_GROUP_HPP
2 #define ENTT_ENTITY_GROUP_HPP
7 #include "../config/config.h"
8 #include "../core/iterator.hpp"
9 #include "../core/type_traits.hpp"
10 #include "component.hpp"
13 #include "sparse_set.hpp"
14 #include "storage.hpp"
15 #include "utility.hpp"
25 template<
typename,
typename,
typename,
typename>
64 template<
typename Entity,
typename... Get,
typename... Exclude>
69 template<
typename Comp>
72 using basic_common_type = std::common_type_t<typename storage_type<Get>::base_type...>;
74 struct extended_group_iterator final {
75 using difference_type = std::ptrdiff_t;
76 using value_type = decltype(std::tuple_cat(std::tuple<Entity>{}, std::declval<basic_group>().get({})));
78 using reference = value_type;
79 using iterator_category = std::input_iterator_tag;
81 extended_group_iterator() =
default;
83 extended_group_iterator(
typename basic_common_type::iterator from,
const std::tuple<storage_type<Get> *...> &args)
87 extended_group_iterator &operator++() ENTT_NOEXCEPT {
91 extended_group_iterator operator++(
int) ENTT_NOEXCEPT {
92 extended_group_iterator orig = *
this;
93 return ++(*this), orig;
96 [[nodiscard]] reference operator*()
const ENTT_NOEXCEPT {
97 const auto entt = *it;
98 return std::tuple_cat(std::make_tuple(
entt), std::get<storage_type<Get> *>(pools)->get_as_tuple(
entt)...);
101 [[nodiscard]] pointer operator->()
const ENTT_NOEXCEPT {
105 [[nodiscard]]
bool operator==(
const extended_group_iterator &other)
const ENTT_NOEXCEPT {
106 return other.it == it;
109 [[nodiscard]]
bool operator!=(
const extended_group_iterator &other)
const ENTT_NOEXCEPT {
110 return !(*
this == other);
114 typename basic_common_type::iterator it;
115 std::tuple<storage_type<Get> *...> pools;
118 basic_group(basic_common_type &ref, storage_type<Get> &...gpool) ENTT_NOEXCEPT
153 template<
typename Comp>
154 [[nodiscard]] decltype(
auto)
storage() const ENTT_NOEXCEPT {
155 return *std::get<storage_type<Comp> *>(pools);
163 template<std::
size_t Comp>
164 [[nodiscard]] decltype(
auto)
storage() const ENTT_NOEXCEPT {
165 return *std::get<Comp>(pools);
173 return *
this ? handler->size() :
size_type{};
182 return *
this ? handler->capacity() :
size_type{};
188 handler->shrink_to_fit();
196 [[nodiscard]]
bool empty() const ENTT_NOEXCEPT {
197 return !*
this || handler->empty();
209 return *
this ? handler->begin() :
iterator{};
223 return *
this ? handler->end() :
iterator{};
259 const auto it = begin();
260 return it != end() ? *it :
null;
269 const auto it = rbegin();
270 return it != rend() ? *it :
null;
280 const auto it = *
this ? handler->find(
entt) :
iterator{};
281 return it != end() && *it ==
entt ? it : end();
297 [[nodiscard]]
explicit operator bool() const ENTT_NOEXCEPT {
298 return handler !=
nullptr;
307 return *
this && handler->contains(
entt);
325 template<
typename... Comp>
327 ENTT_ASSERT(contains(
entt),
"Group does not contain entity");
329 if constexpr(
sizeof...(Comp) == 0) {
330 return std::tuple_cat(std::get<storage_type<Get> *>(pools)->get_as_tuple(
entt)...);
331 }
else if constexpr(
sizeof...(Comp) == 1) {
332 return (std::get<storage_type<Comp> *>(pools)->
get(
entt), ...);
334 return std::tuple_cat(std::get<storage_type<Comp> *>(pools)->get_as_tuple(
entt)...);
360 template<
typename Func>
362 for(
const auto entt: *
this) {
363 if constexpr(
is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_group>().get({})))>) {
364 std::apply(func, std::tuple_cat(std::make_tuple(
entt),
get(
entt)));
385 return handler ?
iterable{extended_group_iterator{handler->
begin(), pools}, extended_group_iterator{handler->end(), pools}}
386 :
iterable{extended_group_iterator{{}, pools}, extended_group_iterator{{}, pools}};
425 template<
typename... Comp,
typename Compare,
typename Sort =
std_sort,
typename... Args>
426 void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
428 if constexpr(
sizeof...(Comp) == 0) {
429 static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>,
"Invalid comparison function");
430 handler->sort(std::move(compare), std::move(algo), std::forward<Args>(args)...);
432 auto comp = [
this, &compare](
const entity_type lhs,
const entity_type rhs) {
433 if constexpr(
sizeof...(Comp) == 1) {
434 return compare((std::get<storage_type<Comp> *>(pools)->
get(lhs), ...), (std::get<storage_type<Comp> *>(pools)->
get(rhs), ...));
436 return compare(std::forward_as_tuple(std::get<storage_type<Comp> *>(pools)->
get(lhs)...), std::forward_as_tuple(std::get<storage_type<Comp> *>(pools)->
get(rhs)...));
440 handler->sort(std::move(comp), std::move(algo), std::forward<Args>(args)...);
461 template<
typename Comp>
464 handler->respect(*std::get<storage_type<Comp> *>(pools));
469 base_type *
const handler;
470 const std::tuple<storage_type<Get> *...> pools;
519 template<
typename Entity,
typename... Owned,
typename... Get,
typename... Exclude>
524 template<
typename Comp>
527 using basic_common_type = std::common_type_t<typename storage_type<Owned>::base_type...,
typename storage_type<Get>::base_type...>;
529 class extended_group_iterator final {
530 template<
typename Type>
531 auto index_to_element(storage_type<Type> &cpool)
const {
533 return std::make_tuple();
535 return std::forward_as_tuple(cpool.rbegin()[it.index()]);
540 using difference_type = std::ptrdiff_t;
541 using value_type = decltype(std::tuple_cat(std::tuple<Entity>{}, std::declval<basic_group>().get({})));
543 using reference = value_type;
544 using iterator_category = std::input_iterator_tag;
546 extended_group_iterator() =
default;
548 template<
typename... Other>
549 extended_group_iterator(
typename basic_common_type::iterator from,
const std::tuple<storage_type<Owned> *..., storage_type<Get> *...> &cpools)
553 extended_group_iterator &operator++() ENTT_NOEXCEPT {
557 extended_group_iterator operator++(
int) ENTT_NOEXCEPT {
558 extended_group_iterator orig = *
this;
559 return ++(*this), orig;
562 [[nodiscard]] reference operator*()
const ENTT_NOEXCEPT {
563 return std::tuple_cat(
564 std::make_tuple(*it),
565 index_to_element<Owned>(*std::get<storage_type<Owned> *>(pools))...,
566 std::get<storage_type<Get> *>(pools)->get_as_tuple(*it)...);
569 [[nodiscard]] pointer operator->()
const ENTT_NOEXCEPT {
573 [[nodiscard]]
bool operator==(
const extended_group_iterator &other)
const ENTT_NOEXCEPT {
574 return other.it == it;
577 [[nodiscard]]
bool operator!=(
const extended_group_iterator &other)
const ENTT_NOEXCEPT {
578 return !(*
this == other);
582 typename basic_common_type::iterator it;
583 std::tuple<storage_type<Owned> *..., storage_type<Get> *...> pools;
586 basic_group(
const std::size_t &extent, storage_type<Owned> &...opool, storage_type<Get> &...gpool) ENTT_NOEXCEPT
587 : pools{&opool..., &gpool...},
613 template<
typename Comp>
614 [[nodiscard]] decltype(
auto)
storage() const ENTT_NOEXCEPT {
615 return *std::get<storage_type<Comp> *>(pools);
623 template<std::
size_t Comp>
624 [[nodiscard]] decltype(
auto)
storage() const ENTT_NOEXCEPT {
625 return *std::get<Comp>(pools);
640 [[nodiscard]]
bool empty() const ENTT_NOEXCEPT {
641 return !*
this || !*length;
653 return *
this ? (std::get<0>(pools)->base_type::end() - *length) :
iterator{};
667 return *
this ? std::get<0>(pools)->base_type::end() :
iterator{};
679 return *
this ? std::get<0>(pools)->base_type::rbegin() :
reverse_iterator{};
694 return *
this ? (std::get<0>(pools)->base_type::rbegin() + *length) :
reverse_iterator{};
703 const auto it = begin();
704 return it != end() ? *it :
null;
713 const auto it = rbegin();
714 return it != rend() ? *it :
null;
724 const auto it = *
this ? std::get<0>(pools)->find(
entt) :
iterator{};
725 return it != end() && it >= begin() && *it ==
entt ? it : end();
741 [[nodiscard]]
explicit operator bool() const ENTT_NOEXCEPT {
742 return length !=
nullptr;
751 return *
this && std::get<0>(pools)->contains(
entt) && (std::get<0>(pools)->index(
entt) < (*length));
769 template<
typename... Comp>
771 ENTT_ASSERT(contains(
entt),
"Group does not contain entity");
773 if constexpr(
sizeof...(Comp) == 0) {
774 return std::tuple_cat(std::get<storage_type<Owned> *>(pools)->get_as_tuple(
entt)..., std::get<storage_type<Get> *>(pools)->get_as_tuple(
entt)...);
775 }
else if constexpr(
sizeof...(Comp) == 1) {
776 return (std::get<storage_type<Comp> *>(pools)->
get(
entt), ...);
778 return std::tuple_cat(std::get<storage_type<Comp> *>(pools)->get_as_tuple(
entt)...);
804 template<
typename Func>
806 for(
auto args: each()) {
807 if constexpr(
is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_group>().get({})))>) {
808 std::apply(func, args);
810 std::apply([&func](
auto,
auto &&...less) { func(std::forward<decltype(less)>(less)...); }, args);
829 iterator last = length ? std::get<0>(pools)->basic_common_type::end() :
iterator{};
830 return {extended_group_iterator{last - *length, pools}, extended_group_iterator{last, pools}};
870 template<
typename... Comp,
typename Compare,
typename Sort =
std_sort,
typename... Args>
871 void sort(Compare compare, Sort algo = Sort{}, Args &&...args)
const {
872 auto *cpool = std::get<0>(pools);
874 if constexpr(
sizeof...(Comp) == 0) {
875 static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>,
"Invalid comparison function");
876 cpool->sort_n(*length, std::move(compare), std::move(algo), std::forward<Args>(args)...);
878 auto comp = [
this, &compare](
const entity_type lhs,
const entity_type rhs) {
879 if constexpr(
sizeof...(Comp) == 1) {
880 return compare((std::get<storage_type<Comp> *>(pools)->
get(lhs), ...), (std::get<storage_type<Comp> *>(pools)->
get(rhs), ...));
882 return compare(std::forward_as_tuple(std::get<storage_type<Comp> *>(pools)->
get(lhs)...), std::forward_as_tuple(std::get<storage_type<Comp> *>(pools)->
get(rhs)...));
886 cpool->sort_n(*length, std::move(comp), std::move(algo), std::forward<Args>(args)...);
889 [
this](
auto *head,
auto *...other) {
890 for(
auto next = *length; next; --next) {
891 const auto pos = next - 1;
892 [[maybe_unused]]
const auto entt = head->data()[pos];
893 (other->swap_elements(other->data()[pos],
entt), ...);
895 }(std::get<storage_type<Owned> *>(pools)...);
899 const std::tuple<storage_type<Owned> *..., storage_type<Get> *...> pools;
900 const size_type *
const length;
Entity entity_type
Underlying entity identifier.
basic_common_type base_type
Common type among all storage types.
entity_type front() const
Returns the first entity of the group, if any.
size_type size() const
Returns the number of entities that have the given components.
typename base_type::iterator iterator
Random access iterator type.
iterator begin() const
Returns an iterator to the first entity of the group.
iterator end() const
Returns an iterator that is past the last entity of the group.
void each(Func func) const
Iterates entities and components and applies the given function object to them.
iterable each() const
Returns an iterable object to use to visit a group.
entity_type back() const
Returns the last entity of the group, if any.
typename base_type::reverse_iterator reverse_iterator
Reversed iterator type.
reverse_iterator rbegin() const
Returns an iterator to the first entity of the reversed group.
std::size_t size_type
Unsigned integer type.
bool contains(const entity_type entt) const
Checks if a group contains an entity.
reverse_iterator rend() const
Returns an iterator that is past the last entity of the reversed group.
void sort(Compare compare, Sort algo=Sort{}, Args &&...args) const
Sort a group according to the given comparison function.
iterator find(const entity_type entt) const
Finds an entity.
bool empty() const
Checks whether a group is empty.
basic_group()
Default constructor to use to create empty, invalid groups.
entity_type operator[](const size_type pos) const
Returns the identifier that occupies the given position.
entity_type back() const
Returns the last entity of the group, if any.
iterable each() const
Returns an iterable object to use to visit a group.
basic_common_type base_type
Common type among all storage types.
basic_group()
Default constructor to use to create empty, invalid groups.
reverse_iterator rend() const
Returns an iterator that is past the last entity of the reversed group.
size_type size() const
Returns the number of entities that have the given components.
void shrink_to_fit()
Requests the removal of unused capacity.
const base_type & handle() const
Returns a const reference to the underlying handler.
bool contains(const entity_type entt) const
Checks if a group contains an entity.
entity_type front() const
Returns the first entity of the group, if any.
void sort(Compare compare, Sort algo=Sort{}, Args &&...args)
Sort a group according to the given comparison function.
typename base_type::iterator iterator
Random access iterator type.
entity_type operator[](const size_type pos) const
Returns the identifier that occupies the given position.
iterator end() const
Returns an iterator that is past the last entity of the group.
std::size_t size_type
Unsigned integer type.
iterator find(const entity_type entt) const
Finds an entity.
bool empty() const
Checks whether a group is empty.
void sort() const
Sort the shared pool of entities according to the given component.
reverse_iterator rbegin() const
Returns an iterator to the first entity of the reversed group.
size_type capacity() const
Returns the number of elements that a group has currently allocated space for.
iterator begin() const
Returns an iterator to the first entity of the group.
Entity entity_type
Underlying entity identifier.
void each(Func func) const
Iterates entities and components and applies the given function object to them.
typename base_type::reverse_iterator reverse_iterator
Reversed iterator type.
Fast and reliable entity-component system.
Basic storage implementation.
constexpr bool operator==(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs)
Compares two hashed strings.
constexpr bool is_applicable_v
Helper variable template.
typename constness_as< To, From >::type constness_as_t
Alias template to facilitate the transcription of the constness.
constexpr get_t< Type... > get
Variable template for lists of observed components.
constexpr bool ignore_as_empty_v
Helper variable template.
bool operator!=(const basic_any< Len, Align > &lhs, const basic_any< Len, Align > &rhs)
Checks if two wrappers differ in their content.
Alias for exclusion lists.
Alias for lists of observed components.
Utility class to create an iterable object from a pair of iterators.
iterator begin() const
Returns an iterator to the beginning.
Alias for lists of owned components.
Function object to wrap std::sort in a class type.