Explorar el Código

registry: ::assign to assign entities to an empty registry

Michele Caini hace 6 años
padre
commit
ee5156704d
Se han modificado 4 ficheros con 49 adiciones y 3 borrados
  1. 4 3
      TODO
  2. 1 0
      src/entt/entity/entity.hpp
  3. 26 0
      src/entt/entity/registry.hpp
  4. 18 0
      test/entt/entity/registry.cpp

+ 4 - 3
TODO

@@ -6,7 +6,6 @@
 * add opaque input iterators to views and groups that return tuples <entity, T &...> (proxy), multi-pass guaranteed
 * allow to replace std:: with custom implementations
 * custom (decoupled) pools ==> N-buffering, shared components, multi-model, hibitsets, and so on
-* snapshot rework/deprecation
 * add examples (and credits) from @alanjfs :)
 * static reflection, hint: template<> meta_type_t<Type>: meta_descriptor<name, func..., props..., etc...>
 * add meta support to registry (eg entity for each component and opaque get)
@@ -16,7 +15,9 @@
 * can we write a bool conv func for entt::entity that silently compares it to null?
 * reset... reset everywhere...
 * document undocumented parts (entt::overload and a few others)
-* range-assign cannot return iterators (eg group or sort-like listeners, see #386)
 * any-of rule for views/groups (eg entity has A and any of B/C/D)
   - get -> all, exclude -> none
-* registry::clear should clear entities etc
+
+* WIP: snapshot rework/deprecation
+ - range-assign cannot return iterators (eg group or sort-like listeners, see #386)
+ - remove snapshot/loader from registry, make them external (faster) tools

+ 1 - 0
src/entt/entity/entity.hpp

@@ -5,6 +5,7 @@
 #include <cstdint>
 #include <type_traits>
 #include "../config/config.h"
+#include "../core/type_traits.hpp"
 
 
 namespace entt {

+ 26 - 0
src/entt/entity/registry.hpp

@@ -650,6 +650,32 @@ public:
         return assure<Component>().assign(*this, first, last, std::forward<Args>(args)...);
     }
 
+    /**
+     * @brief Assigns entities to an empty registry.
+     *
+     * @warning
+     * An assertion will abort the execution at runtime in debug mode if all
+     * pools aren't empty. Groups and context variables are ignored.
+     *
+     * @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.
+     */
+    template<typename It>
+    void assign(It first, It last) {
+        ENTT_ASSERT(std::all_of(pools.cbegin(), pools.cend(), [](auto &&cpool) { return cpool.pool->empty(); }));
+        entities.assign(first, last);
+        destroyed = null;
+
+        for(std::size_t pos{}, end = entities.size(); pos < end; ++pos) {
+            if((to_integral(entities[pos]) & traits_type::entity_mask) != pos) {
+                const auto version = to_integral(entities[pos]) & (traits_type::version_mask << traits_type::entity_shift);
+                entities[pos] = entity_type{to_integral(destroyed) | version};
+                destroyed = entity_type(pos);
+            }
+        }
+    }
+
     /**
      * @brief Assigns or replaces the given component for an entity.
      *

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

@@ -1593,3 +1593,21 @@ TEST(Registry, StableAssign) {
 
     ASSERT_EQ(registry.assign<int>(registry.create(), 1), 1);
 }
+
+TEST(Registry, AssignEntities) {
+    entt::registry registry;
+    entt::entity entities[3];
+    registry.create(std::begin(entities), std::end(entities));
+    registry.destroy(entities[1]);
+    registry.destroy(entities[2]);
+
+    entt::registry other;
+    other.assign(registry.data(), registry.data() + registry.size());
+
+    ASSERT_EQ(registry.size(), other.size());
+    ASSERT_TRUE(other.valid(entities[0]));
+    ASSERT_FALSE(other.valid(entities[1]));
+    ASSERT_FALSE(other.valid(entities[2]));
+    ASSERT_EQ(registry.create(), other.create());
+    ASSERT_EQ(other.entity(other.create()), entities[1]);
+}