Просмотр исходного кода

batch creation returns iterators and no longer raw pointers

Michele Caini 6 лет назад
Родитель
Сommit
ece4480200

+ 2 - 0
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)

+ 8 - 20
src/entt/entity/registry.hpp

@@ -86,28 +86,16 @@ class basic_registry {
         }
 
         template<typename It>
-        Component * batch(basic_registry &registry, It first, It last) {
-            Component *component = nullptr;
+        auto batch(basic_registry &registry, 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, &registry](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, &registry, component](const auto entt) mutable {
-                        construction.publish(entt, registry, *(component++));
-                    });
-                }
+            if(!construction.empty()) {
+                std::for_each(first, last, [this, &registry, it](const auto entt) mutable {
+                    construction.publish(entt, registry, *(it++));
+                });
             }
 
-            return component;
+            return it;
         }
 
         void remove(basic_registry &registry, 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>

+ 5 - 3
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<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);

+ 30 - 8
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<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 */

+ 0 - 4
test/entt/entity/registry.cpp

@@ -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});

+ 3 - 3
test/entt/entity/sparse_set.cpp

@@ -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);
 }
 

+ 5 - 5
test/entt/entity/storage.cpp

@@ -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};