batch creation returns iterators and no longer raw pointers
This commit is contained in:
2
TODO
2
TODO
@@ -28,3 +28,5 @@ 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)
|
||||
|
||||
@@ -86,28 +86,16 @@ class basic_registry {
|
||||
}
|
||||
|
||||
template<typename It>
|
||||
Component * batch(basic_registry ®istry, It first, It last) {
|
||||
Component *component = nullptr;
|
||||
auto batch(basic_registry ®istry, It first, It last) {
|
||||
auto it = storage<Entity, Component>::batch(first, last);
|
||||
|
||||
if constexpr(std::is_empty_v<Component>) {
|
||||
storage<Entity, Component>::batch(first, last);
|
||||
|
||||
if(!construction.empty()) {
|
||||
std::for_each(first, last, [this, ®istry](const auto entt) {
|
||||
construction.publish(entt, registry, Component{});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
component = storage<Entity, Component>::batch(first, last);
|
||||
|
||||
if(!construction.empty()) {
|
||||
std::for_each(first, last, [this, ®istry, component](const auto entt) mutable {
|
||||
construction.publish(entt, registry, *(component++));
|
||||
});
|
||||
}
|
||||
if(!construction.empty()) {
|
||||
std::for_each(first, last, [this, ®istry, it](const auto entt) mutable {
|
||||
construction.publish(entt, registry, *(it++));
|
||||
});
|
||||
}
|
||||
|
||||
return component;
|
||||
return it;
|
||||
}
|
||||
|
||||
void remove(basic_registry ®istry, const Entity entt) {
|
||||
@@ -599,7 +587,7 @@ public:
|
||||
* @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.
|
||||
* @return No return value if the component list is empty, a tuple
|
||||
* containing the pointers to the arrays of components just created and
|
||||
* containing the iterators to the lists of components just created and
|
||||
* sorted the same of the entities otherwise.
|
||||
*/
|
||||
template<typename... Component, typename It>
|
||||
|
||||
@@ -318,7 +318,8 @@ public:
|
||||
* `end()`.
|
||||
*
|
||||
* @note
|
||||
* Input iterators stay true to the order imposed by a call to `respect`.
|
||||
* Random access iterators stay true to the order imposed by a call to
|
||||
* `respect`.
|
||||
*
|
||||
* @return An iterator to the first entity of the internal packed array.
|
||||
*/
|
||||
@@ -335,7 +336,8 @@ public:
|
||||
* iterator results in undefined behavior.
|
||||
*
|
||||
* @note
|
||||
* Input iterators stay true to the order imposed by a call to `respect`.
|
||||
* Random access iterators stay true to the order imposed by a call to
|
||||
* `respect`.
|
||||
*
|
||||
* @return An iterator to the element following the last entity of the
|
||||
* internal packed array.
|
||||
@@ -417,7 +419,7 @@ public:
|
||||
*/
|
||||
template<typename It>
|
||||
void batch(It first, It last) {
|
||||
std::for_each(first, last, [this, next = direct.size()](const auto entt) mutable {
|
||||
std::for_each(std::make_reverse_iterator(last), std::make_reverse_iterator(first), [this, next = direct.size()](const auto entt) mutable {
|
||||
ENTT_ASSERT(!has(entt));
|
||||
auto [page, offset] = index(entt);
|
||||
assure(page);
|
||||
|
||||
@@ -28,7 +28,8 @@ namespace entt {
|
||||
*
|
||||
* @note
|
||||
* Entities and objects have the same order. It's guaranteed both in case of raw
|
||||
* access (either to entities or objects) and when using input iterators.
|
||||
* access (either to entities or objects) and when using random or input access
|
||||
* iterators.
|
||||
*
|
||||
* @note
|
||||
* Internal data structures arrange elements to maximize performance. Because of
|
||||
@@ -215,8 +216,8 @@ public:
|
||||
* the storage is empty, the returned iterator will be equal to `end()`.
|
||||
*
|
||||
* @note
|
||||
* Input iterators stay true to the order imposed by a call to either `sort`
|
||||
* or `respect`.
|
||||
* Random access iterators stay true to the order imposed by a call to
|
||||
* either `sort` or `respect`.
|
||||
*
|
||||
* @return An iterator to the first instance of the given type.
|
||||
*/
|
||||
@@ -244,8 +245,8 @@ public:
|
||||
* results in undefined behavior.
|
||||
*
|
||||
* @note
|
||||
* Input iterators stay true to the order imposed by a call to either `sort`
|
||||
* or `respect`.
|
||||
* Random access iterators stay true to the order imposed by a call to
|
||||
* either `sort` or `respect`.
|
||||
*
|
||||
* @return An iterator to the element following the last instance of the
|
||||
* given type.
|
||||
@@ -345,16 +346,16 @@ public:
|
||||
* @tparam It Type of forward 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.
|
||||
* @return A pointer to the array of instances just created and sorted the
|
||||
* @return An iterator to the list of instances just created and sorted the
|
||||
* same of the entities.
|
||||
*/
|
||||
template<typename It>
|
||||
object_type * batch(It first, It last) {
|
||||
iterator_type batch(It first, It last) {
|
||||
const auto length = last - first;
|
||||
instances.resize(instances.size() + length);
|
||||
// entity goes after component in case constructor throws
|
||||
underlying_type::batch(first, last);
|
||||
return instances.data() + instances.size() - length;
|
||||
return begin();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -645,6 +646,27 @@ public:
|
||||
ENTT_ASSERT(underlying_type::has(entt));
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns one or more entities to a storage.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to assign an entity that already belongs to the storage
|
||||
* results in undefined behavior.<br/>
|
||||
* An assertion will abort the execution at runtime in debug mode if the
|
||||
* storage already contains the given entity.
|
||||
*
|
||||
* @tparam It Type of forward 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.
|
||||
* @return An iterator to the list of instances just created and sorted the
|
||||
* same of the entities.
|
||||
*/
|
||||
template<typename It>
|
||||
iterator_type batch(It first, It last) {
|
||||
underlying_type::batch(first, last);
|
||||
return begin();
|
||||
}
|
||||
};
|
||||
|
||||
/*! @copydoc basic_storage */
|
||||
|
||||
@@ -1138,10 +1138,6 @@ TEST(Registry, CreateManyEntitiesWithComponentsAtOnce) {
|
||||
ASSERT_FALSE(registry.empty<char>());
|
||||
ASSERT_FALSE(registry.empty<empty_type>());
|
||||
|
||||
ASSERT_NE(iptr, nullptr);
|
||||
ASSERT_NE(cptr, nullptr);
|
||||
ASSERT_EQ(eptr, nullptr);
|
||||
|
||||
ASSERT_EQ(registry.size<int>(), entt::registry::size_type{3});
|
||||
ASSERT_EQ(registry.size<char>(), entt::registry::size_type{3});
|
||||
ASSERT_EQ(registry.size<empty_type>(), entt::registry::size_type{3});
|
||||
|
||||
@@ -116,7 +116,7 @@ TEST(SparseSet, Pagination) {
|
||||
|
||||
TEST(SparseSet, BatchAdd) {
|
||||
entt::sparse_set<entt::entity> set;
|
||||
entt::sparse_set<entt::entity>::entity_type entities[2];
|
||||
entt::entity entities[2];
|
||||
|
||||
entities[0] = entt::entity{3};
|
||||
entities[1] = entt::entity{42};
|
||||
@@ -135,8 +135,8 @@ TEST(SparseSet, BatchAdd) {
|
||||
ASSERT_FALSE(set.empty());
|
||||
ASSERT_EQ(set.size(), 4u);
|
||||
ASSERT_EQ(set.get(entt::entity{12}), 0u);
|
||||
ASSERT_EQ(set.get(entities[0]), 1u);
|
||||
ASSERT_EQ(set.get(entities[1]), 2u);
|
||||
ASSERT_EQ(set.get(entities[0]), 2u);
|
||||
ASSERT_EQ(set.get(entities[1]), 1u);
|
||||
ASSERT_EQ(set.get(entt::entity{24}), 3u);
|
||||
}
|
||||
|
||||
|
||||
@@ -96,14 +96,14 @@ TEST(Storage, EmptyType) {
|
||||
|
||||
TEST(Storage, BatchAdd) {
|
||||
entt::storage<entt::entity, int> pool;
|
||||
entt::storage<entt::entity, int>::entity_type entities[2];
|
||||
entt::entity entities[2];
|
||||
|
||||
entities[0] = entt::entity{3};
|
||||
entities[1] = entt::entity{42};
|
||||
|
||||
pool.reserve(4);
|
||||
pool.construct(entt::entity{12}, 21);
|
||||
auto *component = pool.batch(std::begin(entities), std::end(entities));
|
||||
auto it = pool.batch(std::begin(entities), std::end(entities));
|
||||
pool.construct(entt::entity{24}, 42);
|
||||
|
||||
ASSERT_TRUE(pool.has(entities[0]));
|
||||
@@ -120,8 +120,8 @@ TEST(Storage, BatchAdd) {
|
||||
ASSERT_EQ(pool.get(entities[1]), 0);
|
||||
ASSERT_EQ(pool.get(entt::entity{24}), 42);
|
||||
|
||||
component[0] = 1;
|
||||
component[1] = 2;
|
||||
it[0] = 1;
|
||||
it[1] = 2;
|
||||
|
||||
ASSERT_EQ(pool.get(entities[0]), 1);
|
||||
ASSERT_EQ(pool.get(entities[1]), 2);
|
||||
@@ -129,7 +129,7 @@ TEST(Storage, BatchAdd) {
|
||||
|
||||
TEST(Storage, BatchAddEmptyType) {
|
||||
entt::storage<entt::entity, empty_type> pool;
|
||||
entt::storage<entt::entity, empty_type>::entity_type entities[2];
|
||||
entt::entity entities[2];
|
||||
|
||||
entities[0] = entt::entity{3};
|
||||
entities[1] = entt::entity{42};
|
||||
|
||||
Reference in New Issue
Block a user