storage/view/group: reintroduce (opaque) ::raw functions as it ought to be
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
* [Type-less and bitset-free](#type-less-and-bitset-free)
|
||||
* [Build your own](#build-your-own)
|
||||
* [Pay per use](#pay-per-use)
|
||||
* [All or nothing](#all-or-nothing)
|
||||
* [Vademecum](#vademecum)
|
||||
* [Pools](#pools)
|
||||
* [The Registry, the Entity and the Component](#the-registry-the-entity-and-the-component)
|
||||
@@ -118,6 +119,19 @@ performance where needed.
|
||||
So far, this choice has proven to be a good one and I really hope it can be for
|
||||
many others besides me.
|
||||
|
||||
## All or nothing
|
||||
|
||||
`EnTT` is such that a `T**` pointer (or whatever a custom pool returns) is
|
||||
always available to directly access all the instances of a given component type
|
||||
`T`.<br/>
|
||||
I cannot say whether it will be useful or not to the reader, but it's worth to
|
||||
mention it since it's one of the corner stones of this library.
|
||||
|
||||
Many of the tools described below give the possibility to get this information
|
||||
and have been designed around this need.<br/>
|
||||
The rest is experimentation and the desire to invent something new, hoping to
|
||||
have succeeded.
|
||||
|
||||
# Vademecum
|
||||
|
||||
The registry to store, the views and the groups to iterate. That's all.
|
||||
@@ -1237,11 +1251,12 @@ different in the two cases.
|
||||
Single component views are specialized in order to give a boost in terms of
|
||||
performance in all the situations. This kind of views can access the underlying
|
||||
data structures directly and avoid superfluous checks. There is nothing as fast
|
||||
as a single component view. In fact, they walk through a packed array of
|
||||
components and return them one at a time.<br/>
|
||||
Single component views offer a bunch of functionalities to get the number of
|
||||
entities they are going to return and a raw access to the entity list. It's also
|
||||
possible to ask a view if it contains a given entity.<br/>
|
||||
as a single component view. In fact, they walk through a packed (actually paged)
|
||||
array of components and return them one at a time.<br/>
|
||||
Single component views also offer a bunch of functionalities to get the number
|
||||
of entities they are going to return and a raw access to the entity list as well
|
||||
as to the component list. It's also possible to ask a view if it contains a
|
||||
given entity.<br/>
|
||||
Refer to the inline documentation for all the details.
|
||||
|
||||
Multi component views iterate entities that have at least all the given
|
||||
@@ -1435,8 +1450,9 @@ However, it's unlikely that users will be able to appreciate the impact of
|
||||
groups on the other functionalities of a registry.
|
||||
|
||||
Groups offer a bunch of functionalities to get the number of entities they are
|
||||
going to return and a raw access to the entity list. It's also possible to ask a
|
||||
group if it contains a given entity.<br/>
|
||||
going to return and a raw access to the entity list as well as to the component
|
||||
list for owned components. It's also possible to ask a group if it contains a
|
||||
given entity.<br/>
|
||||
Refer to the inline documentation for all the details.
|
||||
|
||||
There is no need to store groups aside for they are extremely cheap to
|
||||
@@ -1846,9 +1862,9 @@ When an empty type is detected, it's not instantiated in any case. Therefore,
|
||||
only the entities to which it's assigned are made available.<br/>
|
||||
There doesn't exist a way to _get_ empty types from a registry, views and groups
|
||||
will never return instances for them (for example, during a call to `each`) and
|
||||
some functions such as `try_get` aren't available for empty types. Finally, the
|
||||
`sort` functionality will only accepts callbacks that require to return entities
|
||||
rather than components:
|
||||
some functions such as `try_get` or the raw access to the list of components
|
||||
aren't available for empty types. Finally, the `sort` functionality will only
|
||||
accepts callbacks that require to return entities rather than components:
|
||||
|
||||
```cpp
|
||||
registry.sort<empty_type>([](const entt::entity lhs, const entt::entity rhs) {
|
||||
|
||||
@@ -680,6 +680,22 @@ public:
|
||||
return !*this || !*length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Direct access to the raw representation offered by the storage.
|
||||
*
|
||||
* @warning
|
||||
* This function is only available for owned types.
|
||||
*
|
||||
* @tparam Component Type of component in which one is interested.
|
||||
* @return A pointer to the array of components.
|
||||
*/
|
||||
template<typename Component>
|
||||
[[nodiscard]] auto raw() const ENTT_NOEXCEPT {
|
||||
static_assert((std::is_same_v<Component, Owned> || ...), "Non-owned type");
|
||||
auto *cpool = std::get<storage_type<Component> *>(pools);
|
||||
return cpool ? cpool->raw() : decltype(cpool->raw()){};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Direct access to the list of entities.
|
||||
*
|
||||
|
||||
@@ -59,11 +59,12 @@ class basic_storage: public basic_sparse_set<Entity, typename std::allocator_tra
|
||||
using alloc_type = typename std::allocator_traits<Allocator>::template rebind_alloc<Type>;
|
||||
using alloc_traits = std::allocator_traits<alloc_type>;
|
||||
using alloc_pointer = typename alloc_traits::pointer;
|
||||
using alloc_const_pointer = typename alloc_traits::const_pointer;
|
||||
|
||||
using bucket_alloc_type = typename std::allocator_traits<Allocator>::template rebind_alloc<alloc_pointer>;
|
||||
using bucket_alloc_traits = std::allocator_traits<bucket_alloc_type>;
|
||||
using bucket_alloc_pointer = typename bucket_alloc_traits::pointer;
|
||||
using bucket_alloc_const_pointer = typename bucket_alloc_traits::const_pointer;
|
||||
using bucket_alloc_const_pointer = typename std::allocator_traits<Allocator>::template rebind_alloc<alloc_const_pointer>::const_pointer;
|
||||
|
||||
using entity_alloc_type = typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>;
|
||||
|
||||
@@ -74,7 +75,7 @@ class basic_storage: public basic_sparse_set<Entity, typename std::allocator_tra
|
||||
class storage_iterator final {
|
||||
friend class basic_storage<Entity, Type>;
|
||||
|
||||
storage_iterator(const bucket_alloc_const_pointer *ref, const typename traits_type::difference_type idx) ENTT_NOEXCEPT
|
||||
storage_iterator(bucket_alloc_pointer const *ref, const typename traits_type::difference_type idx) ENTT_NOEXCEPT
|
||||
: packed{ref}, index{idx}
|
||||
{}
|
||||
|
||||
@@ -166,7 +167,7 @@ class basic_storage: public basic_sparse_set<Entity, typename std::allocator_tra
|
||||
}
|
||||
|
||||
private:
|
||||
const bucket_alloc_const_pointer *packed;
|
||||
bucket_alloc_pointer const *packed;
|
||||
difference_type index;
|
||||
};
|
||||
|
||||
@@ -270,6 +271,10 @@ public:
|
||||
using entity_type = Entity;
|
||||
/*! @brief Unsigned integer type. */
|
||||
using size_type = std::size_t;
|
||||
/*! @brief Pointer type to contained elements. */
|
||||
using pointer = bucket_alloc_pointer;
|
||||
/*! @brief Constant pointer type to contained elements. */
|
||||
using const_pointer = bucket_alloc_const_pointer;
|
||||
/*! @brief Random access iterator type. */
|
||||
using iterator = storage_iterator<Type>;
|
||||
/*! @brief Constant random access iterator type. */
|
||||
@@ -354,6 +359,19 @@ public:
|
||||
count ? maybe_resize_packed(count) : reset_to_empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Direct access to the array of objects.
|
||||
* @return A pointer to the array of objects.
|
||||
*/
|
||||
[[nodiscard]] const_pointer raw() const ENTT_NOEXCEPT {
|
||||
return packed;
|
||||
}
|
||||
|
||||
/*! @copydoc raw */
|
||||
[[nodiscard]] pointer raw() ENTT_NOEXCEPT {
|
||||
return packed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an iterator to the beginning.
|
||||
*
|
||||
|
||||
@@ -708,6 +708,14 @@ public:
|
||||
return std::get<0>(pools)->empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Direct access to the raw representation offered by the storage.
|
||||
* @return A pointer to the array of components.
|
||||
*/
|
||||
[[nodiscard]] auto raw() const ENTT_NOEXCEPT {
|
||||
return std::get<0>(pools)->raw();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Direct access to the list of entities.
|
||||
*
|
||||
|
||||
@@ -53,7 +53,7 @@ TEST(NonOwningGroup, Functionalities) {
|
||||
ASSERT_EQ(cgroup.get<const char>(entity), '2');
|
||||
}
|
||||
|
||||
ASSERT_EQ(*(group.data() + 0), e1);
|
||||
ASSERT_EQ(group.data()[0u], e1);
|
||||
|
||||
registry.erase<char>(e0);
|
||||
registry.erase<char>(e1);
|
||||
@@ -221,17 +221,17 @@ TEST(NonOwningGroup, Sort) {
|
||||
registry.emplace<int>(e1, 1);
|
||||
registry.emplace<int>(e2, 2);
|
||||
|
||||
ASSERT_EQ(*(group.data() + 0u), e0);
|
||||
ASSERT_EQ(*(group.data() + 1u), e1);
|
||||
ASSERT_EQ(*(group.data() + 2u), e2);
|
||||
ASSERT_EQ(group.data()[0u], e0);
|
||||
ASSERT_EQ(group.data()[1u], e1);
|
||||
ASSERT_EQ(group.data()[2u], e2);
|
||||
|
||||
group.sort([](const entt::entity lhs, const entt::entity rhs) {
|
||||
return entt::to_integral(lhs) < entt::to_integral(rhs);
|
||||
});
|
||||
|
||||
ASSERT_EQ(*(group.data() + 0u), e2);
|
||||
ASSERT_EQ(*(group.data() + 1u), e1);
|
||||
ASSERT_EQ(*(group.data() + 2u), e0);
|
||||
ASSERT_EQ(group.data()[0u], e2);
|
||||
ASSERT_EQ(group.data()[1u], e1);
|
||||
ASSERT_EQ(group.data()[2u], e0);
|
||||
|
||||
ASSERT_EQ((group.get<const int, unsigned int>(e0)), (std::make_tuple(0, 0u)));
|
||||
ASSERT_EQ((group.get<const int, unsigned int>(e1)), (std::make_tuple(1, 1u)));
|
||||
@@ -243,9 +243,9 @@ TEST(NonOwningGroup, Sort) {
|
||||
return lhs > rhs;
|
||||
});
|
||||
|
||||
ASSERT_EQ(*(group.data() + 0u), e0);
|
||||
ASSERT_EQ(*(group.data() + 1u), e1);
|
||||
ASSERT_EQ(*(group.data() + 2u), e2);
|
||||
ASSERT_EQ(group.data()[0u], e0);
|
||||
ASSERT_EQ(group.data()[1u], e1);
|
||||
ASSERT_EQ(group.data()[2u], e2);
|
||||
|
||||
ASSERT_EQ((group.get<const int, unsigned int>(e0)), (std::make_tuple(0, 0u)));
|
||||
ASSERT_EQ((group.get<const int, unsigned int>(e1)), (std::make_tuple(1, 1u)));
|
||||
@@ -259,9 +259,9 @@ TEST(NonOwningGroup, Sort) {
|
||||
return std::get<0>(lhs) < std::get<0>(rhs);
|
||||
});
|
||||
|
||||
ASSERT_EQ(*(group.data() + 0u), e2);
|
||||
ASSERT_EQ(*(group.data() + 1u), e1);
|
||||
ASSERT_EQ(*(group.data() + 2u), e0);
|
||||
ASSERT_EQ(group.data()[0u], e2);
|
||||
ASSERT_EQ(group.data()[1u], e1);
|
||||
ASSERT_EQ(group.data()[2u], e0);
|
||||
|
||||
ASSERT_EQ((group.get<const int, unsigned int>(e0)), (std::make_tuple(0, 0u)));
|
||||
ASSERT_EQ((group.get<const int, unsigned int>(e1)), (std::make_tuple(1, 1u)));
|
||||
@@ -665,8 +665,8 @@ TEST(OwningGroup, Functionalities) {
|
||||
|
||||
ASSERT_EQ(group.size(), 1u);
|
||||
|
||||
ASSERT_EQ(*(cgroup.rbegin() + 0), e1);
|
||||
ASSERT_EQ(*(group.rbegin() + 0), e1);
|
||||
ASSERT_EQ(cgroup.raw<const int>()[0u][0u], 42);
|
||||
ASSERT_EQ(group.raw<int>()[0u][0u], 42);
|
||||
|
||||
for(auto entity: group) {
|
||||
ASSERT_EQ(std::get<0>(cgroup.get<const int, const char>(entity)), 42);
|
||||
@@ -674,7 +674,8 @@ TEST(OwningGroup, Functionalities) {
|
||||
ASSERT_EQ(cgroup.get<const char>(entity), '2');
|
||||
}
|
||||
|
||||
ASSERT_EQ(*(group.data() + 0), e1);
|
||||
ASSERT_EQ(group.data()[0u], e1);
|
||||
ASSERT_EQ(group.raw<int>()[0u][0u], 42);
|
||||
|
||||
registry.erase<char>(e0);
|
||||
registry.erase<char>(e1);
|
||||
@@ -705,6 +706,7 @@ TEST(OwningGroup, Invalid) {
|
||||
ASSERT_TRUE(group.empty());
|
||||
ASSERT_EQ(group.size(), 0u);
|
||||
|
||||
ASSERT_EQ(group.raw<const int>(), nullptr);
|
||||
ASSERT_EQ(group.data(), nullptr);
|
||||
|
||||
ASSERT_EQ(group.begin(), group.end());
|
||||
@@ -839,17 +841,21 @@ TEST(OwningGroup, SortOrdered) {
|
||||
return group.get<boxed_int>(lhs).value < group.get<boxed_int>(rhs).value;
|
||||
});
|
||||
|
||||
ASSERT_EQ(*(group.data() + 0u), entities[0]);
|
||||
ASSERT_EQ(*(group.data() + 1u), entities[1]);
|
||||
ASSERT_EQ(*(group.data() + 2u), entities[2]);
|
||||
ASSERT_EQ(group.data()[0u], entities[0]);
|
||||
ASSERT_EQ(group.data()[1u], entities[1]);
|
||||
ASSERT_EQ(group.data()[2u], entities[2]);
|
||||
ASSERT_EQ(group.data()[3u], entities[3]);
|
||||
ASSERT_EQ(group.data()[4u], entities[4]);
|
||||
|
||||
ASSERT_EQ(group.get<boxed_int>(*(group.data() + 0u)).value, 12);
|
||||
ASSERT_EQ(group.get<boxed_int>(*(group.data() + 1u)).value, 9);
|
||||
ASSERT_EQ(group.get<boxed_int>(*(group.data() + 2u)).value, 6);
|
||||
ASSERT_EQ(group.raw<boxed_int>()[0u][0u].value, 12);
|
||||
ASSERT_EQ(group.raw<boxed_int>()[0u][1u].value, 9);
|
||||
ASSERT_EQ(group.raw<boxed_int>()[0u][2u].value, 6);
|
||||
ASSERT_EQ(group.raw<boxed_int>()[0u][3u].value, 1);
|
||||
ASSERT_EQ(group.raw<boxed_int>()[0u][4u].value, 2);
|
||||
|
||||
ASSERT_EQ(group.get<char>(*(group.data() + 0u)), 'a');
|
||||
ASSERT_EQ(group.get<char>(*(group.data() + 1u)), 'b');
|
||||
ASSERT_EQ(group.get<char>(*(group.data() + 2u)), 'c');
|
||||
ASSERT_EQ(group.raw<char>()[0u][0u], 'a');
|
||||
ASSERT_EQ(group.raw<char>()[0u][1u], 'b');
|
||||
ASSERT_EQ(group.raw<char>()[0u][2u], 'c');
|
||||
|
||||
ASSERT_EQ((group.get<boxed_int, char>(entities[0])), (std::make_tuple(boxed_int{12}, 'a')));
|
||||
ASSERT_EQ((group.get<boxed_int, char>(entities[1])), (std::make_tuple(boxed_int{9}, 'b')));
|
||||
@@ -882,17 +888,21 @@ TEST(OwningGroup, SortReverse) {
|
||||
return lhs.value < rhs.value;
|
||||
});
|
||||
|
||||
ASSERT_EQ(*(group.data() + 0u), entities[2]);
|
||||
ASSERT_EQ(*(group.data() + 1u), entities[1]);
|
||||
ASSERT_EQ(*(group.data() + 2u), entities[0]);
|
||||
ASSERT_EQ(group.data()[0u], entities[2]);
|
||||
ASSERT_EQ(group.data()[1u], entities[1]);
|
||||
ASSERT_EQ(group.data()[2u], entities[0]);
|
||||
ASSERT_EQ(group.data()[3u], entities[3]);
|
||||
ASSERT_EQ(group.data()[4u], entities[4]);
|
||||
|
||||
ASSERT_EQ(group.get<boxed_int>(*(group.data() + 0u)).value, 12);
|
||||
ASSERT_EQ(group.get<boxed_int>(*(group.data() + 1u)).value, 9);
|
||||
ASSERT_EQ(group.get<boxed_int>(*(group.data() + 2u)).value, 6);
|
||||
ASSERT_EQ(group.raw<boxed_int>()[0u][0u].value, 12);
|
||||
ASSERT_EQ(group.raw<boxed_int>()[0u][1u].value, 9);
|
||||
ASSERT_EQ(group.raw<boxed_int>()[0u][2u].value, 6);
|
||||
ASSERT_EQ(group.raw<boxed_int>()[0u][3u].value, 1);
|
||||
ASSERT_EQ(group.raw<boxed_int>()[0u][4u].value, 2);
|
||||
|
||||
ASSERT_EQ(group.get<char>(*(group.data() + 0u)), 'c');
|
||||
ASSERT_EQ(group.get<char>(*(group.data() + 1u)), 'b');
|
||||
ASSERT_EQ(group.get<char>(*(group.data() + 2u)), 'a');
|
||||
ASSERT_EQ(group.raw<char>()[0u][0u], 'c');
|
||||
ASSERT_EQ(group.raw<char>()[0u][1u], 'b');
|
||||
ASSERT_EQ(group.raw<char>()[0u][2u], 'a');
|
||||
|
||||
ASSERT_EQ((group.get<boxed_int, char>(entities[0])), (std::make_tuple(boxed_int{6}, 'a')));
|
||||
ASSERT_EQ((group.get<boxed_int, char>(entities[1])), (std::make_tuple(boxed_int{9}, 'b')));
|
||||
@@ -933,29 +943,27 @@ TEST(OwningGroup, SortUnordered) {
|
||||
return std::get<1>(lhs) < std::get<1>(rhs);
|
||||
});
|
||||
|
||||
ASSERT_EQ(*(group.data() + 0u), entities[4]);
|
||||
ASSERT_EQ(*(group.data() + 1u), entities[3]);
|
||||
ASSERT_EQ(*(group.data() + 2u), entities[0]);
|
||||
ASSERT_EQ(*(group.data() + 3u), entities[1]);
|
||||
ASSERT_EQ(*(group.data() + 4u), entities[2]);
|
||||
ASSERT_EQ(group.data()[0u], entities[4]);
|
||||
ASSERT_EQ(group.data()[1u], entities[3]);
|
||||
ASSERT_EQ(group.data()[2u], entities[0]);
|
||||
ASSERT_EQ(group.data()[3u], entities[1]);
|
||||
ASSERT_EQ(group.data()[4u], entities[2]);
|
||||
ASSERT_EQ(group.data()[5u], entities[5]);
|
||||
ASSERT_EQ(group.data()[6u], entities[6]);
|
||||
|
||||
ASSERT_EQ(group.get<boxed_int>(*(group.data() + 0u)).value, 12);
|
||||
ASSERT_EQ(group.get<boxed_int>(*(group.data() + 1u)).value, 9);
|
||||
ASSERT_EQ(group.get<boxed_int>(*(group.data() + 2u)).value, 6);
|
||||
ASSERT_EQ(group.get<boxed_int>(*(group.data() + 3u)).value, 3);
|
||||
ASSERT_EQ(group.get<boxed_int>(*(group.data() + 4u)).value, 1);
|
||||
ASSERT_EQ(group.raw<boxed_int>()[0u][0u].value, 12);
|
||||
ASSERT_EQ(group.raw<boxed_int>()[0u][1u].value, 9);
|
||||
ASSERT_EQ(group.raw<boxed_int>()[0u][2u].value, 6);
|
||||
ASSERT_EQ(group.raw<boxed_int>()[0u][3u].value, 3);
|
||||
ASSERT_EQ(group.raw<boxed_int>()[0u][4u].value, 1);
|
||||
ASSERT_EQ(group.raw<boxed_int>()[0u][5u].value, 4);
|
||||
ASSERT_EQ(group.raw<boxed_int>()[0u][6u].value, 5);
|
||||
|
||||
ASSERT_EQ(group.get<char>(*(group.data() + 0u)), 'e');
|
||||
ASSERT_EQ(group.get<char>(*(group.data() + 1u)), 'd');
|
||||
ASSERT_EQ(group.get<char>(*(group.data() + 2u)), 'c');
|
||||
ASSERT_EQ(group.get<char>(*(group.data() + 3u)), 'b');
|
||||
ASSERT_EQ(group.get<char>(*(group.data() + 4u)), 'a');
|
||||
|
||||
ASSERT_EQ((group.get<boxed_int, char>(entities[0])), (std::make_tuple(boxed_int{6}, 'c')));
|
||||
ASSERT_EQ((group.get<boxed_int, char>(entities[1])), (std::make_tuple(boxed_int{3}, 'b')));
|
||||
ASSERT_EQ((group.get<boxed_int, char>(entities[2])), (std::make_tuple(boxed_int{1}, 'a')));
|
||||
ASSERT_EQ((group.get<boxed_int, char>(entities[3])), (std::make_tuple(boxed_int{9}, 'd')));
|
||||
ASSERT_EQ((group.get<boxed_int, char>(entities[4])), (std::make_tuple(boxed_int{12}, 'e')));
|
||||
ASSERT_EQ(group.get<char>(group.data()[0u]), 'e');
|
||||
ASSERT_EQ(group.get<char>(group.data()[1u]), 'd');
|
||||
ASSERT_EQ(group.get<char>(group.data()[2u]), 'c');
|
||||
ASSERT_EQ(group.get<char>(group.data()[3u]), 'b');
|
||||
ASSERT_EQ(group.get<char>(group.data()[4u]), 'a');
|
||||
|
||||
ASSERT_FALSE(group.contains(entities[5]));
|
||||
ASSERT_FALSE(group.contains(entities[6]));
|
||||
@@ -980,15 +988,20 @@ TEST(OwningGroup, SortWithExclusionList) {
|
||||
return lhs < rhs;
|
||||
});
|
||||
|
||||
ASSERT_EQ(*(group.data() + 0u), entities[4]);
|
||||
ASSERT_EQ(*(group.data() + 1u), entities[3]);
|
||||
ASSERT_EQ(*(group.data() + 2u), entities[1]);
|
||||
ASSERT_EQ(*(group.data() + 3u), entities[0]);
|
||||
ASSERT_EQ(group.data()[0u], entities[4]);
|
||||
ASSERT_EQ(group.data()[1u], entities[3]);
|
||||
ASSERT_EQ(group.data()[2u], entities[1]);
|
||||
ASSERT_EQ(group.data()[3u], entities[0]);
|
||||
|
||||
ASSERT_EQ(group.get<boxed_int>(*(group.data() + 0u)).value, 4);
|
||||
ASSERT_EQ(group.get<boxed_int>(*(group.data() + 1u)).value, 3);
|
||||
ASSERT_EQ(group.get<boxed_int>(*(group.data() + 2u)).value, 1);
|
||||
ASSERT_EQ(group.get<boxed_int>(*(group.data() + 3u)).value, 0);
|
||||
ASSERT_EQ(group.raw<boxed_int>()[0u][0u].value, 4);
|
||||
ASSERT_EQ(group.raw<boxed_int>()[0u][1u].value, 3);
|
||||
ASSERT_EQ(group.raw<boxed_int>()[0u][2u].value, 1);
|
||||
ASSERT_EQ(group.raw<boxed_int>()[0u][3u].value, 0);
|
||||
|
||||
ASSERT_EQ(group.get<boxed_int>(entities[0]).value, 0);
|
||||
ASSERT_EQ(group.get<boxed_int>(entities[1]).value, 1);
|
||||
ASSERT_EQ(group.get<boxed_int>(entities[3]).value, 3);
|
||||
ASSERT_EQ(group.get<boxed_int>(entities[4]).value, 4);
|
||||
|
||||
ASSERT_FALSE(group.contains(entities[2]));
|
||||
}
|
||||
@@ -1049,6 +1062,8 @@ TEST(OwningGroup, ConstNonConstAndAllInBetween) {
|
||||
static_assert(std::is_same_v<decltype(group.get<int, const char, double, const float>({})), std::tuple<int &, const char &, double &, const float &>>);
|
||||
static_assert(std::is_same_v<decltype(group.get({})), std::tuple<int &, const char &, double &, const float &>>);
|
||||
static_assert(std::is_same_v<decltype(group.data()), const entt::entity *>);
|
||||
static_assert(std::is_same_v<decltype(group.raw<const char>()), const char * const *>);
|
||||
static_assert(std::is_same_v<decltype(group.raw<int>()), int **>);
|
||||
|
||||
group.each([](auto &&i, auto &&c, auto &&d, auto &&f) {
|
||||
static_assert(std::is_same_v<decltype(i), int &>);
|
||||
|
||||
@@ -14,6 +14,7 @@ TEST(Registry, NoEto) {
|
||||
registry.emplace<empty_type>(entity);
|
||||
registry.emplace<int>(entity, 42);
|
||||
|
||||
ASSERT_NE(registry.view<empty_type>().raw(), nullptr);
|
||||
ASSERT_NE(registry.try_get<empty_type>(entity), nullptr);
|
||||
ASSERT_EQ(registry.view<empty_type>().get(entity), std::as_const(registry).view<const empty_type>().get(entity));
|
||||
|
||||
|
||||
@@ -418,6 +418,22 @@ TEST(Storage, ConstReverseIterator) {
|
||||
ASSERT_GE(cend, pool.crend());
|
||||
}
|
||||
|
||||
TEST(Storage, Raw) {
|
||||
entt::storage<int> pool;
|
||||
|
||||
pool.emplace(entt::entity{3}, 3);
|
||||
pool.emplace(entt::entity{12}, 6);
|
||||
pool.emplace(entt::entity{42}, 9);
|
||||
|
||||
ASSERT_EQ(pool.get(entt::entity{3}), 3);
|
||||
ASSERT_EQ(std::as_const(pool).get(entt::entity{12}), 6);
|
||||
ASSERT_EQ(pool.get(entt::entity{42}), 9);
|
||||
|
||||
ASSERT_EQ(pool.raw()[0u][0u], 3);
|
||||
ASSERT_EQ(std::as_const(pool).raw()[0u][1u], 6);
|
||||
ASSERT_EQ(pool.raw()[0u][2u], 9);
|
||||
}
|
||||
|
||||
TEST(Storage, SortOrdered) {
|
||||
entt::storage<boxed_int> pool;
|
||||
entt::entity entities[5u]{entt::entity{12}, entt::entity{42}, entt::entity{7}, entt::entity{3}, entt::entity{9}};
|
||||
@@ -480,9 +496,9 @@ TEST(Storage, SortRange) {
|
||||
|
||||
pool.sort_n(2u, [](auto lhs, auto rhs) { return lhs.value < rhs.value; });
|
||||
|
||||
ASSERT_EQ(pool.rbegin()[0u], boxed_int{6});
|
||||
ASSERT_EQ(pool.rbegin()[1u], boxed_int{3});
|
||||
ASSERT_EQ(pool.rbegin()[2u], boxed_int{1});
|
||||
ASSERT_EQ(pool.raw()[0u][0u], boxed_int{6});
|
||||
ASSERT_EQ(pool.raw()[0u][1u], boxed_int{3});
|
||||
ASSERT_EQ(pool.raw()[0u][2u], boxed_int{1});
|
||||
|
||||
ASSERT_EQ(pool.data()[0u], entt::entity{42});
|
||||
ASSERT_EQ(pool.data()[1u], entt::entity{12});
|
||||
|
||||
@@ -44,8 +44,11 @@ TEST(SingleComponentView, Functionalities) {
|
||||
ASSERT_TRUE(cview.get<const char>(entity) == '1' || std::get<const char &>(cview.get(entity)) == '2');
|
||||
}
|
||||
|
||||
ASSERT_EQ(*(view.data() + 0), e1);
|
||||
ASSERT_EQ(*(view.data() + 1), e0);
|
||||
ASSERT_EQ(view.data()[0u], e1);
|
||||
ASSERT_EQ(view.data()[1u], e0);
|
||||
|
||||
ASSERT_EQ(view.raw()[0u][0u], '2');
|
||||
ASSERT_EQ(cview.raw()[0u][1u], '1');
|
||||
|
||||
registry.erase<char>(e0);
|
||||
registry.erase<char>(e1);
|
||||
@@ -61,7 +64,7 @@ TEST(SingleComponentView, Functionalities) {
|
||||
ASSERT_FALSE(invalid);
|
||||
}
|
||||
|
||||
TEST(SingleComponentView, Data) {
|
||||
TEST(SingleComponentView, RawData) {
|
||||
entt::registry registry;
|
||||
auto view = registry.view<int>();
|
||||
auto cview = std::as_const(registry).view<const int>();
|
||||
@@ -70,6 +73,8 @@ TEST(SingleComponentView, Data) {
|
||||
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
ASSERT_EQ(cview.size(), 0u);
|
||||
ASSERT_EQ(view.raw(), nullptr);
|
||||
ASSERT_EQ(cview.raw(), nullptr);
|
||||
ASSERT_EQ(view.data(), nullptr);
|
||||
ASSERT_EQ(cview.data(), nullptr);
|
||||
|
||||
@@ -77,8 +82,10 @@ TEST(SingleComponentView, Data) {
|
||||
|
||||
ASSERT_NE(view.size(), 0u);
|
||||
ASSERT_NE(cview.size(), 0u);
|
||||
ASSERT_EQ(*view.data(), entity);
|
||||
ASSERT_EQ(*cview.data(), entity);
|
||||
ASSERT_EQ(view.raw()[0u][0u], 42);
|
||||
ASSERT_EQ(cview.raw()[0u][0u], 42);
|
||||
ASSERT_EQ(view.data()[0u], entity);
|
||||
ASSERT_EQ(cview.data()[0u], entity);
|
||||
|
||||
registry.destroy(entity);
|
||||
|
||||
@@ -98,6 +105,7 @@ TEST(SingleComponentView, LazyTypeFromConstRegistry) {
|
||||
ASSERT_TRUE(cview);
|
||||
ASSERT_TRUE(eview);
|
||||
|
||||
ASSERT_NE(cview.raw(), nullptr);
|
||||
ASSERT_NE(eview.data(), nullptr);
|
||||
|
||||
ASSERT_FALSE(cview.empty());
|
||||
@@ -218,10 +226,15 @@ TEST(SingleComponentView, ConstNonConstAndAllInBetween) {
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
ASSERT_EQ(cview.size(), 1u);
|
||||
|
||||
static_assert(std::is_same_v<decltype(view.raw()), int **>);
|
||||
static_assert(std::is_same_v<decltype(cview.raw()), const int * const *>);
|
||||
|
||||
static_assert(std::is_same_v<decltype(view.get<int>({})), int &>);
|
||||
static_assert(std::is_same_v<decltype(view.get({})), std::tuple<int &>>);
|
||||
static_assert(std::is_same_v<decltype(view.raw()), int **>);
|
||||
static_assert(std::is_same_v<decltype(cview.get<const int>({})), const int &>);
|
||||
static_assert(std::is_same_v<decltype(cview.get({})), std::tuple<const int &>>);
|
||||
static_assert(std::is_same_v<decltype(cview.raw()), const int * const *>);
|
||||
|
||||
view.each([](auto &&i) {
|
||||
static_assert(std::is_same_v<decltype(i), int &>);
|
||||
|
||||
Reference in New Issue
Block a user