Michele Caini 7 лет назад
Родитель
Сommit
7f8ab67e9e
2 измененных файлов с 44 добавлено и 40 удалено
  1. 36 27
      src/entt/entity/registry.hpp
  2. 8 13
      src/entt/entity/view.hpp

+ 36 - 27
src/entt/entity/registry.hpp

@@ -44,10 +44,10 @@ class Registry {
     using signal_type = SigH<void(Registry &, const Entity)>;
     using traits_type = entt_traits<Entity>;
 
-    template<typename... Component>
+    template<typename handler_family::family_type(*Type)(), typename... Component>
     static void creating(Registry &registry, const Entity entity) {
         if(registry.has<Component...>(entity)) {
-            registry.handlers[handler_family::type<Component...>()]->construct(entity);
+            registry.handlers[Type()]->construct(entity);
         }
     }
 
@@ -74,6 +74,35 @@ class Registry {
         Tag tag;
     };
 
+    template<typename Comp, std::size_t Pivot, typename... Component, std::size_t... Indexes>
+    void connect(std::index_sequence<Indexes...>) {
+        auto &cpool = pools[component_family::type<Comp>()];
+        std::get<1>(cpool).sink().template connect<&Registry::creating<&handler_family::type<Component...>, std::tuple_element_t<(Indexes < Pivot ? Indexes : (Indexes+1)), std::tuple<Component...>>...>>();
+        std::get<2>(cpool).sink().template connect<&Registry::destroying<Component...>>();
+    }
+
+    template<typename... Component, std::size_t... Indexes>
+    void connect(std::index_sequence<Indexes...>) {
+        using accumulator_type = int[];
+        accumulator_type accumulator = { (assure<Component>(), connect<Component, Indexes, Component...>(std::make_index_sequence<sizeof...(Component)-1>{}), 0)... };
+        (void)accumulator;
+    }
+
+    template<typename Comp, std::size_t Pivot, typename... Component, std::size_t... Indexes>
+    void disconnect(std::index_sequence<Indexes...>) {
+        auto &cpool = pools[component_family::type<Comp>()];
+        std::get<1>(cpool).sink().template disconnect<&Registry::creating<&handler_family::type<Component...>, std::tuple_element_t<(Indexes < Pivot ? Indexes : (Indexes+1)), std::tuple<Component...>>...>>();
+        std::get<2>(cpool).sink().template disconnect<&Registry::destroying<Component...>>();
+    }
+
+    template<typename... Component, std::size_t... Indexes>
+    void disconnect(std::index_sequence<Indexes...>) {
+        using accumulator_type = int[];
+        // if a set exists, pools have already been created for it
+        accumulator_type accumulator = { (disconnect<Component, Indexes, Component...>(std::make_index_sequence<sizeof...(Component)-1>{}), 0)... };
+        (void)accumulator;
+    }
+
     template<typename Component>
     inline bool managed() const ENTT_NOEXCEPT {
         const auto ctype = component_family::type<Component>();
@@ -1335,22 +1364,13 @@ public:
         }
 
         if(!handlers[htype]) {
+            connect<Component...>(std::make_index_sequence<sizeof...(Component)>{});
             handlers[htype] = std::make_unique<SparseSet<entity_type>>();
-            auto &handler = handlers[htype];
+            auto &handler = *handlers[htype];
 
             for(auto entity: view<Component...>()) {
-                handler->construct(entity);
+                handler.construct(entity);
             }
-
-            auto connect = [this](const auto ctype) {
-                auto &cpool = pools[ctype];
-                std::get<1>(cpool).sink().template connect<&Registry::creating<Component...>>();
-                std::get<2>(cpool).sink().template connect<&Registry::destroying<Component...>>();
-            };
-
-            using accumulator_type = int[];
-            accumulator_type accumulator = { (assure<Component>(), connect(component_family::type<Component>()), 0)... };
-            (void)accumulator;
         }
     }
 
@@ -1372,19 +1392,8 @@ public:
     template<typename... Component>
     void discard() {
         if(contains<Component...>()) {
-            const auto htype = handler_family::type<Component...>();
-
-            auto disconnect = [this](const auto ctype) {
-                auto &cpool = pools[ctype];
-                std::get<1>(cpool).sink().template disconnect<&Registry::creating<Component...>>();
-                std::get<2>(cpool).sink().template disconnect<&Registry::destroying<Component...>>();
-            };
-
-            // if a set exists, pools have already been created for it
-            using accumulator_type = int[];
-            accumulator_type accumulator = { (disconnect(component_family::type<Component>()), 0)... };
-            handlers[htype].reset();
-            (void)accumulator;
+            disconnect<Component...>(std::make_index_sequence<sizeof...(Component)>{});
+            handlers[handler_family::type<Component...>()].reset();
         }
     }
 

+ 8 - 13
src/entt/entity/view.hpp

@@ -590,26 +590,21 @@ class View final {
     template<typename Comp, typename Func, std::size_t... Indexes>
     void each(const pool_type<Comp> &cpool, Func func, std::index_sequence<Indexes...>) const {
         const auto other = unchecked(&cpool);
-        std::array<underlying_iterator_type, sizeof...(Component)> data{{cpool.view_type::cbegin(), std::get<Indexes>(other)->cbegin()...}};
+        std::array<underlying_iterator_type, sizeof...(Indexes)> data{{std::get<Indexes>(other)->cbegin()...}};
+        const auto extent = std::min({ pool<Component>().extent()... });
         auto raw = std::make_tuple(pool<Component>().cbegin()...);
         const auto end = cpool.view_type::cend();
-        std::size_t pos{};
+        auto begin = cpool.view_type::cbegin();
 
         // we can directly use the raw iterators if pools are ordered
-        while(!pos && data[0] != end) {
-            for(pos = data.size() - 1; pos && *(data[pos]++) == *data[pos-1]; --pos);
-
-            if(!pos) {
-                func(*(data[0]++), *(std::get<component_iterator_type<Component>>(raw)++)...);
-            }
+        while(begin != end && std::min({ (*(std::get<Indexes>(data)++) == *begin)... })) {
+            func(*(begin++), *(std::get<component_iterator_type<Component>>(raw)++)...);
         }
 
-        const auto extent = std::min({ pool<Component>().extent()... });
-        auto it = std::get<component_iterator_type<Comp>>(raw);
-
         // fallback to visit what remains using indirections
-        for(; data[0] != end; ++data[0], ++it) {
-            const auto entity = *data[0];
+        while(begin != end) {
+            const auto entity = *(begin++);
+            const auto it = std::get<component_iterator_type<Comp>>(raw)++;
             const auto sz = size_type(entity & traits_type::entity_mask);
 
             if(sz < extent && std::all_of(other.cbegin(), other.cend(), [entity](const view_type *view) { return view->fast(entity); })) {