Michele Caini 6 лет назад
Родитель
Сommit
c5679b208f
1 измененных файлов с 40 добавлено и 60 удалено
  1. 40 60
      src/entt/entity/registry.hpp

+ 40 - 60
src/entt/entity/registry.hpp

@@ -114,43 +114,12 @@ class basic_registry {
         void(* stamp)(basic_registry &, const Entity, const sparse_set<Entity> &, const Entity);
     };
 
-    struct group_data {
-        const std::size_t extent[3];
-
-        group_data(const std::size_t osize, const std::size_t gsize, const std::size_t esize)
-            : extent{osize, gsize, esize}
-        {}
-
-        virtual ~group_data() = default;
-
-        virtual bool owned(const ENTT_ID_TYPE) ENTT_NOEXCEPT = 0;
-        virtual bool get(const ENTT_ID_TYPE) ENTT_NOEXCEPT = 0;
-        virtual bool exclude(const ENTT_ID_TYPE) ENTT_NOEXCEPT = 0;
-    };
-
     template<typename...>
     struct group_handler;
 
     template<typename... Exclude, typename... Get, typename... Owned>
-    struct group_handler<exclude_t<Exclude...>, get_t<Get...>, Owned...>: group_data {
-        std::conditional_t<sizeof...(Owned) == 0, sparse_set<Entity>, std::size_t> current;
-
-        group_handler()
-            : group_data{sizeof...(Owned), sizeof...(Get), sizeof...(Exclude)},
-              current{}
-        {}
-
-        bool owned(const ENTT_ID_TYPE ctype) ENTT_NOEXCEPT override {
-            return ((ctype == type_info<Owned>::id()) || ...);
-        }
-
-        bool get(const ENTT_ID_TYPE ctype) ENTT_NOEXCEPT override {
-            return ((ctype == type_info<Get>::id()) || ...);
-        }
-
-        bool exclude(const ENTT_ID_TYPE ctype) ENTT_NOEXCEPT override {
-            return ((ctype == type_info<Exclude>::id()) || ...);
-        }
+    struct group_handler<exclude_t<Exclude...>, get_t<Get...>, Owned...> {
+        std::conditional_t<sizeof...(Owned) == 0, sparse_set<Entity>, std::size_t> current{};
 
         template<typename Component>
         void maybe_valid_if(const Entity entt, basic_registry &owner) {
@@ -187,6 +156,14 @@ class basic_registry {
         }
     };
 
+    struct group_data {
+        std::size_t size;
+        std::unique_ptr<void, void(*)(void *)> group;
+        bool (* owned)(const ENTT_ID_TYPE) ENTT_NOEXCEPT;
+        bool (* get)(const ENTT_ID_TYPE) ENTT_NOEXCEPT;
+        bool (* exclude)(const ENTT_ID_TYPE) ENTT_NOEXCEPT;
+    };
+
     struct basic_variable {
         virtual ~basic_variable() = default;
         virtual ENTT_ID_TYPE id() const ENTT_NOEXCEPT = 0;
@@ -1283,51 +1260,54 @@ public:
 
         using handler_type = group_handler<exclude_t<Exclude...>, get_t<std::decay_t<Get>...>, std::decay_t<Owned>...>;
 
-        [[maybe_unused]] constexpr auto size = sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude);
         const auto cpools = std::forward_as_tuple(assure<std::decay_t<Owned>>()..., assure<std::decay_t<Get>>()...);
-        const std::size_t extent[3]{sizeof...(Owned), sizeof...(Get), sizeof...(Exclude)};
+        constexpr auto size = sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude);
         handler_type *handler = nullptr;
 
-        if(auto it = std::find_if(groups.cbegin(), groups.cend(), [&extent](const auto &curr) {
-            return std::equal(std::begin(extent), std::end(extent), std::begin(curr->extent))
-                    && (curr->owned(type_info<std::decay_t<Owned>>::id()) && ...)
-                    && (curr->get(type_info<std::decay_t<Get>>::id()) && ...)
-                    && (curr->exclude(type_info<Exclude>::id()) && ...);
+        if(auto it = std::find_if(groups.cbegin(), groups.cend(), [](const auto &gdata) {
+            return gdata.size == size
+                && (gdata.owned(type_info<std::decay_t<Owned>>::id()) && ...)
+                && (gdata.get(type_info<std::decay_t<Get>>::id()) && ...)
+                && (gdata.exclude(type_info<Exclude>::id()) && ...);
         }); it != groups.cend())
         {
-            handler = static_cast<handler_type *>(it->get());
+            handler = static_cast<handler_type *>(it->group.get());
         }
 
         if(!handler) {
-            auto grp = std::make_unique<handler_type>();
+            group_data gdata = {
+                size,
+                { new handler_type{}, [](void *instance) { delete static_cast<handler_type *>(instance); } },
+                [](const ENTT_ID_TYPE ctype) ENTT_NOEXCEPT { return ((ctype == type_info<std::decay_t<Owned>>::id()) || ...); },
+                [](const ENTT_ID_TYPE ctype) ENTT_NOEXCEPT { return ((ctype == type_info<std::decay_t<Get>>::id()) || ...); },
+                [](const ENTT_ID_TYPE ctype) ENTT_NOEXCEPT { return ((ctype == type_info<Exclude>::id()) || ...); },
+            };
+
+            handler = static_cast<handler_type *>(gdata.group.get());
+
             const void *maybe_valid_if = nullptr;
             const void *discard_if = nullptr;
 
             if constexpr(sizeof...(Owned) == 0) {
-                handler = static_cast<handler_type *>(groups.emplace_back(std::move(grp)).get());
+                groups.push_back(std::move(gdata));
             } else {
-                ENTT_ASSERT(std::all_of(groups.cbegin(), groups.cend(), [&extent](const auto &curr) {
-                    const std::size_t diff[3]{
-                        (0u + ... + curr->owned(type_info<std::decay_t<Owned>>::id())),
-                        (0u + ... + curr->get(type_info<std::decay_t<Get>>::id())),
-                        (0u + ... + curr->exclude(type_info<Exclude>::id()))
-                    };
-
-                    return !diff[0] || ((std::equal(std::begin(diff), std::end(diff), extent) || std::equal(std::begin(diff), std::end(diff), curr->extent)));
+                ENTT_ASSERT(std::all_of(groups.cbegin(), groups.cend(), [](const auto &gdata) {
+                    const auto overlapping = (0u + ... + gdata.owned(type_info<std::decay_t<Owned>>::id()));
+                    const auto sz = overlapping + (0u + ... + gdata.get(type_info<std::decay_t<Get>>::id())) + (0u + ... + gdata.exclude(type_info<Exclude>::id()));
+                    return !overlapping || ((sz == size) || (sz == gdata.size));
                 }));
 
-                const auto next = std::find_if_not(groups.cbegin(), groups.cend(), [&size](const auto &curr) {
-                    const std::size_t diff = (0u + ... + curr->owned(type_info<std::decay_t<Owned>>::id()));
-                    return !diff || (size > (curr->extent[0] + curr->extent[1] + curr->extent[2]));
+                const auto next = std::find_if_not(groups.cbegin(), groups.cend(), [&size](const auto &gdata) {
+                    return !(0u + ... + gdata.owned(type_info<std::decay_t<Owned>>::id())) || (size > (gdata.size));
                 });
 
-                const auto prev = std::find_if(std::make_reverse_iterator(next), groups.crend(), [](const auto &curr) {
-                    return (0u + ... + curr->owned(type_info<std::decay_t<Owned>>::id()));
+                const auto prev = std::find_if(std::make_reverse_iterator(next), groups.crend(), [](const auto &gdata) {
+                    return (0u + ... + gdata.owned(type_info<std::decay_t<Owned>>::id()));
                 });
 
-                maybe_valid_if = (next == groups.cend() ? maybe_valid_if : next->get());
-                discard_if = (prev == groups.crend() ? discard_if : prev->get());
-                handler = static_cast<handler_type *>(groups.insert(next, std::move(grp))->get());
+                maybe_valid_if = (next == groups.cend() ? maybe_valid_if : next->group.get());
+                discard_if = (prev == groups.crend() ? discard_if : prev->group.get());
+                groups.insert(next, std::move(gdata));
             }
 
             ((std::get<pool_type<Owned> &>(cpools).super = std::max(std::get<pool_type<Owned> &>(cpools).super, size)), ...);
@@ -1713,8 +1693,8 @@ public:
     }
 
 private:
+    std::vector<group_data> groups{};
     mutable std::vector<pool_data> pools{};
-    std::vector<std::unique_ptr<group_data>> groups{};
     std::vector<std::unique_ptr<basic_variable>> vars{};
     std::vector<entity_type> entities{};
     entity_type destroyed{null};