Browse Source

registry: use only sequential indexes for component types now

Michele Caini 6 years ago
parent
commit
8a78b0dbd6
2 changed files with 45 additions and 39 deletions
  1. 20 20
      src/entt/entity/registry.hpp
  2. 25 19
      test/entt/entity/registry.cpp

+ 20 - 20
src/entt/entity/registry.hpp

@@ -187,20 +187,18 @@ class basic_registry {
     template<typename Component>
     const pool_handler<Component> & assure() const {
         static_assert(std::is_same_v<Component, std::decay_t<Component>>);
-        static std::size_t index{pools.size()};
-
-        if(const auto length = pools.size(); !(index < length) || pools[index].type_id != type_info<Component>::id()) {
-            for(index = {}; index < length && pools[index].type_id != type_info<Component>::id(); ++index);
-
-            if(index == length) {
-                pools.push_back(pool_data{
-                    type_info<Component>::id(),
-                    std::unique_ptr<sparse_set<entity_type>>{new pool_handler<Component>()},
-                    [](sparse_set<entity_type> &cpool, basic_registry &owner, const entity_type entt) {
-                        static_cast<pool_handler<Component> &>(cpool).remove(owner, entt);
-                    }
-                });
-            }
+        const auto index = type_index<Component>::value();
+
+        if(!(index < pools.size())) {
+            pools.resize(index+1);
+        }
+
+        if(auto &&cpool = pools[index]; !cpool.pool) {
+            cpool.type_id = type_info<Component>::id();
+            cpool.pool.reset(new pool_handler<Component>());
+            cpool.remove = [](sparse_set<entity_type> &cpool, basic_registry &owner, const entity_type entt) {
+                static_cast<pool_handler<Component> &>(cpool).remove(owner, entt);
+            };
         }
 
         return static_cast<pool_handler<Component> &>(*pools[index].pool);
@@ -545,7 +543,7 @@ public:
      */
     template<typename It>
     void assign(It first, It last) {
-        ENTT_ASSERT(std::all_of(pools.cbegin(), pools.cend(), [](auto &&cpool) { return cpool.pool->empty(); }));
+        ENTT_ASSERT(std::all_of(pools.cbegin(), pools.cend(), [](auto &&pdata) { return !pdata.pool || pdata.pool->empty(); }));
         entities.assign(first, last);
         destroyed = null;
 
@@ -582,7 +580,7 @@ public:
         ENTT_ASSERT(valid(entity));
 
         for(auto pos = pools.size(); pos; --pos) {
-            if(auto &pdata = pools[pos-1]; pdata.pool->has(entity)) {
+            if(auto &pdata = pools[pos-1]; pdata.pool && pdata.pool->has(entity)) {
                 pdata.remove(*pdata.pool, *this, entity);
             }
         }
@@ -1072,7 +1070,7 @@ public:
      */
     bool orphan(const entity_type entity) const {
         ENTT_ASSERT(valid(entity));
-        return std::none_of(pools.cbegin(), pools.cend(), [entity](auto &&pdata) { return pdata.pool->has(entity); });
+        return std::none_of(pools.cbegin(), pools.cend(), [entity](auto &&pdata) { return pdata.pool && pdata.pool->has(entity); });
     }
 
     /**
@@ -1523,7 +1521,7 @@ public:
         std::vector<const sparse_set<Entity> *> selected(std::distance(first, last));
 
         std::transform(first, last, selected.begin(), [this](const auto ctype) {
-            const auto it = std::find_if(pools.cbegin(), pools.cend(), [ctype](auto &&pdata) { return pdata.type_id == ctype; });
+            const auto it = std::find_if(pools.cbegin(), pools.cend(), [ctype](auto &&pdata) { return pdata.pool && pdata.type_id == ctype; });
             return it == pools.cend() ? nullptr : it->pool.get();
         });
 
@@ -1624,7 +1622,7 @@ public:
     template<typename Func>
     void visit(entity_type entity, Func func) const {
         for(auto pos = pools.size(); pos; --pos) {
-            if(auto &pdata = pools[pos-1]; pdata.pool->has(entity)) {
+            if(const auto &pdata = pools[pos-1]; pdata.pool && pdata.pool->has(entity)) {
                 func(pdata.type_id);
             }
         }
@@ -1653,7 +1651,9 @@ public:
     template<typename Func>
     void visit(Func func) const {
         for(auto pos = pools.size(); pos; --pos) {
-            func(pools[pos-1].type_id);
+            if(const auto &pdata = pools[pos-1]; pdata.pool) {
+                func(pdata.type_id);
+            }
         }
     }
 

+ 25 - 19
test/entt/entity/registry.cpp

@@ -1424,29 +1424,35 @@ TEST(Registry, Visit) {
     registry.assign<double>(other);
     registry.assign<char>(entity);
 
-    auto total = 0;
-    auto esize = 0;
-    auto osize = 0;
-
-    registry.visit([&total](const auto component) {
-        ASSERT_TRUE(total != 0 || component == entt::type_info<char>::id());
-        ASSERT_TRUE(total != 1 || component == entt::type_info<double>::id());
-        ASSERT_TRUE(total != 2 || component == entt::type_info<int>::id());
-        ++total;
+    bool hasType[3]{};
+
+    registry.visit([&hasType](const auto component) {
+        hasType[0] = hasType[0] || (component == entt::type_info<int>::id());
+        hasType[1] = hasType[1] || (component == entt::type_info<double>::id());
+        hasType[2] = hasType[2] || (component == entt::type_info<char>::id());
     });
 
-    registry.visit(entity, [&esize](const auto component) {
-        ASSERT_TRUE(esize != 0 || component == entt::type_info<char>::id());
-        ASSERT_TRUE(esize != 1 || component == entt::type_info<int>::id());
-        ++esize;
+    ASSERT_TRUE(hasType[0] && hasType[1] && hasType[2]);
+
+    hasType[0] = hasType[1] = hasType[2] = false;
+
+    registry.visit(entity, [&hasType](const auto component) {
+        hasType[0] = hasType[0] || (component == entt::type_info<int>::id());
+        hasType[1] = hasType[1] || (component == entt::type_info<double>::id());
+        hasType[2] = hasType[2] || (component == entt::type_info<char>::id());
     });
 
-    registry.visit(other, [&osize](const auto component) {
-        ASSERT_TRUE(osize != 0 || component == entt::type_info<double>::id());
-        ++osize;
+    ASSERT_TRUE(hasType[0] && !hasType[1] && hasType[2]);
+
+    hasType[0] = hasType[2] = false;
+
+    registry.visit(other, [&hasType](const auto component) {
+        hasType[0] = hasType[0] || (component == entt::type_info<int>::id());
+        hasType[1] = hasType[1] || (component == entt::type_info<double>::id());
+        hasType[2] = hasType[2] || (component == entt::type_info<char>::id());
     });
 
-    ASSERT_EQ(total, 3);
-    ASSERT_EQ(esize, 2);
-    ASSERT_EQ(osize, 1);
+    ASSERT_TRUE(!hasType[0] && hasType[1] && !hasType[2]);
+
+    hasType[1] = false;
 }