Explorar o código

registry: rebind pools from move constructor/assignment operator

Michele Caini %!s(int64=5) %!d(string=hai) anos
pai
achega
91db153710
Modificáronse 2 ficheiros con 81 adicións e 4 borrados
  1. 40 4
      src/entt/entity/registry.hpp
  2. 41 0
      test/entt/entity/registry.cpp

+ 40 - 4
src/entt/entity/registry.hpp

@@ -115,6 +115,7 @@ class basic_registry {
         if(auto &&pdata = pools[index]; !pdata.pool) {
             pdata.pool.reset(new storage_type<Component>());
             pdata.poly = std::ref(*static_cast<storage_type<Component> *>(pdata.pool.get()));
+            pdata.pool->payload(this);
         }
 
         return static_cast<storage_type<Component> *>(pools[index].pool.get());
@@ -146,6 +147,14 @@ class basic_registry {
         available = entity_type{entt};
     }
 
+    void rebind_pools() ENTT_NOEXCEPT {
+        for(auto &&pdata: pools) {
+            if(pdata.pool) {
+                pdata.pool->payload(this);
+            }
+        }
+    }
+
 public:
     /*! @brief Underlying entity identifier. */
     using entity_type = Entity;
@@ -177,11 +186,38 @@ public:
     /*! @brief Default constructor. */
     basic_registry() = default;
 
-    /*! @brief Default move constructor. */
-    basic_registry(basic_registry &&) = default;
+    /**
+     * @brief Move constructor.
+     * @param other The instance to move from.
+     */
+    basic_registry(basic_registry &&other) ENTT_NOEXCEPT
+        : vars{std::move(other.vars)},
+          pools{std::move(other.pools)},
+          groups{std::move(other.groups)},
+          entities{std::move(other.entities)},
+          available{other.available}
+    {
+        rebind_pools();
+    }
 
-    /*! @brief Default move assignment operator. @return This registry. */
-    basic_registry & operator=(basic_registry &&) = default;
+    /**
+     * @brief Move assignment operator.
+     * @param other The instance to assign from.
+     * @return This registry.
+     */
+    basic_registry & operator=(basic_registry &&other) ENTT_NOEXCEPT {
+        if(this != &other) {
+            vars = std::move(other.vars);
+            pools = std::move(other.pools);
+            groups = std::move(other.groups);
+            entities = std::move(other.entities);
+            available = other.available;
+
+            rebind_pools();
+        }
+
+        return *this;
+    }
 
     /**
      * @brief Prepares a pool for the given type if required.

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

@@ -42,6 +42,14 @@ struct listener {
     int counter{0};
 };
 
+struct owner {
+    void receive(const entt::registry &ref) {
+        parent = &ref;
+    }
+
+    const entt::registry *parent{nullptr};
+};
+
 TEST(Registry, Context) {
     entt::registry registry;
 
@@ -258,6 +266,39 @@ TEST(Registry, Functionalities) {
     ASSERT_EQ(registry.capacity<char>(), 0u);
 }
 
+TEST(Registry, Move) {
+    entt::registry registry;
+    const auto entity = registry.create();
+    owner test{};
+
+    registry.on_construct<int>().connect<&owner::receive>(test);
+    registry.on_destroy<int>().connect<&owner::receive>(test);
+
+    ASSERT_EQ(test.parent, nullptr);
+
+    registry.emplace<int>(entity);
+
+    ASSERT_EQ(test.parent, &registry);
+
+    entt::registry other{std::move(registry)};
+    other.remove<int>(entity);
+    registry.emplace<int>(registry.create(entity));
+
+    ASSERT_EQ(test.parent, &other);
+
+    registry = std::move(other);
+    registry.emplace<int>(entity);
+    registry.emplace<int>(registry.create(entity));
+
+    ASSERT_EQ(test.parent, &registry);
+
+    test.parent = nullptr;
+    registry = std::move(registry);
+    registry.remove<int>(entity);
+
+    ASSERT_EQ(test.parent, &registry);
+}
+
 TEST(Registry, ReplaceAggregate) {
     entt::registry registry;
     const auto entity = registry.create();