Просмотр исходного кода

runtime_view: support for storage policy (tombstones)

Michele Caini 4 лет назад
Родитель
Сommit
8aa4d46ce0
2 измененных файлов с 60 добавлено и 8 удалено
  1. 12 8
      src/entt/entity/runtime_view.hpp
  2. 48 0
      test/entt/entity/runtime_view.cpp

+ 12 - 8
src/entt/entity/runtime_view.hpp

@@ -8,6 +8,7 @@
 #include <algorithm>
 #include <algorithm>
 #include <type_traits>
 #include <type_traits>
 #include "../config/config.h"
 #include "../config/config.h"
+#include "entity.hpp"
 #include "sparse_set.hpp"
 #include "sparse_set.hpp"
 #include "fwd.hpp"
 #include "fwd.hpp"
 
 
@@ -60,8 +61,11 @@ class basic_runtime_view final {
 
 
     class view_iterator final {
     class view_iterator final {
         [[nodiscard]] bool valid() const {
         [[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:
     public:
@@ -76,7 +80,8 @@ class basic_runtime_view final {
         view_iterator(const std::vector<const basic_common_type *> &cpools, const std::vector<const basic_common_type *> &ignore, underlying_iterator curr) ENTT_NOEXCEPT
         view_iterator(const std::vector<const basic_common_type *> &cpools, const std::vector<const basic_common_type *> &ignore, underlying_iterator curr) ENTT_NOEXCEPT
             : pools{&cpools},
             : pools{&cpools},
               filter{&ignore},
               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()) {
             if(it != (*pools)[0]->end() && !valid()) {
                 ++(*this);
                 ++(*this);
@@ -123,6 +128,7 @@ class basic_runtime_view final {
         const std::vector<const basic_common_type *> *pools;
         const std::vector<const basic_common_type *> *pools;
         const std::vector<const basic_common_type *> *filter;
         const std::vector<const basic_common_type *> *filter;
         underlying_iterator it;
         underlying_iterator it;
+        bool stable_storage;
     };
     };
 
 
     [[nodiscard]] bool valid() const {
     [[nodiscard]] bool valid() const {
@@ -152,12 +158,10 @@ public:
         : pools{std::move(cpools)},
         : pools{std::move(cpools)},
           filter{std::move(epools)}
           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
         // 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());
     }
     }
 
 
     /**
     /**

+ 48 - 0
test/entt/entity/runtime_view.cpp

@@ -5,6 +5,14 @@
 #include <entt/entity/registry.hpp>
 #include <entt/entity/registry.hpp>
 #include <entt/entity/runtime_view.hpp>
 #include <entt/entity/runtime_view.hpp>
 
 
+struct stable_type { int value; };
+
+template<>
+struct entt::component_traits<stable_type> {
+    using in_place_delete = std::true_type;
+    using ignore_if_empty = std::true_type;
+};
+
 TEST(RuntimeView, Functionalities) {
 TEST(RuntimeView, Functionalities) {
     entt::registry registry;
     entt::registry registry;
 
 
@@ -224,3 +232,43 @@ TEST(RuntimeView, ExcludedComponents) {
         ASSERT_EQ(e0, entity);
         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<int>(e0);
+    registry.emplace<int>(e1);
+    registry.emplace<int>(e2);
+
+    registry.emplace<stable_type>(e0);
+    registry.emplace<stable_type>(e1);
+
+    registry.remove<stable_type>(e1);
+
+    entt::id_type components[] = { entt::type_hash<int>::value(), entt::type_hash<stable_type>::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<decltype(entt), entt::entity>);
+        ASSERT_EQ(e0, entt);
+    }
+
+    registry.compact();
+
+    ASSERT_EQ(view.size_hint(), 1u);
+}