1
0

entity_copy.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #include <gtest/gtest.h>
  2. #include <entt/core/hashed_string.hpp>
  3. #include <entt/core/utility.hpp>
  4. #include <entt/entity/registry.hpp>
  5. #include <entt/entity/storage.hpp>
  6. #include <entt/meta/factory.hpp>
  7. #include <entt/meta/meta.hpp>
  8. #include <entt/meta/policy.hpp>
  9. #include <entt/meta/resolve.hpp>
  10. struct EntityCopy: testing::Test {
  11. enum class my_entity : entt::id_type {};
  12. enum class other_entity : entt::id_type {};
  13. template<typename Type>
  14. // NOLINTNEXTLINE(*-exception-escape)
  15. struct meta_mixin: Type {
  16. using allocator_type = Type::allocator_type;
  17. using element_type = Type::element_type;
  18. explicit meta_mixin(const allocator_type &allocator);
  19. };
  20. void TearDown() override {
  21. entt::meta_reset();
  22. }
  23. };
  24. template<typename Type>
  25. struct entt::storage_type<Type, EntityCopy::my_entity> {
  26. using type = EntityCopy::meta_mixin<basic_storage<Type, EntityCopy::my_entity>>;
  27. };
  28. template<typename Type>
  29. struct entt::storage_type<Type, EntityCopy::other_entity> {
  30. using type = EntityCopy::meta_mixin<basic_storage<Type, EntityCopy::other_entity>>;
  31. };
  32. template<typename Type>
  33. EntityCopy::meta_mixin<Type>::meta_mixin(const allocator_type &allocator)
  34. : Type{allocator} {
  35. using namespace entt::literals;
  36. entt::meta_factory<element_type>{}
  37. // cross registry, same type
  38. .template func<entt::overload<entt::storage_for_t<element_type, my_entity> &(const entt::id_type)>(&entt::basic_registry<my_entity>::storage<element_type>), entt::as_ref_t>("storage"_hs)
  39. // cross registry, different types
  40. .template func<entt::overload<entt::storage_for_t<element_type, other_entity> &(const entt::id_type)>(&entt::basic_registry<other_entity>::storage<element_type>), entt::as_ref_t>("storage"_hs);
  41. }
  42. TEST_F(EntityCopy, SameRegistry) {
  43. using namespace entt::literals;
  44. entt::basic_registry<my_entity> registry{};
  45. auto &&custom = registry.storage<double>("custom"_hs);
  46. const auto src = registry.create();
  47. const auto dst = registry.create();
  48. custom.emplace(src, 1.);
  49. registry.emplace<int>(src, 2);
  50. registry.emplace<char>(src, 'c');
  51. ASSERT_EQ(registry.storage<my_entity>().size(), 2u);
  52. ASSERT_TRUE(custom.contains(src));
  53. ASSERT_FALSE(custom.contains(dst));
  54. ASSERT_TRUE((registry.all_of<int, char>(src)));
  55. ASSERT_FALSE((registry.any_of<int, char>(dst)));
  56. for(auto [id, storage]: registry.storage()) {
  57. // discard the custom storage because why not, this is just an example after all
  58. if(id != "custom"_hs && storage.contains(src)) {
  59. storage.push(dst, storage.value(src));
  60. }
  61. }
  62. ASSERT_EQ(registry.storage<my_entity>().size(), 2u);
  63. ASSERT_TRUE(custom.contains(src));
  64. ASSERT_FALSE(custom.contains(dst));
  65. ASSERT_TRUE((registry.all_of<int, char>(src)));
  66. ASSERT_TRUE((registry.all_of<int, char>(dst)));
  67. ASSERT_EQ(registry.get<int>(dst), 2);
  68. ASSERT_EQ(registry.get<char>(dst), 'c');
  69. }
  70. TEST_F(EntityCopy, CrossRegistry) {
  71. using namespace entt::literals;
  72. entt::basic_registry<my_entity> src{};
  73. entt::basic_registry<other_entity> dst{};
  74. const auto entity = src.create();
  75. const auto copy = dst.create();
  76. src.emplace<int>(entity, 2);
  77. src.emplace<char>(entity, 'c');
  78. ASSERT_EQ(src.storage<my_entity>().size(), 1u);
  79. ASSERT_EQ(dst.storage<other_entity>().size(), 1u);
  80. ASSERT_TRUE((src.all_of<int, char>(entity)));
  81. ASSERT_FALSE((dst.template all_of<int, char>(copy)));
  82. for(auto [id, storage]: src.storage()) {
  83. if(storage.contains(entity)) {
  84. auto *other = dst.storage(id);
  85. if(other == nullptr) {
  86. using namespace entt::literals;
  87. entt::resolve(storage.info()).invoke("storage"_hs, {}, entt::forward_as_meta(dst), id);
  88. other = dst.storage(id);
  89. }
  90. other->push(copy, storage.value(entity));
  91. }
  92. }
  93. ASSERT_EQ(src.storage<my_entity>().size(), 1u);
  94. ASSERT_EQ(dst.storage<other_entity>().size(), 1u);
  95. ASSERT_TRUE((src.all_of<int, char>(entity)));
  96. ASSERT_TRUE((dst.template all_of<int, char>(copy)));
  97. ASSERT_EQ(dst.template get<int>(copy), 2);
  98. ASSERT_EQ(dst.template get<char>(copy), 'c');
  99. }