snapshot.cpp 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466
  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/core/any.hpp>
  10. #include <entt/core/hashed_string.hpp>
  11. #include <entt/entity/entity.hpp>
  12. #include <entt/entity/registry.hpp>
  13. #include <entt/entity/snapshot.hpp>
  14. struct empty {};
  15. struct shadow {
  16. entt::entity target{entt::null};
  17. };
  18. TEST(BasicSnapshot, Constructors) {
  19. static_assert(!std::is_default_constructible_v<entt::basic_snapshot<entt::registry>>);
  20. static_assert(!std::is_copy_constructible_v<entt::basic_snapshot<entt::registry>>);
  21. static_assert(!std::is_copy_assignable_v<entt::basic_snapshot<entt::registry>>);
  22. static_assert(std::is_move_constructible_v<entt::basic_snapshot<entt::registry>>);
  23. static_assert(std::is_move_assignable_v<entt::basic_snapshot<entt::registry>>);
  24. entt::registry registry;
  25. entt::basic_snapshot snapshot{registry};
  26. entt::basic_snapshot other{std::move(snapshot)};
  27. ASSERT_NO_FATAL_FAILURE(snapshot = std::move(other));
  28. }
  29. TEST(BasicSnapshot, GetEntityType) {
  30. using namespace entt::literals;
  31. using traits_type = entt::entt_traits<entt::entity>;
  32. entt::registry registry;
  33. entt::basic_snapshot snapshot{registry};
  34. const auto &storage = registry.storage<entt::entity>();
  35. std::vector<entt::any> data{};
  36. auto archive = [&data](auto &&value) { data.emplace_back(std::forward<decltype(value)>(value)); };
  37. snapshot.get<entt::entity>(archive);
  38. ASSERT_EQ(data.size(), 2u);
  39. ASSERT_NE(entt::any_cast<typename traits_type::entity_type>(&data[0u]), nullptr);
  40. ASSERT_EQ(entt::any_cast<typename traits_type::entity_type>(data[0u]), storage.size());
  41. ASSERT_NE(entt::any_cast<typename traits_type::entity_type>(&data[1u]), nullptr);
  42. ASSERT_EQ(entt::any_cast<typename traits_type::entity_type>(data[1u]), storage.in_use());
  43. entt::entity entities[3u];
  44. registry.create(std::begin(entities), std::end(entities));
  45. registry.destroy(entities[1u]);
  46. data.clear();
  47. snapshot.get<entt::entity>(archive, "ignored"_hs);
  48. ASSERT_EQ(data.size(), 5u);
  49. ASSERT_NE(entt::any_cast<typename traits_type::entity_type>(&data[0u]), nullptr);
  50. ASSERT_EQ(entt::any_cast<typename traits_type::entity_type>(data[0u]), storage.size());
  51. ASSERT_NE(entt::any_cast<typename traits_type::entity_type>(&data[1u]), nullptr);
  52. ASSERT_EQ(entt::any_cast<typename traits_type::entity_type>(data[1u]), storage.in_use());
  53. ASSERT_NE(entt::any_cast<entt::entity>(&data[2u]), nullptr);
  54. ASSERT_EQ(entt::any_cast<entt::entity>(data[2u]), storage.data()[0u]);
  55. ASSERT_NE(entt::any_cast<entt::entity>(&data[3u]), nullptr);
  56. ASSERT_EQ(entt::any_cast<entt::entity>(data[3u]), storage.data()[1u]);
  57. ASSERT_NE(entt::any_cast<entt::entity>(&data[4u]), nullptr);
  58. ASSERT_EQ(entt::any_cast<entt::entity>(data[4u]), storage.data()[2u]);
  59. }
  60. TEST(BasicSnapshot, GetType) {
  61. using namespace entt::literals;
  62. using traits_type = entt::entt_traits<entt::entity>;
  63. entt::registry registry;
  64. entt::basic_snapshot snapshot{registry};
  65. const auto &storage = registry.storage<int>();
  66. entt::entity entities[3u];
  67. const int values[3u]{1, 2, 3};
  68. registry.create(std::begin(entities), std::end(entities));
  69. registry.insert<int>(std::begin(entities), std::end(entities), std::begin(values));
  70. registry.destroy(entities[1u]);
  71. std::vector<entt::any> data{};
  72. auto archive = [&data](auto &&value) { data.emplace_back(std::forward<decltype(value)>(value)); };
  73. snapshot.get<int>(archive, "other"_hs);
  74. ASSERT_EQ(data.size(), 1u);
  75. ASSERT_NE(entt::any_cast<typename traits_type::entity_type>(&data[0u]), nullptr);
  76. ASSERT_EQ(entt::any_cast<typename traits_type::entity_type>(data[0u]), 0u);
  77. data.clear();
  78. snapshot.get<int>(archive);
  79. ASSERT_EQ(data.size(), 5u);
  80. ASSERT_NE(entt::any_cast<typename traits_type::entity_type>(&data[0u]), nullptr);
  81. ASSERT_EQ(entt::any_cast<typename traits_type::entity_type>(data[0u]), storage.size());
  82. ASSERT_NE(entt::any_cast<entt::entity>(&data[1u]), nullptr);
  83. ASSERT_EQ(entt::any_cast<entt::entity>(data[1u]), entities[0u]);
  84. ASSERT_NE(entt::any_cast<int>(&data[2u]), nullptr);
  85. ASSERT_EQ(entt::any_cast<int>(data[2u]), values[0u]);
  86. ASSERT_NE(entt::any_cast<entt::entity>(&data[3u]), nullptr);
  87. ASSERT_EQ(entt::any_cast<entt::entity>(data[3u]), entities[2u]);
  88. ASSERT_NE(entt::any_cast<int>(&data[4u]), nullptr);
  89. ASSERT_EQ(entt::any_cast<int>(data[4u]), values[2u]);
  90. }
  91. TEST(BasicSnapshot, GetEmptyType) {
  92. using namespace entt::literals;
  93. using traits_type = entt::entt_traits<entt::entity>;
  94. entt::registry registry;
  95. entt::basic_snapshot snapshot{registry};
  96. const auto &storage = registry.storage<empty>();
  97. entt::entity entities[3u];
  98. registry.create(std::begin(entities), std::end(entities));
  99. registry.insert<empty>(std::begin(entities), std::end(entities));
  100. registry.destroy(entities[1u]);
  101. std::vector<entt::any> data{};
  102. auto archive = [&data](auto &&value) { data.emplace_back(std::forward<decltype(value)>(value)); };
  103. snapshot.get<empty>(archive, "other"_hs);
  104. ASSERT_EQ(data.size(), 1u);
  105. ASSERT_NE(entt::any_cast<typename traits_type::entity_type>(&data[0u]), nullptr);
  106. ASSERT_EQ(entt::any_cast<typename traits_type::entity_type>(data[0u]), 0u);
  107. data.clear();
  108. snapshot.get<empty>(archive);
  109. ASSERT_EQ(data.size(), 3u);
  110. ASSERT_NE(entt::any_cast<typename traits_type::entity_type>(&data[0u]), nullptr);
  111. ASSERT_EQ(entt::any_cast<typename traits_type::entity_type>(data[0u]), storage.size());
  112. ASSERT_NE(entt::any_cast<entt::entity>(&data[1u]), nullptr);
  113. ASSERT_EQ(entt::any_cast<entt::entity>(data[1u]), entities[0u]);
  114. ASSERT_NE(entt::any_cast<entt::entity>(&data[2u]), nullptr);
  115. ASSERT_EQ(entt::any_cast<entt::entity>(data[2u]), entities[2u]);
  116. }
  117. TEST(BasicSnapshot, GetTypeSparse) {
  118. using namespace entt::literals;
  119. using traits_type = entt::entt_traits<entt::entity>;
  120. entt::registry registry;
  121. entt::basic_snapshot snapshot{registry};
  122. entt::entity entities[3u];
  123. const int values[3u]{1, 2, 3};
  124. registry.create(std::begin(entities), std::end(entities));
  125. registry.insert<int>(std::begin(entities), std::end(entities), std::begin(values));
  126. registry.destroy(entities[1u]);
  127. std::vector<entt::any> data{};
  128. auto archive = [&data](auto &&value) { data.emplace_back(std::forward<decltype(value)>(value)); };
  129. snapshot.get<int>(archive, std::begin(entities), std::end(entities), "other"_hs);
  130. ASSERT_EQ(data.size(), 1u);
  131. ASSERT_NE(entt::any_cast<typename traits_type::entity_type>(&data[0u]), nullptr);
  132. ASSERT_EQ(entt::any_cast<typename traits_type::entity_type>(data[0u]), 0u);
  133. data.clear();
  134. snapshot.get<int>(archive, std::begin(entities), std::end(entities));
  135. ASSERT_EQ(data.size(), 6u);
  136. ASSERT_NE(entt::any_cast<typename traits_type::entity_type>(&data[0u]), nullptr);
  137. ASSERT_EQ(entt::any_cast<typename traits_type::entity_type>(data[0u]), static_cast<typename traits_type::entity_type>(std::distance(std::begin(entities), std::end(entities))));
  138. ASSERT_NE(entt::any_cast<entt::entity>(&data[1u]), nullptr);
  139. ASSERT_EQ(entt::any_cast<entt::entity>(data[1u]), entities[0u]);
  140. ASSERT_NE(entt::any_cast<int>(&data[2u]), nullptr);
  141. ASSERT_EQ(entt::any_cast<int>(data[2u]), values[0u]);
  142. ASSERT_NE(entt::any_cast<entt::entity>(&data[3u]), nullptr);
  143. ASSERT_EQ(entt::any_cast<entt::entity>(data[3u]), static_cast<entt::entity>(entt::null));
  144. ASSERT_NE(entt::any_cast<entt::entity>(&data[4u]), nullptr);
  145. ASSERT_EQ(entt::any_cast<entt::entity>(data[4u]), entities[2u]);
  146. ASSERT_NE(entt::any_cast<int>(&data[5u]), nullptr);
  147. ASSERT_EQ(entt::any_cast<int>(data[5u]), values[2u]);
  148. }
  149. TEST(BasicSnapshotLoader, Constructors) {
  150. static_assert(!std::is_default_constructible_v<entt::basic_snapshot_loader<entt::registry>>);
  151. static_assert(!std::is_copy_constructible_v<entt::basic_snapshot_loader<entt::registry>>);
  152. static_assert(!std::is_copy_assignable_v<entt::basic_snapshot_loader<entt::registry>>);
  153. static_assert(std::is_move_constructible_v<entt::basic_snapshot_loader<entt::registry>>);
  154. static_assert(std::is_move_assignable_v<entt::basic_snapshot_loader<entt::registry>>);
  155. entt::registry registry;
  156. entt::basic_snapshot_loader loader{registry};
  157. entt::basic_snapshot_loader other{std::move(loader)};
  158. ASSERT_NO_FATAL_FAILURE(loader = std::move(other));
  159. }
  160. TEST(BasicSnapshotLoader, GetEntityType) {
  161. using namespace entt::literals;
  162. using traits_type = entt::entt_traits<entt::entity>;
  163. entt::registry registry;
  164. entt::basic_snapshot_loader loader{registry};
  165. const auto &storage = registry.storage<entt::entity>();
  166. std::vector<entt::any> data{};
  167. auto archive = [&data, pos = 0u](auto &value) mutable { value = entt::any_cast<std::remove_reference_t<decltype(value)>>(data[pos++]); };
  168. const entt::entity entities[3u]{traits_type::construct(0u, 0u), traits_type::construct(2u, 0u), traits_type::construct(1u, 1u)};
  169. ASSERT_FALSE(registry.valid(entities[0u]));
  170. ASSERT_FALSE(registry.valid(entities[1u]));
  171. ASSERT_FALSE(registry.valid(entities[2u]));
  172. data.emplace_back(static_cast<typename traits_type::entity_type>(0u));
  173. data.emplace_back(static_cast<typename traits_type::entity_type>(0u));
  174. loader.get<entt::entity>(archive);
  175. ASSERT_FALSE(registry.valid(entities[0u]));
  176. ASSERT_FALSE(registry.valid(entities[1u]));
  177. ASSERT_FALSE(registry.valid(entities[2u]));
  178. ASSERT_EQ(storage.size(), 0u);
  179. ASSERT_EQ(storage.in_use(), 0u);
  180. data.emplace_back(static_cast<typename traits_type::entity_type>(3u));
  181. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  182. data.emplace_back(entities[0u]);
  183. data.emplace_back(entities[1u]);
  184. data.emplace_back(entities[2u]);
  185. loader.get<entt::entity>(archive, "ignored"_hs);
  186. ASSERT_TRUE(registry.valid(entities[0u]));
  187. ASSERT_TRUE(registry.valid(entities[1u]));
  188. ASSERT_TRUE(registry.valid(entities[2u]));
  189. ASSERT_EQ(storage.size(), 3u);
  190. ASSERT_EQ(storage.in_use(), 2u);
  191. ASSERT_EQ(storage[0u], entities[0u]);
  192. ASSERT_EQ(storage[1u], entities[1u]);
  193. ASSERT_EQ(storage[2u], entities[2u]);
  194. ASSERT_EQ(registry.create(), entities[2u]);
  195. }
  196. TEST(BasicSnapshotLoader, GetType) {
  197. using namespace entt::literals;
  198. using traits_type = entt::entt_traits<entt::entity>;
  199. entt::registry registry;
  200. entt::basic_snapshot_loader loader{registry};
  201. const auto &storage = registry.storage<int>();
  202. std::vector<entt::any> data{};
  203. auto archive = [&data, pos = 0u](auto &value) mutable { value = entt::any_cast<std::remove_reference_t<decltype(value)>>(data[pos++]); };
  204. const entt::entity entities[2u]{traits_type::construct(0u, 0u), traits_type::construct(2u, 0u)};
  205. const int values[2u]{1, 3};
  206. ASSERT_FALSE(registry.valid(entities[0u]));
  207. ASSERT_FALSE(registry.valid(entities[1u]));
  208. data.emplace_back(static_cast<typename traits_type::entity_type>(1u));
  209. data.emplace_back(entities[0u]);
  210. data.emplace_back(values[0u]);
  211. loader.get<int>(archive, "other"_hs);
  212. ASSERT_TRUE(registry.valid(entities[0u]));
  213. ASSERT_FALSE(registry.valid(entities[1u]));
  214. ASSERT_EQ(storage.size(), 0u);
  215. ASSERT_EQ(registry.storage<int>("other"_hs).size(), 1u);
  216. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  217. data.emplace_back(entities[0u]);
  218. data.emplace_back(values[0u]);
  219. data.emplace_back(entities[1u]);
  220. data.emplace_back(values[1u]);
  221. loader.get<int>(archive);
  222. ASSERT_TRUE(registry.valid(entities[0u]));
  223. ASSERT_TRUE(registry.valid(entities[1u]));
  224. ASSERT_EQ(storage.size(), 2u);
  225. ASSERT_TRUE(storage.contains(entities[0u]));
  226. ASSERT_TRUE(storage.contains(entities[1u]));
  227. ASSERT_EQ(storage.get(entities[0u]), values[0u]);
  228. ASSERT_EQ(storage.get(entities[1u]), values[1u]);
  229. }
  230. TEST(BasicSnapshotLoader, GetEmptyType) {
  231. using namespace entt::literals;
  232. using traits_type = entt::entt_traits<entt::entity>;
  233. entt::registry registry;
  234. entt::basic_snapshot_loader loader{registry};
  235. const auto &storage = registry.storage<empty>();
  236. std::vector<entt::any> data{};
  237. auto archive = [&data, pos = 0u](auto &value) mutable { value = entt::any_cast<std::remove_reference_t<decltype(value)>>(data[pos++]); };
  238. const entt::entity entities[2u]{traits_type::construct(0u, 0u), traits_type::construct(2u, 0u)};
  239. ASSERT_FALSE(registry.valid(entities[0u]));
  240. ASSERT_FALSE(registry.valid(entities[1u]));
  241. data.emplace_back(static_cast<typename traits_type::entity_type>(1u));
  242. data.emplace_back(entities[0u]);
  243. loader.get<empty>(archive, "other"_hs);
  244. ASSERT_TRUE(registry.valid(entities[0u]));
  245. ASSERT_FALSE(registry.valid(entities[1u]));
  246. ASSERT_EQ(storage.size(), 0u);
  247. ASSERT_EQ(registry.storage<empty>("other"_hs).size(), 1u);
  248. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  249. data.emplace_back(entities[0u]);
  250. data.emplace_back(entities[1u]);
  251. loader.get<empty>(archive);
  252. ASSERT_TRUE(registry.valid(entities[0u]));
  253. ASSERT_TRUE(registry.valid(entities[1u]));
  254. ASSERT_EQ(storage.size(), 2u);
  255. ASSERT_TRUE(storage.contains(entities[0u]));
  256. ASSERT_TRUE(storage.contains(entities[1u]));
  257. }
  258. TEST(BasicSnapshotLoader, GetTypeSparse) {
  259. using namespace entt::literals;
  260. using traits_type = entt::entt_traits<entt::entity>;
  261. entt::registry registry;
  262. entt::basic_snapshot_loader loader{registry};
  263. const auto &storage = registry.storage<int>();
  264. std::vector<entt::any> data{};
  265. auto archive = [&data, pos = 0u](auto &value) mutable { value = entt::any_cast<std::remove_reference_t<decltype(value)>>(data[pos++]); };
  266. const entt::entity entities[2u]{traits_type::construct(0u, 0u), traits_type::construct(2u, 0u)};
  267. const int values[2u]{1, 3};
  268. ASSERT_FALSE(registry.valid(entities[0u]));
  269. ASSERT_FALSE(registry.valid(entities[1u]));
  270. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  271. data.emplace_back(static_cast<entt::entity>(entt::null));
  272. data.emplace_back(entities[0u]);
  273. data.emplace_back(values[0u]);
  274. loader.get<int>(archive, "other"_hs);
  275. ASSERT_TRUE(registry.valid(entities[0u]));
  276. ASSERT_FALSE(registry.valid(entities[1u]));
  277. ASSERT_EQ(storage.size(), 0u);
  278. ASSERT_EQ(registry.storage<int>("other"_hs).size(), 1u);
  279. data.emplace_back(static_cast<typename traits_type::entity_type>(3u));
  280. data.emplace_back(entities[0u]);
  281. data.emplace_back(values[0u]);
  282. data.emplace_back(static_cast<entt::entity>(entt::null));
  283. data.emplace_back(entities[1u]);
  284. data.emplace_back(values[1u]);
  285. loader.get<int>(archive);
  286. ASSERT_TRUE(registry.valid(entities[0u]));
  287. ASSERT_TRUE(registry.valid(entities[1u]));
  288. ASSERT_EQ(storage.size(), 2u);
  289. ASSERT_TRUE(storage.contains(entities[0u]));
  290. ASSERT_TRUE(storage.contains(entities[1u]));
  291. ASSERT_EQ(storage.get(entities[0u]), values[0u]);
  292. ASSERT_EQ(storage.get(entities[1u]), values[1u]);
  293. }
  294. TEST(BasicSnapshotLoader, Orphans) {
  295. using namespace entt::literals;
  296. using traits_type = entt::entt_traits<entt::entity>;
  297. entt::registry registry;
  298. entt::basic_snapshot_loader loader{registry};
  299. std::vector<entt::any> data{};
  300. auto archive = [&data, pos = 0u](auto &value) mutable { value = entt::any_cast<std::remove_reference_t<decltype(value)>>(data[pos++]); };
  301. const entt::entity entities[2u]{traits_type::construct(0u, 0u), traits_type::construct(2u, 0u)};
  302. const int value = 42;
  303. ASSERT_FALSE(registry.valid(entities[0u]));
  304. ASSERT_FALSE(registry.valid(entities[1u]));
  305. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  306. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  307. data.emplace_back(entities[0u]);
  308. data.emplace_back(entities[1u]);
  309. data.emplace_back(static_cast<typename traits_type::entity_type>(1u));
  310. data.emplace_back(entities[0u]);
  311. data.emplace_back(value);
  312. loader.get<entt::entity>(archive);
  313. loader.get<int>(archive);
  314. ASSERT_TRUE(registry.valid(entities[0u]));
  315. ASSERT_TRUE(registry.valid(entities[1u]));
  316. loader.orphans();
  317. ASSERT_TRUE(registry.valid(entities[0u]));
  318. ASSERT_FALSE(registry.valid(entities[1u]));
  319. }
  320. TEST(BasicContinuousLoader, Constructors) {
  321. static_assert(!std::is_default_constructible_v<entt::basic_continuous_loader<entt::registry>>);
  322. static_assert(!std::is_copy_constructible_v<entt::basic_continuous_loader<entt::registry>>);
  323. static_assert(!std::is_copy_assignable_v<entt::basic_continuous_loader<entt::registry>>);
  324. static_assert(std::is_move_constructible_v<entt::basic_continuous_loader<entt::registry>>);
  325. static_assert(std::is_move_assignable_v<entt::basic_continuous_loader<entt::registry>>);
  326. entt::registry registry;
  327. entt::basic_continuous_loader loader{registry};
  328. entt::basic_continuous_loader other{std::move(loader)};
  329. ASSERT_NO_FATAL_FAILURE(loader = std::move(other));
  330. }
  331. TEST(BasicContinuousLoader, GetEntityType) {
  332. using namespace entt::literals;
  333. using traits_type = entt::entt_traits<entt::entity>;
  334. entt::registry registry;
  335. entt::basic_continuous_loader loader{registry};
  336. const auto &storage = registry.storage<entt::entity>();
  337. std::vector<entt::any> data{};
  338. auto archive = [&data, pos = 0u](auto &value) mutable { value = entt::any_cast<std::remove_reference_t<decltype(value)>>(data[pos++]); };
  339. const entt::entity entities[3u]{traits_type::construct(1u, 0u), traits_type::construct(0u, 0u), traits_type::construct(2u, 0u)};
  340. ASSERT_FALSE(registry.valid(entities[0u]));
  341. ASSERT_FALSE(registry.valid(entities[1u]));
  342. ASSERT_FALSE(registry.valid(entities[2u]));
  343. data.emplace_back(static_cast<typename traits_type::entity_type>(0u));
  344. data.emplace_back(static_cast<typename traits_type::entity_type>(0u));
  345. loader.get<entt::entity>(archive);
  346. ASSERT_FALSE(registry.valid(entities[0u]));
  347. ASSERT_FALSE(registry.valid(entities[1u]));
  348. ASSERT_FALSE(registry.valid(entities[2u]));
  349. ASSERT_FALSE(loader.contains(entities[0u]));
  350. ASSERT_FALSE(loader.contains(entities[1u]));
  351. ASSERT_FALSE(loader.contains(entities[2u]));
  352. ASSERT_EQ(loader.map(entities[0u]), static_cast<entt::entity>(entt::null));
  353. ASSERT_EQ(loader.map(entities[1u]), static_cast<entt::entity>(entt::null));
  354. ASSERT_EQ(loader.map(entities[2u]), static_cast<entt::entity>(entt::null));
  355. ASSERT_EQ(storage.size(), 0u);
  356. ASSERT_EQ(storage.in_use(), 0u);
  357. data.emplace_back(static_cast<typename traits_type::entity_type>(3u));
  358. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  359. data.emplace_back(entities[0u]);
  360. data.emplace_back(entities[1u]);
  361. data.emplace_back(entities[2u]);
  362. loader.get<entt::entity>(archive, "ignored"_hs);
  363. ASSERT_TRUE(loader.contains(entities[0u]));
  364. ASSERT_TRUE(loader.contains(entities[1u]));
  365. ASSERT_FALSE(loader.contains(entities[2u]));
  366. ASSERT_NE(loader.map(entities[0u]), static_cast<entt::entity>(entt::null));
  367. ASSERT_NE(loader.map(entities[1u]), static_cast<entt::entity>(entt::null));
  368. ASSERT_EQ(loader.map(entities[2u]), static_cast<entt::entity>(entt::null));
  369. ASSERT_TRUE(registry.valid(loader.map(entities[0u])));
  370. ASSERT_TRUE(registry.valid(loader.map(entities[1u])));
  371. ASSERT_EQ(storage.size(), 2u);
  372. ASSERT_EQ(storage.in_use(), 2u);
  373. ASSERT_EQ(storage[0u], loader.map(entities[0u]));
  374. ASSERT_EQ(storage[1u], loader.map(entities[1u]));
  375. ASSERT_EQ(registry.create(), entities[2u]);
  376. data.emplace_back(static_cast<typename traits_type::entity_type>(3u));
  377. data.emplace_back(static_cast<typename traits_type::entity_type>(3u));
  378. data.emplace_back(entities[0u]);
  379. data.emplace_back(entities[1u]);
  380. data.emplace_back(entities[2u]);
  381. loader.get<entt::entity>(archive);
  382. ASSERT_TRUE(loader.contains(entities[0u]));
  383. ASSERT_TRUE(loader.contains(entities[1u]));
  384. ASSERT_TRUE(loader.contains(entities[2u]));
  385. ASSERT_NE(loader.map(entities[0u]), static_cast<entt::entity>(entt::null));
  386. ASSERT_NE(loader.map(entities[1u]), static_cast<entt::entity>(entt::null));
  387. ASSERT_NE(loader.map(entities[2u]), static_cast<entt::entity>(entt::null));
  388. ASSERT_TRUE(registry.valid(loader.map(entities[0u])));
  389. ASSERT_TRUE(registry.valid(loader.map(entities[1u])));
  390. ASSERT_TRUE(registry.valid(loader.map(entities[2u])));
  391. ASSERT_EQ(storage.size(), 4u);
  392. ASSERT_EQ(storage.in_use(), 4u);
  393. ASSERT_EQ(storage[0u], loader.map(entities[0u]));
  394. ASSERT_EQ(storage[1u], loader.map(entities[1u]));
  395. ASSERT_EQ(storage[3u], loader.map(entities[2u]));
  396. registry.destroy(loader.map(entities[1u]));
  397. ASSERT_TRUE(loader.contains(entities[1u]));
  398. ASSERT_NE(loader.map(entities[1u]), static_cast<entt::entity>(entt::null));
  399. ASSERT_FALSE(registry.valid(loader.map(entities[1u])));
  400. data.emplace_back(static_cast<typename traits_type::entity_type>(1u));
  401. data.emplace_back(static_cast<typename traits_type::entity_type>(1u));
  402. data.emplace_back(entities[1u]);
  403. loader.get<entt::entity>(archive);
  404. ASSERT_TRUE(loader.contains(entities[1u]));
  405. ASSERT_NE(loader.map(entities[1u]), static_cast<entt::entity>(entt::null));
  406. ASSERT_TRUE(registry.valid(loader.map(entities[1u])));
  407. ASSERT_EQ(storage[3u], loader.map(entities[1u]));
  408. data.emplace_back(static_cast<typename traits_type::entity_type>(3u));
  409. data.emplace_back(static_cast<typename traits_type::entity_type>(1u));
  410. data.emplace_back(entities[1u]);
  411. data.emplace_back(entities[2u]);
  412. data.emplace_back(entities[0u]);
  413. loader.get<entt::entity>(archive, "ignored"_hs);
  414. ASSERT_FALSE(loader.contains(entities[0u]));
  415. ASSERT_TRUE(loader.contains(entities[1u]));
  416. ASSERT_FALSE(loader.contains(entities[2u]));
  417. ASSERT_EQ(loader.map(entities[0u]), static_cast<entt::entity>(entt::null));
  418. ASSERT_NE(loader.map(entities[1u]), static_cast<entt::entity>(entt::null));
  419. ASSERT_EQ(loader.map(entities[2u]), static_cast<entt::entity>(entt::null));
  420. ASSERT_TRUE(registry.valid(loader.map(entities[1u])));
  421. ASSERT_EQ(storage.size(), 4u);
  422. ASSERT_EQ(storage.in_use(), 2u);
  423. ASSERT_EQ(storage[1u], loader.map(entities[1u]));
  424. }
  425. TEST(BasicContinuousLoader, GetType) {
  426. using namespace entt::literals;
  427. using traits_type = entt::entt_traits<entt::entity>;
  428. entt::registry registry;
  429. entt::basic_continuous_loader loader{registry};
  430. const auto &storage = registry.storage<int>();
  431. std::vector<entt::any> data{};
  432. auto archive = [&data, pos = 0u](auto &value) mutable { value = entt::any_cast<std::remove_reference_t<decltype(value)>>(data[pos++]); };
  433. const entt::entity entities[2u]{traits_type::construct(0u, 0u), traits_type::construct(2u, 0u)};
  434. const int values[2u]{1, 3};
  435. ASSERT_FALSE(loader.contains(entities[0u]));
  436. ASSERT_FALSE(loader.contains(entities[1u]));
  437. ASSERT_FALSE(registry.valid(loader.map(entities[0u])));
  438. ASSERT_FALSE(registry.valid(loader.map(entities[1u])));
  439. data.emplace_back(static_cast<typename traits_type::entity_type>(1u));
  440. data.emplace_back(entities[0u]);
  441. data.emplace_back(values[0u]);
  442. loader.get<int>(archive, "other"_hs);
  443. ASSERT_TRUE(loader.contains(entities[0u]));
  444. ASSERT_FALSE(loader.contains(entities[1u]));
  445. ASSERT_TRUE(registry.valid(loader.map(entities[0u])));
  446. ASSERT_FALSE(registry.valid(loader.map(entities[1u])));
  447. ASSERT_EQ(storage.size(), 0u);
  448. ASSERT_EQ(registry.storage<int>("other"_hs).size(), 1u);
  449. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  450. data.emplace_back(entities[0u]);
  451. data.emplace_back(values[0u]);
  452. data.emplace_back(entities[1u]);
  453. data.emplace_back(values[1u]);
  454. loader.get<int>(archive);
  455. ASSERT_TRUE(loader.contains(entities[0u]));
  456. ASSERT_TRUE(loader.contains(entities[1u]));
  457. ASSERT_TRUE(registry.valid(loader.map(entities[0u])));
  458. ASSERT_TRUE(registry.valid(loader.map(entities[1u])));
  459. ASSERT_EQ(storage.size(), 2u);
  460. ASSERT_TRUE(storage.contains(loader.map(entities[0u])));
  461. ASSERT_TRUE(storage.contains(loader.map(entities[1u])));
  462. ASSERT_EQ(storage.get(loader.map(entities[0u])), values[0u]);
  463. ASSERT_EQ(storage.get(loader.map(entities[1u])), values[1u]);
  464. }
  465. TEST(BasicContinuousLoader, GetTypeExtended) {
  466. using namespace entt::literals;
  467. using traits_type = entt::entt_traits<entt::entity>;
  468. entt::registry registry;
  469. entt::basic_continuous_loader loader{registry};
  470. const auto &storage = registry.storage<shadow>();
  471. std::vector<entt::any> data{};
  472. const entt::entity entities[2u]{traits_type::construct(0u, 1u), traits_type::construct(1u, 1u)};
  473. const shadow value{entities[0u]};
  474. auto archive = [&loader, &data, pos = 0u](auto &value) mutable {
  475. value = entt::any_cast<std::remove_reference_t<decltype(value)>>(data[pos++]);
  476. if constexpr(std::is_same_v<std::remove_reference_t<decltype(value)>, shadow>) {
  477. value.target = loader.map(value.target);
  478. }
  479. };
  480. ASSERT_FALSE(loader.contains(entities[0u]));
  481. ASSERT_FALSE(loader.contains(entities[1u]));
  482. ASSERT_FALSE(registry.valid(loader.map(entities[0u])));
  483. ASSERT_FALSE(registry.valid(loader.map(entities[1u])));
  484. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  485. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  486. data.emplace_back(entities[0u]);
  487. data.emplace_back(entities[1u]);
  488. data.emplace_back(static_cast<typename traits_type::entity_type>(1u));
  489. data.emplace_back(entities[1u]);
  490. data.emplace_back(value);
  491. loader.get<entt::entity>(archive);
  492. loader.get<shadow>(archive);
  493. ASSERT_TRUE(loader.contains(entities[0u]));
  494. ASSERT_TRUE(loader.contains(entities[1u]));
  495. ASSERT_TRUE(registry.valid(loader.map(entities[0u])));
  496. ASSERT_TRUE(registry.valid(loader.map(entities[1u])));
  497. ASSERT_FALSE(registry.valid(entities[0u]));
  498. ASSERT_FALSE(registry.valid(entities[1u]));
  499. ASSERT_EQ(storage.size(), 1u);
  500. ASSERT_TRUE(storage.contains(loader.map(entities[1u])));
  501. ASSERT_EQ(storage.get(loader.map(entities[1u])).target, loader.map(entities[0u]));
  502. }
  503. TEST(BasicContinuousLoader, GetEmptyType) {
  504. using namespace entt::literals;
  505. using traits_type = entt::entt_traits<entt::entity>;
  506. entt::registry registry;
  507. entt::basic_continuous_loader loader{registry};
  508. const auto &storage = registry.storage<empty>();
  509. std::vector<entt::any> data{};
  510. auto archive = [&data, pos = 0u](auto &value) mutable { value = entt::any_cast<std::remove_reference_t<decltype(value)>>(data[pos++]); };
  511. const entt::entity entities[2u]{traits_type::construct(0u, 0u), traits_type::construct(2u, 0u)};
  512. ASSERT_FALSE(loader.contains(entities[0u]));
  513. ASSERT_FALSE(loader.contains(entities[1u]));
  514. ASSERT_FALSE(registry.valid(loader.map(entities[0u])));
  515. ASSERT_FALSE(registry.valid(loader.map(entities[1u])));
  516. data.emplace_back(static_cast<typename traits_type::entity_type>(1u));
  517. data.emplace_back(entities[0u]);
  518. loader.get<empty>(archive, "other"_hs);
  519. ASSERT_TRUE(loader.contains(entities[0u]));
  520. ASSERT_FALSE(loader.contains(entities[1u]));
  521. ASSERT_TRUE(registry.valid(loader.map(entities[0u])));
  522. ASSERT_FALSE(registry.valid(loader.map(entities[1u])));
  523. ASSERT_EQ(storage.size(), 0u);
  524. ASSERT_EQ(registry.storage<empty>("other"_hs).size(), 1u);
  525. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  526. data.emplace_back(entities[0u]);
  527. data.emplace_back(entities[1u]);
  528. loader.get<empty>(archive);
  529. ASSERT_TRUE(loader.contains(entities[0u]));
  530. ASSERT_TRUE(loader.contains(entities[1u]));
  531. ASSERT_TRUE(registry.valid(loader.map(entities[0u])));
  532. ASSERT_TRUE(registry.valid(loader.map(entities[1u])));
  533. ASSERT_EQ(storage.size(), 2u);
  534. ASSERT_TRUE(storage.contains(loader.map(entities[0u])));
  535. ASSERT_TRUE(storage.contains(loader.map(entities[1u])));
  536. }
  537. TEST(BasicContinuousLoader, GetTypeSparse) {
  538. using namespace entt::literals;
  539. using traits_type = entt::entt_traits<entt::entity>;
  540. entt::registry registry;
  541. entt::basic_continuous_loader loader{registry};
  542. const auto &storage = registry.storage<int>();
  543. std::vector<entt::any> data{};
  544. auto archive = [&data, pos = 0u](auto &value) mutable { value = entt::any_cast<std::remove_reference_t<decltype(value)>>(data[pos++]); };
  545. const entt::entity entities[2u]{traits_type::construct(0u, 0u), traits_type::construct(2u, 0u)};
  546. const int values[2u]{1, 3};
  547. ASSERT_FALSE(loader.contains(entities[0u]));
  548. ASSERT_FALSE(loader.contains(entities[1u]));
  549. ASSERT_FALSE(registry.valid(loader.map(entities[0u])));
  550. ASSERT_FALSE(registry.valid(loader.map(entities[1u])));
  551. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  552. data.emplace_back(static_cast<entt::entity>(entt::null));
  553. data.emplace_back(entities[0u]);
  554. data.emplace_back(values[0u]);
  555. loader.get<int>(archive, "other"_hs);
  556. ASSERT_TRUE(loader.contains(entities[0u]));
  557. ASSERT_FALSE(loader.contains(entities[1u]));
  558. ASSERT_TRUE(registry.valid(loader.map(entities[0u])));
  559. ASSERT_FALSE(registry.valid(loader.map(entities[1u])));
  560. ASSERT_EQ(storage.size(), 0u);
  561. ASSERT_EQ(registry.storage<int>("other"_hs).size(), 1u);
  562. data.emplace_back(static_cast<typename traits_type::entity_type>(3u));
  563. data.emplace_back(entities[0u]);
  564. data.emplace_back(values[0u]);
  565. data.emplace_back(static_cast<entt::entity>(entt::null));
  566. data.emplace_back(entities[1u]);
  567. data.emplace_back(values[1u]);
  568. loader.get<int>(archive);
  569. ASSERT_TRUE(loader.contains(entities[0u]));
  570. ASSERT_TRUE(loader.contains(entities[1u]));
  571. ASSERT_TRUE(registry.valid(loader.map(entities[0u])));
  572. ASSERT_TRUE(registry.valid(loader.map(entities[1u])));
  573. ASSERT_EQ(storage.size(), 2u);
  574. ASSERT_TRUE(storage.contains(loader.map(entities[0u])));
  575. ASSERT_TRUE(storage.contains(loader.map(entities[1u])));
  576. ASSERT_EQ(storage.get(loader.map(entities[0u])), values[0u]);
  577. ASSERT_EQ(storage.get(loader.map(entities[1u])), values[1u]);
  578. }
  579. TEST(BasicContinuousLoader, Shrink) {
  580. entt::registry registry;
  581. entt::basic_continuous_loader loader{registry};
  582. ASSERT_NO_FATAL_FAILURE(loader.shrink());
  583. }
  584. TEST(BasicContinuousLoader, Orphans) {
  585. using namespace entt::literals;
  586. using traits_type = entt::entt_traits<entt::entity>;
  587. entt::registry registry;
  588. entt::basic_continuous_loader loader{registry};
  589. std::vector<entt::any> data{};
  590. auto archive = [&data, pos = 0u](auto &value) mutable { value = entt::any_cast<std::remove_reference_t<decltype(value)>>(data[pos++]); };
  591. const entt::entity entities[2u]{traits_type::construct(0u, 0u), traits_type::construct(2u, 0u)};
  592. const int value = 42;
  593. ASSERT_FALSE(registry.valid(entities[0u]));
  594. ASSERT_FALSE(registry.valid(entities[1u]));
  595. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  596. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  597. data.emplace_back(entities[0u]);
  598. data.emplace_back(entities[1u]);
  599. data.emplace_back(static_cast<typename traits_type::entity_type>(1u));
  600. data.emplace_back(entities[0u]);
  601. data.emplace_back(value);
  602. loader.get<entt::entity>(archive);
  603. loader.get<int>(archive);
  604. ASSERT_TRUE(loader.contains(entities[0u]));
  605. ASSERT_TRUE(loader.contains(entities[1u]));
  606. ASSERT_TRUE(registry.valid(loader.map(entities[0u])));
  607. ASSERT_TRUE(registry.valid(loader.map(entities[1u])));
  608. loader.orphans();
  609. ASSERT_TRUE(loader.contains(entities[0u]));
  610. ASSERT_TRUE(loader.contains(entities[1u]));
  611. ASSERT_TRUE(registry.valid(loader.map(entities[0u])));
  612. ASSERT_FALSE(registry.valid(loader.map(entities[1u])));
  613. }
  614. template<typename Storage>
  615. struct output_archive {
  616. output_archive(Storage &instance)
  617. : storage{instance} {}
  618. template<typename Value>
  619. void operator()(const Value &value) {
  620. std::get<std::queue<Value>>(storage).push(value);
  621. }
  622. void operator()(const std::unique_ptr<int> &instance) {
  623. (*this)(*instance);
  624. }
  625. private:
  626. Storage &storage;
  627. };
  628. template<typename Storage>
  629. struct input_archive {
  630. input_archive(Storage &instance)
  631. : storage{instance} {}
  632. template<typename Value>
  633. void operator()(Value &value) {
  634. auto assign = [this](auto &val) {
  635. auto &queue = std::get<std::queue<std::decay_t<decltype(val)>>>(storage);
  636. val = queue.front();
  637. queue.pop();
  638. };
  639. assign(value);
  640. }
  641. void operator()(std::unique_ptr<int> &instance) {
  642. instance = std::make_unique<int>();
  643. (*this)(*instance);
  644. }
  645. private:
  646. Storage &storage;
  647. };
  648. struct a_component {};
  649. struct another_component {
  650. int key{};
  651. int value{};
  652. };
  653. struct what_a_component {
  654. entt::entity bar{};
  655. std::vector<entt::entity> quux{};
  656. };
  657. struct map_component {
  658. std::map<entt::entity, int> keys{};
  659. std::map<int, entt::entity> values{};
  660. std::map<entt::entity, entt::entity> both{};
  661. };
  662. TEST(Snapshot, Dump) {
  663. using traits_type = entt::entt_traits<entt::entity>;
  664. entt::registry registry;
  665. const auto e0 = registry.create();
  666. registry.emplace<int>(e0, 42);
  667. registry.emplace<char>(e0, 'c');
  668. registry.emplace<double>(e0, .1);
  669. const auto e1 = registry.create();
  670. const auto e2 = registry.create();
  671. registry.emplace<int>(e2, 3);
  672. const auto e3 = registry.create();
  673. registry.emplace<a_component>(e3);
  674. registry.emplace<char>(e3, '0');
  675. registry.destroy(e1);
  676. auto v1 = registry.current(e1);
  677. using archive_type = std::tuple<
  678. std::queue<typename traits_type::entity_type>,
  679. std::queue<entt::entity>,
  680. std::queue<int>,
  681. std::queue<char>,
  682. std::queue<double>,
  683. std::queue<a_component>,
  684. std::queue<another_component>>;
  685. archive_type storage;
  686. output_archive<archive_type> output{storage};
  687. input_archive<archive_type> input{storage};
  688. entt::snapshot{registry}
  689. .entities(output)
  690. .component<int>(output)
  691. .component<char>(output)
  692. .component<double>(output)
  693. .component<a_component>(output)
  694. .component<another_component>(output);
  695. registry.clear();
  696. ASSERT_FALSE(registry.valid(e0));
  697. ASSERT_FALSE(registry.valid(e1));
  698. ASSERT_FALSE(registry.valid(e2));
  699. ASSERT_FALSE(registry.valid(e3));
  700. entt::snapshot_loader{registry}
  701. .entities(input)
  702. .component<int>(input)
  703. .component<char>(input)
  704. .component<double>(input)
  705. .component<a_component>(input)
  706. .component<another_component>(input)
  707. .orphans();
  708. ASSERT_TRUE(registry.valid(e0));
  709. ASSERT_FALSE(registry.valid(e1));
  710. ASSERT_TRUE(registry.valid(e2));
  711. ASSERT_TRUE(registry.valid(e3));
  712. ASSERT_FALSE(registry.orphan(e0));
  713. ASSERT_FALSE(registry.orphan(e2));
  714. ASSERT_FALSE(registry.orphan(e3));
  715. ASSERT_EQ(registry.get<int>(e0), 42);
  716. ASSERT_EQ(registry.get<char>(e0), 'c');
  717. ASSERT_EQ(registry.get<double>(e0), .1);
  718. ASSERT_EQ(registry.current(e1), v1);
  719. ASSERT_EQ(registry.get<int>(e2), 3);
  720. ASSERT_EQ(registry.get<char>(e3), '0');
  721. ASSERT_TRUE(registry.all_of<a_component>(e3));
  722. ASSERT_TRUE(registry.storage<another_component>().empty());
  723. }
  724. TEST(Snapshot, Partial) {
  725. using traits_type = entt::entt_traits<entt::entity>;
  726. entt::registry registry;
  727. const auto e0 = registry.create();
  728. registry.emplace<int>(e0, 42);
  729. registry.emplace<char>(e0, 'c');
  730. registry.emplace<double>(e0, .1);
  731. const auto e1 = registry.create();
  732. const auto e2 = registry.create();
  733. registry.emplace<int>(e2, 3);
  734. const auto e3 = registry.create();
  735. registry.emplace<char>(e3, '0');
  736. registry.destroy(e1);
  737. auto v1 = registry.current(e1);
  738. using archive_type = std::tuple<
  739. std::queue<typename traits_type::entity_type>,
  740. std::queue<entt::entity>,
  741. std::queue<int>,
  742. std::queue<char>,
  743. std::queue<double>>;
  744. archive_type storage;
  745. output_archive<archive_type> output{storage};
  746. input_archive<archive_type> input{storage};
  747. entt::snapshot{registry}
  748. .entities(output)
  749. .component<char>(output)
  750. .component<int>(output);
  751. registry.clear();
  752. ASSERT_FALSE(registry.valid(e0));
  753. ASSERT_FALSE(registry.valid(e1));
  754. ASSERT_FALSE(registry.valid(e2));
  755. ASSERT_FALSE(registry.valid(e3));
  756. entt::snapshot_loader{registry}
  757. .entities(input)
  758. .component<char>(input)
  759. .component<int>(input);
  760. ASSERT_TRUE(registry.valid(e0));
  761. ASSERT_FALSE(registry.valid(e1));
  762. ASSERT_TRUE(registry.valid(e2));
  763. ASSERT_TRUE(registry.valid(e3));
  764. ASSERT_EQ(registry.get<int>(e0), 42);
  765. ASSERT_EQ(registry.get<char>(e0), 'c');
  766. ASSERT_FALSE(registry.all_of<double>(e0));
  767. ASSERT_EQ(registry.current(e1), v1);
  768. ASSERT_EQ(registry.get<int>(e2), 3);
  769. ASSERT_EQ(registry.get<char>(e3), '0');
  770. entt::snapshot{registry}
  771. .entities(output);
  772. registry.clear();
  773. ASSERT_FALSE(registry.valid(e0));
  774. ASSERT_FALSE(registry.valid(e1));
  775. ASSERT_FALSE(registry.valid(e2));
  776. ASSERT_FALSE(registry.valid(e3));
  777. entt::snapshot_loader{registry}
  778. .entities(input)
  779. .orphans();
  780. ASSERT_FALSE(registry.valid(e0));
  781. ASSERT_FALSE(registry.valid(e1));
  782. ASSERT_FALSE(registry.valid(e2));
  783. ASSERT_FALSE(registry.valid(e3));
  784. }
  785. TEST(Snapshot, Iterator) {
  786. using traits_type = entt::entt_traits<entt::entity>;
  787. entt::registry registry;
  788. for(auto i = 0; i < 50; ++i) {
  789. const auto entity = registry.create();
  790. registry.emplace<a_component>(entity);
  791. if(i % 2) {
  792. registry.emplace<another_component>(entity, i, i);
  793. registry.emplace<std::unique_ptr<int>>(entity, std::make_unique<int>(i));
  794. }
  795. }
  796. using archive_type = std::tuple<
  797. std::queue<typename traits_type::entity_type>,
  798. std::queue<entt::entity>,
  799. std::queue<another_component>,
  800. std::queue<int>>;
  801. archive_type storage;
  802. output_archive<archive_type> output{storage};
  803. input_archive<archive_type> input{storage};
  804. const auto view = registry.view<a_component>();
  805. const auto size = view.size();
  806. entt::snapshot{registry}
  807. .component<another_component>(output, view.begin(), view.end())
  808. .component<std::unique_ptr<int>>(output, view.begin(), view.end());
  809. registry.clear();
  810. entt::snapshot_loader{registry}
  811. .component<another_component>(input)
  812. .component<std::unique_ptr<int>>(input);
  813. ASSERT_EQ(registry.view<another_component>().size(), size / 2u);
  814. registry.view<another_component>().each([](const auto entity, const auto &) {
  815. ASSERT_NE(entt::to_integral(entity) % 2u, 0u);
  816. });
  817. }
  818. TEST(Snapshot, Continuous) {
  819. using traits_type = entt::entt_traits<entt::entity>;
  820. entt::registry src;
  821. entt::registry dst;
  822. entt::continuous_loader loader{dst};
  823. std::vector<entt::entity> entities;
  824. entt::entity entity;
  825. using archive_type = std::tuple<
  826. std::queue<typename traits_type::entity_type>,
  827. std::queue<entt::entity>,
  828. std::queue<another_component>,
  829. std::queue<what_a_component>,
  830. std::queue<map_component>,
  831. std::queue<int>,
  832. std::queue<double>>;
  833. archive_type storage;
  834. output_archive<archive_type> output{storage};
  835. input_archive<archive_type> input{storage};
  836. for(int i = 0; i < 10; ++i) {
  837. static_cast<void>(src.create());
  838. }
  839. src.clear();
  840. for(int i = 0; i < 5; ++i) {
  841. entity = src.create();
  842. entities.push_back(entity);
  843. src.emplace<a_component>(entity);
  844. src.emplace<another_component>(entity, i, i);
  845. src.emplace<std::unique_ptr<int>>(entity, std::make_unique<int>(i));
  846. if(i % 2) {
  847. src.emplace<what_a_component>(entity, entity);
  848. } else {
  849. src.emplace<map_component>(entity);
  850. }
  851. }
  852. src.view<what_a_component>().each([&entities](auto, auto &what_a_component) {
  853. what_a_component.quux.insert(what_a_component.quux.begin(), entities.begin(), entities.end());
  854. });
  855. src.view<map_component>().each([&entities](auto, auto &map_component) {
  856. for(std::size_t i = 0; i < entities.size(); ++i) {
  857. map_component.keys.insert({entities[i], int(i)});
  858. map_component.values.insert({int(i), entities[i]});
  859. map_component.both.insert({entities[entities.size() - i - 1], entities[i]});
  860. }
  861. });
  862. entity = dst.create();
  863. dst.emplace<a_component>(entity);
  864. dst.emplace<another_component>(entity, -1, -1);
  865. dst.emplace<std::unique_ptr<int>>(entity, std::make_unique<int>(-1));
  866. entt::snapshot{src}
  867. .entities(output)
  868. .component<a_component>(output)
  869. .component<another_component>(output)
  870. .component<what_a_component>(output)
  871. .component<map_component>(output)
  872. .component<std::unique_ptr<int>>(output);
  873. loader
  874. .entities(input)
  875. .component<a_component>(input)
  876. .component<another_component>(input)
  877. .component<what_a_component>(input, &what_a_component::bar, &what_a_component::quux)
  878. .component<map_component>(input, &map_component::keys, &map_component::values, &map_component::both)
  879. .component<std::unique_ptr<int>>(input)
  880. .orphans();
  881. decltype(dst.size()) a_component_cnt{};
  882. decltype(dst.size()) another_component_cnt{};
  883. decltype(dst.size()) what_a_component_cnt{};
  884. decltype(dst.size()) map_component_cnt{};
  885. decltype(dst.size()) unique_ptr_cnt{};
  886. dst.each([&dst, &a_component_cnt](auto entt) {
  887. ASSERT_TRUE(dst.all_of<a_component>(entt));
  888. ++a_component_cnt;
  889. });
  890. dst.view<another_component>().each([&another_component_cnt](auto, const auto &component) {
  891. ASSERT_EQ(component.value, component.key < 0 ? -1 : component.key);
  892. ++another_component_cnt;
  893. });
  894. dst.view<what_a_component>().each([&dst, &what_a_component_cnt](auto entt, const auto &component) {
  895. ASSERT_EQ(entt, component.bar);
  896. for(auto child: component.quux) {
  897. ASSERT_TRUE(dst.valid(child));
  898. }
  899. ++what_a_component_cnt;
  900. });
  901. dst.view<map_component>().each([&dst, &map_component_cnt](const auto &component) {
  902. for(auto child: component.keys) {
  903. ASSERT_TRUE(dst.valid(child.first));
  904. }
  905. for(auto child: component.values) {
  906. ASSERT_TRUE(dst.valid(child.second));
  907. }
  908. for(auto child: component.both) {
  909. ASSERT_TRUE(dst.valid(child.first));
  910. ASSERT_TRUE(dst.valid(child.second));
  911. }
  912. ++map_component_cnt;
  913. });
  914. dst.view<std::unique_ptr<int>>().each([&dst, &unique_ptr_cnt](auto, const auto &component) {
  915. ++unique_ptr_cnt;
  916. ASSERT_EQ(*component, static_cast<int>(dst.storage<std::unique_ptr<int>>().size() - unique_ptr_cnt - 1u));
  917. });
  918. src.view<another_component>().each([](auto, auto &component) {
  919. component.value = 2 * component.key;
  920. });
  921. auto size = dst.size();
  922. entt::snapshot{src}
  923. .entities(output)
  924. .component<a_component>(output)
  925. .component<what_a_component>(output)
  926. .component<map_component>(output)
  927. .component<another_component>(output);
  928. loader
  929. .entities(input)
  930. .component<a_component>(input)
  931. .component<what_a_component>(input, &what_a_component::bar, &what_a_component::quux)
  932. .component<map_component>(input, &map_component::keys, &map_component::values, &map_component::both)
  933. .component<another_component>(input)
  934. .orphans();
  935. ASSERT_EQ(size, dst.size());
  936. ASSERT_EQ(dst.storage<a_component>().size(), a_component_cnt);
  937. ASSERT_EQ(dst.storage<another_component>().size(), another_component_cnt);
  938. ASSERT_EQ(dst.storage<what_a_component>().size(), what_a_component_cnt);
  939. ASSERT_EQ(dst.storage<map_component>().size(), map_component_cnt);
  940. ASSERT_EQ(dst.storage<std::unique_ptr<int>>().size(), unique_ptr_cnt);
  941. dst.view<another_component>().each([](auto, auto &component) {
  942. ASSERT_EQ(component.value, component.key < 0 ? -1 : (2 * component.key));
  943. });
  944. entity = src.create();
  945. src.view<what_a_component>().each([entity](auto, auto &component) {
  946. component.bar = entity;
  947. });
  948. entt::snapshot{src}
  949. .entities(output)
  950. .component<a_component>(output)
  951. .component<what_a_component>(output)
  952. .component<map_component>(output)
  953. .component<another_component>(output);
  954. loader
  955. .entities(input)
  956. .component<a_component>(input)
  957. .component<what_a_component>(input, &what_a_component::bar, &what_a_component::quux)
  958. .component<map_component>(input, &map_component::keys, &map_component::values, &map_component::both)
  959. .component<another_component>(input)
  960. .orphans();
  961. dst.view<what_a_component>().each([&loader, entity](auto, auto &component) {
  962. ASSERT_EQ(component.bar, loader.map(entity));
  963. });
  964. entities.clear();
  965. for(auto entt: src.view<a_component>()) {
  966. entities.push_back(entt);
  967. }
  968. src.destroy(entity);
  969. loader.shrink();
  970. entt::snapshot{src}
  971. .entities(output)
  972. .component<a_component>(output)
  973. .component<another_component>(output)
  974. .component<what_a_component>(output)
  975. .component<map_component>(output);
  976. loader
  977. .entities(input)
  978. .component<a_component>(input)
  979. .component<another_component>(input)
  980. .component<what_a_component>(input, &what_a_component::bar, &what_a_component::quux)
  981. .component<map_component>(input, &map_component::keys, &map_component::values, &map_component::both)
  982. .orphans()
  983. .shrink();
  984. dst.view<what_a_component>().each([&dst](auto, auto &component) {
  985. ASSERT_FALSE(dst.valid(component.bar));
  986. });
  987. ASSERT_FALSE(loader.contains(entity));
  988. entity = src.create();
  989. src.view<what_a_component>().each([entity](auto, auto &component) {
  990. component.bar = entity;
  991. });
  992. dst.clear<a_component>();
  993. a_component_cnt = src.storage<a_component>().size();
  994. entt::snapshot{src}
  995. .entities(output)
  996. .component<a_component>(output)
  997. .component<what_a_component>(output)
  998. .component<map_component>(output)
  999. .component<another_component>(output);
  1000. loader
  1001. .entities(input)
  1002. .component<a_component>(input)
  1003. .component<what_a_component>(input, &what_a_component::bar, &what_a_component::quux)
  1004. .component<map_component>(input, &map_component::keys, &map_component::values, &map_component::both)
  1005. .component<another_component>(input)
  1006. .orphans();
  1007. ASSERT_EQ(dst.storage<a_component>().size(), a_component_cnt);
  1008. src.clear<a_component>();
  1009. a_component_cnt = {};
  1010. entt::snapshot{src}
  1011. .entities(output)
  1012. .component<what_a_component>(output)
  1013. .component<map_component>(output)
  1014. .component<a_component>(output)
  1015. .component<another_component>(output);
  1016. loader
  1017. .entities(input)
  1018. .component<what_a_component>(input, &what_a_component::bar, &what_a_component::quux)
  1019. .component<map_component>(input, &map_component::keys, &map_component::values, &map_component::both)
  1020. .component<a_component>(input)
  1021. .component<another_component>(input)
  1022. .orphans();
  1023. ASSERT_EQ(dst.storage<a_component>().size(), a_component_cnt);
  1024. }
  1025. TEST(Snapshot, SyncDataMembers) {
  1026. using traits_type = entt::entt_traits<entt::entity>;
  1027. entt::registry src;
  1028. entt::registry dst;
  1029. entt::continuous_loader loader{dst};
  1030. using archive_type = std::tuple<
  1031. std::queue<typename traits_type::entity_type>,
  1032. std::queue<entt::entity>,
  1033. std::queue<what_a_component>,
  1034. std::queue<map_component>>;
  1035. archive_type storage;
  1036. output_archive<archive_type> output{storage};
  1037. input_archive<archive_type> input{storage};
  1038. static_cast<void>(src.create());
  1039. static_cast<void>(src.create());
  1040. src.clear();
  1041. auto parent = src.create();
  1042. auto child = src.create();
  1043. src.emplace<what_a_component>(parent, entt::null);
  1044. src.emplace<what_a_component>(child, parent).quux.push_back(child);
  1045. src.emplace<map_component>(
  1046. child,
  1047. decltype(map_component::keys){{{child, 10}}},
  1048. decltype(map_component::values){{{10, child}}},
  1049. decltype(map_component::both){{{child, child}}});
  1050. entt::snapshot{src}
  1051. .entities(output)
  1052. .component<what_a_component>(output)
  1053. .component<map_component>(output);
  1054. loader
  1055. .entities(input)
  1056. .component<what_a_component>(input, &what_a_component::bar, &what_a_component::quux)
  1057. .component<map_component>(input, &map_component::keys, &map_component::values, &map_component::both);
  1058. ASSERT_FALSE(dst.valid(parent));
  1059. ASSERT_FALSE(dst.valid(child));
  1060. ASSERT_TRUE(dst.all_of<what_a_component>(loader.map(parent)));
  1061. ASSERT_TRUE(dst.all_of<what_a_component>(loader.map(child)));
  1062. ASSERT_EQ(dst.get<what_a_component>(loader.map(parent)).bar, static_cast<entt::entity>(entt::null));
  1063. const auto &component = dst.get<what_a_component>(loader.map(child));
  1064. ASSERT_EQ(component.bar, loader.map(parent));
  1065. ASSERT_EQ(component.quux[0], loader.map(child));
  1066. const auto &elem = dst.get<map_component>(loader.map(child));
  1067. ASSERT_EQ(elem.keys.at(loader.map(child)), 10);
  1068. ASSERT_EQ(elem.values.at(10), loader.map(child));
  1069. ASSERT_EQ(elem.both.at(loader.map(child)), loader.map(child));
  1070. }