registry::stomp supports foreign registries (close #315)
This commit is contained in:
2
TODO
2
TODO
@@ -21,7 +21,6 @@
|
||||
- use direct access (pool-like) also for context variables
|
||||
- allow for key/value variables where the key is an ENTT_ID_TYPE
|
||||
- improves multi-stomp
|
||||
* range based registry::remove and some others?
|
||||
* add examples (and credits) from @alanjfs :)
|
||||
* static reflection, hint: template<> meta_type_t<Type>: meta_descriptor<name, func..., props..., etc...>
|
||||
* ENTT_NAMED_TYPE -> ENTT_EXPORT and add also ENTT_EXPORT_WITH_NAME
|
||||
@@ -34,4 +33,5 @@
|
||||
- and so on (I'm lazy) :)
|
||||
* named types: almost-stable index optimization for direct access to pools, no more linear searches
|
||||
- can implicitly generate types for meta benefit from a similar approach?
|
||||
* registry::each to iterate all components of an entity
|
||||
* multi component registry::remove and some others?
|
||||
|
||||
@@ -42,6 +42,10 @@ namespace entt {
|
||||
*/
|
||||
template<typename Entity>
|
||||
class basic_registry {
|
||||
/*! @brief Registries are friend with one another. */
|
||||
template<typename>
|
||||
friend class basic_registry;
|
||||
|
||||
using context_family = family<struct internal_registry_context_family>;
|
||||
using component_family = family<struct internal_registry_component_family>;
|
||||
using traits_type = entt_traits<std::underlying_type_t<Entity>>;
|
||||
@@ -1542,6 +1546,13 @@ public:
|
||||
* lists. An excluded type will never be copied.
|
||||
*
|
||||
* @warning
|
||||
* Stomping entities between registries with different types of identifiers
|
||||
* without a component list is allowed only if the target registry already
|
||||
* contains the required pools.<br/>
|
||||
* An assertion will abort the execution at runtime in debug mode in case a
|
||||
* pool is missing.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to copy components that aren't copyable results in unexpected
|
||||
* behaviors.<br/>
|
||||
* A static assertion will abort the compilation when the components
|
||||
@@ -1555,22 +1566,33 @@ public:
|
||||
* invalid entities.
|
||||
*
|
||||
* @tparam Component Types of components to copy.
|
||||
* @tparam Entt A valid entity type (see entt_traits for more details).
|
||||
* @tparam Exclude Types of components not to be copied.
|
||||
* @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_type dst, const entity_type src, const basic_registry &other, exclude_t<Exclude...> = {}) {
|
||||
template<typename... Component, typename Entt, typename... Exclude>
|
||||
void stomp(const entity_type dst, const Entt src, const basic_registry<Entt> &other, exclude_t<Exclude...> = {}) {
|
||||
if constexpr(sizeof...(Component) == 0) {
|
||||
for(auto pos = other.pools.size(); pos; --pos) {
|
||||
if(const auto &pdata = other.pools[pos-1]; pdata.set && ((pdata.runtime_type != to_integer(type<Exclude>())) && ...) && pdata.pool->has(src)) {
|
||||
pdata.set(*this, dst, pdata.get(*pdata.pool, src));
|
||||
if constexpr(std::is_same_v<entity_type, Entt>) {
|
||||
pdata.set(*this, dst, pdata.get(*pdata.pool, src));
|
||||
} else {
|
||||
if(const auto ctype = pdata.runtime_type; ctype < pools.size() && pools[ctype].pool && pools[ctype].runtime_type == ctype) {
|
||||
pools[ctype].set(*this, dst, pdata.get(*pdata.pool, src));
|
||||
} else {
|
||||
const auto it = std::find_if(pools.cbegin(), pools.cend(), [ctype](auto &&curr) { return curr.pool && curr.runtime_type == ctype; });
|
||||
ENTT_ASSERT(it != pools.cend());
|
||||
it->set(*this, dst, pdata.get(*pdata.pool, src));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
static_assert(sizeof...(Exclude) == 0 && std::conjunction_v<std::is_copy_constructible<Component>...>);
|
||||
(assign_or_replace<Component>(dst, other.get<Component>(src)), ...);
|
||||
(assign_or_replace<Component>(dst, other.template get<Component>(src)), ...);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,11 @@
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/type_traits.hpp>
|
||||
#include <entt/entity/registry.hpp>
|
||||
#include <entt/entity/entity.hpp>
|
||||
|
||||
ENTT_OPAQUE_TYPE(opaque, std::uint64_t);
|
||||
ENTT_NAMED_TYPE(int);
|
||||
|
||||
struct empty_type {};
|
||||
@@ -1500,6 +1502,27 @@ TEST(Registry, StompMoveOnlyComponent) {
|
||||
ASSERT_FALSE(registry.has<std::unique_ptr<int>>(entity));
|
||||
}
|
||||
|
||||
TEST(Registry, StompBetweenRegistriesWithDifferentIdentifiers) {
|
||||
entt::basic_registry<opaque> source;
|
||||
entt::registry destination;
|
||||
|
||||
const auto entity = source.create();
|
||||
const auto other = destination.create();
|
||||
|
||||
source.assign<char>(entity, 'c');
|
||||
source.assign<double>(entity, 0.);
|
||||
source.assign<int>(entity, 42);
|
||||
|
||||
destination.prepare<int>();
|
||||
destination.prepare<char>();
|
||||
destination.stomp(other, entity, source, entt::exclude<double>);
|
||||
|
||||
ASSERT_TRUE((destination.has<char, int>(other)));
|
||||
ASSERT_FALSE(destination.has<double>(other));
|
||||
ASSERT_EQ(destination.get<char>(other), 'c');
|
||||
ASSERT_EQ(destination.get<int>(other), 42);
|
||||
}
|
||||
|
||||
TEST(Registry, GetOrAssign) {
|
||||
entt::registry registry;
|
||||
const auto entity = registry.create();
|
||||
|
||||
Reference in New Issue
Block a user