From f66db81edd379a0863476e6b6876751e1caa615c Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Sun, 14 Apr 2019 18:29:17 +0200 Subject: [PATCH] sort owning groups by owned components --- docs/md/entity.md | 18 ++++++++++++------ src/entt/entity/group.hpp | 18 ++++++++++++++---- test/entt/entity/group.cpp | 16 ++++++++-------- 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/docs/md/entity.md b/docs/md/entity.md index 5c98b5e98..8c9b2f720 100644 --- a/docs/md/entity.md +++ b/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. 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 @@ -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. 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 @@ -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 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 diff --git a/src/entt/entity/group.hpp b/src/entt/entity/group.hpp index 3e264e7dd..d43af9e28 100644 --- a/src/entt/entity/group.hpp +++ b/src/entt/entity/group.hpp @@ -395,6 +395,9 @@ private: * 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 * 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 * 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 * 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} + * bool(const Owned &..., const Owned &...); * bool(const Entity, const Entity); * @endcode * @@ -712,9 +716,15 @@ public: std::vector copy(*length); 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)...); + if constexpr(std::is_invocable_v) { + algo(copy.rbegin(), copy.rend(), [compare = std::move(compare), raw = std::make_tuple(std::get *>(pools)->raw()...)](const auto lhs, const auto rhs) { + return compare(std::as_const(std::get(raw)[lhs])..., std::as_const(std::get(raw)[rhs])...); + }, std::forward(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)...); + } for(size_type pos = 0, last = copy.size(); pos < last; ++pos) { auto curr = pos; diff --git a/test/entt/entity/group.cpp b/test/entt/entity/group.cpp index abac1f48d..02b2945f0 100644 --- a/test/entt/entity/group.cpp +++ b/test/entt/entity/group.cpp @@ -641,7 +641,7 @@ TEST(OwningGroup, SortReverse) { TEST(OwningGroup, SortUnordered) { entt::registry registry; - auto group = registry.group(); + auto group = registry.group(entt::get); entt::entity entities[7] = { registry.create(), @@ -671,8 +671,8 @@ TEST(OwningGroup, SortUnordered) { registry.assign(entities[5], 4); registry.assign(entities[6], 5); - group.sort([&group](const auto lhs, const auto rhs) { - return group.get(lhs).value < group.get(rhs).value; + group.sort([](const auto &lhs, const auto &rhs) { + return lhs.value < rhs.value; }); ASSERT_EQ(*(group.data() + 0u), entities[4]); @@ -691,11 +691,11 @@ TEST(OwningGroup, SortUnordered) { ASSERT_EQ((group.raw() + 5u)->value, 4); ASSERT_EQ((group.raw() + 6u)->value, 5); - ASSERT_EQ(*(group.raw() + 0u), 'e'); - ASSERT_EQ(*(group.raw() + 1u), 'd'); - ASSERT_EQ(*(group.raw() + 2u), 'a'); - ASSERT_EQ(*(group.raw() + 3u), 'b'); - ASSERT_EQ(*(group.raw() + 4u), 'c'); + ASSERT_EQ(*(group.raw() + 0u), 'a'); + ASSERT_EQ(*(group.raw() + 1u), 'b'); + ASSERT_EQ(*(group.raw() + 2u), 'c'); + ASSERT_EQ(*(group.raw() + 3u), 'd'); + ASSERT_EQ(*(group.raw() + 4u), 'e'); } TEST(OwningGroup, IndexRebuiltOnDestroy) {