From 645edfb2b8c2136fbe6040b2e161b9602daec7e5 Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Wed, 29 Mar 2023 17:35:53 +0200 Subject: [PATCH] group: decouple constructing and setting prev/next links --- src/entt/entity/group.hpp | 20 +++++++++++++++++--- src/entt/entity/registry.hpp | 14 ++++++++------ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/entt/entity/group.hpp b/src/entt/entity/group.hpp index 53a6ed556..67cbc7636 100644 --- a/src/entt/entity/group.hpp +++ b/src/entt/entity/group.hpp @@ -136,7 +136,7 @@ class group_handler, get_t, exclude_t> fin } public: - group_handler(Owned &...opool, Get &...gpool, Exclude &...epool, const void *prev, const void *next) + group_handler(Owned &...opool, Get &...gpool, Exclude &...epool) : owning_group_descriptor{ sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude), +[](const id_type ctype) noexcept { return ((ctype == entt::type_hash::value()) || ...); }, @@ -145,8 +145,8 @@ public: pools{&opool..., &gpool...}, filter{&epool...}, len{} { - std::apply([this, prev, next](auto *...cpool) { ((cpool->on_construct().before(next).template connect<&group_handler::push_on_construct>(*this), cpool->on_destroy().before(prev).template connect<&group_handler::remove_if>(*this)), ...); }, pools); - std::apply([this, prev, next](auto *...cpool) { ((cpool->on_construct().before(prev).template connect<&group_handler::remove_if>(*this), cpool->on_destroy().before(next).template connect<&group_handler::push_on_destroy>(*this)), ...); }, filter); + std::apply([this](auto *...cpool) { ((cpool->on_construct().template connect<&group_handler::push_on_construct>(*this), cpool->on_destroy().template connect<&group_handler::remove_if>(*this)), ...); }, pools); + std::apply([this](auto *...cpool) { ((cpool->on_construct().template connect<&group_handler::remove_if>(*this), cpool->on_destroy().template connect<&group_handler::push_on_destroy>(*this)), ...); }, filter); // we cannot iterate backwards because we want to leave behind valid entities in case of owned types for(auto *first = std::get<0>(pools)->data(), *last = first + std::get<0>(pools)->size(); first != last; ++first) { @@ -154,6 +154,20 @@ public: } } + void previous(const void *elem) { + if(elem) { + std::apply([this, elem](auto *...cpool) { ((cpool->on_destroy().disconnect(this), cpool->on_destroy().before(elem).template connect<&group_handler::remove_if>(*this)), ...); }, pools); + std::apply([this, elem](auto *...cpool) { ((cpool->on_construct().disconnect(this), cpool->on_construct().before(elem).template connect<&group_handler::remove_if>(*this)), ...); }, filter); + } + } + + void next(const void *elem) { + if(elem) { + std::apply([this, elem](auto *...cpool) { ((cpool->on_construct().disconnect(this), cpool->on_construct().before(elem).template connect<&group_handler::push_on_construct>(*this)), ...); }, pools); + std::apply([this, elem](auto *...cpool) { ((cpool->on_destroy().disconnect(this), cpool->on_destroy().before(elem).template connect<&group_handler::push_on_destroy>(*this)), ...); }, filter); + } + } + [[nodiscard]] std::size_t length() const noexcept { return len; } diff --git a/src/entt/entity/registry.hpp b/src/entt/entity/registry.hpp index 35eb73131..0fdd13570 100644 --- a/src/entt/entity/registry.hpp +++ b/src/entt/entity/registry.hpp @@ -1222,9 +1222,10 @@ public: return {*std::static_pointer_cast(it->second)}; } - constexpr auto hsize = sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude); + auto handler = std::allocate_shared(get_allocator(), assure>()..., assure>()..., assure>()...); + owning_groups.emplace(type_hash::value(), handler); - ENTT_ASSERT(std::all_of(owning_groups.cbegin(), owning_groups.cend(), [hsize](const auto &data) { + ENTT_ASSERT(std::all_of(owning_groups.cbegin(), owning_groups.cend(), [hsize = handler->size](const auto &data) { const auto overlapping = (0u + ... + data.second->owned(type_hash>::value())); const auto sz = overlapping + (0u + ... + data.second->get(type_hash>::value())) + (0u + ... + data.second->exclude(type_hash>::value())); return !overlapping || ((sz == hsize) || (sz == data.second->size)); @@ -1236,18 +1237,19 @@ public: for(auto &&data: owning_groups) { if((data.second->owned(type_hash>::value()) || ...)) { - if(const auto sz = data.second->size; sz < hsize && (prev == nullptr || prev->size < sz)) { + if(const auto sz = data.second->size; sz < handler->size && (prev == nullptr || prev->size < sz)) { prev = data.second.get(); } - if(const auto sz = data.second->size; sz > hsize && (next == nullptr || next->size > sz)) { + if(const auto sz = data.second->size; sz > handler->size && (next == nullptr || next->size > sz)) { next = data.second.get(); } } } - auto handler = std::allocate_shared(get_allocator(), assure>()..., assure>()..., assure>()..., prev, next); - owning_groups.emplace(type_hash::value(), handler); + handler->previous(prev); + handler->next(next); + return {*handler}; } }