registry.cpp 43 KB

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