registry: stomp and spawn
This commit is contained in:
5
TODO
5
TODO
@@ -28,5 +28,6 @@ TODO
|
||||
* make meta work across boundaries
|
||||
- inline variables are fine here, only the head represents a problem
|
||||
- we should always resolve by looking into the list of types when working across boundaries, no direct resolve
|
||||
* review stomp signature: first, last, other, from <-- the registry "acquires" the other entity
|
||||
* create from prototype (literally a stomp with batch creation)
|
||||
* nested groups: AB/ABC/ABCD/... (hints: sort, check functions)
|
||||
* use make_tuple and reference_wrapper instead of explicing tuple<T &>
|
||||
* improve multi-stomp so as to reuse the known pool and the known element
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
* [Sorting: is it possible?](#sorting-is-it-possible)
|
||||
* [Helpers](#helpers)
|
||||
* [Null entity](#null-entity)
|
||||
* [Multiple registries](#multiple-registries)
|
||||
* [Stomp and spawn](#stomp-and-spawn)
|
||||
* [Dependencies](#dependencies)
|
||||
* [Tags](#tags)
|
||||
* [Actor](#actor)
|
||||
@@ -44,6 +44,7 @@
|
||||
* [Empty type optimization](#empty-type-optimization)
|
||||
* [Multithreading](#multithreading)
|
||||
* [Iterators](#iterators)
|
||||
* [Beyond this document](#beyond-this-document)
|
||||
<!--
|
||||
@endcond TURN_OFF_DOXYGEN
|
||||
-->
|
||||
@@ -666,26 +667,29 @@ const auto entity = registry.create();
|
||||
const bool null = (entity == entt::null);
|
||||
```
|
||||
|
||||
### Multiple registries
|
||||
### Stomp and spawn
|
||||
|
||||
The use of multiple registries is quite common. Examples of use are the
|
||||
separation of the UI from the simulation or the loading of different scenes in
|
||||
the background, possibly on a separate thread, without having to keep track of
|
||||
which entity belongs to which scene.<br/>
|
||||
In fact, with `EnTT` this is even a recommended practice, as the registry is
|
||||
nothing more than a container and different optimizations can be applied to
|
||||
different containers.
|
||||
nothing more than a container and different optimizations and strategies can be
|
||||
applied to different containers.
|
||||
|
||||
Once there are multiple registries available, however, a method is needed to
|
||||
transfer information from one container to another and this results in the
|
||||
`stomp` member function of the `registry` class.<br/>
|
||||
This function allows to take one or more entities from a registry and use them
|
||||
to _stomp_ other entities in another registry (or even the same, actually making
|
||||
local copies).<br/>
|
||||
It opens definitely the doors to a lot of interesting features like migrating
|
||||
entities between registries, prototypes, shadow registry, prefabs, shared
|
||||
components without an explicit owner and copy-on-write policies among the other
|
||||
things.
|
||||
Once there are multiple registries available, however, one or more methods are
|
||||
needed to transfer information from one container to another and this results in
|
||||
the `stomp` member function and a couple of overloads of the `create` member
|
||||
function for the `registry` class .<br/>
|
||||
The `stomp` function allows to take one entity from a registry and use it to
|
||||
_stomp_ one or more entities in another registry (or even the same, actually
|
||||
making local copies). On the other hand, the overloads of the `create` member
|
||||
function can be used to spawn new entities from a prototype.
|
||||
|
||||
These features open definitely the doors to a lot of interesting features like
|
||||
migrating entities between registries, prototypes, shadow registry, prefabs,
|
||||
shared components without an explicit owner and copy-on-write policies among the
|
||||
other things.
|
||||
|
||||
### Dependencies
|
||||
|
||||
@@ -1672,3 +1676,14 @@ This may change in the future and the iterators will almost certainly return
|
||||
both the entities and a list of references to their components sooner or later.
|
||||
Multi-pass guarantee won't break in any case and the performance should even
|
||||
benefit from it further.
|
||||
|
||||
# Beyond this document
|
||||
|
||||
There are many other features and functions not listed in this document.<br/>
|
||||
`EnTT` and in particular its ECS part is in continuous development and some
|
||||
things could be forgotten, others could have been omitted on purpose to reduce
|
||||
the size of this file. Unfortunately, some parts may even be outdated and still
|
||||
to be updated.
|
||||
|
||||
For further information, it's recommended to refer to the documentation included
|
||||
in the code itself or join the official channels to ask a question.
|
||||
|
||||
@@ -85,9 +85,9 @@ class basic_registry {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename It>
|
||||
auto batch(basic_registry ®istry, It first, It last) {
|
||||
auto it = storage<Entity, Component>::batch(first, last);
|
||||
template<typename It, typename... Comp>
|
||||
auto batch(basic_registry ®istry, It first, It last, const Comp &... value) {
|
||||
auto it = storage<Entity, Component>::batch(first, last, value...);
|
||||
|
||||
if(!construction.empty()) {
|
||||
std::for_each(first, last, [this, ®istry, it](const auto entt) mutable {
|
||||
@@ -543,11 +543,11 @@ public:
|
||||
* Users should not care about the type of the returned entity identifier.
|
||||
* In case entity identifers are stored around, the `valid` member
|
||||
* function can be used to know if they are still valid or the entity has
|
||||
* been destroyed and potentially recycled.
|
||||
* been destroyed and potentially recycled.<br/>
|
||||
* The returned entity has assigned the given components, if any.
|
||||
*
|
||||
* The returned entity has assigned the given components, if any. The
|
||||
* components must be at least default constructible. A compilation error
|
||||
* will occur otherwhise.
|
||||
* The components must be at least default constructible. A compilation
|
||||
* error will occur otherwhise.
|
||||
*
|
||||
* @tparam Component Types of components to assign to the entity.
|
||||
* @return A valid entity identifier if the component list is empty, a tuple
|
||||
@@ -556,24 +556,14 @@ public:
|
||||
*/
|
||||
template<typename... Component>
|
||||
auto create() {
|
||||
entity_type entity;
|
||||
|
||||
if(destroyed == null) {
|
||||
entity = entities.emplace_back(entity_type(entities.size()));
|
||||
// traits_type::entity_mask is reserved to allow for null identifiers
|
||||
ENTT_ASSERT(to_integer(entity) < traits_type::entity_mask);
|
||||
} else {
|
||||
const auto entt = to_integer(destroyed);
|
||||
const auto version = to_integer(entities[entt]) & (traits_type::version_mask << traits_type::entity_shift);
|
||||
destroyed = entity_type{to_integer(entities[entt]) & traits_type::entity_mask};
|
||||
entity = entity_type{entt | version};
|
||||
entities[entt] = entity;
|
||||
}
|
||||
entity_type entities[1]{};
|
||||
|
||||
if constexpr(sizeof...(Component) == 0) {
|
||||
return entity;
|
||||
create<Component...>(std::begin(entities), std::end(entities));
|
||||
return entities[0];
|
||||
} else {
|
||||
return std::tuple<entity_type, decltype(assign<Component>(entity))...>{entity, assign<Component>(entity)...};
|
||||
auto it = create<Component...>(std::begin(entities), std::end(entities));
|
||||
return std::tuple<entity_type, decltype(assign<Component>(entities[0]))...>{entities[0], *std::get<typename pool_type<Component>::iterator_type>(it)...};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -582,6 +572,9 @@ public:
|
||||
*
|
||||
* @sa create
|
||||
*
|
||||
* The components must be at least move and default insertable. A
|
||||
* compilation error will occur otherwhise.
|
||||
*
|
||||
* @tparam Component Types of components to assign to the entity.
|
||||
* @tparam It Type of forward iterator.
|
||||
* @param first An iterator to the first element of the range to generate.
|
||||
@@ -597,13 +590,16 @@ public:
|
||||
std::generate(first, last, [this]() {
|
||||
entity_type curr;
|
||||
|
||||
if(destroyed != null) {
|
||||
if(destroyed == null) {
|
||||
curr = entities.emplace_back(entity_type(entities.size()));
|
||||
// traits_type::entity_mask is reserved to allow for null identifiers
|
||||
ENTT_ASSERT(to_integer(curr) < traits_type::entity_mask);
|
||||
} else {
|
||||
const auto entt = to_integer(destroyed);
|
||||
const auto version = to_integer(entities[entt]) & (traits_type::version_mask << traits_type::entity_shift);
|
||||
destroyed = entity_type{to_integer(entities[entt]) & traits_type::entity_mask};
|
||||
curr = (entities[entt] = entity_type{entt | version});
|
||||
} else {
|
||||
curr = entities.emplace_back(entity_type(entities.size()));
|
||||
curr = entity_type{entt | version};
|
||||
entities[entt] = curr;
|
||||
}
|
||||
|
||||
return curr;
|
||||
@@ -614,6 +610,48 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a new entity from a prototype entity.
|
||||
*
|
||||
* @sa create
|
||||
*
|
||||
* @tparam Component Types of components to copy.
|
||||
* @tparam Exclude Types of components not to be copied.
|
||||
* @param src A valid entity identifier to be copied.
|
||||
* @param other The registry that owns the source entity.
|
||||
* @return A valid entity identifier.
|
||||
*/
|
||||
template<typename... Component, typename... Exclude>
|
||||
auto create(entity_type src, basic_registry &other, exclude_t<Exclude...> = {}) {
|
||||
entity_type entities[1]{};
|
||||
create<Component...>(std::begin(entities), std::end(entities), src, other, exclude<Exclude...>);
|
||||
return entities[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns each element in a range an entity from a prototype entity.
|
||||
*
|
||||
* @sa create
|
||||
*
|
||||
* @tparam Component Types of components to copy.
|
||||
* @tparam Exclude Types of components not to be copied.
|
||||
* @param first An iterator to the first element of the range to generate.
|
||||
* @param last An iterator past the last element of the range to generate.
|
||||
* @param src A valid entity identifier to be copied.
|
||||
* @param other The registry that owns the source entity.
|
||||
*/
|
||||
template<typename... Component, typename It, typename... Exclude>
|
||||
void create(It first, It last, entity_type src, basic_registry &other, exclude_t<Exclude...> = {}) {
|
||||
create(first, last);
|
||||
|
||||
if constexpr(sizeof...(Component) == 0) {
|
||||
stomp<Component...>(first, last, src, other, exclude<Exclude...>);
|
||||
} else {
|
||||
static_assert(sizeof...(Component) == 0 || sizeof...(Exclude) == 0);
|
||||
(assure<Component>()->batch(*this, first, last, other.get<Component>(src)), ...);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destroys an entity and lets the registry recycle the identifier.
|
||||
*
|
||||
@@ -1528,16 +1566,15 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Makes a full or partial copy of an entity.
|
||||
* @brief Stomps an entity and its components.
|
||||
*
|
||||
* The components must be copyable for obvious reasons. The entities
|
||||
* must be both valid.<br/>
|
||||
* If no components are provided, the registry will try to copy all the
|
||||
* existing types. The non-copyable ones will be ignored.
|
||||
*
|
||||
* This feature supports exclusion lists. The excluded types have higher
|
||||
* priority than those indicated for copying. An excluded type will never be
|
||||
* copied.
|
||||
* This feature supports exclusion lists as an alternative to component
|
||||
* lists. An excluded type will never be copied.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to copy components that aren't copyable results in unexpected
|
||||
@@ -1554,25 +1591,45 @@ public:
|
||||
*
|
||||
* @tparam Component Types of components to copy.
|
||||
* @tparam Exclude Types of components not to be copied.
|
||||
* @param from A valid entity identifier to be copied.
|
||||
* @param other The registry that owns the target entity.
|
||||
* @param to A valid entity identifier to copy to.
|
||||
* @param dst A valid entity identifier to copy to.
|
||||
* @param src A valid entity identifier to be copied.
|
||||
* @param other The registry that owns the source entity.
|
||||
*/
|
||||
template<typename... Component, typename... Exclude>
|
||||
void stomp(const Entity from, basic_registry &other, const Entity to, exclude_t<Exclude...> = {}) {
|
||||
static_assert(std::conjunction_v<std::is_copy_constructible<Component>...>);
|
||||
ENTT_ASSERT(valid(from) && other.valid(to));
|
||||
void stomp(const entity_type dst, const entity_type src, basic_registry &other, exclude_t<Exclude...> = {}) {
|
||||
const entity_type entities[1]{dst};
|
||||
stomp<Component...>(std::begin(entities), std::end(entities), src, other, exclude<Exclude...>);
|
||||
}
|
||||
|
||||
for(auto pos = pools.size(); pos; --pos) {
|
||||
const auto &pdata = pools[pos-1];
|
||||
/**
|
||||
* @brief Stomps the entities in a range and their components.
|
||||
*
|
||||
* @sa stomp
|
||||
*
|
||||
* @tparam Component Types of components to copy.
|
||||
* @tparam Exclude Types of components not to be copied.
|
||||
* @param first An iterator to the first element of the range to stomp.
|
||||
* @param last An iterator past the last element of the range to stomp.
|
||||
* @param src A valid entity identifier to be copied.
|
||||
* @param other The registry that owns the source entity.
|
||||
*/
|
||||
template<typename... Component, typename It, typename... Exclude>
|
||||
void stomp(It first, It last, const entity_type src, basic_registry &other, exclude_t<Exclude...> = {}) {
|
||||
static_assert(sizeof...(Component) == 0 || sizeof...(Exclude) == 0);
|
||||
static_assert(std::conjunction_v<std::is_copy_constructible<Component>...>);
|
||||
|
||||
for(auto pos = other.pools.size(); pos; --pos) {
|
||||
const auto &pdata = other.pools[pos-1];
|
||||
ENTT_ASSERT(!sizeof...(Component) || !pdata.pool || pdata.stomp);
|
||||
|
||||
if(pdata.pool && pdata.stomp
|
||||
&& (!sizeof...(Component) || ... || (pdata.runtime_type == to_integer(type<Component>())))
|
||||
&& ((pdata.runtime_type != to_integer(type<Exclude>())) && ...)
|
||||
&& pdata.pool->has(from))
|
||||
&& pdata.pool->has(src))
|
||||
{
|
||||
pdata.stomp(*pdata.pool, from, other, to);
|
||||
std::for_each(first, last, [this, &pdata, src](const auto entity) {
|
||||
pdata.stomp(*pdata.pool, src, *this, entity);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,8 +351,7 @@ public:
|
||||
*/
|
||||
template<typename It>
|
||||
iterator_type batch(It first, It last) {
|
||||
const auto length = last - first;
|
||||
instances.resize(instances.size() + length);
|
||||
instances.resize(instances.size() + std::distance(first, last));
|
||||
// entity goes after component in case constructor throws
|
||||
underlying_type::batch(first, last);
|
||||
return begin();
|
||||
@@ -375,8 +374,7 @@ public:
|
||||
*/
|
||||
template<typename It>
|
||||
iterator_type batch(It first, It last, const object_type &value) {
|
||||
const auto length = last - first;
|
||||
instances.resize(instances.size() + length, value);
|
||||
instances.resize(instances.size() + std::distance(first, last), value);
|
||||
// entity goes after component in case constructor throws
|
||||
underlying_type::batch(first, last);
|
||||
return begin();
|
||||
|
||||
@@ -1187,6 +1187,82 @@ TEST(Registry, CreateManyEntitiesWithComponentsAtOnceWithListener) {
|
||||
ASSERT_EQ(listener.counter, 6);
|
||||
}
|
||||
|
||||
TEST(Registry, CreateFromPrototype) {
|
||||
entt::registry registry;
|
||||
|
||||
const auto prototype = registry.create();
|
||||
registry.assign<int>(prototype, 3);
|
||||
registry.assign<char>(prototype, 'c');
|
||||
|
||||
const auto full = registry.create(prototype, registry);
|
||||
|
||||
ASSERT_TRUE((registry.has<int, char>(full)));
|
||||
ASSERT_EQ(registry.get<int>(full), 3);
|
||||
ASSERT_EQ(registry.get<char>(full), 'c');
|
||||
|
||||
const auto partial = registry.create<int>(prototype, registry);
|
||||
|
||||
ASSERT_TRUE(registry.has<int>(partial));
|
||||
ASSERT_FALSE(registry.has<char>(partial));
|
||||
ASSERT_EQ(registry.get<int>(partial), 3);
|
||||
|
||||
const auto exclude = registry.create(prototype, registry, entt::exclude<int>);
|
||||
|
||||
ASSERT_FALSE(registry.has<int>(exclude));
|
||||
ASSERT_TRUE(registry.has<char>(exclude));
|
||||
ASSERT_EQ(registry.get<char>(exclude), 'c');
|
||||
}
|
||||
|
||||
TEST(Registry, CreateManyFromPrototype) {
|
||||
entt::registry registry;
|
||||
entt::entity entities[2];
|
||||
|
||||
const auto prototype = registry.create();
|
||||
registry.assign<int>(prototype, 3);
|
||||
registry.assign<char>(prototype, 'c');
|
||||
|
||||
registry.create(std::begin(entities), std::end(entities), prototype, registry);
|
||||
|
||||
ASSERT_TRUE((registry.has<int, char>(entities[0])));
|
||||
ASSERT_TRUE((registry.has<int, char>(entities[1])));
|
||||
ASSERT_EQ(registry.get<int>(entities[0]), 3);
|
||||
ASSERT_EQ(registry.get<char>(entities[1]), 'c');
|
||||
|
||||
registry.create<int>(std::begin(entities), std::end(entities), prototype, registry);
|
||||
|
||||
ASSERT_TRUE(registry.has<int>(entities[0]));
|
||||
ASSERT_FALSE(registry.has<char>(entities[1]));
|
||||
ASSERT_EQ(registry.get<int>(entities[0]), 3);
|
||||
|
||||
registry.create(std::begin(entities), std::end(entities), prototype, registry, entt::exclude<int>);
|
||||
|
||||
ASSERT_FALSE(registry.has<int>(entities[0]));
|
||||
ASSERT_TRUE(registry.has<char>(entities[1]));
|
||||
ASSERT_EQ(registry.get<char>(entities[0]), 'c');
|
||||
}
|
||||
|
||||
TEST(Registry, CreateFromPrototypeWithListener) {
|
||||
entt::registry registry;
|
||||
entt::entity entities[3];
|
||||
listener listener;
|
||||
|
||||
const auto prototype = registry.create();
|
||||
registry.assign<int>(prototype, 3);
|
||||
registry.assign<char>(prototype, 'c');
|
||||
registry.assign<empty_type>(prototype);
|
||||
|
||||
registry.on_construct<int>().connect<&listener::incr<int>>(listener);
|
||||
registry.create<int, char>(std::begin(entities), std::end(entities), prototype, registry);
|
||||
|
||||
ASSERT_EQ(listener.counter, 3);
|
||||
|
||||
registry.on_construct<int>().disconnect<&listener::incr<int>>(listener);
|
||||
registry.on_construct<empty_type>().connect<&listener::incr<empty_type>>(listener);
|
||||
registry.create<char, empty_type>(std::begin(entities), std::end(entities), prototype, registry);
|
||||
|
||||
ASSERT_EQ(listener.counter, 6);
|
||||
}
|
||||
|
||||
TEST(Registry, NonOwningGroupInterleaved) {
|
||||
entt::registry registry;
|
||||
typename entt::entity entity = entt::null;
|
||||
@@ -1416,67 +1492,82 @@ TEST(Registry, CloneMoveOnlyComponent) {
|
||||
TEST(Registry, Stomp) {
|
||||
entt::registry registry;
|
||||
|
||||
const auto entity = registry.create();
|
||||
registry.assign<int>(entity, 3);
|
||||
registry.assign<char>(entity, 'c');
|
||||
const auto prototype = registry.create();
|
||||
registry.assign<int>(prototype, 3);
|
||||
registry.assign<char>(prototype, 'c');
|
||||
|
||||
auto other = registry.create();
|
||||
registry.stomp<int, char, double>(entity, registry, other);
|
||||
auto entity = registry.create();
|
||||
registry.stomp<int, char, double>(entity, prototype, registry);
|
||||
|
||||
ASSERT_TRUE(registry.has<int>(other));
|
||||
ASSERT_TRUE(registry.has<char>(other));
|
||||
ASSERT_EQ(registry.get<int>(other), 3);
|
||||
ASSERT_EQ(registry.get<char>(other), 'c');
|
||||
ASSERT_TRUE((registry.has<int, char>(entity)));
|
||||
ASSERT_EQ(registry.get<int>(entity), 3);
|
||||
ASSERT_EQ(registry.get<char>(entity), 'c');
|
||||
|
||||
registry.replace<int>(entity, 42);
|
||||
registry.replace<char>(entity, 'a');
|
||||
registry.stomp<int>(entity, registry, other);
|
||||
registry.replace<int>(prototype, 42);
|
||||
registry.replace<char>(prototype, 'a');
|
||||
registry.stomp<int>(entity, prototype, registry);
|
||||
|
||||
ASSERT_EQ(registry.get<int>(other), 42);
|
||||
ASSERT_EQ(registry.get<char>(other), 'c');
|
||||
ASSERT_EQ(registry.get<int>(entity), 42);
|
||||
ASSERT_EQ(registry.get<char>(entity), 'c');
|
||||
}
|
||||
|
||||
TEST(Registry, StompExclude) {
|
||||
entt::registry registry;
|
||||
|
||||
const auto prototype = registry.create();
|
||||
registry.assign<int>(prototype, 3);
|
||||
registry.assign<char>(prototype, 'c');
|
||||
|
||||
const auto entity = registry.create();
|
||||
registry.assign<int>(entity, 3);
|
||||
registry.assign<char>(entity, 'c');
|
||||
registry.stomp(entity, prototype, registry, entt::exclude<char>);
|
||||
|
||||
const auto other = registry.create();
|
||||
registry.stomp<int, char>(entity, registry, other, entt::exclude<char>);
|
||||
ASSERT_TRUE(registry.has<int>(entity));
|
||||
ASSERT_FALSE(registry.has<char>(entity));
|
||||
ASSERT_EQ(registry.get<int>(entity), 3);
|
||||
|
||||
ASSERT_TRUE(registry.has<int>(other));
|
||||
ASSERT_FALSE(registry.has<char>(other));
|
||||
ASSERT_EQ(registry.get<int>(other), 3);
|
||||
registry.replace<int>(prototype, 42);
|
||||
registry.stomp(entity, prototype, registry, entt::exclude<int>);
|
||||
|
||||
registry.replace<int>(entity, 42);
|
||||
registry.stomp(entity, registry, other, entt::exclude<int>);
|
||||
ASSERT_TRUE((registry.has<int, char>(entity)));
|
||||
ASSERT_EQ(registry.get<int>(entity), 3);
|
||||
ASSERT_EQ(registry.get<char>(entity), 'c');
|
||||
|
||||
ASSERT_TRUE(registry.has<int>(other));
|
||||
ASSERT_TRUE(registry.has<char>(other));
|
||||
ASSERT_EQ(registry.get<int>(other), 3);
|
||||
ASSERT_EQ(registry.get<char>(other), 'c');
|
||||
registry.remove<int>(entity);
|
||||
registry.remove<char>(entity);
|
||||
registry.stomp(entity, prototype, registry, entt::exclude<int, char>);
|
||||
|
||||
registry.remove<int>(other);
|
||||
registry.remove<char>(other);
|
||||
registry.stomp(entity, registry, other, entt::exclude<int, char>);
|
||||
ASSERT_TRUE(registry.orphan(entity));
|
||||
}
|
||||
|
||||
ASSERT_TRUE(registry.orphan(other));
|
||||
TEST(Registry, StompMulti) {
|
||||
entt::registry registry;
|
||||
|
||||
const auto prototype = registry.create();
|
||||
registry.assign<int>(prototype, 3);
|
||||
registry.assign<char>(prototype, 'c');
|
||||
|
||||
entt::entity entities[2];
|
||||
registry.create(std::begin(entities), std::end(entities));
|
||||
registry.stomp(std::begin(entities), std::end(entities), prototype, registry);
|
||||
|
||||
ASSERT_TRUE((registry.has<int, char>(entities[0])));
|
||||
ASSERT_TRUE((registry.has<int, char>(entities[1])));
|
||||
ASSERT_EQ(registry.get<int>(entities[0]), 3);
|
||||
ASSERT_EQ(registry.get<char>(entities[1]), 'c');
|
||||
}
|
||||
|
||||
TEST(Registry, StompMoveOnlyComponent) {
|
||||
entt::registry registry;
|
||||
|
||||
const auto prototype = registry.create();
|
||||
registry.assign<std::unique_ptr<int>>(prototype);
|
||||
registry.assign<char>(prototype);
|
||||
|
||||
const auto entity = registry.create();
|
||||
registry.stomp(entity, prototype, registry);
|
||||
|
||||
registry.assign<std::unique_ptr<int>>(entity);
|
||||
registry.assign<char>(entity);
|
||||
|
||||
const auto other = registry.create();
|
||||
registry.stomp(entity, registry, other);
|
||||
|
||||
ASSERT_TRUE(registry.has<char>(other));
|
||||
ASSERT_FALSE(registry.has<std::unique_ptr<int>>(other));
|
||||
ASSERT_TRUE(registry.has<char>(entity));
|
||||
ASSERT_FALSE(registry.has<std::unique_ptr<int>>(entity));
|
||||
}
|
||||
|
||||
TEST(Registry, GetOrAssign) {
|
||||
|
||||
Reference in New Issue
Block a user