浏览代码

pool: storage adapter and signal mixin are now independent from each other

Michele Caini 5 年之前
父节点
当前提交
cb27a7fe3e
共有 2 个文件被更改,包括 91 次插入59 次删除
  1. 1 0
      TODO
  2. 90 59
      src/entt/entity/pool.hpp

+ 1 - 0
TODO

@@ -9,6 +9,7 @@
 * update documentation for meta, it contains less than half of the actual feature
 
 WIP:
+* HP: write documentation for custom storages and views!!
 * factory invoke: add support for external member functions as static meta functions
 * pagination doesn't work nicely across boundaries probably, give it a look. RO operations are fine, adding components maybe not.
 * make it easier to hook into the type system and describe how to do that to eg auto-generate meta types on first use

+ 90 - 59
src/entt/entity/pool.hpp

@@ -21,7 +21,7 @@ namespace entt {
  * @tparam Type Type of objects assigned to the entities.
  */
 template<typename Entity, typename Type>
-struct default_pool final: basic_storage<Entity, Type> {
+struct storage_adapter: basic_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. */
@@ -29,6 +29,79 @@ struct default_pool final: basic_storage<Entity, Type> {
     /*! @brief Underlying entity identifier. */
     using entity_type = Entity;
 
+    /**
+     * @brief Assigns entities to a 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(basic_registry<entity_type> &, const entity_type entity, Args &&... args) {
+        return basic_storage<entity_type, Type>::emplace(entity, std::forward<Args>(args)...);
+    }
+
+    /**
+     * @brief Assigns entities to a pool.
+     * @tparam It Type of input iterator.
+     * @tparam Args Types of arguments to use to construct the objects
+     * associated with the entities.
+     * @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 args Parameters to use to initialize the objects associated with
+     * the entities.
+     */
+    template<typename It, typename... Args>
+    void insert(basic_registry<entity_type> &, It first, It last, Args &&... args) {
+        basic_storage<entity_type, value_type>::insert(first, last, std::forward<Args>(args)...);
+    }
+
+    /**
+     * @brief Removes entities from a pool.
+     * @param entity A valid entity identifier.
+     */
+    void erase(basic_registry<entity_type> &, const entity_type entity) {
+        basic_storage<entity_type, value_type>::erase(entity);
+    }
+
+    /**
+     * @copybrief erase
+     * @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(basic_registry<entity_type> &, It first, It last) {
+        basic_sparse_set<entity_type>::erase(first, last);
+    }
+
+    /**
+     * @brief Patches the given instance for an entity.
+     * @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(basic_registry<entity_type> &, const entity_type entity, [[maybe_unused]] Func &&... func) {
+        auto &instance = this->get(entity);
+        (std::forward<Func>(func)(instance), ...);
+        return instance;
+    }
+};
+
+
+/**
+ * @brief Mixin type to use to add signal support to pools.
+ * @tparam Pool The type of the underlying pool.
+ */
+template<typename Pool>
+struct sigh_pool_mixin: Pool {
+    /*! @brief Underlying value type. */
+    using value_type = typename Pool::value_type;
+    /*! @brief Underlying entity identifier. */
+    using entity_type = typename Pool::entity_type;
+
     /**
      * @brief Returns a sink object.
      *
@@ -37,7 +110,7 @@ struct default_pool final: basic_storage<Entity, Type> {
      * The function type for a listener is equivalent to:
      *
      * @code{.cpp}
-     * void(basic_registry<Entity> &, Entity);
+     * void(basic_registry<entity_type> &, entity_type);
      * @endcode
      *
      * Listeners are invoked **after** the object has been assigned to the
@@ -52,14 +125,14 @@ struct default_pool final: basic_storage<Entity, Type> {
     }
 
     /**
-     * @brief Returns a sink object for the given type.
+     * @brief Returns a sink object.
      *
      * 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(basic_registry<Entity> &, Entity);
+     * void(basic_registry<entity_type> &, entity_type);
      * @endcode
      *
      * Listeners are invoked **after** the object has been updated.
@@ -73,14 +146,14 @@ struct default_pool final: basic_storage<Entity, Type> {
     }
 
     /**
-     * @brief Returns a sink object for the given type.
+     * @brief Returns a sink object.
      *
      * 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(basic_registry<Entity> &, Entity);
+     * void(basic_registry<entity_type> &, entity_type);
      * @endcode
      *
      * Listeners are invoked **before** the object has been removed from the
@@ -95,18 +168,7 @@ struct default_pool final: basic_storage<Entity, Type> {
     }
 
     /**
-     * @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.
-     *
+     * @copybrief storage_adapter::emplace
      * @tparam Args Types of arguments to use to construct the object.
      * @param owner The registry that issued the request.
      * @param entity A valid entity identifier.
@@ -115,7 +177,7 @@ struct default_pool final: basic_storage<Entity, Type> {
      */
     template<typename... Args>
     decltype(auto) emplace(basic_registry<entity_type> &owner, const entity_type entity, Args &&... args) {
-        basic_storage<entity_type, Type>::emplace(entity, std::forward<Args>(args)...);
+        Pool::emplace(owner, entity, std::forward<Args>(args)...);
         construction.publish(owner, entity);
 
         if constexpr(!is_eto_eligible_v<value_type>) {
@@ -124,10 +186,7 @@ struct default_pool final: basic_storage<Entity, Type> {
     }
 
     /**
-     * @brief Assigns multiple entities to a pool.
-     *
-     * @sa emplace
-     *
+     * @copybrief storage_adapter::insert
      * @tparam It Type of input iterator.
      * @tparam Args Types of arguments to use to construct the objects
      * associated with the entities.
@@ -139,7 +198,7 @@ struct default_pool final: basic_storage<Entity, Type> {
      */
     template<typename It, typename... Args>
     void insert(basic_registry<entity_type> &owner, It first, It last, Args &&... args) {
-        basic_storage<entity_type, value_type>::insert(first, last, std::forward<Args>(args)...);
+        Pool::insert(owner, first, last, std::forward<Args>(args)...);
 
         if(!construction.empty()) {
             for(; first != last; ++first) {
@@ -149,27 +208,17 @@ struct default_pool final: basic_storage<Entity, Type> {
     }
 
     /**
-     * @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.
-     *
+     * @copybrief storage_adapter::erase
      * @param owner The registry that issued the request.
      * @param entity A valid entity identifier.
      */
     void erase(basic_registry<entity_type> &owner, const entity_type entity) {
         destruction.publish(owner, entity);
-        basic_storage<entity_type, value_type>::erase(entity);
+        Pool::erase(owner, entity);
     }
 
     /**
-     * @brief Removes multiple entities from a pool.
-     *
-     * @see erase
-     *
+     * @copybrief storage_adapter::erase
      * @tparam It Type of input iterator.
      * @param owner The registry that issued the request.
      * @param first An iterator to the first element of the range of entities.
@@ -183,29 +232,11 @@ struct default_pool final: basic_storage<Entity, Type> {
             }
         }
 
-        basic_sparse_set<entity_type>::erase(first, last);
+        Pool::erase(owner, first, last);
     }
 
     /**
-     * @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.
-     *
+     * @copybrief storage_adapter::patch
      * @tparam Func Types of the function objects to invoke.
      * @param owner The registry that issued the request.
      * @param entity A valid entity identifier.
@@ -217,7 +248,7 @@ struct default_pool final: basic_storage<Entity, Type> {
         if constexpr(is_eto_eligible_v<value_type>) {
             update.publish(owner, entity);
         } else {
-            (std::forward<Func>(func)(this->get(entity)), ...);
+            Pool::patch(owner, entity, std::forward<Func>(func)...);
             update.publish(owner, entity);
             return this->get(entity);
         }
@@ -247,7 +278,7 @@ private:
 template<typename Entity, typename Type, typename = void>
 struct pool {
     /*! @brief Resulting type after component-to-pool conversion. */
-    using type = default_pool<Entity, Type>;
+    using type = sigh_pool_mixin<storage_adapter<Entity, Type>>;
 };