فهرست منبع

review stomp & spawn (close #306)

Michele Caini 6 سال پیش
والد
کامیت
454f072f13
3فایلهای تغییر یافته به همراه54 افزوده شده و 40 حذف شده
  1. 4 4
      TODO
  2. 30 35
      src/entt/entity/registry.hpp
  3. 20 1
      test/entt/entity/registry.cpp

+ 4 - 4
TODO

@@ -26,8 +26,8 @@ TODO
   - we should always resolve by looking into the list of types when working across boundaries, no direct resolve
 * nested groups: AB/ABC/ABCD/... (hints: sort, check functions)
 * snapshot rework/deprecation
-  * create(hint: entity) -> force-create
-  * assign<T...>(first, last)
+  - create(hint: entity) -> force-create
+  - assign<T...>(first, last)
 * use unordered_map for named pools and context variables:
-  * use direct access (pool-like) also for context variables
-  * improves multi-stomp
+  - use direct access (pool-like) also for context variables
+  - improves multi-stomp

+ 30 - 35
src/entt/entity/registry.hpp

@@ -218,6 +218,24 @@ class basic_registry {
         }
     }
 
+    auto generate() {
+        Entity entt;
+
+        if(destroyed == null) {
+            entt = entities.emplace_back(entity_type(entities.size()));
+            // traits_type::entity_mask is reserved to allow for null identifiers
+            ENTT_ASSERT(to_integer(entt) < traits_type::entity_mask);
+        } else {
+            const auto curr = to_integer(destroyed);
+            const auto version = to_integer(entities[curr]) & (traits_type::version_mask << traits_type::entity_shift);
+            destroyed = entity_type{to_integer(entities[curr]) & traits_type::entity_mask};
+            entt = entity_type{curr | version};
+            entities[curr] = entt;
+        }
+
+        return entt;
+    }
+
     void release(const Entity entity) {
         // lengthens the implicit list of destroyed entities
         const auto entt = to_integer(entity) & traits_type::entity_mask;
@@ -557,14 +575,11 @@ public:
      */
     template<typename... Component>
     auto create() {
-        entity_type entities[1]{};
-
         if constexpr(sizeof...(Component) == 0) {
-            create<Component...>(std::begin(entities), std::end(entities));
-            return entities[0];
+            return generate();
         } else {
-            auto it = create<Component...>(std::begin(entities), std::end(entities));
-            return std::tuple<entity_type, decltype(assign<Component>(entities[0]))...>{entities[0], *std::get<typename pool_type<Component>::iterator_type>(it)...};
+            const entity_type entt = generate();
+            return std::tuple<entity_type, decltype(assign<Component>({}))...>{entt, assign<Component>(entt)...};
         }
     }
 
@@ -586,25 +601,7 @@ public:
      */
     template<typename... Component, typename It>
     auto create(It first, It last) {
-        static_assert(std::is_convertible_v<entity_type, typename std::iterator_traits<It>::value_type>);
-
-        std::generate(first, last, [this]() {
-            entity_type curr;
-
-            if(destroyed == null) {
-                curr = entities.emplace_back(entity_type(entities.size()));
-                // traits_type::entity_mask is reserved to allow for null identifiers
-                ENTT_ASSERT(to_integer(curr) < traits_type::entity_mask);
-            } else {
-                const auto entt = to_integer(destroyed);
-                const auto version = to_integer(entities[entt]) & (traits_type::version_mask << traits_type::entity_shift);
-                destroyed = entity_type{to_integer(entities[entt]) & traits_type::entity_mask};
-                curr = entity_type{entt | version};
-                entities[entt] = curr;
-            }
-
-            return curr;
-        });
+        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())
@@ -632,10 +629,10 @@ public:
      * @return A valid entity identifier.
      */
     template<typename... Component, typename... Exclude>
-    auto create(entity_type src, basic_registry &other, exclude_t<Exclude...> = {}) {
-        entity_type entities[1]{};
-        create<Component...>(std::begin(entities), std::end(entities), src, other, exclude<Exclude...>);
-        return entities[0];
+    entity_type create(entity_type src, basic_registry &other, exclude_t<Exclude...> = {}) {
+        const auto entt = create();
+        stomp<Component...>(entt, src, other, exclude<Exclude...>);
+        return entt;
     }
 
     /**
@@ -666,8 +663,8 @@ public:
         if constexpr(sizeof...(Component) == 0) {
             stomp<Component...>(first, last, src, other, exclude<Exclude...>);
         } else {
-            static_assert(sizeof...(Component) == 0 || sizeof...(Exclude) == 0);
-            (assure<Component>()->batch(*this, first, last, other.get<Component>(src)), ...);
+            static_assert(sizeof...(Exclude) == 0);
+            (assure<Component>()->batch(*this, std::make_reverse_iterator(last), std::make_reverse_iterator(first), other.get<Component>(src)), ...);
         }
     }
 
@@ -1499,7 +1496,6 @@ public:
      */
     template<typename It>
     entt::basic_runtime_view<Entity> runtime_view(It first, It last) const {
-        static_assert(std::is_same_v<typename std::iterator_traits<It>::value_type, component>);
         std::vector<const sparse_set<Entity> *> set(std::distance(first, last));
 
         std::transform(first, last, set.begin(), [this](const component ctype) {
@@ -1613,8 +1609,8 @@ public:
      */
     template<typename... Component, typename... Exclude>
     void stomp(const entity_type dst, const entity_type src, basic_registry &other, exclude_t<Exclude...> = {}) {
-        const entity_type entities[1]{dst};
-        stomp<Component...>(std::begin(entities), std::end(entities), src, other, exclude<Exclude...>);
+        const entity_type entt[1]{dst};
+        stomp<Component...>(std::begin(entt), std::end(entt), src, other, exclude<Exclude...>);
     }
 
     /**
@@ -1632,7 +1628,6 @@ public:
     template<typename... Component, typename It, typename... Exclude>
     void stomp(It first, It last, const entity_type src, basic_registry &other, exclude_t<Exclude...> = {}) {
         static_assert(sizeof...(Component) == 0 || sizeof...(Exclude) == 0);
-        static_assert(std::conjunction_v<std::is_copy_constructible<Component>...>);
 
         for(auto pos = other.pools.size(); pos; --pos) {
             const auto &pdata = other.pools[pos-1];

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

@@ -1548,7 +1548,7 @@ TEST(Registry, StompMulti) {
 
     entt::entity entities[2];
     registry.create(std::begin(entities), std::end(entities));
-    registry.stomp(std::begin(entities), std::end(entities), prototype, registry);
+    registry.stomp<int, char, double>(std::begin(entities), std::end(entities), prototype, registry);
 
     ASSERT_TRUE((registry.has<int, char>(entities[0])));
     ASSERT_TRUE((registry.has<int, char>(entities[1])));
@@ -1556,6 +1556,25 @@ TEST(Registry, StompMulti) {
     ASSERT_EQ(registry.get<char>(entities[1]), 'c');
 }
 
+TEST(Registry, StompExcludeMulti) {
+    entt::registry registry;
+
+    const auto prototype = registry.create();
+    registry.assign<int>(prototype, 3);
+    registry.assign<char>(prototype, 'c');
+
+    entt::entity entities[2];
+    registry.create(std::begin(entities), std::end(entities));
+    registry.stomp(std::begin(entities), std::end(entities), prototype, registry, entt::exclude<char>);
+
+    ASSERT_TRUE((registry.has<int>(entities[0])));
+    ASSERT_TRUE((registry.has<int>(entities[1])));
+    ASSERT_FALSE((registry.has<char>(entities[0])));
+    ASSERT_FALSE((registry.has<char>(entities[1])));
+    ASSERT_EQ(registry.get<int>(entities[0]), 3);
+    ASSERT_EQ(registry.get<int>(entities[1]), 3);
+}
+
 TEST(Registry, StompMoveOnlyComponent) {
     entt::registry registry;