view: prepare to storage based model

This commit is contained in:
Michele Caini
2022-06-15 09:01:57 +02:00
parent cb202c15a5
commit 67b2fc085c

View File

@@ -25,12 +25,12 @@ namespace entt {
namespace internal {
template<typename Type, std::size_t Component, std::size_t Exclude>
template<typename Type, std::size_t Get, std::size_t Exclude>
class view_iterator final {
using iterator_type = typename Type::const_iterator;
[[nodiscard]] bool valid() const noexcept {
return ((Component != 0u) || (*it != tombstone))
return ((Get != 0u) || (*it != tombstone))
&& std::apply([entt = *it](const auto *...curr) { return (curr->contains(entt) && ...); }, pools)
&& std::apply([entt = *it](const auto *...curr) { return (!curr->contains(entt) && ...); }, filter);
}
@@ -48,7 +48,7 @@ public:
pools{},
filter{} {}
view_iterator(iterator_type curr, iterator_type to, std::array<const Type *, Component> all_of, std::array<const Type *, Exclude> none_of) noexcept
view_iterator(iterator_type curr, iterator_type to, std::array<const Type *, Get> all_of, std::array<const Type *, Exclude> none_of) noexcept
: it{curr},
last{to},
pools{all_of},
@@ -82,7 +82,7 @@ public:
private:
iterator_type it;
iterator_type last;
std::array<const Type *, Component> pools;
std::array<const Type *, Get> pools;
std::array<const Type *, Exclude> filter;
};
@@ -184,41 +184,41 @@ class basic_view;
* invalidates all the iterators and using them results in undefined behavior.
*
* @tparam Entity A valid entity type (see entt_traits for more details).
* @tparam Component Types of components iterated by the view.
* @tparam Get Types of components iterated by the view.
* @tparam Exclude Types of components used to filter the view.
*/
template<typename Entity, typename... Component, typename... Exclude>
class basic_view<Entity, get_t<Component...>, exclude_t<Exclude...>> {
template<typename Entity, typename... Get, typename... Exclude>
class basic_view<Entity, get_t<Get...>, exclude_t<Exclude...>> {
template<typename, typename, typename, typename>
friend class basic_view;
[[nodiscard]] auto opaque_check_set() const noexcept {
std::array<const base_type *, sizeof...(Component) - 1u> other{};
std::array<const base_type *, sizeof...(Get) - 1u> other{};
std::apply([&other, pos = 0u, view = view](const auto *...curr) mutable { ((curr == view ? void() : void(other[pos++] = curr)), ...); }, pools);
return other;
}
template<std::size_t Comp, std::size_t Other, typename... Args>
template<std::size_t Curr, std::size_t Other, typename... Args>
[[nodiscard]] auto dispatch_get(const std::tuple<Entity, Args...> &curr) const {
if constexpr(Comp == Other) {
if constexpr(Curr == Other) {
return std::forward_as_tuple(std::get<Args>(curr)...);
} else {
return std::get<Other>(pools)->get_as_tuple(std::get<0>(curr));
}
}
template<std::size_t Comp, typename Func, std::size_t... Index>
template<std::size_t Curr, typename Func, std::size_t... Index>
void each(Func func, std::index_sequence<Index...>) const {
for(const auto curr: std::get<Comp>(pools)->each()) {
for(const auto curr: std::get<Curr>(pools)->each()) {
const auto entt = std::get<0>(curr);
if(((sizeof...(Component) != 1u) || (entt != tombstone))
&& ((Comp == Index || std::get<Index>(pools)->contains(entt)) && ...)
if(((sizeof...(Get) != 1u) || (entt != tombstone))
&& ((Curr == Index || std::get<Index>(pools)->contains(entt)) && ...)
&& std::apply([entt](const auto *...epool) { return (!epool->contains(entt) && ...); }, filter)) {
if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_view>().get({})))>) {
std::apply(func, std::tuple_cat(std::make_tuple(entt), dispatch_get<Comp, Index>(curr)...));
std::apply(func, std::tuple_cat(std::make_tuple(entt), dispatch_get<Curr, Index>(curr)...));
} else {
std::apply(func, std::tuple_cat(dispatch_get<Comp, Index>(curr)...));
std::apply(func, std::tuple_cat(dispatch_get<Curr, Index>(curr)...));
}
}
}
@@ -235,11 +235,11 @@ public:
/*! @brief Unsigned integer type. */
using size_type = std::size_t;
/*! @brief Common type among all storage types. */
using base_type = std::common_type_t<typename storage_for_t<Component, entity_type>::base_type...>;
using base_type = std::common_type_t<typename storage_for_t<Get, entity_type>::base_type...>;
/*! @brief Bidirectional iterator type. */
using iterator = internal::view_iterator<base_type, sizeof...(Component) - 1u, sizeof...(Exclude)>;
using iterator = internal::view_iterator<base_type, sizeof...(Get) - 1u, sizeof...(Exclude)>;
/*! @brief Iterable view type. */
using iterable = iterable_adaptor<internal::extended_view_iterator<iterator, storage_for_t<Component, entity_type>...>>;
using iterable = iterable_adaptor<internal::extended_view_iterator<iterator, storage_for_t<Get, entity_type>...>>;
/*! @brief Default constructor to use to create empty, invalid views. */
basic_view() noexcept
@@ -249,45 +249,45 @@ public:
/**
* @brief Constructs a multi-type view from a set of storage classes.
* @param component The storage for the types to iterate.
* @param epool The storage for the types used to filter the view.
* @param get The storage for the types to iterate.
* @param exclude The storage for the types used to filter the view.
*/
basic_view(storage_for_t<Component, entity_type> &...component, storage_for_t<const Exclude, entity_type> &...epool) noexcept
: pools{&component...},
filter{&epool...},
view{(std::min)({&static_cast<const base_type &>(component)...}, [](auto *lhs, auto *rhs) { return lhs->size() < rhs->size(); })} {}
basic_view(storage_for_t<Get, entity_type> &...get, storage_for_t<const Exclude, entity_type> &...exclude) noexcept
: pools{&get...},
filter{&exclude...},
view{(std::min)({&static_cast<const base_type &>(get)...}, [](auto *lhs, auto *rhs) { return lhs->size() < rhs->size(); })} {}
/**
* @brief Constructs a multi-type view from a set of storage classes.
* @param component The storage for the types to iterate.
* @param epool The storage for the types used to filter the view.
* @param get The storage for the types to iterate.
* @param exclude The storage for the types used to filter the view.
*/
basic_view(std::tuple<storage_for_t<Component, entity_type> &...> component, std::tuple<storage_for_t<const Exclude, entity_type> &...> epool = {}) noexcept
: pools{std::apply([](auto &...curr) { return std::make_tuple(&curr...); }, component)},
filter{std::apply([](auto &...curr) { return std::array(&static_cast<const base_type &>(curr)...); }, epool)},
view{std::apply([](const auto &...curr) { return (std::min)({&static_cast<const base_type &>(curr)...}, [](auto *lhs, auto *rhs) { return lhs->size() < rhs->size(); }); }, component)} {}
basic_view(std::tuple<storage_for_t<Get, entity_type> &...> get, std::tuple<storage_for_t<const Exclude, entity_type> &...> exclude = {}) noexcept
: pools{std::apply([](auto &...curr) { return std::make_tuple(&curr...); }, get)},
filter{std::apply([](auto &...curr) { return std::array(&static_cast<const base_type &>(curr)...); }, exclude)},
view{std::apply([](const auto &...curr) { return (std::min)({&static_cast<const base_type &>(curr)...}, [](auto *lhs, auto *rhs) { return lhs->size() < rhs->size(); }); }, get)} {}
/**
* @brief Creates a new view driven by a given component in its iterations.
* @tparam Comp Type of component used to drive the iteration.
* @tparam Type Type of component used to drive the iteration.
* @return A new view driven by the given component in its iterations.
*/
template<typename Comp>
template<typename Type>
[[nodiscard]] basic_view use() const noexcept {
basic_view other{*this};
other.view = std::get<storage_for_t<Comp, entity_type> *>(pools);
other.view = std::get<storage_for_t<Type, entity_type> *>(pools);
return other;
}
/**
* @brief Creates a new view driven by a given component in its iterations.
* @tparam Comp Index of the component used to drive the iteration.
* @tparam Index Index of the component used to drive the iteration.
* @return A new view driven by the given component in its iterations.
*/
template<std::size_t Comp>
template<std::size_t Index>
[[nodiscard]] basic_view use() const noexcept {
basic_view other{*this};
other.view = std::get<Comp>(pools);
other.view = std::get<Index>(pools);
return other;
}
@@ -304,19 +304,19 @@ public:
* @tparam Comp Type of component of which to return the storage.
* @return The storage for the given component type.
*/
template<typename Comp>
template<typename Type>
[[nodiscard]] decltype(auto) storage() const noexcept {
return *std::get<storage_for_t<Comp, entity_type> *>(pools);
return *std::get<storage_for_t<Type, entity_type> *>(pools);
}
/**
* @brief Returns the storage for a given component type.
* @tparam Comp Index of component of which to return the storage.
* @return The storage for the given component type.
* @brief Returns the storage for a given index.
* @tparam Index Index of the storage to return.
* @return The storage for the given index.
*/
template<std::size_t Comp>
template<std::size_t Index>
[[nodiscard]] decltype(auto) storage() const noexcept {
return *std::get<Comp>(pools);
return *std::get<Index>(pools);
}
/**
@@ -389,7 +389,7 @@ public:
* @return The components assigned to the given entity.
*/
[[nodiscard]] decltype(auto) operator[](const entity_type entt) const {
return get<Component...>(entt);
return get<Get...>(entt);
}
/**
@@ -417,20 +417,20 @@ public:
* Attempting to use an entity that doesn't belong to the view results in
* undefined behavior.
*
* @tparam Comp Types of components to get.
* @tparam Type Types of components to get.
* @param entt A valid identifier.
* @return The components assigned to the entity.
*/
template<typename... Comp>
template<typename... Type>
[[nodiscard]] decltype(auto) get(const entity_type entt) const {
ENTT_ASSERT(contains(entt), "View does not contain entity");
if constexpr(sizeof...(Comp) == 0) {
if constexpr(sizeof...(Type) == 0) {
return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, pools);
} else if constexpr(sizeof...(Comp) == 1) {
return (std::get<storage_for_t<Comp, entity_type> *>(pools)->get(entt), ...);
} else if constexpr(sizeof...(Type) == 1) {
return (std::get<storage_for_t<Type, entity_type> *>(pools)->get(entt), ...);
} else {
return std::tuple_cat(std::get<storage_for_t<Comp, entity_type> *>(pools)->get_as_tuple(entt)...);
return std::tuple_cat(std::get<storage_for_t<Type, entity_type> *>(pools)->get_as_tuple(entt)...);
}
}
@@ -477,7 +477,7 @@ public:
*/
template<typename Func>
void each(Func func) const {
pick_and_each(std::move(func), std::index_sequence_for<Component...>{});
pick_and_each(std::move(func), std::index_sequence_for<Get...>{});
}
/**
@@ -495,22 +495,22 @@ public:
/**
* @brief Combines two views in a _more specific_ one (friend function).
* @tparam Get Component list of the view to combine with.
* @tparam Excl Filter list of the view to combine with.
* @tparam OGet Component list of the view to combine with.
* @tparam OExclude Filter list of the view to combine with.
* @param other The view to combine with.
* @return A more specific view.
*/
template<typename... Get, typename... Excl>
[[nodiscard]] auto operator|(const basic_view<entity_type, get_t<Get...>, exclude_t<Excl...>> &other) const noexcept {
return std::make_from_tuple<basic_view<entity_type, get_t<Component..., Get...>, exclude_t<Exclude..., Excl...>>>(std::tuple_cat(
template<typename... OGet, typename... OExclude>
[[nodiscard]] auto operator|(const basic_view<entity_type, get_t<OGet...>, exclude_t<OExclude...>> &other) const noexcept {
return std::make_from_tuple<basic_view<entity_type, get_t<Get..., OGet...>, exclude_t<Exclude..., OExclude...>>>(std::tuple_cat(
std::apply([](auto *...curr) { return std::forward_as_tuple(*curr...); }, pools),
std::apply([](auto *...curr) { return std::forward_as_tuple(*curr...); }, other.pools),
std::apply([](const auto *...curr) { return std::forward_as_tuple(*static_cast<const storage_for_t<Exclude> *>(curr)...); }, filter),
std::apply([](const auto *...curr) { return std::forward_as_tuple(*static_cast<const storage_for_t<Excl> *>(curr)...); }, other.filter)));
std::apply([](const auto *...curr) { return std::forward_as_tuple(*static_cast<const storage_for_t<OExclude> *>(curr)...); }, other.filter)));
}
private:
std::tuple<storage_for_t<Component, entity_type> *...> pools;
std::tuple<storage_for_t<Get, entity_type> *...> pools;
std::array<const base_type *, sizeof...(Exclude)> filter;
const base_type *view;
};
@@ -535,10 +535,10 @@ private:
* invalidates all the iterators and using them results in undefined behavior.
*
* @tparam Entity A valid entity type (see entt_traits for more details).
* @tparam Component Type of component iterated by the view.
* @tparam Get Type of component iterated by the view.
*/
template<typename Entity, typename Component>
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>>> {
template<typename Entity, typename Get>
class basic_view<Entity, get_t<Get>, exclude_t<>, std::void_t<std::enable_if_t<!component_traits<std::remove_const_t<Get>>::in_place_delete>>> {
template<typename, typename, typename, typename>
friend class basic_view;
@@ -548,13 +548,13 @@ public:
/*! @brief Unsigned integer type. */
using size_type = std::size_t;
/*! @brief Common type among all storage types. */
using base_type = typename storage_for_t<Component, entity_type>::base_type;
using base_type = typename storage_for_t<Get, entity_type>::base_type;
/*! @brief Random access iterator type. */
using iterator = typename base_type::iterator;
/*! @brief Reversed iterator type. */
using reverse_iterator = typename base_type::reverse_iterator;
/*! @brief Iterable view type. */
using iterable = decltype(std::declval<storage_for_t<Component, entity_type>>().each());
using iterable = decltype(std::declval<storage_for_t<Get, entity_type>>().each());
/*! @brief Default constructor to use to create empty, invalid views. */
basic_view() noexcept
@@ -566,7 +566,7 @@ public:
* @brief Constructs a single-type view from a storage class.
* @param ref The storage for the type to iterate.
*/
basic_view(storage_for_t<Component, entity_type> &ref) noexcept
basic_view(storage_for_t<Get, entity_type> &ref) noexcept
: pools{&ref},
filter{},
view{&ref} {}
@@ -575,7 +575,7 @@ public:
* @brief Constructs a single-type view from a storage class.
* @param ref The storage for the type to iterate.
*/
basic_view(std::tuple<storage_for_t<Component, entity_type> &> ref, std::tuple<> = {}) noexcept
basic_view(std::tuple<storage_for_t<Get, entity_type> &> ref, std::tuple<> = {}) noexcept
: basic_view{std::get<0>(ref)} {}
/**
@@ -588,23 +588,23 @@ public:
/**
* @brief Returns the storage for a given component type.
* @tparam Comp Type of component of which to return the storage.
* @tparam Type Type of component of which to return the storage.
* @return The storage for the given component type.
*/
template<typename Comp = Component>
template<typename Type = Get>
[[nodiscard]] decltype(auto) storage() const noexcept {
static_assert(std::is_same_v<Comp, Component>, "Invalid component type");
static_assert(std::is_same_v<Type, Get>, "Invalid component type");
return *std::get<0>(pools);
}
/**
* @brief Returns the storage for a given component type.
* @tparam Comp Index of component of which to return the storage.
* @return The storage for the given component type.
* @brief Returns the storage for a given index.
* @tparam Index Index of the storage to return.
* @return The storage for the given index.
*/
template<std::size_t Comp>
template<std::size_t Index>
[[nodiscard]] decltype(auto) storage() const noexcept {
return *std::get<Comp>(pools);
return *std::get<Index>(pools);
}
/**
@@ -718,7 +718,7 @@ public:
* @return The component assigned to the given entity.
*/
[[nodiscard]] decltype(auto) operator[](const entity_type entt) const {
return get<Component>(entt);
return get<Get>(entt);
}
/**
@@ -745,24 +745,24 @@ public:
* Attempting to use an entity that doesn't belong to the view results in
* undefined behavior.
*
* @tparam Comp Type or index of the component to get.
* @tparam Type Type or index of the component to get.
* @param entt A valid identifier.
* @return The component assigned to the entity.
*/
template<typename... Comp>
template<typename... Type>
[[nodiscard]] decltype(auto) get(const entity_type entt) const {
ENTT_ASSERT(contains(entt), "View does not contain entity");
if constexpr(sizeof...(Comp) == 0) {
if constexpr(sizeof...(Type) == 0) {
return std::get<0>(pools)->get_as_tuple(entt);
} else {
static_assert(std::is_same_v<Comp..., Component>, "Invalid component type");
static_assert(std::is_same_v<Type..., Get>, "Invalid component type");
return std::get<0>(pools)->get(entt);
}
}
/*! @copydoc get */
template<std::size_t Comp>
template<std::size_t Index>
[[nodiscard]] decltype(auto) get(const entity_type entt) const {
ENTT_ASSERT(contains(entt), "View does not contain entity");
return std::get<0>(pools)->get(entt);
@@ -779,8 +779,8 @@ public:
* forms:
*
* @code{.cpp}
* void(const entity_type, Component &);
* void(Component &);
* void(const entity_type, Get &);
* void(Get &);
* @endcode
*
* @tparam Func Type of the function object to invoke.
@@ -792,7 +792,7 @@ public:
for(const auto pack: each()) {
std::apply(func, pack);
}
} else if constexpr(std::is_invocable_v<Func, Component &>) {
} else if constexpr(std::is_invocable_v<Func, Get &>) {
for(auto &&component: *std::get<0>(pools)) {
func(component);
}
@@ -822,21 +822,21 @@ public:
/**
* @brief Combines two views in a _more specific_ one (friend function).
* @tparam Get Component list of the view to combine with.
* @tparam Excl Filter list of the view to combine with.
* @tparam OGet Component list of the view to combine with.
* @tparam OExclude Filter list of the view to combine with.
* @param other The view to combine with.
* @return A more specific view.
*/
template<typename... Get, typename... Excl>
[[nodiscard]] auto operator|(const basic_view<entity_type, get_t<Get...>, exclude_t<Excl...>> &other) const noexcept {
return std::make_from_tuple<basic_view<entity_type, get_t<Component, Get...>, exclude_t<Excl...>>>(std::tuple_cat(
template<typename... OGet, typename... OExclude>
[[nodiscard]] auto operator|(const basic_view<entity_type, get_t<OGet...>, exclude_t<OExclude...>> &other) const noexcept {
return std::make_from_tuple<basic_view<entity_type, get_t<Get, OGet...>, exclude_t<OExclude...>>>(std::tuple_cat(
std::forward_as_tuple(*std::get<0>(pools)),
std::apply([](auto *...curr) { return std::forward_as_tuple(*curr...); }, other.pools),
std::apply([](const auto *...curr) { return std::forward_as_tuple(*static_cast<const storage_for_t<Excl> *>(curr)...); }, other.filter)));
std::apply([](const auto *...curr) { return std::forward_as_tuple(*static_cast<const storage_for_t<OExclude> *>(curr)...); }, other.filter)));
}
private:
std::tuple<storage_for_t<Component, entity_type> *> pools;
std::tuple<storage_for_t<Get, entity_type> *> pools;
std::array<const base_type *, 0u> filter;
const base_type *view;
};
@@ -851,11 +851,11 @@ basic_view(Type &...storage) -> basic_view<std::common_type_t<typename Type::ent
/**
* @brief Deduction guide.
* @tparam Component Types of components iterated by the view.
* @tparam Get Types of components iterated by the view.
* @tparam Exclude Types of components used to filter the view.
*/
template<typename... Component, typename... Exclude>
basic_view(std::tuple<Component &...>, std::tuple<Exclude &...> = {}) -> basic_view<std::common_type_t<typename Component::entity_type..., typename Exclude::entity_type...>, get_t<constness_as_t<typename Component::value_type, Component>...>, exclude_t<constness_as_t<typename Exclude::value_type, Exclude>...>>;
template<typename... Get, typename... Exclude>
basic_view(std::tuple<Get &...>, std::tuple<Exclude &...> = {}) -> basic_view<std::common_type_t<typename Get::entity_type..., typename Exclude::entity_type...>, get_t<constness_as_t<typename Get::value_type, Get>...>, exclude_t<constness_as_t<typename Exclude::value_type, Exclude>...>>;
} // namespace entt