Browse Source

group: single check function for group handlers

Michele Caini 3 years ago
parent
commit
ebb1e8a728
2 changed files with 42 additions and 17 deletions
  1. 30 9
      src/entt/entity/group.hpp
  2. 12 8
      src/entt/entity/registry.hpp

+ 30 - 9
src/entt/entity/group.hpp

@@ -93,10 +93,15 @@ template<typename... Lhs, typename... Rhs>
 }
 }
 
 
 struct owning_group_descriptor {
 struct owning_group_descriptor {
-    const std::size_t size;
-    bool (*const owned)(const id_type) noexcept;
-    bool (*const get)(const id_type) noexcept;
-    bool (*const exclude)(const id_type) noexcept;
+    using size_type = std::size_t;
+
+    owning_group_descriptor(const size_type sz)
+        : size{sz} {}
+
+    virtual ~owning_group_descriptor() = default;
+    virtual size_type check(const id_type *, const size_type, const size_type, const size_type) const noexcept = 0;
+
+    const size_type size;
 };
 };
 
 
 template<typename, typename, typename>
 template<typename, typename, typename>
@@ -136,12 +141,10 @@ class group_handler<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> fin
     }
     }
 
 
 public:
 public:
+    using size_type = typename owning_group_descriptor::size_type;
+
     group_handler(Owned &...opool, Get &...gpool, Exclude &...epool)
     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()) || ...); },
-            +[]([[maybe_unused]] const id_type ctype) noexcept { return ((ctype == entt::type_hash<typename Get::value_type>::value()) || ...); },
-            +[]([[maybe_unused]] const id_type ctype) noexcept { return ((ctype == entt::type_hash<typename Exclude::value_type>::value()) || ...); }},
+        : owning_group_descriptor{sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude)},
           pools{&opool..., &gpool...},
           pools{&opool..., &gpool...},
           filter{&epool...},
           filter{&epool...},
           len{} {
           len{} {
@@ -154,6 +157,24 @@ public:
         }
         }
     }
     }
 
 
+    size_type check(const id_type *elem, const size_type olen, const size_type glen, const size_type elen) const noexcept final {
+        size_type cnt = 0u;
+
+        for(auto pos = 0u; pos < olen; ++pos) {
+            cnt += ((elem[pos] == entt::type_hash<typename Owned::value_type>::value()) || ...);
+        }
+
+        for(auto pos = 0u; pos < glen; ++pos) {
+            cnt += ((elem[olen + pos] == entt::type_hash<typename Get::value_type>::value()) || ...);
+        }
+
+        for(auto pos = 0u; pos < elen; ++pos) {
+            cnt += ((elem[olen + glen + pos] == entt::type_hash<typename Exclude::value_type>::value()) || ...);
+        }
+
+        return cnt;
+    }
+
     void previous(const owning_group_descriptor &elem) {
     void previous(const owning_group_descriptor &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_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);
         std::apply([this, &elem](auto *...cpool) { ((cpool->on_construct().disconnect(this), cpool->on_construct().before(&elem).template connect<&group_handler::remove_if>(*this)), ...); }, filter);

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

@@ -1222,12 +1222,13 @@ public:
                 return {*std::static_pointer_cast<handler_type>(it->second)};
                 return {*std::static_pointer_cast<handler_type>(it->second)};
             }
             }
 
 
+            const id_type elem[]{type_hash<std::remove_const_t<Owned>>::value()..., type_hash<std::remove_const_t<Get>>::value()..., type_hash<std::remove_const_t<Exclude>>::value()...};
             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>>()...);
             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);
             owning_groups.emplace(type_hash<handler_type>::value(), handler);
 
 
-            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()));
+            ENTT_ASSERT(std::all_of(owning_groups.cbegin(), owning_groups.cend(), [&elem, hsize = handler->size](const auto &data) {
+                            const auto overlapping = data.second->check(elem, sizeof...(Owned), 0u, 0u);
+                            const auto sz = data.second->check(elem, sizeof...(Owned), sizeof...(Get), sizeof...(Exclude));
                             return !overlapping || ((sz == hsize) || (sz == data.second->size));
                             return !overlapping || ((sz == hsize) || (sz == data.second->size));
                         }),
                         }),
                         "Conflicting groups");
                         "Conflicting groups");
@@ -1236,7 +1237,7 @@ public:
             const internal::owning_group_descriptor *next = nullptr;
             const internal::owning_group_descriptor *next = nullptr;
 
 
             for(auto &&data: owning_groups) {
             for(auto &&data: owning_groups) {
-                if((data.second->owned(type_hash<std::remove_const_t<Owned>>::value()) || ...)) {
+                if(data.second->check(elem, sizeof...(Owned), 0u, 0u)) {
                     if(const auto sz = data.second->size; sz < handler->size && (prev == nullptr || prev->size < sz)) {
                     if(const auto sz = data.second->size; sz < handler->size && (prev == nullptr || prev->size < sz)) {
                         prev = data.second.get();
                         prev = data.second.get();
                     }
                     }
@@ -1280,13 +1281,15 @@ public:
 
 
     /**
     /**
      * @brief Checks whether the given components belong to any group.
      * @brief Checks whether the given components belong to any group.
-     * @tparam Type Types of components in which one is interested.
+     * @tparam Type Type of component in which one is interested.
+     * @tparam Other Other types of components in which one is interested.
      * @return True if the pools of the given components are _free_, false
      * @return True if the pools of the given components are _free_, false
      * otherwise.
      * otherwise.
      */
      */
-    template<typename... Type>
+    template<typename Type, typename... Other>
     [[nodiscard]] bool owned() const {
     [[nodiscard]] bool owned() const {
-        return std::any_of(owning_groups.cbegin(), owning_groups.cend(), [](auto &&data) { return (data.second->owned(type_hash<std::remove_const_t<Type>>::value()) || ...); });
+        const id_type elem[]{type_hash<std::remove_const_t<Type>>::value(), type_hash<std::remove_const_t<Other>>::value()...};
+        return std::any_of(owning_groups.cbegin(), owning_groups.cend(), [&elem](auto &&data) { return data.second->check(elem, 1u + sizeof...(Other), 0u, 0u); });
     }
     }
 
 
     /**
     /**
@@ -1299,7 +1302,8 @@ public:
     template<typename... Owned, typename... Get, typename... Exclude>
     template<typename... Owned, typename... Get, typename... Exclude>
     [[nodiscard]] bool sortable(const basic_group<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> &) noexcept {
     [[nodiscard]] bool sortable(const basic_group<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> &) noexcept {
         constexpr auto size = sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude);
         constexpr auto size = sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude);
-        auto pred = [size](const auto &data) { return (data.second->owned(type_hash<typename Owned::value_type>::value()) || ...) && (size < data.second->size); };
+        const id_type elem[]{type_hash<typename Owned::value_type>::value()...};
+        auto pred = [&elem, size](const auto &data) { return data.second->check(elem, sizeof...(Owned), 0u, 0u) && (size < data.second->size); };
         return std::find_if(owning_groups.cbegin(), owning_groups.cend(), std::move(pred)) == owning_groups.cend();
         return std::find_if(owning_groups.cbegin(), owning_groups.cend(), std::move(pred)) == owning_groups.cend();
     }
     }