clone functionality (close #161)

This commit is contained in:
Michele Caini
2018-12-13 08:55:43 +01:00
parent c9fddedbf1
commit cb9a147fff
6 changed files with 121 additions and 26 deletions

28
AUTHORS
View File

@@ -1,16 +1,28 @@
# Author
Michele Caini aka skypjack
skypjack
# Contributors
Paolo Monteverde aka morbo84
David Nerjes aka DavidHamburg
Indi Kernick aka Kerndog73
Malte Müller-Rowold aka m-waka
Richard Caseres aka richardbmx
Michael Keck aka Croydon
BenediktConze
bjadamson
Croydon
dbacchet
DonKult
drglove
eugeneko
gale83
ghost
Milerius
morbo84
m-waka
Kerndog73
pgruenbacher
prowolf
vblanco20-1
willtunnels
w1th0utnam3
# Special thanks for patrons
Arn aka ArnCarveris
ArnCarveris

5
TODO
View File

@@ -18,9 +18,12 @@
* destroy overload that accepts a couple of iterators (see create)
* allow for built-in parallel each if possible
* add on-the-fly sort functionality (is it possible?)
* write/show how to work with missing components using and-strategies
* write/show how to create an archetype based model on top of EnTT
* mention hunter in the readme file, section packaging tools
* monostate: make constraint trivially copyable due to atomic optional
* monostate: use template variable to avoid {}
* travis + windows is now available, try it
* hashed string: static (constexpr) member function to_value for direct hashing
* entity: simplify get functions so as to generate less symbols for multiple components
* events on replace, so that one can track updated components? indagate impact
* add merge functionality for type list

View File

@@ -178,19 +178,6 @@ public:
/*! @brief Type of sink for the given component. */
using sink_type = typename component_signal_type::sink_type;
/*! @brief Default constructor. */
registry() ENTT_NOEXCEPT = default;
/*! @brief Copying a registry isn't allowed. */
registry(const registry &) = delete;
/*! @brief Default move constructor. */
registry(registry &&) = default;
/*! @brief Copying a registry isn't allowed. @return This registry. */
registry & operator=(const registry &) = delete;
/*! @brief Default move assignment operator. @return This registry. */
registry & operator=(registry &&) = default;
/**
* @brief Returns the numeric identifier of a type of component at runtime.
*
@@ -208,6 +195,19 @@ public:
return component_family::type<Component>;
}
/*! @brief Default constructor. */
registry() ENTT_NOEXCEPT = default;
/*! @brief Copying a registry isn't allowed. */
registry(const registry &) = delete;
/*! @brief Default move constructor. */
registry(registry &&) = default;
/*! @brief Copying a registry isn't allowed. @return This registry. */
registry & operator=(const registry &) = delete;
/*! @brief Default move assignment operator. @return This registry. */
registry & operator=(registry &&) = default;
/**
* @brief Returns the number of existing components of the given type.
* @tparam Component Type of component of which to return the size.
@@ -1404,6 +1404,43 @@ public:
return { std::move(set) };
}
/**
* @brief Clones the given components and all the entity identifiers.
*
* The components must be copiable for obvious reasons. The entities
* maintain their versions once copied.
*
* @note
* There isn't an efficient way to know if all the entities are assigned at
* least one component once copied. Therefore, there may be orphans. It is
* up to the caller to clean up the registry if necessary.
*
* @warning
* This function requires that the registry be empty. In case it isn't, all
* the data will be automatically deleted beforehand.
*
* @tparam Component Types of components to clone.
* @param reg A valid reference to a source registry.
*/
template<typename... Component>
void clone(const registry &reg) {
*this = {};
(assure<Component>(), ...);
(reserve<Component>(reg.size<Component>()), ...);
(std::copy(reg.raw<Component>(), reg.raw<Component>() + reg.size<Component>(), pool<Component>().raw()), ...);
// double lambda function used to work around a bug of gcc7
(std::for_each(reg.data<Component>(), reg.data<Component>() + reg.size<Component>(), ([](auto *cpool) {
return [cpool](const auto entity) { cpool->construct(entity); };
})(pools[component_family::type<Component>].get())), ...);
next = reg.next;
available = reg.available;
entities.resize(reg.entities.size());
std::copy(reg.entities.cbegin(), reg.entities.cend(), entities.begin());
}
/**
* @brief Returns a temporary object to use to create snapshots.
*

View File

@@ -245,6 +245,7 @@ TEST(Benchmark, IterateTwoComponents1MOne) {
TEST(Benchmark, IterateTwoComponentsPersistent1M) {
entt::registry<> registry;
registry.persistent_view<position, velocity>();
std::cout << "Iterating over 1000000 entities, two components, persistent view" << std::endl;
@@ -439,6 +440,7 @@ TEST(Benchmark, IterateFiveComponents1MOne) {
TEST(Benchmark, IterateFiveComponentsPersistent1M) {
entt::registry<> registry;
registry.persistent_view<position, velocity, comp<1>, comp<2>, comp<3>>();
std::cout << "Iterating over 1000000 entities, five components, persistent view" << std::endl;
@@ -687,6 +689,7 @@ TEST(Benchmark, IterateTenComponents1MOne) {
TEST(Benchmark, IterateTenComponentsPersistent1M) {
entt::registry<> registry;
registry.persistent_view<position, velocity, comp<1>, comp<2>, comp<3>, comp<4>, comp<5>, comp<6>, comp<7>, comp<8>>();
std::cout << "Iterating over 1000000 entities, ten components, persistent view" << std::endl;

View File

@@ -748,18 +748,18 @@ TEST(Registry, PersistentViewSortInterleaved) {
entt::registry<> registry;
const auto view = registry.persistent_view<int, char>();
auto e0 = registry.create();
const auto e0 = registry.create();
registry.assign<int>(e0, 0);
registry.assign<char>(e0, '0');
auto e1 = registry.create();
const auto e1 = registry.create();
registry.assign<int>(e1, 1);
registry.assign<char>(e1, '1');
registry.sort<int>([](auto lhs, auto rhs) { return lhs > rhs; });
registry.sort<char>([](auto lhs, auto rhs) { return lhs < rhs; });
auto e2 = registry.create();
const auto e2 = registry.create();
registry.assign<int>(e2, 2);
registry.assign<char>(e2, '2');
@@ -776,3 +776,43 @@ TEST(Registry, PersistentViewSortInterleaved) {
}
});
}
TEST(Registry, Clone) {
entt::registry<> registry;
entt::registry<> other;
const auto entity = other.create();
other.assign<int>(entity, 42);
other.assign<char>(entity, 'c');
registry.destroy(registry.create());
const auto e0 = registry.create();
registry.assign<int>(e0, 0);
registry.assign<double>(e0, 0.0);
const auto e1 = registry.create();
registry.assign<int>(e1, 1);
registry.assign<char>(e1, '1');
registry.assign<double>(e1, 1.1);
const auto e2 = registry.create();
registry.assign<int>(e2, 2);
registry.assign<char>(e2, '2');
registry.destroy(e1);
other.clone<int, char>(registry);
ASSERT_FALSE(other.valid(entity));
ASSERT_TRUE(other.valid(e0));
ASSERT_FALSE(other.valid(e1));
ASSERT_TRUE(other.valid(e2));
ASSERT_TRUE((other.has<int>(e0)));
ASSERT_FALSE((other.has<double>(e0)));
ASSERT_TRUE((other.has<int, char>(e2)));
ASSERT_EQ(other.get<int>(e0), 0);
ASSERT_EQ(other.get<int>(e2), 2);
ASSERT_EQ(other.get<char>(e2), '2');
}

View File

@@ -848,7 +848,7 @@ TEST(SparseSetWithType, MoveOnlyComponent) {
move_only_component & operator=(move_only_component &&) = default;
};
// it's purpose is to ensure that move only components are always accepted
// the purpose is to ensure that move only components are always accepted
entt::sparse_set<std::uint64_t, move_only_component> set;
(void)set;
}