Browse Source

group: auto init for owning groups

Michele Caini 3 years ago
parent
commit
6a16a8a20b
2 changed files with 28 additions and 33 deletions
  1. 22 14
      src/entt/entity/group.hpp
  2. 6 19
      src/entt/entity/registry.hpp

+ 22 - 14
src/entt/entity/group.hpp

@@ -114,18 +114,7 @@ class group_handler<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> fin
         std::apply([pos, entt](auto *...cpool) { (cpool->swap_elements(cpool->data()[pos], entt), ...); }, pools);
         std::apply([pos, entt](auto *...cpool) { (cpool->swap_elements(cpool->data()[pos], entt), ...); }, pools);
     }
     }
 
 
-public:
-    using entity_type = underlying_type;
-
-    group_handler(Owned &...opool, Get &...gpool, Exclude &...epool)
-        : basic_group_handler{
-            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()) || ...); }},
-          pools{&opool..., &gpool...}, filter{&epool...}, len{} {}
-
-    void push_on_construct(const entity_type entt) {
+    void push_on_construct(const underlying_type entt) {
         if(std::apply([entt](auto *...cpool) { return (cpool->contains(entt) && ...); }, pools)
         if(std::apply([entt](auto *...cpool) { return (cpool->contains(entt) && ...); }, pools)
            && std::apply([entt](auto *...cpool) { return (!cpool->contains(entt) && ...); }, filter)
            && std::apply([entt](auto *...cpool) { return (!cpool->contains(entt) && ...); }, filter)
            && !(std::get<0>(pools)->index(entt) < len)) {
            && !(std::get<0>(pools)->index(entt) < len)) {
@@ -133,7 +122,7 @@ public:
         }
         }
     }
     }
 
 
-    void push_on_destroy(const entity_type entt) {
+    void push_on_destroy(const underlying_type entt) {
         if(std::apply([entt](auto *...cpool) { return (cpool->contains(entt) && ...); }, pools)
         if(std::apply([entt](auto *...cpool) { return (cpool->contains(entt) && ...); }, pools)
            && std::apply([entt](auto *...cpool) { return (0u + ... + cpool->contains(entt)) == 1u; }, filter)
            && std::apply([entt](auto *...cpool) { return (0u + ... + cpool->contains(entt)) == 1u; }, filter)
            && !(std::get<0>(pools)->index(entt) < len)) {
            && !(std::get<0>(pools)->index(entt) < len)) {
@@ -141,12 +130,31 @@ public:
         }
         }
     }
     }
 
 
-    void remove_if(const entity_type entt) {
+    void remove_if(const underlying_type entt) {
         if(std::get<0>(pools)->contains(entt) && (std::get<0>(pools)->index(entt) < len)) {
         if(std::get<0>(pools)->contains(entt) && (std::get<0>(pools)->index(entt) < len)) {
             swap_elements(--len, entt);
             swap_elements(--len, entt);
         }
         }
     }
     }
 
 
+public:
+    using entity_type = underlying_type;
+
+    group_handler(Owned &...opool, Get &...gpool, Exclude &...epool, const void *prev, const void *next)
+        : basic_group_handler{
+            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()) || ...); }},
+          pools{&opool..., &gpool...}, filter{&epool...}, len{} {
+        std::apply([this, prev, next](auto *...cpool) { ((cpool->on_construct().before(next).template connect<&group_handler::push_on_construct>(*this), cpool->on_destroy().before(prev).template connect<&group_handler::remove_if>(*this)), ...); }, pools);
+        std::apply([this, prev, next](auto *...cpool) { ((cpool->on_construct().before(prev).template connect<&group_handler::remove_if>(*this), cpool->on_destroy().before(next).template connect<&group_handler::push_on_destroy>(*this)), ...); }, filter);
+
+        // we cannot iterate backwards because we want to leave behind valid entities in case of owned types
+        for(auto *first = std::get<0>(pools)->data(), *last = first + std::get<0>(pools)->size(); first != last; ++first) {
+            push_on_construct(*first);
+        }
+    }
+
     [[nodiscard]] std::size_t length() const noexcept {
     [[nodiscard]] std::size_t length() const noexcept {
         return len;
         return len;
     }
     }

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

@@ -1213,12 +1213,12 @@ public:
         if constexpr(sizeof...(Owned) == 0u) {
         if constexpr(sizeof...(Owned) == 0u) {
             handler = std::allocate_shared<handler_type>(get_allocator(), get_allocator(), assure<std::remove_const_t<Get>>()..., assure<std::remove_const_t<Exclude>>()...);
             handler = std::allocate_shared<handler_type>(get_allocator(), get_allocator(), assure<std::remove_const_t<Get>>()..., assure<std::remove_const_t<Exclude>>()...);
         } else {
         } else {
-            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>>()...);
+            constexpr auto hsize = sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude);
 
 
-            ENTT_ASSERT(std::all_of(groups.cbegin(), groups.cend(), [size = handler->size](const auto &data) {
+            ENTT_ASSERT(std::all_of(groups.cbegin(), groups.cend(), [hsize](const auto &data) {
                             const auto overlapping = (0u + ... + data.second->owned(type_hash<std::remove_const_t<Owned>>::value()));
                             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()));
                             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()));
-                            return !overlapping || ((sz == size) || (sz == data.second->size));
+                            return !overlapping || ((sz == hsize) || (sz == data.second->size));
                         }),
                         }),
                         "Conflicting groups");
                         "Conflicting groups");
 
 
@@ -1227,30 +1227,17 @@ public:
 
 
             for(auto &&data: groups) {
             for(auto &&data: groups) {
                 if((data.second->owned(type_hash<std::remove_const_t<Owned>>::value()) || ...)) {
                 if((data.second->owned(type_hash<std::remove_const_t<Owned>>::value()) || ...)) {
-                    if(const auto sz = data.second->size; sz < handler->size && (prev == nullptr || prev->size < sz)) {
+                    if(const auto sz = data.second->size; sz < hsize && (prev == nullptr || prev->size < sz)) {
                         prev = data.second.get();
                         prev = data.second.get();
                     }
                     }
 
 
-                    if(const auto sz = data.second->size; sz > handler->size && (next == nullptr || next->size > sz)) {
+                    if(const auto sz = data.second->size; sz > hsize && (next == nullptr || next->size > sz)) {
                         next = data.second.get();
                         next = data.second.get();
                     }
                     }
                 }
                 }
             }
             }
 
 
-            (on_construct<std::remove_const_t<Owned>>().before(*next).template connect<&handler_type::push_on_construct>(*handler), ...);
-            (on_construct<std::remove_const_t<Get>>().before(*next).template connect<&handler_type::push_on_construct>(*handler), ...);
-            (on_destroy<std::remove_const_t<Exclude>>().before(*next).template connect<&handler_type::push_on_destroy>(*handler), ...);
-
-            (on_destroy<std::remove_const_t<Owned>>().before(*prev).template connect<&handler_type::remove_if>(*handler), ...);
-            (on_destroy<std::remove_const_t<Get>>().before(*prev).template connect<&handler_type::remove_if>(*handler), ...);
-            (on_construct<std::remove_const_t<Exclude>>().before(*prev).template connect<&handler_type::remove_if>(*handler), ...);
-
-            auto &cpool = assure<type_list_element_t<0u, type_list<std::remove_const_t<Owned>...>>>();
-
-            // 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) {
-                handler->push_on_construct(*first);
-            }
+            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>>()..., prev, next);
         }
         }
 
 
         groups.emplace(type_hash<handler_type>::value(), handler);
         groups.emplace(type_hash<handler_type>::value(), handler);