From 8aa4d46ce0710374601aebfe3e7b41a586f5e293 Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Mon, 21 Jun 2021 15:18:13 +0200 Subject: [PATCH] runtime_view: support for storage policy (tombstones) --- src/entt/entity/runtime_view.hpp | 20 +++++++------ test/entt/entity/runtime_view.cpp | 48 +++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 8 deletions(-) diff --git a/src/entt/entity/runtime_view.hpp b/src/entt/entity/runtime_view.hpp index 3a3454af0..4063274a9 100644 --- a/src/entt/entity/runtime_view.hpp +++ b/src/entt/entity/runtime_view.hpp @@ -8,6 +8,7 @@ #include #include #include "../config/config.h" +#include "entity.hpp" #include "sparse_set.hpp" #include "fwd.hpp" @@ -60,8 +61,11 @@ class basic_runtime_view final { class view_iterator final { [[nodiscard]] bool valid() const { - return std::all_of(pools->begin()++, pools->end(), [entt = *it](const auto *curr) { return curr->contains(entt); }) - && std::none_of(filter->cbegin(), filter->cend(), [entt = *it](const auto *curr) { return curr && curr->contains(entt); }); + const auto entt = *it; + + return (!stable_storage || (entt != tombstone)) + && std::all_of(pools->begin()++, pools->end(), [entt](const auto *curr) { return curr->contains(entt); }) + && std::none_of(filter->cbegin(), filter->cend(), [entt](const auto *curr) { return curr && curr->contains(entt); }); } public: @@ -76,7 +80,8 @@ class basic_runtime_view final { view_iterator(const std::vector &cpools, const std::vector &ignore, underlying_iterator curr) ENTT_NOEXCEPT : pools{&cpools}, filter{&ignore}, - it{curr} + it{curr}, + stable_storage{std::any_of(pools->cbegin(), pools->cend(), [](const basic_common_type *curr) { return (curr->policy() == deletion_policy::in_place); })} { if(it != (*pools)[0]->end() && !valid()) { ++(*this); @@ -123,6 +128,7 @@ class basic_runtime_view final { const std::vector *pools; const std::vector *filter; underlying_iterator it; + bool stable_storage; }; [[nodiscard]] bool valid() const { @@ -152,12 +158,10 @@ public: : pools{std::move(cpools)}, filter{std::move(epools)} { - const auto it = std::min_element(pools.begin(), pools.end(), [](const auto *lhs, const auto *rhs) { - return (!lhs && rhs) || (lhs && rhs && lhs->size() < rhs->size()); - }); - // brings the best candidate (if any) on front of the vector - std::rotate(pools.begin(), it, pools.end()); + std::rotate(pools.begin(), std::min_element(pools.begin(), pools.end(), [](const auto *lhs, const auto *rhs) { + return (!lhs && rhs) || (lhs && rhs && lhs->size() < rhs->size()); + }), pools.end()); } /** diff --git a/test/entt/entity/runtime_view.cpp b/test/entt/entity/runtime_view.cpp index a3f807b9d..b6426c381 100644 --- a/test/entt/entity/runtime_view.cpp +++ b/test/entt/entity/runtime_view.cpp @@ -5,6 +5,14 @@ #include #include +struct stable_type { int value; }; + +template<> +struct entt::component_traits { + using in_place_delete = std::true_type; + using ignore_if_empty = std::true_type; +}; + TEST(RuntimeView, Functionalities) { entt::registry registry; @@ -224,3 +232,43 @@ TEST(RuntimeView, ExcludedComponents) { ASSERT_EQ(e0, entity); }); } + +TEST(RuntimeView, StableType) { + entt::registry registry; + + const auto e0 = registry.create(); + const auto e1 = registry.create(); + const auto e2 = registry.create(); + + registry.emplace(e0); + registry.emplace(e1); + registry.emplace(e2); + + registry.emplace(e0); + registry.emplace(e1); + + registry.remove(e1); + + entt::id_type components[] = { entt::type_hash::value(), entt::type_hash::value() }; + auto view = registry.runtime_view(std::begin(components), std::end(components)); + + ASSERT_EQ(view.size_hint(), 2u); + ASSERT_TRUE(view.contains(e0)); + ASSERT_FALSE(view.contains(e1)); + + ASSERT_EQ(*view.begin(), e0); + ASSERT_EQ(++view.begin(), view.end()); + + view.each([e0](const auto entt) { + ASSERT_EQ(e0, entt); + }); + + for(auto entt: view) { + static_assert(std::is_same_v); + ASSERT_EQ(e0, entt); + } + + registry.compact(); + + ASSERT_EQ(view.size_hint(), 1u); +}