Browse Source

group: make group handlers work with multiple storage of the same type

Michele Caini 3 years ago
parent
commit
520c2e660d
2 changed files with 46 additions and 39 deletions
  1. 27 20
      src/entt/entity/group.hpp
  2. 19 19
      src/entt/entity/registry.hpp

+ 27 - 20
src/entt/entity/group.hpp

@@ -91,35 +91,40 @@ template<typename... Lhs, typename... Rhs>
 }
 }
 
 
 template<typename, typename, typename>
 template<typename, typename, typename>
-struct group_handler;
+class group_handler;
 
 
 template<typename... Owned, typename... Get, typename... Exclude>
 template<typename... Owned, typename... Get, typename... Exclude>
-struct group_handler<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> {
+class group_handler<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> {
     // nasty workaround for an issue with the toolset v141 that doesn't accept a fold expression here
     // nasty workaround for an issue with the toolset v141 that doesn't accept a fold expression here
     static_assert(!std::disjunction_v<std::bool_constant<Owned::traits_type::in_place_delete>...>, "Groups do not support in-place delete");
     static_assert(!std::disjunction_v<std::bool_constant<Owned::traits_type::in_place_delete>...>, "Groups do not support in-place delete");
     static_assert(!std::disjunction_v<std::is_const<Owned>..., std::is_const<Get>..., std::is_const<Exclude>...>, "Const storage type not allowed");
     static_assert(!std::disjunction_v<std::is_const<Owned>..., std::is_const<Get>..., std::is_const<Exclude>...>, "Const storage type not allowed");
 
 
-    using entity_type = std::common_type_t<typename Owned::entity_type..., typename Get::entity_type..., typename Exclude::entity_type...>;
+    using underlying_type = std::common_type_t<typename Owned::entity_type..., typename Get::entity_type..., typename Exclude::entity_type...>;
+
+    template<std::size_t... Index>
+    void swap_elements(std::index_sequence<Index...>, const std::size_t pos, const underlying_type entt) {
+        (std::get<Index>(pools)->swap_elements(std::get<Index>(pools)->data()[pos], entt), ...);
+    }
+
+public:
+    using entity_type = underlying_type;
 
 
     group_handler(Owned &...opool, Get &...gpool, Exclude &...epool)
     group_handler(Owned &...opool, Get &...gpool, Exclude &...epool)
         : pools{&opool..., &gpool...},
         : pools{&opool..., &gpool...},
           filter{&epool...} {}
           filter{&epool...} {}
 
 
-    template<typename Type>
-    void maybe_valid_if(const entity_type entt) {
-        if(((std::is_same_v<Type, Owned> || std::get<Owned *>(pools)->contains(entt)) && ...)
-           && ((std::is_same_v<Type, Get> || std::get<Get *>(pools)->contains(entt)) && ...)
-           && ((std::is_same_v<Type, Exclude> || !std::get<Exclude *>(filter)->contains(entt)) && ...)
+    template<bool Expected>
+    void push_if(const entity_type entt) {
+        if(std::apply([entt](auto *...cpool) { return (cpool->contains(entt) && ...); }, pools)
+           && std::apply([entt](auto *...cpool) { return (Expected == (0u + ... + cpool->contains(entt))); }, filter)
            && !(std::get<0>(pools)->index(entt) < current)) {
            && !(std::get<0>(pools)->index(entt) < current)) {
-            const auto pos = current++;
-            (std::get<Owned *>(pools)->swap_elements(std::get<Owned *>(pools)->data()[pos], entt), ...);
+            swap_elements(std::index_sequence_for<Owned...>{}, current++, entt);
         }
         }
     }
     }
 
 
-    void discard_if(const entity_type entt) {
+    void remove_if(const entity_type entt) {
         if(std::get<0>(pools)->contains(entt) && (std::get<0>(pools)->index(entt) < current)) {
         if(std::get<0>(pools)->contains(entt) && (std::get<0>(pools)->index(entt) < current)) {
-            const auto pos = --current;
-            (std::get<Owned *>(pools)->swap_elements(std::get<Owned *>(pools)->data()[pos], entt), ...);
+            swap_elements(std::index_sequence_for<Owned...>{}, --current, entt);
         }
         }
     }
     }
 
 
@@ -131,29 +136,31 @@ private:
 };
 };
 
 
 template<typename... Get, typename... Exclude>
 template<typename... Get, typename... Exclude>
-struct group_handler<owned_t<>, get_t<Get...>, exclude_t<Exclude...>>: std::common_type_t<typename Get::base_type..., typename Exclude::base_type...> {
+class group_handler<owned_t<>, get_t<Get...>, exclude_t<Exclude...>>: public std::common_type_t<typename Get::base_type..., typename Exclude::base_type...> {
     // nasty workaround for an issue with the toolset v141 that doesn't accept a fold expression here
     // nasty workaround for an issue with the toolset v141 that doesn't accept a fold expression here
     static_assert(!std::disjunction_v<std::is_const<Get>..., std::is_const<Exclude>...>, "Const storage type not allowed");
     static_assert(!std::disjunction_v<std::is_const<Get>..., std::is_const<Exclude>...>, "Const storage type not allowed");
 
 
-    using entity_type = std::common_type_t<typename Get::entity_type..., typename Exclude::entity_type...>;
     using basic_common_type = std::common_type_t<typename Get::base_type..., typename Exclude::base_type...>;
     using basic_common_type = std::common_type_t<typename Get::base_type..., typename Exclude::base_type...>;
 
 
+public:
+    using entity_type = std::common_type_t<typename Get::entity_type..., typename Exclude::entity_type...>;
+
     template<typename Alloc>
     template<typename Alloc>
     group_handler(const Alloc &alloc, Get &...gpool, Exclude &...epool)
     group_handler(const Alloc &alloc, Get &...gpool, Exclude &...epool)
         : basic_common_type{alloc},
         : basic_common_type{alloc},
           pools{&gpool...},
           pools{&gpool...},
           filter{&epool...} {}
           filter{&epool...} {}
 
 
-    template<typename Type>
-    void maybe_valid_if(const entity_type entt) {
-        if(((std::is_same_v<Type, Get> || std::get<Get *>(pools)->contains(entt)) && ...)
-           && ((std::is_same_v<Type, Exclude> || !std::get<Exclude *>(filter)->contains(entt)) && ...)
+    template<bool Expected>
+    void push_if(const entity_type entt) {
+        if(std::apply([entt](auto *...cpool) { return (cpool->contains(entt) && ...); }, pools)
+           && std::apply([entt](auto *...cpool) { return (Expected == (0u + ... + cpool->contains(entt))); }, filter)
            && !basic_common_type::contains(entt)) {
            && !basic_common_type::contains(entt)) {
             basic_common_type::push(entt);
             basic_common_type::push(entt);
         }
         }
     }
     }
 
 
-    void discard_if(const entity_type entt) {
+    void remove_if(const entity_type entt) {
         basic_common_type::remove(entt);
         basic_common_type::remove(entt);
     }
     }
 
 

+ 19 - 19
src/entt/entity/registry.hpp

@@ -1235,8 +1235,8 @@ public:
 
 
             handler = static_cast<handler_type *>(candidate.handler.get());
             handler = static_cast<handler_type *>(candidate.handler.get());
 
 
-            const void *maybe_valid_if = nullptr;
-            const void *discard_if = nullptr;
+            const void *push_if = nullptr;
+            const void *remove_if = nullptr;
 
 
             [[maybe_unused]] auto has_conflict = [size](const auto &gdata) {
             [[maybe_unused]] auto has_conflict = [size](const auto &gdata) {
                 const auto overlapping = (gdata.owned(type_hash<std::remove_const_t<Owned>>::value()) + ... + gdata.owned(type_hash<std::remove_const_t<Other>>::value()));
                 const auto overlapping = (gdata.owned(type_hash<std::remove_const_t<Owned>>::value()) + ... + gdata.owned(type_hash<std::remove_const_t<Other>>::value()));
@@ -1254,25 +1254,25 @@ public:
                 return (gdata.owned(type_hash<std::remove_const_t<Owned>>::value()) + ... + gdata.owned(type_hash<std::remove_const_t<Other>>::value()));
                 return (gdata.owned(type_hash<std::remove_const_t<Owned>>::value()) + ... + gdata.owned(type_hash<std::remove_const_t<Other>>::value()));
             });
             });
 
 
-            maybe_valid_if = (next == groups.cend() ? maybe_valid_if : next->handler.get());
-            discard_if = (prev == groups.crend() ? discard_if : prev->handler.get());
+            push_if = (next == groups.cend() ? push_if : next->handler.get());
+            remove_if = (prev == groups.crend() ? remove_if : prev->handler.get());
             groups.insert(next, std::move(candidate));
             groups.insert(next, std::move(candidate));
 
 
-            on_construct<std::remove_const_t<Owned>>().before(maybe_valid_if).template connect<&handler_type::template maybe_valid_if<storage_for_type<std::remove_const_t<Owned>>>>(*handler);
-            (on_construct<std::remove_const_t<Other>>().before(maybe_valid_if).template connect<&handler_type::template maybe_valid_if<storage_for_type<std::remove_const_t<Other>>>>(*handler), ...);
-            (on_construct<std::remove_const_t<Get>>().before(maybe_valid_if).template connect<&handler_type::template maybe_valid_if<storage_for_type<std::remove_const_t<Get>>>>(*handler), ...);
-            (on_destroy<std::remove_const_t<Exclude>>().before(maybe_valid_if).template connect<&handler_type::template maybe_valid_if<storage_for_type<std::remove_const_t<Exclude>>>>(*handler), ...);
+            on_construct<std::remove_const_t<Owned>>().before(push_if).template connect<&handler_type::template push_if<0u>>(*handler);
+            (on_construct<std::remove_const_t<Other>>().before(push_if).template connect<&handler_type::template push_if<0u>>(*handler), ...);
+            (on_construct<std::remove_const_t<Get>>().before(push_if).template connect<&handler_type::template push_if<0u>>(*handler), ...);
+            (on_destroy<std::remove_const_t<Exclude>>().before(push_if).template connect<&handler_type::template push_if<1u>>(*handler), ...);
 
 
-            on_destroy<std::remove_const_t<Owned>>().before(discard_if).template connect<&handler_type::discard_if>(*handler);
-            (on_destroy<std::remove_const_t<Other>>().before(discard_if).template connect<&handler_type::discard_if>(*handler), ...);
-            (on_destroy<std::remove_const_t<Get>>().before(discard_if).template connect<&handler_type::discard_if>(*handler), ...);
-            (on_construct<std::remove_const_t<Exclude>>().before(discard_if).template connect<&handler_type::discard_if>(*handler), ...);
+            on_destroy<std::remove_const_t<Owned>>().before(remove_if).template connect<&handler_type::remove_if>(*handler);
+            (on_destroy<std::remove_const_t<Other>>().before(remove_if).template connect<&handler_type::remove_if>(*handler), ...);
+            (on_destroy<std::remove_const_t<Get>>().before(remove_if).template connect<&handler_type::remove_if>(*handler), ...);
+            (on_construct<std::remove_const_t<Exclude>>().before(remove_if).template connect<&handler_type::remove_if>(*handler), ...);
 
 
             auto &cpool = assure<std::remove_const_t<Owned>>();
             auto &cpool = assure<std::remove_const_t<Owned>>();
 
 
             // we cannot iterate backwards because we want to leave behind valid entities in case of owned types
             // we cannot iterate backwards because we want to leave behind valid entities in case of owned types
             for(auto *first = cpool.data(), *last = first + cpool.size(); first != last; ++first) {
             for(auto *first = cpool.data(), *last = first + cpool.size(); first != last; ++first) {
-                handler->template maybe_valid_if<Owned>(*first);
+                handler->template push_if<0u>(*first);
             }
             }
         }
         }
 
 
@@ -1316,13 +1316,13 @@ public:
 
 
             groups.push_back(std::move(candidate));
             groups.push_back(std::move(candidate));
 
 
-            on_construct<std::remove_const_t<Get>>().template connect<&handler_type::template maybe_valid_if<storage_for_type<std::remove_const_t<Get>>>>(*handler);
-            (on_construct<std::remove_const_t<Other>>().template connect<&handler_type::template maybe_valid_if<storage_for_type<std::remove_const_t<Other>>>>(*handler), ...);
-            (on_destroy<std::remove_const_t<Exclude>>().template connect<&handler_type::template maybe_valid_if<storage_for_type<std::remove_const_t<Exclude>>>>(*handler), ...);
+            on_construct<std::remove_const_t<Get>>().template connect<&handler_type::template push_if<0u>>(*handler);
+            (on_construct<std::remove_const_t<Other>>().template connect<&handler_type::template push_if<0u>>(*handler), ...);
+            (on_destroy<std::remove_const_t<Exclude>>().template connect<&handler_type::template push_if<1u>>(*handler), ...);
 
 
-            on_destroy<std::remove_const_t<Get>>().template connect<&handler_type::discard_if>(*handler);
-            (on_destroy<std::remove_const_t<Other>>().template connect<&handler_type::discard_if>(*handler), ...);
-            (on_construct<std::remove_const_t<Exclude>>().template connect<&handler_type::discard_if>(*handler), ...);
+            on_destroy<std::remove_const_t<Get>>().template connect<&handler_type::remove_if>(*handler);
+            (on_destroy<std::remove_const_t<Other>>().template connect<&handler_type::remove_if>(*handler), ...);
+            (on_construct<std::remove_const_t<Exclude>>().template connect<&handler_type::remove_if>(*handler), ...);
 
 
             for(const auto entity: view<Get, Other...>(exclude<Exclude...>)) {
             for(const auto entity: view<Get, Other...>(exclude<Exclude...>)) {
                 handler->push(entity);
                 handler->push(entity);