registry.cpp 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590
  1. #include <unordered_map>
  2. #include <unordered_set>
  3. #include <functional>
  4. #include <iterator>
  5. #include <memory>
  6. #include <cstdint>
  7. #include <type_traits>
  8. #include <gtest/gtest.h>
  9. #include <entt/core/type_traits.hpp>
  10. #include <entt/entity/registry.hpp>
  11. #include <entt/entity/entity.hpp>
  12. struct empty_type {};
  13. struct listener {
  14. template<typename Component>
  15. void incr(entt::entity entity, entt::registry &registry, const Component &) {
  16. ASSERT_TRUE(registry.valid(entity));
  17. ASSERT_TRUE(registry.has<Component>(entity));
  18. last = entity;
  19. ++counter;
  20. }
  21. template<typename Component>
  22. void decr(entt::entity entity, entt::registry &registry) {
  23. ASSERT_TRUE(registry.valid(entity));
  24. ASSERT_TRUE(registry.has<Component>(entity));
  25. last = entity;
  26. --counter;
  27. }
  28. entt::entity last;
  29. int counter{0};
  30. };
  31. TEST(Registry, Context) {
  32. entt::registry registry;
  33. ASSERT_EQ(registry.try_ctx<char>(), nullptr);
  34. ASSERT_EQ(registry.try_ctx<int>(), nullptr);
  35. ASSERT_EQ(registry.try_ctx<double>(), nullptr);
  36. registry.set<char>();
  37. registry.set<int>();
  38. registry.ctx_or_set<double>();
  39. ASSERT_NE(registry.try_ctx<char>(), nullptr);
  40. ASSERT_NE(registry.try_ctx<int>(), nullptr);
  41. ASSERT_NE(registry.try_ctx<double>(), nullptr);
  42. registry.unset<int>();
  43. registry.unset<double>();
  44. ASSERT_NE(registry.try_ctx<char>(), nullptr);
  45. ASSERT_EQ(registry.try_ctx<int>(), nullptr);
  46. ASSERT_EQ(registry.try_ctx<double>(), nullptr);
  47. registry.set<char>('c');
  48. registry.set<int>(0);
  49. registry.set<double>(1.);
  50. registry.set<int>(42);
  51. ASSERT_EQ(registry.ctx_or_set<char>('a'), 'c');
  52. ASSERT_NE(registry.try_ctx<char>(), nullptr);
  53. ASSERT_EQ(registry.try_ctx<char>(), &registry.ctx<char>());
  54. ASSERT_EQ(registry.ctx<char>(), std::as_const(registry).ctx<char>());
  55. ASSERT_EQ(registry.ctx<int>(), 42);
  56. ASSERT_NE(registry.try_ctx<int>(), nullptr);
  57. ASSERT_EQ(registry.try_ctx<int>(), &registry.ctx<int>());
  58. ASSERT_EQ(registry.ctx<int>(), std::as_const(registry).ctx<int>());
  59. ASSERT_EQ(registry.ctx<double>(), 1.);
  60. ASSERT_NE(registry.try_ctx<double>(), nullptr);
  61. ASSERT_EQ(registry.try_ctx<double>(), &registry.ctx<double>());
  62. ASSERT_EQ(registry.ctx<double>(), std::as_const(registry).ctx<double>());
  63. ASSERT_EQ(registry.try_ctx<float>(), nullptr);
  64. }
  65. TEST(Registry, Functionalities) {
  66. entt::registry registry;
  67. ASSERT_EQ(registry.size(), entt::registry::size_type{0});
  68. ASSERT_EQ(registry.alive(), entt::registry::size_type{0});
  69. ASSERT_NO_THROW((registry.reserve<int, char>(8)));
  70. ASSERT_NO_THROW(registry.reserve(42));
  71. ASSERT_TRUE(registry.empty());
  72. ASSERT_EQ(registry.capacity(), entt::registry::size_type{42});
  73. ASSERT_EQ(registry.capacity<int>(), entt::registry::size_type{8});
  74. ASSERT_EQ(registry.capacity<char>(), entt::registry::size_type{8});
  75. ASSERT_EQ(registry.size<int>(), entt::registry::size_type{0});
  76. ASSERT_EQ(registry.size<char>(), entt::registry::size_type{0});
  77. ASSERT_TRUE((registry.empty<int, char>()));
  78. registry.prepare<double>();
  79. const auto e0 = registry.create();
  80. const auto e1 = registry.create();
  81. registry.assign<int>(e1);
  82. registry.assign<char>(e1);
  83. ASSERT_TRUE(registry.has<>(e0));
  84. ASSERT_TRUE(registry.has<>(e1));
  85. ASSERT_EQ(registry.size<int>(), entt::registry::size_type{1});
  86. ASSERT_EQ(registry.size<char>(), entt::registry::size_type{1});
  87. ASSERT_FALSE(registry.empty<int>());
  88. ASSERT_FALSE(registry.empty<char>());
  89. ASSERT_NE(e0, e1);
  90. ASSERT_FALSE(registry.has<int>(e0));
  91. ASSERT_TRUE(registry.has<int>(e1));
  92. ASSERT_FALSE(registry.has<char>(e0));
  93. ASSERT_TRUE(registry.has<char>(e1));
  94. ASSERT_FALSE((registry.has<int, char>(e0)));
  95. ASSERT_TRUE((registry.has<int, char>(e1)));
  96. ASSERT_EQ(registry.try_get<int>(e0), nullptr);
  97. ASSERT_NE(registry.try_get<int>(e1), nullptr);
  98. ASSERT_EQ(registry.try_get<char>(e0), nullptr);
  99. ASSERT_NE(registry.try_get<char>(e1), nullptr);
  100. ASSERT_EQ(registry.try_get<double>(e0), nullptr);
  101. ASSERT_EQ(registry.try_get<double>(e1), nullptr);
  102. ASSERT_EQ(registry.assign<int>(e0, 42), 42);
  103. ASSERT_EQ(registry.assign<char>(e0, 'c'), 'c');
  104. ASSERT_NO_THROW(registry.remove<int>(e1));
  105. ASSERT_NO_THROW(registry.remove<char>(e1));
  106. ASSERT_TRUE(registry.has<int>(e0));
  107. ASSERT_FALSE(registry.has<int>(e1));
  108. ASSERT_TRUE(registry.has<char>(e0));
  109. ASSERT_FALSE(registry.has<char>(e1));
  110. ASSERT_TRUE((registry.has<int, char>(e0)));
  111. ASSERT_FALSE((registry.has<int, char>(e1)));
  112. const auto e2 = registry.create();
  113. registry.assign_or_replace<int>(e2, registry.get<int>(e0));
  114. registry.assign_or_replace<char>(e2, registry.get<char>(e0));
  115. ASSERT_TRUE(registry.has<int>(e2));
  116. ASSERT_TRUE(registry.has<char>(e2));
  117. ASSERT_EQ(registry.get<int>(e0), 42);
  118. ASSERT_EQ(registry.get<char>(e0), 'c');
  119. ASSERT_NE(registry.try_get<int>(e0), nullptr);
  120. ASSERT_NE(registry.try_get<char>(e0), nullptr);
  121. ASSERT_EQ(registry.try_get<double>(e0), nullptr);
  122. ASSERT_EQ(*registry.try_get<int>(e0), 42);
  123. ASSERT_EQ(*registry.try_get<char>(e0), 'c');
  124. ASSERT_EQ(std::get<0>(registry.get<int, char>(e0)), 42);
  125. ASSERT_EQ(*std::get<0>(registry.try_get<int, char, double>(e0)), 42);
  126. ASSERT_EQ(std::get<1>(static_cast<const entt::registry &>(registry).get<int, char>(e0)), 'c');
  127. ASSERT_EQ(*std::get<1>(static_cast<const entt::registry &>(registry).try_get<int, char, double>(e0)), 'c');
  128. ASSERT_EQ(registry.get<int>(e0), registry.get<int>(e2));
  129. ASSERT_EQ(registry.get<char>(e0), registry.get<char>(e2));
  130. ASSERT_NE(&registry.get<int>(e0), &registry.get<int>(e2));
  131. ASSERT_NE(&registry.get<char>(e0), &registry.get<char>(e2));
  132. ASSERT_NO_THROW(registry.replace<int>(e0, 0));
  133. ASSERT_EQ(registry.get<int>(e0), 0);
  134. ASSERT_NO_THROW(registry.assign_or_replace<int>(e0, 1));
  135. ASSERT_NO_THROW(registry.assign_or_replace<int>(e1, 1));
  136. ASSERT_EQ(static_cast<const entt::registry &>(registry).get<int>(e0), 1);
  137. ASSERT_EQ(static_cast<const entt::registry &>(registry).get<int>(e1), 1);
  138. ASSERT_EQ(registry.size(), entt::registry::size_type{3});
  139. ASSERT_EQ(registry.alive(), entt::registry::size_type{3});
  140. ASSERT_FALSE(registry.empty());
  141. ASSERT_EQ(registry.version(e2), entt::registry::version_type{0});
  142. ASSERT_EQ(registry.current(e2), entt::registry::version_type{0});
  143. ASSERT_NO_THROW(registry.destroy(e2));
  144. ASSERT_EQ(registry.version(e2), entt::registry::version_type{0});
  145. ASSERT_EQ(registry.current(e2), entt::registry::version_type{1});
  146. ASSERT_TRUE(registry.valid(e0));
  147. ASSERT_TRUE(registry.valid(e1));
  148. ASSERT_FALSE(registry.valid(e2));
  149. ASSERT_EQ(registry.size(), entt::registry::size_type{3});
  150. ASSERT_EQ(registry.alive(), entt::registry::size_type{2});
  151. ASSERT_FALSE(registry.empty());
  152. ASSERT_NO_THROW(registry.reset());
  153. ASSERT_EQ(registry.size(), entt::registry::size_type{3});
  154. ASSERT_EQ(registry.alive(), entt::registry::size_type{0});
  155. ASSERT_TRUE(registry.empty());
  156. const auto e3 = registry.create();
  157. ASSERT_EQ(registry.get_or_assign<int>(e3, 3), 3);
  158. ASSERT_EQ(registry.get_or_assign<char>(e3, 'c'), 'c');
  159. ASSERT_EQ(registry.size<int>(), entt::registry::size_type{1});
  160. ASSERT_EQ(registry.size<char>(), entt::registry::size_type{1});
  161. ASSERT_FALSE(registry.empty<int>());
  162. ASSERT_FALSE(registry.empty<char>());
  163. ASSERT_TRUE(registry.has<int>(e3));
  164. ASSERT_TRUE(registry.has<char>(e3));
  165. ASSERT_EQ(registry.get<int>(e3), 3);
  166. ASSERT_EQ(registry.get<char>(e3), 'c');
  167. ASSERT_NO_THROW(registry.reset<int>());
  168. ASSERT_EQ(registry.size<int>(), entt::registry::size_type{0});
  169. ASSERT_EQ(registry.size<char>(), entt::registry::size_type{1});
  170. ASSERT_TRUE(registry.empty<int>());
  171. ASSERT_FALSE(registry.empty<char>());
  172. ASSERT_NO_THROW(registry.reset());
  173. ASSERT_EQ(registry.size<int>(), entt::registry::size_type{0});
  174. ASSERT_EQ(registry.size<char>(), entt::registry::size_type{0});
  175. ASSERT_TRUE((registry.empty<int, char>()));
  176. const auto e4 = registry.create();
  177. const auto e5 = registry.create();
  178. registry.assign<int>(e4);
  179. ASSERT_NO_THROW(registry.reset<int>(e4));
  180. ASSERT_NO_THROW(registry.reset<int>(e5));
  181. ASSERT_EQ(registry.size<int>(), entt::registry::size_type{0});
  182. ASSERT_EQ(registry.size<char>(), entt::registry::size_type{0});
  183. ASSERT_TRUE(registry.empty<int>());
  184. ASSERT_EQ(registry.capacity<int>(), entt::registry::size_type{8});
  185. ASSERT_EQ(registry.capacity<char>(), entt::registry::size_type{8});
  186. registry.shrink_to_fit<int, char>();
  187. ASSERT_EQ(registry.capacity<int>(), entt::registry::size_type{});
  188. ASSERT_EQ(registry.capacity<char>(), entt::registry::size_type{});
  189. }
  190. TEST(Registry, Identifiers) {
  191. entt::registry registry;
  192. const auto pre = registry.create();
  193. ASSERT_EQ(pre, registry.entity(pre));
  194. registry.destroy(pre);
  195. const auto post = registry.create();
  196. ASSERT_NE(pre, post);
  197. ASSERT_EQ(entt::registry::entity(pre), entt::registry::entity(post));
  198. ASSERT_NE(entt::registry::version(pre), entt::registry::version(post));
  199. ASSERT_NE(registry.version(pre), registry.current(pre));
  200. ASSERT_EQ(registry.version(post), registry.current(post));
  201. }
  202. TEST(Registry, RawData) {
  203. entt::registry registry;
  204. const auto entity = registry.create();
  205. ASSERT_EQ(registry.raw<int>(), nullptr);
  206. ASSERT_EQ(std::as_const(registry).raw<int>(), nullptr);
  207. ASSERT_EQ(std::as_const(registry).data<int>(), nullptr);
  208. registry.assign<int>(entity, 42);
  209. ASSERT_NE(registry.raw<int>(), nullptr);
  210. ASSERT_NE(std::as_const(registry).raw<int>(), nullptr);
  211. ASSERT_NE(std::as_const(registry).data<int>(), nullptr);
  212. ASSERT_EQ(*registry.raw<int>(), 42);
  213. ASSERT_EQ(*std::as_const(registry).raw<int>(), 42);
  214. ASSERT_EQ(*std::as_const(registry).data<int>(), entity);
  215. }
  216. TEST(Registry, CreateManyEntitiesAtOnce) {
  217. entt::registry registry;
  218. entt::entity entities[3];
  219. const auto entity = registry.create();
  220. registry.destroy(registry.create());
  221. registry.destroy(entity);
  222. registry.destroy(registry.create());
  223. registry.create(std::begin(entities), std::end(entities));
  224. ASSERT_TRUE(registry.valid(entities[0]));
  225. ASSERT_TRUE(registry.valid(entities[1]));
  226. ASSERT_TRUE(registry.valid(entities[2]));
  227. ASSERT_EQ(registry.entity(entities[0]), entt::entity{0});
  228. ASSERT_EQ(registry.version(entities[0]), entt::registry::version_type{2});
  229. ASSERT_EQ(registry.entity(entities[1]), entt::entity{1});
  230. ASSERT_EQ(registry.version(entities[1]), entt::registry::version_type{1});
  231. ASSERT_EQ(registry.entity(entities[2]), entt::entity{2});
  232. ASSERT_EQ(registry.version(entities[2]), entt::registry::version_type{0});
  233. }
  234. TEST(Registry, CreateManyEntitiesAtOnceWithListener) {
  235. entt::registry registry;
  236. entt::entity entities[3];
  237. listener listener;
  238. registry.on_construct<int>().connect<&listener::incr<int>>(listener);
  239. registry.create(std::begin(entities), std::end(entities));
  240. registry.assign<int>(std::begin(entities), std::end(entities));
  241. registry.assign<char>(std::begin(entities), std::end(entities));
  242. ASSERT_EQ(listener.counter, 3);
  243. registry.on_construct<int>().disconnect<&listener::incr<int>>(listener);
  244. registry.on_construct<empty_type>().connect<&listener::incr<empty_type>>(listener);
  245. registry.create(std::begin(entities), std::end(entities));
  246. registry.assign<char>(std::begin(entities), std::end(entities));
  247. registry.assign<empty_type>(std::begin(entities), std::end(entities));
  248. ASSERT_EQ(listener.counter, 6);
  249. }
  250. TEST(Registry, CreateWithHint) {
  251. entt::registry registry;
  252. auto e3 = registry.create(entt::entity{3});
  253. auto e2 = registry.create(entt::entity{3});
  254. ASSERT_EQ(e2, entt::entity{2});
  255. ASSERT_FALSE(registry.valid(entt::entity{1}));
  256. ASSERT_EQ(e3, entt::entity{3});
  257. registry.destroy(e2);
  258. ASSERT_EQ(registry.version(e2), 0);
  259. ASSERT_EQ(registry.current(e2), 1);
  260. e2 = registry.create();
  261. auto e1 = registry.create(entt::entity{2});
  262. ASSERT_EQ(registry.entity(e2), entt::entity{2});
  263. ASSERT_EQ(registry.version(e2), 1);
  264. ASSERT_EQ(registry.entity(e1), entt::entity{1});
  265. ASSERT_EQ(registry.version(e1), 0);
  266. registry.destroy(e1);
  267. registry.destroy(e2);
  268. auto e0 = registry.create(entt::entity{0});
  269. ASSERT_EQ(e0, entt::entity{0});
  270. ASSERT_EQ(registry.version(e0), 0);
  271. }
  272. TEST(Registry, CreateDestroyEntities) {
  273. entt::registry registry;
  274. entt::entity pre{}, post{};
  275. for(int i = 0; i < 10; ++i) {
  276. const auto entity = registry.create();
  277. registry.assign<double>(entity);
  278. }
  279. registry.reset();
  280. for(int i = 0; i < 7; ++i) {
  281. const auto entity = registry.create();
  282. registry.assign<int>(entity);
  283. if(i == 3) { pre = entity; }
  284. }
  285. registry.reset();
  286. for(int i = 0; i < 5; ++i) {
  287. const auto entity = registry.create();
  288. if(i == 3) { post = entity; }
  289. }
  290. ASSERT_FALSE(registry.valid(pre));
  291. ASSERT_TRUE(registry.valid(post));
  292. ASSERT_NE(registry.version(pre), registry.version(post));
  293. ASSERT_EQ(registry.version(pre) + 1, registry.version(post));
  294. ASSERT_EQ(registry.current(pre), registry.current(post));
  295. }
  296. TEST(Registry, CreateDestroyCornerCase) {
  297. entt::registry registry;
  298. const auto e0 = registry.create();
  299. const auto e1 = registry.create();
  300. registry.destroy(e0);
  301. registry.destroy(e1);
  302. registry.each([](auto) { FAIL(); });
  303. ASSERT_EQ(registry.current(e0), entt::registry::version_type{1});
  304. ASSERT_EQ(registry.current(e1), entt::registry::version_type{1});
  305. }
  306. TEST(Registry, VersionOverflow) {
  307. entt::registry registry;
  308. const auto entity = registry.create();
  309. registry.destroy(entity);
  310. ASSERT_EQ(registry.version(entity), entt::registry::version_type{});
  311. for(auto i = entt::entt_traits<std::underlying_type_t<entt::entity>>::version_mask; i; --i) {
  312. ASSERT_NE(registry.current(entity), registry.version(entity));
  313. registry.destroy(registry.create());
  314. }
  315. ASSERT_EQ(registry.current(entity), registry.version(entity));
  316. }
  317. TEST(Registry, Each) {
  318. entt::registry registry;
  319. entt::registry::size_type tot;
  320. entt::registry::size_type match;
  321. registry.create();
  322. registry.assign<int>(registry.create());
  323. registry.create();
  324. registry.assign<int>(registry.create());
  325. registry.create();
  326. tot = 0u;
  327. match = 0u;
  328. registry.each([&](auto entity) {
  329. if(registry.has<int>(entity)) { ++match; }
  330. registry.create();
  331. ++tot;
  332. });
  333. ASSERT_EQ(tot, 5u);
  334. ASSERT_EQ(match, 2u);
  335. tot = 0u;
  336. match = 0u;
  337. registry.each([&](auto entity) {
  338. if(registry.has<int>(entity)) {
  339. registry.destroy(entity);
  340. ++match;
  341. }
  342. ++tot;
  343. });
  344. ASSERT_EQ(tot, 10u);
  345. ASSERT_EQ(match, 2u);
  346. tot = 0u;
  347. match = 0u;
  348. registry.each([&](auto entity) {
  349. if(registry.has<int>(entity)) { ++match; }
  350. registry.destroy(entity);
  351. ++tot;
  352. });
  353. ASSERT_EQ(tot, 8u);
  354. ASSERT_EQ(match, 0u);
  355. registry.each([&](auto) { FAIL(); });
  356. }
  357. TEST(Registry, Orphans) {
  358. entt::registry registry;
  359. entt::registry::size_type tot{};
  360. registry.assign<int>(registry.create());
  361. registry.create();
  362. registry.assign<int>(registry.create());
  363. registry.orphans([&](auto) { ++tot; });
  364. ASSERT_EQ(tot, 1u);
  365. tot = {};
  366. registry.each([&](auto entity) { registry.reset<int>(entity); });
  367. registry.orphans([&](auto) { ++tot; });
  368. ASSERT_EQ(tot, 3u);
  369. registry.reset();
  370. tot = {};
  371. registry.orphans([&](auto) { ++tot; });
  372. ASSERT_EQ(tot, 0u);
  373. }
  374. TEST(Registry, View) {
  375. entt::registry registry;
  376. auto mview = registry.view<int, char>();
  377. auto iview = registry.view<int>();
  378. auto cview = registry.view<char>();
  379. const auto e0 = registry.create();
  380. registry.assign<int>(e0, 0);
  381. registry.assign<char>(e0, 'c');
  382. const auto e1 = registry.create();
  383. registry.assign<int>(e1, 0);
  384. const auto e2 = registry.create();
  385. registry.assign<int>(e2, 0);
  386. registry.assign<char>(e2, 'c');
  387. ASSERT_EQ(iview.size(), 3u);
  388. ASSERT_EQ(cview.size(), 2u);
  389. std::size_t cnt{};
  390. mview.each([&cnt](auto...) { ++cnt; });
  391. ASSERT_EQ(cnt, 2u);
  392. }
  393. TEST(Registry, NonOwningGroupInitOnFirstUse) {
  394. entt::registry registry;
  395. auto create = [&](auto... component) {
  396. const auto entity = registry.create();
  397. (registry.assign<decltype(component)>(entity, component), ...);
  398. };
  399. create(0, 'c');
  400. create(0);
  401. create(0, 'c');
  402. std::size_t cnt{};
  403. auto group = registry.group<>(entt::get<int, char>);
  404. group.each([&cnt](auto...) { ++cnt; });
  405. ASSERT_TRUE((registry.sortable<int, char>()));
  406. ASSERT_EQ(cnt, 2u);
  407. }
  408. TEST(Registry, NonOwningGroupInitOnAssign) {
  409. entt::registry registry;
  410. auto group = registry.group<>(entt::get<int, char>);
  411. auto create = [&](auto... component) {
  412. const auto entity = registry.create();
  413. (registry.assign<decltype(component)>(entity, component), ...);
  414. };
  415. create(0, 'c');
  416. create(0);
  417. create(0, 'c');
  418. std::size_t cnt{};
  419. group.each([&cnt](auto...) { ++cnt; });
  420. ASSERT_TRUE((registry.sortable<int, char>()));
  421. ASSERT_EQ(cnt, 2u);
  422. }
  423. TEST(Registry, FullOwningGroupInitOnFirstUse) {
  424. entt::registry registry;
  425. auto create = [&](auto... component) {
  426. const auto entity = registry.create();
  427. (registry.assign<decltype(component)>(entity, component), ...);
  428. };
  429. create(0, 'c');
  430. create(0);
  431. create(0, 'c');
  432. std::size_t cnt{};
  433. auto group = registry.group<int, char>();
  434. group.each([&cnt](auto...) { ++cnt; });
  435. ASSERT_FALSE(registry.sortable<int>());
  436. ASSERT_FALSE(registry.sortable<char>());
  437. ASSERT_TRUE(registry.sortable<double>());
  438. ASSERT_EQ(cnt, 2u);
  439. }
  440. TEST(Registry, FullOwningGroupInitOnAssign) {
  441. entt::registry registry;
  442. auto group = registry.group<int, char>();
  443. auto create = [&](auto... component) {
  444. const auto entity = registry.create();
  445. (registry.assign<decltype(component)>(entity, component), ...);
  446. };
  447. create(0, 'c');
  448. create(0);
  449. create(0, 'c');
  450. std::size_t cnt{};
  451. group.each([&cnt](auto...) { ++cnt; });
  452. ASSERT_FALSE(registry.sortable<int>());
  453. ASSERT_FALSE(registry.sortable<char>());
  454. ASSERT_TRUE(registry.sortable<double>());
  455. ASSERT_EQ(cnt, 2u);
  456. }
  457. TEST(Registry, PartialOwningGroupInitOnFirstUse) {
  458. entt::registry registry;
  459. auto create = [&](auto... component) {
  460. const auto entity = registry.create();
  461. (registry.assign<decltype(component)>(entity, component), ...);
  462. };
  463. create(0, 'c');
  464. create(0);
  465. create(0, 'c');
  466. std::size_t cnt{};
  467. auto group = registry.group<int>(entt::get<char>);
  468. group.each([&cnt](auto...) { ++cnt; });
  469. ASSERT_FALSE((registry.sortable<int, char>()));
  470. ASSERT_FALSE(registry.sortable<int>());
  471. ASSERT_TRUE(registry.sortable<char>());
  472. ASSERT_EQ(cnt, 2u);
  473. }
  474. TEST(Registry, PartialOwningGroupInitOnAssign) {
  475. entt::registry registry;
  476. auto group = registry.group<int>(entt::get<char>);
  477. auto create = [&](auto... component) {
  478. const auto entity = registry.create();
  479. (registry.assign<decltype(component)>(entity, component), ...);
  480. };
  481. create(0, 'c');
  482. create(0);
  483. create(0, 'c');
  484. std::size_t cnt{};
  485. group.each([&cnt](auto...) { ++cnt; });
  486. ASSERT_FALSE((registry.sortable<int, char>()));
  487. ASSERT_FALSE(registry.sortable<int>());
  488. ASSERT_TRUE(registry.sortable<char>());
  489. ASSERT_EQ(cnt, 2u);
  490. }
  491. TEST(Registry, CleanViewAfterReset) {
  492. entt::registry registry;
  493. auto view = registry.view<int, char>();
  494. const auto entity = registry.create();
  495. registry.assign<int>(entity, 0);
  496. registry.assign<char>(entity, 'c');
  497. ASSERT_EQ(view.size(), entt::registry::size_type{1});
  498. registry.reset<char>(entity);
  499. ASSERT_EQ(view.size(), entt::registry::size_type{0});
  500. registry.assign<char>(entity, 'c');
  501. ASSERT_EQ(view.size(), entt::registry::size_type{1});
  502. registry.reset<int>();
  503. ASSERT_EQ(view.size(), entt::registry::size_type{0});
  504. registry.assign<int>(entity, 0);
  505. ASSERT_EQ(view.size(), entt::registry::size_type{1});
  506. registry.reset();
  507. ASSERT_EQ(view.size(), entt::registry::size_type{0});
  508. }
  509. TEST(Registry, CleanNonOwningGroupViewAfterReset) {
  510. entt::registry registry;
  511. auto group = registry.group<>(entt::get<int, char>);
  512. const auto entity = registry.create();
  513. registry.assign<int>(entity, 0);
  514. registry.assign<char>(entity, 'c');
  515. ASSERT_EQ(group.size(), entt::registry::size_type{1});
  516. registry.reset<char>(entity);
  517. ASSERT_EQ(group.size(), entt::registry::size_type{0});
  518. registry.assign<char>(entity, 'c');
  519. ASSERT_EQ(group.size(), entt::registry::size_type{1});
  520. registry.reset<int>();
  521. ASSERT_EQ(group.size(), entt::registry::size_type{0});
  522. registry.assign<int>(entity, 0);
  523. ASSERT_EQ(group.size(), entt::registry::size_type{1});
  524. registry.reset();
  525. ASSERT_EQ(group.size(), entt::registry::size_type{0});
  526. }
  527. TEST(Registry, CleanFullOwningGroupViewAfterReset) {
  528. entt::registry registry;
  529. auto group = registry.group<int, char>();
  530. const auto entity = registry.create();
  531. registry.assign<int>(entity, 0);
  532. registry.assign<char>(entity, 'c');
  533. ASSERT_EQ(group.size(), entt::registry::size_type{1});
  534. registry.reset<char>(entity);
  535. ASSERT_EQ(group.size(), entt::registry::size_type{0});
  536. registry.assign<char>(entity, 'c');
  537. ASSERT_EQ(group.size(), entt::registry::size_type{1});
  538. registry.reset<int>();
  539. ASSERT_EQ(group.size(), entt::registry::size_type{0});
  540. registry.assign<int>(entity, 0);
  541. ASSERT_EQ(group.size(), entt::registry::size_type{1});
  542. registry.reset();
  543. ASSERT_EQ(group.size(), entt::registry::size_type{0});
  544. }
  545. TEST(Registry, CleanPartialOwningGroupViewAfterReset) {
  546. entt::registry registry;
  547. auto group = registry.group<int>(entt::get<char>);
  548. const auto entity = registry.create();
  549. registry.assign<int>(entity, 0);
  550. registry.assign<char>(entity, 'c');
  551. ASSERT_EQ(group.size(), entt::registry::size_type{1});
  552. registry.reset<char>(entity);
  553. ASSERT_EQ(group.size(), entt::registry::size_type{0});
  554. registry.assign<char>(entity, 'c');
  555. ASSERT_EQ(group.size(), entt::registry::size_type{1});
  556. registry.reset<int>();
  557. ASSERT_EQ(group.size(), entt::registry::size_type{0});
  558. registry.assign<int>(entity, 0);
  559. ASSERT_EQ(group.size(), entt::registry::size_type{1});
  560. registry.reset();
  561. ASSERT_EQ(group.size(), entt::registry::size_type{0});
  562. }
  563. TEST(Registry, NestedGroups) {
  564. entt::registry registry;
  565. entt::entity entities[10];
  566. registry.create(std::begin(entities), std::end(entities));
  567. registry.assign<int>(std::begin(entities), std::end(entities));
  568. registry.assign<char>(std::begin(entities), std::end(entities));
  569. const auto g1 = registry.group<int>(entt::get<char>, entt::exclude<double>);
  570. ASSERT_TRUE(g1.sortable());
  571. ASSERT_EQ(g1.size(), 10u);
  572. const auto g2 = registry.group<int>(entt::get<char>);
  573. ASSERT_TRUE(g1.sortable());
  574. ASSERT_FALSE(g2.sortable());
  575. ASSERT_EQ(g1.size(), 10u);
  576. ASSERT_EQ(g2.size(), 10u);
  577. for(auto i = 0u; i < 5u; ++i) {
  578. ASSERT_TRUE(g1.contains(entities[i*2+1]));
  579. ASSERT_TRUE(g1.contains(entities[i*2]));
  580. ASSERT_TRUE(g2.contains(entities[i*2+1]));
  581. ASSERT_TRUE(g2.contains(entities[i*2]));
  582. registry.assign<double>(entities[i*2]);
  583. }
  584. ASSERT_EQ(g1.size(), 5u);
  585. ASSERT_EQ(g2.size(), 10u);
  586. for(auto i = 0u; i < 5u; ++i) {
  587. ASSERT_TRUE(g1.contains(entities[i*2+1]));
  588. ASSERT_FALSE(g1.contains(entities[i*2]));
  589. ASSERT_TRUE(g2.contains(entities[i*2+1]));
  590. ASSERT_TRUE(g2.contains(entities[i*2]));
  591. registry.remove<int>(entities[i*2+1]);
  592. }
  593. ASSERT_EQ(g1.size(), 0u);
  594. ASSERT_EQ(g2.size(), 5u);
  595. const auto g3= registry.group<int, float>(entt::get<char>, entt::exclude<double>);
  596. ASSERT_FALSE(g1.sortable());
  597. ASSERT_FALSE(g2.sortable());
  598. ASSERT_TRUE(g3.sortable());
  599. ASSERT_EQ(g1.size(), 0u);
  600. ASSERT_EQ(g2.size(), 5u);
  601. ASSERT_EQ(g3.size(), 0u);
  602. for(auto i = 0u; i < 5u; ++i) {
  603. ASSERT_FALSE(g1.contains(entities[i*2+1]));
  604. ASSERT_FALSE(g1.contains(entities[i*2]));
  605. ASSERT_FALSE(g2.contains(entities[i*2+1]));
  606. ASSERT_TRUE(g2.contains(entities[i*2]));
  607. ASSERT_FALSE(g3.contains(entities[i*2+1]));
  608. ASSERT_FALSE(g3.contains(entities[i*2]));
  609. registry.assign<int>(entities[i*2+1]);
  610. }
  611. ASSERT_EQ(g1.size(), 5u);
  612. ASSERT_EQ(g2.size(), 10u);
  613. ASSERT_EQ(g3.size(), 0u);
  614. for(auto i = 0u; i < 5u; ++i) {
  615. ASSERT_TRUE(g1.contains(entities[i*2+1]));
  616. ASSERT_FALSE(g1.contains(entities[i*2]));
  617. ASSERT_TRUE(g2.contains(entities[i*2+1]));
  618. ASSERT_TRUE(g2.contains(entities[i*2]));
  619. ASSERT_FALSE(g3.contains(entities[i*2+1]));
  620. ASSERT_FALSE(g3.contains(entities[i*2]));
  621. registry.assign<float>(entities[i*2]);
  622. }
  623. ASSERT_EQ(g1.size(), 5u);
  624. ASSERT_EQ(g2.size(), 10u);
  625. ASSERT_EQ(g3.size(), 0u);
  626. for(auto i = 0u; i < 5u; ++i) {
  627. registry.remove<double>(entities[i*2]);
  628. }
  629. ASSERT_EQ(g1.size(), 10u);
  630. ASSERT_EQ(g2.size(), 10u);
  631. ASSERT_EQ(g3.size(), 5u);
  632. for(auto i = 0u; i < 5u; ++i) {
  633. ASSERT_TRUE(g1.contains(entities[i*2+1]));
  634. ASSERT_TRUE(g1.contains(entities[i*2]));
  635. ASSERT_TRUE(g2.contains(entities[i*2+1]));
  636. ASSERT_TRUE(g2.contains(entities[i*2]));
  637. ASSERT_FALSE(g3.contains(entities[i*2+1]));
  638. ASSERT_TRUE(g3.contains(entities[i*2]));
  639. registry.remove<int>(entities[i*2+1]);
  640. registry.remove<int>(entities[i*2]);
  641. }
  642. ASSERT_EQ(g1.size(), 0u);
  643. ASSERT_EQ(g2.size(), 0u);
  644. ASSERT_EQ(g3.size(), 0u);
  645. }
  646. TEST(Registry, SortSingle) {
  647. entt::registry registry;
  648. int val = 0;
  649. registry.assign<int>(registry.create(), val++);
  650. registry.assign<int>(registry.create(), val++);
  651. registry.assign<int>(registry.create(), val++);
  652. for(auto entity: registry.view<int>()) {
  653. ASSERT_EQ(registry.get<int>(entity), --val);
  654. }
  655. registry.sort<int>(std::less<int>{});
  656. for(auto entity: registry.view<int>()) {
  657. ASSERT_EQ(registry.get<int>(entity), val++);
  658. }
  659. }
  660. TEST(Registry, SortMulti) {
  661. entt::registry registry;
  662. unsigned int uval = 0u;
  663. int ival = 0;
  664. for(auto i = 0; i < 3; ++i) {
  665. const auto entity = registry.create();
  666. registry.assign<unsigned int>(entity, uval++);
  667. registry.assign<int>(entity, ival++);
  668. }
  669. for(auto entity: registry.view<unsigned int>()) {
  670. ASSERT_EQ(registry.get<unsigned int>(entity), --uval);
  671. }
  672. for(auto entity: registry.view<int>()) {
  673. ASSERT_EQ(registry.get<int>(entity), --ival);
  674. }
  675. registry.sort<unsigned int>(std::less<unsigned int>{});
  676. registry.sort<int, unsigned int>();
  677. for(auto entity: registry.view<unsigned int>()) {
  678. ASSERT_EQ(registry.get<unsigned int>(entity), uval++);
  679. }
  680. for(auto entity: registry.view<int>()) {
  681. ASSERT_EQ(registry.get<int>(entity), ival++);
  682. }
  683. }
  684. TEST(Registry, SortEmpty) {
  685. entt::registry registry;
  686. registry.assign<empty_type>(registry.create());
  687. registry.assign<empty_type>(registry.create());
  688. registry.assign<empty_type>(registry.create());
  689. ASSERT_LT(registry.data<empty_type>()[0], registry.data<empty_type>()[1]);
  690. ASSERT_LT(registry.data<empty_type>()[1], registry.data<empty_type>()[2]);
  691. registry.sort<empty_type>(std::less<entt::entity>{});
  692. ASSERT_GT(registry.data<empty_type>()[0], registry.data<empty_type>()[1]);
  693. ASSERT_GT(registry.data<empty_type>()[1], registry.data<empty_type>()[2]);
  694. }
  695. TEST(Registry, ComponentsWithTypesFromStandardTemplateLibrary) {
  696. // see #37 - the test shouldn't crash, that's all
  697. entt::registry registry;
  698. const auto entity = registry.create();
  699. registry.assign<std::unordered_set<int>>(entity).insert(42);
  700. registry.destroy(entity);
  701. }
  702. TEST(Registry, ConstructWithComponents) {
  703. // it should compile, that's all
  704. entt::registry registry;
  705. const auto value = 0;
  706. registry.assign<int>(registry.create(), value);
  707. }
  708. TEST(Registry, MergeTwoRegistries) {
  709. entt::registry src;
  710. entt::registry dst;
  711. std::unordered_map<entt::entity, entt::entity> ref;
  712. auto merge = [&ref, &dst](const auto &view) {
  713. view.each([&](auto entity, const auto &component) {
  714. if(ref.find(entity) == ref.cend()) {
  715. const auto other = dst.create();
  716. dst.template assign<std::decay_t<decltype(component)>>(other, component);
  717. ref.emplace(entity, other);
  718. } else {
  719. using component_type = std::decay_t<decltype(component)>;
  720. dst.template assign<component_type>(ref[entity], component);
  721. }
  722. });
  723. };
  724. auto e0 = src.create();
  725. src.assign<int>(e0);
  726. src.assign<float>(e0);
  727. src.assign<double>(e0);
  728. auto e1 = src.create();
  729. src.assign<char>(e1);
  730. src.assign<float>(e1);
  731. src.assign<int>(e1);
  732. auto e2 = dst.create();
  733. dst.assign<int>(e2);
  734. dst.assign<char>(e2);
  735. dst.assign<double>(e2);
  736. auto e3 = dst.create();
  737. dst.assign<float>(e3);
  738. dst.assign<int>(e3);
  739. auto eq = [](auto begin, auto end) { ASSERT_EQ(begin, end); };
  740. auto ne = [](auto begin, auto end) { ASSERT_NE(begin, end); };
  741. eq(dst.view<int, float, double>().begin(), dst.view<int, float, double>().end());
  742. eq(dst.view<char, float, int>().begin(), dst.view<char, float, int>().end());
  743. merge(src.view<int>());
  744. merge(src.view<char>());
  745. merge(src.view<double>());
  746. merge(src.view<float>());
  747. ne(dst.view<int, float, double>().begin(), dst.view<int, float, double>().end());
  748. ne(dst.view<char, float, int>().begin(), dst.view<char, float, int>().end());
  749. }
  750. TEST(Registry, Signals) {
  751. entt::registry registry;
  752. listener listener;
  753. registry.on_construct<empty_type>().connect<&listener::incr<empty_type>>(listener);
  754. registry.on_destroy<empty_type>().connect<&listener::decr<empty_type>>(listener);
  755. registry.on_construct<int>().connect<&listener::incr<int>>(listener);
  756. registry.on_destroy<int>().connect<&listener::decr<int>>(listener);
  757. auto e0 = registry.create();
  758. auto e1 = registry.create();
  759. registry.assign<empty_type>(e0);
  760. registry.assign<empty_type>(e1);
  761. ASSERT_EQ(listener.counter, 2);
  762. ASSERT_EQ(listener.last, e1);
  763. registry.assign<int>(e1);
  764. registry.assign<int>(e0);
  765. ASSERT_EQ(listener.counter, 4);
  766. ASSERT_EQ(listener.last, e0);
  767. registry.remove<empty_type>(e0);
  768. registry.remove<int>(e0);
  769. ASSERT_EQ(listener.counter, 2);
  770. ASSERT_EQ(listener.last, e0);
  771. registry.on_destroy<empty_type>().disconnect<&listener::decr<empty_type>>(listener);
  772. registry.on_destroy<int>().disconnect<&listener::decr<int>>(listener);
  773. registry.remove<empty_type>(e1);
  774. registry.remove<int>(e1);
  775. ASSERT_EQ(listener.counter, 2);
  776. ASSERT_EQ(listener.last, e0);
  777. registry.on_construct<empty_type>().disconnect<&listener::incr<empty_type>>(listener);
  778. registry.on_construct<int>().disconnect<&listener::incr<int>>(listener);
  779. registry.assign<empty_type>(e1);
  780. registry.assign<int>(e1);
  781. ASSERT_EQ(listener.counter, 2);
  782. ASSERT_EQ(listener.last, e0);
  783. registry.on_construct<int>().connect<&listener::incr<int>>(listener);
  784. registry.on_destroy<int>().connect<&listener::decr<int>>(listener);
  785. registry.assign<int>(e0);
  786. registry.reset<int>(e1);
  787. ASSERT_EQ(listener.counter, 2);
  788. ASSERT_EQ(listener.last, e1);
  789. registry.on_construct<empty_type>().connect<&listener::incr<empty_type>>(listener);
  790. registry.on_destroy<empty_type>().connect<&listener::decr<empty_type>>(listener);
  791. registry.reset<empty_type>(e1);
  792. registry.assign<empty_type>(e0);
  793. ASSERT_EQ(listener.counter, 2);
  794. ASSERT_EQ(listener.last, e0);
  795. registry.reset<empty_type>();
  796. registry.reset<int>();
  797. ASSERT_EQ(listener.counter, 0);
  798. ASSERT_EQ(listener.last, e0);
  799. registry.assign<empty_type>(e0);
  800. registry.assign<empty_type>(e1);
  801. registry.assign<int>(e0);
  802. registry.assign<int>(e1);
  803. registry.destroy(e1);
  804. ASSERT_EQ(listener.counter, 2);
  805. ASSERT_EQ(listener.last, e1);
  806. registry.remove<int>(e0);
  807. registry.remove<empty_type>(e0);
  808. registry.assign_or_replace<int>(e0);
  809. registry.assign_or_replace<empty_type>(e0);
  810. ASSERT_EQ(listener.counter, 2);
  811. ASSERT_EQ(listener.last, e0);
  812. registry.on_destroy<empty_type>().disconnect<&listener::decr<empty_type>>(listener);
  813. registry.on_destroy<int>().disconnect<&listener::decr<int>>(listener);
  814. registry.assign_or_replace<empty_type>(e0);
  815. registry.assign_or_replace<int>(e0);
  816. ASSERT_EQ(listener.counter, 2);
  817. ASSERT_EQ(listener.last, e0);
  818. registry.on_replace<empty_type>().connect<&listener::incr<empty_type>>(listener);
  819. registry.on_replace<int>().connect<&listener::incr<int>>(listener);
  820. registry.assign_or_replace<empty_type>(e0);
  821. registry.assign_or_replace<int>(e0);
  822. ASSERT_EQ(listener.counter, 4);
  823. ASSERT_EQ(listener.last, e0);
  824. registry.replace<empty_type>(e0);
  825. registry.replace<int>(e0);
  826. ASSERT_EQ(listener.counter, 6);
  827. ASSERT_EQ(listener.last, e0);
  828. }
  829. TEST(Registry, RangeDestroy) {
  830. entt::registry registry;
  831. const auto e0 = registry.create();
  832. const auto e1 = registry.create();
  833. const auto e2 = registry.create();
  834. registry.assign<int>(e0);
  835. registry.assign<char>(e0);
  836. registry.assign<double>(e0);
  837. registry.assign<int>(e1);
  838. registry.assign<char>(e1);
  839. registry.assign<int>(e2);
  840. ASSERT_TRUE(registry.valid(e0));
  841. ASSERT_TRUE(registry.valid(e1));
  842. ASSERT_TRUE(registry.valid(e2));
  843. {
  844. const auto view = registry.view<int, char>();
  845. registry.destroy(view.begin(), view.end());
  846. }
  847. ASSERT_FALSE(registry.valid(e0));
  848. ASSERT_FALSE(registry.valid(e1));
  849. ASSERT_TRUE(registry.valid(e2));
  850. {
  851. const auto view = registry.view<int>();
  852. registry.destroy(view.begin(), view.end());
  853. }
  854. ASSERT_FALSE(registry.valid(e0));
  855. ASSERT_FALSE(registry.valid(e1));
  856. ASSERT_FALSE(registry.valid(e2));
  857. }
  858. TEST(Registry, RangeAssign) {
  859. entt::registry registry;
  860. const auto e0 = registry.create();
  861. const auto e1 = registry.create();
  862. const auto e2 = registry.create();
  863. registry.assign<int>(e0);
  864. registry.assign<char>(e0);
  865. registry.assign<double>(e0);
  866. registry.assign<int>(e1);
  867. registry.assign<char>(e1);
  868. registry.assign<int>(e2);
  869. ASSERT_FALSE(registry.has<float>(e0));
  870. ASSERT_FALSE(registry.has<float>(e1));
  871. ASSERT_FALSE(registry.has<float>(e2));
  872. const auto view = registry.view<int, char>();
  873. auto it = registry.assign<float>(view.begin(), view.end());
  874. ASSERT_TRUE(registry.has<float>(e0));
  875. ASSERT_TRUE(registry.has<float>(e1));
  876. ASSERT_FALSE(registry.has<float>(e2));
  877. *it = 0.f;
  878. *(it+1) = 1.f;
  879. ASSERT_EQ(registry.get<float>(*view.begin()), 0.f);
  880. ASSERT_EQ(registry.get<float>(*(++view.begin())), 1.f);
  881. }
  882. TEST(Registry, RangeRemove) {
  883. entt::registry registry;
  884. const auto e0 = registry.create();
  885. const auto e1 = registry.create();
  886. const auto e2 = registry.create();
  887. registry.assign<int>(e0);
  888. registry.assign<char>(e0);
  889. registry.assign<double>(e0);
  890. registry.assign<int>(e1);
  891. registry.assign<char>(e1);
  892. registry.assign<int>(e2);
  893. ASSERT_TRUE(registry.has<int>(e0));
  894. ASSERT_TRUE(registry.has<int>(e1));
  895. ASSERT_TRUE(registry.has<int>(e2));
  896. const auto view = registry.view<int, char>();
  897. registry.remove<int>(view.begin(), view.end());
  898. ASSERT_FALSE(registry.has<int>(e0));
  899. ASSERT_FALSE(registry.has<int>(e1));
  900. ASSERT_TRUE(registry.has<int>(e2));
  901. }
  902. TEST(Registry, NonOwningGroupInterleaved) {
  903. entt::registry registry;
  904. typename entt::entity entity = entt::null;
  905. entity = registry.create();
  906. registry.assign<int>(entity);
  907. registry.assign<char>(entity);
  908. const auto group = registry.group<>(entt::get<int, char>);
  909. entity = registry.create();
  910. registry.assign<int>(entity);
  911. registry.assign<char>(entity);
  912. std::size_t cnt{};
  913. group.each([&cnt](auto...) { ++cnt; });
  914. ASSERT_EQ(cnt, 2u);
  915. }
  916. TEST(Registry, FullOwningGroupInterleaved) {
  917. entt::registry registry;
  918. typename entt::entity entity = entt::null;
  919. entity = registry.create();
  920. registry.assign<int>(entity);
  921. registry.assign<char>(entity);
  922. const auto group = registry.group<int, char>();
  923. entity = registry.create();
  924. registry.assign<int>(entity);
  925. registry.assign<char>(entity);
  926. std::size_t cnt{};
  927. group.each([&cnt](auto...) { ++cnt; });
  928. ASSERT_EQ(cnt, 2u);
  929. }
  930. TEST(Registry, PartialOwningGroupInterleaved) {
  931. entt::registry registry;
  932. typename entt::entity entity = entt::null;
  933. entity = registry.create();
  934. registry.assign<int>(entity);
  935. registry.assign<char>(entity);
  936. const auto group = registry.group<int>(entt::get<char>);
  937. entity = registry.create();
  938. registry.assign<int>(entity);
  939. registry.assign<char>(entity);
  940. std::size_t cnt{};
  941. group.each([&cnt](auto...) { ++cnt; });
  942. ASSERT_EQ(cnt, 2u);
  943. }
  944. TEST(Registry, NonOwningGroupSortInterleaved) {
  945. entt::registry registry;
  946. const auto group = registry.group<>(entt::get<int, char>);
  947. const auto e0 = registry.create();
  948. registry.assign<int>(e0, 0);
  949. registry.assign<char>(e0, '0');
  950. const auto e1 = registry.create();
  951. registry.assign<int>(e1, 1);
  952. registry.assign<char>(e1, '1');
  953. registry.sort<int>(std::greater{});
  954. registry.sort<char>(std::less{});
  955. const auto e2 = registry.create();
  956. registry.assign<int>(e2, 2);
  957. registry.assign<char>(e2, '2');
  958. group.each([e0, e1, e2](const auto entity, const auto &i, const auto &c) {
  959. if(entity == e0) {
  960. ASSERT_EQ(i, 0);
  961. ASSERT_EQ(c, '0');
  962. } else if(entity == e1) {
  963. ASSERT_EQ(i, 1);
  964. ASSERT_EQ(c, '1');
  965. } else if(entity == e2) {
  966. ASSERT_EQ(i, 2);
  967. ASSERT_EQ(c, '2');
  968. }
  969. });
  970. }
  971. TEST(Registry, Clone) {
  972. entt::registry registry;
  973. entt::registry other;
  974. registry.destroy(registry.create());
  975. const auto e0 = registry.create();
  976. registry.assign<int>(e0, 0);
  977. registry.assign<double>(e0, 0.0);
  978. const auto e1 = registry.create();
  979. registry.assign<int>(e1, 1);
  980. registry.assign<char>(e1, '1');
  981. registry.assign<double>(e1, 1.1);
  982. const auto e2 = registry.create();
  983. registry.assign<int>(e2, 2);
  984. registry.assign<char>(e2, '2');
  985. registry.destroy(e1);
  986. ASSERT_EQ((other.group<int, char>().size()), entt::registry::size_type{0});
  987. other = registry.clone<int, char, float>();
  988. ASSERT_EQ((other.group<int, char>().size()), entt::registry::size_type{1});
  989. ASSERT_EQ(other.size(), registry.size());
  990. ASSERT_EQ(other.alive(), registry.alive());
  991. ASSERT_TRUE(other.valid(e0));
  992. ASSERT_FALSE(other.valid(e1));
  993. ASSERT_TRUE(other.valid(e2));
  994. ASSERT_TRUE((other.has<int>(e0)));
  995. ASSERT_FALSE((other.has<double>(e0)));
  996. ASSERT_TRUE((other.has<int, char>(e2)));
  997. ASSERT_EQ(other.get<int>(e0), 0);
  998. ASSERT_EQ(other.get<int>(e2), 2);
  999. ASSERT_EQ(other.get<char>(e2), '2');
  1000. const auto e3 = other.create();
  1001. ASSERT_NE(e1, e3);
  1002. ASSERT_EQ(registry.entity(e1), registry.entity(e3));
  1003. ASSERT_EQ(other.entity(e1), other.entity(e3));
  1004. other.assign<int>(e3, 3);
  1005. other.assign<char>(e3, '3');
  1006. ASSERT_EQ((registry.group<int, char>().size()), entt::registry::size_type{1});
  1007. ASSERT_EQ((other.group<int, char>().size()), entt::registry::size_type{2});
  1008. other = registry.clone();
  1009. ASSERT_EQ(other.size(), registry.size());
  1010. ASSERT_EQ(other.alive(), registry.alive());
  1011. ASSERT_TRUE(other.valid(e0));
  1012. ASSERT_FALSE(other.valid(e1));
  1013. ASSERT_TRUE(other.valid(e2));
  1014. ASSERT_FALSE(other.valid(e3));
  1015. ASSERT_TRUE((other.has<int, double>(e0)));
  1016. ASSERT_TRUE((other.has<int, char>(e2)));
  1017. ASSERT_EQ(other.get<int>(e0), 0);
  1018. ASSERT_EQ(other.get<double>(e0), 0.);
  1019. ASSERT_EQ(other.get<int>(e2), 2);
  1020. ASSERT_EQ(other.get<char>(e2), '2');
  1021. other = other.clone<char>();
  1022. ASSERT_EQ(other.size(), registry.size());
  1023. ASSERT_EQ(other.alive(), registry.alive());
  1024. ASSERT_TRUE(other.valid(e0));
  1025. ASSERT_FALSE(other.valid(e1));
  1026. ASSERT_TRUE(other.valid(e2));
  1027. ASSERT_FALSE(other.valid(e3));
  1028. ASSERT_FALSE((other.has<int>(e0)));
  1029. ASSERT_FALSE((other.has<double>(e0)));
  1030. ASSERT_FALSE((other.has<int>(e2)));
  1031. ASSERT_TRUE((other.has<char>(e2)));
  1032. ASSERT_TRUE(other.orphan(e0));
  1033. ASSERT_EQ(other.get<char>(e2), '2');
  1034. // the remove erased function must be available after cloning
  1035. other.reset();
  1036. }
  1037. TEST(Registry, CloneExclude) {
  1038. entt::registry registry;
  1039. entt::registry other;
  1040. const auto entity = registry.create();
  1041. registry.assign<int>(entity);
  1042. registry.assign<char>(entity);
  1043. other = registry.clone<int>();
  1044. ASSERT_TRUE(other.has(entity));
  1045. ASSERT_TRUE(other.has<int>(entity));
  1046. ASSERT_FALSE(other.has<char>(entity));
  1047. other = registry.clone(entt::exclude<int>);
  1048. ASSERT_TRUE(other.has(entity));
  1049. ASSERT_FALSE(other.has<int>(entity));
  1050. ASSERT_TRUE(other.has<char>(entity));
  1051. other = registry.clone(entt::exclude<int, char>);
  1052. ASSERT_TRUE(other.has(entity));
  1053. ASSERT_TRUE(other.orphan(entity));
  1054. }
  1055. TEST(Registry, CloneMoveOnlyComponent) {
  1056. entt::registry registry;
  1057. const auto entity = registry.create();
  1058. registry.assign<std::unique_ptr<int>>(entity);
  1059. registry.assign<char>(entity);
  1060. auto other = registry.clone();
  1061. ASSERT_TRUE(other.valid(entity));
  1062. ASSERT_TRUE(other.has<char>(entity));
  1063. ASSERT_FALSE(other.has<std::unique_ptr<int>>(entity));
  1064. }
  1065. TEST(Registry, Stamp) {
  1066. entt::registry registry;
  1067. const auto prototype = registry.create();
  1068. registry.assign<int>(prototype, 3);
  1069. registry.assign<char>(prototype, 'c');
  1070. auto entity = registry.create();
  1071. registry.stamp<int, char>(entity, registry, prototype);
  1072. ASSERT_TRUE((registry.has<int, char>(entity)));
  1073. ASSERT_EQ(registry.get<int>(entity), 3);
  1074. ASSERT_EQ(registry.get<char>(entity), 'c');
  1075. registry.replace<int>(prototype, 42);
  1076. registry.replace<char>(prototype, 'a');
  1077. registry.stamp<int>(entity, registry, prototype);
  1078. ASSERT_EQ(registry.get<int>(entity), 42);
  1079. ASSERT_EQ(registry.get<char>(entity), 'c');
  1080. }
  1081. TEST(Registry, StampExclude) {
  1082. entt::registry registry;
  1083. const auto prototype = registry.create();
  1084. registry.assign<int>(prototype, 3);
  1085. registry.assign<char>(prototype, 'c');
  1086. registry.assign<empty_type>(prototype);
  1087. const auto entity = registry.create();
  1088. registry.stamp(entity, registry, prototype, entt::exclude<char>);
  1089. ASSERT_TRUE((registry.has<int, empty_type>(entity)));
  1090. ASSERT_FALSE(registry.has<char>(entity));
  1091. ASSERT_EQ(registry.get<int>(entity), 3);
  1092. registry.replace<int>(prototype, 42);
  1093. registry.stamp(entity, registry, prototype, entt::exclude<int>);
  1094. ASSERT_TRUE((registry.has<int, char, empty_type>(entity)));
  1095. ASSERT_EQ(registry.get<int>(entity), 3);
  1096. ASSERT_EQ(registry.get<char>(entity), 'c');
  1097. registry.remove<int, char, empty_type>(entity);
  1098. registry.stamp(entity, registry, prototype, entt::exclude<int, char, empty_type>);
  1099. ASSERT_TRUE(registry.orphan(entity));
  1100. }
  1101. TEST(Registry, StampMoveOnlyComponent) {
  1102. entt::registry registry;
  1103. const auto prototype = registry.create();
  1104. registry.assign<std::unique_ptr<int>>(prototype);
  1105. registry.assign<char>(prototype);
  1106. const auto entity = registry.create();
  1107. registry.stamp(entity, registry, prototype);
  1108. ASSERT_TRUE(registry.has<char>(entity));
  1109. ASSERT_FALSE(registry.has<std::unique_ptr<int>>(entity));
  1110. }
  1111. TEST(Registry, GetOrAssign) {
  1112. entt::registry registry;
  1113. const auto entity = registry.create();
  1114. const auto value = registry.get_or_assign<int>(entity, 3);
  1115. ASSERT_TRUE(registry.has<int>(entity));
  1116. ASSERT_EQ(registry.get<int>(entity), value);
  1117. ASSERT_EQ(registry.get<int>(entity), 3);
  1118. }
  1119. TEST(Registry, Constness) {
  1120. entt::registry registry;
  1121. ASSERT_TRUE((std::is_same_v<decltype(registry.assign<int>({})), int &>));
  1122. ASSERT_TRUE((std::is_same_v<decltype(registry.assign<empty_type>({})), empty_type>));
  1123. ASSERT_TRUE((std::is_same_v<decltype(registry.get<int>({})), int &>));
  1124. ASSERT_TRUE((std::is_same_v<decltype(registry.get<int, char>({})), std::tuple<int &, char &>>));
  1125. ASSERT_TRUE((std::is_same_v<decltype(registry.try_get<int>({})), int *>));
  1126. ASSERT_TRUE((std::is_same_v<decltype(registry.try_get<int, char>({})), std::tuple<int *, char *>>));
  1127. ASSERT_TRUE((std::is_same_v<decltype(std::as_const(registry).get<int>({})), const int &>));
  1128. ASSERT_TRUE((std::is_same_v<decltype(std::as_const(registry).get<int, char>({})), std::tuple<const int &, const char &>>));
  1129. ASSERT_TRUE((std::is_same_v<decltype(std::as_const(registry).try_get<int>({})), const int *>));
  1130. ASSERT_TRUE((std::is_same_v<decltype(std::as_const(registry).try_get<int, char>({})), std::tuple<const int *, const char *>>));
  1131. }
  1132. TEST(Registry, BatchCreateAmbiguousCall) {
  1133. struct ambiguous { std::uint32_t foo; std::uint64_t bar; };
  1134. entt::registry registry;
  1135. const auto entity = registry.create();
  1136. std::uint32_t foo = 32u;
  1137. std::uint64_t bar = 64u;
  1138. // this should work, no other tests required
  1139. registry.assign<ambiguous>(entity, foo, bar);
  1140. }
  1141. TEST(Registry, MoveOnlyComponent) {
  1142. // the purpose is to ensure that move only components are always accepted
  1143. entt::registry registry;
  1144. const auto entity = registry.create();
  1145. registry.assign<std::unique_ptr<int>>(entity);
  1146. }
  1147. TEST(Registry, Dependencies) {
  1148. entt::registry registry;
  1149. const auto entity = registry.create();
  1150. // required because of an issue of VS2019
  1151. constexpr auto assign_or_replace = &entt::registry::assign_or_replace<double>;
  1152. constexpr auto remove = &entt::registry::remove<double>;
  1153. registry.on_construct<int>().connect<assign_or_replace>(registry);
  1154. registry.on_destroy<int>().connect<remove>(registry);
  1155. registry.assign<double>(entity, .3);
  1156. ASSERT_FALSE(registry.has<int>(entity));
  1157. ASSERT_EQ(registry.get<double>(entity), .3);
  1158. registry.assign<int>(entity);
  1159. ASSERT_TRUE(registry.has<int>(entity));
  1160. ASSERT_EQ(registry.get<double>(entity), .0);
  1161. registry.remove<int>(entity);
  1162. ASSERT_FALSE(registry.has<int>(entity));
  1163. ASSERT_FALSE(registry.has<double>(entity));
  1164. registry.on_construct<int>().disconnect<assign_or_replace>(registry);
  1165. registry.on_destroy<int>().disconnect<remove>(registry);
  1166. registry.assign<int>(entity);
  1167. ASSERT_TRUE(registry.has<int>(entity));
  1168. ASSERT_FALSE(registry.has<double>(entity));
  1169. }