diff --git a/TODO b/TODO index b328c42bd..eca4fcb73 100644 --- a/TODO +++ b/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) diff --git a/src/entt/entity/registry.hpp b/src/entt/entity/registry.hpp index 1564c4a24..4e6091ac8 100644 --- a/src/entt/entity/registry.hpp +++ b/src/entt/entity/registry.hpp @@ -86,28 +86,16 @@ class basic_registry { } template - Component * batch(basic_registry ®istry, It first, It last) { - Component *component = nullptr; + auto batch(basic_registry ®istry, It first, It last) { + auto it = storage::batch(first, last); - if constexpr(std::is_empty_v) { - storage::batch(first, last); - - if(!construction.empty()) { - std::for_each(first, last, [this, ®istry](const auto entt) { - construction.publish(entt, registry, Component{}); - }); - } - } else { - component = storage::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 diff --git a/src/entt/entity/sparse_set.hpp b/src/entt/entity/sparse_set.hpp index dca8ed06e..a9c965217 100644 --- a/src/entt/entity/sparse_set.hpp +++ b/src/entt/entity/sparse_set.hpp @@ -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 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); diff --git a/src/entt/entity/storage.hpp b/src/entt/entity/storage.hpp index 76422ca2d..15440e73a 100644 --- a/src/entt/entity/storage.hpp +++ b/src/entt/entity/storage.hpp @@ -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 - 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.
+ * 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 + iterator_type batch(It first, It last) { + underlying_type::batch(first, last); + return begin(); + } }; /*! @copydoc basic_storage */ diff --git a/test/entt/entity/registry.cpp b/test/entt/entity/registry.cpp index f197fff91..88f6280fc 100644 --- a/test/entt/entity/registry.cpp +++ b/test/entt/entity/registry.cpp @@ -1138,10 +1138,6 @@ TEST(Registry, CreateManyEntitiesWithComponentsAtOnce) { ASSERT_FALSE(registry.empty()); ASSERT_FALSE(registry.empty()); - ASSERT_NE(iptr, nullptr); - ASSERT_NE(cptr, nullptr); - ASSERT_EQ(eptr, nullptr); - ASSERT_EQ(registry.size(), entt::registry::size_type{3}); ASSERT_EQ(registry.size(), entt::registry::size_type{3}); ASSERT_EQ(registry.size(), entt::registry::size_type{3}); diff --git a/test/entt/entity/sparse_set.cpp b/test/entt/entity/sparse_set.cpp index 5a2cd12ac..b8f7f0a6f 100644 --- a/test/entt/entity/sparse_set.cpp +++ b/test/entt/entity/sparse_set.cpp @@ -116,7 +116,7 @@ TEST(SparseSet, Pagination) { TEST(SparseSet, BatchAdd) { entt::sparse_set set; - entt::sparse_set::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); } diff --git a/test/entt/entity/storage.cpp b/test/entt/entity/storage.cpp index f7e77ab4c..c4ac65616 100644 --- a/test/entt/entity/storage.cpp +++ b/test/entt/entity/storage.cpp @@ -96,14 +96,14 @@ TEST(Storage, EmptyType) { TEST(Storage, BatchAdd) { entt::storage pool; - entt::storage::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 pool; - entt::storage::entity_type entities[2]; + entt::entity entities[2]; entities[0] = entt::entity{3}; entities[1] = entt::entity{42};