registry/storage: assign review
This commit is contained in:
@@ -206,8 +206,26 @@ vel.dx = 0.;
|
||||
vel.dy = 0.;
|
||||
```
|
||||
|
||||
This function is overloaded and accepts also a couple of iterators to be used to
|
||||
assign the same component to multiple entities at once.
|
||||
This function is overloaded and accepts also a couple of iterators in order to:
|
||||
|
||||
* Assign the same component to multiple entities at once when a type is
|
||||
specified as a template parameter or an instance is passed as an argument.
|
||||
|
||||
```cpp
|
||||
// default initialized type assigned by copy to all entities
|
||||
registry.assign<position>(first, last);
|
||||
|
||||
// user-defined instance assigned by copy to all entities
|
||||
registry.assign(from, to, position{0., 0.});
|
||||
```
|
||||
|
||||
* Assign a range of components to multiple entities when a range is provided
|
||||
(the length of the range of components must be the same of that of entities):
|
||||
|
||||
```cpp
|
||||
// first and last specify the range of entities, instances points to the first element of the range of components
|
||||
registry.assign<position>(first, last, instances);
|
||||
```
|
||||
|
||||
If an entity already has the given component, the `replace` member function
|
||||
template can be used to replace it:
|
||||
|
||||
@@ -69,11 +69,10 @@ class basic_registry {
|
||||
return this->get(entt);
|
||||
}
|
||||
|
||||
template<typename It, typename... Func>
|
||||
template<typename It, typename... Value>
|
||||
std::enable_if_t<std::is_same_v<typename std::iterator_traits<It>::value_type, Entity>, void>
|
||||
assign(basic_registry &owner, It first, It last, Func... func) {
|
||||
this->construct(first, last);
|
||||
(func(this->raw() + this->size() - std::distance(first, last)), ...);
|
||||
assign(basic_registry &owner, It first, It last, Value &&... value) {
|
||||
this->construct(first, last, std::forward<Value>(value)...);
|
||||
|
||||
if(!construction.empty()) {
|
||||
std::for_each(first, last, [this, &owner](const auto entt) { construction.publish(owner, entt); });
|
||||
@@ -213,10 +212,7 @@ class basic_registry {
|
||||
if constexpr(ENTT_ENABLE_ETO(Component)) {
|
||||
other.assure<Component>().assign(other, cpool.begin(), cpool.end());
|
||||
} else {
|
||||
other.assure<Component>().assign(other, cpool.begin(), cpool.end(), [&cpool](auto *instance) {
|
||||
const auto &source = static_cast<const pool_handler<Component> &>(cpool);
|
||||
std::copy(source.cbegin(), source.cend(), instance);
|
||||
});
|
||||
other.assure<Component>().assign(other, cpool.begin(), cpool.end(), static_cast<const pool_handler<Component> &>(cpool).cbegin());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -635,32 +631,38 @@ public:
|
||||
/**
|
||||
* @brief Assigns each entity in a range the given component.
|
||||
*
|
||||
* Function objects are optional. They are invoked to give the caller a
|
||||
* chance to initialize the components before they are passed to any
|
||||
* registered listener.<br/>
|
||||
* The signature of the functions should be equivalent to the following:
|
||||
*
|
||||
* @code{.cpp}
|
||||
* void(It it);
|
||||
* @endcode
|
||||
*
|
||||
* Where `it` is an iterator to the first element of the range of newly
|
||||
* created objects.
|
||||
*
|
||||
* @sa assign
|
||||
*
|
||||
* @tparam Component Type of component to create.
|
||||
* @tparam It Type of input iterator.
|
||||
* @tparam Func Types of the function objects to invoke.
|
||||
* @param first An iterator to the first element of the range of entities.
|
||||
* @param last An iterator past the last element of the range of entities.
|
||||
* @param func Valid function objects.
|
||||
* @param value An instance of the component to assign.
|
||||
*/
|
||||
template<typename Component, typename It, typename... Func>
|
||||
template<typename Component, typename It>
|
||||
std::enable_if_t<std::is_same_v<typename std::iterator_traits<It>::value_type, entity_type>, void>
|
||||
assign(It first, It last, Func... func) {
|
||||
assign(It first, It last, const Component &value = {}) {
|
||||
ENTT_ASSERT(std::all_of(first, last, [this](const auto entity) { return valid(entity); }));
|
||||
assure<Component>().assign(*this, first, last, std::move(func)...);
|
||||
assure<Component>().assign(*this, first, last, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns each entity in a range the given components.
|
||||
*
|
||||
* @sa assign
|
||||
*
|
||||
* @tparam Component Type of component to create.
|
||||
* @tparam EIt Type of input iterator.
|
||||
* @tparam CIt Type of input iterator.
|
||||
* @param first An iterator to the first element of the range of entities.
|
||||
* @param last An iterator past the last element of the range of entities.
|
||||
* @param value An iterator to the first element of the range of components.
|
||||
*/
|
||||
template<typename Component, typename EIt, typename CIt>
|
||||
std::enable_if_t<std::is_same_v<typename std::iterator_traits<EIt>::value_type, entity_type>, void>
|
||||
assign(EIt first, EIt last, CIt value) {
|
||||
ENTT_ASSERT(std::all_of(first, last, [this](const auto entity) { return valid(entity); }));
|
||||
assure<Component>().assign(*this, first, last, value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -329,10 +329,8 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns one or more entities to a storage and default constructs
|
||||
* their objects.
|
||||
*
|
||||
* The object type must be at least move and default insertable.
|
||||
* @brief Assigns one or more entities to a storage and constructs their
|
||||
* objects with from a given instance.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to assign an entity that already belongs to the storage
|
||||
@@ -343,11 +341,32 @@ public:
|
||||
* @tparam It Type of input iterator.
|
||||
* @param first An iterator to the first element of the range of entities.
|
||||
* @param last An iterator past the last element of the range of entities.
|
||||
* @param value An instance of the object to construct.
|
||||
*/
|
||||
template<typename It>
|
||||
std::enable_if_t<std::is_same_v<typename std::iterator_traits<It>::value_type, entity_type>, void>
|
||||
construct(It first, It last) {
|
||||
instances.insert(instances.end(), std::distance(first, last), object_type{});
|
||||
construct(It first, It last, const object_type &value = {}) {
|
||||
instances.insert(instances.end(), std::distance(first, last), value);
|
||||
// entities go after components in case constructors throw
|
||||
underlying_type::construct(first, last);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns one or more entities to a storage and constructs their
|
||||
* objects from a given range.
|
||||
*
|
||||
* @sa construct
|
||||
*
|
||||
* @tparam EIt Type of input iterator.
|
||||
* @tparam CIt Type of input iterator.
|
||||
* @param first An iterator to the first element of the range of entities.
|
||||
* @param last An iterator past the last element of the range of entities.
|
||||
* @param value An iterator to the first element of the range of objects.
|
||||
*/
|
||||
template<typename EIt, typename CIt>
|
||||
std::enable_if_t<std::is_same_v<typename std::iterator_traits<EIt>::value_type, entity_type>, void>
|
||||
construct(EIt first, EIt last, CIt value) {
|
||||
instances.insert(instances.end(), value, value + std::distance(first, last));
|
||||
// entities go after components in case constructors throw
|
||||
underlying_type::construct(first, last);
|
||||
}
|
||||
@@ -675,7 +694,7 @@ public:
|
||||
*/
|
||||
template<typename It>
|
||||
std::enable_if_t<std::is_same_v<typename std::iterator_traits<It>::value_type, entity_type>, void>
|
||||
construct(It first, It last) {
|
||||
construct(It first, It last, const object_type & = {}) {
|
||||
underlying_type::construct(first, last);
|
||||
}
|
||||
|
||||
|
||||
@@ -315,17 +315,21 @@ TEST(Registry, CreateManyEntitiesAtOnceWithListener) {
|
||||
|
||||
registry.on_construct<int>().connect<&listener::incr<int>>(listener);
|
||||
registry.create(std::begin(entities), std::end(entities));
|
||||
registry.assign<int>(std::begin(entities), std::end(entities));
|
||||
registry.assign<char>(std::begin(entities), std::end(entities));
|
||||
registry.assign(std::begin(entities), std::end(entities), 42);
|
||||
registry.assign(std::begin(entities), std::end(entities), 'c');
|
||||
|
||||
ASSERT_EQ(registry.get<int>(entities[0]), 42);
|
||||
ASSERT_EQ(registry.get<char>(entities[1]), 'c');
|
||||
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(std::begin(entities), std::end(entities));
|
||||
registry.assign<char>(std::begin(entities), std::end(entities));
|
||||
registry.assign(std::begin(entities), std::end(entities), 'a');
|
||||
registry.assign<empty_type>(std::begin(entities), std::end(entities));
|
||||
|
||||
ASSERT_TRUE(registry.has<empty_type>(entities[0]));
|
||||
ASSERT_EQ(registry.get<char>(entities[2]), 'a');
|
||||
ASSERT_EQ(listener.counter, 6);
|
||||
}
|
||||
|
||||
@@ -1131,18 +1135,19 @@ TEST(Registry, RangeAssign) {
|
||||
ASSERT_FALSE(registry.has<float>(e2));
|
||||
|
||||
const auto view = registry.view<int, char>();
|
||||
registry.assign<float>(view.begin(), view.end());
|
||||
registry.assign(view.begin(), view.end(), 3.f);
|
||||
|
||||
ASSERT_EQ(registry.get<float>(e0), 0.f);
|
||||
ASSERT_EQ(registry.get<float>(e1), 0.f);
|
||||
ASSERT_EQ(registry.get<float>(e0), 3.f);
|
||||
ASSERT_EQ(registry.get<float>(e1), 3.f);
|
||||
ASSERT_FALSE(registry.has<float>(e2));
|
||||
|
||||
registry.clear<float>();
|
||||
registry.assign<float>(registry.data<int>(), registry.data<int>() + registry.size<int>(), [](float *raw) { *(++raw) = 1.f; });
|
||||
float value[3]{0.f, 1.f, 2.f};
|
||||
registry.assign<float>(registry.data<int>(), registry.data<int>() + registry.size<int>(), value);
|
||||
|
||||
ASSERT_EQ(registry.get<float>(e0), 0.f);
|
||||
ASSERT_EQ(registry.get<float>(e1), 1.f);
|
||||
ASSERT_EQ(registry.get<float>(e2), 0.f);
|
||||
ASSERT_EQ(registry.get<float>(e2), 2.f);
|
||||
}
|
||||
|
||||
TEST(Registry, RangeRemove) {
|
||||
|
||||
@@ -100,7 +100,7 @@ TEST(Storage, BatchAdd) {
|
||||
|
||||
entities[0] = entt::entity{3};
|
||||
entities[1] = entt::entity{42};
|
||||
pool.construct(std::begin(entities), std::end(entities));
|
||||
pool.construct(std::begin(entities), std::end(entities), {});
|
||||
|
||||
ASSERT_TRUE(pool.has(entities[0]));
|
||||
ASSERT_TRUE(pool.has(entities[1]));
|
||||
|
||||
Reference in New Issue
Block a user