1#ifndef ENTT_ENTITY_VIEW_HPP
2#define ENTT_ENTITY_VIEW_HPP
9#include "../config/config.h"
10#include "../core/iterator.hpp"
11#include "../core/type_traits.hpp"
20template<
typename Type,
typename Entity>
21[[nodiscard]]
bool all_of_but(
const std::size_t index,
const Type *
const *it,
const std::size_t len,
const Entity
entt)
noexcept {
23 for(; (pos != index) && it[pos]->contains(
entt); ++pos) {}
26 for(++pos; (pos != len) && it[pos]->contains(
entt); ++pos) {}
32template<
typename Type,
typename Entity>
33[[nodiscard]]
bool none_of(
const Type *
const *it,
const std::size_t len,
const Entity
entt)
noexcept {
35 for(; (pos != len) && !(it[pos] && it[pos]->contains(
entt)); ++pos) {}
39template<
typename Type>
40[[nodiscard]]
bool fully_initialized(
const Type *
const *it,
const std::size_t len)
noexcept {
42 for(; (pos != len) && it[pos]; ++pos) {}
46template<
typename Result,
typename View,
typename Other, std::size_t... VGet, std::size_t... VExclude, std::size_t... OGet, std::size_t... OExclude>
47[[nodiscard]] Result view_pack(
const View &view,
const Other &other, std::index_sequence<VGet...>, std::index_sequence<VExclude...>, std::index_sequence<OGet...>, std::index_sequence<OExclude...>) {
50 elem.pools = {
view.template storage<VGet>()..., other.template storage<OGet>()...};
51 elem.filter = {
view.template
storage<
sizeof...(VGet) + VExclude>()..., other.template
storage<
sizeof...(OGet) + OExclude>()...};
56template<
typename Type, std::
size_t Get, std::
size_t Exclude>
57class view_iterator final {
58 using iterator_type =
typename Type::const_iterator;
60 [[nodiscard]]
bool valid(
const typename iterator_type::value_type
entt)
const noexcept {
61 return ((Get != 1u) || (
entt != tombstone)) && all_of_but(index, pools.data(), Get,
entt) && none_of(filter.data(), Exclude,
entt);
65 using value_type =
typename iterator_type::value_type;
66 using pointer =
typename iterator_type::pointer;
67 using reference =
typename iterator_type::reference;
68 using difference_type =
typename iterator_type::difference_type;
69 using iterator_category = std::forward_iterator_tag;
71 constexpr view_iterator() noexcept
78 view_iterator(iterator_type curr, iterator_type to, std::array<const Type *, Get> value, std::array<const Type *, Exclude> excl,
const std::size_t idx) noexcept
84 while(it != last && !valid(*it)) {
89 view_iterator &operator++() noexcept {
90 while(++it != last && !valid(*it)) {}
94 view_iterator operator++(
int)
noexcept {
95 view_iterator orig = *
this;
96 return ++(*this), orig;
99 [[nodiscard]] pointer operator->() const noexcept {
103 [[nodiscard]] reference operator*() const noexcept {
104 return *operator->();
107 template<
typename LhsType,
auto... LhsArgs,
typename RhsType,
auto... RhsArgs>
108 friend constexpr bool operator==(
const view_iterator<LhsType, LhsArgs...> &,
const view_iterator<RhsType, RhsArgs...> &)
noexcept;
113 std::array<const Type *, Get> pools;
114 std::array<const Type *, Exclude> filter;
118template<
typename LhsType,
auto... LhsArgs,
typename RhsType,
auto... RhsArgs>
119[[nodiscard]]
constexpr bool operator==(
const view_iterator<LhsType, LhsArgs...> &lhs,
const view_iterator<RhsType, RhsArgs...> &rhs)
noexcept {
120 return lhs.it == rhs.it;
123template<
typename LhsType,
auto... LhsArgs,
typename RhsType,
auto... RhsArgs>
124[[nodiscard]]
constexpr bool operator!=(
const view_iterator<LhsType, LhsArgs...> &lhs,
const view_iterator<RhsType, RhsArgs...> &rhs)
noexcept {
125 return !(lhs == rhs);
128template<
typename It,
typename... Type>
129struct extended_view_iterator final {
130 using iterator_type = It;
131 using difference_type = std::ptrdiff_t;
132 using value_type =
decltype(std::tuple_cat(std::make_tuple(*std::declval<It>()), std::declval<Type>().get_as_tuple({})...));
133 using pointer = input_iterator_pointer<value_type>;
134 using reference = value_type;
135 using iterator_category = std::input_iterator_tag;
136 using iterator_concept = std::forward_iterator_tag;
138 constexpr extended_view_iterator()
142 extended_view_iterator(iterator_type from, std::tuple<Type *...> value)
146 extended_view_iterator &operator++() noexcept {
150 extended_view_iterator operator++(
int)
noexcept {
151 extended_view_iterator orig = *
this;
152 return ++(*this), orig;
155 [[nodiscard]] reference operator*() const noexcept {
156 return std::apply([
entt = *it](
auto *...curr) {
return std::tuple_cat(std::make_tuple(
entt), curr->get_as_tuple(
entt)...); }, pools);
159 [[nodiscard]] pointer operator->() const noexcept {
163 [[nodiscard]]
constexpr iterator_type base() const noexcept {
167 template<
typename... Lhs,
typename... Rhs>
168 friend bool constexpr operator==(
const extended_view_iterator<Lhs...> &,
const extended_view_iterator<Rhs...> &)
noexcept;
172 std::tuple<Type *...> pools;
175template<
typename... Lhs,
typename... Rhs>
176[[nodiscard]]
constexpr bool operator==(
const extended_view_iterator<Lhs...> &lhs,
const extended_view_iterator<Rhs...> &rhs)
noexcept {
177 return lhs.it == rhs.it;
180template<
typename... Lhs,
typename... Rhs>
181[[nodiscard]]
constexpr bool operator!=(
const extended_view_iterator<Lhs...> &lhs,
const extended_view_iterator<Rhs...> &rhs)
noexcept {
182 return !(lhs == rhs);
206template<
typename,
typename,
typename>
216template<
typename Type, std::
size_t Get, std::
size_t Exclude>
219 friend Return internal::view_pack(
const View &,
const Other &, std::index_sequence<VGet...>, std::index_sequence<VExclude...>, std::index_sequence<OGet...>, std::index_sequence<OExclude...>);
233 void use(
const std::size_t
pos)
noexcept {
244 if(pools[
pos]->size() < pools[index]->size()) {
261 using iterator = internal::view_iterator<common_type, Get, Exclude>;
326 const auto last =
leading->rend(0);
349 return leading && internal::fully_initialized(filter.data(),
Exclude);
368 std::array<const common_type *, Get> pools{};
369 std::array<const common_type *, Exclude> filter{};
391 template<
typename Type>
394 template<std::size_t...
Index>
395 auto storage(std::index_sequence<Index...>)
const noexcept {
399 template<std::size_t
Curr, std::size_t
Other,
typename...
Args>
400 [[
nodiscard]]
auto dispatch_get(
const std::tuple<typename base_type::entity_type, Args...> &
curr)
const {
402 return std::forward_as_tuple(std::get<Args>(
curr)...);
408 template<std::size_t
Curr,
typename Func, std::size_t...
Index>
409 void each(Func &func, std::index_sequence<Index...>)
const {
411 if(
const auto entt = std::get<0>(
curr); ((
sizeof...(Get) != 1u) || (
entt !=
tombstone)) && internal::all_of_but(this->index, this->pools.data(),
sizeof...(Get),
entt) && internal::none_of(this->filter.data(),
sizeof...(Exclude),
entt)) {
412 if constexpr(
is_applicable_v<Func,
decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_view>().get({})))>) {
421 template<
typename Func, std::size_t...
Index>
422 void pick_and_each(Func &func, std::index_sequence<Index...> seq)
const {
456 basic_view(std::tuple<Get &...> value, std::tuple<Exclude &...>
excl = {})
noexcept
463 template<
typename Type>
472 template<std::
size_t Index>
474 base_type::use(
Index);
482 template<
typename Type>
492 template<std::
size_t Index>
496 if constexpr(
Index <
sizeof...(Get)) {
508 template<
typename Type>
519 template<std::
size_t Index,
typename Type>
523 if constexpr(
Index <
sizeof...(Get)) {
525 base_type::refresh();
527 this->filter[
Index -
sizeof...(Get)] = &
elem;
547 template<
typename Type,
typename...
Other>
558 template<std::size_t...
Index>
560 if constexpr(
sizeof...(Index) == 0) {
561 return std::apply([
entt](
auto *...
curr) {
return std::tuple_cat(
curr->get_as_tuple(
entt)...); },
storage(std::index_sequence_for<Get...>{}));
562 }
else if constexpr(
sizeof...(Index) == 1) {
584 template<
typename Func>
586 if(base_type::handle() !=
nullptr) {
587 pick_and_each(func, std::index_sequence_for<Get...>{});
602 return {internal::extended_view_iterator{base_type::begin(),
as_pools}, internal::extended_view_iterator{base_type::end(),
as_pools}};
615 *
this,
other, std::index_sequence_for<
Get...>{}, std::index_sequence_for<
Exclude...>{}, std::index_sequence_for<
OGet...>{}, std::index_sequence_for<
OExclude...>{});
624template<
typename Type>
771template<
typename Get>
787 using iterable =
decltype(std::declval<Get>().each());
805 basic_view(std::tuple<Get &> value, std::tuple<> = {})
noexcept
813 template<
typename Type =
typename Get::value_type>
815 static_assert(std::is_same_v<std::remove_const_t<Type>,
typename Get::value_type>,
"Invalid component type");
824 template<std::
size_t Index>
826 static_assert(
Index == 0
u,
"Index out of bounds");
843 template<std::
size_t Index>
845 static_assert(
Index == 0
u,
"Index out of bounds");
864 return base_type::begin()[
pos];
873 template<
typename Elem>
875 static_assert(std::is_same_v<std::remove_const_t<Elem>,
typename Get::value_type>,
"Invalid component type");
885 template<std::size_t...
Index>
887 if constexpr(
sizeof...(Index) == 0) {
909 template<
typename Func>
913 for(
const auto pack:
elem->each()) {
914 std::apply(func, pack);
916 }
else if constexpr(std::is_invocable_v<Func,
decltype(*
elem->begin())>) {
952 *
this,
other, std::index_sequence_for<Get>{}, std::index_sequence_for<>{}, std::index_sequence_for<
OGet...>{}, std::index_sequence_for<
OExclude...>{});
961template<
typename... Type>
Basic storage view implementation.
size_type size_hint() const noexcept
Estimates the number of entities iterated by the view.
void refresh() noexcept
Updates the internal leading view if required.
Type common_type
Common type among all storage types.
const common_type * handle() const noexcept
Returns the leading storage of a view, if any.
bool contains(const entity_type entt) const noexcept
Checks if a view contains an entity.
iterator begin() const noexcept
Returns an iterator to the first entity of the view.
entity_type back() const noexcept
Returns the last entity of the view, if any.
entity_type front() const noexcept
Returns the first entity of the view, if any.
std::size_t size_type
Unsigned integer type.
iterator end() const noexcept
Returns an iterator that is past the last entity of the view.
iterator find(const entity_type entt) const noexcept
Finds an entity.
internal::view_iterator< common_type, Get, Exclude > iterator
Bidirectional iterator type.
typename Type::entity_type entity_type
Underlying entity identifier.
Basic storage view implementation.
reverse_iterator rbegin() const noexcept
Returns an iterator to the first entity of the reversed view.
iterator begin() const noexcept
Returns an iterator to the first entity of the view.
reverse_iterator rend() const noexcept
Returns an iterator that is past the last entity of the reversed view.
typename common_type::entity_type entity_type
Underlying entity identifier.
typename common_type::reverse_iterator reverse_iterator
Reversed iterator type.
iterator find(const entity_type entt) const noexcept
Finds an entity.
bool contains(const entity_type entt) const noexcept
Checks if a view contains an entity.
entity_type back() const noexcept
Returns the last entity of the view, if any.
std::size_t size_type
Unsigned integer type.
iterator end() const noexcept
Returns an iterator that is past the last entity of the view.
size_type size() const noexcept
Returns the number of entities that have the given component.
const common_type * handle() const noexcept
Returns the leading storage of a view, if any.
entity_type front() const noexcept
Returns the first entity of the view, if any.
typename common_type::iterator iterator
Random access iterator type.
Type common_type
Common type among all storage types.
bool empty() const noexcept
Checks whether a view is empty.
Basic storage implementation.
const value_type & get(const entity_type entt) const noexcept
Returns the object assigned to an entity.
iterable each() const noexcept
Returns an iterable object to use to visit a view.
typename base_type::size_type size_type
Unsigned integer type.
void each(Func func) const
Iterates entities and components and applies the given function object to them.
basic_view(Get &value) noexcept
Constructs a view from a storage class.
auto operator|(const basic_view< get_t< OGet... >, exclude_t< OExclude... > > &other) const noexcept
Combines two views in a more specific one.
decltype(std::declval< Get >().each()) iterable
Iterable view type.
decltype(auto) get(const entity_type entt) const
Returns the component assigned to the given entity.
basic_view(std::tuple< Get & > value, std::tuple<>={}) noexcept
Constructs a view from a storage class.
auto * storage() const noexcept
Returns the storage for a given component type, if any.
typename base_type::entity_type entity_type
Underlying entity identifier.
typename base_type::common_type common_type
Common type among all storage types.
entity_type operator[](const size_type pos) const
Returns the identifier that occupies the given position.
void storage(Get &elem) noexcept
Assigns a storage to a view.
void storage(Get &elem) noexcept
Assigns a storage to a view.
typename base_type::reverse_iterator reverse_iterator
Reversed iterator type.
typename base_type::iterator iterator
Random access iterator type.
basic_view() noexcept
Default constructor to use to create empty, invalid views.
decltype(auto) get(const entity_type entt) const
Returns the components assigned to the given entity.
basic_view(Get &...value, Exclude &...excl) noexcept
Constructs a view from a set of storage classes.
typename base_type::iterator iterator
Bidirectional iterator type.
void use() noexcept
Forces a view to use a given component to drive iterations.
void storage(Type &elem) noexcept
Assigns a storage to a view.
typename base_type::size_type size_type
Unsigned integer type.
auto * storage() const noexcept
Returns the storage for a given component type, if any.
iterable each() const noexcept
Returns an iterable object to use to visit a view.
void each(Func func) const
Iterates entities and components and applies the given function object to them.
basic_view(std::tuple< Get &... > value, std::tuple< Exclude &... > excl={}) noexcept
Constructs a view from a set of storage classes.
void storage(Type &elem) noexcept
Assigns a storage to a view.
typename base_type::common_type common_type
Common type among all storage types.
typename base_type::entity_type entity_type
Underlying entity identifier.
auto operator|(const basic_view< get_t< OGet... >, exclude_t< OExclude... > > &other) const noexcept
Combines two views in a more specific one.
basic_view() noexcept
Default constructor to use to create empty, invalid views.
decltype(auto) get(const entity_type entt) const
Returns the components assigned to the given entity.
basic_view(Type &...storage) -> basic_view< get_t< Type... >, exclude_t<> >
Deduction guide.
constexpr Type make_obj_using_allocator(const Allocator &allocator, Args &&...args)
Uses-allocator construction utility (waiting for C++20).
typename constness_as< To, From >::type constness_as_t
Alias template to facilitate the transcription of the constness.
constexpr null_t null
Compile-time constant for null entities.
basic_view< type_list_transform_t< Get, storage_for >, type_list_transform_t< Exclude, storage_for > > view
Alias declaration for the most common use case.
constexpr bool is_applicable_v
Helper variable template.
constexpr tombstone_t tombstone
Compile-time constant for tombstone entities.
constexpr get_t< Type... > get
Variable template for lists of observed components.
typename type_list_element< Index, List >::type type_list_element_t
Helper type.
constexpr bool operator!=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
constexpr bool operator==(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
basic_storage< Type > storage
Alias declaration for the most common use case.
Alias for exclusion lists.
Alias for lists of observed components.
Utility class to create an iterable object from a pair of iterators.
A class to use to push around lists of types, nothing more.