소스 검색

registry: added ::visit to get all components in a registry of owned by an entity

Michele Caini 6 년 전
부모
커밋
ad0dab2493
2개의 변경된 파일95개의 추가작업 그리고 55개의 파일을 삭제
  1. 57 1
      src/entt/entity/registry.hpp
  2. 38 54
      test/entt/entity/registry.cpp

+ 57 - 1
src/entt/entity/registry.hpp

@@ -938,7 +938,6 @@ public:
     }
 
     /**
-
      * @brief Clears a whole registry or the pools for the given components.
      * @tparam Component Types of components to remove from their entities.
      */
@@ -1713,6 +1712,63 @@ public:
         return const_cast<Type &>(std::as_const(*this).template ctx<Type>());
     }
 
+    /**
+     * @brief Visits an entity and returns the types for its components.
+     *
+     * The signature of the function should be equivalent to the following:
+     *
+     * @code{.cpp}
+     * void(const ENTT_ID_TYPE);
+     * @endcode
+     *
+     * Returned identifiers are those of the components owned by the entity.
+     *
+     * @sa type_info
+     *
+     * @warning
+     * It's not specified whether a component attached to or removed from the
+     * given entity during the visit is returned or not to the caller.
+     *
+     * @tparam Func Type of the function object to invoke.
+     * @param entity A valid entity identifier.
+     * @param func A valid function object.
+     */
+    template<typename Func>
+    void visit(entity_type entity, Func func) {
+        for(auto pos = pools.size(); pos; --pos) {
+            if(auto &pdata = pools[pos-1]; pdata.pool->has(entity)) {
+                func(pdata.type_id);
+            }
+        }
+    }
+
+    /**
+     * @brief Visits a registry and returns the types for its components.
+     *
+     * The signature of the function should be equivalent to the following:
+     *
+     * @code{.cpp}
+     * void(const ENTT_ID_TYPE);
+     * @endcode
+     *
+     * Returned identifiers are those of the components managed by the registry.
+     *
+     * @sa type_info
+     *
+     * @warning
+     * It's not specified whether a component for which a pool is created during
+     * the visit is returned or not to the caller.
+     *
+     * @tparam Func Type of the function object to invoke.
+     * @param func A valid function object.
+     */
+    template<typename Func>
+    void visit(Func func) {
+        for(auto pos = pools.size(); pos; --pos) {
+            func(pools[pos-1].type_id);
+        }
+    }
+
 private:
     std::vector<group_data> groups{};
     mutable std::vector<pool_data> pools{};

+ 38 - 54
test/entt/entity/registry.cpp

@@ -1,4 +1,3 @@
-#include <unordered_map>
 #include <unordered_set>
 #include <functional>
 #include <iterator>
@@ -957,59 +956,6 @@ TEST(Registry, ConstructWithComponents) {
     registry.assign<int>(registry.create(), value);
 }
 
-TEST(Registry, MergeTwoRegistries) {
-    entt::registry src;
-    entt::registry dst;
-
-    std::unordered_map<entt::entity, entt::entity> ref;
-
-    auto merge = [&ref, &dst](const auto &view) {
-        view.each([&](auto entity, const auto &component) {
-            if(ref.find(entity) == ref.cend()) {
-                const auto other = dst.create();
-                dst.template assign<std::decay_t<decltype(component)>>(other, component);
-                ref.emplace(entity, other);
-            } else {
-                using component_type = std::decay_t<decltype(component)>;
-                dst.template assign<component_type>(ref[entity], component);
-            }
-        });
-    };
-
-    auto e0 = src.create();
-    src.assign<int>(e0);
-    src.assign<float>(e0);
-    src.assign<double>(e0);
-
-    auto e1 = src.create();
-    src.assign<char>(e1);
-    src.assign<float>(e1);
-    src.assign<int>(e1);
-
-    auto e2 = dst.create();
-    dst.assign<int>(e2);
-    dst.assign<char>(e2);
-    dst.assign<double>(e2);
-
-    auto e3 = dst.create();
-    dst.assign<float>(e3);
-    dst.assign<int>(e3);
-
-    auto eq = [](auto begin, auto end) { ASSERT_EQ(begin, end); };
-    auto ne = [](auto begin, auto end) { ASSERT_NE(begin, end); };
-
-    eq(dst.view<int, float, double>().begin(), dst.view<int, float, double>().end());
-    eq(dst.view<char, float, int>().begin(), dst.view<char, float, int>().end());
-
-    merge(src.view<int>());
-    merge(src.view<char>());
-    merge(src.view<double>());
-    merge(src.view<float>());
-
-    ne(dst.view<int, float, double>().begin(), dst.view<int, float, double>().end());
-    ne(dst.view<char, float, int>().begin(), dst.view<char, float, int>().end());
-}
-
 TEST(Registry, Signals) {
     entt::registry registry;
     listener listener;
@@ -1604,3 +1550,41 @@ TEST(Registry, AssignEntities) {
     ASSERT_EQ(registry.create(), other.create());
     ASSERT_EQ(other.entity(other.create()), entities[1]);
 }
+
+TEST(Registry, Visit) {
+    entt::registry registry;
+    const auto entity = registry.create();
+    const auto other = registry.create();
+
+    registry.assign<int>(entity);
+    registry.assign<double>(other);
+    registry.assign<char>(entity);
+
+    bool has[3]{};
+
+    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;
+    });
+
+    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;
+    });
+
+    registry.visit(other, [&osize](const auto component) {
+        ASSERT_TRUE(osize != 0 || component == entt::type_info<double>::id());
+        ++osize;
+    });
+
+    ASSERT_EQ(total, 3);
+    ASSERT_EQ(esize, 2);
+    ASSERT_EQ(osize, 1);
+}