sort owning groups by owned components

This commit is contained in:
Michele Caini
2019-04-14 18:29:17 +02:00
parent a47471d0ae
commit f66db81edd
3 changed files with 34 additions and 18 deletions

View File

@@ -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

View File

@@ -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<size_type> 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>(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) {
auto curr = pos;

View File

@@ -641,7 +641,7 @@ TEST(OwningGroup, SortReverse) {
TEST(OwningGroup, SortUnordered) {
entt::registry registry;
auto group = registry.group<boxed_int, char>();
auto group = registry.group<boxed_int>(entt::get<char>);
entt::entity entities[7] = {
registry.create(),
@@ -671,8 +671,8 @@ TEST(OwningGroup, SortUnordered) {
registry.assign<boxed_int>(entities[5], 4);
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]);
@@ -691,11 +691,11 @@ 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), '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) {