Просмотр исходного кода

sort owning groups by owned components

Michele Caini 6 лет назад
Родитель
Сommit
f66db81edd
3 измененных файлов с 34 добавлено и 18 удалено
  1. 12 6
      docs/md/entity.md
  2. 14 4
      src/entt/entity/group.hpp
  3. 8 8
      test/entt/entity/group.cpp

+ 12 - 6
docs/md/entity.md

@@ -1186,8 +1186,10 @@ the template parameter list and arranges their pools so as to iterate all of
 them as fast as possible.
 them as fast as possible.
 
 
 Sorting owned components is no longer allowed once the group has been created.
 Sorting owned components is no longer allowed once the group has been created.
-However, full-owning groups can be sorted by means of the `sort` member
-function, if required.
+However, full-owning groups can be sorted by means of their `sort` member
+functions, if required. Sorting a full-owning group affects all the instance of
+the same group (it means that users don't have to call `sort` on each instance
+to sort all of them because they share the underlying data structure).
 
 
 ### Partial-owning groups
 ### Partial-owning groups
 
 
@@ -1215,8 +1217,10 @@ them as fast as possible. The ownership of the types provided via `entt::get`
 doesn't pass to the group instead.
 doesn't pass to the group instead.
 
 
 Sorting owned components is no longer allowed once the group has been created.
 Sorting owned components is no longer allowed once the group has been created.
-However, partial-owning groups can be sorted by means of the `sort` member
-function, if required.
+However, partial-owning groups can be sorted by means of their `sort` member
+functions, if required. Sorting a partial-owning group affects all the instance
+of the same group (it means that users don't have to call `sort` on each
+instance to sort all of them because they share the underlying data structure).
 
 
 ### Non-owning groups
 ### Non-owning groups
 
 
@@ -1242,8 +1246,10 @@ case. This type of groups is therefore the least performing in general, but also
 the only one that can be used in any situation to improve a performance where
 the only one that can be used in any situation to improve a performance where
 necessary.
 necessary.
 
 
-Non-owning groups can be sorted by means of the `sort` member function, if
-required.
+Non-owning groups can be sorted by means of their `sort` member functions, if
+required. Sorting a non-owning group affects all the instance of the same group
+(it means that users don't have to call `sort` on each instance to sort all of
+them because they share the set of entities).
 
 
 # Types: const, non-const and all in between
 # Types: const, non-const and all in between
 
 

+ 14 - 4
src/entt/entity/group.hpp

@@ -395,6 +395,9 @@ private:
  * that generated them. Therefore any change to the entities and to the
  * that generated them. Therefore any change to the entities and to the
  * components made by means of the registry are immediately reflected by all the
  * components made by means of the registry are immediately reflected by all the
  * groups.
  * groups.
+ * Moreover, sorting an owning group affects all the instance of the same group
+ * (it means that users don't have to call `sort` on each instance to sort all
+ * of them because they share the underlying data structure).
  *
  *
  * @warning
  * @warning
  * Lifetime of a group must overcome the one of the registry that generated it.
  * Lifetime of a group must overcome the one of the registry that generated it.
@@ -675,9 +678,10 @@ public:
      *
      *
      * The comparison function object must return `true` if the first element
      * The comparison function object must return `true` if the first element
      * is _less_ than the second one, `false` otherwise. The signature of the
      * is _less_ than the second one, `false` otherwise. The signature of the
-     * comparison function should be equivalent to the following:
+     * comparison function should be equivalent to one of the following:
      *
      *
      * @code{.cpp}
      * @code{.cpp}
+     * bool(const Owned &..., const Owned &...);
      * bool(const Entity, const Entity);
      * bool(const Entity, const Entity);
      * @endcode
      * @endcode
      *
      *
@@ -712,9 +716,15 @@ public:
         std::vector<size_type> copy(*length);
         std::vector<size_type> copy(*length);
         std::iota(copy.begin(), copy.end(), 0);
         std::iota(copy.begin(), copy.end(), 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)...);
+        if constexpr(std::is_invocable_v<Compare, const Owned &..., const Owned &...>) {
+            algo(copy.rbegin(), copy.rend(), [compare = std::move(compare), raw = std::make_tuple(std::get<pool_type<Owned> *>(pools)->raw()...)](const auto lhs, const auto rhs) {
+                return compare(std::as_const(std::get<Owned *>(raw)[lhs])..., std::as_const(std::get<Owned *>(raw)[rhs])...);
+            }, std::forward<Args>(args)...);
+        } else {
+            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)...);
+        }
 
 
         for(size_type pos = 0, last = copy.size(); pos < last; ++pos) {
         for(size_type pos = 0, last = copy.size(); pos < last; ++pos) {
             auto curr = pos;
             auto curr = pos;

+ 8 - 8
test/entt/entity/group.cpp

@@ -641,7 +641,7 @@ TEST(OwningGroup, SortReverse) {
 
 
 TEST(OwningGroup, SortUnordered) {
 TEST(OwningGroup, SortUnordered) {
     entt::registry registry;
     entt::registry registry;
-    auto group = registry.group<boxed_int, char>();
+    auto group = registry.group<boxed_int>(entt::get<char>);
 
 
     entt::entity entities[7] = {
     entt::entity entities[7] = {
         registry.create(),
         registry.create(),
@@ -671,8 +671,8 @@ TEST(OwningGroup, SortUnordered) {
     registry.assign<boxed_int>(entities[5], 4);
     registry.assign<boxed_int>(entities[5], 4);
     registry.assign<boxed_int>(entities[6], 5);
     registry.assign<boxed_int>(entities[6], 5);
 
 
-    group.sort([&group](const auto lhs, const auto rhs) {
-        return group.get<boxed_int>(lhs).value < group.get<boxed_int>(rhs).value;
+    group.sort([](const auto &lhs, const auto &rhs) {
+        return lhs.value < rhs.value;
     });
     });
 
 
     ASSERT_EQ(*(group.data() + 0u), entities[4]);
     ASSERT_EQ(*(group.data() + 0u), entities[4]);
@@ -691,11 +691,11 @@ TEST(OwningGroup, SortUnordered) {
     ASSERT_EQ((group.raw<boxed_int>() + 5u)->value, 4);
     ASSERT_EQ((group.raw<boxed_int>() + 5u)->value, 4);
     ASSERT_EQ((group.raw<boxed_int>() + 6u)->value, 5);
     ASSERT_EQ((group.raw<boxed_int>() + 6u)->value, 5);
 
 
-    ASSERT_EQ(*(group.raw<char>() + 0u), 'e');
-    ASSERT_EQ(*(group.raw<char>() + 1u), 'd');
-    ASSERT_EQ(*(group.raw<char>() + 2u), 'a');
-    ASSERT_EQ(*(group.raw<char>() + 3u), 'b');
-    ASSERT_EQ(*(group.raw<char>() + 4u), 'c');
+    ASSERT_EQ(*(group.raw<char>() + 0u), 'a');
+    ASSERT_EQ(*(group.raw<char>() + 1u), 'b');
+    ASSERT_EQ(*(group.raw<char>() + 2u), 'c');
+    ASSERT_EQ(*(group.raw<char>() + 3u), 'd');
+    ASSERT_EQ(*(group.raw<char>() + 4u), 'e');
 }
 }
 
 
 TEST(OwningGroup, IndexRebuiltOnDestroy) {
 TEST(OwningGroup, IndexRebuiltOnDestroy) {