Procházet zdrojové kódy

better sorting functionality for groups

Michele Caini před 6 roky
rodič
revize
e01230e425
2 změnil soubory, kde provedl 30 přidání a 15 odebrání
  1. 22 7
      src/entt/entity/group.hpp
  2. 8 8
      test/entt/entity/group.cpp

+ 22 - 7
src/entt/entity/group.hpp

@@ -681,10 +681,12 @@ public:
      * comparison function should be equivalent to one of the following:
      *
      * @code{.cpp}
-     * bool(const Owned &..., const Owned &...);
+     * bool(const Component &..., const Component &...);
      * bool(const Entity, const Entity);
      * @endcode
      *
+     * Where `Component` are either owned types or not but still such that they
+     * are iterated by the group.<br/>
      * Moreover, the comparison function object shall induce a
      * _strict weak ordering_ on the values.
      *
@@ -704,6 +706,7 @@ public:
      * either `data` or `raw` gives no guarantees on the order, even though
      * `sort` has been invoked.
      *
+     * @tparam Component Optional types of components to compare.
      * @tparam Compare Type of comparison function object.
      * @tparam Sort Type of sort function object.
      * @tparam Args Types of arguments to forward to the sort function object.
@@ -711,19 +714,31 @@ public:
      * @param algo A valid sort function object.
      * @param args Arguments to forward to the sort function object, if any.
      */
-    template<typename Compare, typename Sort = std_sort, typename... Args>
+    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);
 
-        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 {
+        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)...);
+        } else {
+            algo(copy.rbegin(), copy.rend(), [compare = std::move(compare), this](const auto lhs, const auto rhs) {
+                return compare([lhs, this](auto *cpool) -> decltype(auto) {
+                    if constexpr(std::disjunction_v<std::is_same<typename std::remove_pointer_t<decltype(cpool)>::object_type, Owned>...>) {
+                        return cpool->raw()[lhs];
+                    } else {
+                        return cpool->get(data()[lhs]);
+                    }
+                }(std::get<pool_type<Component> *>(pools))..., [rhs, this](auto *cpool) -> decltype(auto) {
+                    if constexpr(std::disjunction_v<std::is_same<typename std::remove_pointer_t<decltype(cpool)>::object_type, Owned>...>) {
+                        return cpool->raw()[rhs];
+                    } else {
+                        return cpool->get(data()[rhs]);
+                    }
+                }(std::get<pool_type<Component> *>(pools))...);
+            }, std::forward<Args>(args)...);
         }
 
         for(size_type pos = 0, last = copy.size(); pos < last; ++pos) {

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

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