|
|
@@ -94,22 +94,21 @@ class basic_group;
|
|
|
*
|
|
|
* @tparam Entity A valid entity type (see entt_traits for more details).
|
|
|
* @tparam Exclude Types of components used to filter the group.
|
|
|
- * @tparam Get Types of components observed by the group.
|
|
|
+ * @tparam Get Type of component observed by the group.
|
|
|
+ * @tparam Other Other types of components observed by the group.
|
|
|
*/
|
|
|
-template<typename Entity, typename... Exclude, typename... Get>
|
|
|
-class basic_group<Entity, exclude_t<Exclude...>, get_t<Get...>> {
|
|
|
- static_assert(sizeof...(Get) > 0);
|
|
|
-
|
|
|
+template<typename Entity, typename... Exclude, typename Get, typename... Other>
|
|
|
+class basic_group<Entity, exclude_t<Exclude...>, get_t<Get, Other...>> {
|
|
|
/*! @brief A registry is allowed to create groups. */
|
|
|
friend class basic_registry<Entity>;
|
|
|
|
|
|
template<typename Component>
|
|
|
using pool_type = std::conditional_t<std::is_const_v<Component>, const storage<Entity, std::remove_const_t<Component>>, storage<Entity, Component>>;
|
|
|
|
|
|
- // we could use pool_type<Get> *..., but vs complains about it and refuses to compile for unknown reasons (likely a bug)
|
|
|
- basic_group(sparse_set<Entity> *ref, storage<Entity, std::remove_const_t<Get>> *... get) ENTT_NOEXCEPT
|
|
|
+ // we could use pool_type<Type> *..., but vs complains about it and refuses to compile for unknown reasons (most likely a bug)
|
|
|
+ basic_group(sparse_set<Entity> *ref, storage<Entity, std::remove_const_t<Get>> *get, storage<Entity, std::remove_const_t<Other>> *... other) ENTT_NOEXCEPT
|
|
|
: handler{ref},
|
|
|
- pools{get...}
|
|
|
+ pools{get, other...}
|
|
|
{}
|
|
|
|
|
|
template<typename Func, typename... Weak>
|
|
|
@@ -341,8 +340,8 @@ public:
|
|
|
* forms:
|
|
|
*
|
|
|
* @code{.cpp}
|
|
|
- * void(const entity_type, Get &...);
|
|
|
- * void(Get &...);
|
|
|
+ * void(const entity_type, Get &, Other &...);
|
|
|
+ * void(Get &, Other &...);
|
|
|
* @endcode
|
|
|
*
|
|
|
* @note
|
|
|
@@ -355,7 +354,7 @@ public:
|
|
|
*/
|
|
|
template<typename Func>
|
|
|
void each(Func func) const {
|
|
|
- traverse(std::move(func), type_list<Get...>{});
|
|
|
+ traverse(std::move(func), type_list<Get, Other...>{});
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -380,8 +379,9 @@ public:
|
|
|
*/
|
|
|
template<typename Func>
|
|
|
void less(Func func) const {
|
|
|
- using non_empty_get = type_list_cat_t<std::conditional_t<std::is_empty_v<Get>, type_list<>, type_list<Get>>...>;
|
|
|
- traverse(std::move(func), non_empty_get{});
|
|
|
+ using get_type_list = std::conditional_t<std::is_empty_v<Get>, type_list<>, type_list<Get>>;
|
|
|
+ using other_type_list = type_list_cat_t<std::conditional_t<std::is_empty_v<Other>, type_list<>, type_list<Other>>...>;
|
|
|
+ traverse(std::move(func), type_list_cat_t<get_type_list, other_type_list>{});
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -407,7 +407,7 @@ public:
|
|
|
|
|
|
private:
|
|
|
sparse_set<entity_type> *handler;
|
|
|
- const std::tuple<pool_type<Get> *...> pools;
|
|
|
+ const std::tuple<pool_type<Get> *, pool_type<Other> *...> pools;
|
|
|
};
|
|
|
|
|
|
|
|
|
@@ -456,12 +456,11 @@ private:
|
|
|
* @tparam Entity A valid entity type (see entt_traits for more details).
|
|
|
* @tparam Exclude Types of components used to filter the group.
|
|
|
* @tparam Get Types of components observed by the group.
|
|
|
- * @tparam Owned Types of components owned by the group.
|
|
|
+ * @tparam Owned Type of component owned by the group.
|
|
|
+ * @tparam Other Other types of components owned by the group.
|
|
|
*/
|
|
|
-template<typename Entity, typename... Exclude, typename... Get, typename... Owned>
|
|
|
-class basic_group<Entity, exclude_t<Exclude...>, get_t<Get...>, Owned...> {
|
|
|
- static_assert(sizeof...(Get) + sizeof...(Owned) > 0);
|
|
|
-
|
|
|
+template<typename Entity, typename... Exclude, typename... Get, typename Owned, typename... Other>
|
|
|
+class basic_group<Entity, exclude_t<Exclude...>, get_t<Get...>, Owned, Other...> {
|
|
|
/*! @brief A registry is allowed to create groups. */
|
|
|
friend class basic_registry<Entity>;
|
|
|
|
|
|
@@ -471,16 +470,16 @@ class basic_group<Entity, exclude_t<Exclude...>, get_t<Get...>, Owned...> {
|
|
|
template<typename Component>
|
|
|
using component_iterator_type = decltype(std::declval<pool_type<Component>>().begin());
|
|
|
|
|
|
- // we could use pool_type<Type> *..., but vs complains about it and refuses to compile for unknown reasons (likely a bug)
|
|
|
- basic_group(const typename basic_registry<Entity>::size_type *sz, storage<Entity, std::remove_const_t<Owned>> *... owned, storage<Entity, std::remove_const_t<Get>> *... get) ENTT_NOEXCEPT
|
|
|
+ // we could use pool_type<Type> *..., but vs complains about it and refuses to compile for unknown reasons (most likely a bug)
|
|
|
+ basic_group(const typename basic_registry<Entity>::size_type *sz, storage<Entity, std::remove_const_t<Owned>> *owned, storage<Entity, std::remove_const_t<Other>> *... other, storage<Entity, std::remove_const_t<Get>> *... get) ENTT_NOEXCEPT
|
|
|
: length{sz},
|
|
|
- pools{owned..., get...}
|
|
|
+ pools{owned, other..., get...}
|
|
|
{}
|
|
|
|
|
|
template<typename Func, typename... Strong, typename... Weak>
|
|
|
void traverse(Func func, type_list<Strong...>, type_list<Weak...>) const {
|
|
|
[[maybe_unused]] auto raw = std::make_tuple((std::get<pool_type<Strong> *>(pools)->end() - *length)...);
|
|
|
- [[maybe_unused]] auto data = std::get<0>(pools)->sparse_set<entity_type>::end() - *length;
|
|
|
+ [[maybe_unused]] auto data = std::get<pool_type<Owned> *>(pools)->sparse_set<entity_type>::end() - *length;
|
|
|
|
|
|
for(auto next = *length; next; --next) {
|
|
|
if constexpr(std::is_invocable_v<Func, decltype(get<Strong>({}))..., decltype(get<Weak>({}))...>) {
|
|
|
@@ -599,7 +598,7 @@ public:
|
|
|
* @return A pointer to the array of entities.
|
|
|
*/
|
|
|
const entity_type * data() const ENTT_NOEXCEPT {
|
|
|
- return std::get<0>(pools)->data();
|
|
|
+ return std::get<pool_type<Owned> *>(pools)->data();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -617,7 +616,7 @@ public:
|
|
|
* @return An iterator to the first entity that has the given components.
|
|
|
*/
|
|
|
iterator_type begin() const ENTT_NOEXCEPT {
|
|
|
- return std::get<0>(pools)->sparse_set<entity_type>::end() - *length;
|
|
|
+ return std::get<pool_type<Owned> *>(pools)->sparse_set<entity_type>::end() - *length;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -636,7 +635,7 @@ public:
|
|
|
* given components.
|
|
|
*/
|
|
|
iterator_type end() const ENTT_NOEXCEPT {
|
|
|
- return std::get<0>(pools)->sparse_set<entity_type>::end();
|
|
|
+ return std::get<pool_type<Owned> *>(pools)->sparse_set<entity_type>::end();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -646,7 +645,7 @@ public:
|
|
|
* iterator otherwise.
|
|
|
*/
|
|
|
iterator_type find(const entity_type entt) const ENTT_NOEXCEPT {
|
|
|
- const auto it = std::get<0>(pools)->find(entt);
|
|
|
+ const auto it = std::get<pool_type<Owned> *>(pools)->find(entt);
|
|
|
return it != end() && it >= begin() && *it == entt ? it : end();
|
|
|
}
|
|
|
|
|
|
@@ -707,8 +706,8 @@ public:
|
|
|
* forms:
|
|
|
*
|
|
|
* @code{.cpp}
|
|
|
- * void(const entity_type, Owned &..., Get &...);
|
|
|
- * void(Owned &..., Get &...);
|
|
|
+ * void(const entity_type, Owned &, Other &..., Get &...);
|
|
|
+ * void(Owned &, Other &..., Get &...);
|
|
|
* @endcode
|
|
|
*
|
|
|
* @note
|
|
|
@@ -721,7 +720,7 @@ public:
|
|
|
*/
|
|
|
template<typename Func>
|
|
|
void each(Func func) const {
|
|
|
- traverse(std::move(func), type_list<Owned...>{}, type_list<Get...>{});
|
|
|
+ traverse(std::move(func), type_list<Owned, Other...>{}, type_list<Get...>{});
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -746,9 +745,10 @@ public:
|
|
|
*/
|
|
|
template<typename Func>
|
|
|
void less(Func func) const {
|
|
|
- using non_empty_owned = type_list_cat_t<std::conditional_t<std::is_empty_v<Owned>, type_list<>, type_list<Owned>>...>;
|
|
|
- using non_empty_get = type_list_cat_t<std::conditional_t<std::is_empty_v<Get>, type_list<>, type_list<Get>>...>;
|
|
|
- traverse(std::move(func), non_empty_owned{}, non_empty_get{});
|
|
|
+ using owned_type_list = std::conditional_t<std::is_empty_v<Owned>, type_list<>, type_list<Owned>>;
|
|
|
+ using other_type_list = type_list_cat_t<std::conditional_t<std::is_empty_v<Other>, type_list<>, type_list<Other>>...>;
|
|
|
+ using get_type_list = type_list_cat_t<std::conditional_t<std::is_empty_v<Get>, type_list<>, type_list<Get>>...>;
|
|
|
+ traverse(std::move(func), type_list_cat_t<owned_type_list, other_type_list>{}, get_type_list{});
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -798,36 +798,32 @@ public:
|
|
|
*/
|
|
|
template<typename... Component, typename Compare, typename Sort = std_sort, typename... Args>
|
|
|
void sort(Compare compare, Sort algo = Sort{}, Args &&... args) {
|
|
|
- std::vector<size_type> copy(*length);
|
|
|
- std::iota(copy.begin(), copy.end(), 0);
|
|
|
+ auto *cpool = std::get<pool_type<Owned> *>(pools);
|
|
|
|
|
|
if constexpr(sizeof...(Component) == 0) {
|
|
|
- algo(copy.rbegin(), copy.rend(), [compare = std::move(compare), data = data()](const auto lhs, const auto rhs) {
|
|
|
- return compare(data[lhs], data[rhs]);
|
|
|
- }, std::forward<Args>(args)...);
|
|
|
+ static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>);
|
|
|
+ cpool->sort(cpool->end()-*length, cpool->end(), std::move(compare), std::move(algo), std::forward<Args>(args)...);
|
|
|
} else {
|
|
|
- algo(copy.rbegin(), copy.rend(), [compare = std::move(compare), data = data(), this](const auto lhs, const auto rhs) {
|
|
|
+ cpool->sort(cpool->end()-*length, cpool->end(), [compare = std::move(compare), this](const entity_type lhs, const entity_type rhs) {
|
|
|
// useless this-> used to suppress a warning with clang
|
|
|
- return compare(this->get<Component>(data[lhs])..., this->get<Component>(data[rhs])...);
|
|
|
- }, std::forward<Args>(args)...);
|
|
|
+ return compare(this->get<Component>(lhs)..., this->get<Component>(rhs)...);
|
|
|
+ }, std::move(algo), std::forward<Args>(args)...);
|
|
|
}
|
|
|
|
|
|
- for(size_type pos{}, last = copy.size(); pos < last; ++pos) {
|
|
|
- auto curr = pos;
|
|
|
- auto next = copy[curr];
|
|
|
+ for(auto next = *length; next; --next) {
|
|
|
+ ([next = next-1, curr = cpool->data()[next-1]](auto *cpool) {
|
|
|
+ const auto pos = cpool->sparse_set<entity_type>::get(curr);
|
|
|
|
|
|
- while(curr != next) {
|
|
|
- (std::get<pool_type<Owned> *>(pools)->swap(copy[curr], copy[next]), ...);
|
|
|
- copy[curr] = curr;
|
|
|
- curr = next;
|
|
|
- next = copy[curr];
|
|
|
- }
|
|
|
+ if(pos != next) {
|
|
|
+ cpool->swap(next, cpool->sparse_set<entity_type>::get(curr));
|
|
|
+ }
|
|
|
+ }(std::get<pool_type<Other> *>(pools)), ...);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
const typename basic_registry<Entity>::size_type *length;
|
|
|
- const std::tuple<pool_type<Owned> *..., pool_type<Get> *...> pools;
|
|
|
+ const std::tuple<pool_type<Owned> *, pool_type<Other> *..., pool_type<Get> *...> pools;
|
|
|
};
|
|
|
|
|
|
|