snapshot.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  1. #include <cstddef>
  2. #include <map>
  3. #include <memory>
  4. #include <queue>
  5. #include <tuple>
  6. #include <type_traits>
  7. #include <vector>
  8. #include <gtest/gtest.h>
  9. #include <entt/entity/entity.hpp>
  10. #include <entt/entity/registry.hpp>
  11. #include <entt/entity/snapshot.hpp>
  12. template<typename Storage>
  13. struct output_archive {
  14. output_archive(Storage &instance)
  15. : storage{instance} {}
  16. template<typename... Value>
  17. void operator()(const Value &...value) {
  18. (std::get<std::queue<Value>>(storage).push(value), ...);
  19. }
  20. void operator()(const entt::entity &entity, const std::unique_ptr<int> &instance) {
  21. (*this)(entity, *instance);
  22. }
  23. private:
  24. Storage &storage;
  25. };
  26. template<typename Storage>
  27. struct input_archive {
  28. input_archive(Storage &instance)
  29. : storage{instance} {}
  30. template<typename... Value>
  31. void operator()(Value &...value) {
  32. auto assign = [this](auto &val) {
  33. auto &queue = std::get<std::queue<std::decay_t<decltype(val)>>>(storage);
  34. val = queue.front();
  35. queue.pop();
  36. };
  37. (assign(value), ...);
  38. }
  39. void operator()(entt::entity &entity, std::unique_ptr<int> &instance) {
  40. instance = std::make_unique<int>();
  41. (*this)(entity, *instance);
  42. }
  43. private:
  44. Storage &storage;
  45. };
  46. struct a_component {};
  47. struct another_component {
  48. int key{};
  49. int value{};
  50. };
  51. struct what_a_component {
  52. entt::entity bar{};
  53. std::vector<entt::entity> quux{};
  54. };
  55. struct map_component {
  56. std::map<entt::entity, int> keys{};
  57. std::map<int, entt::entity> values{};
  58. std::map<entt::entity, entt::entity> both{};
  59. };
  60. TEST(Snapshot, Dump) {
  61. using traits_type = entt::entt_traits<entt::entity>;
  62. entt::registry registry;
  63. const auto e0 = registry.create();
  64. registry.emplace<int>(e0, 42);
  65. registry.emplace<char>(e0, 'c');
  66. registry.emplace<double>(e0, .1);
  67. const auto e1 = registry.create();
  68. const auto e2 = registry.create();
  69. registry.emplace<int>(e2, 3);
  70. const auto e3 = registry.create();
  71. registry.emplace<a_component>(e3);
  72. registry.emplace<char>(e3, '0');
  73. registry.destroy(e1);
  74. auto v1 = registry.current(e1);
  75. using archive_type = std::tuple<
  76. std::queue<typename traits_type::entity_type>,
  77. std::queue<entt::entity>,
  78. std::queue<int>,
  79. std::queue<char>,
  80. std::queue<double>,
  81. std::queue<a_component>,
  82. std::queue<another_component>>;
  83. archive_type storage;
  84. output_archive<archive_type> output{storage};
  85. input_archive<archive_type> input{storage};
  86. entt::snapshot{registry}.entities(output).component<int, char, double, a_component, another_component>(output);
  87. registry.clear();
  88. ASSERT_FALSE(registry.valid(e0));
  89. ASSERT_FALSE(registry.valid(e1));
  90. ASSERT_FALSE(registry.valid(e2));
  91. ASSERT_FALSE(registry.valid(e3));
  92. entt::snapshot_loader{registry}.entities(input).component<int, char, double, a_component, another_component>(input).orphans();
  93. ASSERT_TRUE(registry.valid(e0));
  94. ASSERT_FALSE(registry.valid(e1));
  95. ASSERT_TRUE(registry.valid(e2));
  96. ASSERT_TRUE(registry.valid(e3));
  97. ASSERT_FALSE(registry.orphan(e0));
  98. ASSERT_FALSE(registry.orphan(e2));
  99. ASSERT_FALSE(registry.orphan(e3));
  100. ASSERT_EQ(registry.get<int>(e0), 42);
  101. ASSERT_EQ(registry.get<char>(e0), 'c');
  102. ASSERT_EQ(registry.get<double>(e0), .1);
  103. ASSERT_EQ(registry.current(e1), v1);
  104. ASSERT_EQ(registry.get<int>(e2), 3);
  105. ASSERT_EQ(registry.get<char>(e3), '0');
  106. ASSERT_TRUE(registry.all_of<a_component>(e3));
  107. ASSERT_TRUE(registry.storage<another_component>().empty());
  108. }
  109. TEST(Snapshot, Partial) {
  110. using traits_type = entt::entt_traits<entt::entity>;
  111. entt::registry registry;
  112. const auto e0 = registry.create();
  113. registry.emplace<int>(e0, 42);
  114. registry.emplace<char>(e0, 'c');
  115. registry.emplace<double>(e0, .1);
  116. const auto e1 = registry.create();
  117. const auto e2 = registry.create();
  118. registry.emplace<int>(e2, 3);
  119. const auto e3 = registry.create();
  120. registry.emplace<char>(e3, '0');
  121. registry.destroy(e1);
  122. auto v1 = registry.current(e1);
  123. using archive_type = std::tuple<
  124. std::queue<typename traits_type::entity_type>,
  125. std::queue<entt::entity>,
  126. std::queue<int>,
  127. std::queue<char>,
  128. std::queue<double>>;
  129. archive_type storage;
  130. output_archive<archive_type> output{storage};
  131. input_archive<archive_type> input{storage};
  132. entt::snapshot{registry}.entities(output).component<char, int>(output);
  133. registry.clear();
  134. ASSERT_FALSE(registry.valid(e0));
  135. ASSERT_FALSE(registry.valid(e1));
  136. ASSERT_FALSE(registry.valid(e2));
  137. ASSERT_FALSE(registry.valid(e3));
  138. entt::snapshot_loader{registry}.entities(input).component<char, int>(input);
  139. ASSERT_TRUE(registry.valid(e0));
  140. ASSERT_FALSE(registry.valid(e1));
  141. ASSERT_TRUE(registry.valid(e2));
  142. ASSERT_TRUE(registry.valid(e3));
  143. ASSERT_EQ(registry.get<int>(e0), 42);
  144. ASSERT_EQ(registry.get<char>(e0), 'c');
  145. ASSERT_FALSE(registry.all_of<double>(e0));
  146. ASSERT_EQ(registry.current(e1), v1);
  147. ASSERT_EQ(registry.get<int>(e2), 3);
  148. ASSERT_EQ(registry.get<char>(e3), '0');
  149. entt::snapshot{registry}.entities(output);
  150. registry.clear();
  151. ASSERT_FALSE(registry.valid(e0));
  152. ASSERT_FALSE(registry.valid(e1));
  153. ASSERT_FALSE(registry.valid(e2));
  154. ASSERT_FALSE(registry.valid(e3));
  155. entt::snapshot_loader{registry}.entities(input).orphans();
  156. ASSERT_FALSE(registry.valid(e0));
  157. ASSERT_FALSE(registry.valid(e1));
  158. ASSERT_FALSE(registry.valid(e2));
  159. ASSERT_FALSE(registry.valid(e3));
  160. }
  161. TEST(Snapshot, Iterator) {
  162. using traits_type = entt::entt_traits<entt::entity>;
  163. entt::registry registry;
  164. for(auto i = 0; i < 50; ++i) {
  165. const auto entity = registry.create();
  166. registry.emplace<a_component>(entity);
  167. if(i % 2) {
  168. registry.emplace<another_component>(entity, i, i);
  169. registry.emplace<std::unique_ptr<int>>(entity, std::make_unique<int>(i));
  170. }
  171. }
  172. using archive_type = std::tuple<
  173. std::queue<typename traits_type::entity_type>,
  174. std::queue<entt::entity>,
  175. std::queue<another_component>,
  176. std::queue<int>>;
  177. archive_type storage;
  178. output_archive<archive_type> output{storage};
  179. input_archive<archive_type> input{storage};
  180. const auto view = registry.view<a_component>();
  181. const auto size = view.size();
  182. entt::snapshot{registry}.component<another_component, std::unique_ptr<int>>(output, view.begin(), view.end());
  183. registry.clear();
  184. entt::snapshot_loader{registry}.component<another_component, std::unique_ptr<int>>(input);
  185. ASSERT_EQ(registry.view<another_component>().size(), size / 2u);
  186. registry.view<another_component>().each([](const auto entity, const auto &) {
  187. ASSERT_NE(entt::to_integral(entity) % 2u, 0u);
  188. });
  189. }
  190. TEST(Snapshot, Continuous) {
  191. using traits_type = entt::entt_traits<entt::entity>;
  192. entt::registry src;
  193. entt::registry dst;
  194. entt::continuous_loader loader{dst};
  195. std::vector<entt::entity> entities;
  196. entt::entity entity;
  197. using archive_type = std::tuple<
  198. std::queue<typename traits_type::entity_type>,
  199. std::queue<entt::entity>,
  200. std::queue<another_component>,
  201. std::queue<what_a_component>,
  202. std::queue<map_component>,
  203. std::queue<int>,
  204. std::queue<double>>;
  205. archive_type storage;
  206. output_archive<archive_type> output{storage};
  207. input_archive<archive_type> input{storage};
  208. for(int i = 0; i < 10; ++i) {
  209. static_cast<void>(src.create());
  210. }
  211. src.clear();
  212. for(int i = 0; i < 5; ++i) {
  213. entity = src.create();
  214. entities.push_back(entity);
  215. src.emplace<a_component>(entity);
  216. src.emplace<another_component>(entity, i, i);
  217. src.emplace<std::unique_ptr<int>>(entity, std::make_unique<int>(i));
  218. if(i % 2) {
  219. src.emplace<what_a_component>(entity, entity);
  220. } else {
  221. src.emplace<map_component>(entity);
  222. }
  223. }
  224. src.view<what_a_component>().each([&entities](auto, auto &what_a_component) {
  225. what_a_component.quux.insert(what_a_component.quux.begin(), entities.begin(), entities.end());
  226. });
  227. src.view<map_component>().each([&entities](auto, auto &map_component) {
  228. for(std::size_t i = 0; i < entities.size(); ++i) {
  229. map_component.keys.insert({entities[i], int(i)});
  230. map_component.values.insert({int(i), entities[i]});
  231. map_component.both.insert({entities[entities.size() - i - 1], entities[i]});
  232. }
  233. });
  234. entity = dst.create();
  235. dst.emplace<a_component>(entity);
  236. dst.emplace<another_component>(entity, -1, -1);
  237. dst.emplace<std::unique_ptr<int>>(entity, std::make_unique<int>(-1));
  238. entt::snapshot{src}.entities(output).component<a_component, another_component, what_a_component, map_component, std::unique_ptr<int>>(output);
  239. loader.entities(input)
  240. .component<a_component, another_component, what_a_component, map_component, std::unique_ptr<int>>(
  241. input,
  242. &what_a_component::bar,
  243. &what_a_component::quux,
  244. &map_component::keys,
  245. &map_component::values,
  246. &map_component::both)
  247. .orphans();
  248. decltype(dst.size()) a_component_cnt{};
  249. decltype(dst.size()) another_component_cnt{};
  250. decltype(dst.size()) what_a_component_cnt{};
  251. decltype(dst.size()) map_component_cnt{};
  252. decltype(dst.size()) unique_ptr_cnt{};
  253. dst.each([&dst, &a_component_cnt](auto entt) {
  254. ASSERT_TRUE(dst.all_of<a_component>(entt));
  255. ++a_component_cnt;
  256. });
  257. dst.view<another_component>().each([&another_component_cnt](auto, const auto &component) {
  258. ASSERT_EQ(component.value, component.key < 0 ? -1 : component.key);
  259. ++another_component_cnt;
  260. });
  261. dst.view<what_a_component>().each([&dst, &what_a_component_cnt](auto entt, const auto &component) {
  262. ASSERT_EQ(entt, component.bar);
  263. for(auto child: component.quux) {
  264. ASSERT_TRUE(dst.valid(child));
  265. }
  266. ++what_a_component_cnt;
  267. });
  268. dst.view<map_component>().each([&dst, &map_component_cnt](const auto &component) {
  269. for(auto child: component.keys) {
  270. ASSERT_TRUE(dst.valid(child.first));
  271. }
  272. for(auto child: component.values) {
  273. ASSERT_TRUE(dst.valid(child.second));
  274. }
  275. for(auto child: component.both) {
  276. ASSERT_TRUE(dst.valid(child.first));
  277. ASSERT_TRUE(dst.valid(child.second));
  278. }
  279. ++map_component_cnt;
  280. });
  281. dst.view<std::unique_ptr<int>>().each([&dst, &unique_ptr_cnt](auto, const auto &component) {
  282. ++unique_ptr_cnt;
  283. ASSERT_EQ(*component, static_cast<int>(dst.storage<std::unique_ptr<int>>().size() - unique_ptr_cnt - 1u));
  284. });
  285. src.view<another_component>().each([](auto, auto &component) {
  286. component.value = 2 * component.key;
  287. });
  288. auto size = dst.size();
  289. entt::snapshot{src}.entities(output).component<a_component, what_a_component, map_component, another_component>(output);
  290. loader.entities(input)
  291. .component<a_component, what_a_component, map_component, another_component>(
  292. input,
  293. &what_a_component::bar,
  294. &what_a_component::quux,
  295. &map_component::keys,
  296. &map_component::values,
  297. &map_component::both)
  298. .orphans();
  299. ASSERT_EQ(size, dst.size());
  300. ASSERT_EQ(dst.storage<a_component>().size(), a_component_cnt);
  301. ASSERT_EQ(dst.storage<another_component>().size(), another_component_cnt);
  302. ASSERT_EQ(dst.storage<what_a_component>().size(), what_a_component_cnt);
  303. ASSERT_EQ(dst.storage<map_component>().size(), map_component_cnt);
  304. ASSERT_EQ(dst.storage<std::unique_ptr<int>>().size(), unique_ptr_cnt);
  305. dst.view<another_component>().each([](auto, auto &component) {
  306. ASSERT_EQ(component.value, component.key < 0 ? -1 : (2 * component.key));
  307. });
  308. entity = src.create();
  309. src.view<what_a_component>().each([entity](auto, auto &component) {
  310. component.bar = entity;
  311. });
  312. entt::snapshot{src}.entities(output).component<what_a_component, map_component, a_component, another_component>(output);
  313. loader.entities(input)
  314. .component<what_a_component, map_component, a_component, another_component>(
  315. input,
  316. &what_a_component::bar,
  317. &what_a_component::quux,
  318. &map_component::keys,
  319. &map_component::values,
  320. &map_component::both)
  321. .orphans();
  322. dst.view<what_a_component>().each([&loader, entity](auto, auto &component) {
  323. ASSERT_EQ(component.bar, loader.map(entity));
  324. });
  325. entities.clear();
  326. for(auto entt: src.view<a_component>()) {
  327. entities.push_back(entt);
  328. }
  329. src.destroy(entity);
  330. loader.shrink();
  331. entt::snapshot{src}.entities(output).component<a_component, another_component, what_a_component, map_component>(output);
  332. loader.entities(input)
  333. .component<a_component, another_component, what_a_component, map_component>(
  334. input,
  335. &what_a_component::bar,
  336. &what_a_component::quux,
  337. &map_component::keys,
  338. &map_component::values,
  339. &map_component::both)
  340. .orphans()
  341. .shrink();
  342. dst.view<what_a_component>().each([&dst](auto, auto &component) {
  343. ASSERT_FALSE(dst.valid(component.bar));
  344. });
  345. ASSERT_FALSE(loader.contains(entity));
  346. entity = src.create();
  347. src.view<what_a_component>().each([entity](auto, auto &component) {
  348. component.bar = entity;
  349. });
  350. dst.clear<a_component>();
  351. a_component_cnt = src.storage<a_component>().size();
  352. entt::snapshot{src}.entities(output).component<a_component, what_a_component, map_component, another_component>(output);
  353. loader.entities(input)
  354. .component<a_component, what_a_component, map_component, another_component>(
  355. input,
  356. &what_a_component::bar,
  357. &what_a_component::quux,
  358. &map_component::keys,
  359. &map_component::values,
  360. &map_component::both)
  361. .orphans();
  362. ASSERT_EQ(dst.storage<a_component>().size(), a_component_cnt);
  363. src.clear<a_component>();
  364. a_component_cnt = {};
  365. entt::snapshot{src}.entities(output).component<what_a_component, map_component, a_component, another_component>(output);
  366. loader.entities(input)
  367. .component<what_a_component, map_component, a_component, another_component>(
  368. input,
  369. &what_a_component::bar,
  370. &what_a_component::quux,
  371. &map_component::keys,
  372. &map_component::values,
  373. &map_component::both)
  374. .orphans();
  375. ASSERT_EQ(dst.storage<a_component>().size(), a_component_cnt);
  376. }
  377. TEST(Snapshot, MoreOnShrink) {
  378. using traits_type = entt::entt_traits<entt::entity>;
  379. entt::registry src;
  380. entt::registry dst;
  381. entt::continuous_loader loader{dst};
  382. using archive_type = std::tuple<
  383. std::queue<typename traits_type::entity_type>,
  384. std::queue<entt::entity>>;
  385. archive_type storage;
  386. output_archive<archive_type> output{storage};
  387. input_archive<archive_type> input{storage};
  388. auto entity = src.create();
  389. entt::snapshot{src}.entities(output);
  390. loader.entities(input).shrink();
  391. ASSERT_TRUE(dst.valid(entity));
  392. loader.shrink();
  393. ASSERT_FALSE(dst.valid(entity));
  394. }
  395. TEST(Snapshot, SyncDataMembers) {
  396. using traits_type = entt::entt_traits<entt::entity>;
  397. entt::registry src;
  398. entt::registry dst;
  399. entt::continuous_loader loader{dst};
  400. using archive_type = std::tuple<
  401. std::queue<typename traits_type::entity_type>,
  402. std::queue<entt::entity>,
  403. std::queue<what_a_component>,
  404. std::queue<map_component>>;
  405. archive_type storage;
  406. output_archive<archive_type> output{storage};
  407. input_archive<archive_type> input{storage};
  408. static_cast<void>(src.create());
  409. static_cast<void>(src.create());
  410. src.clear();
  411. auto parent = src.create();
  412. auto child = src.create();
  413. src.emplace<what_a_component>(parent, entt::null);
  414. src.emplace<what_a_component>(child, parent).quux.push_back(child);
  415. src.emplace<map_component>(
  416. child,
  417. decltype(map_component::keys){{{child, 10}}},
  418. decltype(map_component::values){{{10, child}}},
  419. decltype(map_component::both){{{child, child}}});
  420. entt::snapshot{src}.entities(output).component<what_a_component, map_component>(output);
  421. loader.entities(input).component<what_a_component, map_component>(
  422. input,
  423. &what_a_component::bar,
  424. &what_a_component::quux,
  425. &map_component::keys,
  426. &map_component::values,
  427. &map_component::both);
  428. ASSERT_FALSE(dst.valid(parent));
  429. ASSERT_FALSE(dst.valid(child));
  430. ASSERT_TRUE(dst.all_of<what_a_component>(loader.map(parent)));
  431. ASSERT_TRUE(dst.all_of<what_a_component>(loader.map(child)));
  432. ASSERT_EQ(dst.get<what_a_component>(loader.map(parent)).bar, static_cast<entt::entity>(entt::null));
  433. const auto &component = dst.get<what_a_component>(loader.map(child));
  434. ASSERT_EQ(component.bar, loader.map(parent));
  435. ASSERT_EQ(component.quux[0], loader.map(child));
  436. const auto &elem = dst.get<map_component>(loader.map(child));
  437. ASSERT_EQ(elem.keys.at(loader.map(child)), 10);
  438. ASSERT_EQ(elem.values.at(10), loader.map(child));
  439. ASSERT_EQ(elem.both.at(loader.map(child)), loader.map(child));
  440. }