group: decouple constructing and setting prev/next links
This commit is contained in:
@@ -136,7 +136,7 @@ class group_handler<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> 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<typename Owned::value_type>::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;
|
||||
}
|
||||
|
||||
@@ -1222,9 +1222,10 @@ public:
|
||||
return {*std::static_pointer_cast<handler_type>(it->second)};
|
||||
}
|
||||
|
||||
constexpr auto hsize = sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude);
|
||||
auto handler = std::allocate_shared<handler_type>(get_allocator(), assure<std::remove_const_t<Owned>>()..., assure<std::remove_const_t<Get>>()..., assure<std::remove_const_t<Exclude>>()...);
|
||||
owning_groups.emplace(type_hash<handler_type>::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<std::remove_const_t<Owned>>::value()));
|
||||
const auto sz = overlapping + (0u + ... + data.second->get(type_hash<std::remove_const_t<Get>>::value())) + (0u + ... + data.second->exclude(type_hash<std::remove_const_t<Exclude>>::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<std::remove_const_t<Owned>>::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<handler_type>(get_allocator(), assure<std::remove_const_t<Owned>>()..., assure<std::remove_const_t<Get>>()..., assure<std::remove_const_t<Exclude>>()..., prev, next);
|
||||
owning_groups.emplace(type_hash<handler_type>::value(), handler);
|
||||
handler->previous(prev);
|
||||
handler->next(next);
|
||||
|
||||
return {*handler};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user