Michele Caini 7 лет назад
Родитель
Сommit
cb9a147fff
6 измененных файлов с 121 добавлено и 26 удалено
  1. 20 8
      AUTHORS
  2. 4 1
      TODO
  3. 50 13
      src/entt/entity/registry.hpp
  4. 3 0
      test/benchmark/benchmark.cpp
  5. 43 3
      test/entt/entity/registry.cpp
  6. 1 1
      test/entt/entity/sparse_set.cpp

+ 20 - 8
AUTHORS

@@ -1,16 +1,28 @@
 # Author
 
-Michele Caini aka skypjack
+skypjack
 
 # Contributors
 
-Paolo Monteverde aka morbo84
-David Nerjes aka DavidHamburg
-Indi Kernick aka Kerndog73
-Malte Müller-Rowold aka m-waka
-Richard Caseres aka richardbmx
-Michael Keck aka Croydon
+BenediktConze
+bjadamson
+Croydon
+dbacchet
+DonKult
+drglove
+eugeneko
+gale83
+ghost
+Milerius
+morbo84
+m-waka
+Kerndog73
+pgruenbacher
+prowolf
+vblanco20-1
+willtunnels
+w1th0utnam3
 
 # Special thanks for patrons
 
-Arn aka ArnCarveris
+ArnCarveris

+ 4 - 1
TODO

@@ -18,9 +18,12 @@
 * destroy overload that accepts a couple of iterators (see create)
 * allow for built-in parallel each if possible
 * add on-the-fly sort functionality (is it possible?)
-* write/show how to work with missing components using and-strategies
 * write/show how to create an archetype based model on top of EnTT
 * mention hunter in the readme file, section packaging tools
 * monostate: make constraint trivially copyable due to atomic optional
 * monostate: use template variable to avoid {}
 * travis + windows is now available, try it
+* hashed string: static (constexpr) member function to_value for direct hashing
+* entity: simplify get functions so as to generate less symbols for multiple components
+* events on replace, so that one can track updated components? indagate impact
+* add merge functionality for type list

+ 50 - 13
src/entt/entity/registry.hpp

@@ -178,19 +178,6 @@ public:
     /*! @brief Type of sink for the given component. */
     using sink_type = typename component_signal_type::sink_type;
 
-    /*! @brief Default constructor. */
-    registry() ENTT_NOEXCEPT = default;
-
-    /*! @brief Copying a registry isn't allowed. */
-    registry(const registry &) = delete;
-    /*! @brief Default move constructor. */
-    registry(registry &&) = default;
-
-    /*! @brief Copying a registry isn't allowed. @return This registry. */
-    registry & operator=(const registry &) = delete;
-    /*! @brief Default move assignment operator. @return This registry. */
-    registry & operator=(registry &&) = default;
-
     /**
      * @brief Returns the numeric identifier of a type of component at runtime.
      *
@@ -208,6 +195,19 @@ public:
         return component_family::type<Component>;
     }
 
+    /*! @brief Default constructor. */
+    registry() ENTT_NOEXCEPT = default;
+
+    /*! @brief Copying a registry isn't allowed. */
+    registry(const registry &) = delete;
+    /*! @brief Default move constructor. */
+    registry(registry &&) = default;
+
+    /*! @brief Copying a registry isn't allowed. @return This registry. */
+    registry & operator=(const registry &) = delete;
+    /*! @brief Default move assignment operator. @return This registry. */
+    registry & operator=(registry &&) = default;
+
     /**
      * @brief Returns the number of existing components of the given type.
      * @tparam Component Type of component of which to return the size.
@@ -1404,6 +1404,43 @@ public:
         return { std::move(set) };
     }
 
+    /**
+     * @brief Clones the given components and all the entity identifiers.
+     *
+     * The components must be copiable for obvious reasons. The entities
+     * maintain their versions once copied.
+     *
+     * @note
+     * There isn't an efficient way to know if all the entities are assigned at
+     * least one component once copied. Therefore, there may be orphans. It is
+     * up to the caller to clean up the registry if necessary.
+     *
+     * @warning
+     * This function requires that the registry be empty. In case it isn't, all
+     * the data will be automatically deleted beforehand.
+     *
+     * @tparam Component Types of components to clone.
+     * @param reg A valid reference to a source registry.
+     */
+    template<typename... Component>
+    void clone(const registry &reg) {
+        *this = {};
+
+        (assure<Component>(), ...);
+        (reserve<Component>(reg.size<Component>()), ...);
+
+        (std::copy(reg.raw<Component>(), reg.raw<Component>() + reg.size<Component>(), pool<Component>().raw()), ...);
+        // double lambda function used to work around a bug of gcc7
+        (std::for_each(reg.data<Component>(), reg.data<Component>() + reg.size<Component>(), ([](auto *cpool) {
+            return [cpool](const auto entity) { cpool->construct(entity); };
+        })(pools[component_family::type<Component>].get())), ...);
+
+        next = reg.next;
+        available = reg.available;
+        entities.resize(reg.entities.size());
+        std::copy(reg.entities.cbegin(), reg.entities.cend(), entities.begin());
+    }
+
     /**
      * @brief Returns a temporary object to use to create snapshots.
      *

+ 3 - 0
test/benchmark/benchmark.cpp

@@ -245,6 +245,7 @@ TEST(Benchmark, IterateTwoComponents1MOne) {
 
 TEST(Benchmark, IterateTwoComponentsPersistent1M) {
     entt::registry<> registry;
+    registry.persistent_view<position, velocity>();
 
     std::cout << "Iterating over 1000000 entities, two components, persistent view" << std::endl;
 
@@ -439,6 +440,7 @@ TEST(Benchmark, IterateFiveComponents1MOne) {
 
 TEST(Benchmark, IterateFiveComponentsPersistent1M) {
     entt::registry<> registry;
+    registry.persistent_view<position, velocity, comp<1>, comp<2>, comp<3>>();
 
     std::cout << "Iterating over 1000000 entities, five components, persistent view" << std::endl;
 
@@ -687,6 +689,7 @@ TEST(Benchmark, IterateTenComponents1MOne) {
 
 TEST(Benchmark, IterateTenComponentsPersistent1M) {
     entt::registry<> registry;
+    registry.persistent_view<position, velocity, comp<1>, comp<2>, comp<3>, comp<4>, comp<5>, comp<6>, comp<7>, comp<8>>();
 
     std::cout << "Iterating over 1000000 entities, ten components, persistent view" << std::endl;
 

+ 43 - 3
test/entt/entity/registry.cpp

@@ -748,18 +748,18 @@ TEST(Registry, PersistentViewSortInterleaved) {
     entt::registry<> registry;
     const auto view = registry.persistent_view<int, char>();
 
-    auto e0 = registry.create();
+    const auto e0 = registry.create();
     registry.assign<int>(e0, 0);
     registry.assign<char>(e0, '0');
 
-    auto e1 = registry.create();
+    const auto e1 = registry.create();
     registry.assign<int>(e1, 1);
     registry.assign<char>(e1, '1');
 
     registry.sort<int>([](auto lhs, auto rhs) { return lhs > rhs; });
     registry.sort<char>([](auto lhs, auto rhs) { return lhs < rhs; });
 
-    auto e2 = registry.create();
+    const auto e2 = registry.create();
     registry.assign<int>(e2, 2);
     registry.assign<char>(e2, '2');
 
@@ -776,3 +776,43 @@ TEST(Registry, PersistentViewSortInterleaved) {
         }
     });
 }
+
+TEST(Registry, Clone) {
+    entt::registry<> registry;
+    entt::registry<> other;
+
+    const auto entity = other.create();
+    other.assign<int>(entity, 42);
+    other.assign<char>(entity, 'c');
+
+    registry.destroy(registry.create());
+
+    const auto e0 = registry.create();
+    registry.assign<int>(e0, 0);
+    registry.assign<double>(e0, 0.0);
+
+    const auto e1 = registry.create();
+    registry.assign<int>(e1, 1);
+    registry.assign<char>(e1, '1');
+    registry.assign<double>(e1, 1.1);
+
+    const auto e2 = registry.create();
+    registry.assign<int>(e2, 2);
+    registry.assign<char>(e2, '2');
+
+    registry.destroy(e1);
+    other.clone<int, char>(registry);
+
+    ASSERT_FALSE(other.valid(entity));
+    ASSERT_TRUE(other.valid(e0));
+    ASSERT_FALSE(other.valid(e1));
+    ASSERT_TRUE(other.valid(e2));
+
+    ASSERT_TRUE((other.has<int>(e0)));
+    ASSERT_FALSE((other.has<double>(e0)));
+    ASSERT_TRUE((other.has<int, char>(e2)));
+
+    ASSERT_EQ(other.get<int>(e0), 0);
+    ASSERT_EQ(other.get<int>(e2), 2);
+    ASSERT_EQ(other.get<char>(e2), '2');
+}

+ 1 - 1
test/entt/entity/sparse_set.cpp

@@ -848,7 +848,7 @@ TEST(SparseSetWithType, MoveOnlyComponent) {
         move_only_component & operator=(move_only_component &&) = default;
     };
 
-    // it's purpose is to ensure that move only components are always accepted
+    // the purpose is to ensure that move only components are always accepted
     entt::sparse_set<std::uint64_t, move_only_component> set;
     (void)set;
 }