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

doc: updated documentation about signals from a registry

Michele Caini 5 лет назад
Родитель
Сommit
2d69e5f6ff
3 измененных файлов с 186 добавлено и 39 удалено
  1. 10 11
      docs/md/entity.md
  2. 170 16
      src/entt/entity/pool.hpp
  3. 6 12
      src/entt/entity/registry.hpp

+ 10 - 11
docs/md/entity.md

@@ -364,7 +364,7 @@ registry.on_construct<position>().disconnect<&my_free_function>();
 registry.on_construct<position>().disconnect<&my_class::member>(instance);
 ```
 
-To be notified when components are destroyed, use the `on_destroy` member
+To be notified when a component is destroyed, use the `on_destroy` member
 function instead. Finally, the `on_update` member function will return a sink
 to which to connect listeners to observe changes.<br/>
 In the last case, given the way C++ works, it's also necessary to use specific
@@ -375,12 +375,9 @@ attached to `on_update` will only be invoked following a call to `replace` or
 The function type of a listener should be equivalent to the following:
 
 ```cpp
-void(entt::registry &, entt::entity);
+void(entt::entity);
 ```
 
-In all cases, listeners are provided with the registry that triggered the
-notification and the involved entity.
-
 Note also that:
 
 * Listeners for the construction signals are invoked **after** components have
@@ -633,25 +630,25 @@ that isn't associated with the given registry can result in undefined behavior.
 
 The `registry` class is designed to be able to create short circuits between its
 functions. This simplifies the definition of _dependencies_ between different
-operations.<br/>
+operations and registries.<br/>
 For example, the following adds (or replaces) the component `a_type` whenever
 `my_type` is assigned to an entity:
 
 ```cpp
-registry.on_construct<my_type>().connect<&entt::registry::emplace_or_replace<a_type>>();
+registry.on_construct<my_type>().connect<&entt::registry::emplace_or_replace<a_type>>(registry);
 ```
 
 Similarly, the code shown below removes `a_type` from an entity whenever
 `my_type` is assigned to it:
 
 ```cpp
-registry.on_construct<my_type>().connect<&entt::registry::remove<a_type>>();
+registry.on_construct<my_type>().connect<&entt::registry::remove<a_type>>(registry);
 ```
 
 A dependency can also be easily broken as follows:
 
 ```cpp
-registry.on_construct<my_type>().disconnect<&entt::registry::emplace_or_replace<a_type>>();
+registry.on_construct<my_type>().disconnect<&entt::registry::emplace_or_replace<a_type>>(registry);
 ```
 
 There are many other types of dependencies. In general, most of the functions
@@ -666,11 +663,13 @@ _extend_ their classes and this may not always be possible.<br/>
 The `invoke` helper allows to _propagate_ the signal in these cases:
 
 ```cpp
-registry.on_construct<clazz>().connect<entt::invoke<&clazz::func>>();
+registry.on_construct<clazz>().connect<entt::invoke<&clazz::func>>(registry);
 ```
 
 All it does is pick up the _right_ component for the received entity and invoke
-the requested method, passing on the arguments if necessary.
+the requested method, passing on the arguments if necessary.<br/>
+The registry is also supplied by the invoker directly to the function invoked as
+the first argument.
 
 ### Handle
 

+ 170 - 16
src/entt/entity/pool.hpp

@@ -14,35 +14,126 @@
 namespace entt {
 
 
-template<typename Entity, typename Component>
-struct default_pool final: storage<Entity, Component> {
-    static_assert(std::is_same_v<Component, std::decay_t<Component>>, "Invalid component type");
+/**
+ * @brief Default pool implementation.
+ * @tparam Entity A valid entity type (see entt_traits for more details).
+ * @tparam Type Type of objects assigned to the entities.
+ */
+template<typename Entity, typename Type>
+struct default_pool final: storage<Entity, Type> {
+    static_assert(std::is_same_v<Type, std::decay_t<Type>>, "Invalid object type");
+
+    /*! @brief Type of the objects associated with the entities. */
+    using object_type = Type;
+    /*! @brief Underlying entity identifier. */
+    using entity_type = Entity;
 
+    /**
+    * @brief Returns a sink object.
+    *
+    * The sink returned by this function can be used to receive notifications
+    * whenever a new instance is created and assigned to an entity.<br/>
+    * The function type for a listener is equivalent to:
+    *
+    * @code{.cpp}
+    * void(Entity);
+    * @endcode
+    *
+    * Listeners are invoked **after** the object has been assigned to the
+    * entity.
+    *
+    * @sa sink
+    *
+    * @return A temporary sink object.
+    */
     [[nodiscard]] auto on_construct() ENTT_NOEXCEPT {
         return sink{construction};
     }
 
+    /**
+    * @brief Returns a sink object for the given type.
+    *
+    * The sink returned by this function can be used to receive notifications
+    * whenever an instance is explicitly updated.<br/>
+    * The function type for a listener is equivalent to:
+    *
+    * @code{.cpp}
+    * void(Entity);
+    * @endcode
+    *
+    * Listeners are invoked **after** the object has been updated.
+    *
+    * @sa sink
+    *
+    * @return A temporary sink object.
+    */
     [[nodiscard]] auto on_update() ENTT_NOEXCEPT {
         return sink{update};
     }
 
+    /**
+    * @brief Returns a sink object for the given type.
+    *
+    * The sink returned by this function can be used to receive notifications
+    * whenever an instance is removed from an entity and thus destroyed.<br/>
+    * The function type for a listener is equivalent to:
+    *
+    * @code{.cpp}
+    * void(Entity);
+    * @endcode
+    *
+    * Listeners are invoked **before** the object has been removed from the
+    * entity.
+    *
+    * @sa sink
+    *
+    * @return A temporary sink object.
+    */
     [[nodiscard]] auto on_destroy() ENTT_NOEXCEPT {
         return sink{destruction};
     }
 
+    /**
+    * @brief Assigns an entity to a pool.
+    *
+    * A new object is created and initialized with the arguments provided (the
+    * object type must have a proper constructor or be of aggregate type). Then
+    * the instance is assigned to the given entity.
+    *
+    * @warning
+    * Attempting to use an invalid entity or to assign an entity that already
+    * belongs to the pool 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 already belongs to the pool.
+    *
+    * @tparam Args Types of arguments to use to construct the object.
+    * @param entity A valid entity identifier.
+    * @param args Parameters to use to initialize the object.
+    * @return A reference to the newly created object.
+    */
     template<typename... Args>
-    decltype(auto) emplace(const Entity entt, Args &&... args) {
-        storage<entity_type, Component>::emplace(entt, std::forward<Args>(args)...);
+    decltype(auto) emplace(const entity_type entt, Args &&... args) {
+        storage<entity_type, Type>::emplace(entt, std::forward<Args>(args)...);
         construction.publish(entt);
 
-        if constexpr(!is_eto_eligible_v<Component>) {
+        if constexpr(!is_eto_eligible_v<object_type>) {
             return this->get(entt);
         }
     }
 
+    /**
+    * @brief Assigns multiple entities to a pool.
+    *
+    * @sa emplace
+    *
+    * @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.
+    * @param value An instance of the type to assign.
+    */
     template<typename It, typename... Args>
     void insert(It first, It last, Args &&... args) {
-        storage<entity_type, Component>::insert(first, last, std::forward<Args>(args)...);
+        storage<entity_type, object_type>::insert(first, last, std::forward<Args>(args)...);
 
         if(!construction.empty()) {
             for(; first != last; ++first) {
@@ -51,11 +142,31 @@ struct default_pool final: storage<Entity, Component> {
         }
     }
 
-    void erase(const Entity entt) override {
+    /**
+    * @brief Removes an entity from a pool.
+    *
+    * @warning
+    * Attempting to use an invalid entity or to remove an entity that doesn't
+    * belong to the pool 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 belong to the pool.
+    *
+    * @param entity A valid entity identifier.
+    */
+    void erase(const entity_type entt) override {
         destruction.publish(entt);
-        storage<entity_type, Component>::erase(entt);
+        storage<entity_type, object_type>::erase(entt);
     }
 
+    /**
+    * @brief Removes multiple entities from a pool.
+    *
+    * @see remove
+    *
+    * @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 erase(It first, It last) {
         if(std::distance(first, last) == std::distance(this->begin(), this->end())) {
@@ -73,9 +184,34 @@ struct default_pool final: storage<Entity, Component> {
         }
     }
 
+    /**
+    * @brief Patches the given instance for an entity.
+    *
+    * The signature of the functions should be equivalent to the following:
+    *
+    * @code{.cpp}
+    * void(Type &);
+    * @endcode
+    *
+    * @note
+    * Empty types aren't explicitly instantiated and therefore they are never
+    * returned. However, this function can be used to trigger an update signal
+    * for them.
+    *
+    * @warning
+    * Attempting to use an invalid entity or to patch an object of an entity
+    * that doesn't belong to the pool 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 belong to the pool.
+    *
+    * @tparam Func Types of the function objects to invoke.
+    * @param entity A valid entity identifier.
+    * @param func Valid function objects.
+    * @return A reference to the patched instance.
+    */
     template<typename... Func>
-    decltype(auto) patch(const Entity entt, [[maybe_unused]] Func &&... func) {
-        if constexpr(is_eto_eligible_v<Component>) {
+    decltype(auto) patch(const entity_type entt, [[maybe_unused]] Func &&... func) {
+        if constexpr(is_eto_eligible_v<object_type>) {
             update.publish(entt);
         } else {
             (std::forward<Func>(func)(this->get(entt)), ...);
@@ -84,14 +220,32 @@ struct default_pool final: storage<Entity, Component> {
         }
     }
 
-    decltype(auto) replace(const Entity entt, Component component) {
-        return patch(entt, [&component](auto &&curr) { curr = std::move(component); });
+    /**
+    * @brief Replaces the object associated with an entity in a pool.
+    *
+    * A new object is created and initialized with the arguments provided (the
+    * object type must have a proper constructor or be of aggregate type). Then
+    * the instance is assigned to the given entity.
+    *
+    * @warning
+    * Attempting to use an invalid entity or to replace an object of an entity
+    * that doesn't belong to the pool 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 belong to the pool.
+    *
+    * @tparam Args Types of arguments to use to construct the object.
+    * @param entity A valid entity identifier.
+    * @param args Parameters to use to initialize the object.
+    * @return A reference to the object being replaced.
+    */
+    decltype(auto) replace(const entity_type entt, object_type instance) {
+        return patch(entt, [&instance](auto &&curr) { curr = std::move(instance); });
     }
 
 private:
-    sigh<void(const Entity)> construction{};
-    sigh<void(const Entity)> destruction{};
-    sigh<void(const Entity)> update{};
+    sigh<void(const entity_type)> construction{};
+    sigh<void(const entity_type)> destruction{};
+    sigh<void(const entity_type)> update{};
 };
 
 

+ 6 - 12
src/entt/entity/registry.hpp

@@ -1015,15 +1015,13 @@ public:
     /**
      * @brief Returns a sink object for the given component.
      *
-     * A sink is an opaque object used to connect listeners to components.<br/>
      * The sink returned by this function can be used to receive notifications
      * whenever a new instance of the given component is created and assigned to
-     * an entity.
-     *
+     * an entity.<br/>
      * The function type for a listener is equivalent to:
      *
      * @code{.cpp}
-     * void(registry<Entity> &, Entity);
+     * void(Entity);
      * @endcode
      *
      * Listeners are invoked **after** the component has been assigned to the
@@ -1042,14 +1040,12 @@ public:
     /**
      * @brief Returns a sink object for the given component.
      *
-     * A sink is an opaque object used to connect listeners to components.<br/>
      * The sink returned by this function can be used to receive notifications
-     * whenever an instance of the given component is explicitly updated.
-     *
+     * whenever an instance of the given component is explicitly updated.<br/>
      * The function type for a listener is equivalent to:
      *
      * @code{.cpp}
-     * void(registry<Entity> &, Entity);
+     * void(Entity);
      * @endcode
      *
      * Listeners are invoked **after** the component has been updated.
@@ -1067,15 +1063,13 @@ public:
     /**
      * @brief Returns a sink object for the given component.
      *
-     * A sink is an opaque object used to connect listeners to components.<br/>
      * The sink returned by this function can be used to receive notifications
      * whenever an instance of the given component is removed from an entity and
-     * thus destroyed.
-     *
+     * thus destroyed.<br/>
      * The function type for a listener is equivalent to:
      *
      * @code{.cpp}
-     * void(registry<Entity> &, Entity);
+     * void(Entity);
      * @endcode
      *
      * Listeners are invoked **before** the component has been removed from the