|
|
@@ -10,6 +10,7 @@
|
|
|
#include <type_traits>
|
|
|
#include "../config/config.h"
|
|
|
#include "../core/type_traits.hpp"
|
|
|
+#include "component.hpp"
|
|
|
#include "entity.hpp"
|
|
|
#include "fwd.hpp"
|
|
|
#include "sparse_set.hpp"
|
|
|
@@ -21,13 +22,153 @@ namespace entt {
|
|
|
|
|
|
|
|
|
/**
|
|
|
- * @brief View.
|
|
|
+ * @cond TURN_OFF_DOXYGEN
|
|
|
+ * Internal details not to be documented.
|
|
|
+ */
|
|
|
+
|
|
|
+
|
|
|
+namespace internal {
|
|
|
+
|
|
|
+
|
|
|
+template<typename Policy, typename It, std::size_t AllOf, std::size_t NoneOf>
|
|
|
+class view_iterator final {
|
|
|
+ using basic_common_type = basic_sparse_set<typename std::iterator_traits<It>::value_type>;
|
|
|
+
|
|
|
+ [[nodiscard]] bool valid() const {
|
|
|
+ const auto entt = *it;
|
|
|
+ return Policy::accept(entt)
|
|
|
+ && std::apply([entt](const auto *... curr) { return (curr->contains(entt) && ...); }, pools)
|
|
|
+ && std::apply([entt](const auto *... curr) { return (!curr->contains(entt) && ...); }, filter);
|
|
|
+ }
|
|
|
+
|
|
|
+public:
|
|
|
+ using difference_type = typename std::iterator_traits<It>::difference_type;
|
|
|
+ using value_type = typename std::iterator_traits<It>::value_type;
|
|
|
+ using pointer = typename std::iterator_traits<It>::pointer;
|
|
|
+ using reference = typename std::iterator_traits<It>::reference;
|
|
|
+ using iterator_category = std::bidirectional_iterator_tag;
|
|
|
+
|
|
|
+ view_iterator() ENTT_NOEXCEPT
|
|
|
+ : first{},
|
|
|
+ last{},
|
|
|
+ it{},
|
|
|
+ pools{},
|
|
|
+ filter{}
|
|
|
+ {}
|
|
|
+
|
|
|
+ view_iterator(It from, It to, It curr, std::array<const basic_common_type *, AllOf> all_of, std::array<const basic_common_type *, NoneOf> none_of) ENTT_NOEXCEPT
|
|
|
+ : first{from},
|
|
|
+ last{to},
|
|
|
+ it{curr},
|
|
|
+ pools{all_of},
|
|
|
+ filter{none_of}
|
|
|
+ {
|
|
|
+ if(it != last && !valid()) {
|
|
|
+ ++(*this);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ view_iterator & operator++() ENTT_NOEXCEPT {
|
|
|
+ while(++it != last && !valid());
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ view_iterator operator++(int) ENTT_NOEXCEPT {
|
|
|
+ view_iterator orig = *this;
|
|
|
+ return ++(*this), orig;
|
|
|
+ }
|
|
|
+
|
|
|
+ view_iterator & operator--() ENTT_NOEXCEPT {
|
|
|
+ while(--it != first && !valid());
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ view_iterator operator--(int) ENTT_NOEXCEPT {
|
|
|
+ view_iterator orig = *this;
|
|
|
+ return operator--(), orig;
|
|
|
+ }
|
|
|
+
|
|
|
+ [[nodiscard]] bool operator==(const view_iterator &other) const ENTT_NOEXCEPT {
|
|
|
+ return other.it == it;
|
|
|
+ }
|
|
|
+
|
|
|
+ [[nodiscard]] bool operator!=(const view_iterator &other) const ENTT_NOEXCEPT {
|
|
|
+ return !(*this == other);
|
|
|
+ }
|
|
|
+
|
|
|
+ [[nodiscard]] pointer operator->() const {
|
|
|
+ return &*it;
|
|
|
+ }
|
|
|
+
|
|
|
+ [[nodiscard]] reference operator*() const {
|
|
|
+ return *operator->();
|
|
|
+ }
|
|
|
+
|
|
|
+private:
|
|
|
+ It first;
|
|
|
+ It last;
|
|
|
+ It it;
|
|
|
+ std::array<const basic_common_type *, AllOf> pools;
|
|
|
+ std::array<const basic_common_type *, NoneOf> filter;
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*! @brief Stable storage policy, aimed at pointer stability. */
|
|
|
+struct stable_storage_policy {
|
|
|
+ /**
|
|
|
+ * @cond TURN_OFF_DOXYGEN
|
|
|
+ * Internal details not to be documented.
|
|
|
+ */
|
|
|
+ template<typename Entity>
|
|
|
+ [[nodiscard]] static constexpr bool accept(const Entity entity) ENTT_NOEXCEPT {
|
|
|
+ return entity != tombstone;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * Internal details not to be documented.
|
|
|
+ * @endcond
|
|
|
+ */
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+/*! @brief Packed storage policy, aimed at faster linear iteration. */
|
|
|
+struct packed_storage_policy {
|
|
|
+ /**
|
|
|
+ * @cond TURN_OFF_DOXYGEN
|
|
|
+ * Internal details not to be documented.
|
|
|
+ */
|
|
|
+ template<typename Entity>
|
|
|
+ [[nodiscard]] static constexpr bool accept(const Entity) ENTT_NOEXCEPT {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * Internal details not to be documented.
|
|
|
+ * @endcond
|
|
|
+ */
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * Internal details not to be documented.
|
|
|
+ * @endcond
|
|
|
+ */
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief View implementation.
|
|
|
*
|
|
|
* Primary template isn't defined on purpose. All the specializations give a
|
|
|
* compile-time error, but for a few reasonable cases.
|
|
|
*/
|
|
|
template<typename...>
|
|
|
-class basic_view;
|
|
|
+class basic_view_impl;
|
|
|
+
|
|
|
+
|
|
|
+/*! @brief View implementation dispatcher. */
|
|
|
+template<typename...>
|
|
|
+struct basic_view;
|
|
|
|
|
|
|
|
|
/**
|
|
|
@@ -59,120 +200,38 @@ class basic_view;
|
|
|
* Lifetime of a view must not overcome that of the registry that generated it.
|
|
|
* In any other case, attempting to use a view results in undefined behavior.
|
|
|
*
|
|
|
+ * @tparam Policy Common (stricter) storage policy.
|
|
|
* @tparam Entity A valid entity type (see entt_traits for more details).
|
|
|
* @tparam Exclude Types of components used to filter the view.
|
|
|
* @tparam Component Types of components iterated by the view.
|
|
|
*/
|
|
|
-template<typename Entity, typename... Exclude, typename... Component>
|
|
|
-class basic_view<Entity, exclude_t<Exclude...>, Component...> final {
|
|
|
+template<typename Policy, typename Entity, typename... Exclude, typename... Component>
|
|
|
+class basic_view_impl<Policy, Entity, exclude_t<Exclude...>, Component...> {
|
|
|
+ using basic_common_type = basic_sparse_set<Entity>;
|
|
|
+
|
|
|
template<typename Comp>
|
|
|
using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Comp>>::storage_type, Comp>;
|
|
|
|
|
|
- using unchecked_type = std::array<const basic_sparse_set<Entity> *, (sizeof...(Component) - 1)>;
|
|
|
-
|
|
|
- template<typename It>
|
|
|
- class view_iterator final {
|
|
|
- friend class basic_view<Entity, exclude_t<Exclude...>, Component...>;
|
|
|
-
|
|
|
- view_iterator(It from, It to, It curr, unchecked_type other, const std::tuple<const storage_type<Exclude> *...> &ignore) ENTT_NOEXCEPT
|
|
|
- : first{from},
|
|
|
- last{to},
|
|
|
- it{curr},
|
|
|
- unchecked{other},
|
|
|
- filter{ignore}
|
|
|
- {
|
|
|
- if(it != last && !valid()) {
|
|
|
- ++(*this);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- [[nodiscard]] bool valid() const {
|
|
|
- const auto entt = *it;
|
|
|
-
|
|
|
- return std::all_of(unchecked.cbegin(), unchecked.cend(), [entt](const basic_sparse_set<Entity> *curr) { return curr->contains(entt); })
|
|
|
- && !(std::get<const storage_type<Exclude> *>(filter)->contains(entt) || ...);
|
|
|
- }
|
|
|
-
|
|
|
- public:
|
|
|
- using difference_type = typename std::iterator_traits<It>::difference_type;
|
|
|
- using value_type = typename std::iterator_traits<It>::value_type;
|
|
|
- using pointer = typename std::iterator_traits<It>::pointer;
|
|
|
- using reference = typename std::iterator_traits<It>::reference;
|
|
|
- using iterator_category = std::bidirectional_iterator_tag;
|
|
|
-
|
|
|
- view_iterator() ENTT_NOEXCEPT
|
|
|
- : view_iterator{{}, {}, {}, {}, {}}
|
|
|
- {}
|
|
|
-
|
|
|
- view_iterator & operator++() ENTT_NOEXCEPT {
|
|
|
- while(++it != last && !valid());
|
|
|
- return *this;
|
|
|
- }
|
|
|
-
|
|
|
- view_iterator operator++(int) ENTT_NOEXCEPT {
|
|
|
- view_iterator orig = *this;
|
|
|
- return ++(*this), orig;
|
|
|
- }
|
|
|
-
|
|
|
- view_iterator & operator--() ENTT_NOEXCEPT {
|
|
|
- while(--it != first && !valid());
|
|
|
- return *this;
|
|
|
- }
|
|
|
-
|
|
|
- view_iterator operator--(int) ENTT_NOEXCEPT {
|
|
|
- view_iterator orig = *this;
|
|
|
- return operator--(), orig;
|
|
|
- }
|
|
|
-
|
|
|
- [[nodiscard]] bool operator==(const view_iterator &other) const ENTT_NOEXCEPT {
|
|
|
- return other.it == it;
|
|
|
- }
|
|
|
-
|
|
|
- [[nodiscard]] bool operator!=(const view_iterator &other) const ENTT_NOEXCEPT {
|
|
|
- return !(*this == other);
|
|
|
- }
|
|
|
-
|
|
|
- [[nodiscard]] pointer operator->() const {
|
|
|
- return &*it;
|
|
|
- }
|
|
|
-
|
|
|
- [[nodiscard]] reference operator*() const {
|
|
|
- return *operator->();
|
|
|
- }
|
|
|
-
|
|
|
- private:
|
|
|
- It first;
|
|
|
- It last;
|
|
|
- It it;
|
|
|
- unchecked_type unchecked;
|
|
|
- std::tuple<const storage_type<Exclude> *...> filter;
|
|
|
- };
|
|
|
-
|
|
|
- class iterable_view final {
|
|
|
- friend class basic_view<Entity, exclude_t<Exclude...>, Component...>;
|
|
|
-
|
|
|
+ class iterable final {
|
|
|
template<typename It>
|
|
|
- class iterable_view_iterator final {
|
|
|
- friend class iterable_view;
|
|
|
-
|
|
|
- iterable_view_iterator(It from, const basic_view *parent) ENTT_NOEXCEPT
|
|
|
- : it{from},
|
|
|
- view{parent}
|
|
|
- {}
|
|
|
-
|
|
|
- public:
|
|
|
+ struct iterable_iterator final {
|
|
|
using difference_type = std::ptrdiff_t;
|
|
|
- using value_type = decltype(std::tuple_cat(std::tuple<Entity>{}, std::declval<basic_view>().get({})));
|
|
|
+ using value_type = decltype(std::tuple_cat(std::tuple<Entity>{}, std::declval<basic_view_impl>().get({})));
|
|
|
using pointer = void;
|
|
|
using reference = value_type;
|
|
|
using iterator_category = std::input_iterator_tag;
|
|
|
|
|
|
- iterable_view_iterator & operator++() ENTT_NOEXCEPT {
|
|
|
+ iterable_iterator(It from, const basic_view_impl *parent) ENTT_NOEXCEPT
|
|
|
+ : it{from},
|
|
|
+ view{parent}
|
|
|
+ {}
|
|
|
+
|
|
|
+ iterable_iterator & operator++() ENTT_NOEXCEPT {
|
|
|
return ++it, *this;
|
|
|
}
|
|
|
|
|
|
- iterable_view_iterator operator++(int) ENTT_NOEXCEPT {
|
|
|
- iterable_view_iterator orig = *this;
|
|
|
+ iterable_iterator operator++(int) ENTT_NOEXCEPT {
|
|
|
+ iterable_iterator orig = *this;
|
|
|
return ++(*this), orig;
|
|
|
}
|
|
|
|
|
|
@@ -180,27 +239,27 @@ class basic_view<Entity, exclude_t<Exclude...>, Component...> final {
|
|
|
return std::tuple_cat(std::make_tuple(*it), view->get(*it));
|
|
|
}
|
|
|
|
|
|
- [[nodiscard]] bool operator==(const iterable_view_iterator &other) const ENTT_NOEXCEPT {
|
|
|
+ [[nodiscard]] bool operator==(const iterable_iterator &other) const ENTT_NOEXCEPT {
|
|
|
return other.it == it;
|
|
|
}
|
|
|
|
|
|
- [[nodiscard]] bool operator!=(const iterable_view_iterator &other) const ENTT_NOEXCEPT {
|
|
|
+ [[nodiscard]] bool operator!=(const iterable_iterator &other) const ENTT_NOEXCEPT {
|
|
|
return !(*this == other);
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
It it;
|
|
|
- const basic_view *view;
|
|
|
+ const basic_view_impl *view;
|
|
|
};
|
|
|
|
|
|
- iterable_view(const basic_view &parent)
|
|
|
+ public:
|
|
|
+ using iterator = iterable_iterator<internal::view_iterator<Policy, typename basic_common_type::iterator, sizeof...(Component) - 1u, sizeof...(Exclude)>>;
|
|
|
+ using reverse_iterator = iterable_iterator<internal::view_iterator<Policy, typename basic_common_type::reverse_iterator, sizeof...(Component) - 1u, sizeof...(Exclude)>>;
|
|
|
+
|
|
|
+ iterable(const basic_view_impl &parent)
|
|
|
: view{parent}
|
|
|
{}
|
|
|
|
|
|
- public:
|
|
|
- using iterator = iterable_view_iterator<view_iterator<typename basic_sparse_set<Entity>::iterator>>;
|
|
|
- using reverse_iterator = iterable_view_iterator<view_iterator<typename basic_sparse_set<Entity>::reverse_iterator>>;
|
|
|
-
|
|
|
[[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
|
|
|
return { view.begin(), &view };
|
|
|
}
|
|
|
@@ -218,22 +277,26 @@ class basic_view<Entity, exclude_t<Exclude...>, Component...> final {
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
- const basic_view view;
|
|
|
+ const basic_view_impl view;
|
|
|
};
|
|
|
|
|
|
- [[nodiscard]] const basic_sparse_set<Entity> * candidate() const ENTT_NOEXCEPT {
|
|
|
- return (std::min)({ static_cast<const basic_sparse_set<entity_type> *>(std::get<storage_type<Component> *>(pools))... }, [](const auto *lhs, const auto *rhs) {
|
|
|
+ [[nodiscard]] const auto * candidate() const ENTT_NOEXCEPT {
|
|
|
+ return (std::min)({ static_cast<const basic_common_type *>(std::get<storage_type<Component> *>(pools))... }, [](const auto *lhs, const auto *rhs) {
|
|
|
return lhs->size() < rhs->size();
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- [[nodiscard]] unchecked_type unchecked(const basic_sparse_set<Entity> *cpool) const {
|
|
|
+ [[nodiscard]] auto pools_to_unchecked_array() const ENTT_NOEXCEPT {
|
|
|
std::size_t pos{};
|
|
|
- unchecked_type other{};
|
|
|
- (static_cast<void>(std::get<storage_type<Component> *>(pools) == cpool ? void() : void(other[pos++] = std::get<storage_type<Component> *>(pools))), ...);
|
|
|
+ std::array<const basic_common_type *, sizeof...(Component) - 1u> other{};
|
|
|
+ (static_cast<void>(std::get<storage_type<Component> *>(pools) == view ? void() : void(other[pos++] = std::get<storage_type<Component> *>(pools))), ...);
|
|
|
return other;
|
|
|
}
|
|
|
|
|
|
+ [[nodiscard]] auto filter_to_array() const ENTT_NOEXCEPT {
|
|
|
+ return std::array<const basic_common_type *, sizeof...(Exclude)>{std::get<const storage_type<Exclude> *>(filter)...};
|
|
|
+ }
|
|
|
+
|
|
|
template<typename Comp, typename It>
|
|
|
[[nodiscard]] auto dispatch_get([[maybe_unused]] It &it, [[maybe_unused]] const Entity entt) const {
|
|
|
if constexpr(std::is_same_v<typename std::iterator_traits<It>::value_type, typename storage_type<Comp>::value_type>) {
|
|
|
@@ -246,11 +309,11 @@ class basic_view<Entity, exclude_t<Exclude...>, Component...> final {
|
|
|
template<typename Comp, typename Func>
|
|
|
void traverse(Func func) const {
|
|
|
if constexpr(std::is_void_v<decltype(std::get<storage_type<Comp> *>(pools)->get({}))>) {
|
|
|
- for(const auto entt: static_cast<const basic_sparse_set<entity_type> &>(*std::get<storage_type<Comp> *>(pools))) {
|
|
|
- if(((std::is_same_v<Comp, Component> || std::get<storage_type<Component> *>(pools)->contains(entt)) && ...)
|
|
|
- && !(std::get<const storage_type<Exclude> *>(filter)->contains(entt) || ...))
|
|
|
+ for(const auto entt: static_cast<const basic_common_type &>(*std::get<storage_type<Comp> *>(pools))) {
|
|
|
+ if(Policy::accept(entt) && ((std::is_same_v<Comp, Component> || std::get<storage_type<Component> *>(pools)->contains(entt)) && ...)
|
|
|
+ && (!std::get<const storage_type<Exclude> *>(filter)->contains(entt) && ...))
|
|
|
{
|
|
|
- if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_view>().get({})))>) {
|
|
|
+ if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_view_impl>().get({})))>) {
|
|
|
std::apply(func, std::tuple_cat(std::make_tuple(entt), get(entt)));
|
|
|
} else {
|
|
|
std::apply(func, get(entt));
|
|
|
@@ -260,11 +323,11 @@ class basic_view<Entity, exclude_t<Exclude...>, Component...> final {
|
|
|
} else {
|
|
|
auto it = std::get<storage_type<Comp> *>(pools)->begin();
|
|
|
|
|
|
- for(const auto entt: static_cast<const basic_sparse_set<entity_type> &>(*std::get<storage_type<Comp> *>(pools))) {
|
|
|
- if(((std::is_same_v<Comp, Component> || std::get<storage_type<Component> *>(pools)->contains(entt)) && ...)
|
|
|
- && !(std::get<const storage_type<Exclude> *>(filter)->contains(entt) || ...))
|
|
|
+ for(const auto entt: static_cast<const basic_common_type &>(*std::get<storage_type<Comp> *>(pools))) {
|
|
|
+ if(Policy::accept(entt) && ((std::is_same_v<Comp, Component> || std::get<storage_type<Component> *>(pools)->contains(entt)) && ...)
|
|
|
+ && (!std::get<const storage_type<Exclude> *>(filter)->contains(entt) && ...))
|
|
|
{
|
|
|
- if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_view>().get({})))>) {
|
|
|
+ if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_view_impl>().get({})))>) {
|
|
|
std::apply(func, std::tuple_cat(std::make_tuple(entt), dispatch_get<Component>(it, entt)...));
|
|
|
} else {
|
|
|
std::apply(func, std::tuple_cat(dispatch_get<Component>(it, entt)...));
|
|
|
@@ -282,12 +345,14 @@ public:
|
|
|
/*! @brief Unsigned integer type. */
|
|
|
using size_type = std::size_t;
|
|
|
/*! @brief Bidirectional iterator type. */
|
|
|
- using iterator = view_iterator<typename basic_sparse_set<entity_type>::iterator>;
|
|
|
+ using iterator = internal::view_iterator<Policy, typename basic_common_type::iterator, sizeof...(Component) - 1u, sizeof...(Exclude)>;
|
|
|
/*! @brief Reverse iterator type. */
|
|
|
- using reverse_iterator = view_iterator<typename basic_sparse_set<entity_type>::reverse_iterator>;
|
|
|
+ using reverse_iterator = internal::view_iterator<Policy, typename basic_common_type::reverse_iterator, sizeof...(Component) - 1u, sizeof...(Exclude)>;
|
|
|
+ /*! @brief Iterable view type. */
|
|
|
+ using iterable_view = iterable;
|
|
|
|
|
|
/*! @brief Default constructor to use to create empty, invalid views. */
|
|
|
- basic_view() ENTT_NOEXCEPT
|
|
|
+ basic_view_impl() ENTT_NOEXCEPT
|
|
|
: view{}
|
|
|
{}
|
|
|
|
|
|
@@ -296,7 +361,7 @@ public:
|
|
|
* @param component The storage for the types to iterate.
|
|
|
* @param epool The storage for the types used to filter the view.
|
|
|
*/
|
|
|
- basic_view(storage_type<Component> &... component, const storage_type<Exclude> &... epool) ENTT_NOEXCEPT
|
|
|
+ basic_view_impl(storage_type<Component> &... component, const storage_type<Exclude> &... epool) ENTT_NOEXCEPT
|
|
|
: pools{&component...},
|
|
|
filter{&epool...},
|
|
|
view{candidate()}
|
|
|
@@ -328,7 +393,7 @@ public:
|
|
|
* @return An iterator to the first entity of the view.
|
|
|
*/
|
|
|
[[nodiscard]] iterator begin() const {
|
|
|
- return iterator{view->begin(), view->end(), view->begin(), unchecked(view), filter};
|
|
|
+ return iterator{view->begin(), view->end(), view->begin(), pools_to_unchecked_array(), filter_to_array()};
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -341,7 +406,7 @@ public:
|
|
|
* @return An iterator to the entity following the last entity of the view.
|
|
|
*/
|
|
|
[[nodiscard]] iterator end() const {
|
|
|
- return iterator{view->begin(), view->end(), view->end(), unchecked(view), filter};
|
|
|
+ return iterator{view->begin(), view->end(), view->end(), pools_to_unchecked_array(), filter_to_array()};
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -353,7 +418,7 @@ public:
|
|
|
* @return An iterator to the first entity of the reversed view.
|
|
|
*/
|
|
|
[[nodiscard]] reverse_iterator rbegin() const {
|
|
|
- return reverse_iterator{view->rbegin(), view->rend(), view->rbegin(), unchecked(view), filter};
|
|
|
+ return reverse_iterator{view->rbegin(), view->rend(), view->rbegin(), pools_to_unchecked_array(), filter_to_array()};
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -368,7 +433,7 @@ public:
|
|
|
* reversed view.
|
|
|
*/
|
|
|
[[nodiscard]] reverse_iterator rend() const {
|
|
|
- return reverse_iterator{view->rbegin(), view->rend(), view->rend(), unchecked(view), filter};
|
|
|
+ return reverse_iterator{view->rbegin(), view->rend(), view->rend(), pools_to_unchecked_array(), filter_to_array()};
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -398,7 +463,7 @@ public:
|
|
|
* iterator otherwise.
|
|
|
*/
|
|
|
[[nodiscard]] iterator find(const entity_type entt) const {
|
|
|
- const auto it = iterator{view->begin(), view->end(), view->find(entt), unchecked(view), filter};
|
|
|
+ const auto it = iterator{view->begin(), view->end(), view->find(entt), pools_to_unchecked_array(), filter_to_array()};
|
|
|
return (it != end() && *it == entt) ? it : end();
|
|
|
}
|
|
|
|
|
|
@@ -416,7 +481,7 @@ public:
|
|
|
* @return True if the view contains the given entity, false otherwise.
|
|
|
*/
|
|
|
[[nodiscard]] bool contains(const entity_type entt) const {
|
|
|
- return (std::get<storage_type<Component> *>(pools)->contains(entt) && ...) && !(std::get<const storage_type<Exclude> *>(filter)->contains(entt) || ...);
|
|
|
+ return (std::get<storage_type<Component> *>(pools)->contains(entt) && ...) && (!std::get<const storage_type<Exclude> *>(filter)->contains(entt) && ...);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -480,9 +545,7 @@ public:
|
|
|
*
|
|
|
* The pool of the suggested component is used to lead the iterations. The
|
|
|
* returned entities will therefore respect the order of the pool associated
|
|
|
- * with that type.<br/>
|
|
|
- * It is no longer guaranteed that the performance is the best possible, but
|
|
|
- * there will be greater control over the order of iteration.
|
|
|
+ * with that type.
|
|
|
*
|
|
|
* @sa each
|
|
|
*
|
|
|
@@ -518,9 +581,7 @@ public:
|
|
|
*
|
|
|
* The pool of the suggested component is used to lead the iterations. The
|
|
|
* returned elements will therefore respect the order of the pool associated
|
|
|
- * with that type.<br/>
|
|
|
- * It is no longer guaranteed that the performance is the best possible, but
|
|
|
- * there will be greater control over the order of iteration.
|
|
|
+ * with that type.
|
|
|
*
|
|
|
* @sa each
|
|
|
*
|
|
|
@@ -548,7 +609,7 @@ public:
|
|
|
private:
|
|
|
const std::tuple<storage_type<Component> *...> pools;
|
|
|
const std::tuple<const storage_type<Exclude> *...> filter;
|
|
|
- mutable const basic_sparse_set<entity_type> *view;
|
|
|
+ mutable const basic_common_type *view;
|
|
|
};
|
|
|
|
|
|
|
|
|
@@ -584,34 +645,30 @@ private:
|
|
|
* @tparam Component Type of component iterated by the view.
|
|
|
*/
|
|
|
template<typename Entity, typename Component>
|
|
|
-class basic_view<Entity, exclude_t<>, Component> final {
|
|
|
+class basic_view_impl<packed_storage_policy, Entity, exclude_t<>, Component> {
|
|
|
+ using basic_common_type = basic_sparse_set<Entity>;
|
|
|
using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Component>>::storage_type, Component>;
|
|
|
|
|
|
- class iterable_view final {
|
|
|
- friend class basic_view<Entity, exclude_t<>, Component>;
|
|
|
-
|
|
|
+ class iterable final {
|
|
|
template<typename... It>
|
|
|
- class iterable_view_iterator final {
|
|
|
- friend class iterable_view;
|
|
|
-
|
|
|
- template<typename... Discard>
|
|
|
- iterable_view_iterator(It... from, Discard...) ENTT_NOEXCEPT
|
|
|
- : it{from...}
|
|
|
- {}
|
|
|
-
|
|
|
- public:
|
|
|
+ struct iterable_iterator final {
|
|
|
using difference_type = std::ptrdiff_t;
|
|
|
- using value_type = decltype(std::tuple_cat(std::tuple<Entity>{}, std::declval<basic_view>().get({})));
|
|
|
+ using value_type = decltype(std::tuple_cat(std::tuple<Entity>{}, std::declval<basic_view_impl>().get({})));
|
|
|
using pointer = void;
|
|
|
using reference = value_type;
|
|
|
using iterator_category = std::input_iterator_tag;
|
|
|
|
|
|
- iterable_view_iterator & operator++() ENTT_NOEXCEPT {
|
|
|
+ template<typename... Discard>
|
|
|
+ iterable_iterator(It... from, Discard...) ENTT_NOEXCEPT
|
|
|
+ : it{from...}
|
|
|
+ {}
|
|
|
+
|
|
|
+ iterable_iterator & operator++() ENTT_NOEXCEPT {
|
|
|
return (++std::get<It>(it), ...), *this;
|
|
|
}
|
|
|
|
|
|
- iterable_view_iterator operator++(int) ENTT_NOEXCEPT {
|
|
|
- iterable_view_iterator orig = *this;
|
|
|
+ iterable_iterator operator++(int) ENTT_NOEXCEPT {
|
|
|
+ iterable_iterator orig = *this;
|
|
|
return ++(*this), orig;
|
|
|
}
|
|
|
|
|
|
@@ -619,11 +676,11 @@ class basic_view<Entity, exclude_t<>, Component> final {
|
|
|
return { *std::get<It>(it)... };
|
|
|
}
|
|
|
|
|
|
- [[nodiscard]] bool operator==(const iterable_view_iterator &other) const ENTT_NOEXCEPT {
|
|
|
+ [[nodiscard]] bool operator==(const iterable_iterator &other) const ENTT_NOEXCEPT {
|
|
|
return std::get<0>(other.it) == std::get<0>(it);
|
|
|
}
|
|
|
|
|
|
- [[nodiscard]] bool operator!=(const iterable_view_iterator &other) const ENTT_NOEXCEPT {
|
|
|
+ [[nodiscard]] bool operator!=(const iterable_iterator &other) const ENTT_NOEXCEPT {
|
|
|
return !(*this == other);
|
|
|
}
|
|
|
|
|
|
@@ -631,36 +688,36 @@ class basic_view<Entity, exclude_t<>, Component> final {
|
|
|
std::tuple<It...> it;
|
|
|
};
|
|
|
|
|
|
- iterable_view(storage_type &ref)
|
|
|
- : pool{&ref}
|
|
|
- {}
|
|
|
-
|
|
|
public:
|
|
|
using iterator = std::conditional_t<
|
|
|
std::is_void_v<decltype(std::declval<storage_type>().get({}))>,
|
|
|
- iterable_view_iterator<typename basic_sparse_set<Entity>::iterator>,
|
|
|
- iterable_view_iterator<typename basic_sparse_set<Entity>::iterator, decltype(std::declval<storage_type>().begin())>
|
|
|
+ iterable_iterator<typename basic_common_type::iterator>,
|
|
|
+ iterable_iterator<typename basic_common_type::iterator, decltype(std::declval<storage_type>().begin())>
|
|
|
>;
|
|
|
using reverse_iterator = std::conditional_t<
|
|
|
std::is_void_v<decltype(std::declval<storage_type>().get({}))>,
|
|
|
- iterable_view_iterator<typename basic_sparse_set<Entity>::reverse_iterator>,
|
|
|
- iterable_view_iterator<typename basic_sparse_set<Entity>::reverse_iterator, decltype(std::declval<storage_type>().rbegin())>
|
|
|
+ iterable_iterator<typename basic_common_type::reverse_iterator>,
|
|
|
+ iterable_iterator<typename basic_common_type::reverse_iterator, decltype(std::declval<storage_type>().rbegin())>
|
|
|
>;
|
|
|
|
|
|
+ iterable(storage_type &ref)
|
|
|
+ : pool{&ref}
|
|
|
+ {}
|
|
|
+
|
|
|
[[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
|
|
|
- return iterator{pool->basic_sparse_set<entity_type>::begin(), pool->begin()};
|
|
|
+ return iterator{pool->basic_common_type::begin(), pool->begin()};
|
|
|
}
|
|
|
|
|
|
[[nodiscard]] iterator end() const ENTT_NOEXCEPT {
|
|
|
- return iterator{pool->basic_sparse_set<entity_type>::end(), pool->end()};
|
|
|
+ return iterator{pool->basic_common_type::end(), pool->end()};
|
|
|
}
|
|
|
|
|
|
[[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT {
|
|
|
- return reverse_iterator{pool->basic_sparse_set<entity_type>::rbegin(), pool->rbegin()};
|
|
|
+ return reverse_iterator{pool->basic_common_type::rbegin(), pool->rbegin()};
|
|
|
}
|
|
|
|
|
|
[[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
|
|
|
- return reverse_iterator{pool->basic_sparse_set<entity_type>::rend(), pool->rend()};
|
|
|
+ return reverse_iterator{pool->basic_common_type::rend(), pool->rend()};
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
@@ -673,12 +730,14 @@ public:
|
|
|
/*! @brief Unsigned integer type. */
|
|
|
using size_type = std::size_t;
|
|
|
/*! @brief Random access iterator type. */
|
|
|
- using iterator = typename basic_sparse_set<Entity>::iterator;
|
|
|
+ using iterator = typename basic_common_type::iterator;
|
|
|
/*! @brief Reversed iterator type. */
|
|
|
- using reverse_iterator = typename basic_sparse_set<Entity>::reverse_iterator;
|
|
|
+ using reverse_iterator = typename basic_common_type::reverse_iterator;
|
|
|
+ /*! @brief Iterable view type. */
|
|
|
+ using iterable_view = iterable;
|
|
|
|
|
|
/*! @brief Default constructor to use to create empty, invalid views. */
|
|
|
- basic_view() ENTT_NOEXCEPT
|
|
|
+ basic_view_impl() ENTT_NOEXCEPT
|
|
|
: pools{},
|
|
|
filter{}
|
|
|
{}
|
|
|
@@ -687,7 +746,7 @@ public:
|
|
|
* @brief Constructs a single-type view from a storage class.
|
|
|
* @param ref The storage for the type to iterate.
|
|
|
*/
|
|
|
- basic_view(storage_type &ref) ENTT_NOEXCEPT
|
|
|
+ basic_view_impl(storage_type &ref) ENTT_NOEXCEPT
|
|
|
: pools{&ref},
|
|
|
filter{}
|
|
|
{}
|
|
|
@@ -737,7 +796,7 @@ public:
|
|
|
* @return An iterator to the first entity of the view.
|
|
|
*/
|
|
|
[[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
|
|
|
- return std::get<0>(pools)->basic_sparse_set<entity_type>::begin();
|
|
|
+ return std::get<0>(pools)->basic_common_type::begin();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -750,7 +809,7 @@ public:
|
|
|
* @return An iterator to the entity following the last entity of the view.
|
|
|
*/
|
|
|
[[nodiscard]] iterator end() const ENTT_NOEXCEPT {
|
|
|
- return std::get<0>(pools)->basic_sparse_set<entity_type>::end();
|
|
|
+ return std::get<0>(pools)->basic_common_type::end();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -762,7 +821,7 @@ public:
|
|
|
* @return An iterator to the first entity of the reversed view.
|
|
|
*/
|
|
|
[[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT {
|
|
|
- return std::get<0>(pools)->basic_sparse_set<entity_type>::rbegin();
|
|
|
+ return std::get<0>(pools)->basic_common_type::rbegin();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -777,7 +836,7 @@ public:
|
|
|
* reversed view.
|
|
|
*/
|
|
|
[[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
|
|
|
- return std::get<0>(pools)->basic_sparse_set<entity_type>::rend();
|
|
|
+ return std::get<0>(pools)->basic_common_type::rend();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -946,6 +1005,22 @@ private:
|
|
|
};
|
|
|
|
|
|
|
|
|
+/**
|
|
|
+ * @brief View implementation dispatcher.
|
|
|
+ * @tparam Entity A valid entity type (see entt_traits for more details).
|
|
|
+ * @tparam Exclude Types of components used to filter the view.
|
|
|
+ * @tparam Component Types of components iterated by the view.
|
|
|
+ */
|
|
|
+template<typename Entity, typename... Exclude, typename... Component>
|
|
|
+struct basic_view<Entity, exclude_t<Exclude...>, Component...>
|
|
|
+ : basic_view_impl<std::conditional_t<std::disjunction_v<typename component_traits<std::remove_const_t<Component>>::in_place_delete...>, stable_storage_policy, packed_storage_policy>, Entity, exclude_t<Exclude...>, Component...>
|
|
|
+{
|
|
|
+ /*! @brief Most restrictive storage policy of all component types. */
|
|
|
+ using storage_policy = std::conditional_t<std::disjunction_v<typename component_traits<std::remove_const_t<Component>>::in_place_delete...>, stable_storage_policy, packed_storage_policy>;
|
|
|
+ using basic_view_impl<storage_policy, Entity, exclude_t<Exclude...>, Component...>::basic_view_impl;
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* @brief Deduction guide.
|
|
|
* @tparam Storage Type of storage classes used to create the view.
|