handle.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. #include <memory>
  2. #include <tuple>
  3. #include <type_traits>
  4. #include <utility>
  5. #include <gtest/gtest.h>
  6. #include <entt/core/type_info.hpp>
  7. #include <entt/core/type_traits.hpp>
  8. #include <entt/entity/entity.hpp>
  9. #include <entt/entity/handle.hpp>
  10. #include <entt/entity/registry.hpp>
  11. template<typename Type>
  12. struct BasicHandle: testing::Test {
  13. using type = Type;
  14. };
  15. using BasicHandleTypes = ::testing::Types<entt::handle, entt::const_handle>;
  16. TYPED_TEST_SUITE(BasicHandle, BasicHandleTypes, );
  17. TYPED_TEST(BasicHandle, Assumptions) {
  18. using handle_type = typename TestFixture::type;
  19. static_assert(std::is_trivially_copyable_v<handle_type>, "Trivially copyable type required");
  20. static_assert((std::is_trivially_assignable_v<handle_type, handle_type>), "Trivially assignable type required");
  21. static_assert(std::is_trivially_destructible_v<handle_type>, "Trivially destructible type required");
  22. }
  23. TYPED_TEST(BasicHandle, DeductionGuide) {
  24. using handle_type = typename TestFixture::type;
  25. testing::StaticAssertTypeEq<decltype(entt::basic_handle{std::declval<typename handle_type::registry_type &>(), {}}), handle_type>();
  26. }
  27. TYPED_TEST(BasicHandle, Construction) {
  28. using handle_type = typename TestFixture::type;
  29. entt::registry registry;
  30. const auto entity = registry.create();
  31. const handle_type handle{registry, entity};
  32. ASSERT_FALSE(entt::null == handle.entity());
  33. ASSERT_EQ(entity, handle);
  34. ASSERT_TRUE(handle);
  35. ASSERT_EQ(handle, (entt::handle{registry, entity}));
  36. ASSERT_EQ(handle, (entt::const_handle{registry, entity}));
  37. testing::StaticAssertTypeEq<typename handle_type::registry_type *, decltype(handle.registry())>();
  38. }
  39. TYPED_TEST(BasicHandle, Invalidation) {
  40. using handle_type = typename TestFixture::type;
  41. handle_type handle;
  42. ASSERT_FALSE(handle);
  43. ASSERT_EQ(handle.registry(), nullptr);
  44. ASSERT_EQ(handle.entity(), entt::entity{entt::null});
  45. entt::registry registry;
  46. const auto entity = registry.create();
  47. handle = {registry, entity};
  48. ASSERT_TRUE(handle);
  49. ASSERT_NE(handle.registry(), nullptr);
  50. ASSERT_NE(handle.entity(), entt::entity{entt::null});
  51. handle = {};
  52. ASSERT_FALSE(handle);
  53. ASSERT_EQ(handle.registry(), nullptr);
  54. ASSERT_EQ(handle.entity(), entt::entity{entt::null});
  55. }
  56. TEST(BasicHandle, Destruction) {
  57. using traits_type = entt::entt_traits<entt::entity>;
  58. entt::registry registry;
  59. const auto entity = registry.create();
  60. entt::handle handle{registry, entity};
  61. ASSERT_TRUE(handle);
  62. ASSERT_TRUE(handle.valid());
  63. ASSERT_NE(handle.registry(), nullptr);
  64. ASSERT_EQ(handle.entity(), entity);
  65. handle.destroy(traits_type::to_version(entity));
  66. ASSERT_FALSE(handle);
  67. ASSERT_FALSE(handle.valid());
  68. ASSERT_NE(handle.registry(), nullptr);
  69. ASSERT_EQ(registry.current(entity), typename entt::registry::version_type{});
  70. ASSERT_EQ(handle.entity(), entt::entity{entt::null});
  71. handle = entt::handle{registry, registry.create()};
  72. ASSERT_TRUE(handle);
  73. ASSERT_TRUE(handle.valid());
  74. ASSERT_NE(handle.registry(), nullptr);
  75. ASSERT_EQ(handle.entity(), entity);
  76. handle.destroy();
  77. ASSERT_FALSE(handle);
  78. ASSERT_FALSE(handle.valid());
  79. ASSERT_NE(handle.registry(), nullptr);
  80. ASSERT_NE(registry.current(entity), typename entt::registry::version_type{});
  81. ASSERT_EQ(handle.entity(), entt::entity{entt::null});
  82. }
  83. TYPED_TEST(BasicHandle, Comparison) {
  84. using handle_type = typename TestFixture::type;
  85. handle_type handle{};
  86. ASSERT_EQ(handle, entt::handle{});
  87. ASSERT_TRUE(handle == entt::handle{});
  88. ASSERT_FALSE(handle != entt::handle{});
  89. ASSERT_EQ(handle, entt::const_handle{});
  90. ASSERT_TRUE(handle == entt::const_handle{});
  91. ASSERT_FALSE(handle != entt::const_handle{});
  92. entt::registry registry;
  93. const auto entity = registry.create();
  94. handle = handle_type{registry, entity};
  95. ASSERT_NE(handle, entt::handle{});
  96. ASSERT_FALSE(handle == entt::handle{});
  97. ASSERT_TRUE(handle != entt::handle{});
  98. ASSERT_NE(handle, entt::const_handle{});
  99. ASSERT_FALSE(handle == entt::const_handle{});
  100. ASSERT_TRUE(handle != entt::const_handle{});
  101. handle = {};
  102. ASSERT_EQ(handle, entt::handle{});
  103. ASSERT_TRUE(handle == entt::handle{});
  104. ASSERT_FALSE(handle != entt::handle{});
  105. ASSERT_EQ(handle, entt::const_handle{});
  106. ASSERT_TRUE(handle == entt::const_handle{});
  107. ASSERT_FALSE(handle != entt::const_handle{});
  108. entt::registry diff;
  109. handle = {registry, entity};
  110. const handle_type other = {diff, diff.create()};
  111. ASSERT_NE(handle, other);
  112. ASSERT_FALSE(other == handle);
  113. ASSERT_TRUE(other != handle);
  114. ASSERT_EQ(handle.entity(), other.entity());
  115. ASSERT_NE(handle.registry(), other.registry());
  116. }
  117. TEST(BasicHandle, Component) {
  118. entt::registry registry;
  119. const auto entity = registry.create();
  120. const entt::handle_view<int, char, double> handle{registry, entity};
  121. ASSERT_EQ(3, handle.emplace<int>(3));
  122. ASSERT_EQ('c', handle.emplace_or_replace<char>('c'));
  123. ASSERT_EQ(.3, handle.emplace_or_replace<double>(.3));
  124. const auto &patched = handle.patch<int>([](auto &comp) { comp = 2; });
  125. ASSERT_EQ(2, patched);
  126. ASSERT_EQ('a', handle.replace<char>('a'));
  127. ASSERT_TRUE((handle.all_of<int, char, double>()));
  128. ASSERT_EQ((std::make_tuple(2, 'a', .3)), (handle.get<int, char, double>()));
  129. handle.erase<char, double>();
  130. ASSERT_TRUE(registry.storage<char>().empty());
  131. ASSERT_TRUE(registry.storage<double>().empty());
  132. ASSERT_EQ(0u, (handle.remove<char, double>()));
  133. for(auto [id, pool]: handle.storage()) {
  134. ASSERT_EQ(id, entt::type_id<int>().hash());
  135. ASSERT_TRUE(pool.contains(handle.entity()));
  136. }
  137. ASSERT_TRUE((handle.any_of<int, char, double>()));
  138. ASSERT_FALSE((handle.all_of<int, char, double>()));
  139. ASSERT_FALSE(handle.orphan());
  140. ASSERT_EQ(1u, (handle.remove<int>()));
  141. ASSERT_TRUE(registry.storage<int>().empty());
  142. ASSERT_TRUE(handle.orphan());
  143. ASSERT_EQ(2, handle.get_or_emplace<int>(2));
  144. ASSERT_EQ(2, handle.get_or_emplace<int>(1));
  145. ASSERT_EQ(2, handle.get<int>());
  146. ASSERT_EQ(2, *handle.try_get<int>());
  147. ASSERT_EQ(nullptr, handle.try_get<char>());
  148. ASSERT_EQ(nullptr, std::get<1>(handle.try_get<int, char, double>()));
  149. }
  150. TYPED_TEST(BasicHandle, FromEntity) {
  151. using handle_type = typename TestFixture::type;
  152. entt::registry registry;
  153. const auto entity = registry.create();
  154. registry.emplace<int>(entity, 2);
  155. registry.emplace<char>(entity, 'c');
  156. const handle_type handle{registry, entity};
  157. ASSERT_TRUE(handle);
  158. ASSERT_EQ(entity, handle.entity());
  159. ASSERT_TRUE((handle.template all_of<int, char>()));
  160. ASSERT_EQ(handle.template get<int>(), 2);
  161. ASSERT_EQ(handle.template get<char>(), 'c');
  162. }
  163. TEST(BasicHandle, Lifetime) {
  164. entt::registry registry;
  165. const auto entity = registry.create();
  166. auto handle = std::make_unique<entt::handle>(registry, entity);
  167. handle->emplace<int>();
  168. ASSERT_FALSE(registry.storage<int>().empty());
  169. ASSERT_NE(registry.storage<entt::entity>().free_list(), 0u);
  170. for(auto [entt]: registry.storage<entt::entity>().each()) {
  171. ASSERT_EQ(handle->entity(), entt);
  172. }
  173. handle.reset();
  174. ASSERT_FALSE(registry.storage<int>().empty());
  175. ASSERT_NE(registry.storage<entt::entity>().free_list(), 0u);
  176. }
  177. TEST(BasicHandle, ImplicitConversions) {
  178. entt::registry registry;
  179. const entt::handle handle{registry, registry.create()};
  180. const entt::const_handle const_handle = handle;
  181. const entt::handle_view<int, char> handle_view = handle;
  182. const entt::const_handle_view<int> const_handle_view = handle_view;
  183. handle.emplace<int>(2);
  184. ASSERT_EQ(handle.get<int>(), const_handle.get<int>());
  185. ASSERT_EQ(const_handle.get<int>(), handle_view.get<int>());
  186. ASSERT_EQ(handle_view.get<int>(), const_handle_view.get<int>());
  187. ASSERT_EQ(const_handle_view.get<int>(), 2);
  188. }
  189. TYPED_TEST(BasicHandle, Storage) {
  190. using handle_type = typename TestFixture::type;
  191. entt::registry registry;
  192. const auto entity = registry.create();
  193. const handle_type handle{registry, entity};
  194. testing::StaticAssertTypeEq<decltype(*handle.storage().begin()), std::pair<entt::id_type, entt::constness_as_t<entt::sparse_set, typename handle_type::registry_type> &>>();
  195. ASSERT_EQ(handle.storage().begin(), handle.storage().end());
  196. registry.storage<double>();
  197. registry.emplace<int>(entity);
  198. ASSERT_NE(handle.storage().begin(), handle.storage().end());
  199. ASSERT_EQ(++handle.storage().begin(), handle.storage().end());
  200. ASSERT_EQ(handle.storage().begin()->second.type(), entt::type_id<int>());
  201. }
  202. TYPED_TEST(BasicHandle, HandleStorageIterator) {
  203. using handle_type = typename TestFixture::type;
  204. entt::registry registry;
  205. const auto entity = registry.create();
  206. registry.emplace<int>(entity);
  207. registry.emplace<double>(entity);
  208. // required to test the find-first initialization step
  209. registry.storage<entt::entity>().erase(entity);
  210. const handle_type handle{registry, entity};
  211. auto iterable = handle.storage();
  212. ASSERT_FALSE(registry.valid(entity));
  213. ASSERT_FALSE(handle);
  214. auto end{iterable.begin()};
  215. decltype(end) begin{};
  216. begin = iterable.end();
  217. std::swap(begin, end);
  218. ASSERT_EQ(begin, iterable.cbegin());
  219. ASSERT_EQ(end, iterable.cend());
  220. ASSERT_NE(begin, end);
  221. ASSERT_EQ(begin++, iterable.begin());
  222. ASSERT_EQ(++begin, iterable.end());
  223. }