snapshot.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. #include <tuple>
  2. #include <queue>
  3. #include <vector>
  4. #include <gtest/gtest.h>
  5. #include <entt/entity/registry.hpp>
  6. template<typename Storage>
  7. struct OutputArchive {
  8. OutputArchive(Storage &storage)
  9. : storage{storage}
  10. {}
  11. template<typename Value>
  12. void operator()(const Value &value) {
  13. std::get<std::queue<Value>>(storage).push(value);
  14. }
  15. private:
  16. Storage &storage;
  17. };
  18. template<typename Storage>
  19. struct InputArchive {
  20. InputArchive(Storage &storage)
  21. : storage{storage}
  22. {}
  23. template<typename Value>
  24. void operator()(Value &value) {
  25. auto &queue = std::get<std::queue<Value>>(storage);
  26. value = queue.front();
  27. queue.pop();
  28. }
  29. private:
  30. Storage &storage;
  31. };
  32. struct AComponent {};
  33. struct AnotherComponent {
  34. int key;
  35. int value;
  36. };
  37. struct WhatAComponent {
  38. entt::DefaultRegistry::entity_type bar;
  39. std::vector<entt::DefaultRegistry::entity_type> quux;
  40. };
  41. TEST(Snapshot, Dump) {
  42. entt::DefaultRegistry registry;
  43. const auto e0 = registry.create();
  44. registry.assign<int>(e0, 42);
  45. registry.assign<char>(e0, 'c');
  46. registry.assign<double>(e0, .1);
  47. const auto e1 = registry.create();
  48. const auto e2 = registry.create();
  49. registry.assign<int>(e2, 3);
  50. const auto e3 = registry.create();
  51. registry.assign<char>(e3, '0');
  52. registry.assign<float>(entt::tag_type_t{}, e3, .3f);
  53. const auto e4 = registry.create();
  54. registry.assign<AComponent>(entt::tag_type_t{}, e4);
  55. registry.destroy(e1);
  56. auto v1 = registry.current(e1);
  57. using storage_type = std::tuple<
  58. std::queue<entt::DefaultRegistry::entity_type>,
  59. std::queue<int>,
  60. std::queue<char>,
  61. std::queue<double>,
  62. std::queue<float>,
  63. std::queue<bool>,
  64. std::queue<AComponent>,
  65. std::queue<AnotherComponent>,
  66. std::queue<WhatAComponent>
  67. >;
  68. storage_type storage;
  69. OutputArchive<storage_type> output{storage};
  70. InputArchive<storage_type> input{storage};
  71. registry.snapshot()
  72. .entities(output)
  73. .destroyed(output)
  74. .component<int, char, AnotherComponent, double>(output)
  75. .tag<float, bool, AComponent>(output);
  76. registry.reset();
  77. ASSERT_FALSE(registry.valid(e0));
  78. ASSERT_FALSE(registry.valid(e1));
  79. ASSERT_FALSE(registry.valid(e2));
  80. ASSERT_FALSE(registry.valid(e3));
  81. ASSERT_FALSE(registry.valid(e4));
  82. registry.restore()
  83. .entities(input)
  84. .destroyed(input)
  85. .component<int, char, AnotherComponent, double>(input)
  86. .tag<float, bool, AComponent>(input)
  87. .orphans();
  88. ASSERT_TRUE(registry.valid(e0));
  89. ASSERT_FALSE(registry.valid(e1));
  90. ASSERT_TRUE(registry.valid(e2));
  91. ASSERT_TRUE(registry.valid(e3));
  92. ASSERT_TRUE(registry.valid(e4));
  93. ASSERT_FALSE(registry.orphan(e0));
  94. ASSERT_FALSE(registry.orphan(e2));
  95. ASSERT_FALSE(registry.orphan(e3));
  96. ASSERT_FALSE(registry.orphan(e4));
  97. ASSERT_EQ(registry.get<int>(e0), 42);
  98. ASSERT_EQ(registry.get<char>(e0), 'c');
  99. ASSERT_EQ(registry.get<double>(e0), .1);
  100. ASSERT_EQ(registry.current(e1), v1);
  101. ASSERT_EQ(registry.get<int>(e2), 3);
  102. ASSERT_EQ(registry.get<char>(e3), '0');
  103. ASSERT_TRUE(registry.has<float>());
  104. ASSERT_EQ(registry.attachee<float>(), e3);
  105. ASSERT_EQ(registry.get<float>(), .3f);
  106. ASSERT_TRUE(registry.has<AComponent>());
  107. ASSERT_EQ(registry.attachee<AComponent>(), e4);
  108. ASSERT_TRUE(registry.empty<AnotherComponent>());
  109. ASSERT_FALSE(registry.has<long int>());
  110. }
  111. TEST(Snapshot, Partial) {
  112. entt::DefaultRegistry registry;
  113. const auto e0 = registry.create();
  114. registry.assign<int>(e0, 42);
  115. registry.assign<char>(e0, 'c');
  116. registry.assign<double>(e0, .1);
  117. const auto e1 = registry.create();
  118. const auto e2 = registry.create();
  119. registry.assign<int>(e2, 3);
  120. const auto e3 = registry.create();
  121. registry.assign<char>(e3, '0');
  122. registry.assign<float>(entt::tag_type_t{}, e3, .3f);
  123. const auto e4 = registry.create();
  124. registry.assign<AComponent>(entt::tag_type_t{}, e4);
  125. registry.destroy(e1);
  126. auto v1 = registry.current(e1);
  127. using storage_type = std::tuple<
  128. std::queue<entt::DefaultRegistry::entity_type>,
  129. std::queue<int>,
  130. std::queue<char>,
  131. std::queue<double>,
  132. std::queue<float>,
  133. std::queue<bool>,
  134. std::queue<AComponent>,
  135. std::queue<WhatAComponent>
  136. >;
  137. storage_type storage;
  138. OutputArchive<storage_type> output{storage};
  139. InputArchive<storage_type> input{storage};
  140. registry.snapshot()
  141. .entities(output)
  142. .destroyed(output)
  143. .component<char, int>(output)
  144. .tag<bool, float>(output);
  145. registry.reset();
  146. ASSERT_FALSE(registry.valid(e0));
  147. ASSERT_FALSE(registry.valid(e1));
  148. ASSERT_FALSE(registry.valid(e2));
  149. ASSERT_FALSE(registry.valid(e3));
  150. ASSERT_FALSE(registry.valid(e4));
  151. registry.restore()
  152. .entities(input)
  153. .destroyed(input)
  154. .component<char, int>(input)
  155. .tag<bool, float>(input);
  156. ASSERT_TRUE(registry.valid(e0));
  157. ASSERT_FALSE(registry.valid(e1));
  158. ASSERT_TRUE(registry.valid(e2));
  159. ASSERT_TRUE(registry.valid(e3));
  160. ASSERT_TRUE(registry.valid(e4));
  161. ASSERT_EQ(registry.get<int>(e0), 42);
  162. ASSERT_EQ(registry.get<char>(e0), 'c');
  163. ASSERT_FALSE(registry.has<double>(e0));
  164. ASSERT_EQ(registry.current(e1), v1);
  165. ASSERT_EQ(registry.get<int>(e2), 3);
  166. ASSERT_EQ(registry.get<char>(e3), '0');
  167. ASSERT_TRUE(registry.orphan(e4));
  168. ASSERT_TRUE(registry.has<float>());
  169. ASSERT_EQ(registry.attachee<float>(), e3);
  170. ASSERT_EQ(registry.get<float>(), .3f);
  171. ASSERT_FALSE(registry.has<long int>());
  172. registry.snapshot()
  173. .tag<float>(output)
  174. .destroyed(output)
  175. .entities(output);
  176. registry.reset();
  177. ASSERT_FALSE(registry.valid(e0));
  178. ASSERT_FALSE(registry.valid(e1));
  179. ASSERT_FALSE(registry.valid(e2));
  180. ASSERT_FALSE(registry.valid(e3));
  181. ASSERT_FALSE(registry.valid(e4));
  182. registry.restore()
  183. .tag<float>(input)
  184. .destroyed(input)
  185. .entities(input)
  186. .orphans();
  187. ASSERT_FALSE(registry.valid(e0));
  188. ASSERT_FALSE(registry.valid(e1));
  189. ASSERT_FALSE(registry.valid(e2));
  190. ASSERT_TRUE(registry.valid(e3));
  191. ASSERT_FALSE(registry.valid(e4));
  192. }
  193. TEST(Snapshot, Continuous) {
  194. using entity_type = entt::DefaultRegistry::entity_type;
  195. entt::DefaultRegistry src;
  196. entt::DefaultRegistry dst;
  197. entt::ContinuousLoader<entity_type> loader{dst};
  198. std::vector<entity_type> entities;
  199. entity_type entity;
  200. using storage_type = std::tuple<
  201. std::queue<entity_type>,
  202. std::queue<AComponent>,
  203. std::queue<AnotherComponent>,
  204. std::queue<WhatAComponent>,
  205. std::queue<double>
  206. >;
  207. storage_type storage;
  208. OutputArchive<storage_type> output{storage};
  209. InputArchive<storage_type> input{storage};
  210. for(int i = 0; i < 10; ++i) {
  211. src.create();
  212. }
  213. src.each([&src](auto entity) {
  214. src.destroy(entity);
  215. });
  216. for(int i = 0; i < 5; ++i) {
  217. entity = src.create();
  218. entities.push_back(entity);
  219. src.assign<AComponent>(entity);
  220. src.assign<AnotherComponent>(entity, i, i);
  221. if(i % 2) {
  222. src.assign<WhatAComponent>(entity, entity);
  223. } else if(i == 2) {
  224. src.assign<double>(entt::tag_type_t{}, entity, .3);
  225. }
  226. }
  227. src.view<WhatAComponent>().each([&entities](auto, auto &whatAComponent) {
  228. whatAComponent.quux.insert(whatAComponent.quux.begin(), entities.begin(), entities.end());
  229. });
  230. entity = dst.create();
  231. dst.assign<AComponent>(entity);
  232. dst.assign<AnotherComponent>(entity, -1, -1);
  233. src.snapshot()
  234. .entities(output)
  235. .destroyed(output)
  236. .component<AComponent, AnotherComponent, WhatAComponent>(output)
  237. .tag<double>(output);
  238. loader.entities(input)
  239. .destroyed(input)
  240. .component<AComponent, AnotherComponent>(input)
  241. .component<WhatAComponent>(input, &WhatAComponent::bar, &WhatAComponent::quux)
  242. .tag<double>(input)
  243. .orphans();
  244. decltype(dst.size()) aComponentCnt{};
  245. decltype(dst.size()) anotherComponentCnt{};
  246. decltype(dst.size()) whatAComponentCnt{};
  247. dst.each([&dst, &aComponentCnt](auto entity) {
  248. ASSERT_TRUE(dst.has<AComponent>(entity));
  249. ++aComponentCnt;
  250. });
  251. dst.view<AnotherComponent>().each([&anotherComponentCnt](auto, const auto &component) {
  252. ASSERT_EQ(component.value, component.key < 0 ? -1 : component.key);
  253. ++anotherComponentCnt;
  254. });
  255. dst.view<WhatAComponent>().each([&dst, &whatAComponentCnt](auto entity, const auto &component) {
  256. ASSERT_EQ(entity, component.bar);
  257. for(auto entity: component.quux) {
  258. ASSERT_TRUE(dst.valid(entity));
  259. }
  260. ++whatAComponentCnt;
  261. });
  262. ASSERT_TRUE(dst.has<double>());
  263. ASSERT_EQ(dst.get<double>(), .3);
  264. src.view<AnotherComponent>().each([](auto, auto &component) {
  265. component.value = 2 * component.key;
  266. });
  267. auto size = dst.size();
  268. src.snapshot()
  269. .entities(output)
  270. .destroyed(output)
  271. .component<AComponent, AnotherComponent, WhatAComponent>(output)
  272. .tag<double>(output);
  273. loader.entities(input)
  274. .destroyed(input)
  275. .component<AComponent, AnotherComponent>(input)
  276. .component<WhatAComponent>(input, &WhatAComponent::bar, &WhatAComponent::quux)
  277. .tag<double>(input)
  278. .orphans();
  279. ASSERT_EQ(size, dst.size());
  280. ASSERT_EQ(dst.size<AComponent>(), aComponentCnt);
  281. ASSERT_EQ(dst.size<AnotherComponent>(), anotherComponentCnt);
  282. ASSERT_EQ(dst.size<WhatAComponent>(), whatAComponentCnt);
  283. ASSERT_TRUE(dst.has<double>());
  284. dst.view<AnotherComponent>().each([](auto, auto &component) {
  285. ASSERT_EQ(component.value, component.key < 0 ? -1 : (2 * component.key));
  286. });
  287. entity = src.create();
  288. src.view<WhatAComponent>().each([entity](auto, auto &component) {
  289. component.bar = entity;
  290. });
  291. src.snapshot()
  292. .entities(output)
  293. .destroyed(output)
  294. .component<AComponent, AnotherComponent, WhatAComponent>(output)
  295. .tag<double>(output);
  296. loader.entities(input)
  297. .destroyed(input)
  298. .component<AComponent, AnotherComponent>(input)
  299. .component<WhatAComponent>(input, &WhatAComponent::bar, &WhatAComponent::quux)
  300. .tag<double>(input)
  301. .orphans();
  302. dst.view<WhatAComponent>().each([&loader, entity](auto, auto &component) {
  303. ASSERT_EQ(component.bar, loader.map(entity));
  304. });
  305. entities.clear();
  306. for(auto entity: src.view<AComponent>()) {
  307. entities.push_back(entity);
  308. }
  309. src.destroy(entity);
  310. loader.shrink();
  311. src.snapshot()
  312. .entities(output)
  313. .destroyed(output)
  314. .component<AComponent, AnotherComponent, WhatAComponent>(output)
  315. .tag<double>(output);
  316. loader.entities(input)
  317. .destroyed(input)
  318. .component<AComponent, AnotherComponent>(input)
  319. .component<WhatAComponent>(input, &WhatAComponent::bar, &WhatAComponent::quux)
  320. .tag<double>(input)
  321. .orphans()
  322. .shrink();
  323. dst.view<WhatAComponent>().each([&dst, &loader, entity](auto, auto &component) {
  324. ASSERT_FALSE(dst.valid(component.bar));
  325. });
  326. ASSERT_FALSE(loader.has(entity));
  327. entity = src.create();
  328. src.view<WhatAComponent>().each([entity](auto, auto &component) {
  329. component.bar = entity;
  330. });
  331. dst.reset<AComponent>();
  332. aComponentCnt = src.size<AComponent>();
  333. src.snapshot()
  334. .entities(output)
  335. .destroyed(output)
  336. .component<AComponent, AnotherComponent, WhatAComponent>(output)
  337. .tag<double>(output);
  338. loader.entities(input)
  339. .destroyed(input)
  340. .component<AComponent, AnotherComponent>(input)
  341. .component<WhatAComponent>(input, &WhatAComponent::bar, &WhatAComponent::quux)
  342. .tag<double>(input)
  343. .orphans();
  344. ASSERT_EQ(dst.size<AComponent>(), aComponentCnt);
  345. ASSERT_TRUE(dst.has<double>());
  346. src.reset<AComponent>();
  347. src.remove<double>();
  348. aComponentCnt = {};
  349. src.snapshot()
  350. .entities(output)
  351. .destroyed(output)
  352. .component<AComponent, AnotherComponent, WhatAComponent>(output)
  353. .tag<double>(output);
  354. loader.entities(input)
  355. .destroyed(input)
  356. .component<AComponent, AnotherComponent>(input)
  357. .component<WhatAComponent>(input, &WhatAComponent::bar, &WhatAComponent::quux)
  358. .tag<double>(input)
  359. .orphans();
  360. ASSERT_EQ(dst.size<AComponent>(), aComponentCnt);
  361. ASSERT_FALSE(dst.has<double>());
  362. }
  363. TEST(Snapshot, ContinuousMoreOnShrink) {
  364. using entity_type = entt::DefaultRegistry::entity_type;
  365. entt::DefaultRegistry src;
  366. entt::DefaultRegistry dst;
  367. entt::ContinuousLoader<entity_type> loader{dst};
  368. using storage_type = std::tuple<
  369. std::queue<entity_type>,
  370. std::queue<AComponent>
  371. >;
  372. storage_type storage;
  373. OutputArchive<storage_type> output{storage};
  374. InputArchive<storage_type> input{storage};
  375. auto entity = src.create();
  376. src.snapshot().entities(output);
  377. loader.entities(input).shrink();
  378. ASSERT_TRUE(dst.valid(entity));
  379. loader.shrink();
  380. ASSERT_FALSE(dst.valid(entity));
  381. }