diff --git a/src/entt/entity/registry.hpp b/src/entt/entity/registry.hpp index c2d588c6a..10e659e5f 100644 --- a/src/entt/entity/registry.hpp +++ b/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(std::as_const(*this).template ctx()); } + /** + * @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 + 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 + void visit(Func func) { + for(auto pos = pools.size(); pos; --pos) { + func(pools[pos-1].type_id); + } + } + private: std::vector groups{}; mutable std::vector pools{}; diff --git a/test/entt/entity/registry.cpp b/test/entt/entity/registry.cpp index fd6eba557..79c7b6cd5 100644 --- a/test/entt/entity/registry.cpp +++ b/test/entt/entity/registry.cpp @@ -1,4 +1,3 @@ -#include #include #include #include @@ -957,59 +956,6 @@ TEST(Registry, ConstructWithComponents) { registry.assign(registry.create(), value); } -TEST(Registry, MergeTwoRegistries) { - entt::registry src; - entt::registry dst; - - std::unordered_map 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>(other, component); - ref.emplace(entity, other); - } else { - using component_type = std::decay_t; - dst.template assign(ref[entity], component); - } - }); - }; - - auto e0 = src.create(); - src.assign(e0); - src.assign(e0); - src.assign(e0); - - auto e1 = src.create(); - src.assign(e1); - src.assign(e1); - src.assign(e1); - - auto e2 = dst.create(); - dst.assign(e2); - dst.assign(e2); - dst.assign(e2); - - auto e3 = dst.create(); - dst.assign(e3); - dst.assign(e3); - - auto eq = [](auto begin, auto end) { ASSERT_EQ(begin, end); }; - auto ne = [](auto begin, auto end) { ASSERT_NE(begin, end); }; - - eq(dst.view().begin(), dst.view().end()); - eq(dst.view().begin(), dst.view().end()); - - merge(src.view()); - merge(src.view()); - merge(src.view()); - merge(src.view()); - - ne(dst.view().begin(), dst.view().end()); - ne(dst.view().begin(), dst.view().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(entity); + registry.assign(other); + registry.assign(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::id()); + ASSERT_TRUE(total != 1 || component == entt::type_info::id()); + ASSERT_TRUE(total != 2 || component == entt::type_info::id()); + ++total; + }); + + registry.visit(entity, [&esize](const auto component) { + ASSERT_TRUE(esize != 0 || component == entt::type_info::id()); + ASSERT_TRUE(esize != 1 || component == entt::type_info::id()); + ++esize; + }); + + registry.visit(other, [&osize](const auto component) { + ASSERT_TRUE(osize != 0 || component == entt::type_info::id()); + ++osize; + }); + + ASSERT_EQ(total, 3); + ASSERT_EQ(esize, 2); + ASSERT_EQ(osize, 1); +}