snapshot.cpp 5.7 KB

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