registry: internal rework (close #564 among the other things)

This commit is contained in:
Michele Caini
2020-10-05 12:52:55 +02:00
parent 7684e1bad5
commit 49f65d6762

View File

@@ -45,7 +45,7 @@ class basic_registry {
struct pool_data {
type_info info{};
std::unique_ptr<sparse_set<Entity>> pool{};
void(* erase)(sparse_set<Entity> &, basic_registry &, const Entity);
void(* erase)(sparse_set<Entity> &, basic_registry &, const Entity *, const Entity *);
};
template<typename...>
@@ -114,8 +114,8 @@ class basic_registry {
if(auto &&pdata = pools[index]; !pdata.pool) {
pdata.info = type_id<Component>();
pdata.pool.reset(new pool_t<Entity, Component>());
pdata.erase = +[](sparse_set<Entity> &cpool, basic_registry &owner, const Entity entt) {
static_cast<pool_t<Entity, Component> &>(cpool).erase(owner, entt);
pdata.erase = +[](sparse_set<Entity> &cpool, basic_registry &owner, const Entity *first, const Entity *last) {
static_cast<pool_t<Entity, Component> &>(cpool).erase(owner, first, last);
};
}
@@ -141,6 +141,12 @@ class basic_registry {
return entities[curr] = entity_type{curr | version};
}
void release_entity(const Entity entity, const typename traits_type::version_type version) {
const auto entt = to_integral(entity) & traits_type::entity_mask;
entities[entt] = entity_type{to_integral(destroyed) | (typename traits_type::entity_type{version} << traits_type::entity_shift)};
destroyed = entity_type{entt};
}
public:
/*! @brief Underlying entity identifier. */
using entity_type = Entity;
@@ -378,7 +384,7 @@ public:
[[nodiscard]] version_type current(const entity_type entity) const {
const auto pos = size_type(to_integral(entity) & traits_type::entity_mask);
ENTT_ASSERT(pos < entities.size());
return version_type(to_integral(entities[pos]) >> traits_type::entity_shift);
return version(entities[pos]);
}
/**
@@ -411,11 +417,10 @@ public:
entity_type entt;
if(const auto req = (to_integral(hint) & traits_type::entity_mask); !(req < entities.size())) {
entities.reserve(req + 1);
entities.reserve(req + 1u);
for(auto pos = entities.size(); pos < req; ++pos) {
entities.emplace_back(destroyed);
destroyed = entity_type{static_cast<typename traits_type::entity_type>(pos)};
release_entity(generate_identifier(), {});
}
entt = entities.emplace_back(hint);
@@ -474,9 +479,7 @@ public:
for(std::size_t pos{}, end = entities.size(); pos < end; ++pos) {
if((to_integral(entities[pos]) & traits_type::entity_mask) != pos) {
const auto version = to_integral(entities[pos]) & (traits_type::version_mask << traits_type::entity_shift);
entities[pos] = entity_type{to_integral(destroyed) | version};
destroyed = entity_type{static_cast<typename traits_type::entity_type>(pos)};
release_entity(entity_type{static_cast<typename traits_type::entity_type>(pos)}, version(entities[pos]));
}
}
}
@@ -492,7 +495,7 @@ public:
* @param entity A valid entity identifier.
*/
void destroy(const entity_type entity) {
destroy(entity, version_type((to_integral(entity) >> traits_type::entity_shift) + 1));
destroy(entity, version(entity) + 1u);
}
/**
@@ -508,10 +511,7 @@ public:
*/
void destroy(const entity_type entity, const version_type version) {
remove_all(entity);
// lengthens the implicit list of destroyed entities
const auto entt = to_integral(entity) & traits_type::entity_mask;
entities[entt] = entity_type{to_integral(destroyed) | (typename traits_type::entity_type{version} << traits_type::entity_shift)};
destroyed = entity_type{entt};
release_entity(entity, version);
}
/**
@@ -765,10 +765,11 @@ public:
*/
void remove_all(const entity_type entity) {
ENTT_ASSERT(valid(entity));
entity_type wrap[1]{entity};
for(auto pos = pools.size(); pos; --pos) {
if(auto &pdata = pools[pos-1]; pdata.pool && pdata.pool->contains(entity)) {
pdata.erase(*pdata.pool, *this, entity);
pdata.erase(*pdata.pool, *this, std::begin(wrap), std::end(wrap));
}
}
}
@@ -920,8 +921,17 @@ public:
template<typename... Component>
void clear() {
if constexpr(sizeof...(Component) == 0) {
// useless this-> used to suppress a warning with clang
each([this](const auto entity) { this->destroy(entity); });
for(auto pos = pools.size(); pos; --pos) {
if(const auto &pdata = pools[pos-1]; pdata.pool) {
pdata.erase(*pdata.pool, *this, pdata.pool->rbegin(), pdata.pool->rend());
}
}
for(auto pos = entities.size(); pos; --pos) {
if(const auto entt = entities[pos - 1]; (to_integral(entt) & traits_type::entity_mask) == (pos - 1)) {
release_entity(entt, version(entt) + 1u);
}
}
} else {
([this](auto &&cpool) {
cpool.erase(*this, cpool.sparse_set<entity_type>::begin(), cpool.sparse_set<entity_type>::end());