Selaa lähdekoodia

multi-component [registry|view|group]::empty

Michele Caini 6 vuotta sitten
vanhempi
commit
cc41caede9

+ 2 - 0
TODO

@@ -31,3 +31,5 @@ TODO
 * use unordered_map for named pools and context variables:
   - use direct access (pool-like) also for context variables
   - improves multi-stomp
+* improve registry::alive
+* allocation-less and faster sort

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

@@ -132,22 +132,19 @@ public:
     }
 
     /**
-     * @brief Checks whether the pool of a given component is empty.
-     * @tparam Component Type of component in which one is interested.
-     * @return True if the pool of the given component is empty, false
-     * otherwise.
-     */
-    template<typename Component>
-    bool empty() const ENTT_NOEXCEPT {
-        return std::get<pool_type<Component> *>(pools)->empty();
-    }
-
-    /**
-     * @brief Checks whether the group is empty.
-     * @return True if the group is empty, false otherwise.
+     * @brief Checks whether the group or the pools of the given components are
+     * empty.
+     * @tparam Component Types of components in which one is interested.
+     * @return True if the group or the pools of the given components are empty,
+     * false otherwise.
      */
+    template<typename... Component>
     bool empty() const ENTT_NOEXCEPT {
-        return handler->empty();
+        if constexpr(sizeof...(Component) == 0) {
+            return handler->empty();
+        } else {
+            return (std::get<pool_type<Component> *>(pools)->empty() && ...);
+        }
     }
 
     /**
@@ -550,22 +547,19 @@ public:
     }
 
     /**
-     * @brief Checks whether the pool of a given component is empty.
-     * @tparam Component Type of component in which one is interested.
-     * @return True if the pool of the given component is empty, false
-     * otherwise.
-     */
-    template<typename Component>
-    bool empty() const ENTT_NOEXCEPT {
-        return std::get<pool_type<Component> *>(pools)->empty();
-    }
-
-    /**
-     * @brief Checks whether the group is empty.
-     * @return True if the group is empty, false otherwise.
+     * @brief Checks whether the group or the pools of the given components are
+     * empty.
+     * @tparam Component Types of components in which one is interested.
+     * @return True if the group or the pools of the given components are empty,
+     * false otherwise.
      */
+    template<typename... Component>
     bool empty() const ENTT_NOEXCEPT {
-        return !*length;
+        if constexpr(sizeof...(Component) == 0) {
+            return !*length;
+        } else {
+            return (std::get<pool_type<Component> *>(pools)->empty() && ...);
+        }
     }
 
     /**

+ 17 - 16
src/entt/entity/registry.hpp

@@ -435,23 +435,24 @@ public:
     }
 
     /**
-     * @brief Checks whether the pool of a given component is empty.
-     * @tparam Component Type of component in which one is interested.
-     * @return True if the pool of the given component is empty, false
-     * otherwise.
-     */
-    template<typename Component>
-    bool empty() const ENTT_NOEXCEPT {
-        const auto *cpool = pool<Component>();
-        return cpool ? cpool->empty() : true;
-    }
-
-    /**
-     * @brief Checks if there exists at least an entity still in use.
-     * @return True if at least an entity is still in use, false otherwise.
+     * @brief Checks whether the registry or the pools of the given components
+     * are empty.
+     *
+     * A registry is considered empty when it doesn't contain entities that are
+     * still in use.
+     *
+     * @tparam Component Types of components in which one is interested.
+     * @return True if the registry or the pools of the given components are
+     * empty, false otherwise.
      */
+    template<typename... Component>
     bool empty() const ENTT_NOEXCEPT {
-        return !alive();
+        if constexpr(sizeof...(Component) == 0) {
+            return !alive();
+        } else {
+            [[maybe_unused]] const auto cpools = std::make_tuple(pool<Component>()...);
+            return ((!std::get<const pool_type<Component> *>(cpools) || std::get<const pool_type<Component> *>(cpools)->empty()) && ...);
+        }
     }
 
     /**
@@ -779,7 +780,7 @@ public:
     bool has(const entity_type entity) const ENTT_NOEXCEPT {
         ENTT_ASSERT(valid(entity));
         [[maybe_unused]] const auto cpools = std::make_tuple(pool<Component>()...);
-        return ((std::get<const pool_type<Component> *>(cpools) ? std::get<const pool_type<Component> *>(cpools)->has(entity) : false) && ...);
+        return ((std::get<const pool_type<Component> *>(cpools) && std::get<const pool_type<Component> *>(cpools)->has(entity)) && ...);
     }
 
     /**

+ 16 - 14
src/entt/entity/view.hpp

@@ -216,22 +216,24 @@ public:
     }
 
     /**
-     * @brief Checks whether the pool of a given component is empty.
-     * @tparam Comp Type of component in which one is interested.
-     * @return True if the pool of the given component is empty, false
-     * otherwise.
-     */
-    template<typename Comp>
-    bool empty() const ENTT_NOEXCEPT {
-        return std::get<pool_type<Comp> *>(pools)->empty();
-    }
-
-    /**
-     * @brief Checks if the view is definitely empty.
-     * @return True if the view is definitely empty, false otherwise.
+     * @brief Checks whether the view or the pools of the given components are
+     * empty.
+     *
+     * The view is definitely empty if one of the pools is empty. In all other
+     * cases, the view may be empty and not return entities even if this
+     * function returns false.
+     *
+     * @tparam Comp Types of components in which one is interested.
+     * @return True if the view or the pools of the given components are empty,
+     * false otherwise.
      */
+    template<typename... Comp>
     bool empty() const ENTT_NOEXCEPT {
-        return (std::get<pool_type<Component> *>(pools)->empty() || ...);
+        if constexpr(sizeof...(Comp) == 0) {
+            return (std::get<pool_type<Component> *>(pools)->empty() || ...);
+        } else {
+            return (std::get<pool_type<Comp> *>(pools)->empty() && ...);
+        }
     }
 
     /**

+ 8 - 8
test/entt/entity/group.cpp

@@ -16,8 +16,8 @@ TEST(NonOwningGroup, Functionalities) {
     auto cgroup = std::as_const(registry).group(entt::get<const int, const char>);
 
     ASSERT_TRUE(group.empty());
-    ASSERT_TRUE(group.empty<int>());
-    ASSERT_TRUE(cgroup.empty<const char>());
+    ASSERT_TRUE((group.empty<int, char>()));
+    ASSERT_TRUE((cgroup.empty<const int, const char>()));
 
     const auto e0 = registry.create();
     registry.assign<char>(e0);
@@ -27,8 +27,8 @@ TEST(NonOwningGroup, Functionalities) {
     registry.assign<char>(e1);
 
     ASSERT_FALSE(group.empty());
-    ASSERT_FALSE(group.empty<int>());
-    ASSERT_FALSE(cgroup.empty<const char>());
+    ASSERT_FALSE((group.empty<int>()));
+    ASSERT_FALSE((cgroup.empty<const char>()));
     ASSERT_NO_THROW((group.begin()++));
     ASSERT_NO_THROW((++cgroup.begin()));
 
@@ -469,8 +469,8 @@ TEST(OwningGroup, Functionalities) {
     auto cgroup = std::as_const(registry).group<const int>(entt::get<const char>);
 
     ASSERT_TRUE(group.empty());
-    ASSERT_TRUE(group.empty<int>());
-    ASSERT_TRUE(cgroup.empty<const char>());
+    ASSERT_TRUE((group.empty<int, char>()));
+    ASSERT_TRUE((cgroup.empty<const int, const char>()));
 
     const auto e0 = registry.create();
     registry.assign<char>(e0);
@@ -480,8 +480,8 @@ TEST(OwningGroup, Functionalities) {
     registry.assign<char>(e1);
 
     ASSERT_FALSE(group.empty());
-    ASSERT_FALSE(group.empty<int>());
-    ASSERT_FALSE(cgroup.empty<const char>());
+    ASSERT_FALSE((group.empty<int>()));
+    ASSERT_FALSE((cgroup.empty<const char>()));
     ASSERT_NO_THROW((group.begin()++));
     ASSERT_NO_THROW((++cgroup.begin()));
 

+ 2 - 4
test/entt/entity/registry.cpp

@@ -99,8 +99,7 @@ TEST(Registry, Functionalities) {
     ASSERT_EQ(registry.capacity<char>(), entt::registry::size_type{8});
     ASSERT_EQ(registry.size<int>(), entt::registry::size_type{0});
     ASSERT_EQ(registry.size<char>(), entt::registry::size_type{0});
-    ASSERT_TRUE(registry.empty<int>());
-    ASSERT_TRUE(registry.empty<char>());
+    ASSERT_TRUE((registry.empty<int, char>()));
 
     const auto e0 = registry.create();
     const auto e1 = registry.create();
@@ -227,8 +226,7 @@ TEST(Registry, Functionalities) {
 
     ASSERT_EQ(registry.size<int>(), entt::registry::size_type{0});
     ASSERT_EQ(registry.size<char>(), entt::registry::size_type{0});
-    ASSERT_TRUE(registry.empty<int>());
-    ASSERT_TRUE(registry.empty<char>());
+    ASSERT_TRUE((registry.empty<int, char>()));
 
     const auto e4 = registry.create();
     const auto e5 = registry.create();

+ 4 - 4
test/entt/entity/view.cpp

@@ -220,8 +220,8 @@ TEST(MultipleComponentView, Functionalities) {
     auto cview = std::as_const(registry).view<const int, const char>();
 
     ASSERT_TRUE(view.empty());
-    ASSERT_TRUE(view.empty<int>());
-    ASSERT_TRUE(cview.empty<const char>());
+    ASSERT_TRUE((view.empty<int, char>()));
+    ASSERT_TRUE((cview.empty<const int, const char>()));
 
     const auto e0 = registry.create();
     registry.assign<char>(e0);
@@ -230,8 +230,8 @@ TEST(MultipleComponentView, Functionalities) {
     registry.assign<int>(e1);
 
     ASSERT_FALSE(view.empty());
-    ASSERT_FALSE(view.empty<int>());
-    ASSERT_FALSE(cview.empty<const char>());
+    ASSERT_FALSE((view.empty<int>()));
+    ASSERT_FALSE((cview.empty<const char>()));
 
     registry.assign<char>(e1);