1
0

snapshot.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. #include <sstream>
  2. #include <type_traits>
  3. #include <vector>
  4. #include <gtest/gtest.h>
  5. #include <cereal/archives/json.hpp>
  6. #include <entt/core/hashed_string.hpp>
  7. #include <entt/core/type_traits.hpp>
  8. #include <entt/entity/registry.hpp>
  9. #include <entt/entity/snapshot.hpp>
  10. struct position {
  11. float x;
  12. float y;
  13. };
  14. struct timer {
  15. int duration;
  16. int elapsed{0};
  17. };
  18. struct relationship {
  19. entt::entity parent;
  20. };
  21. template<typename Archive>
  22. void serialize(Archive &archive, position &position) {
  23. archive(position.x, position.y);
  24. }
  25. template<typename Archive>
  26. void serialize(Archive &archive, timer &timer) {
  27. archive(timer.duration);
  28. }
  29. template<typename Archive>
  30. void serialize(Archive &archive, relationship &relationship) {
  31. archive(relationship.parent);
  32. }
  33. TEST(Snapshot, Full) {
  34. using namespace entt::literals;
  35. std::stringstream storage;
  36. entt::registry source;
  37. entt::registry destination;
  38. auto e0 = source.create();
  39. source.emplace<position>(e0, 16.f, 16.f);
  40. source.destroy(source.create());
  41. auto e1 = source.create();
  42. source.emplace<position>(e1, .8f, .0f);
  43. source.emplace<relationship>(e1, e0);
  44. auto e2 = source.create();
  45. auto e3 = source.create();
  46. source.emplace<timer>(e3, 1000, 100);
  47. source.emplace<entt::tag<"empty"_hs>>(e3);
  48. source.destroy(e2);
  49. auto v2 = source.current(e2);
  50. {
  51. // output finishes flushing its contents when it goes out of scope
  52. cereal::JSONOutputArchive output{storage};
  53. entt::snapshot{source}
  54. .get<entt::entity>(output)
  55. .get<position>(output)
  56. .get<timer>(output)
  57. .get<relationship>(output)
  58. .get<entt::tag<"empty"_hs>>(output);
  59. }
  60. cereal::JSONInputArchive input{storage};
  61. entt::snapshot_loader{destination}
  62. .get<entt::entity>(input)
  63. .get<position>(input)
  64. .get<timer>(input)
  65. .get<relationship>(input)
  66. .get<entt::tag<"empty"_hs>>(input);
  67. ASSERT_TRUE(destination.valid(e0));
  68. ASSERT_TRUE(destination.all_of<position>(e0));
  69. ASSERT_EQ(destination.get<position>(e0).x, 16.f);
  70. ASSERT_EQ(destination.get<position>(e0).y, 16.f);
  71. ASSERT_TRUE(destination.valid(e1));
  72. ASSERT_TRUE(destination.all_of<position>(e1));
  73. ASSERT_EQ(destination.get<position>(e1).x, .8f);
  74. ASSERT_EQ(destination.get<position>(e1).y, .0f);
  75. ASSERT_TRUE(destination.all_of<relationship>(e1));
  76. ASSERT_EQ(destination.get<relationship>(e1).parent, e0);
  77. ASSERT_FALSE(destination.valid(e2));
  78. ASSERT_EQ(destination.current(e2), v2);
  79. ASSERT_TRUE(destination.valid(e3));
  80. ASSERT_TRUE(destination.all_of<timer>(e3));
  81. ASSERT_TRUE(destination.all_of<entt::tag<"empty"_hs>>(e3));
  82. ASSERT_EQ(destination.get<timer>(e3).duration, 1000);
  83. ASSERT_EQ(destination.get<timer>(e3).elapsed, 0);
  84. }
  85. TEST(Snapshot, Continuous) {
  86. using namespace entt::literals;
  87. std::stringstream storage;
  88. entt::registry source;
  89. entt::registry destination;
  90. std::vector<entt::entity> entity;
  91. for(auto i = 0; i < 10; ++i) {
  92. entity.push_back(source.create());
  93. }
  94. for(auto entt: entity) {
  95. source.destroy(entt);
  96. }
  97. auto e0 = source.create();
  98. source.emplace<position>(e0, 0.f, 0.f);
  99. source.emplace<relationship>(e0, e0);
  100. auto e1 = source.create();
  101. source.emplace<position>(e1, 1.f, 1.f);
  102. source.emplace<relationship>(e1, e0);
  103. auto e2 = source.create();
  104. source.emplace<position>(e2, .2f, .2f);
  105. source.emplace<relationship>(e2, e0);
  106. auto e3 = source.create();
  107. source.emplace<timer>(e3, 1000, 1000);
  108. source.emplace<relationship>(e3, e2);
  109. source.emplace<entt::tag<"empty"_hs>>(e3);
  110. {
  111. // output finishes flushing its contents when it goes out of scope
  112. cereal::JSONOutputArchive output{storage};
  113. entt::snapshot{source}
  114. .get<entt::entity>(output)
  115. .get<position>(output)
  116. .get<relationship>(output)
  117. .get<timer>(output)
  118. .get<entt::tag<"empty"_hs>>(output);
  119. }
  120. cereal::JSONInputArchive input{storage};
  121. entt::continuous_loader loader{destination};
  122. auto archive = [&input, &loader](auto &value) {
  123. input(value);
  124. if constexpr(std::is_same_v<std::remove_reference_t<decltype(value)>, relationship>) {
  125. value.parent = loader.map(value.parent);
  126. }
  127. };
  128. loader
  129. .get<entt::entity>(input)
  130. .get<position>(input)
  131. .get<relationship>(archive)
  132. .get<timer>(input)
  133. .get<entt::tag<"empty"_hs>>(input);
  134. ASSERT_FALSE(destination.valid(e0));
  135. ASSERT_TRUE(loader.contains(e0));
  136. auto l0 = loader.map(e0);
  137. ASSERT_TRUE(destination.valid(l0));
  138. ASSERT_TRUE(destination.all_of<position>(l0));
  139. ASSERT_EQ(destination.get<position>(l0).x, 0.f);
  140. ASSERT_EQ(destination.get<position>(l0).y, 0.f);
  141. ASSERT_TRUE(destination.all_of<relationship>(l0));
  142. ASSERT_EQ(destination.get<relationship>(l0).parent, l0);
  143. ASSERT_FALSE(destination.valid(e1));
  144. ASSERT_TRUE(loader.contains(e1));
  145. auto l1 = loader.map(e1);
  146. ASSERT_TRUE(destination.valid(l1));
  147. ASSERT_TRUE(destination.all_of<position>(l1));
  148. ASSERT_EQ(destination.get<position>(l1).x, 1.f);
  149. ASSERT_EQ(destination.get<position>(l1).y, 1.f);
  150. ASSERT_TRUE(destination.all_of<relationship>(l1));
  151. ASSERT_EQ(destination.get<relationship>(l1).parent, l0);
  152. ASSERT_FALSE(destination.valid(e2));
  153. ASSERT_TRUE(loader.contains(e2));
  154. auto l2 = loader.map(e2);
  155. ASSERT_TRUE(destination.valid(l2));
  156. ASSERT_TRUE(destination.all_of<position>(l2));
  157. ASSERT_EQ(destination.get<position>(l2).x, .2f);
  158. ASSERT_EQ(destination.get<position>(l2).y, .2f);
  159. ASSERT_TRUE(destination.all_of<relationship>(l2));
  160. ASSERT_EQ(destination.get<relationship>(l2).parent, l0);
  161. ASSERT_FALSE(destination.valid(e3));
  162. ASSERT_TRUE(loader.contains(e3));
  163. auto l3 = loader.map(e3);
  164. ASSERT_TRUE(destination.valid(l3));
  165. ASSERT_TRUE(destination.all_of<timer>(l3));
  166. ASSERT_EQ(destination.get<timer>(l3).duration, 1000);
  167. ASSERT_EQ(destination.get<timer>(l3).elapsed, 0);
  168. ASSERT_TRUE(destination.all_of<relationship>(l3));
  169. ASSERT_EQ(destination.get<relationship>(l3).parent, l2);
  170. ASSERT_TRUE(destination.all_of<entt::tag<"empty"_hs>>(l3));
  171. }