registry.cpp 66 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148
  1. #include <cstddef>
  2. #include <functional>
  3. #include <iterator>
  4. #include <memory>
  5. #include <tuple>
  6. #include <type_traits>
  7. #include <unordered_set>
  8. #include <utility>
  9. #include <gtest/gtest.h>
  10. #include <entt/core/hashed_string.hpp>
  11. #include <entt/core/type_info.hpp>
  12. #include <entt/entity/entity.hpp>
  13. #include <entt/entity/registry.hpp>
  14. #include "../common/config.h"
  15. struct empty_type {};
  16. struct no_eto_type {
  17. static constexpr std::size_t page_size = 1024u;
  18. };
  19. bool operator==(const no_eto_type &lhs, const no_eto_type &rhs) {
  20. return &lhs == &rhs;
  21. }
  22. struct stable_type {
  23. static constexpr auto in_place_delete = true;
  24. int value;
  25. };
  26. struct non_default_constructible {
  27. non_default_constructible(int v)
  28. : value{v} {}
  29. int value;
  30. };
  31. struct aggregate {
  32. int value{};
  33. };
  34. struct listener {
  35. template<typename Component>
  36. static void sort(entt::registry &registry) {
  37. registry.sort<Component>([](auto lhs, auto rhs) { return lhs < rhs; });
  38. }
  39. template<typename Component>
  40. void incr(const entt::registry &, entt::entity entity) {
  41. last = entity;
  42. ++counter;
  43. }
  44. template<typename Component>
  45. void decr(const entt::registry &, entt::entity entity) {
  46. last = entity;
  47. --counter;
  48. }
  49. entt::entity last{entt::null};
  50. int counter{0};
  51. };
  52. struct owner {
  53. void receive(const entt::registry &ref) {
  54. parent = &ref;
  55. }
  56. const entt::registry *parent{nullptr};
  57. };
  58. TEST(Registry, Context) {
  59. entt::registry registry;
  60. auto &ctx = registry.ctx();
  61. const auto &cctx = std::as_const(registry).ctx();
  62. ASSERT_FALSE(ctx.contains<char>());
  63. ASSERT_FALSE(cctx.contains<const int>());
  64. ASSERT_EQ(ctx.find<char>(), nullptr);
  65. ASSERT_EQ(cctx.find<const int>(), nullptr);
  66. ctx.emplace<char>();
  67. ctx.emplace<int>();
  68. ASSERT_TRUE(ctx.contains<char>());
  69. ASSERT_TRUE(cctx.contains<int>());
  70. ASSERT_NE(ctx.find<const char>(), nullptr);
  71. ASSERT_NE(cctx.find<const int>(), nullptr);
  72. ASSERT_FALSE(ctx.erase<double>());
  73. ASSERT_TRUE(ctx.erase<int>());
  74. ASSERT_TRUE(ctx.contains<const char>());
  75. ASSERT_FALSE(cctx.contains<const int>());
  76. ASSERT_NE(ctx.find<char>(), nullptr);
  77. ASSERT_EQ(cctx.find<int>(), nullptr);
  78. ASSERT_FALSE(ctx.erase<int>());
  79. ASSERT_TRUE(ctx.erase<char>());
  80. ctx.emplace<char>('c');
  81. ctx.emplace<int>(42);
  82. ASSERT_EQ(ctx.emplace<char>('a'), 'c');
  83. ASSERT_EQ(ctx.find<const char>(), cctx.find<char>());
  84. ASSERT_EQ(ctx.get<char>(), cctx.get<const char>());
  85. ASSERT_EQ(ctx.get<char>(), 'c');
  86. ASSERT_EQ(ctx.emplace<const int>(0), 42);
  87. ASSERT_EQ(ctx.find<const int>(), cctx.find<int>());
  88. ASSERT_EQ(ctx.at<int>(), cctx.at<const int>());
  89. ASSERT_EQ(ctx.at<int>(), 42);
  90. ASSERT_EQ(ctx.find<double>(), nullptr);
  91. ASSERT_EQ(cctx.find<double>(), nullptr);
  92. ASSERT_EQ(ctx.insert_or_assign<char>('a'), 'a');
  93. ASSERT_EQ(ctx.find<const char>(), cctx.find<char>());
  94. ASSERT_EQ(ctx.get<char>(), cctx.get<const char>());
  95. ASSERT_EQ(ctx.get<const char>(), 'a');
  96. ASSERT_EQ(ctx.insert_or_assign<const int>(0), 0);
  97. ASSERT_EQ(ctx.find<const int>(), cctx.find<int>());
  98. ASSERT_EQ(ctx.at<int>(), cctx.at<const int>());
  99. ASSERT_EQ(ctx.at<int>(), 0);
  100. }
  101. TEST(Registry, ContextHint) {
  102. using namespace entt::literals;
  103. entt::registry registry;
  104. auto &ctx = registry.ctx();
  105. const auto &cctx = std::as_const(registry).ctx();
  106. ctx.emplace<int>(42);
  107. ctx.emplace_as<int>("other"_hs, 3);
  108. ASSERT_TRUE(ctx.contains<int>());
  109. ASSERT_TRUE(cctx.contains<const int>("other"_hs));
  110. ASSERT_FALSE(ctx.contains<char>("other"_hs));
  111. ASSERT_NE(cctx.find<const int>(), nullptr);
  112. ASSERT_NE(ctx.find<int>("other"_hs), nullptr);
  113. ASSERT_EQ(cctx.find<const char>("other"_hs), nullptr);
  114. ASSERT_EQ(ctx.get<int>(), 42);
  115. ASSERT_EQ(cctx.get<const int>("other"_hs), 3);
  116. ctx.insert_or_assign(3);
  117. ctx.insert_or_assign("other"_hs, 42);
  118. ASSERT_EQ(ctx.get<const int>(), 3);
  119. ASSERT_EQ(cctx.get<int>("other"_hs), 42);
  120. ASSERT_FALSE(ctx.erase<char>("other"_hs));
  121. ASSERT_TRUE(ctx.erase<int>());
  122. ASSERT_TRUE(cctx.contains<int>("other"_hs));
  123. ASSERT_EQ(ctx.get<int>("other"_hs), 42);
  124. ASSERT_TRUE(ctx.erase<int>("other"_hs));
  125. ASSERT_FALSE(cctx.contains<int>("other"_hs));
  126. ASSERT_EQ(ctx.find<int>("other"_hs), nullptr);
  127. }
  128. TEST(Registry, ContextAsRef) {
  129. entt::registry registry;
  130. int value{3};
  131. registry.ctx().emplace<int &>(value);
  132. ASSERT_NE(registry.ctx().find<int>(), nullptr);
  133. ASSERT_NE(registry.ctx().find<const int>(), nullptr);
  134. ASSERT_NE(std::as_const(registry).ctx().find<const int>(), nullptr);
  135. ASSERT_EQ(registry.ctx().get<const int>(), 3);
  136. ASSERT_EQ(registry.ctx().get<int>(), 3);
  137. registry.ctx().get<int>() = 42;
  138. ASSERT_EQ(registry.ctx().get<int>(), 42);
  139. ASSERT_EQ(value, 42);
  140. value = 3;
  141. ASSERT_EQ(std::as_const(registry).ctx().get<const int>(), 3);
  142. }
  143. TEST(Registry, ContextAsConstRef) {
  144. entt::registry registry;
  145. int value{3};
  146. registry.ctx().emplace<const int &>(value);
  147. ASSERT_EQ(registry.ctx().find<int>(), nullptr);
  148. ASSERT_NE(registry.ctx().find<const int>(), nullptr);
  149. ASSERT_NE(std::as_const(registry).ctx().find<const int>(), nullptr);
  150. ASSERT_EQ(registry.ctx().get<const int>(), 3);
  151. value = 42;
  152. ASSERT_EQ(std::as_const(registry).ctx().get<const int>(), 42);
  153. }
  154. TEST(Registry, Functionalities) {
  155. using traits_type = entt::entt_traits<entt::entity>;
  156. entt::registry registry;
  157. ASSERT_NO_THROW([[maybe_unused]] auto alloc = registry.get_allocator());
  158. ASSERT_EQ(registry.size(), 0u);
  159. ASSERT_EQ(registry.alive(), 0u);
  160. ASSERT_NO_FATAL_FAILURE(registry.reserve(42));
  161. ASSERT_EQ(registry.capacity(), 42u);
  162. ASSERT_TRUE(registry.empty());
  163. ASSERT_EQ(registry.storage<int>().size(), 0u);
  164. ASSERT_EQ(registry.storage<char>().size(), 0u);
  165. ASSERT_TRUE(registry.storage<int>().empty());
  166. ASSERT_TRUE(registry.storage<char>().empty());
  167. const auto e0 = registry.create();
  168. const auto e1 = registry.create();
  169. registry.emplace<int>(e1);
  170. registry.emplace<char>(e1);
  171. ASSERT_TRUE(registry.all_of<>(e0));
  172. ASSERT_FALSE(registry.any_of<>(e1));
  173. ASSERT_EQ(registry.storage<int>().size(), 1u);
  174. ASSERT_EQ(registry.storage<char>().size(), 1u);
  175. ASSERT_FALSE(registry.storage<int>().empty());
  176. ASSERT_FALSE(registry.storage<char>().empty());
  177. ASSERT_NE(e0, e1);
  178. ASSERT_FALSE((registry.all_of<int, const char>(e0)));
  179. ASSERT_TRUE((registry.all_of<const int, char>(e1)));
  180. ASSERT_FALSE((registry.any_of<int, const double>(e0)));
  181. ASSERT_TRUE((registry.any_of<const int, double>(e1)));
  182. ASSERT_EQ(registry.try_get<int>(e0), nullptr);
  183. ASSERT_NE(registry.try_get<int>(e1), nullptr);
  184. ASSERT_EQ(registry.try_get<char>(e0), nullptr);
  185. ASSERT_NE(registry.try_get<char>(e1), nullptr);
  186. ASSERT_EQ(registry.try_get<double>(e0), nullptr);
  187. ASSERT_EQ(registry.try_get<double>(e1), nullptr);
  188. ASSERT_EQ(registry.emplace<int>(e0, 42), 42);
  189. ASSERT_EQ(registry.emplace<char>(e0, 'c'), 'c');
  190. ASSERT_NO_FATAL_FAILURE(registry.erase<int>(e1));
  191. ASSERT_NO_FATAL_FAILURE(registry.erase<char>(e1));
  192. ASSERT_TRUE((registry.all_of<const int, char>(e0)));
  193. ASSERT_FALSE((registry.all_of<int, const char>(e1)));
  194. ASSERT_TRUE((registry.any_of<const int, double>(e0)));
  195. ASSERT_FALSE((registry.any_of<int, const double>(e1)));
  196. const auto e2 = registry.create();
  197. registry.emplace_or_replace<int>(e2, registry.get<int>(e0));
  198. registry.emplace_or_replace<char>(e2, registry.get<char>(e0));
  199. ASSERT_TRUE((registry.all_of<int, char>(e2)));
  200. ASSERT_EQ(registry.get<int>(e0), 42);
  201. ASSERT_EQ(registry.get<char>(e0), 'c');
  202. ASSERT_NE(registry.try_get<int>(e0), nullptr);
  203. ASSERT_NE(registry.try_get<char>(e0), nullptr);
  204. ASSERT_EQ(registry.try_get<double>(e0), nullptr);
  205. ASSERT_EQ(*registry.try_get<int>(e0), 42);
  206. ASSERT_EQ(*registry.try_get<char>(e0), 'c');
  207. ASSERT_EQ(std::get<0>(registry.get<int, char>(e0)), 42);
  208. ASSERT_EQ(*std::get<0>(registry.try_get<int, char, double>(e0)), 42);
  209. ASSERT_EQ(std::get<1>(static_cast<const entt::registry &>(registry).get<int, char>(e0)), 'c');
  210. ASSERT_EQ(*std::get<1>(static_cast<const entt::registry &>(registry).try_get<int, char, double>(e0)), 'c');
  211. ASSERT_EQ(registry.get<int>(e0), registry.get<int>(e2));
  212. ASSERT_EQ(registry.get<char>(e0), registry.get<char>(e2));
  213. ASSERT_NE(&registry.get<int>(e0), &registry.get<int>(e2));
  214. ASSERT_NE(&registry.get<char>(e0), &registry.get<char>(e2));
  215. ASSERT_EQ(registry.patch<int>(e0, [](auto &instance) { instance = 2; }), 2);
  216. ASSERT_EQ(registry.replace<int>(e0, 3), 3);
  217. ASSERT_NO_FATAL_FAILURE(registry.emplace_or_replace<int>(e0, 1));
  218. ASSERT_NO_FATAL_FAILURE(registry.emplace_or_replace<int>(e1, 1));
  219. ASSERT_EQ(static_cast<const entt::registry &>(registry).get<int>(e0), 1);
  220. ASSERT_EQ(static_cast<const entt::registry &>(registry).get<int>(e1), 1);
  221. ASSERT_EQ(registry.size(), 3u);
  222. ASSERT_EQ(registry.alive(), 3u);
  223. ASSERT_FALSE(registry.empty());
  224. ASSERT_EQ(traits_type::to_version(e2), 0u);
  225. ASSERT_EQ(registry.current(e2), 0u);
  226. ASSERT_NO_FATAL_FAILURE(registry.destroy(e2));
  227. ASSERT_EQ(traits_type::to_version(e2), 0u);
  228. ASSERT_EQ(registry.current(e2), 1u);
  229. ASSERT_TRUE(registry.valid(e0));
  230. ASSERT_TRUE(registry.valid(e1));
  231. ASSERT_FALSE(registry.valid(e2));
  232. ASSERT_EQ(registry.size(), 3u);
  233. ASSERT_EQ(registry.alive(), 2u);
  234. ASSERT_FALSE(registry.empty());
  235. ASSERT_NO_FATAL_FAILURE(registry.clear());
  236. ASSERT_EQ(registry.size(), 3u);
  237. ASSERT_EQ(registry.alive(), 0u);
  238. ASSERT_TRUE(registry.empty());
  239. const auto e3 = registry.create();
  240. ASSERT_EQ(registry.get_or_emplace<int>(e3, 3), 3);
  241. ASSERT_EQ(registry.get_or_emplace<char>(e3, 'c'), 'c');
  242. ASSERT_EQ(registry.storage<int>().size(), 1u);
  243. ASSERT_EQ(registry.storage<char>().size(), 1u);
  244. ASSERT_FALSE(registry.storage<int>().empty());
  245. ASSERT_FALSE(registry.storage<char>().empty());
  246. ASSERT_TRUE((registry.all_of<int, char>(e3)));
  247. ASSERT_EQ(registry.get<int>(e3), 3);
  248. ASSERT_EQ(registry.get<char>(e3), 'c');
  249. ASSERT_NO_FATAL_FAILURE(registry.clear<int>());
  250. ASSERT_EQ(registry.storage<int>().size(), 0u);
  251. ASSERT_EQ(registry.storage<char>().size(), 1u);
  252. ASSERT_TRUE(registry.storage<int>().empty());
  253. ASSERT_FALSE(registry.storage<char>().empty());
  254. ASSERT_NO_FATAL_FAILURE(registry.clear());
  255. ASSERT_EQ(registry.storage<int>().size(), 0u);
  256. ASSERT_EQ(registry.storage<char>().size(), 0u);
  257. ASSERT_TRUE(registry.storage<int>().empty());
  258. ASSERT_TRUE(registry.storage<char>().empty());
  259. const auto e4 = registry.create();
  260. const auto e5 = registry.create();
  261. registry.emplace<int>(e4);
  262. ASSERT_EQ(registry.remove<int>(e4), 1u);
  263. ASSERT_EQ(registry.remove<int>(e5), 0u);
  264. ASSERT_EQ(registry.storage<int>().size(), 0u);
  265. ASSERT_EQ(registry.storage<char>().size(), 0u);
  266. ASSERT_TRUE(registry.storage<int>().empty());
  267. }
  268. TEST(Registry, Constructors) {
  269. entt::registry registry;
  270. entt::registry other{42};
  271. const entt::entity entity = entt::tombstone;
  272. ASSERT_TRUE(registry.empty());
  273. ASSERT_TRUE(other.empty());
  274. ASSERT_EQ(registry.released(), entity);
  275. ASSERT_EQ(other.released(), entity);
  276. }
  277. TEST(Registry, Move) {
  278. entt::registry registry;
  279. const auto entity = registry.create();
  280. owner test{};
  281. registry.on_construct<int>().connect<&owner::receive>(test);
  282. registry.on_destroy<int>().connect<&owner::receive>(test);
  283. ASSERT_EQ(test.parent, nullptr);
  284. registry.emplace<int>(entity);
  285. ASSERT_EQ(test.parent, &registry);
  286. entt::registry other{std::move(registry)};
  287. other.erase<int>(entity);
  288. registry = {};
  289. registry.emplace<int>(registry.create(entity));
  290. ASSERT_EQ(test.parent, &other);
  291. registry = std::move(other);
  292. registry.emplace<int>(entity);
  293. registry.emplace<int>(registry.create(entity));
  294. ASSERT_EQ(test.parent, &registry);
  295. }
  296. TEST(Registry, ReplaceAggregate) {
  297. entt::registry registry;
  298. const auto entity = registry.create();
  299. registry.emplace<aggregate>(entity, 0);
  300. auto &instance = registry.replace<aggregate>(entity, 42);
  301. ASSERT_EQ(instance.value, 42);
  302. }
  303. TEST(Registry, EmplaceOrReplaceAggregate) {
  304. entt::registry registry;
  305. const auto entity = registry.create();
  306. auto &instance = registry.emplace_or_replace<aggregate>(entity, 42);
  307. ASSERT_EQ(instance.value, 42);
  308. }
  309. TEST(Registry, Identifiers) {
  310. using traits_type = entt::entt_traits<entt::entity>;
  311. entt::registry registry;
  312. const auto pre = registry.create();
  313. ASSERT_EQ(traits_type::to_integral(pre), traits_type::to_entity(pre));
  314. registry.release(pre);
  315. const auto post = registry.create();
  316. ASSERT_NE(pre, post);
  317. ASSERT_EQ(traits_type::to_entity(pre), traits_type::to_entity(post));
  318. ASSERT_NE(traits_type::to_version(pre), traits_type::to_version(post));
  319. ASSERT_NE(traits_type::to_version(pre), registry.current(pre));
  320. ASSERT_EQ(traits_type::to_version(post), registry.current(post));
  321. const auto invalid = traits_type::combine(traits_type::to_entity(post) + 1u, {});
  322. ASSERT_EQ(traits_type::to_version(invalid), typename traits_type::version_type{});
  323. ASSERT_EQ(registry.current(invalid), traits_type::to_version(entt::tombstone));
  324. }
  325. TEST(Registry, Data) {
  326. entt::registry registry;
  327. ASSERT_EQ(std::as_const(registry).data(), nullptr);
  328. const auto entity = registry.create();
  329. ASSERT_EQ(*std::as_const(registry).data(), entity);
  330. const auto other = registry.create();
  331. registry.release(entity);
  332. ASSERT_NE(*std::as_const(registry).data(), entity);
  333. ASSERT_EQ(*(std::as_const(registry).data() + 1u), other);
  334. }
  335. TEST(Registry, CreateManyEntitiesAtOnce) {
  336. using traits_type = entt::entt_traits<entt::entity>;
  337. entt::registry registry;
  338. entt::entity entities[3];
  339. const auto entity = registry.create();
  340. registry.release(registry.create());
  341. registry.release(entity);
  342. registry.release(registry.create());
  343. registry.create(std::begin(entities), std::end(entities));
  344. ASSERT_TRUE(registry.valid(entities[0]));
  345. ASSERT_TRUE(registry.valid(entities[1]));
  346. ASSERT_TRUE(registry.valid(entities[2]));
  347. ASSERT_EQ(traits_type::to_entity(entities[0]), 0u);
  348. ASSERT_EQ(traits_type::to_version(entities[0]), 2u);
  349. ASSERT_EQ(traits_type::to_entity(entities[1]), 1u);
  350. ASSERT_EQ(traits_type::to_version(entities[1]), 1u);
  351. ASSERT_EQ(traits_type::to_entity(entities[2]), 2u);
  352. ASSERT_EQ(traits_type::to_version(entities[2]), 0u);
  353. }
  354. TEST(Registry, CreateManyEntitiesAtOnceWithListener) {
  355. entt::registry registry;
  356. entt::entity entities[3];
  357. listener listener;
  358. registry.on_construct<int>().connect<&listener::incr<int>>(listener);
  359. registry.create(std::begin(entities), std::end(entities));
  360. registry.insert(std::begin(entities), std::end(entities), 42);
  361. registry.insert(std::begin(entities), std::end(entities), 'c');
  362. ASSERT_EQ(registry.get<int>(entities[0]), 42);
  363. ASSERT_EQ(registry.get<char>(entities[1]), 'c');
  364. ASSERT_EQ(listener.counter, 3);
  365. registry.on_construct<int>().disconnect<&listener::incr<int>>(listener);
  366. registry.on_construct<empty_type>().connect<&listener::incr<empty_type>>(listener);
  367. registry.create(std::begin(entities), std::end(entities));
  368. registry.insert(std::begin(entities), std::end(entities), 'a');
  369. registry.insert<empty_type>(std::begin(entities), std::end(entities));
  370. ASSERT_TRUE(registry.all_of<empty_type>(entities[0]));
  371. ASSERT_EQ(registry.get<char>(entities[2]), 'a');
  372. ASSERT_EQ(listener.counter, 6);
  373. }
  374. TEST(Registry, CreateWithHint) {
  375. using traits_type = entt::entt_traits<entt::entity>;
  376. entt::registry registry;
  377. auto e3 = registry.create(entt::entity{3});
  378. auto e2 = registry.create(entt::entity{3});
  379. ASSERT_EQ(e2, entt::entity{2});
  380. ASSERT_FALSE(registry.valid(entt::entity{1}));
  381. ASSERT_EQ(e3, entt::entity{3});
  382. registry.release(e2);
  383. ASSERT_EQ(traits_type::to_version(e2), 0u);
  384. ASSERT_EQ(registry.current(e2), 1u);
  385. e2 = registry.create();
  386. auto e1 = registry.create(entt::entity{2});
  387. ASSERT_EQ(traits_type::to_entity(e2), 2u);
  388. ASSERT_EQ(traits_type::to_version(e2), 1u);
  389. ASSERT_EQ(traits_type::to_entity(e1), 1u);
  390. ASSERT_EQ(traits_type::to_version(e1), 0u);
  391. registry.release(e1);
  392. registry.release(e2);
  393. auto e0 = registry.create(entt::entity{0});
  394. ASSERT_EQ(e0, entt::entity{0});
  395. ASSERT_EQ(traits_type::to_version(e0), 0u);
  396. }
  397. TEST(Registry, CreateClearCycle) {
  398. using traits_type = entt::entt_traits<entt::entity>;
  399. entt::registry registry;
  400. entt::entity pre{}, post{};
  401. for(int i = 0; i < 10; ++i) {
  402. const auto entity = registry.create();
  403. registry.emplace<double>(entity);
  404. }
  405. registry.clear();
  406. for(int i = 0; i < 7; ++i) {
  407. const auto entity = registry.create();
  408. registry.emplace<int>(entity);
  409. if(i == 3) {
  410. pre = entity;
  411. }
  412. }
  413. registry.clear();
  414. for(int i = 0; i < 5; ++i) {
  415. const auto entity = registry.create();
  416. if(i == 3) {
  417. post = entity;
  418. }
  419. }
  420. ASSERT_FALSE(registry.valid(pre));
  421. ASSERT_TRUE(registry.valid(post));
  422. ASSERT_NE(traits_type::to_version(pre), traits_type::to_version(post));
  423. ASSERT_EQ(traits_type::to_version(pre) + 1, traits_type::to_version(post));
  424. ASSERT_EQ(registry.current(pre), registry.current(post));
  425. }
  426. TEST(Registry, CreateDestroyReleaseCornerCase) {
  427. entt::registry registry;
  428. const auto e0 = registry.create();
  429. const auto e1 = registry.create();
  430. registry.destroy(e0);
  431. registry.release(e1);
  432. registry.each([](auto) { FAIL(); });
  433. ASSERT_EQ(registry.current(e0), 1u);
  434. ASSERT_EQ(registry.current(e1), 1u);
  435. }
  436. TEST(Registry, DestroyVersion) {
  437. entt::registry registry;
  438. const auto e0 = registry.create();
  439. const auto e1 = registry.create();
  440. ASSERT_EQ(registry.current(e0), 0u);
  441. ASSERT_EQ(registry.current(e1), 0u);
  442. registry.destroy(e0);
  443. registry.destroy(e1, 3);
  444. ASSERT_EQ(registry.current(e0), 1u);
  445. ASSERT_EQ(registry.current(e1), 3u);
  446. }
  447. ENTT_DEBUG_TEST(RegistryDeathTest, DestroyVersion) {
  448. entt::registry registry;
  449. const auto entity = registry.create();
  450. registry.destroy(entity);
  451. ASSERT_DEATH(registry.destroy(entity), "");
  452. ASSERT_DEATH(registry.destroy(entity, 3), "");
  453. }
  454. TEST(Registry, RangeDestroy) {
  455. entt::registry registry;
  456. const auto iview = registry.view<int>();
  457. const auto icview = registry.view<int, char>();
  458. entt::entity entities[3u];
  459. registry.create(std::begin(entities), std::end(entities));
  460. registry.emplace<int>(entities[0u]);
  461. registry.emplace<char>(entities[0u]);
  462. registry.emplace<double>(entities[0u]);
  463. registry.emplace<int>(entities[1u]);
  464. registry.emplace<char>(entities[1u]);
  465. registry.emplace<int>(entities[2u]);
  466. ASSERT_TRUE(registry.valid(entities[0u]));
  467. ASSERT_TRUE(registry.valid(entities[1u]));
  468. ASSERT_TRUE(registry.valid(entities[2u]));
  469. registry.destroy(icview.begin(), icview.end());
  470. ASSERT_FALSE(registry.valid(entities[0u]));
  471. ASSERT_FALSE(registry.valid(entities[1u]));
  472. ASSERT_TRUE(registry.valid(entities[2u]));
  473. ASSERT_EQ(registry.storage<int>().size(), 1u);
  474. ASSERT_EQ(registry.storage<char>().size(), 0u);
  475. ASSERT_EQ(registry.storage<double>().size(), 0u);
  476. registry.destroy(iview.begin(), iview.end());
  477. ASSERT_FALSE(registry.valid(entities[2u]));
  478. ASSERT_NO_FATAL_FAILURE(registry.destroy(iview.rbegin(), iview.rend()));
  479. ASSERT_EQ(iview.size(), 0u);
  480. ASSERT_EQ(icview.size_hint(), 0u);
  481. ASSERT_EQ(registry.storage<int>().size(), 0u);
  482. ASSERT_EQ(registry.storage<char>().size(), 0u);
  483. ASSERT_EQ(registry.storage<double>().size(), 0u);
  484. registry.create(std::begin(entities), std::end(entities));
  485. registry.insert<int>(std::begin(entities), std::end(entities));
  486. ASSERT_TRUE(registry.valid(entities[0u]));
  487. ASSERT_TRUE(registry.valid(entities[1u]));
  488. ASSERT_TRUE(registry.valid(entities[2u]));
  489. ASSERT_EQ(registry.storage<int>().size(), 3u);
  490. registry.destroy(std::begin(entities), std::end(entities));
  491. ASSERT_FALSE(registry.valid(entities[0u]));
  492. ASSERT_FALSE(registry.valid(entities[1u]));
  493. ASSERT_FALSE(registry.valid(entities[2u]));
  494. ASSERT_EQ(registry.storage<int>().size(), 0u);
  495. }
  496. TEST(Registry, StableDestroy) {
  497. entt::registry registry;
  498. const auto iview = registry.view<int>();
  499. const auto icview = registry.view<int, stable_type>();
  500. entt::entity entities[3u];
  501. registry.create(std::begin(entities), std::end(entities));
  502. registry.emplace<int>(entities[0u]);
  503. registry.emplace<stable_type>(entities[0u]);
  504. registry.emplace<double>(entities[0u]);
  505. registry.emplace<int>(entities[1u]);
  506. registry.emplace<stable_type>(entities[1u]);
  507. registry.emplace<int>(entities[2u]);
  508. ASSERT_TRUE(registry.valid(entities[0u]));
  509. ASSERT_TRUE(registry.valid(entities[1u]));
  510. ASSERT_TRUE(registry.valid(entities[2u]));
  511. registry.destroy(icview.begin(), icview.end());
  512. ASSERT_FALSE(registry.valid(entities[0u]));
  513. ASSERT_FALSE(registry.valid(entities[1u]));
  514. ASSERT_TRUE(registry.valid(entities[2u]));
  515. ASSERT_EQ(registry.storage<int>().size(), 1u);
  516. ASSERT_EQ(registry.storage<stable_type>().size(), 2u);
  517. ASSERT_EQ(registry.storage<double>().size(), 0u);
  518. registry.destroy(iview.begin(), iview.end());
  519. ASSERT_FALSE(registry.valid(entities[2u]));
  520. ASSERT_EQ(iview.size(), 0u);
  521. ASSERT_EQ(icview.size_hint(), 0u);
  522. ASSERT_EQ(registry.storage<int>().size(), 0u);
  523. ASSERT_EQ(registry.storage<stable_type>().size(), 2u);
  524. ASSERT_EQ(registry.storage<double>().size(), 0u);
  525. }
  526. TEST(Registry, ReleaseVersion) {
  527. entt::registry registry;
  528. entt::entity entities[2u];
  529. registry.create(std::begin(entities), std::end(entities));
  530. ASSERT_EQ(registry.current(entities[0u]), 0u);
  531. ASSERT_EQ(registry.current(entities[1u]), 0u);
  532. registry.release(entities[0u]);
  533. registry.release(entities[1u], 3);
  534. ASSERT_EQ(registry.current(entities[0u]), 1u);
  535. ASSERT_EQ(registry.current(entities[1u]), 3u);
  536. }
  537. ENTT_DEBUG_TEST(RegistryDeathTest, ReleaseVersion) {
  538. entt::registry registry;
  539. entt::entity entity = registry.create();
  540. registry.release(entity);
  541. ASSERT_DEATH(registry.release(entity), "");
  542. ASSERT_DEATH(registry.release(entity, 3), "");
  543. }
  544. TEST(Registry, RangeRelease) {
  545. entt::registry registry;
  546. entt::entity entities[3u];
  547. registry.create(std::begin(entities), std::end(entities));
  548. ASSERT_TRUE(registry.valid(entities[0u]));
  549. ASSERT_TRUE(registry.valid(entities[1u]));
  550. ASSERT_TRUE(registry.valid(entities[2u]));
  551. registry.release(std::begin(entities), std::end(entities) - 1u);
  552. ASSERT_FALSE(registry.valid(entities[0u]));
  553. ASSERT_FALSE(registry.valid(entities[1u]));
  554. ASSERT_TRUE(registry.valid(entities[2u]));
  555. registry.release(std::end(entities) - 1u, std::end(entities));
  556. ASSERT_FALSE(registry.valid(entities[2u]));
  557. }
  558. TEST(Registry, VersionOverflow) {
  559. using traits_type = entt::entt_traits<entt::entity>;
  560. entt::registry registry;
  561. const auto entity = registry.create();
  562. registry.release(entity);
  563. ASSERT_NE(registry.current(entity), traits_type::to_version(entity));
  564. ASSERT_NE(registry.current(entity), typename traits_type::version_type{});
  565. registry.release(registry.create(), traits_type::to_version(entt::tombstone) - 1u);
  566. registry.release(registry.create());
  567. ASSERT_EQ(registry.current(entity), traits_type::to_version(entity));
  568. ASSERT_EQ(registry.current(entity), typename traits_type::version_type{});
  569. }
  570. TEST(Registry, NullEntity) {
  571. entt::registry registry;
  572. const entt::entity entity = entt::null;
  573. ASSERT_FALSE(registry.valid(entity));
  574. ASSERT_NE(registry.create(entity), entity);
  575. }
  576. TEST(Registry, TombstoneVersion) {
  577. using traits_type = entt::entt_traits<entt::entity>;
  578. entt::registry registry;
  579. const entt::entity entity = entt::tombstone;
  580. ASSERT_FALSE(registry.valid(entity));
  581. const auto other = registry.create();
  582. const auto vers = traits_type::to_version(entity);
  583. const auto required = traits_type::construct(traits_type::to_entity(other), vers);
  584. ASSERT_NE(registry.release(other, vers), vers);
  585. ASSERT_NE(registry.create(required), required);
  586. }
  587. TEST(Registry, Each) {
  588. entt::registry registry;
  589. entt::registry::size_type tot;
  590. entt::registry::size_type match;
  591. static_cast<void>(registry.create());
  592. registry.emplace<int>(registry.create());
  593. static_cast<void>(registry.create());
  594. registry.emplace<int>(registry.create());
  595. static_cast<void>(registry.create());
  596. tot = 0u;
  597. match = 0u;
  598. registry.each([&](auto entity) {
  599. if(registry.all_of<int>(entity)) {
  600. ++match;
  601. }
  602. static_cast<void>(registry.create());
  603. ++tot;
  604. });
  605. ASSERT_EQ(tot, 5u);
  606. ASSERT_EQ(match, 2u);
  607. tot = 0u;
  608. match = 0u;
  609. registry.each([&](auto entity) {
  610. if(registry.all_of<int>(entity)) {
  611. registry.destroy(entity);
  612. ++match;
  613. }
  614. ++tot;
  615. });
  616. ASSERT_EQ(tot, 10u);
  617. ASSERT_EQ(match, 2u);
  618. tot = 0u;
  619. match = 0u;
  620. registry.each([&](auto entity) {
  621. if(registry.all_of<int>(entity)) {
  622. ++match;
  623. }
  624. registry.destroy(entity);
  625. ++tot;
  626. });
  627. ASSERT_EQ(tot, 8u);
  628. ASSERT_EQ(match, 0u);
  629. registry.each([&](auto) { FAIL(); });
  630. }
  631. TEST(Registry, Orphans) {
  632. entt::registry registry;
  633. entt::entity entities[3u]{};
  634. registry.create(std::begin(entities), std::end(entities));
  635. registry.emplace<int>(entities[0u]);
  636. registry.emplace<int>(entities[2u]);
  637. registry.each([&](const auto entt) {
  638. ASSERT_TRUE(entt != entities[1u] || registry.orphan(entt));
  639. });
  640. registry.erase<int>(entities[0u]);
  641. registry.erase<int>(entities[2u]);
  642. registry.each([&](const auto entt) {
  643. ASSERT_TRUE(registry.orphan(entt));
  644. });
  645. }
  646. TEST(Registry, View) {
  647. entt::registry registry;
  648. auto mview = registry.view<int, char>();
  649. auto iview = registry.view<int>();
  650. auto cview = registry.view<char>();
  651. entt::entity entities[3u];
  652. registry.create(std::begin(entities), std::end(entities));
  653. registry.emplace<int>(entities[0u], 0);
  654. registry.emplace<char>(entities[0u], 'c');
  655. registry.emplace<int>(entities[1u], 0);
  656. registry.emplace<int>(entities[2u], 0);
  657. registry.emplace<char>(entities[2u], 'c');
  658. ASSERT_EQ(iview.size(), 3u);
  659. ASSERT_EQ(cview.size(), 2u);
  660. std::size_t cnt{};
  661. mview.each([&cnt](auto...) { ++cnt; });
  662. ASSERT_EQ(cnt, 2u);
  663. }
  664. TEST(Registry, NonOwningGroupInitOnFirstUse) {
  665. entt::registry registry;
  666. entt::entity entities[3u];
  667. registry.create(std::begin(entities), std::end(entities));
  668. registry.insert<int>(std::begin(entities), std::end(entities), 0);
  669. registry.emplace<char>(entities[0u], 'c');
  670. registry.emplace<char>(entities[2u], 'c');
  671. std::size_t cnt{};
  672. auto group = registry.group<>(entt::get<int, char>);
  673. group.each([&cnt](auto...) { ++cnt; });
  674. ASSERT_FALSE((registry.owned<int, char>()));
  675. ASSERT_EQ(cnt, 2u);
  676. }
  677. TEST(Registry, NonOwningGroupInitOnEmplace) {
  678. entt::registry registry;
  679. entt::entity entities[3u];
  680. auto group = registry.group<>(entt::get<int, char>);
  681. registry.create(std::begin(entities), std::end(entities));
  682. registry.insert<int>(std::begin(entities), std::end(entities), 0);
  683. registry.emplace<char>(entities[0u], 'c');
  684. registry.emplace<char>(entities[2u], 'c');
  685. std::size_t cnt{};
  686. group.each([&cnt](auto...) { ++cnt; });
  687. ASSERT_FALSE((registry.owned<int, char>()));
  688. ASSERT_EQ(cnt, 2u);
  689. }
  690. TEST(Registry, FullOwningGroupInitOnFirstUse) {
  691. entt::registry registry;
  692. entt::entity entities[3u];
  693. registry.create(std::begin(entities), std::end(entities));
  694. registry.insert<int>(std::begin(entities), std::end(entities), 0);
  695. registry.emplace<char>(entities[0u], 'c');
  696. registry.emplace<char>(entities[2u], 'c');
  697. std::size_t cnt{};
  698. auto group = registry.group<int, char>();
  699. group.each([&cnt](auto...) { ++cnt; });
  700. ASSERT_TRUE(registry.owned<int>());
  701. ASSERT_TRUE(registry.owned<char>());
  702. ASSERT_FALSE(registry.owned<double>());
  703. ASSERT_EQ(cnt, 2u);
  704. }
  705. TEST(Registry, FullOwningGroupInitOnEmplace) {
  706. entt::registry registry;
  707. entt::entity entities[3u];
  708. auto group = registry.group<int, char>();
  709. registry.create(std::begin(entities), std::end(entities));
  710. registry.insert<int>(std::begin(entities), std::end(entities), 0);
  711. registry.emplace<char>(entities[0u], 'c');
  712. registry.emplace<char>(entities[2u], 'c');
  713. std::size_t cnt{};
  714. group.each([&cnt](auto...) { ++cnt; });
  715. ASSERT_TRUE(registry.owned<int>());
  716. ASSERT_TRUE(registry.owned<char>());
  717. ASSERT_FALSE(registry.owned<double>());
  718. ASSERT_EQ(cnt, 2u);
  719. }
  720. TEST(Registry, PartialOwningGroupInitOnFirstUse) {
  721. entt::registry registry;
  722. entt::entity entities[3u];
  723. registry.create(std::begin(entities), std::end(entities));
  724. registry.insert<int>(std::begin(entities), std::end(entities), 0);
  725. registry.emplace<char>(entities[0u], 'c');
  726. registry.emplace<char>(entities[2u], 'c');
  727. std::size_t cnt{};
  728. auto group = registry.group<int>(entt::get<char>);
  729. group.each([&cnt](auto...) { ++cnt; });
  730. ASSERT_TRUE((registry.owned<int, char>()));
  731. ASSERT_TRUE(registry.owned<int>());
  732. ASSERT_FALSE(registry.owned<char>());
  733. ASSERT_EQ(cnt, 2u);
  734. }
  735. TEST(Registry, PartialOwningGroupInitOnEmplace) {
  736. entt::registry registry;
  737. entt::entity entities[3u];
  738. auto group = registry.group<int>(entt::get<char>);
  739. registry.create(std::begin(entities), std::end(entities));
  740. registry.insert<int>(std::begin(entities), std::end(entities), 0);
  741. registry.emplace<char>(entities[0u], 'c');
  742. registry.emplace<char>(entities[2u], 'c');
  743. std::size_t cnt{};
  744. group.each([&cnt](auto...) { ++cnt; });
  745. ASSERT_TRUE((registry.owned<int, char>()));
  746. ASSERT_TRUE(registry.owned<int>());
  747. ASSERT_FALSE(registry.owned<char>());
  748. ASSERT_EQ(cnt, 2u);
  749. }
  750. TEST(Registry, CleanViewAfterRemoveAndClear) {
  751. entt::registry registry;
  752. auto view = registry.view<int, char>();
  753. const auto entity = registry.create();
  754. registry.emplace<int>(entity);
  755. registry.emplace<char>(entity);
  756. ASSERT_EQ(view.size_hint(), 1u);
  757. registry.erase<char>(entity);
  758. ASSERT_EQ(view.size_hint(), 1u);
  759. registry.emplace<char>(entity);
  760. ASSERT_EQ(view.size_hint(), 1u);
  761. registry.clear<int>();
  762. ASSERT_EQ(view.size_hint(), 0u);
  763. registry.emplace<int>(entity);
  764. ASSERT_EQ(view.size_hint(), 1u);
  765. registry.clear();
  766. ASSERT_EQ(view.size_hint(), 0u);
  767. }
  768. TEST(Registry, CleanNonOwningGroupViewAfterRemoveAndClear) {
  769. entt::registry registry;
  770. auto group = registry.group<>(entt::get<int, char>);
  771. const auto entity = registry.create();
  772. registry.emplace<int>(entity, 0);
  773. registry.emplace<char>(entity, 'c');
  774. ASSERT_EQ(group.size(), 1u);
  775. registry.erase<char>(entity);
  776. ASSERT_EQ(group.size(), 0u);
  777. registry.emplace<char>(entity, 'c');
  778. ASSERT_EQ(group.size(), 1u);
  779. registry.clear<int>();
  780. ASSERT_EQ(group.size(), 0u);
  781. registry.emplace<int>(entity, 0);
  782. ASSERT_EQ(group.size(), 1u);
  783. registry.clear();
  784. ASSERT_EQ(group.size(), 0u);
  785. }
  786. TEST(Registry, CleanFullOwningGroupViewAfterRemoveAndClear) {
  787. entt::registry registry;
  788. auto group = registry.group<int, char>();
  789. const auto entity = registry.create();
  790. registry.emplace<int>(entity, 0);
  791. registry.emplace<char>(entity, 'c');
  792. ASSERT_EQ(group.size(), 1u);
  793. registry.erase<char>(entity);
  794. ASSERT_EQ(group.size(), 0u);
  795. registry.emplace<char>(entity, 'c');
  796. ASSERT_EQ(group.size(), 1u);
  797. registry.clear<int>();
  798. ASSERT_EQ(group.size(), 0u);
  799. registry.emplace<int>(entity, 0);
  800. ASSERT_EQ(group.size(), 1u);
  801. registry.clear();
  802. ASSERT_EQ(group.size(), 0u);
  803. }
  804. TEST(Registry, CleanPartialOwningGroupViewAfterRemoveAndClear) {
  805. entt::registry registry;
  806. auto group = registry.group<int>(entt::get<char>);
  807. const auto entity = registry.create();
  808. registry.emplace<int>(entity, 0);
  809. registry.emplace<char>(entity, 'c');
  810. ASSERT_EQ(group.size(), 1u);
  811. registry.erase<char>(entity);
  812. ASSERT_EQ(group.size(), 0u);
  813. registry.emplace<char>(entity, 'c');
  814. ASSERT_EQ(group.size(), 1u);
  815. registry.clear<int>();
  816. ASSERT_EQ(group.size(), 0u);
  817. registry.emplace<int>(entity, 0);
  818. ASSERT_EQ(group.size(), 1u);
  819. registry.clear();
  820. ASSERT_EQ(group.size(), 0u);
  821. }
  822. TEST(Registry, NestedGroups) {
  823. entt::registry registry;
  824. entt::entity entities[10];
  825. registry.create(std::begin(entities), std::end(entities));
  826. registry.insert<int>(std::begin(entities), std::end(entities));
  827. registry.insert<char>(std::begin(entities), std::end(entities));
  828. const auto g1 = registry.group<int>(entt::get<char>, entt::exclude<double>);
  829. ASSERT_TRUE(registry.sortable(g1));
  830. ASSERT_EQ(g1.size(), 10u);
  831. const auto g2 = registry.group<int>(entt::get<char>);
  832. ASSERT_TRUE(registry.sortable(g1));
  833. ASSERT_FALSE(registry.sortable(g2));
  834. ASSERT_EQ(g1.size(), 10u);
  835. ASSERT_EQ(g2.size(), 10u);
  836. for(auto i = 0u; i < 5u; ++i) {
  837. ASSERT_TRUE(g1.contains(entities[i * 2 + 1]));
  838. ASSERT_TRUE(g1.contains(entities[i * 2]));
  839. ASSERT_TRUE(g2.contains(entities[i * 2 + 1]));
  840. ASSERT_TRUE(g2.contains(entities[i * 2]));
  841. registry.emplace<double>(entities[i * 2]);
  842. }
  843. ASSERT_EQ(g1.size(), 5u);
  844. ASSERT_EQ(g2.size(), 10u);
  845. for(auto i = 0u; i < 5u; ++i) {
  846. ASSERT_TRUE(g1.contains(entities[i * 2 + 1]));
  847. ASSERT_FALSE(g1.contains(entities[i * 2]));
  848. ASSERT_TRUE(g2.contains(entities[i * 2 + 1]));
  849. ASSERT_TRUE(g2.contains(entities[i * 2]));
  850. registry.erase<int>(entities[i * 2 + 1]);
  851. }
  852. ASSERT_EQ(g1.size(), 0u);
  853. ASSERT_EQ(g2.size(), 5u);
  854. const auto g3 = registry.group<int, float>(entt::get<char>, entt::exclude<double>);
  855. ASSERT_FALSE(registry.sortable(g1));
  856. ASSERT_FALSE(registry.sortable(g2));
  857. ASSERT_TRUE(registry.sortable(g3));
  858. ASSERT_EQ(g1.size(), 0u);
  859. ASSERT_EQ(g2.size(), 5u);
  860. ASSERT_EQ(g3.size(), 0u);
  861. for(auto i = 0u; i < 5u; ++i) {
  862. ASSERT_FALSE(g1.contains(entities[i * 2 + 1]));
  863. ASSERT_FALSE(g1.contains(entities[i * 2]));
  864. ASSERT_FALSE(g2.contains(entities[i * 2 + 1]));
  865. ASSERT_TRUE(g2.contains(entities[i * 2]));
  866. ASSERT_FALSE(g3.contains(entities[i * 2 + 1]));
  867. ASSERT_FALSE(g3.contains(entities[i * 2]));
  868. registry.emplace<int>(entities[i * 2 + 1]);
  869. }
  870. ASSERT_EQ(g1.size(), 5u);
  871. ASSERT_EQ(g2.size(), 10u);
  872. ASSERT_EQ(g3.size(), 0u);
  873. for(auto i = 0u; i < 5u; ++i) {
  874. ASSERT_TRUE(g1.contains(entities[i * 2 + 1]));
  875. ASSERT_FALSE(g1.contains(entities[i * 2]));
  876. ASSERT_TRUE(g2.contains(entities[i * 2 + 1]));
  877. ASSERT_TRUE(g2.contains(entities[i * 2]));
  878. ASSERT_FALSE(g3.contains(entities[i * 2 + 1]));
  879. ASSERT_FALSE(g3.contains(entities[i * 2]));
  880. registry.emplace<float>(entities[i * 2]);
  881. }
  882. ASSERT_EQ(g1.size(), 5u);
  883. ASSERT_EQ(g2.size(), 10u);
  884. ASSERT_EQ(g3.size(), 0u);
  885. for(auto i = 0u; i < 5u; ++i) {
  886. registry.erase<double>(entities[i * 2]);
  887. }
  888. ASSERT_EQ(g1.size(), 10u);
  889. ASSERT_EQ(g2.size(), 10u);
  890. ASSERT_EQ(g3.size(), 5u);
  891. for(auto i = 0u; i < 5u; ++i) {
  892. ASSERT_TRUE(g1.contains(entities[i * 2 + 1]));
  893. ASSERT_TRUE(g1.contains(entities[i * 2]));
  894. ASSERT_TRUE(g2.contains(entities[i * 2 + 1]));
  895. ASSERT_TRUE(g2.contains(entities[i * 2]));
  896. ASSERT_FALSE(g3.contains(entities[i * 2 + 1]));
  897. ASSERT_TRUE(g3.contains(entities[i * 2]));
  898. registry.erase<int>(entities[i * 2 + 1]);
  899. registry.erase<int>(entities[i * 2]);
  900. }
  901. ASSERT_EQ(g1.size(), 0u);
  902. ASSERT_EQ(g2.size(), 0u);
  903. ASSERT_EQ(g3.size(), 0u);
  904. }
  905. TEST(Registry, SortSingle) {
  906. entt::registry registry;
  907. int val = 0;
  908. registry.emplace<int>(registry.create(), val++);
  909. registry.emplace<int>(registry.create(), val++);
  910. registry.emplace<int>(registry.create(), val++);
  911. for(auto entity: registry.view<int>()) {
  912. ASSERT_EQ(registry.get<int>(entity), --val);
  913. }
  914. registry.sort<int>(std::less<int>{});
  915. for(auto entity: registry.view<int>()) {
  916. ASSERT_EQ(registry.get<int>(entity), val++);
  917. }
  918. }
  919. TEST(Registry, SortMulti) {
  920. entt::registry registry;
  921. unsigned int uval = 0u;
  922. int ival = 0;
  923. for(auto i = 0; i < 3; ++i) {
  924. const auto entity = registry.create();
  925. registry.emplace<unsigned int>(entity, uval++);
  926. registry.emplace<int>(entity, ival++);
  927. }
  928. for(auto entity: registry.view<unsigned int>()) {
  929. ASSERT_EQ(registry.get<unsigned int>(entity), --uval);
  930. }
  931. for(auto entity: registry.view<int>()) {
  932. ASSERT_EQ(registry.get<int>(entity), --ival);
  933. }
  934. registry.sort<unsigned int>(std::less<unsigned int>{});
  935. registry.sort<int, unsigned int>();
  936. for(auto entity: registry.view<unsigned int>()) {
  937. ASSERT_EQ(registry.get<unsigned int>(entity), uval++);
  938. }
  939. for(auto entity: registry.view<int>()) {
  940. ASSERT_EQ(registry.get<int>(entity), ival++);
  941. }
  942. }
  943. TEST(Registry, SortEmpty) {
  944. entt::registry registry;
  945. registry.emplace<empty_type>(registry.create());
  946. registry.emplace<empty_type>(registry.create());
  947. registry.emplace<empty_type>(registry.create());
  948. ASSERT_LT(registry.storage<empty_type>().data()[0], registry.storage<empty_type>().data()[1]);
  949. ASSERT_LT(registry.storage<empty_type>().data()[1], registry.storage<empty_type>().data()[2]);
  950. registry.sort<empty_type>(std::less<entt::entity>{});
  951. ASSERT_GT(registry.storage<empty_type>().data()[0], registry.storage<empty_type>().data()[1]);
  952. ASSERT_GT(registry.storage<empty_type>().data()[1], registry.storage<empty_type>().data()[2]);
  953. }
  954. TEST(Registry, ComponentsWithTypesFromStandardTemplateLibrary) {
  955. // see #37 - the test shouldn't crash, that's all
  956. entt::registry registry;
  957. const auto entity = registry.create();
  958. registry.emplace<std::unordered_set<int>>(entity).insert(42);
  959. registry.destroy(entity);
  960. }
  961. TEST(Registry, ConstructWithComponents) {
  962. // it should compile, that's all
  963. entt::registry registry;
  964. const auto value = 0;
  965. registry.emplace<int>(registry.create(), value);
  966. }
  967. TEST(Registry, Signals) {
  968. entt::registry registry;
  969. entt::entity entities[2u];
  970. listener listener;
  971. registry.on_construct<empty_type>().connect<&listener::incr<empty_type>>(listener);
  972. registry.on_destroy<empty_type>().connect<&listener::decr<empty_type>>(listener);
  973. registry.on_construct<int>().connect<&listener::incr<int>>(listener);
  974. registry.on_destroy<int>().connect<&listener::decr<int>>(listener);
  975. registry.create(std::begin(entities), std::end(entities));
  976. registry.insert<empty_type>(std::begin(entities), std::end(entities));
  977. ASSERT_EQ(listener.counter, 2);
  978. ASSERT_EQ(listener.last, entities[1u]);
  979. registry.insert<int>(std::rbegin(entities), std::rend(entities));
  980. ASSERT_EQ(listener.counter, 4);
  981. ASSERT_EQ(listener.last, entities[0u]);
  982. registry.erase<empty_type, int>(entities[0u]);
  983. ASSERT_EQ(listener.counter, 2);
  984. ASSERT_EQ(listener.last, entities[0u]);
  985. registry.on_destroy<empty_type>().disconnect<&listener::decr<empty_type>>(listener);
  986. registry.on_destroy<int>().disconnect<&listener::decr<int>>(listener);
  987. registry.erase<empty_type, int>(entities[1u]);
  988. ASSERT_EQ(listener.counter, 2);
  989. ASSERT_EQ(listener.last, entities[0u]);
  990. registry.on_construct<empty_type>().disconnect<&listener::incr<empty_type>>(listener);
  991. registry.on_construct<int>().disconnect<&listener::incr<int>>(listener);
  992. registry.emplace<empty_type>(entities[1u]);
  993. registry.emplace<int>(entities[1u]);
  994. ASSERT_EQ(listener.counter, 2);
  995. ASSERT_EQ(listener.last, entities[0u]);
  996. registry.on_construct<int>().connect<&listener::incr<int>>(listener);
  997. registry.on_destroy<int>().connect<&listener::decr<int>>(listener);
  998. registry.emplace<int>(entities[0u]);
  999. registry.erase<int>(entities[1u]);
  1000. ASSERT_EQ(listener.counter, 2);
  1001. ASSERT_EQ(listener.last, entities[1u]);
  1002. registry.on_construct<empty_type>().connect<&listener::incr<empty_type>>(listener);
  1003. registry.on_destroy<empty_type>().connect<&listener::decr<empty_type>>(listener);
  1004. registry.erase<empty_type>(entities[1u]);
  1005. registry.emplace<empty_type>(entities[0u]);
  1006. ASSERT_EQ(listener.counter, 2);
  1007. ASSERT_EQ(listener.last, entities[0u]);
  1008. registry.clear<empty_type, int>();
  1009. ASSERT_EQ(listener.counter, 0);
  1010. ASSERT_EQ(listener.last, entities[0u]);
  1011. registry.insert<empty_type>(std::begin(entities), std::end(entities));
  1012. registry.insert<int>(std::begin(entities), std::end(entities));
  1013. registry.destroy(entities[1u]);
  1014. ASSERT_EQ(listener.counter, 2);
  1015. ASSERT_EQ(listener.last, entities[1u]);
  1016. registry.erase<int, empty_type>(entities[0u]);
  1017. registry.emplace_or_replace<int>(entities[0u]);
  1018. registry.emplace_or_replace<empty_type>(entities[0u]);
  1019. ASSERT_EQ(listener.counter, 2);
  1020. ASSERT_EQ(listener.last, entities[0u]);
  1021. registry.on_destroy<empty_type>().disconnect<&listener::decr<empty_type>>(listener);
  1022. registry.on_destroy<int>().disconnect<&listener::decr<int>>(listener);
  1023. registry.emplace_or_replace<empty_type>(entities[0u]);
  1024. registry.emplace_or_replace<int>(entities[0u]);
  1025. ASSERT_EQ(listener.counter, 2);
  1026. ASSERT_EQ(listener.last, entities[0u]);
  1027. registry.on_update<empty_type>().connect<&listener::incr<empty_type>>(listener);
  1028. registry.on_update<int>().connect<&listener::incr<int>>(listener);
  1029. registry.emplace_or_replace<empty_type>(entities[0u]);
  1030. registry.emplace_or_replace<int>(entities[0u]);
  1031. ASSERT_EQ(listener.counter, 4);
  1032. ASSERT_EQ(listener.last, entities[0u]);
  1033. registry.replace<empty_type>(entities[0u]);
  1034. registry.replace<int>(entities[0u]);
  1035. ASSERT_EQ(listener.counter, 6);
  1036. ASSERT_EQ(listener.last, entities[0u]);
  1037. }
  1038. TEST(Registry, SignalWhenDestroying) {
  1039. entt::registry registry;
  1040. const auto entity = registry.create();
  1041. registry.on_destroy<double>().connect<&entt::registry::remove<char>>();
  1042. registry.emplace<double>(entity);
  1043. registry.emplace<int>(entity);
  1044. ASSERT_NE(registry.storage(entt::type_id<double>().hash()), registry.storage().end());
  1045. ASSERT_NE(registry.storage(entt::type_id<int>().hash()), registry.storage().end());
  1046. ASSERT_EQ(registry.storage(entt::type_id<char>().hash()), registry.storage().end());
  1047. ASSERT_TRUE(registry.valid(entity));
  1048. registry.destroy(entity);
  1049. ASSERT_NE(registry.storage(entt::type_id<char>().hash()), registry.storage().end());
  1050. ASSERT_FALSE(registry.valid(entity));
  1051. }
  1052. TEST(Registry, Insert) {
  1053. entt::registry registry;
  1054. entt::entity entities[3u];
  1055. registry.create(std::begin(entities), std::end(entities));
  1056. registry.emplace<int>(entities[0u]);
  1057. registry.emplace<char>(entities[0u]);
  1058. registry.emplace<double>(entities[0u]);
  1059. registry.emplace<int>(entities[1u]);
  1060. registry.emplace<char>(entities[1u]);
  1061. registry.emplace<int>(entities[2u]);
  1062. ASSERT_FALSE(registry.all_of<float>(entities[0u]));
  1063. ASSERT_FALSE(registry.all_of<float>(entities[1u]));
  1064. ASSERT_FALSE(registry.all_of<float>(entities[2u]));
  1065. const auto icview = registry.view<int, char>();
  1066. registry.insert(icview.begin(), icview.end(), 3.f);
  1067. ASSERT_EQ(registry.get<float>(entities[0u]), 3.f);
  1068. ASSERT_EQ(registry.get<float>(entities[1u]), 3.f);
  1069. ASSERT_FALSE(registry.all_of<float>(entities[2u]));
  1070. registry.clear<float>();
  1071. float value[3]{0.f, 1.f, 2.f};
  1072. const auto iview = registry.view<int>();
  1073. registry.insert<float>(iview.rbegin(), iview.rend(), value);
  1074. ASSERT_EQ(registry.get<float>(entities[0u]), 0.f);
  1075. ASSERT_EQ(registry.get<float>(entities[1u]), 1.f);
  1076. ASSERT_EQ(registry.get<float>(entities[2u]), 2.f);
  1077. }
  1078. TEST(Registry, Erase) {
  1079. entt::registry registry;
  1080. const auto iview = registry.view<int>();
  1081. const auto icview = registry.view<int, char>();
  1082. entt::entity entities[3u];
  1083. registry.create(std::begin(entities), std::end(entities));
  1084. registry.emplace<int>(entities[0u]);
  1085. registry.emplace<char>(entities[0u]);
  1086. registry.emplace<double>(entities[0u]);
  1087. registry.emplace<int>(entities[1u]);
  1088. registry.emplace<char>(entities[1u]);
  1089. registry.emplace<int>(entities[2u]);
  1090. ASSERT_TRUE(registry.any_of<int>(entities[0u]));
  1091. ASSERT_TRUE(registry.all_of<int>(entities[1u]));
  1092. ASSERT_TRUE(registry.any_of<int>(entities[2u]));
  1093. registry.erase<int, char>(entities[0u]);
  1094. registry.erase<int, char>(icview.begin(), icview.end());
  1095. ASSERT_FALSE(registry.any_of<int>(entities[0u]));
  1096. ASSERT_FALSE(registry.all_of<int>(entities[1u]));
  1097. ASSERT_TRUE(registry.any_of<int>(entities[2u]));
  1098. ASSERT_EQ(registry.storage<int>().size(), 1u);
  1099. ASSERT_EQ(registry.storage<char>().size(), 0u);
  1100. ASSERT_EQ(registry.storage<double>().size(), 1u);
  1101. registry.erase<int>(iview.begin(), iview.end());
  1102. ASSERT_FALSE(registry.any_of<int>(entities[2u]));
  1103. ASSERT_NO_FATAL_FAILURE(registry.erase<int>(iview.rbegin(), iview.rend()));
  1104. ASSERT_EQ(registry.storage<int>().size(), 0u);
  1105. ASSERT_EQ(registry.storage<char>().size(), 0u);
  1106. ASSERT_EQ(registry.storage<double>().size(), 1u);
  1107. registry.insert<int>(std::begin(entities), std::end(entities));
  1108. registry.insert<char>(std::begin(entities), std::end(entities));
  1109. ASSERT_EQ(registry.storage<int>().size(), 3u);
  1110. ASSERT_EQ(registry.storage<char>().size(), 3u);
  1111. registry.erase<int, char>(std::begin(entities), std::end(entities));
  1112. ASSERT_EQ(registry.storage<int>().size(), 0u);
  1113. ASSERT_EQ(registry.storage<char>().size(), 0u);
  1114. ASSERT_FALSE(registry.orphan(entities[0u]));
  1115. ASSERT_TRUE(registry.orphan(entities[1u]));
  1116. ASSERT_TRUE(registry.orphan(entities[2u]));
  1117. }
  1118. ENTT_DEBUG_TEST(RegistryDeathTest, Erase) {
  1119. entt::registry registry;
  1120. const entt::entity entities[1u]{registry.create()};
  1121. ASSERT_FALSE((registry.any_of<int>(entities[0u])));
  1122. ASSERT_DEATH((registry.erase<int>(std::begin(entities), std::end(entities))), "");
  1123. ASSERT_DEATH(registry.erase<int>(entities[0u]), "");
  1124. }
  1125. TEST(Registry, StableErase) {
  1126. entt::registry registry;
  1127. const auto iview = registry.view<int>();
  1128. const auto icview = registry.view<int, stable_type>();
  1129. entt::entity entities[3u];
  1130. registry.create(std::begin(entities), std::end(entities));
  1131. registry.emplace<int>(entities[0u]);
  1132. registry.emplace<stable_type>(entities[0u]);
  1133. registry.emplace<double>(entities[0u]);
  1134. registry.emplace<int>(entities[1u]);
  1135. registry.emplace<stable_type>(entities[1u]);
  1136. registry.emplace<int>(entities[2u]);
  1137. ASSERT_TRUE(registry.any_of<int>(entities[0u]));
  1138. ASSERT_TRUE(registry.all_of<int>(entities[1u]));
  1139. ASSERT_TRUE(registry.any_of<int>(entities[2u]));
  1140. registry.erase<int, stable_type>(entities[0u]);
  1141. registry.erase<int, stable_type>(icview.begin(), icview.end());
  1142. registry.erase<int, stable_type>(icview.begin(), icview.end());
  1143. ASSERT_FALSE(registry.any_of<int>(entities[0u]));
  1144. ASSERT_FALSE(registry.all_of<int>(entities[1u]));
  1145. ASSERT_TRUE(registry.any_of<int>(entities[2u]));
  1146. ASSERT_EQ(registry.storage<int>().size(), 1u);
  1147. ASSERT_EQ(registry.storage<stable_type>().size(), 2u);
  1148. ASSERT_EQ(registry.storage<double>().size(), 1u);
  1149. registry.erase<int>(iview.begin(), iview.end());
  1150. ASSERT_FALSE(registry.any_of<int>(entities[2u]));
  1151. ASSERT_EQ(registry.storage<int>().size(), 0u);
  1152. ASSERT_EQ(registry.storage<stable_type>().size(), 2u);
  1153. ASSERT_EQ(registry.storage<double>().size(), 1u);
  1154. }
  1155. TEST(Registry, Remove) {
  1156. entt::registry registry;
  1157. const auto iview = registry.view<int>();
  1158. const auto icview = registry.view<int, char>();
  1159. entt::entity entities[3u];
  1160. registry.create(std::begin(entities), std::end(entities));
  1161. registry.emplace<int>(entities[0u]);
  1162. registry.emplace<char>(entities[0u]);
  1163. registry.emplace<double>(entities[0u]);
  1164. registry.emplace<int>(entities[1u]);
  1165. registry.emplace<char>(entities[1u]);
  1166. registry.emplace<int>(entities[2u]);
  1167. ASSERT_TRUE(registry.any_of<int>(entities[0u]));
  1168. ASSERT_TRUE(registry.all_of<int>(entities[1u]));
  1169. ASSERT_TRUE(registry.any_of<int>(entities[2u]));
  1170. registry.remove<int, char>(entities[0u]);
  1171. ASSERT_EQ((registry.remove<int, char>(icview.begin(), icview.end())), 2u);
  1172. ASSERT_EQ((registry.remove<int, char>(icview.begin(), icview.end())), 0u);
  1173. ASSERT_FALSE(registry.any_of<int>(entities[0u]));
  1174. ASSERT_FALSE(registry.all_of<int>(entities[1u]));
  1175. ASSERT_TRUE(registry.any_of<int>(entities[2u]));
  1176. ASSERT_EQ(registry.storage<int>().size(), 1u);
  1177. ASSERT_EQ(registry.storage<char>().size(), 0u);
  1178. ASSERT_EQ(registry.storage<double>().size(), 1u);
  1179. ASSERT_EQ((registry.remove<int>(iview.begin(), iview.end())), 1u);
  1180. ASSERT_EQ(registry.remove<int>(entities[0u]), 0u);
  1181. ASSERT_EQ(registry.remove<int>(entities[1u]), 0u);
  1182. ASSERT_FALSE(registry.any_of<int>(entities[2u]));
  1183. ASSERT_EQ(registry.remove<int>(iview.begin(), iview.end()), 0u);
  1184. ASSERT_EQ(registry.storage<int>().size(), 0u);
  1185. ASSERT_EQ(registry.storage<char>().size(), 0u);
  1186. ASSERT_EQ(registry.storage<double>().size(), 1u);
  1187. registry.insert<int>(std::begin(entities), std::end(entities));
  1188. registry.insert<char>(std::begin(entities), std::end(entities));
  1189. ASSERT_EQ(registry.storage<int>().size(), 3u);
  1190. ASSERT_EQ(registry.storage<char>().size(), 3u);
  1191. registry.remove<int, char>(std::begin(entities), std::end(entities));
  1192. registry.remove<int, char>(std::begin(entities), std::end(entities));
  1193. ASSERT_EQ(registry.storage<int>().size(), 0u);
  1194. ASSERT_EQ(registry.storage<char>().size(), 0u);
  1195. ASSERT_FALSE(registry.orphan(entities[0u]));
  1196. ASSERT_TRUE(registry.orphan(entities[1u]));
  1197. ASSERT_TRUE(registry.orphan(entities[2u]));
  1198. }
  1199. TEST(Registry, StableRemove) {
  1200. entt::registry registry;
  1201. const auto iview = registry.view<int>();
  1202. const auto icview = registry.view<int, stable_type>();
  1203. entt::entity entities[3u];
  1204. registry.create(std::begin(entities), std::end(entities));
  1205. registry.emplace<int>(entities[0u]);
  1206. registry.emplace<stable_type>(entities[0u]);
  1207. registry.emplace<double>(entities[0u]);
  1208. registry.emplace<int>(entities[1u]);
  1209. registry.emplace<stable_type>(entities[1u]);
  1210. registry.emplace<int>(entities[2u]);
  1211. ASSERT_TRUE(registry.any_of<int>(entities[0u]));
  1212. ASSERT_TRUE(registry.all_of<int>(entities[1u]));
  1213. ASSERT_TRUE(registry.any_of<int>(entities[2u]));
  1214. registry.remove<int, stable_type>(entities[0u]);
  1215. ASSERT_EQ((registry.remove<int, stable_type>(icview.begin(), icview.end())), 2u);
  1216. ASSERT_EQ((registry.remove<int, stable_type>(icview.begin(), icview.end())), 0u);
  1217. ASSERT_FALSE(registry.any_of<int>(entities[0u]));
  1218. ASSERT_FALSE(registry.all_of<int>(entities[1u]));
  1219. ASSERT_TRUE(registry.any_of<int>(entities[2u]));
  1220. ASSERT_EQ(registry.storage<int>().size(), 1u);
  1221. ASSERT_EQ(registry.storage<stable_type>().size(), 2u);
  1222. ASSERT_EQ(registry.storage<double>().size(), 1u);
  1223. ASSERT_EQ((registry.remove<int>(iview.begin(), iview.end())), 1u);
  1224. ASSERT_EQ(registry.remove<int>(entities[0u]), 0u);
  1225. ASSERT_EQ(registry.remove<int>(entities[1u]), 0u);
  1226. ASSERT_FALSE(registry.any_of<int>(entities[2u]));
  1227. ASSERT_EQ(registry.storage<int>().size(), 0u);
  1228. ASSERT_EQ(registry.storage<stable_type>().size(), 2u);
  1229. ASSERT_EQ(registry.storage<double>().size(), 1u);
  1230. }
  1231. TEST(Registry, Compact) {
  1232. entt::registry registry;
  1233. entt::entity entities[2u];
  1234. registry.create(std::begin(entities), std::end(entities));
  1235. registry.emplace<int>(entities[0u]);
  1236. registry.emplace<stable_type>(entities[0u]);
  1237. registry.emplace<int>(entities[1u]);
  1238. registry.emplace<stable_type>(entities[1u]);
  1239. ASSERT_EQ(registry.storage<int>().size(), 2u);
  1240. ASSERT_EQ(registry.storage<stable_type>().size(), 2u);
  1241. registry.destroy(std::begin(entities), std::end(entities));
  1242. ASSERT_EQ(registry.storage<int>().size(), 0u);
  1243. ASSERT_EQ(registry.storage<stable_type>().size(), 2u);
  1244. registry.compact<int>();
  1245. ASSERT_EQ(registry.storage<int>().size(), 0u);
  1246. ASSERT_EQ(registry.storage<stable_type>().size(), 2u);
  1247. registry.compact();
  1248. ASSERT_EQ(registry.storage<int>().size(), 0u);
  1249. ASSERT_EQ(registry.storage<stable_type>().size(), 0u);
  1250. }
  1251. TEST(Registry, NonOwningGroupInterleaved) {
  1252. entt::registry registry;
  1253. typename entt::entity entity = entt::null;
  1254. entity = registry.create();
  1255. registry.emplace<int>(entity);
  1256. registry.emplace<char>(entity);
  1257. const auto group = registry.group<>(entt::get<int, char>);
  1258. entity = registry.create();
  1259. registry.emplace<int>(entity);
  1260. registry.emplace<char>(entity);
  1261. std::size_t cnt{};
  1262. group.each([&cnt](auto...) { ++cnt; });
  1263. ASSERT_EQ(cnt, 2u);
  1264. }
  1265. TEST(Registry, FullOwningGroupInterleaved) {
  1266. entt::registry registry;
  1267. typename entt::entity entity = entt::null;
  1268. entity = registry.create();
  1269. registry.emplace<int>(entity);
  1270. registry.emplace<char>(entity);
  1271. const auto group = registry.group<int, char>();
  1272. entity = registry.create();
  1273. registry.emplace<int>(entity);
  1274. registry.emplace<char>(entity);
  1275. std::size_t cnt{};
  1276. group.each([&cnt](auto...) { ++cnt; });
  1277. ASSERT_EQ(cnt, 2u);
  1278. }
  1279. TEST(Registry, PartialOwningGroupInterleaved) {
  1280. entt::registry registry;
  1281. typename entt::entity entity = entt::null;
  1282. entity = registry.create();
  1283. registry.emplace<int>(entity);
  1284. registry.emplace<char>(entity);
  1285. const auto group = registry.group<int>(entt::get<char>);
  1286. entity = registry.create();
  1287. registry.emplace<int>(entity);
  1288. registry.emplace<char>(entity);
  1289. std::size_t cnt{};
  1290. group.each([&cnt](auto...) { ++cnt; });
  1291. ASSERT_EQ(cnt, 2u);
  1292. }
  1293. TEST(Registry, NonOwningGroupSortInterleaved) {
  1294. entt::registry registry;
  1295. const auto group = registry.group<>(entt::get<int, char>);
  1296. const auto e0 = registry.create();
  1297. registry.emplace<int>(e0, 0);
  1298. registry.emplace<char>(e0, '0');
  1299. const auto e1 = registry.create();
  1300. registry.emplace<int>(e1, 1);
  1301. registry.emplace<char>(e1, '1');
  1302. registry.sort<int>(std::greater{});
  1303. registry.sort<char>(std::less{});
  1304. const auto e2 = registry.create();
  1305. registry.emplace<int>(e2, 2);
  1306. registry.emplace<char>(e2, '2');
  1307. group.each([e0, e1, e2](const auto entity, const auto &i, const auto &c) {
  1308. if(entity == e0) {
  1309. ASSERT_EQ(i, 0);
  1310. ASSERT_EQ(c, '0');
  1311. } else if(entity == e1) {
  1312. ASSERT_EQ(i, 1);
  1313. ASSERT_EQ(c, '1');
  1314. } else if(entity == e2) {
  1315. ASSERT_EQ(i, 2);
  1316. ASSERT_EQ(c, '2');
  1317. }
  1318. });
  1319. }
  1320. TEST(Registry, GetOrEmplace) {
  1321. entt::registry registry;
  1322. const auto entity = registry.create();
  1323. const auto value = registry.get_or_emplace<int>(entity, 3);
  1324. // get_or_emplace must work for empty types
  1325. static_cast<void>(registry.get_or_emplace<empty_type>(entity));
  1326. ASSERT_TRUE((registry.all_of<int, empty_type>(entity)));
  1327. ASSERT_EQ(registry.get<int>(entity), value);
  1328. ASSERT_EQ(registry.get<int>(entity), 3);
  1329. }
  1330. TEST(Registry, Constness) {
  1331. entt::registry registry;
  1332. static_assert((std::is_same_v<decltype(registry.emplace<int>({})), int &>));
  1333. static_assert((std::is_same_v<decltype(registry.emplace<empty_type>({})), void>));
  1334. static_assert((std::is_same_v<decltype(registry.get<int>({})), int &>));
  1335. static_assert((std::is_same_v<decltype(registry.get<int, const char>({})), std::tuple<int &, const char &>>));
  1336. static_assert((std::is_same_v<decltype(registry.try_get<int>({})), int *>));
  1337. static_assert((std::is_same_v<decltype(registry.try_get<int, const char>({})), std::tuple<int *, const char *>>));
  1338. static_assert((std::is_same_v<decltype(registry.ctx().get<int>()), int &>));
  1339. static_assert((std::is_same_v<decltype(registry.ctx().get<const char>()), const char &>));
  1340. static_assert((std::is_same_v<decltype(registry.ctx().find<int>()), int *>));
  1341. static_assert((std::is_same_v<decltype(registry.ctx().find<const char>()), const char *>));
  1342. static_assert((std::is_same_v<decltype(std::as_const(registry).get<int>({})), const int &>));
  1343. static_assert((std::is_same_v<decltype(std::as_const(registry).get<int, const char>({})), std::tuple<const int &, const char &>>));
  1344. static_assert((std::is_same_v<decltype(std::as_const(registry).try_get<int>({})), const int *>));
  1345. static_assert((std::is_same_v<decltype(std::as_const(registry).try_get<int, const char>({})), std::tuple<const int *, const char *>>));
  1346. static_assert((std::is_same_v<decltype(std::as_const(registry).ctx().get<int>()), const int &>));
  1347. static_assert((std::is_same_v<decltype(std::as_const(registry).ctx().get<const char>()), const char &>));
  1348. static_assert((std::is_same_v<decltype(std::as_const(registry).ctx().find<int>()), const int *>));
  1349. static_assert((std::is_same_v<decltype(std::as_const(registry).ctx().find<const char>()), const char *>));
  1350. }
  1351. TEST(Registry, MoveOnlyComponent) {
  1352. entt::registry registry;
  1353. // the purpose is to ensure that move only types are always accepted
  1354. registry.emplace<std::unique_ptr<int>>(registry.create());
  1355. }
  1356. TEST(Registry, NonDefaultConstructibleComponent) {
  1357. entt::registry registry;
  1358. // the purpose is to ensure that non default constructible type are always accepted
  1359. registry.emplace<non_default_constructible>(registry.create(), 42);
  1360. }
  1361. TEST(Registry, Dependencies) {
  1362. entt::registry registry;
  1363. const auto entity = registry.create();
  1364. // required because of an issue of VS2019
  1365. constexpr auto emplace_or_replace = &entt::registry::emplace_or_replace<double>;
  1366. constexpr auto remove = &entt::registry::remove<double>;
  1367. registry.on_construct<int>().connect<emplace_or_replace>();
  1368. registry.on_destroy<int>().connect<remove>();
  1369. registry.emplace<double>(entity, .3);
  1370. ASSERT_FALSE(registry.all_of<int>(entity));
  1371. ASSERT_EQ(registry.get<double>(entity), .3);
  1372. registry.emplace<int>(entity);
  1373. ASSERT_TRUE(registry.all_of<int>(entity));
  1374. ASSERT_EQ(registry.get<double>(entity), .0);
  1375. registry.erase<int>(entity);
  1376. ASSERT_FALSE((registry.any_of<int, double>(entity)));
  1377. registry.on_construct<int>().disconnect<emplace_or_replace>();
  1378. registry.on_destroy<int>().disconnect<remove>();
  1379. registry.emplace<int>(entity);
  1380. ASSERT_TRUE((registry.any_of<int, double>(entity)));
  1381. ASSERT_FALSE(registry.all_of<double>(entity));
  1382. }
  1383. TEST(Registry, StableEmplace) {
  1384. entt::registry registry;
  1385. registry.on_construct<int>().connect<&listener::sort<int>>();
  1386. registry.emplace<int>(registry.create(), 0);
  1387. ASSERT_EQ(registry.emplace<int>(registry.create(), 1), 1);
  1388. }
  1389. TEST(Registry, AssignEntities) {
  1390. using traits_type = entt::entt_traits<entt::entity>;
  1391. entt::registry registry;
  1392. entt::entity entities[3];
  1393. registry.create(std::begin(entities), std::end(entities));
  1394. registry.release(entities[1]);
  1395. registry.release(entities[2]);
  1396. entt::registry other;
  1397. const auto *data = registry.data();
  1398. other.assign(data, data + registry.size(), registry.released());
  1399. ASSERT_EQ(registry.size(), other.size());
  1400. ASSERT_TRUE(other.valid(entities[0]));
  1401. ASSERT_FALSE(other.valid(entities[1]));
  1402. ASSERT_FALSE(other.valid(entities[2]));
  1403. ASSERT_EQ(registry.create(), other.create());
  1404. ASSERT_EQ(traits_type::to_entity(other.create()), traits_type::to_integral(entities[1]));
  1405. }
  1406. TEST(Registry, ScramblingPoolsIsAllowed) {
  1407. entt::registry registry;
  1408. registry.on_destroy<int>().connect<&listener::sort<int>>();
  1409. for(std::size_t i{}; i < 2u; ++i) {
  1410. const auto entity = registry.create();
  1411. registry.emplace<int>(entity, static_cast<int>(i));
  1412. }
  1413. registry.destroy(registry.view<int>().back());
  1414. // thanks to @andranik3949 for pointing out this missing test
  1415. registry.view<const int>().each([](const auto entity, const auto &value) {
  1416. ASSERT_EQ(entt::to_integral(entity), value);
  1417. });
  1418. }
  1419. TEST(Registry, RuntimePools) {
  1420. using namespace entt::literals;
  1421. entt::registry registry;
  1422. auto &storage = registry.storage<empty_type>("other"_hs);
  1423. const auto entity = registry.create();
  1424. static_assert(std::is_same_v<decltype(registry.storage<empty_type>()), entt::storage_type_t<empty_type> &>);
  1425. static_assert(std::is_same_v<decltype(std::as_const(registry).storage<empty_type>()), const entt::storage_type_t<empty_type> &>);
  1426. static_assert(std::is_same_v<decltype(registry.storage("other"_hs)->second), entt::storage_type_t<empty_type>::base_type &>);
  1427. static_assert(std::is_same_v<decltype(std::as_const(registry).storage("other"_hs)->second), const entt::storage_type_t<empty_type>::base_type &>);
  1428. ASSERT_NE(registry.storage("other"_hs), registry.storage().end());
  1429. ASSERT_EQ(std::as_const(registry).storage("rehto"_hs), registry.storage().end());
  1430. ASSERT_EQ(&registry.storage<empty_type>("other"_hs), &storage);
  1431. ASSERT_NE(&std::as_const(registry).storage<empty_type>(), &storage);
  1432. ASSERT_FALSE(registry.any_of<empty_type>(entity));
  1433. ASSERT_FALSE(storage.contains(entity));
  1434. registry.emplace<empty_type>(entity);
  1435. ASSERT_FALSE(storage.contains(entity));
  1436. ASSERT_TRUE(registry.any_of<empty_type>(entity));
  1437. ASSERT_EQ((entt::basic_view{registry.storage<empty_type>(), storage}.size_hint()), 0u);
  1438. storage.emplace(entity);
  1439. ASSERT_TRUE(storage.contains(entity));
  1440. ASSERT_TRUE(registry.any_of<empty_type>(entity));
  1441. ASSERT_EQ((entt::basic_view{registry.storage<empty_type>(), storage}.size_hint()), 1u);
  1442. registry.destroy(entity);
  1443. ASSERT_EQ(registry.create(entity), entity);
  1444. ASSERT_FALSE(storage.contains(entity));
  1445. ASSERT_FALSE(registry.any_of<empty_type>(entity));
  1446. }
  1447. ENTT_DEBUG_TEST(RegistryDeathTest, RuntimePools) {
  1448. using namespace entt::literals;
  1449. entt::registry registry;
  1450. registry.storage<empty_type>("other"_hs);
  1451. ASSERT_DEATH(registry.storage<int>("other"_hs), "");
  1452. ASSERT_DEATH(std::as_const(registry).storage<int>("other"_hs), "");
  1453. }
  1454. TEST(Registry, Storage) {
  1455. using namespace entt::literals;
  1456. entt::registry registry;
  1457. const auto entity = registry.create();
  1458. auto &storage = registry.storage<int>("int"_hs);
  1459. storage.emplace(entity);
  1460. for(auto [id, pool]: registry.storage()) {
  1461. static_assert(std::is_same_v<decltype(pool), entt::sparse_set &>);
  1462. static_assert(std::is_same_v<decltype(id), entt::id_type>);
  1463. ASSERT_TRUE(pool.contains(entity));
  1464. ASSERT_EQ(std::addressof(storage), std::addressof(pool));
  1465. ASSERT_EQ(id, "int"_hs);
  1466. }
  1467. for(auto &&curr: std::as_const(registry).storage()) {
  1468. static_assert(std::is_same_v<decltype(curr.second), const entt::sparse_set &>);
  1469. static_assert(std::is_same_v<decltype(curr.first), entt::id_type>);
  1470. ASSERT_TRUE(curr.second.contains(entity));
  1471. ASSERT_EQ(std::addressof(storage), std::addressof(curr.second));
  1472. ASSERT_EQ(curr.first, "int"_hs);
  1473. }
  1474. }
  1475. TEST(Registry, RegistryStorageIterator) {
  1476. entt::registry registry;
  1477. const auto entity = registry.create();
  1478. registry.emplace<int>(entity);
  1479. auto test = [entity](auto iterable) {
  1480. auto end{iterable.begin()};
  1481. decltype(end) begin{};
  1482. begin = iterable.end();
  1483. std::swap(begin, end);
  1484. ASSERT_EQ(begin, iterable.cbegin());
  1485. ASSERT_EQ(end, iterable.cend());
  1486. ASSERT_NE(begin, end);
  1487. ASSERT_EQ(begin++, iterable.begin());
  1488. ASSERT_EQ(begin--, iterable.end());
  1489. ASSERT_EQ(begin + 1, iterable.end());
  1490. ASSERT_EQ(end - 1, iterable.begin());
  1491. ASSERT_EQ(++begin, iterable.end());
  1492. ASSERT_EQ(--begin, iterable.begin());
  1493. ASSERT_EQ(begin += 1, iterable.end());
  1494. ASSERT_EQ(begin -= 1, iterable.begin());
  1495. ASSERT_EQ(begin + (end - begin), iterable.end());
  1496. ASSERT_EQ(begin - (begin - end), iterable.end());
  1497. ASSERT_EQ(end - (end - begin), iterable.begin());
  1498. ASSERT_EQ(end + (begin - end), iterable.begin());
  1499. ASSERT_EQ(begin[0u].first, iterable.begin()->first);
  1500. ASSERT_EQ(std::addressof(begin[0u].second), std::addressof((*iterable.begin()).second));
  1501. ASSERT_LT(begin, end);
  1502. ASSERT_LE(begin, iterable.begin());
  1503. ASSERT_GT(end, begin);
  1504. ASSERT_GE(end, iterable.end());
  1505. ASSERT_EQ(begin[0u].first, entt::type_id<int>().hash());
  1506. ASSERT_TRUE(begin[0u].second.contains(entity));
  1507. };
  1508. test(registry.storage());
  1509. test(std::as_const(registry).storage());
  1510. decltype(std::as_const(registry).storage().begin()) cit = registry.storage().begin();
  1511. ASSERT_EQ(cit, registry.storage().begin());
  1512. ASSERT_NE(cit, std::as_const(registry).storage().end());
  1513. }
  1514. TEST(Registry, RegistryStorageIteratorConversion) {
  1515. entt::registry registry;
  1516. const auto entity = registry.create();
  1517. registry.emplace<int>(entity);
  1518. auto proxy = registry.storage();
  1519. auto cproxy = std::as_const(registry).storage();
  1520. typename decltype(proxy)::iterator it = proxy.begin();
  1521. typename decltype(cproxy)::iterator cit = it;
  1522. static_assert(std::is_same_v<decltype(*it), std::pair<entt::id_type, entt::sparse_set &>>);
  1523. static_assert(std::is_same_v<decltype(*cit), std::pair<entt::id_type, const entt::sparse_set &>>);
  1524. ASSERT_EQ(it->first, entt::type_id<int>().hash());
  1525. ASSERT_EQ((*it).second.type(), entt::type_id<int>());
  1526. ASSERT_EQ(it->first, cit->first);
  1527. ASSERT_EQ((*it).second.type(), (*cit).second.type());
  1528. ASSERT_EQ(it - cit, 0);
  1529. ASSERT_EQ(cit - it, 0);
  1530. ASSERT_LE(it, cit);
  1531. ASSERT_LE(cit, it);
  1532. ASSERT_GE(it, cit);
  1533. ASSERT_GE(cit, it);
  1534. ASSERT_EQ(it, cit);
  1535. ASSERT_NE(++cit, it);
  1536. }
  1537. TEST(Registry, NoEtoType) {
  1538. entt::registry registry;
  1539. const auto entity = registry.create();
  1540. registry.emplace<no_eto_type>(entity);
  1541. registry.emplace<int>(entity, 42);
  1542. ASSERT_NE(registry.storage<no_eto_type>().raw(), nullptr);
  1543. ASSERT_NE(registry.try_get<no_eto_type>(entity), nullptr);
  1544. ASSERT_EQ(registry.view<no_eto_type>().get(entity), std::as_const(registry).view<const no_eto_type>().get(entity));
  1545. auto view = registry.view<no_eto_type, int>();
  1546. auto cview = std::as_const(registry).view<const no_eto_type, const int>();
  1547. ASSERT_EQ((std::get<0>(view.get<no_eto_type, int>(entity))), (std::get<0>(cview.get<const no_eto_type, const int>(entity))));
  1548. }