Explorar o código

entity: fully support reserved bits on identifiers

Michele Caini %!s(int64=2) %!d(string=hai) anos
pai
achega
3db20d0aa5
Modificáronse 2 ficheiros con 39 adicións e 5 borrados
  1. 3 4
      src/entt/entity/entity.hpp
  2. 36 1
      test/entt/entity/entity.cpp

+ 3 - 4
src/entt/entity/entity.hpp

@@ -114,7 +114,7 @@ public:
      * @return The integral representation of the version part.
      */
     [[nodiscard]] static constexpr version_type to_version(const value_type value) noexcept {
-        return static_cast<version_type>(to_integral(value) >> length);
+        return (static_cast<version_type>(to_integral(value) >> length) & version_mask);
     }
 
     /**
@@ -138,7 +138,7 @@ public:
      * @return A properly constructed identifier.
      */
     [[nodiscard]] static constexpr value_type construct(const entity_type entity, const version_type version) noexcept {
-        return value_type{(entity & entity_mask) | (static_cast<entity_type>(version) << length)};
+        return value_type{(entity & entity_mask) | (static_cast<entity_type>(version & version_mask) << length)};
     }
 
     /**
@@ -152,8 +152,7 @@ public:
      * @return A properly constructed identifier.
      */
     [[nodiscard]] static constexpr value_type combine(const entity_type lhs, const entity_type rhs) noexcept {
-        constexpr auto mask = (version_mask << length);
-        return value_type{(lhs & entity_mask) | (rhs & mask)};
+        return value_type{(lhs & entity_mask) | (rhs & (version_mask << length))};
     }
 };
 

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

@@ -7,7 +7,7 @@ struct custom_entity_traits {
     using entity_type = std::uint32_t;
     using version_type = std::uint16_t;
     static constexpr entity_type entity_mask = 0x3FFFF; // 18b
-    static constexpr entity_type version_mask = 0x3FFF; // 14b
+    static constexpr entity_type version_mask = 0x0FFF; // 12b
 };
 
 template<>
@@ -57,6 +57,41 @@ TYPED_TEST(Entity, Traits) {
 
     ASSERT_EQ(traits_type::next(entt::tombstone), traits_type::construct(entt::null, {}));
     ASSERT_EQ(traits_type::next(entt::null), traits_type::construct(entt::null, {}));
+
+    if constexpr(traits_type::to_integral(tombstone) != ~traits_type::entity_type{}) {
+        // test reserved bits, if any
+        constexpr entity_type reserved{traits_type::to_integral(entity) | (traits_type::to_integral(tombstone) + 1u)};
+
+        ASSERT_NE(reserved, entity);
+
+        ASSERT_NE(traits_type::to_integral(null), ~traits_type::entity_type{});
+        ASSERT_NE(traits_type::to_integral(tombstone), ~traits_type::entity_type{});
+
+        ASSERT_EQ(traits_type::to_entity(reserved), traits_type::to_entity(entity));
+        ASSERT_EQ(traits_type::to_version(reserved), traits_type::to_version(entity));
+
+        ASSERT_EQ(traits_type::to_version(null), traits_type::version_mask);
+        ASSERT_EQ(traits_type::to_version(tombstone), traits_type::version_mask);
+
+        ASSERT_EQ(traits_type::to_version(traits_type::next(null)), 0u);
+        ASSERT_EQ(traits_type::to_version(traits_type::next(tombstone)), 0u);
+
+        ASSERT_EQ(traits_type::construct(traits_type::to_integral(entity), traits_type::version_mask + 1u), entity_type{traits_type::to_entity(entity)});
+
+        ASSERT_EQ(traits_type::construct(traits_type::to_integral(null), traits_type::to_version(null) + 1u), entity_type{traits_type::to_entity(null)});
+        ASSERT_EQ(traits_type::construct(traits_type::to_integral(tombstone), traits_type::to_version(tombstone) + 1u), entity_type{traits_type::to_entity(tombstone)});
+
+        ASSERT_EQ(traits_type::next(reserved), traits_type::next(entity));
+
+        ASSERT_EQ(traits_type::next(null), traits_type::combine(null, entity_type{}));
+        ASSERT_EQ(traits_type::next(tombstone), traits_type::combine(tombstone, entity_type{}));
+
+        ASSERT_EQ(traits_type::combine(entity, reserved), entity);
+        ASSERT_NE(traits_type::combine(entity, reserved), reserved);
+
+        ASSERT_EQ(traits_type::combine(reserved, entity), entity);
+        ASSERT_NE(traits_type::combine(reserved, entity), reserved);
+    }
 }
 
 TYPED_TEST(Entity, Null) {