From 49f65d6762756c7e30ef4587e94da18215dfcaf9 Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Mon, 5 Oct 2020 12:52:55 +0200 Subject: [PATCH] registry: internal rework (close #564 among the other things) --- src/entt/entity/registry.hpp | 46 ++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/src/entt/entity/registry.hpp b/src/entt/entity/registry.hpp index 607b21206..109bce34d 100644 --- a/src/entt/entity/registry.hpp +++ b/src/entt/entity/registry.hpp @@ -45,7 +45,7 @@ class basic_registry { struct pool_data { type_info info{}; std::unique_ptr> pool{}; - void(* erase)(sparse_set &, basic_registry &, const Entity); + void(* erase)(sparse_set &, basic_registry &, const Entity *, const Entity *); }; template @@ -114,8 +114,8 @@ class basic_registry { if(auto &&pdata = pools[index]; !pdata.pool) { pdata.info = type_id(); pdata.pool.reset(new pool_t()); - pdata.erase = +[](sparse_set &cpool, basic_registry &owner, const Entity entt) { - static_cast &>(cpool).erase(owner, entt); + pdata.erase = +[](sparse_set &cpool, basic_registry &owner, const Entity *first, const Entity *last) { + static_cast &>(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(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(pos)}; + release_entity(entity_type{static_cast(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 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::begin(), cpool.sparse_set::end());