Procházet zdrojové kódy

registry: internal rework (close #564 among the other things)

Michele Caini před 5 roky
rodič
revize
49f65d6762
1 změnil soubory, kde provedl 28 přidání a 18 odebrání
  1. 28 18
      src/entt/entity/registry.hpp

+ 28 - 18
src/entt/entity/registry.hpp

@@ -45,7 +45,7 @@ class basic_registry {
     struct pool_data {
         type_info info{};
         std::unique_ptr<sparse_set<Entity>> pool{};
-        void(* erase)(sparse_set<Entity> &, basic_registry &, const Entity);
+        void(* erase)(sparse_set<Entity> &, basic_registry &, const Entity *, const Entity *);
     };
 
     template<typename...>
@@ -114,8 +114,8 @@ class basic_registry {
         if(auto &&pdata = pools[index]; !pdata.pool) {
             pdata.info = type_id<Component>();
             pdata.pool.reset(new pool_t<Entity, Component>());
-            pdata.erase = +[](sparse_set<Entity> &cpool, basic_registry &owner, const Entity entt) {
-                static_cast<pool_t<Entity, Component> &>(cpool).erase(owner, entt);
+            pdata.erase = +[](sparse_set<Entity> &cpool, basic_registry &owner, const Entity *first, const Entity *last) {
+                static_cast<pool_t<Entity, Component> &>(cpool).erase(owner, first, last);
             };
         }
         
@@ -141,6 +141,12 @@ class basic_registry {
         return entities[curr] = entity_type{curr | version};
     }
 
+    void release_entity(const Entity entity, const typename traits_type::version_type version) {
+        const auto entt = to_integral(entity) & traits_type::entity_mask;
+        entities[entt] = entity_type{to_integral(destroyed) | (typename traits_type::entity_type{version} << traits_type::entity_shift)};
+        destroyed = entity_type{entt};
+    }
+
 public:
     /*! @brief Underlying entity identifier. */
     using entity_type = Entity;
@@ -378,7 +384,7 @@ public:
     [[nodiscard]] version_type current(const entity_type entity) const {
         const auto pos = size_type(to_integral(entity) & traits_type::entity_mask);
         ENTT_ASSERT(pos < entities.size());
-        return version_type(to_integral(entities[pos]) >> traits_type::entity_shift);
+        return version(entities[pos]);
     }
 
     /**
@@ -411,11 +417,10 @@ public:
         entity_type entt;
 
         if(const auto req = (to_integral(hint) & traits_type::entity_mask); !(req < entities.size())) {
-            entities.reserve(req + 1);
+            entities.reserve(req + 1u);
 
             for(auto pos = entities.size(); pos < req; ++pos) {
-                entities.emplace_back(destroyed);
-                destroyed = entity_type{static_cast<typename traits_type::entity_type>(pos)};
+                release_entity(generate_identifier(), {});
             }
 
             entt = entities.emplace_back(hint);
@@ -474,9 +479,7 @@ public:
 
         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{static_cast<typename traits_type::entity_type>(pos)};
+                release_entity(entity_type{static_cast<typename traits_type::entity_type>(pos)}, version(entities[pos]));
             }
         }
     }
@@ -492,7 +495,7 @@ public:
      * @param entity A valid entity identifier.
      */
     void destroy(const entity_type entity) {
-        destroy(entity, version_type((to_integral(entity) >> traits_type::entity_shift) + 1));
+        destroy(entity, version(entity) + 1u);
     }
 
     /**
@@ -508,10 +511,7 @@ public:
      */
     void destroy(const entity_type entity, const version_type version) {
         remove_all(entity);
-        // lengthens the implicit list of destroyed entities
-        const auto entt = to_integral(entity) & traits_type::entity_mask;
-        entities[entt] = entity_type{to_integral(destroyed) | (typename traits_type::entity_type{version} << traits_type::entity_shift)};
-        destroyed = entity_type{entt};
+        release_entity(entity, version);
     }
 
     /**
@@ -765,10 +765,11 @@ public:
      */
     void remove_all(const entity_type entity) {
         ENTT_ASSERT(valid(entity));
+        entity_type wrap[1]{entity};
 
         for(auto pos = pools.size(); pos; --pos) {
             if(auto &pdata = pools[pos-1]; pdata.pool && pdata.pool->contains(entity)) {
-                pdata.erase(*pdata.pool, *this, entity);
+                pdata.erase(*pdata.pool, *this, std::begin(wrap), std::end(wrap));
             }
         }
     }
@@ -920,8 +921,17 @@ public:
     template<typename... Component>
     void clear() {
         if constexpr(sizeof...(Component) == 0) {
-            // useless this-> used to suppress a warning with clang
-            each([this](const auto entity) { this->destroy(entity); });
+            for(auto pos = pools.size(); pos; --pos) {
+                if(const auto &pdata = pools[pos-1]; pdata.pool) {
+                    pdata.erase(*pdata.pool, *this, pdata.pool->rbegin(), pdata.pool->rend());
+                }
+            }
+
+            for(auto pos = entities.size(); pos; --pos) {
+                if(const auto entt = entities[pos - 1]; (to_integral(entt) & traits_type::entity_mask) == (pos - 1)) {
+                    release_entity(entt, version(entt) + 1u);
+                }
+            }
         } else {
             ([this](auto &&cpool) {
                 cpool.erase(*this, cpool.sparse_set<entity_type>::begin(), cpool.sparse_set<entity_type>::end());