Browse Source

observer: fixed an issue with exclusion lists (close #549)

Michele Caini 5 years ago
parent
commit
1c650cb136
2 changed files with 37 additions and 3 deletions
  1. 10 3
      src/entt/entity/observer.hpp
  2. 27 0
      test/entt/entity/observer.cpp

+ 10 - 3
src/entt/entity/observer.hpp

@@ -212,9 +212,16 @@ class basic_observer {
 
     template<typename... Reject, typename... Require, typename... NoneOf, typename... AllOf>
     struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, type_list<NoneOf...>, AllOf...>> {
-        template<std::size_t Index>
+        template<std::size_t Index, typename... Ignore>
         static void maybe_valid_if(basic_observer &obs, const basic_registry<Entity> &reg, const Entity entt) {
-            if(reg.template has<AllOf..., Require...>(entt) && !reg.template any<NoneOf..., Reject...>(entt)) {
+            if([&reg, entt]() {
+                if constexpr(sizeof...(Ignore) == 0) {
+                    return reg.template has<AllOf..., Require...>(entt) && !reg.template any<NoneOf..., Reject...>(entt);
+                } else {
+                    return reg.template has<AllOf..., Require...>(entt) && ((std::is_same_v<Ignore..., NoneOf> || !reg.template any<NoneOf>(entt)) && ...) && !reg.template any<Reject...>(entt);
+                }
+            }())
+            {
                 if(auto *comp = obs.view.try_get(entt); !comp) {
                     obs.view.emplace(entt);
                 }
@@ -235,7 +242,7 @@ class basic_observer {
             (reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
             (reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
             (reg.template on_construct<AllOf>().template connect<&maybe_valid_if<Index>>(obs), ...);
-            (reg.template on_destroy<NoneOf>().template connect<&maybe_valid_if<Index>>(obs), ...);
+            (reg.template on_destroy<NoneOf>().template connect<&maybe_valid_if<Index, NoneOf>>(obs), ...);
             (reg.template on_destroy<AllOf>().template connect<&discard_if<Index>>(obs), ...);
             (reg.template on_construct<NoneOf>().template connect<&discard_if<Index>>(obs), ...);
         }

+ 27 - 0
test/entt/entity/observer.cpp

@@ -340,3 +340,30 @@ TEST(Observer, MultipleFilters) {
 
     ASSERT_TRUE(observer.empty());
 }
+
+TEST(Observer, GroupCornerCase) {
+    constexpr auto add_collector =  entt::collector.group<int>(entt::exclude<char>);
+    constexpr auto remove_collector =  entt::collector.group<int, char>();
+
+    entt::registry registry;
+    entt::observer add_observer{registry, add_collector};
+    entt::observer remove_observer{registry, remove_collector};
+
+    const auto entity = registry.create();
+    registry.emplace<int>(entity);
+
+    ASSERT_FALSE(add_observer.empty());
+    ASSERT_TRUE(remove_observer.empty());
+
+    add_observer.clear();
+    registry.emplace<char>(entity);
+
+    ASSERT_TRUE(add_observer.empty());
+    ASSERT_FALSE(remove_observer.empty());
+
+    remove_observer.clear();
+    registry.remove<char>(entity);
+
+    ASSERT_FALSE(add_observer.empty());
+    ASSERT_TRUE(remove_observer.empty());
+}