registry: removed pdata container, pools are standalone objects and thus ready to go public
This commit is contained in:
5
TODO
5
TODO
@@ -4,7 +4,6 @@
|
||||
* add examples (and credits) from @alanjfs :)
|
||||
|
||||
WIP:
|
||||
* remove the const_cast within registry::assure (view<const E, ...> vs view<E, ...>, thread safe const registry)
|
||||
* fast-contains for sparse sets (low prio but nice-to-have)
|
||||
* runtime components (registry), runtime events (dispatcher/emitter), runtime context variables ...
|
||||
* runtime_view/registry, remove reference to basic_sparse_set<E>
|
||||
@@ -14,11 +13,9 @@ WIP:
|
||||
|
||||
WIP:
|
||||
* customizable any_vtable, sfinae-friendly definition and op::custom for user-def
|
||||
* registry: fake vtable (mixin injected) to get rid of poly storage, use pointer to sparse set only for pools, discard pool_data type.
|
||||
* resource, forward the id to the loader from the cache and if constexpr the call to load, update doc and describe customization points
|
||||
* make it possible to create views of the type `view<T, T>`, add get by index and such, allow to register custom pools by name with the registry
|
||||
* allow to register custom pools by name with the registry
|
||||
* add user data to type_info
|
||||
* make const registry::view thread safe, switch to a view<T...>{registry} model (long term goal)
|
||||
* headless (sparse set only) view
|
||||
* write documentation for custom storages and views!!
|
||||
* make runtime views use opaque storage and therefore return also elements.
|
||||
|
||||
@@ -265,7 +265,7 @@ struct basic_handle {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Visits a handle and returns the types for its components.
|
||||
* @brief Visits a handle and returns the pools for its components.
|
||||
* @sa basic_registry::visit
|
||||
* @tparam Func Type of the function object to invoke.
|
||||
* @param func A valid function object.
|
||||
|
||||
@@ -47,11 +47,6 @@ class basic_registry {
|
||||
template<typename Component>
|
||||
using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Component>>::storage_type, Component>;
|
||||
|
||||
struct pool_data {
|
||||
std::unique_ptr<basic_common_type> pool{};
|
||||
const entt::type_info *info{};
|
||||
};
|
||||
|
||||
template<typename...>
|
||||
struct group_handler;
|
||||
|
||||
@@ -104,15 +99,14 @@ class basic_registry {
|
||||
template<typename Component>
|
||||
[[nodiscard]] storage_type<Component> &assure() {
|
||||
static_assert(std::is_same_v<Component, std::decay_t<Component>>, "Non-decayed types not allowed");
|
||||
auto &&pdata = pools[type_id<Component>().hash()];
|
||||
auto &&cpool = pools[type_id<Component>().hash()];
|
||||
|
||||
if(!pdata.pool) {
|
||||
pdata.pool.reset(new storage_type<Component>{});
|
||||
pdata.pool->bind(forward_as_any(*this));
|
||||
pdata.info = &type_id<Component>();
|
||||
if(!cpool) {
|
||||
cpool.reset(new storage_type<Component>{});
|
||||
cpool->bind(forward_as_any(*this));
|
||||
}
|
||||
|
||||
return static_cast<storage_type<Component> &>(*pdata.pool);
|
||||
return static_cast<storage_type<Component> &>(*cpool);
|
||||
}
|
||||
|
||||
template<typename Component>
|
||||
@@ -120,7 +114,7 @@ class basic_registry {
|
||||
static_assert(std::is_same_v<Component, std::decay_t<Component>>, "Non-decayed types not allowed");
|
||||
|
||||
if(const auto it = pools.find(type_id<Component>().hash()); it != pools.cend()) {
|
||||
return static_cast<storage_type<Component> &>(*it->second.pool);
|
||||
return static_cast<storage_type<Component> &>(*it->second);
|
||||
}
|
||||
|
||||
static storage_type<Component> placeholder{};
|
||||
@@ -167,8 +161,8 @@ public:
|
||||
groups{std::move(other.groups)},
|
||||
entities{std::move(other.entities)},
|
||||
free_list{other.free_list} {
|
||||
for(auto &&pdata: pools) {
|
||||
pdata.second.pool->bind(forward_as_any(*this));
|
||||
for(auto &&curr: pools) {
|
||||
curr.second->bind(forward_as_any(*this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,8 +178,8 @@ public:
|
||||
entities = std::move(other.entities);
|
||||
free_list = other.free_list;
|
||||
|
||||
for(auto &&pdata: pools) {
|
||||
pdata.second.pool->bind(forward_as_any(*this));
|
||||
for(auto &&curr: pools) {
|
||||
curr.second->bind(forward_as_any(*this));
|
||||
}
|
||||
|
||||
return *this;
|
||||
@@ -529,7 +523,7 @@ public:
|
||||
ENTT_ASSERT(valid(entity), "Invalid entity");
|
||||
|
||||
for(auto &&curr: pools) {
|
||||
curr.second.pool->remove(entity);
|
||||
curr.second->remove(entity);
|
||||
}
|
||||
|
||||
return release_entity(entity, version);
|
||||
@@ -552,7 +546,7 @@ public:
|
||||
}
|
||||
} else {
|
||||
for(auto &&curr: pools) {
|
||||
curr.second.pool->remove(first, last);
|
||||
curr.second->remove(first, last);
|
||||
}
|
||||
|
||||
release(first, last);
|
||||
@@ -783,7 +777,7 @@ public:
|
||||
void compact() {
|
||||
if constexpr(sizeof...(Component) == 0) {
|
||||
for(auto &&curr: pools) {
|
||||
curr.second.pool->compact();
|
||||
curr.second->compact();
|
||||
}
|
||||
} else {
|
||||
(assure<Component>().compact(), ...);
|
||||
@@ -920,7 +914,7 @@ public:
|
||||
void clear() {
|
||||
if constexpr(sizeof...(Component) == 0) {
|
||||
for(auto &&curr: pools) {
|
||||
curr.second.pool->clear();
|
||||
curr.second->clear();
|
||||
}
|
||||
|
||||
each([this](const auto entity) { release_entity(entity, entity_traits::to_version(entity) + 1u); });
|
||||
@@ -968,7 +962,7 @@ public:
|
||||
*/
|
||||
[[nodiscard]] bool orphan(const entity_type entity) const {
|
||||
ENTT_ASSERT(valid(entity), "Invalid entity");
|
||||
return std::none_of(pools.cbegin(), pools.cend(), [entity](auto &&curr) { return curr.second.pool->contains(entity); });
|
||||
return std::none_of(pools.cbegin(), pools.cend(), [entity](auto &&curr) { return curr.second->contains(entity); });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1152,12 +1146,12 @@ public:
|
||||
|
||||
for(; first != last; ++first) {
|
||||
const auto it = pools.find(*first);
|
||||
component.emplace_back(it == pools.cend() ? nullptr : it->second.pool.get());
|
||||
component.emplace_back(it == pools.cend() ? nullptr : it->second.get());
|
||||
}
|
||||
|
||||
for(; from != to; ++from) {
|
||||
const auto it = pools.find(*from);
|
||||
filter.emplace_back(it == pools.cend() ? nullptr : it->second.pool.get());
|
||||
filter.emplace_back(it == pools.cend() ? nullptr : it->second.get());
|
||||
}
|
||||
|
||||
return {std::move(component), std::move(filter)};
|
||||
@@ -1408,17 +1402,15 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Visits an entity and returns the type info for its components.
|
||||
* @brief Visits an entity and returns the pools for its components.
|
||||
*
|
||||
* The signature of the function should be equivalent to the following:
|
||||
*
|
||||
* @code{.cpp}
|
||||
* void(const type_info &);
|
||||
* void(const basic_sparse_set<entity_type> &);
|
||||
* @endcode
|
||||
*
|
||||
* Returned identifiers are those of the components owned by the entity.
|
||||
*
|
||||
* @sa type_info
|
||||
* Returned pools are those of the components owned by the entity.
|
||||
*
|
||||
* @tparam Func Type of the function object to invoke.
|
||||
* @param entity A valid identifier.
|
||||
@@ -1427,24 +1419,22 @@ public:
|
||||
template<typename Func>
|
||||
void visit(entity_type entity, Func func) const {
|
||||
for(auto &&curr: pools) {
|
||||
if(curr.second.pool->contains(entity)) {
|
||||
func(*curr.second.info);
|
||||
if(curr.second->contains(entity)) {
|
||||
func(*curr.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Visits a registry and returns the type info for its components.
|
||||
* @brief Visits a registry and returns the pools for its components.
|
||||
*
|
||||
* The signature of the function should be equivalent to the following:
|
||||
*
|
||||
* @code{.cpp}
|
||||
* void(const type_info &);
|
||||
* void(const basic_sparse_set<entity_type> &);
|
||||
* @endcode
|
||||
*
|
||||
* Returned identifiers are those of the components managed by the registry.
|
||||
*
|
||||
* @sa type_info
|
||||
* Returned pools are those of the components managed by the registry.
|
||||
*
|
||||
* @tparam Func Type of the function object to invoke.
|
||||
* @param func A valid function object.
|
||||
@@ -1452,7 +1442,7 @@ public:
|
||||
template<typename Func>
|
||||
void visit(Func func) const {
|
||||
for(auto &&curr: pools) {
|
||||
func(*curr.second.info);
|
||||
func(*curr.second);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1573,7 +1563,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
dense_hash_map<id_type, pool_data, identity> pools{};
|
||||
dense_hash_map<id_type, std::unique_ptr<basic_common_type>, identity> pools{};
|
||||
dense_hash_map<id_type, basic_any<0u>, identity> vars{};
|
||||
std::vector<group_data> groups{};
|
||||
std::vector<entity_type> entities{};
|
||||
|
||||
@@ -168,7 +168,7 @@ TEST(BasicHandle, Component) {
|
||||
ASSERT_TRUE((registry.empty<char, double>()));
|
||||
ASSERT_EQ(0u, (handle.remove<char, double>()));
|
||||
|
||||
handle.visit([](const auto &info) { ASSERT_EQ(entt::type_id<int>(), info); });
|
||||
handle.visit([](const auto &pool) { ASSERT_EQ(entt::type_id<int>(), pool.type()); });
|
||||
|
||||
ASSERT_TRUE((handle.any_of<int, char, double>()));
|
||||
ASSERT_FALSE((handle.all_of<int, char, double>()));
|
||||
|
||||
@@ -1886,30 +1886,30 @@ TEST(Registry, Visit) {
|
||||
|
||||
bool hasType[3]{};
|
||||
|
||||
registry.visit([&hasType](const auto &info) {
|
||||
hasType[0] = hasType[0] || (info.hash() == entt::type_hash<int>::value());
|
||||
hasType[1] = hasType[1] || (info.hash() == entt::type_hash<double>::value());
|
||||
hasType[2] = hasType[2] || (info.hash() == entt::type_hash<char>::value());
|
||||
registry.visit([&hasType](const auto &pool) {
|
||||
hasType[0] = hasType[0] || (pool.type() == entt::type_id<int>());
|
||||
hasType[1] = hasType[1] || (pool.type() == entt::type_id<double>());
|
||||
hasType[2] = hasType[2] || (pool.type() == entt::type_id<char>());
|
||||
});
|
||||
|
||||
ASSERT_TRUE(hasType[0] && hasType[1] && hasType[2]);
|
||||
|
||||
hasType[0] = hasType[1] = hasType[2] = false;
|
||||
|
||||
registry.visit(entity, [&hasType](const auto &info) {
|
||||
hasType[0] = hasType[0] || (info.hash() == entt::type_hash<int>::value());
|
||||
hasType[1] = hasType[1] || (info.hash() == entt::type_hash<double>::value());
|
||||
hasType[2] = hasType[2] || (info.hash() == entt::type_hash<char>::value());
|
||||
registry.visit(entity, [&hasType](const auto &pool) {
|
||||
hasType[0] = hasType[0] || (pool.type() == entt::type_id<int>());
|
||||
hasType[1] = hasType[1] || (pool.type() == entt::type_id<double>());
|
||||
hasType[2] = hasType[2] || (pool.type() == entt::type_id<char>());
|
||||
});
|
||||
|
||||
ASSERT_TRUE(hasType[0] && !hasType[1] && hasType[2]);
|
||||
|
||||
hasType[0] = hasType[2] = false;
|
||||
|
||||
registry.visit(other, [&hasType](const auto &info) {
|
||||
hasType[0] = hasType[0] || (info.hash() == entt::type_hash<int>::value());
|
||||
hasType[1] = hasType[1] || (info.hash() == entt::type_hash<double>::value());
|
||||
hasType[2] = hasType[2] || (info.hash() == entt::type_hash<char>::value());
|
||||
registry.visit(other, [&hasType](const auto &pool) {
|
||||
hasType[0] = hasType[0] || (pool.type() == entt::type_id<int>());
|
||||
hasType[1] = hasType[1] || (pool.type() == entt::type_id<double>());
|
||||
hasType[2] = hasType[2] || (pool.type() == entt::type_id<char>());
|
||||
});
|
||||
|
||||
ASSERT_TRUE(!hasType[0] && hasType[1] && !hasType[2]);
|
||||
|
||||
Reference in New Issue
Block a user