Michele Caini 8 лет назад
Родитель
Сommit
cf5074bdc5
3 измененных файлов с 95 добавлено и 26 удалено
  1. 72 19
      src/entt/entity/registry.hpp
  2. 3 7
      src/entt/entity/snapshot.hpp
  3. 20 0
      test/entt/entity/registry.cpp

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

@@ -71,10 +71,16 @@ class Registry {
         Tag tag;
         Tag tag;
     };
     };
 
 
+    template<typename Component>
+    bool managed() const ENTT_NOEXCEPT {
+        const auto ctype = component_family::type<Component>();
+        return ctype < pools.size() && std::get<0>(pools[ctype]);
+    }
+
     template<typename Component>
     template<typename Component>
     const SparseSet<Entity, Component> & pool() const ENTT_NOEXCEPT {
     const SparseSet<Entity, Component> & pool() const ENTT_NOEXCEPT {
+        assert(managed<Component>());
         const auto ctype = component_family::type<Component>();
         const auto ctype = component_family::type<Component>();
-        assert(ctype < pools.size() && std::get<0>(pools[ctype]));
         return static_cast<SparseSet<Entity, Component> &>(*std::get<0>(pools[ctype]));
         return static_cast<SparseSet<Entity, Component> &>(*std::get<0>(pools[ctype]));
     }
     }
 
 
@@ -175,8 +181,7 @@ public:
      */
      */
     template<typename Component>
     template<typename Component>
     size_type size() const ENTT_NOEXCEPT {
     size_type size() const ENTT_NOEXCEPT {
-        const auto ctype = component_family::type<Component>();
-        return ((ctype < pools.size()) && std::get<0>(pools[ctype])) ? std::get<0>(pools[ctype])->size() : size_type{};
+        return managed<Component>() ? pool<Component>().size() : size_type{};
     }
     }
 
 
     /**
     /**
@@ -230,8 +235,7 @@ public:
      */
      */
     template<typename Component>
     template<typename Component>
     bool empty() const ENTT_NOEXCEPT {
     bool empty() const ENTT_NOEXCEPT {
-        const auto ctype = component_family::type<Component>();
-        return (!(ctype < pools.size()) || !std::get<0>(pools[ctype]) || std::get<0>(pools[ctype])->empty());
+        return !managed<Component>() || pool<Component>().empty();
     }
     }
 
 
     /**
     /**
@@ -242,6 +246,63 @@ public:
         return entities.size() == available;
         return entities.size() == available;
     }
     }
 
 
+    /**
+     * @brief Direct access to the list of components of a given pool.
+     *
+     * The returned pointer is such that range
+     * `[raw<Component>(), raw<Component>() + size<Component>()]` is always a
+     * valid range, even if the container is empty.
+     *
+     * @note
+     * There are no guarantees on the order of the components. Use a view if you
+     * want to iterate entities and components in the expected order.
+     *
+     * @tparam Component Type of component in which one is interested.
+     * @return A pointer to the array of components of the given type.
+     */
+    template<typename Component>
+    const Component * raw() const ENTT_NOEXCEPT {
+        return managed<Component>() ? pool<Component>().raw() : nullptr;
+    }
+
+    /**
+     * @brief Direct access to the list of components of a given pool.
+     *
+     * The returned pointer is such that range
+     * `[raw<Component>(), raw<Component>() + size<Component>()]` is always a
+     * valid range, even if the container is empty.
+     *
+     * @note
+     * There are no guarantees on the order of the components. Use a view if you
+     * want to iterate entities and components in the expected order.
+     *
+     * @tparam Component Type of component in which one is interested.
+     * @return A pointer to the array of components of the given type.
+     */
+    template<typename Component>
+    Component * raw() ENTT_NOEXCEPT {
+        return const_cast<Component *>(const_cast<const Registry *>(this)->raw<Component>());
+    }
+
+    /**
+     * @brief Direct access to the list of entities of a given pool.
+     *
+     * The returned pointer is such that range
+     * `[data<Component>(), data<Component>() + size<Component>()]` is always a
+     * valid range, even if the container is empty.
+     *
+     * @note
+     * There are no guarantees on the order of the entities. Use a view if you
+     * want to iterate entities and components in the expected order.
+     *
+     * @tparam Component Type of component in which one is interested.
+     * @return A pointer to the array of entities.
+     */
+    template<typename Component>
+    const entity_type * data() const ENTT_NOEXCEPT {
+        return managed<Component>() ? pool<Component>().data() : nullptr;
+    }
+
     /**
     /**
      * @brief Checks if an entity identifier refers to a valid entity.
      * @brief Checks if an entity identifier refers to a valid entity.
      * @param entity An entity identifier, either valid or not.
      * @param entity An entity identifier, either valid or not.
@@ -480,8 +541,8 @@ public:
     template<typename Component>
     template<typename Component>
     void remove(entity_type entity) {
     void remove(entity_type entity) {
         assert(valid(entity));
         assert(valid(entity));
+        assert(managed<Component>());
         const auto ctype = component_family::type<Component>();
         const auto ctype = component_family::type<Component>();
-        assert(ctype < pools.size() && std::get<0>(pools[ctype]));
         std::get<2>(pools[ctype]).publish(*this, entity);
         std::get<2>(pools[ctype]).publish(*this, entity);
         pool<Component>().destroy(entity);
         pool<Component>().destroy(entity);
     }
     }
@@ -522,9 +583,8 @@ public:
         assert(valid(entity));
         assert(valid(entity));
         using accumulator_type = bool[];
         using accumulator_type = bool[];
         bool all = true;
         bool all = true;
-        auto test = [entity, this](auto ctype) { return (ctype < pools.size()) && std::get<0>(pools[ctype]) && std::get<0>(pools[ctype])->has(entity); };
-        accumulator_type accumulator = { all, (all = all && test(component_family::type<Component>()))... };
-        (void)test, (void)accumulator;
+        accumulator_type accumulator = { all, (all = all && managed<Component>() && pool<Component>().has(entity))... };
+        (void)accumulator;
         return all;
         return all;
     }
     }
 
 
@@ -580,9 +640,8 @@ public:
     template<typename Component>
     template<typename Component>
     const Component & get(entity_type entity) const ENTT_NOEXCEPT {
     const Component & get(entity_type entity) const ENTT_NOEXCEPT {
         assert(valid(entity));
         assert(valid(entity));
-        const auto ctype = component_family::type<Component>();
-        assert((ctype < pools.size()) && std::get<0>(pools[ctype]));
-        return static_cast<SparseSet<Entity, Component> &>(*std::get<0>(pools[ctype])).get(entity);
+        assert(managed<Component>());
+        return pool<Component>().get(entity);
     }
     }
 
 
     /**
     /**
@@ -1315,7 +1374,6 @@ public:
      */
      */
     Snapshot<Entity> snapshot() const {
     Snapshot<Entity> snapshot() const {
         using follow_fn_type = entity_type(*)(const Registry &, entity_type);
         using follow_fn_type = entity_type(*)(const Registry &, entity_type);
-        using raw_fn_type = const entity_type *(*)(const Registry &, component_type);
         const entity_type seed = available ? (next | (entities[next] & ~traits_type::entity_mask)) : next;
         const entity_type seed = available ? (next | (entities[next] & ~traits_type::entity_mask)) : next;
 
 
         follow_fn_type follow = [](const Registry &registry, entity_type entity) -> entity_type {
         follow_fn_type follow = [](const Registry &registry, entity_type entity) -> entity_type {
@@ -1325,12 +1383,7 @@ public:
             return (next | (entities[next] & ~traits_type::entity_mask));
             return (next | (entities[next] & ~traits_type::entity_mask));
         };
         };
 
 
-        raw_fn_type raw = [](const Registry &registry, component_type component) -> const entity_type * {
-            const auto &pools = registry.pools;
-            return (component < pools.size() && std::get<0>(pools[component])) ? std::get<0>(pools[component])->data() : nullptr;
-        };
-
-        return { *this, seed, available, follow, raw };
+        return { *this, seed, available, follow };
     }
     }
 
 
     /**
     /**

+ 3 - 7
src/entt/entity/snapshot.hpp

@@ -40,21 +40,18 @@ class Snapshot final {
     friend class Registry<Entity>;
     friend class Registry<Entity>;
 
 
     using follow_fn_type = Entity(*)(const Registry<Entity> &, Entity);
     using follow_fn_type = Entity(*)(const Registry<Entity> &, Entity);
-    using raw_fn_type = const Entity *(*)(const Registry<Entity> &, typename Registry<Entity>::component_type);
 
 
-    Snapshot(const Registry<Entity> &registry, Entity seed, std::size_t size, follow_fn_type follow, raw_fn_type raw) ENTT_NOEXCEPT
+    Snapshot(const Registry<Entity> &registry, Entity seed, std::size_t size, follow_fn_type follow) ENTT_NOEXCEPT
         : registry{registry},
         : registry{registry},
           seed{seed},
           seed{seed},
           size{size},
           size{size},
-          follow{follow},
-          raw{raw}
+          follow{follow}
     {}
     {}
 
 
     template<typename Component, typename Archive>
     template<typename Component, typename Archive>
     void get(Archive &archive, const Registry<Entity> &registry) {
     void get(Archive &archive, const Registry<Entity> &registry) {
-        const auto component = registry.template type<Component>();
         const auto sz = registry.template size<Component>();
         const auto sz = registry.template size<Component>();
-        const auto *entities = raw(registry, component);
+        const auto *entities = registry.template data<Component>();
 
 
         archive(static_cast<Entity>(sz));
         archive(static_cast<Entity>(sz));
 
 
@@ -176,7 +173,6 @@ private:
     const Entity seed;
     const Entity seed;
     const std::size_t size;
     const std::size_t size;
     follow_fn_type follow;
     follow_fn_type follow;
-    raw_fn_type raw;
 };
 };
 
 
 
 

+ 20 - 0
test/entt/entity/registry.cpp

@@ -195,6 +195,26 @@ TEST(DefaultRegistry, Functionalities) {
     ASSERT_TRUE(registry.empty<int>());
     ASSERT_TRUE(registry.empty<int>());
 }
 }
 
 
+TEST(DefaultRegistry, RawData) {
+    entt::DefaultRegistry registry;
+    const entt::DefaultRegistry &cregistry = registry;
+    const auto entity = registry.create();
+
+    ASSERT_EQ(registry.raw<int>(), nullptr);
+    ASSERT_EQ(cregistry.raw<int>(), nullptr);
+    ASSERT_EQ(cregistry.data<int>(), nullptr);
+
+    registry.assign<int>(entity, 42);
+
+    ASSERT_NE(registry.raw<int>(), nullptr);
+    ASSERT_NE(cregistry.raw<int>(), nullptr);
+    ASSERT_NE(cregistry.data<int>(), nullptr);
+
+    ASSERT_EQ(*registry.raw<int>(), 42);
+    ASSERT_EQ(*cregistry.raw<int>(), 42);
+    ASSERT_EQ(*cregistry.data<int>(), entity);
+}
+
 TEST(DefaultRegistry, CreateDestroyCornerCase) {
 TEST(DefaultRegistry, CreateDestroyCornerCase) {
     entt::DefaultRegistry registry;
     entt::DefaultRegistry registry;