Michele Caini 6 лет назад
Родитель
Сommit
74d901b7ae
5 измененных файлов с 67 добавлено и 9 удалено
  1. 6 3
      TODO
  2. 3 0
      docs/md/entity.md
  3. 22 4
      src/entt/entity/registry.hpp
  4. 1 1
      src/entt/entity/storage.hpp
  5. 35 1
      test/entt/entity/registry.cpp

+ 6 - 3
TODO

@@ -26,15 +26,18 @@
   - use direct access (pool-like) also for context variables
   - allow for key/value variables where the key is an ENTT_ID_TYPE
   - improves multi-stomp
-* multi component registry::remove and some others?
-  - auto foo(It first, It last = entity_type{null})
 * range based registry::remove and some others?
 * add examples (and credits) from @alanjfs :)
 * explore the possibility to wrap other backend with a XHandler component
 * use [[nodiscard]] consistently for safety purposes
 * static reflection, hint: template<> meta_type_t<Type>: meta_descriptor<name, func..., props..., etc...>
 * null support for entt::component
-* add ENTT_CUSTOM_NAMED_TYPE for custom names
+* ENTT_NAMED_TYPE -> ENTT_EXPORT and add also ENTT_EXPORT_WITH_NAME
 * Make another attempt to overcome named types
 * meta: members+class as fake functions, is it possible?
+* meta: are fake types not backed by actual types possible?
 * named types: almost-stable index optimization for direct access to pools, no more linear searches
+* multi component registry::remove and some others?
+  - range destroy and range stomp -> destroy_each, stomp_each
+  - remove create overload for spwaning
+  - clean up stomp functions

+ 3 - 0
docs/md/entity.md

@@ -235,6 +235,9 @@ vel.dx = 0.;
 vel.dy = 0.;
 ```
 
+Similarly, the `assign_each` member function accepts two iterators, that is a
+range of entities to which to assign the component.
+
 If an entity already has the given component, the `replace` member function
 template can be used to replace it:
 

+ 22 - 4
src/entt/entity/registry.hpp

@@ -592,8 +592,8 @@ public:
         std::generate(first, last, [this]() { return generate(); });
 
         if constexpr(sizeof...(Component) > 0) {
-            // the reverse iterators guarantee the ordering between entities and components (hint: the pools return begin())
-            return std::make_tuple(assure<Component>()->batch(*this, std::make_reverse_iterator(last), std::make_reverse_iterator(first))...);
+            const auto distance = std::distance(first, last);
+            return std::make_tuple(std::make_reverse_iterator(assure<Component>()->batch(*this, first, last) + distance)...);
         }
     }
 
@@ -653,7 +653,7 @@ public:
             stomp<Component...>(first, last, src, other, exclude<Exclude...>);
         } else {
             static_assert(sizeof...(Exclude) == 0);
-            (assure<Component>()->batch(*this, std::make_reverse_iterator(last), std::make_reverse_iterator(first), other.get<Component>(src)), ...);
+            (assure<Component>()->batch(*this, first, last, other.get<Component>(src)), ...);
         }
     }
 
@@ -729,11 +729,29 @@ public:
      * @return A reference to the newly created component.
      */
     template<typename Component, typename... Args>
-    decltype(auto) assign(const entity_type entity, [[maybe_unused]] Args &&... args) {
+    decltype(auto) assign(const entity_type entity, Args &&... args) {
         ENTT_ASSERT(valid(entity));
         return assure<Component>()->assign(*this, entity, std::forward<Args>(args)...);
     }
 
+    /**
+     * @brief Assigns each entity in a range the given component.
+     *
+     * @sa assign
+     *
+     * @tparam Component Type of component to create.
+     * @tparam It Type of input iterator.
+     * @tparam Args Types of arguments to use to construct the component.
+     * @param first An iterator to the first element of the range to assign.
+     * @param last An iterator past the last element of the range to assign.
+     * @param args Parameters to use to initialize the component.
+     * @return An iterator to the list of components just created.
+     */
+    template<typename Component, typename It, typename... Args>
+    auto assign_each(It first, It last, Args &&... args) {
+        return std::make_reverse_iterator(assure<Component>()->batch(*this, first, last, std::forward<Args>(args)...) + std::distance(first, last));
+    }
+
     /**
      * @brief Removes the given component from an entity.
      *

+ 1 - 1
src/entt/entity/storage.hpp

@@ -353,7 +353,7 @@ public:
      * same of the entities.
      */
     template<typename It, typename... Args>
-    iterator_type batch(It first, It last, Args &&... args) {
+    iterator_type batch(It first, It last, [[maybe_unused]] Args &&... args) {
         if constexpr(sizeof...(Args) == 0) {
             instances.resize(instances.size() + std::distance(first, last));
         } else {

+ 35 - 1
test/entt/entity/registry.cpp

@@ -1024,7 +1024,7 @@ TEST(Registry, Signals) {
     ASSERT_EQ(listener.last, e0);
 }
 
-TEST(Registry, DestroyByComponents) {
+TEST(Registry, RangeDestroy) {
     entt::registry registry;
 
     const auto e0 = registry.create();
@@ -1063,6 +1063,40 @@ TEST(Registry, DestroyByComponents) {
     ASSERT_FALSE(registry.valid(e2));
 }
 
+TEST(Registry, RangeAssign) {
+    entt::registry registry;
+
+    const auto e0 = registry.create();
+    const auto e1 = registry.create();
+    const auto e2 = registry.create();
+
+    registry.assign<int>(e0);
+    registry.assign<char>(e0);
+    registry.assign<double>(e0);
+
+    registry.assign<int>(e1);
+    registry.assign<char>(e1);
+
+    registry.assign<int>(e2);
+
+    ASSERT_FALSE(registry.has<float>(e0));
+    ASSERT_FALSE(registry.has<float>(e1));
+    ASSERT_FALSE(registry.has<float>(e2));
+
+    const auto view = registry.view<int, char>();
+    auto it = registry.assign_each<float>(view.begin(), view.end());
+
+    ASSERT_TRUE(registry.has<float>(e0));
+    ASSERT_TRUE(registry.has<float>(e1));
+    ASSERT_FALSE(registry.has<float>(e2));
+
+    *it = 0.f;
+    *(it+1) = 1.f;
+
+    ASSERT_EQ(registry.get<float>(*view.begin()), 0.f);
+    ASSERT_EQ(registry.get<float>(*(++view.begin())), 1.f);
+}
+
 TEST(Registry, CreateManyEntitiesAtOnce) {
     entt::registry registry;
     entt::entity entities[3];