snapshot.cpp 18 KB

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