snapshot.cpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  1. #include <iterator>
  2. #include <type_traits>
  3. #include <utility>
  4. #include <vector>
  5. #include <gtest/gtest.h>
  6. #include <entt/core/any.hpp>
  7. #include <entt/core/hashed_string.hpp>
  8. #include <entt/entity/entity.hpp>
  9. #include <entt/entity/registry.hpp>
  10. #include <entt/entity/snapshot.hpp>
  11. #include <entt/signal/sigh.hpp>
  12. #include "../common/config.h"
  13. #include "../common/empty.h"
  14. struct shadow {
  15. entt::entity target{entt::null};
  16. static void listener(entt::entity &elem, entt::registry &registry, const entt::entity entt) {
  17. elem = registry.get<shadow>(entt).target;
  18. }
  19. };
  20. TEST(BasicSnapshot, Constructors) {
  21. static_assert(!std::is_default_constructible_v<entt::basic_snapshot<entt::registry>>, "Default constructible type not allowed");
  22. static_assert(!std::is_copy_constructible_v<entt::basic_snapshot<entt::registry>>, "Copy constructible type not allowed");
  23. static_assert(!std::is_copy_assignable_v<entt::basic_snapshot<entt::registry>>, "Copy assignable type not allowed");
  24. static_assert(std::is_move_constructible_v<entt::basic_snapshot<entt::registry>>, "Move constructible type required");
  25. static_assert(std::is_move_assignable_v<entt::basic_snapshot<entt::registry>>, "Move assignable type required");
  26. const entt::registry registry;
  27. entt::basic_snapshot snapshot{registry};
  28. entt::basic_snapshot other{std::move(snapshot)};
  29. ASSERT_NO_THROW(snapshot = std::move(other));
  30. }
  31. TEST(BasicSnapshot, GetEntityType) {
  32. using namespace entt::literals;
  33. using traits_type = entt::entt_traits<entt::entity>;
  34. entt::registry registry;
  35. const entt::basic_snapshot snapshot{registry};
  36. const auto &storage = registry.storage<entt::entity>();
  37. std::vector<entt::any> data{};
  38. auto archive = [&data](auto &&elem) { data.emplace_back(std::forward<decltype(elem)>(elem)); };
  39. snapshot.get<entt::entity>(archive);
  40. ASSERT_EQ(data.size(), 2u);
  41. ASSERT_NE(entt::any_cast<typename traits_type::entity_type>(&data[0u]), nullptr);
  42. ASSERT_EQ(entt::any_cast<typename traits_type::entity_type>(data[0u]), storage.size());
  43. ASSERT_NE(entt::any_cast<typename traits_type::entity_type>(&data[1u]), nullptr);
  44. ASSERT_EQ(entt::any_cast<typename traits_type::entity_type>(data[1u]), storage.free_list());
  45. entt::entity entity[3u]; // NOLINT
  46. registry.create(std::begin(entity), std::end(entity));
  47. registry.destroy(entity[1u]);
  48. data.clear();
  49. snapshot.get<entt::entity>(archive, "ignored"_hs);
  50. ASSERT_EQ(data.size(), 5u);
  51. ASSERT_NE(entt::any_cast<typename traits_type::entity_type>(&data[0u]), nullptr);
  52. ASSERT_EQ(entt::any_cast<typename traits_type::entity_type>(data[0u]), storage.size());
  53. ASSERT_NE(entt::any_cast<typename traits_type::entity_type>(&data[1u]), nullptr);
  54. ASSERT_EQ(entt::any_cast<typename traits_type::entity_type>(data[1u]), storage.free_list());
  55. ASSERT_NE(entt::any_cast<entt::entity>(&data[2u]), nullptr);
  56. ASSERT_EQ(entt::any_cast<entt::entity>(data[2u]), storage.data()[0u]);
  57. ASSERT_NE(entt::any_cast<entt::entity>(&data[3u]), nullptr);
  58. ASSERT_EQ(entt::any_cast<entt::entity>(data[3u]), storage.data()[1u]);
  59. ASSERT_NE(entt::any_cast<entt::entity>(&data[4u]), nullptr);
  60. ASSERT_EQ(entt::any_cast<entt::entity>(data[4u]), storage.data()[2u]);
  61. }
  62. TEST(BasicSnapshot, GetType) {
  63. using namespace entt::literals;
  64. using traits_type = entt::entt_traits<entt::entity>;
  65. entt::registry registry;
  66. const entt::basic_snapshot snapshot{registry};
  67. const auto &storage = registry.storage<int>();
  68. entt::entity entity[3u]; // NOLINT
  69. const int values[3u]{1, 2, 3}; // NOLINT
  70. registry.create(std::begin(entity), std::end(entity));
  71. registry.insert<int>(std::begin(entity), std::end(entity), std::begin(values));
  72. registry.destroy(entity[1u]);
  73. std::vector<entt::any> data{};
  74. auto archive = [&data](auto &&elem) { data.emplace_back(std::forward<decltype(elem)>(elem)); };
  75. snapshot.get<int>(archive, "other"_hs);
  76. ASSERT_EQ(data.size(), 1u);
  77. ASSERT_NE(entt::any_cast<typename traits_type::entity_type>(&data[0u]), nullptr);
  78. ASSERT_EQ(entt::any_cast<typename traits_type::entity_type>(data[0u]), 0u);
  79. data.clear();
  80. snapshot.get<int>(archive);
  81. ASSERT_EQ(data.size(), 5u);
  82. ASSERT_NE(entt::any_cast<typename traits_type::entity_type>(&data[0u]), nullptr);
  83. ASSERT_EQ(entt::any_cast<typename traits_type::entity_type>(data[0u]), storage.size());
  84. ASSERT_NE(entt::any_cast<entt::entity>(&data[1u]), nullptr);
  85. ASSERT_EQ(entt::any_cast<entt::entity>(data[1u]), entity[0u]);
  86. ASSERT_NE(entt::any_cast<int>(&data[2u]), nullptr);
  87. ASSERT_EQ(entt::any_cast<int>(data[2u]), values[0u]);
  88. ASSERT_NE(entt::any_cast<entt::entity>(&data[3u]), nullptr);
  89. ASSERT_EQ(entt::any_cast<entt::entity>(data[3u]), entity[2u]);
  90. ASSERT_NE(entt::any_cast<int>(&data[4u]), nullptr);
  91. ASSERT_EQ(entt::any_cast<int>(data[4u]), values[2u]);
  92. }
  93. TEST(BasicSnapshot, GetEmptyType) {
  94. using namespace entt::literals;
  95. using traits_type = entt::entt_traits<entt::entity>;
  96. entt::registry registry;
  97. const entt::basic_snapshot snapshot{registry};
  98. const auto &storage = registry.storage<test::empty>();
  99. entt::entity entity[3u]; // NOLINT
  100. registry.create(std::begin(entity), std::end(entity));
  101. registry.insert<test::empty>(std::begin(entity), std::end(entity));
  102. registry.destroy(entity[1u]);
  103. std::vector<entt::any> data{};
  104. auto archive = [&data](auto &&elem) { data.emplace_back(std::forward<decltype(elem)>(elem)); };
  105. snapshot.get<test::empty>(archive, "other"_hs);
  106. ASSERT_EQ(data.size(), 1u);
  107. ASSERT_NE(entt::any_cast<typename traits_type::entity_type>(&data[0u]), nullptr);
  108. ASSERT_EQ(entt::any_cast<typename traits_type::entity_type>(data[0u]), 0u);
  109. data.clear();
  110. snapshot.get<test::empty>(archive);
  111. ASSERT_EQ(data.size(), 3u);
  112. ASSERT_NE(entt::any_cast<typename traits_type::entity_type>(&data[0u]), nullptr);
  113. ASSERT_EQ(entt::any_cast<typename traits_type::entity_type>(data[0u]), storage.size());
  114. ASSERT_NE(entt::any_cast<entt::entity>(&data[1u]), nullptr);
  115. ASSERT_EQ(entt::any_cast<entt::entity>(data[1u]), entity[0u]);
  116. ASSERT_NE(entt::any_cast<entt::entity>(&data[2u]), nullptr);
  117. ASSERT_EQ(entt::any_cast<entt::entity>(data[2u]), entity[2u]);
  118. }
  119. TEST(BasicSnapshot, GetTypeSparse) {
  120. using namespace entt::literals;
  121. using traits_type = entt::entt_traits<entt::entity>;
  122. entt::registry registry;
  123. const entt::basic_snapshot snapshot{registry};
  124. entt::entity entity[3u]; // NOLINT
  125. const int values[3u]{1, 2, 3}; // NOLINT
  126. registry.create(std::begin(entity), std::end(entity));
  127. registry.insert<int>(std::begin(entity), std::end(entity), std::begin(values));
  128. registry.destroy(entity[1u]);
  129. std::vector<entt::any> data{};
  130. auto archive = [&data](auto &&elem) { data.emplace_back(std::forward<decltype(elem)>(elem)); };
  131. snapshot.get<int>(archive, std::begin(entity), std::end(entity), "other"_hs);
  132. ASSERT_EQ(data.size(), 1u);
  133. ASSERT_NE(entt::any_cast<typename traits_type::entity_type>(&data[0u]), nullptr);
  134. ASSERT_EQ(entt::any_cast<typename traits_type::entity_type>(data[0u]), 0u);
  135. data.clear();
  136. snapshot.get<int>(archive, std::begin(entity), std::end(entity));
  137. ASSERT_EQ(data.size(), 6u);
  138. ASSERT_NE(entt::any_cast<typename traits_type::entity_type>(&data[0u]), nullptr);
  139. ASSERT_EQ(entt::any_cast<typename traits_type::entity_type>(data[0u]), static_cast<typename traits_type::entity_type>(std::distance(std::begin(entity), std::end(entity))));
  140. ASSERT_NE(entt::any_cast<entt::entity>(&data[1u]), nullptr);
  141. ASSERT_EQ(entt::any_cast<entt::entity>(data[1u]), entity[0u]);
  142. ASSERT_NE(entt::any_cast<int>(&data[2u]), nullptr);
  143. ASSERT_EQ(entt::any_cast<int>(data[2u]), values[0u]);
  144. ASSERT_NE(entt::any_cast<entt::entity>(&data[3u]), nullptr);
  145. ASSERT_EQ(entt::any_cast<entt::entity>(data[3u]), static_cast<entt::entity>(entt::null));
  146. ASSERT_NE(entt::any_cast<entt::entity>(&data[4u]), nullptr);
  147. ASSERT_EQ(entt::any_cast<entt::entity>(data[4u]), entity[2u]);
  148. ASSERT_NE(entt::any_cast<int>(&data[5u]), nullptr);
  149. ASSERT_EQ(entt::any_cast<int>(data[5u]), values[2u]);
  150. }
  151. TEST(BasicSnapshotLoader, Constructors) {
  152. static_assert(!std::is_default_constructible_v<entt::basic_snapshot_loader<entt::registry>>, "Default constructible type not allowed");
  153. static_assert(!std::is_copy_constructible_v<entt::basic_snapshot_loader<entt::registry>>, "Copy constructible type not allowed");
  154. static_assert(!std::is_copy_assignable_v<entt::basic_snapshot_loader<entt::registry>>, "Copy assignable type not allowed");
  155. static_assert(std::is_move_constructible_v<entt::basic_snapshot_loader<entt::registry>>, "Move constructible type required");
  156. static_assert(std::is_move_assignable_v<entt::basic_snapshot_loader<entt::registry>>, "Move assignable type required");
  157. entt::registry registry;
  158. entt::basic_snapshot_loader loader{registry};
  159. entt::basic_snapshot_loader other{std::move(loader)};
  160. ASSERT_NO_THROW(loader = std::move(other));
  161. }
  162. ENTT_DEBUG_TEST(BasicSnapshotLoaderDeathTest, Constructors) {
  163. entt::registry registry;
  164. registry.emplace<int>(registry.create());
  165. ASSERT_DEATH([[maybe_unused]] const entt::basic_snapshot_loader loader{registry}, "");
  166. }
  167. TEST(BasicSnapshotLoader, GetEntityType) {
  168. using namespace entt::literals;
  169. using traits_type = entt::entt_traits<entt::entity>;
  170. entt::registry registry;
  171. entt::basic_snapshot_loader loader{registry};
  172. const auto &storage = registry.storage<entt::entity>();
  173. std::vector<entt::any> data{};
  174. auto archive = [&data, pos = 0u](auto &elem) mutable { elem = entt::any_cast<std::remove_reference_t<decltype(elem)>>(data[pos++]); };
  175. const entt::entity entity[3u]{traits_type::construct(0u, 0u), traits_type::construct(2u, 0u), traits_type::construct(1u, 1u)}; // NOLINT
  176. ASSERT_FALSE(registry.valid(entity[0u]));
  177. ASSERT_FALSE(registry.valid(entity[1u]));
  178. ASSERT_FALSE(registry.valid(entity[2u]));
  179. data.emplace_back(static_cast<typename traits_type::entity_type>(0u));
  180. data.emplace_back(static_cast<typename traits_type::entity_type>(0u));
  181. loader.get<entt::entity>(archive);
  182. ASSERT_FALSE(registry.valid(entity[0u]));
  183. ASSERT_FALSE(registry.valid(entity[1u]));
  184. ASSERT_FALSE(registry.valid(entity[2u]));
  185. ASSERT_EQ(storage.size(), 0u);
  186. ASSERT_EQ(storage.free_list(), 0u);
  187. data.emplace_back(static_cast<typename traits_type::entity_type>(3u));
  188. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  189. data.emplace_back(entity[0u]);
  190. data.emplace_back(entity[1u]);
  191. data.emplace_back(entity[2u]);
  192. loader.get<entt::entity>(archive, "ignored"_hs);
  193. ASSERT_TRUE(registry.valid(entity[0u]));
  194. ASSERT_TRUE(registry.valid(entity[1u]));
  195. ASSERT_FALSE(registry.valid(entity[2u]));
  196. ASSERT_EQ(storage.size(), 3u);
  197. ASSERT_EQ(storage.free_list(), 2u);
  198. ASSERT_EQ(storage[0u], entity[0u]);
  199. ASSERT_EQ(storage[1u], entity[1u]);
  200. ASSERT_EQ(storage[2u], entity[2u]);
  201. ASSERT_EQ(registry.create(), entity[2u]);
  202. }
  203. TEST(BasicSnapshotLoader, GetType) {
  204. using namespace entt::literals;
  205. using traits_type = entt::entt_traits<entt::entity>;
  206. entt::registry registry;
  207. entt::basic_snapshot_loader loader{registry};
  208. const auto &storage = registry.storage<int>();
  209. std::vector<entt::any> data{};
  210. auto archive = [&data, pos = 0u](auto &elem) mutable { elem = entt::any_cast<std::remove_reference_t<decltype(elem)>>(data[pos++]); };
  211. const entt::entity entity[2u]{traits_type::construct(0u, 0u), traits_type::construct(2u, 0u)}; // NOLINT
  212. const int values[2u]{1, 3}; // NOLINT
  213. ASSERT_FALSE(registry.valid(entity[0u]));
  214. ASSERT_FALSE(registry.valid(entity[1u]));
  215. data.emplace_back(static_cast<typename traits_type::entity_type>(1u));
  216. data.emplace_back(entity[0u]);
  217. data.emplace_back(values[0u]);
  218. loader.get<int>(archive, "other"_hs);
  219. ASSERT_TRUE(registry.valid(entity[0u]));
  220. ASSERT_FALSE(registry.valid(entity[1u]));
  221. ASSERT_EQ(storage.size(), 0u);
  222. ASSERT_EQ(registry.storage<int>("other"_hs).size(), 1u);
  223. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  224. data.emplace_back(entity[0u]);
  225. data.emplace_back(values[0u]);
  226. data.emplace_back(entity[1u]);
  227. data.emplace_back(values[1u]);
  228. loader.get<int>(archive);
  229. ASSERT_TRUE(registry.valid(entity[0u]));
  230. ASSERT_TRUE(registry.valid(entity[1u]));
  231. ASSERT_EQ(storage.size(), 2u);
  232. ASSERT_TRUE(storage.contains(entity[0u]));
  233. ASSERT_TRUE(storage.contains(entity[1u]));
  234. ASSERT_EQ(storage.get(entity[0u]), values[0u]);
  235. ASSERT_EQ(storage.get(entity[1u]), values[1u]);
  236. }
  237. TEST(BasicSnapshotLoader, GetEmptyType) {
  238. using namespace entt::literals;
  239. using traits_type = entt::entt_traits<entt::entity>;
  240. entt::registry registry;
  241. entt::basic_snapshot_loader loader{registry};
  242. const auto &storage = registry.storage<test::empty>();
  243. std::vector<entt::any> data{};
  244. auto archive = [&data, pos = 0u](auto &elem) mutable { elem = entt::any_cast<std::remove_reference_t<decltype(elem)>>(data[pos++]); };
  245. const entt::entity entity[2u]{traits_type::construct(0u, 0u), traits_type::construct(2u, 0u)}; // NOLINT
  246. ASSERT_FALSE(registry.valid(entity[0u]));
  247. ASSERT_FALSE(registry.valid(entity[1u]));
  248. data.emplace_back(static_cast<typename traits_type::entity_type>(1u));
  249. data.emplace_back(entity[0u]);
  250. loader.get<test::empty>(archive, "other"_hs);
  251. ASSERT_TRUE(registry.valid(entity[0u]));
  252. ASSERT_FALSE(registry.valid(entity[1u]));
  253. ASSERT_EQ(storage.size(), 0u);
  254. ASSERT_EQ(registry.storage<test::empty>("other"_hs).size(), 1u);
  255. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  256. data.emplace_back(entity[0u]);
  257. data.emplace_back(entity[1u]);
  258. loader.get<test::empty>(archive);
  259. ASSERT_TRUE(registry.valid(entity[0u]));
  260. ASSERT_TRUE(registry.valid(entity[1u]));
  261. ASSERT_EQ(storage.size(), 2u);
  262. ASSERT_TRUE(storage.contains(entity[0u]));
  263. ASSERT_TRUE(storage.contains(entity[1u]));
  264. }
  265. TEST(BasicSnapshotLoader, GetTypeSparse) {
  266. using namespace entt::literals;
  267. using traits_type = entt::entt_traits<entt::entity>;
  268. entt::registry registry;
  269. entt::basic_snapshot_loader loader{registry};
  270. const auto &storage = registry.storage<int>();
  271. std::vector<entt::any> data{};
  272. auto archive = [&data, pos = 0u](auto &elem) mutable { elem = entt::any_cast<std::remove_reference_t<decltype(elem)>>(data[pos++]); };
  273. const entt::entity entity[2u]{traits_type::construct(0u, 0u), traits_type::construct(2u, 0u)}; // NOLINT
  274. const int values[2u]{1, 3}; // NOLINT
  275. ASSERT_FALSE(registry.valid(entity[0u]));
  276. ASSERT_FALSE(registry.valid(entity[1u]));
  277. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  278. data.emplace_back(static_cast<entt::entity>(entt::null));
  279. data.emplace_back(entity[0u]);
  280. data.emplace_back(values[0u]);
  281. loader.get<int>(archive, "other"_hs);
  282. ASSERT_TRUE(registry.valid(entity[0u]));
  283. ASSERT_FALSE(registry.valid(entity[1u]));
  284. ASSERT_EQ(storage.size(), 0u);
  285. ASSERT_EQ(registry.storage<int>("other"_hs).size(), 1u);
  286. data.emplace_back(static_cast<typename traits_type::entity_type>(3u));
  287. data.emplace_back(entity[0u]);
  288. data.emplace_back(values[0u]);
  289. data.emplace_back(static_cast<entt::entity>(entt::null));
  290. data.emplace_back(entity[1u]);
  291. data.emplace_back(values[1u]);
  292. loader.get<int>(archive);
  293. ASSERT_TRUE(registry.valid(entity[0u]));
  294. ASSERT_TRUE(registry.valid(entity[1u]));
  295. ASSERT_EQ(storage.size(), 2u);
  296. ASSERT_TRUE(storage.contains(entity[0u]));
  297. ASSERT_TRUE(storage.contains(entity[1u]));
  298. ASSERT_EQ(storage.get(entity[0u]), values[0u]);
  299. ASSERT_EQ(storage.get(entity[1u]), values[1u]);
  300. }
  301. TEST(BasicSnapshotLoader, GetTypeWithListener) {
  302. using traits_type = entt::entt_traits<entt::entity>;
  303. entt::registry registry;
  304. entt::basic_snapshot_loader loader{registry};
  305. entt::entity check{entt::null};
  306. std::vector<entt::any> data{};
  307. auto archive = [&data, pos = 0u](auto &value) mutable { value = entt::any_cast<std::remove_reference_t<decltype(value)>>(data[pos++]); };
  308. const auto entity{traits_type::construct(1u, 1u)};
  309. const shadow value{entity};
  310. ASSERT_FALSE(registry.valid(entity));
  311. ASSERT_EQ(check, static_cast<entt::entity>(entt::null));
  312. registry.on_construct<shadow>().connect<&shadow::listener>(check);
  313. data.emplace_back(static_cast<typename traits_type::entity_type>(1u));
  314. data.emplace_back(entity);
  315. data.emplace_back(value);
  316. loader.get<shadow>(archive);
  317. ASSERT_TRUE(registry.valid(entity));
  318. ASSERT_EQ(check, entity);
  319. }
  320. TEST(BasicSnapshotLoader, Orphans) {
  321. using namespace entt::literals;
  322. using traits_type = entt::entt_traits<entt::entity>;
  323. entt::registry registry;
  324. entt::basic_snapshot_loader loader{registry};
  325. std::vector<entt::any> data{};
  326. auto archive = [&data, pos = 0u](auto &elem) mutable { elem = entt::any_cast<std::remove_reference_t<decltype(elem)>>(data[pos++]); };
  327. const entt::entity entity[2u]{traits_type::construct(0u, 0u), traits_type::construct(2u, 0u)}; // NOLINT
  328. const int value = 42;
  329. ASSERT_FALSE(registry.valid(entity[0u]));
  330. ASSERT_FALSE(registry.valid(entity[1u]));
  331. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  332. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  333. data.emplace_back(entity[0u]);
  334. data.emplace_back(entity[1u]);
  335. data.emplace_back(static_cast<typename traits_type::entity_type>(1u));
  336. data.emplace_back(entity[0u]);
  337. data.emplace_back(value);
  338. loader.get<entt::entity>(archive);
  339. loader.get<int>(archive);
  340. ASSERT_TRUE(registry.valid(entity[0u]));
  341. ASSERT_TRUE(registry.valid(entity[1u]));
  342. loader.orphans();
  343. ASSERT_TRUE(registry.valid(entity[0u]));
  344. ASSERT_FALSE(registry.valid(entity[1u]));
  345. }
  346. TEST(BasicContinuousLoader, Constructors) {
  347. static_assert(!std::is_default_constructible_v<entt::basic_continuous_loader<entt::registry>>, "Default constructible type not allowed");
  348. static_assert(!std::is_copy_constructible_v<entt::basic_continuous_loader<entt::registry>>, "Copy constructible type not allowed");
  349. static_assert(!std::is_copy_assignable_v<entt::basic_continuous_loader<entt::registry>>, "Copy assignable type not allowed");
  350. static_assert(std::is_move_constructible_v<entt::basic_continuous_loader<entt::registry>>, "Move constructible type required");
  351. static_assert(std::is_move_assignable_v<entt::basic_continuous_loader<entt::registry>>, "Move assignable type required");
  352. entt::registry registry;
  353. entt::basic_continuous_loader loader{registry};
  354. entt::basic_continuous_loader other{std::move(loader)};
  355. ASSERT_NO_THROW(loader = std::move(other));
  356. }
  357. TEST(BasicContinuousLoader, GetEntityType) {
  358. using namespace entt::literals;
  359. using traits_type = entt::entt_traits<entt::entity>;
  360. entt::registry registry;
  361. entt::basic_continuous_loader loader{registry};
  362. const auto &storage = registry.storage<entt::entity>();
  363. std::vector<entt::any> data{};
  364. auto archive = [&data, pos = 0u](auto &elem) mutable { elem = entt::any_cast<std::remove_reference_t<decltype(elem)>>(data[pos++]); };
  365. const entt::entity entity[3u]{traits_type::construct(1u, 0u), traits_type::construct(0u, 0u), traits_type::construct(2u, 0u)}; // NOLINT
  366. ASSERT_FALSE(registry.valid(entity[0u]));
  367. ASSERT_FALSE(registry.valid(entity[1u]));
  368. ASSERT_FALSE(registry.valid(entity[2u]));
  369. data.emplace_back(static_cast<typename traits_type::entity_type>(0u));
  370. data.emplace_back(static_cast<typename traits_type::entity_type>(0u));
  371. loader.get<entt::entity>(archive);
  372. ASSERT_FALSE(registry.valid(entity[0u]));
  373. ASSERT_FALSE(registry.valid(entity[1u]));
  374. ASSERT_FALSE(registry.valid(entity[2u]));
  375. ASSERT_FALSE(loader.contains(entity[0u]));
  376. ASSERT_FALSE(loader.contains(entity[1u]));
  377. ASSERT_FALSE(loader.contains(entity[2u]));
  378. ASSERT_EQ(loader.map(entity[0u]), static_cast<entt::entity>(entt::null));
  379. ASSERT_EQ(loader.map(entity[1u]), static_cast<entt::entity>(entt::null));
  380. ASSERT_EQ(loader.map(entity[2u]), static_cast<entt::entity>(entt::null));
  381. ASSERT_EQ(storage.size(), 0u);
  382. ASSERT_EQ(storage.free_list(), 0u);
  383. data.emplace_back(static_cast<typename traits_type::entity_type>(3u));
  384. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  385. data.emplace_back(entity[0u]);
  386. data.emplace_back(entity[1u]);
  387. data.emplace_back(entity[2u]);
  388. loader.get<entt::entity>(archive, "ignored"_hs);
  389. ASSERT_TRUE(loader.contains(entity[0u]));
  390. ASSERT_TRUE(loader.contains(entity[1u]));
  391. ASSERT_FALSE(loader.contains(entity[2u]));
  392. ASSERT_NE(loader.map(entity[0u]), static_cast<entt::entity>(entt::null));
  393. ASSERT_NE(loader.map(entity[1u]), static_cast<entt::entity>(entt::null));
  394. ASSERT_EQ(loader.map(entity[2u]), static_cast<entt::entity>(entt::null));
  395. ASSERT_TRUE(registry.valid(loader.map(entity[0u])));
  396. ASSERT_TRUE(registry.valid(loader.map(entity[1u])));
  397. ASSERT_EQ(storage.size(), 2u);
  398. ASSERT_EQ(storage.free_list(), 2u);
  399. ASSERT_EQ(storage[0u], loader.map(entity[0u]));
  400. ASSERT_EQ(storage[1u], loader.map(entity[1u]));
  401. ASSERT_EQ(registry.create(), entity[2u]);
  402. data.emplace_back(static_cast<typename traits_type::entity_type>(3u));
  403. data.emplace_back(static_cast<typename traits_type::entity_type>(3u));
  404. data.emplace_back(entity[0u]);
  405. data.emplace_back(entity[1u]);
  406. data.emplace_back(entity[2u]);
  407. loader.get<entt::entity>(archive);
  408. ASSERT_TRUE(loader.contains(entity[0u]));
  409. ASSERT_TRUE(loader.contains(entity[1u]));
  410. ASSERT_TRUE(loader.contains(entity[2u]));
  411. ASSERT_NE(loader.map(entity[0u]), static_cast<entt::entity>(entt::null));
  412. ASSERT_NE(loader.map(entity[1u]), static_cast<entt::entity>(entt::null));
  413. ASSERT_NE(loader.map(entity[2u]), static_cast<entt::entity>(entt::null));
  414. ASSERT_TRUE(registry.valid(loader.map(entity[0u])));
  415. ASSERT_TRUE(registry.valid(loader.map(entity[1u])));
  416. ASSERT_TRUE(registry.valid(loader.map(entity[2u])));
  417. ASSERT_EQ(storage.size(), 4u);
  418. ASSERT_EQ(storage.free_list(), 4u);
  419. ASSERT_EQ(storage[0u], loader.map(entity[0u]));
  420. ASSERT_EQ(storage[1u], loader.map(entity[1u]));
  421. ASSERT_EQ(storage[3u], loader.map(entity[2u]));
  422. registry.destroy(loader.map(entity[1u]));
  423. ASSERT_TRUE(loader.contains(entity[1u]));
  424. ASSERT_NE(loader.map(entity[1u]), static_cast<entt::entity>(entt::null));
  425. ASSERT_FALSE(registry.valid(loader.map(entity[1u])));
  426. data.emplace_back(static_cast<typename traits_type::entity_type>(1u));
  427. data.emplace_back(static_cast<typename traits_type::entity_type>(1u));
  428. data.emplace_back(entity[1u]);
  429. loader.get<entt::entity>(archive);
  430. ASSERT_TRUE(loader.contains(entity[1u]));
  431. ASSERT_NE(loader.map(entity[1u]), static_cast<entt::entity>(entt::null));
  432. ASSERT_TRUE(registry.valid(loader.map(entity[1u])));
  433. ASSERT_EQ(storage[3u], loader.map(entity[1u]));
  434. data.emplace_back(static_cast<typename traits_type::entity_type>(3u));
  435. data.emplace_back(static_cast<typename traits_type::entity_type>(1u));
  436. data.emplace_back(entity[1u]);
  437. data.emplace_back(entity[2u]);
  438. data.emplace_back(entity[0u]);
  439. loader.get<entt::entity>(archive, "ignored"_hs);
  440. ASSERT_FALSE(loader.contains(entity[0u]));
  441. ASSERT_TRUE(loader.contains(entity[1u]));
  442. ASSERT_FALSE(loader.contains(entity[2u]));
  443. ASSERT_EQ(loader.map(entity[0u]), static_cast<entt::entity>(entt::null));
  444. ASSERT_NE(loader.map(entity[1u]), static_cast<entt::entity>(entt::null));
  445. ASSERT_EQ(loader.map(entity[2u]), static_cast<entt::entity>(entt::null));
  446. ASSERT_TRUE(registry.valid(loader.map(entity[1u])));
  447. ASSERT_EQ(storage.size(), 4u);
  448. ASSERT_EQ(storage.free_list(), 2u);
  449. ASSERT_EQ(storage[1u], loader.map(entity[1u]));
  450. }
  451. TEST(BasicContinuousLoader, GetType) {
  452. using namespace entt::literals;
  453. using traits_type = entt::entt_traits<entt::entity>;
  454. entt::registry registry;
  455. entt::basic_continuous_loader loader{registry};
  456. const auto &storage = registry.storage<int>();
  457. std::vector<entt::any> data{};
  458. auto archive = [&data, pos = 0u](auto &elem) mutable { elem = entt::any_cast<std::remove_reference_t<decltype(elem)>>(data[pos++]); };
  459. const entt::entity entity[2u]{traits_type::construct(0u, 0u), traits_type::construct(2u, 0u)}; // NOLINT
  460. const int values[2u]{1, 3}; // NOLINT
  461. ASSERT_FALSE(loader.contains(entity[0u]));
  462. ASSERT_FALSE(loader.contains(entity[1u]));
  463. ASSERT_FALSE(registry.valid(loader.map(entity[0u])));
  464. ASSERT_FALSE(registry.valid(loader.map(entity[1u])));
  465. data.emplace_back(static_cast<typename traits_type::entity_type>(1u));
  466. data.emplace_back(entity[0u]);
  467. data.emplace_back(values[0u]);
  468. loader.get<int>(archive, "other"_hs);
  469. ASSERT_TRUE(loader.contains(entity[0u]));
  470. ASSERT_FALSE(loader.contains(entity[1u]));
  471. ASSERT_TRUE(registry.valid(loader.map(entity[0u])));
  472. ASSERT_FALSE(registry.valid(loader.map(entity[1u])));
  473. ASSERT_EQ(storage.size(), 0u);
  474. ASSERT_EQ(registry.storage<int>("other"_hs).size(), 1u);
  475. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  476. data.emplace_back(entity[0u]);
  477. data.emplace_back(values[0u]);
  478. data.emplace_back(entity[1u]);
  479. data.emplace_back(values[1u]);
  480. loader.get<int>(archive);
  481. ASSERT_TRUE(loader.contains(entity[0u]));
  482. ASSERT_TRUE(loader.contains(entity[1u]));
  483. ASSERT_TRUE(registry.valid(loader.map(entity[0u])));
  484. ASSERT_TRUE(registry.valid(loader.map(entity[1u])));
  485. ASSERT_EQ(storage.size(), 2u);
  486. ASSERT_TRUE(storage.contains(loader.map(entity[0u])));
  487. ASSERT_TRUE(storage.contains(loader.map(entity[1u])));
  488. ASSERT_EQ(storage.get(loader.map(entity[0u])), values[0u]);
  489. ASSERT_EQ(storage.get(loader.map(entity[1u])), values[1u]);
  490. }
  491. TEST(BasicContinuousLoader, GetTypeExtended) {
  492. using namespace entt::literals;
  493. using traits_type = entt::entt_traits<entt::entity>;
  494. entt::registry registry;
  495. entt::basic_continuous_loader loader{registry};
  496. const auto &storage = registry.storage<shadow>();
  497. std::vector<entt::any> data{};
  498. const entt::entity entity[2u]{traits_type::construct(0u, 1u), traits_type::construct(1u, 1u)}; // NOLINT
  499. const shadow value{entity[0u]};
  500. auto archive = [&loader, &data, pos = 0u](auto &elem) mutable {
  501. elem = entt::any_cast<std::remove_reference_t<decltype(elem)>>(data[pos++]);
  502. if constexpr(std::is_same_v<std::remove_reference_t<decltype(elem)>, shadow>) {
  503. elem.target = loader.map(elem.target);
  504. }
  505. };
  506. ASSERT_FALSE(loader.contains(entity[0u]));
  507. ASSERT_FALSE(loader.contains(entity[1u]));
  508. ASSERT_FALSE(registry.valid(loader.map(entity[0u])));
  509. ASSERT_FALSE(registry.valid(loader.map(entity[1u])));
  510. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  511. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  512. data.emplace_back(entity[0u]);
  513. data.emplace_back(entity[1u]);
  514. data.emplace_back(static_cast<typename traits_type::entity_type>(1u));
  515. data.emplace_back(entity[1u]);
  516. data.emplace_back(value);
  517. loader.get<entt::entity>(archive);
  518. loader.get<shadow>(archive);
  519. ASSERT_TRUE(loader.contains(entity[0u]));
  520. ASSERT_TRUE(loader.contains(entity[1u]));
  521. ASSERT_TRUE(registry.valid(loader.map(entity[0u])));
  522. ASSERT_TRUE(registry.valid(loader.map(entity[1u])));
  523. ASSERT_FALSE(registry.valid(entity[0u]));
  524. ASSERT_FALSE(registry.valid(entity[1u]));
  525. ASSERT_EQ(storage.size(), 1u);
  526. ASSERT_TRUE(storage.contains(loader.map(entity[1u])));
  527. ASSERT_EQ(storage.get(loader.map(entity[1u])).target, loader.map(entity[0u]));
  528. }
  529. TEST(BasicContinuousLoader, GetEmptyType) {
  530. using namespace entt::literals;
  531. using traits_type = entt::entt_traits<entt::entity>;
  532. entt::registry registry;
  533. entt::basic_continuous_loader loader{registry};
  534. const auto &storage = registry.storage<test::empty>();
  535. std::vector<entt::any> data{};
  536. auto archive = [&data, pos = 0u](auto &elem) mutable { elem = entt::any_cast<std::remove_reference_t<decltype(elem)>>(data[pos++]); };
  537. const entt::entity entity[2u]{traits_type::construct(0u, 0u), traits_type::construct(2u, 0u)}; // NOLINT
  538. ASSERT_FALSE(loader.contains(entity[0u]));
  539. ASSERT_FALSE(loader.contains(entity[1u]));
  540. ASSERT_FALSE(registry.valid(loader.map(entity[0u])));
  541. ASSERT_FALSE(registry.valid(loader.map(entity[1u])));
  542. data.emplace_back(static_cast<typename traits_type::entity_type>(1u));
  543. data.emplace_back(entity[0u]);
  544. loader.get<test::empty>(archive, "other"_hs);
  545. ASSERT_TRUE(loader.contains(entity[0u]));
  546. ASSERT_FALSE(loader.contains(entity[1u]));
  547. ASSERT_TRUE(registry.valid(loader.map(entity[0u])));
  548. ASSERT_FALSE(registry.valid(loader.map(entity[1u])));
  549. ASSERT_EQ(storage.size(), 0u);
  550. ASSERT_EQ(registry.storage<test::empty>("other"_hs).size(), 1u);
  551. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  552. data.emplace_back(entity[0u]);
  553. data.emplace_back(entity[1u]);
  554. loader.get<test::empty>(archive);
  555. ASSERT_TRUE(loader.contains(entity[0u]));
  556. ASSERT_TRUE(loader.contains(entity[1u]));
  557. ASSERT_TRUE(registry.valid(loader.map(entity[0u])));
  558. ASSERT_TRUE(registry.valid(loader.map(entity[1u])));
  559. ASSERT_EQ(storage.size(), 2u);
  560. ASSERT_TRUE(storage.contains(loader.map(entity[0u])));
  561. ASSERT_TRUE(storage.contains(loader.map(entity[1u])));
  562. }
  563. TEST(BasicContinuousLoader, GetTypeSparse) {
  564. using namespace entt::literals;
  565. using traits_type = entt::entt_traits<entt::entity>;
  566. entt::registry registry;
  567. entt::basic_continuous_loader loader{registry};
  568. const auto &storage = registry.storage<int>();
  569. std::vector<entt::any> data{};
  570. auto archive = [&data, pos = 0u](auto &elem) mutable { elem = entt::any_cast<std::remove_reference_t<decltype(elem)>>(data[pos++]); };
  571. const entt::entity entity[2u]{traits_type::construct(0u, 0u), traits_type::construct(2u, 0u)}; // NOLINT
  572. const int values[2u]{1, 3}; // NOLINT
  573. ASSERT_FALSE(loader.contains(entity[0u]));
  574. ASSERT_FALSE(loader.contains(entity[1u]));
  575. ASSERT_FALSE(registry.valid(loader.map(entity[0u])));
  576. ASSERT_FALSE(registry.valid(loader.map(entity[1u])));
  577. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  578. data.emplace_back(static_cast<entt::entity>(entt::null));
  579. data.emplace_back(entity[0u]);
  580. data.emplace_back(values[0u]);
  581. loader.get<int>(archive, "other"_hs);
  582. ASSERT_TRUE(loader.contains(entity[0u]));
  583. ASSERT_FALSE(loader.contains(entity[1u]));
  584. ASSERT_TRUE(registry.valid(loader.map(entity[0u])));
  585. ASSERT_FALSE(registry.valid(loader.map(entity[1u])));
  586. ASSERT_EQ(storage.size(), 0u);
  587. ASSERT_EQ(registry.storage<int>("other"_hs).size(), 1u);
  588. data.emplace_back(static_cast<typename traits_type::entity_type>(3u));
  589. data.emplace_back(entity[0u]);
  590. data.emplace_back(values[0u]);
  591. data.emplace_back(static_cast<entt::entity>(entt::null));
  592. data.emplace_back(entity[1u]);
  593. data.emplace_back(values[1u]);
  594. loader.get<int>(archive);
  595. ASSERT_TRUE(loader.contains(entity[0u]));
  596. ASSERT_TRUE(loader.contains(entity[1u]));
  597. ASSERT_TRUE(registry.valid(loader.map(entity[0u])));
  598. ASSERT_TRUE(registry.valid(loader.map(entity[1u])));
  599. ASSERT_EQ(storage.size(), 2u);
  600. ASSERT_TRUE(storage.contains(loader.map(entity[0u])));
  601. ASSERT_TRUE(storage.contains(loader.map(entity[1u])));
  602. ASSERT_EQ(storage.get(loader.map(entity[0u])), values[0u]);
  603. ASSERT_EQ(storage.get(loader.map(entity[1u])), values[1u]);
  604. }
  605. TEST(BasicContinuousLoader, GetTypeWithListener) {
  606. using traits_type = entt::entt_traits<entt::entity>;
  607. entt::registry registry;
  608. entt::basic_continuous_loader loader{registry};
  609. entt::entity check{entt::null};
  610. std::vector<entt::any> data{};
  611. auto archive = [&data, pos = 0u](auto &value) mutable { value = entt::any_cast<std::remove_reference_t<decltype(value)>>(data[pos++]); };
  612. const auto entity{traits_type::construct(1u, 1u)};
  613. const shadow value{entity};
  614. ASSERT_FALSE(registry.valid(loader.map(entity)));
  615. ASSERT_EQ(check, static_cast<entt::entity>(entt::null));
  616. registry.on_construct<shadow>().connect<&shadow::listener>(check);
  617. data.emplace_back(static_cast<typename traits_type::entity_type>(1u));
  618. data.emplace_back(entity);
  619. data.emplace_back(value);
  620. loader.get<shadow>(archive);
  621. ASSERT_TRUE(registry.valid(loader.map(entity)));
  622. ASSERT_EQ(check, entity);
  623. }
  624. TEST(BasicContinuousLoader, Orphans) {
  625. using namespace entt::literals;
  626. using traits_type = entt::entt_traits<entt::entity>;
  627. entt::registry registry;
  628. entt::basic_continuous_loader loader{registry};
  629. std::vector<entt::any> data{};
  630. auto archive = [&data, pos = 0u](auto &elem) mutable { elem = entt::any_cast<std::remove_reference_t<decltype(elem)>>(data[pos++]); };
  631. const entt::entity entity[2u]{traits_type::construct(0u, 0u), traits_type::construct(2u, 0u)}; // NOLINT
  632. const int value = 42;
  633. ASSERT_FALSE(registry.valid(entity[0u]));
  634. ASSERT_FALSE(registry.valid(entity[1u]));
  635. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  636. data.emplace_back(static_cast<typename traits_type::entity_type>(2u));
  637. data.emplace_back(entity[0u]);
  638. data.emplace_back(entity[1u]);
  639. data.emplace_back(static_cast<typename traits_type::entity_type>(1u));
  640. data.emplace_back(entity[0u]);
  641. data.emplace_back(value);
  642. loader.get<entt::entity>(archive);
  643. loader.get<int>(archive);
  644. ASSERT_TRUE(loader.contains(entity[0u]));
  645. ASSERT_TRUE(loader.contains(entity[1u]));
  646. ASSERT_TRUE(registry.valid(loader.map(entity[0u])));
  647. ASSERT_TRUE(registry.valid(loader.map(entity[1u])));
  648. loader.orphans();
  649. ASSERT_TRUE(loader.contains(entity[0u]));
  650. ASSERT_TRUE(loader.contains(entity[1u]));
  651. ASSERT_TRUE(registry.valid(loader.map(entity[0u])));
  652. ASSERT_FALSE(registry.valid(loader.map(entity[1u])));
  653. }