Forráskód Böngészése

registry: added ::patch, reintroduced ::replace from arguments (close #437)

Michele Caini 6 éve
szülő
commit
32fb335832
3 módosított fájl, 48 hozzáadás és 6 törlés
  1. 7 3
      docs/md/entity.md
  2. 39 2
      src/entt/entity/registry.hpp
  3. 2 1
      test/entt/entity/registry.cpp

+ 7 - 3
docs/md/entity.md

@@ -228,11 +228,15 @@ This function is overloaded and accepts also a couple of iterators in order to:
   registry.assign<position>(first, last, instances);
   registry.assign<position>(first, last, instances);
   ```
   ```
 
 
-If an entity already has the given component, the `replace` member function
-template can be used to edit it in-place:
+If an entity already has the given component, the `replace` and `patch` member
+function templates can be used to updated it:
 
 
 ```cpp
 ```cpp
-registry.replace<position>(entity, [](auto &pos) { pos.x = pos.y = 0.; });
+// replaces the component in-place
+registry.patch<position>(entity, [](auto &pos) { pos.x = pos.y = 0.; });
+
+// constructs a new instance from a list of arguments and replaces the component
+registry.replace<position>(entity, 0., 0.);
 ```
 ```
 
 
 When it's unknown whether an entity already owns an instance of a component,
 When it's unknown whether an entity already owns an instance of a component,

+ 39 - 2
src/entt/entity/registry.hpp

@@ -693,7 +693,7 @@ public:
     }
     }
 
 
     /**
     /**
-     * @brief Replaces the given component for an entity.
+     * @brief Replaces the given component for an entity in-place.
      *
      *
      * The signature of the functions should be equivalent to the following:
      * The signature of the functions should be equivalent to the following:
      *
      *
@@ -718,11 +718,48 @@ public:
      * @return A reference to the replaced component.
      * @return A reference to the replaced component.
      */
      */
     template<typename Component, typename... Func>
     template<typename Component, typename... Func>
-    decltype(auto) replace(const entity_type entity, Func &&... func) {
+    [[deprecated("use registry::patch instead")]]
+    decltype(auto) patch(const entity_type entity, Func &&... func) {
         ENTT_ASSERT(valid(entity));
         ENTT_ASSERT(valid(entity));
         return assure<Component>().replace(*this, entity, std::forward<Func>(func)...);
         return assure<Component>().replace(*this, entity, std::forward<Func>(func)...);
     }
     }
 
 
+    /*! @copydoc patch */
+    template<typename Component, typename... Func>
+    [[deprecated("use registry::patch instead")]]
+    auto replace(const entity_type entity, Func &&... func)
+    -> decltype((func(assure<Component>().get(entity)), ...), assure<Component>().get(entity)) {
+        return patch<Component>(entity, std::forward<Func>(func)...);
+    }
+
+    /**
+     * @brief Replaces the given component for an entity.
+     *
+     * A new instance of the given component is created and initialized with the
+     * arguments provided (the component must have a proper constructor or be of
+     * aggregate type). Then the component is assigned to the given entity.
+     *
+     * @warning
+     * Attempting to use an invalid entity or to replace a component of an
+     * entity that doesn't own it results in undefined behavior.<br/>
+     * An assertion will abort the execution at runtime in debug mode in case of
+     * invalid entity or if the entity doesn't own an instance of the given
+     * component.
+     *
+     * @tparam Component Type of component to replace.
+     * @tparam Args Types of arguments to use to construct the component.
+     * @param entity A valid entity identifier.
+     * @param args Parameters to use to initialize the component.
+     * @return A reference to the component being replaced.
+     */
+    template<typename Component, typename... Args>
+    auto replace(const entity_type entity, Args &&... args)
+    -> decltype(std::enable_if_t<sizeof...(Args) != 0>(), Component{std::forward<Args>(args)...}, assure<Component>().get(entity)) {
+        return patch<Component>(entity, [args = std::forward_as_tuple(std::forward<Args>(args)...)](auto &&component) {
+            component = std::make_from_tuple<Component>(std::move(args));
+        });
+    }
+
     /**
     /**
      * @brief Removes the given components from an entity.
      * @brief Removes the given components from an entity.
      *
      *

+ 2 - 1
test/entt/entity/registry.cpp

@@ -181,7 +181,8 @@ TEST(Registry, Functionalities) {
     ASSERT_NE(&registry.get<int>(e0), &registry.get<int>(e2));
     ASSERT_NE(&registry.get<int>(e0), &registry.get<int>(e2));
     ASSERT_NE(&registry.get<char>(e0), &registry.get<char>(e2));
     ASSERT_NE(&registry.get<char>(e0), &registry.get<char>(e2));
 
 
-    ASSERT_EQ(registry.replace<int>(e0, [](auto &instance) { instance = 3; }), 3);
+    ASSERT_EQ(registry.replace<int>(e0, [](auto &instance) { instance = 2; }), 2);
+    ASSERT_EQ(registry.replace<int>(e0, 3), 3);
 
 
     ASSERT_NO_THROW(registry.assign_or_replace<int>(e0, 1));
     ASSERT_NO_THROW(registry.assign_or_replace<int>(e0, 1));
     ASSERT_NO_THROW(registry.assign_or_replace<int>(e1, 1));
     ASSERT_NO_THROW(registry.assign_or_replace<int>(e1, 1));