1 #ifndef ENTT_ENTITY_VIEW_HPP
2 #define ENTT_ENTITY_VIEW_HPP
10 #include "../config/config.h"
11 #include "../core/iterator.hpp"
12 #include "../core/type_traits.hpp"
13 #include "component.hpp"
16 #include "sparse_set.hpp"
17 #include "storage.hpp"
18 #include "utility.hpp"
29 template<
typename Type, std::
size_t Component, std::
size_t Exclude>
30 class view_iterator final {
31 using iterator_type =
typename Type::const_iterator;
33 [[nodiscard]]
bool valid() const ENTT_NOEXCEPT {
34 return ((Component != 0u) || (*it !=
tombstone))
35 && std::apply([
entt = *it](
const auto *...curr) {
return (curr->contains(
entt) && ...); }, pools)
36 && std::apply([
entt = *it](
const auto *...curr) {
return (!curr->contains(
entt) && ...); }, filter);
40 using value_type =
typename iterator_type::value_type;
41 using pointer =
typename iterator_type::pointer;
42 using reference =
typename iterator_type::reference;
43 using difference_type =
typename iterator_type::difference_type;
44 using iterator_category = std::forward_iterator_tag;
46 view_iterator() ENTT_NOEXCEPT = default;
48 view_iterator(iterator_type curr, iterator_type to, std::array<const Type *, Component> all_of, std::array<const Type *, Exclude> none_of) ENTT_NOEXCEPT
53 if(it != last && !valid()) {
58 view_iterator &operator++() ENTT_NOEXCEPT {
59 while(++it != last && !valid()) {}
63 view_iterator operator++(
int) ENTT_NOEXCEPT {
64 view_iterator orig = *
this;
65 return ++(*this), orig;
68 [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
72 [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
76 template<
typename LhsType,
auto... LhsArgs,
typename RhsType,
auto... RhsArgs>
77 friend bool operator==(
const view_iterator<LhsType, LhsArgs...> &,
const view_iterator<RhsType, RhsArgs...> &) ENTT_NOEXCEPT;
82 std::array<const Type *, Component> pools;
83 std::array<const Type *, Exclude> filter;
86 template<
typename LhsType,
auto... LhsArgs,
typename RhsType,
auto... RhsArgs>
87 [[nodiscard]]
bool operator==(
const view_iterator<LhsType, LhsArgs...> &lhs,
const view_iterator<RhsType, RhsArgs...> &rhs) ENTT_NOEXCEPT {
88 return lhs.it == rhs.it;
91 template<
typename LhsType,
auto... LhsArgs,
typename RhsType,
auto... RhsArgs>
92 [[nodiscard]]
bool operator!=(
const view_iterator<LhsType, LhsArgs...> &lhs,
const view_iterator<RhsType, RhsArgs...> &rhs) ENTT_NOEXCEPT {
96 template<
typename It,
typename... Storage>
97 struct extended_view_iterator final {
98 using difference_type = std::ptrdiff_t;
99 using value_type = decltype(std::tuple_cat(std::make_tuple(*std::declval<It>()), std::declval<Storage>().get_as_tuple({})...));
100 using pointer = input_iterator_pointer<value_type>;
101 using reference = value_type;
102 using iterator_category = std::input_iterator_tag;
104 extended_view_iterator() =
default;
106 extended_view_iterator(It from, std::tuple<Storage *...>
storage)
110 extended_view_iterator &operator++() ENTT_NOEXCEPT {
114 extended_view_iterator operator++(
int) ENTT_NOEXCEPT {
115 extended_view_iterator orig = *
this;
116 return ++(*this), orig;
119 [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
120 return std::apply([
entt = *it](
auto *...curr) {
return std::tuple_cat(std::make_tuple(
entt), curr->get_as_tuple(
entt)...); }, pools);
123 [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
127 template<
typename... Lhs,
typename... Rhs>
128 friend bool operator==(
const extended_view_iterator<Lhs...> &,
const extended_view_iterator<Rhs...> &) ENTT_NOEXCEPT;
132 std::tuple<Storage *...> pools;
135 template<
typename... Lhs,
typename... Rhs>
136 [[nodiscard]]
bool operator==(
const extended_view_iterator<Lhs...> &lhs,
const extended_view_iterator<Rhs...> &rhs) ENTT_NOEXCEPT {
137 return lhs.it == rhs.it;
140 template<
typename... Lhs,
typename... Rhs>
141 [[nodiscard]]
bool operator!=(
const extended_view_iterator<Lhs...> &lhs,
const extended_view_iterator<Rhs...> &rhs) ENTT_NOEXCEPT {
142 return !(lhs == rhs);
158 template<
typename,
typename,
typename,
typename>
185 template<
typename Entity,
typename... Component,
typename... Exclude>
187 template<
typename,
typename,
typename,
typename>
190 template<
typename Comp>
193 template<std::size_t... Index>
194 [[nodiscard]]
auto pools_to_array(std::index_sequence<Index...>)
const ENTT_NOEXCEPT {
196 std::array<
const base_type *,
sizeof...(Component) - 1u> other{};
197 (
static_cast<void>(std::get<Index>(pools) ==
view ? void() : void(other[pos++] = std::get<Index>(pools))), ...);
201 template<std::size_t Comp, std::size_t Other,
typename... Args>
202 [[nodiscard]]
auto dispatch_get(
const std::tuple<Entity, Args...> &curr)
const {
203 if constexpr(Comp == Other) {
204 return std::forward_as_tuple(std::get<Args>(curr)...);
206 return std::get<Other>(pools)->get_as_tuple(std::get<0>(curr));
210 template<std::size_t Comp,
typename Func, std::size_t... Index>
211 void each(Func func, std::index_sequence<Index...>)
const {
212 for(
const auto curr: std::get<Comp>(pools)->each()) {
213 const auto entt = std::get<0>(curr);
216 && ((Comp == Index || std::get<Index>(pools)->contains(
entt)) && ...)
217 && std::apply([
entt](
const auto *...cpool) {
return (!cpool->contains(
entt) && ...); }, filter)) {
218 if constexpr(
is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_view>().get({})))>) {
219 std::apply(func, std::tuple_cat(std::make_tuple(
entt), dispatch_get<Comp, Index>(curr)...));
221 std::apply(func, std::tuple_cat(dispatch_get<Comp, Index>(curr)...));
227 template<
typename Func, std::size_t... Index>
228 void pick_and_each(Func func, std::index_sequence<Index...> seq)
const {
229 ((std::get<Index>(pools) ==
view ? each<Index>(std::move(func), seq) : void()), ...);
238 using base_type = std::common_type_t<typename storage_type<Component>::base_type...>;
240 using iterator = internal::view_iterator<
base_type,
sizeof...(Component) - 1u,
sizeof...(Exclude)>;
255 basic_view(storage_type<Component> &...component,
const storage_type<Exclude> &...epool) ENTT_NOEXCEPT
256 : pools{&component...},
258 view{(std::min)({&
static_cast<const base_type &
>(component)...}, [](
auto *lhs,
auto *rhs) {
return lhs->size() < rhs->size(); })} {}
265 template<
typename Comp>
268 other.view = std::get<storage_type<Comp> *>(pools);
277 template<std::
size_t Comp>
280 other.view = std::get<Comp>(pools);
297 template<
typename Comp>
298 [[nodiscard]] decltype(
auto)
storage() const ENTT_NOEXCEPT {
299 return *std::get<storage_type<Comp> *>(pools);
307 template<std::
size_t Comp>
308 [[nodiscard]] decltype(
auto)
storage() const ENTT_NOEXCEPT {
309 return *std::get<Comp>(pools);
329 return iterator{
view->begin(),
view->end(), pools_to_array(std::index_sequence_for<Component...>{}), filter};
342 return iterator{
view->end(),
view->end(), pools_to_array(std::index_sequence_for<Component...>{}), filter};
351 const auto it = begin();
352 return it != end() ? *it :
null;
361 auto it =
view->rbegin();
362 for(
const auto last =
view->rend(); it != last && !contains(*it); ++it) {}
363 return it ==
view->rend() ?
null : *it;
373 return contains(
entt) ?
iterator{
view->find(
entt),
view->end(), pools_to_array(std::index_sequence_for<Component...>{}), filter} : end();
382 return get<Component...>(
entt);
389 [[nodiscard]]
explicit operator bool() const ENTT_NOEXCEPT {
390 return view !=
nullptr;
399 return std::apply([
entt](
const auto *...curr) {
return (curr->contains(
entt) && ...); }, pools)
400 && std::apply([
entt](
const auto *...curr) {
return (!curr->contains(
entt) && ...); }, filter);
414 template<
typename... Comp>
416 ENTT_ASSERT(contains(
entt),
"View does not contain entity");
418 if constexpr(
sizeof...(Comp) == 0) {
419 return std::apply([
entt](
auto *...curr) {
return std::tuple_cat(curr->get_as_tuple(
entt)...); }, pools);
420 }
else if constexpr(
sizeof...(Comp) == 1) {
421 return (std::get<storage_type<Comp> *>(pools)->
get(
entt), ...);
423 return std::tuple_cat(std::get<storage_type<Comp> *>(pools)->get_as_tuple(
entt)...);
439 template<std::size_t First, std::size_t... Other>
441 ENTT_ASSERT(contains(
entt),
"View does not contain entity");
443 if constexpr(
sizeof...(Other) == 0) {
444 return std::get<First>(pools)->get(
entt);
446 return std::tuple_cat(std::get<First>(pools)->get_as_tuple(
entt), std::get<Other>(pools)->get_as_tuple(
entt)...);
468 template<
typename Func>
470 pick_and_each(std::move(func), std::index_sequence_for<Component...>{});
483 return {internal::extended_view_iterator{begin(), pools}, internal::extended_view_iterator{end(), pools}};
493 template<
typename... Get,
typename... Excl>
496 return std::make_from_tuple<view_type>(std::tuple_cat(
497 std::apply([](
auto *...curr) {
return std::forward_as_tuple(*curr...); }, pools),
498 std::apply([](
auto *...curr) {
return std::forward_as_tuple(*curr...); }, other.pools),
499 std::apply([](
const auto *...curr) {
return std::forward_as_tuple(
static_cast<const storage_type<Exclude> &
>(*curr)...); }, filter),
500 std::apply([](
const auto *...curr) {
return std::forward_as_tuple(
static_cast<const storage_type<Excl> &
>(*curr)...); }, other.filter)));
504 std::tuple<storage_type<Component> *...> pools;
505 std::array<
const base_type *,
sizeof...(Exclude)> filter;
506 const base_type *
view;
531 template<
typename Entity,
typename Component>
532 class basic_view<Entity,
get_t<Component>,
exclude_t<>, std::void_t<std::enable_if_t<!component_traits<std::remove_const_t<Component>>::in_place_delete>>> {
533 template<
typename,
typename,
typename,
typename>
550 using iterable = decltype(std::declval<storage_type>().each());
580 template<
typename Comp = Component>
581 [[nodiscard]] decltype(
auto)
storage() const ENTT_NOEXCEPT {
582 static_assert(std::is_same_v<Comp, Component>,
"Invalid component type");
583 return *std::get<0>(pools);
591 template<std::
size_t Comp>
592 [[nodiscard]] decltype(
auto)
storage() const ENTT_NOEXCEPT {
593 return *std::get<Comp>(pools);
608 [[nodiscard]]
bool empty() const ENTT_NOEXCEPT {
609 return view->empty();
621 return view->begin();
646 return view->rbegin();
670 return empty() ?
null : *begin();
679 return empty() ?
null : *rbegin();
707 return get<Component>(
entt);
714 [[nodiscard]]
explicit operator bool() const ENTT_NOEXCEPT {
715 return view !=
nullptr;
738 template<
typename... Comp>
740 ENTT_ASSERT(contains(
entt),
"View does not contain entity");
742 if constexpr(
sizeof...(Comp) == 0) {
743 return std::get<0>(pools)->get_as_tuple(
entt);
745 static_assert(std::is_same_v<Comp..., Component>,
"Invalid component type");
746 return std::get<0>(pools)->get(
entt);
751 template<std::
size_t Comp>
753 ENTT_ASSERT(contains(
entt),
"View does not contain entity");
754 return std::get<0>(pools)->get(
entt);
775 template<
typename Func>
778 for(
const auto pack: each()) {
779 std::apply(func, pack);
781 }
else if constexpr(std::is_invocable_v<Func, Component &>) {
782 for(
auto &&component: *std::get<0>(pools)) {
785 }
else if constexpr(std::is_invocable_v<Func, Entity>) {
790 for(
size_type pos{}, last = size(); pos < last; ++pos) {
806 return std::get<0>(pools)->each();
816 template<
typename... Get,
typename... Excl>
819 return std::make_from_tuple<view_type>(std::tuple_cat(
820 std::forward_as_tuple(*std::get<0>(pools)),
821 std::apply([](
auto *...curr) {
return std::forward_as_tuple(*curr...); }, other.pools),
822 std::apply([](
const auto *...curr) {
return std::forward_as_tuple(
static_cast<const typename view_type::template storage_type<Excl> &
>(*curr)...); }, other.filter)));
826 std::tuple<storage_type *> pools;
827 std::array<const base_type *, 0u> filter;
828 const base_type *
view;
836 template<
typename... Storage>
Basic storage implementation.
iterator end() const
Returns an iterator that is past the last entity of the view.
std::size_t size_type
Unsigned integer type.
auto operator|(const basic_view< Entity, get_t< Get... >, exclude_t< Excl... >> &other) const
Combines two views in a more specific one (friend function).
void each(Func func) const
Iterates entities and components and applies the given function object to them.
entity_type back() const
Returns the last entity of the view, if any.
reverse_iterator rbegin() const
Returns an iterator to the first entity of the reversed view.
entity_type front() const
Returns the first entity of the view, if any.
reverse_iterator rend() const
Returns an iterator that is past the last entity of the reversed view.
iterator find(const entity_type entt) const
Finds an entity.
basic_view(storage_type &ref)
Constructs a single-type view from a storage class.
iterator begin() const
Returns an iterator to the first entity of the view.
size_type size() const
Returns the number of entities that have the given component.
typename base_type::iterator iterator
Random access iterator type.
basic_view()
Default constructor to use to create empty, invalid views.
decltype(std::declval< storage_type >().each()) iterable
Iterable view type.
bool empty() const
Checks whether a view is empty.
Entity entity_type
Underlying entity identifier.
entity_type operator[](const size_type pos) const
Returns the identifier that occupies the given position.
const base_type & handle() const
Returns the leading storage of a view.
bool contains(const entity_type entt) const
Checks if a view contains an entity.
iterable each() const
Returns an iterable object to use to visit a view.
typename base_type::reverse_iterator reverse_iterator
Reversed iterator type.
typename storage_type::base_type base_type
Common type among all storage types.
const base_type & handle() const
Returns the leading storage of a view.
basic_view()
Default constructor to use to create empty, invalid views.
iterator find(const entity_type entt) const
Finds an entity.
Entity entity_type
Underlying entity identifier.
entity_type back() const
Returns the last entity of the view, if any.
iterator end() const
Returns an iterator that is past the last entity of the view.
iterator begin() const
Returns an iterator to the first entity of the view.
auto operator|(const basic_view< Entity, get_t< Get... >, exclude_t< Excl... >> &other) const
Combines two views in a more specific one (friend function).
internal::view_iterator< base_type, sizeof...(Component) - 1u, sizeof...(Exclude)> iterator
Bidirectional iterator type.
std::size_t size_type
Unsigned integer type.
iterable each() const
Returns an iterable object to use to visit a view.
basic_view use() const
Creates a new view driven by a given component in its iterations.
entity_type front() const
Returns the first entity of the view, if any.
std::common_type_t< typename storage_type< Component >::base_type... > base_type
Common type among all storage types.
bool contains(const entity_type entt) const
Checks if a view contains an entity.
void each(Func func) const
Iterates entities and components and applies the given function object to them.
size_type size_hint() const
Estimates the number of entities iterated by the view.
basic_view(storage_type< Component > &...component, const storage_type< Exclude > &...epool)
Constructs a multi-type view from a set of storage classes.
constexpr bool operator==(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs)
Compares two hashed strings.
entity
Default entity identifier.
basic_view(Storage &...storage) -> basic_view< std::common_type_t< typename Storage::entity_type... >, get_t< constness_as_t< typename Storage::value_type, Storage >... >, exclude_t<>>
Deduction guide.
constexpr null_t null
Compile-time constant for null entities.
constexpr bool is_applicable_v
Helper variable template.
constexpr tombstone_t tombstone
Compile-time constant for tombstone entities.
typename constness_as< To, From >::type constness_as_t
Alias template to facilitate the transcription of the constness.
basic_view< entity, Get, Exclude > view
Alias declaration for the most common use case.
constexpr get_t< Type... > get
Variable template for lists of observed components.
basic_storage< entity, Args... > storage
Alias declaration for the most common use case.
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.