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

This commit is contained in:
Michele Caini
2020-01-31 22:43:25 +01:00
parent 8b66316180
commit ad0dab2493
2 changed files with 95 additions and 55 deletions

View File

@@ -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{};

View File

@@ -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);
}