view.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988
  1. #include <utility>
  2. #include <iterator>
  3. #include <gtest/gtest.h>
  4. #include <entt/entity/registry.hpp>
  5. #include <entt/entity/view.hpp>
  6. TEST(PersistentView, Functionalities) {
  7. entt::registry<> registry;
  8. auto view = registry.persistent_view<int, char>();
  9. auto cview = std::as_const(registry).persistent_view<const int, const char>();
  10. ASSERT_TRUE(view.empty());
  11. const auto e0 = registry.create();
  12. registry.assign<char>(e0);
  13. const auto e1 = registry.create();
  14. registry.assign<int>(e1);
  15. registry.assign<char>(e1);
  16. ASSERT_FALSE(view.empty());
  17. ASSERT_NO_THROW((view.begin()++));
  18. ASSERT_NO_THROW((++cview.begin()));
  19. ASSERT_NE(view.begin(), view.end());
  20. ASSERT_NE(cview.begin(), cview.end());
  21. ASSERT_EQ(view.size(), typename decltype(view)::size_type{1});
  22. registry.assign<int>(e0);
  23. ASSERT_EQ(view.size(), typename decltype(view)::size_type{2});
  24. registry.remove<int>(e0);
  25. ASSERT_EQ(view.size(), typename decltype(view)::size_type{1});
  26. registry.get<char>(e0) = '1';
  27. registry.get<char>(e1) = '2';
  28. registry.get<int>(e1) = 42;
  29. for(auto entity: view) {
  30. ASSERT_EQ(std::get<0>(cview.get<const int, const char>(entity)), 42);
  31. ASSERT_EQ(std::get<1>(view.get<int, char>(entity)), '2');
  32. ASSERT_EQ(cview.get<const char>(entity), '2');
  33. }
  34. ASSERT_EQ(*(view.data() + 0), e1);
  35. registry.remove<char>(e0);
  36. registry.remove<char>(e1);
  37. ASSERT_EQ(view.begin(), view.end());
  38. ASSERT_EQ(cview.begin(), cview.end());
  39. ASSERT_TRUE(view.empty());
  40. }
  41. TEST(PersistentView, ElementAccess) {
  42. entt::registry<> registry;
  43. auto view = registry.persistent_view<int, char>();
  44. auto cview = std::as_const(registry).persistent_view<const int, const char>();
  45. const auto e0 = registry.create();
  46. registry.assign<int>(e0);
  47. registry.assign<char>(e0);
  48. const auto e1 = registry.create();
  49. registry.assign<int>(e1);
  50. registry.assign<char>(e1);
  51. for(typename decltype(view)::size_type i{}; i < view.size(); ++i) {
  52. ASSERT_EQ(view[i], i ? e0 : e1);
  53. ASSERT_EQ(cview[i], i ? e0 : e1);
  54. }
  55. }
  56. TEST(PersistentView, Contains) {
  57. entt::registry<> registry;
  58. auto view = registry.persistent_view<int, char>();
  59. const auto e0 = registry.create();
  60. registry.assign<int>(e0);
  61. registry.assign<char>(e0);
  62. const auto e1 = registry.create();
  63. registry.assign<int>(e1);
  64. registry.assign<char>(e1);
  65. registry.destroy(e0);
  66. ASSERT_FALSE(view.contains(e0));
  67. ASSERT_TRUE(view.contains(e1));
  68. }
  69. TEST(PersistentView, Empty) {
  70. entt::registry<> registry;
  71. const auto e0 = registry.create();
  72. registry.assign<double>(e0);
  73. registry.assign<int>(e0);
  74. registry.assign<float>(e0);
  75. const auto e1 = registry.create();
  76. registry.assign<char>(e1);
  77. registry.assign<float>(e1);
  78. for(auto entity: registry.persistent_view<char, int, float>()) {
  79. (void)entity;
  80. FAIL();
  81. }
  82. for(auto entity: registry.persistent_view<double, char, int, float>()) {
  83. (void)entity;
  84. FAIL();
  85. }
  86. }
  87. TEST(PersistentView, Each) {
  88. entt::registry<> registry;
  89. auto view = registry.persistent_view<int, char>();
  90. const auto e0 = registry.create();
  91. registry.assign<int>(e0);
  92. registry.assign<char>(e0);
  93. const auto e1 = registry.create();
  94. registry.assign<int>(e1);
  95. registry.assign<char>(e1);
  96. auto cview = std::as_const(registry).persistent_view<const int, const char>();
  97. std::size_t cnt = 0;
  98. view.each([&cnt](auto, int &, char &) { ++cnt; });
  99. ASSERT_EQ(cnt, std::size_t{2});
  100. cview.each([&cnt](auto, const int &, const char &) { --cnt; });
  101. ASSERT_EQ(cnt, std::size_t{0});
  102. }
  103. TEST(PersistentView, Sort) {
  104. entt::registry<> registry;
  105. auto view = registry.persistent_view<const int, unsigned int>();
  106. const auto e0 = registry.create();
  107. const auto e1 = registry.create();
  108. const auto e2 = registry.create();
  109. auto uval = 0u;
  110. auto ival = 0;
  111. registry.assign<unsigned int>(e0, uval++);
  112. registry.assign<unsigned int>(e1, uval++);
  113. registry.assign<unsigned int>(e2, uval++);
  114. registry.assign<int>(e0, ival++);
  115. registry.assign<int>(e1, ival++);
  116. registry.assign<int>(e2, ival++);
  117. for(auto entity: view) {
  118. ASSERT_EQ(view.get<unsigned int>(entity), --uval);
  119. ASSERT_EQ(view.get<const int>(entity), --ival);
  120. }
  121. registry.sort<unsigned int>(std::less<unsigned int>{});
  122. view.sort<unsigned int>();
  123. for(auto entity: view) {
  124. ASSERT_EQ(view.get<unsigned int>(entity), uval++);
  125. ASSERT_EQ(view.get<const int>(entity), ival++);
  126. }
  127. }
  128. TEST(PersistentView, Initialize) {
  129. entt::registry<> registry;
  130. registry.assign<int>(registry.create());
  131. const auto entity = registry.create();
  132. registry.assign<char>(entity);
  133. registry.assign<int>(entity);
  134. registry.assign<int>(registry.create());
  135. auto view = std::as_const(registry).persistent_view<const int, const char>();
  136. ASSERT_TRUE(view.empty());
  137. ASSERT_EQ(view.size(), typename decltype(view)::size_type{});
  138. for(auto entt: view) {
  139. (void)entt;
  140. FAIL();
  141. }
  142. ASSERT_TRUE(view.empty());
  143. ASSERT_EQ(view.size(), typename decltype(view)::size_type{});
  144. view.initialize();
  145. for(auto entt: view) {
  146. ASSERT_EQ(entity, entt);
  147. }
  148. ASSERT_FALSE(view.empty());
  149. ASSERT_EQ(view.size(), typename decltype(view)::size_type{1});
  150. }
  151. TEST(PersistentView, RebuildOnFirstUse) {
  152. entt::registry<> registry;
  153. registry.assign<int>(registry.create());
  154. const auto entity = registry.create();
  155. registry.assign<char>(entity);
  156. registry.assign<int>(entity);
  157. registry.assign<int>(registry.create());
  158. auto view = registry.persistent_view<int, char>();
  159. ASSERT_TRUE(view.empty());
  160. ASSERT_EQ(view.size(), typename decltype(view)::size_type{});
  161. for(auto entt: view) {
  162. (void)entt;
  163. FAIL();
  164. }
  165. ASSERT_TRUE(view.empty());
  166. ASSERT_EQ(view.size(), typename decltype(view)::size_type{});
  167. view.each([entity](auto entt, auto &&...) {
  168. ASSERT_EQ(entity, entt);
  169. });
  170. ASSERT_FALSE(view.empty());
  171. ASSERT_EQ(view.size(), typename decltype(view)::size_type{1});
  172. }
  173. TEST(PersistentView, RebuildOnFirstUseAfterDirectSort) {
  174. entt::registry<> registry;
  175. auto view = registry.persistent_view<int, char>();
  176. registry.assign<int>(registry.create(), 1);
  177. const auto entity = registry.create();
  178. registry.assign<char>(entity, 'c');
  179. registry.assign<int>(entity, 0);
  180. registry.assign<int>(registry.create(), 2);
  181. ASSERT_FALSE(view.empty());
  182. ASSERT_EQ(view.size(), typename decltype(view)::size_type{1});
  183. registry.sort<int>([](auto lhs, auto rhs) { return lhs < rhs; });
  184. ASSERT_TRUE(view.empty());
  185. ASSERT_EQ(view.size(), typename decltype(view)::size_type{});
  186. view.each([entity](auto entt, auto &&...) {
  187. ASSERT_EQ(entity, entt);
  188. });
  189. ASSERT_FALSE(view.empty());
  190. ASSERT_EQ(view.size(), typename decltype(view)::size_type{1});
  191. }
  192. TEST(PersistentView, RebuildOnFirstUseAfterDependentSort) {
  193. entt::registry<> registry;
  194. auto view = registry.persistent_view<int, char>();
  195. registry.assign<int>(registry.create(), 1);
  196. const auto entity = registry.create();
  197. registry.assign<char>(entity, 'c');
  198. registry.assign<int>(entity, 0);
  199. registry.assign<int>(registry.create(), 2);
  200. ASSERT_FALSE(view.empty());
  201. ASSERT_EQ(view.size(), typename decltype(view)::size_type{1});
  202. registry.sort<int, char>();
  203. ASSERT_TRUE(view.empty());
  204. ASSERT_EQ(view.size(), typename decltype(view)::size_type{});
  205. view.each([entity](auto entt, auto &&...) {
  206. ASSERT_EQ(entity, entt);
  207. });
  208. ASSERT_FALSE(view.empty());
  209. ASSERT_EQ(view.size(), typename decltype(view)::size_type{1});
  210. }
  211. TEST(PersistentView, IndexRebuiltOnDestroy) {
  212. entt::registry<> registry;
  213. auto view = registry.persistent_view<int, unsigned int>();
  214. const auto e0 = registry.create();
  215. const auto e1 = registry.create();
  216. registry.assign<unsigned int>(e0, 0u);
  217. registry.assign<unsigned int>(e1, 1u);
  218. registry.assign<int>(e0, 0);
  219. registry.assign<int>(e1, 1);
  220. registry.destroy(e0);
  221. registry.assign<int>(registry.create(), 42);
  222. ASSERT_EQ(view.size(), typename decltype(view)::size_type{1});
  223. ASSERT_EQ(view[{}], e1);
  224. ASSERT_EQ(view.get<int>(e1), 1);
  225. ASSERT_EQ(view.get<unsigned int>(e1), 1u);
  226. view.each([e1](auto entity, auto ivalue, auto uivalue) {
  227. ASSERT_EQ(entity, e1);
  228. ASSERT_EQ(ivalue, 1);
  229. ASSERT_EQ(uivalue, 1u);
  230. });
  231. }
  232. TEST(PersistentView, ConstNonConstAndAllInBetween) {
  233. entt::registry<> registry;
  234. auto view = registry.persistent_view<int, const char>();
  235. ASSERT_TRUE((std::is_same_v<decltype(view.get<int>(0)), int &>));
  236. ASSERT_TRUE((std::is_same_v<decltype(view.get<const int>(0)), const int &>));
  237. ASSERT_TRUE((std::is_same_v<decltype(view.get<const char>(0)), const char &>));
  238. ASSERT_TRUE((std::is_same_v<decltype(view.get<int, const char>(0)), std::tuple<int &, const char &>>));
  239. ASSERT_TRUE((std::is_same_v<decltype(view.get<const int, const char>(0)), std::tuple<const int &, const char &>>));
  240. view.each([](auto, auto &&i, auto &&c) {
  241. ASSERT_TRUE((std::is_same_v<decltype(i), int &>));
  242. ASSERT_TRUE((std::is_same_v<decltype(c), const char &>));
  243. });
  244. }
  245. TEST(SingleComponentView, Functionalities) {
  246. entt::registry<> registry;
  247. auto view = registry.view<char>();
  248. auto cview = std::as_const(registry).view<const char>();
  249. const auto e0 = registry.create();
  250. const auto e1 = registry.create();
  251. ASSERT_TRUE(view.empty());
  252. registry.assign<int>(e1);
  253. registry.assign<char>(e1);
  254. ASSERT_NO_THROW(registry.view<char>().begin()++);
  255. ASSERT_NO_THROW(++registry.view<char>().begin());
  256. ASSERT_NE(view.begin(), view.end());
  257. ASSERT_NE(cview.begin(), cview.end());
  258. ASSERT_EQ(view.size(), typename decltype(view)::size_type{1});
  259. ASSERT_FALSE(view.empty());
  260. registry.assign<char>(e0);
  261. ASSERT_EQ(view.size(), typename decltype(view)::size_type{2});
  262. view.get(e0) = '1';
  263. view.get(e1) = '2';
  264. for(auto entity: view) {
  265. ASSERT_TRUE(cview.get(entity) == '1' || cview.get(entity) == '2');
  266. }
  267. ASSERT_EQ(*(view.data() + 0), e1);
  268. ASSERT_EQ(*(view.data() + 1), e0);
  269. ASSERT_EQ(*(view.raw() + 0), '2');
  270. ASSERT_EQ(*(static_cast<const decltype(view) &>(view).raw() + 1), '1');
  271. registry.remove<char>(e0);
  272. registry.remove<char>(e1);
  273. ASSERT_EQ(view.begin(), view.end());
  274. ASSERT_TRUE(view.empty());
  275. }
  276. TEST(SingleComponentView, ElementAccess) {
  277. entt::registry<> registry;
  278. auto view = registry.view<int>();
  279. auto cview = std::as_const(registry).view<const int>();
  280. const auto e0 = registry.create();
  281. registry.assign<int>(e0);
  282. const auto e1 = registry.create();
  283. registry.assign<int>(e1);
  284. for(typename decltype(view)::size_type i{}; i < view.size(); ++i) {
  285. ASSERT_EQ(view[i], i ? e0 : e1);
  286. ASSERT_EQ(cview[i], i ? e0 : e1);
  287. }
  288. }
  289. TEST(SingleComponentView, Contains) {
  290. entt::registry<> registry;
  291. const auto e0 = registry.create();
  292. registry.assign<int>(e0);
  293. const auto e1 = registry.create();
  294. registry.assign<int>(e1);
  295. registry.destroy(e0);
  296. auto view = registry.view<int>();
  297. ASSERT_FALSE(view.contains(e0));
  298. ASSERT_TRUE(view.contains(e1));
  299. }
  300. TEST(SingleComponentView, Empty) {
  301. entt::registry<> registry;
  302. const auto e0 = registry.create();
  303. registry.assign<char>(e0);
  304. registry.assign<double>(e0);
  305. const auto e1 = registry.create();
  306. registry.assign<char>(e1);
  307. auto view = registry.view<int>();
  308. ASSERT_EQ(view.size(), entt::registry<>::size_type{0});
  309. for(auto entity: view) {
  310. (void)entity;
  311. FAIL();
  312. }
  313. }
  314. TEST(SingleComponentView, Each) {
  315. entt::registry<> registry;
  316. registry.assign<int>(registry.create());
  317. registry.assign<int>(registry.create());
  318. auto view = registry.view<int>();
  319. const auto &cview = static_cast<const decltype(view) &>(view);
  320. std::size_t cnt = 0;
  321. view.each([&cnt](auto, int &) { ++cnt; });
  322. ASSERT_EQ(cnt, std::size_t{2});
  323. cview.each([&cnt](auto, const int &) { --cnt; });
  324. ASSERT_EQ(cnt, std::size_t{0});
  325. }
  326. TEST(SingleComponentView, ConstNonConstAndAllInBetween) {
  327. entt::registry<> registry;
  328. auto view = registry.view<int>();
  329. auto cview = registry.view<const int>();
  330. ASSERT_TRUE((std::is_same_v<typename decltype(view)::raw_type, int>));
  331. ASSERT_TRUE((std::is_same_v<typename decltype(cview)::raw_type, const int>));
  332. ASSERT_TRUE((std::is_same_v<decltype(view.get(0)), int &>));
  333. ASSERT_TRUE((std::is_same_v<decltype(view.raw()), int *>));
  334. ASSERT_TRUE((std::is_same_v<decltype(cview.get(0)), const int &>));
  335. ASSERT_TRUE((std::is_same_v<decltype(cview.raw()), const int *>));
  336. view.each([](auto, auto &&i) {
  337. ASSERT_TRUE((std::is_same_v<decltype(i), int &>));
  338. });
  339. cview.each([](auto, auto &&i) {
  340. ASSERT_TRUE((std::is_same_v<decltype(i), const int &>));
  341. });
  342. }
  343. TEST(MultipleComponentView, Functionalities) {
  344. entt::registry<> registry;
  345. auto view = registry.view<int, char>();
  346. auto cview = std::as_const(registry).view<const int, const char>();
  347. ASSERT_TRUE(view.empty());
  348. const auto e0 = registry.create();
  349. registry.assign<char>(e0);
  350. const auto e1 = registry.create();
  351. registry.assign<int>(e1);
  352. ASSERT_FALSE(view.empty());
  353. registry.assign<char>(e1);
  354. auto it = registry.view<int, char>().begin();
  355. ASSERT_EQ(*it, e1);
  356. ASSERT_EQ(++it, (registry.view<int, char>().end()));
  357. ASSERT_NO_THROW((registry.view<int, char>().begin()++));
  358. ASSERT_NO_THROW((++registry.view<int, char>().begin()));
  359. ASSERT_NE(view.begin(), view.end());
  360. ASSERT_NE(cview.begin(), cview.end());
  361. ASSERT_EQ(view.size(), decltype(view.size()){1});
  362. registry.get<char>(e0) = '1';
  363. registry.get<char>(e1) = '2';
  364. registry.get<int>(e1) = 42;
  365. for(auto entity: view) {
  366. ASSERT_EQ(std::get<0>(cview.get<const int, const char>(entity)), 42);
  367. ASSERT_EQ(std::get<1>(view.get<int, char>(entity)), '2');
  368. ASSERT_EQ(cview.get<const char>(entity), '2');
  369. }
  370. }
  371. TEST(MultipleComponentView, Iterator) {
  372. entt::registry<> registry;
  373. const auto entity = registry.create();
  374. registry.assign<int>(entity);
  375. registry.assign<char>(entity);
  376. const auto view = registry.view<int, char>();
  377. using iterator_type = typename decltype(view)::iterator_type;
  378. iterator_type end{view.begin()};
  379. iterator_type begin{};
  380. begin = view.end();
  381. std::swap(begin, end);
  382. ASSERT_EQ(begin, view.begin());
  383. ASSERT_EQ(end, view.end());
  384. ASSERT_NE(begin, end);
  385. ASSERT_EQ(view.begin()++, view.begin());
  386. ASSERT_EQ(++view.begin(), view.end());
  387. }
  388. TEST(MultipleComponentView, Contains) {
  389. entt::registry<> registry;
  390. const auto e0 = registry.create();
  391. registry.assign<int>(e0);
  392. registry.assign<char>(e0);
  393. const auto e1 = registry.create();
  394. registry.assign<int>(e1);
  395. registry.assign<char>(e1);
  396. registry.destroy(e0);
  397. auto view = registry.view<int, char>();
  398. ASSERT_FALSE(view.contains(e0));
  399. ASSERT_TRUE(view.contains(e1));
  400. }
  401. TEST(MultipleComponentView, Empty) {
  402. entt::registry<> registry;
  403. const auto e0 = registry.create();
  404. registry.assign<double>(e0);
  405. registry.assign<int>(e0);
  406. registry.assign<float>(e0);
  407. const auto e1 = registry.create();
  408. registry.assign<char>(e1);
  409. registry.assign<float>(e1);
  410. auto view = registry.view<char, int, float>();
  411. for(auto entity: view) {
  412. (void)entity;
  413. FAIL();
  414. }
  415. }
  416. TEST(MultipleComponentView, Each) {
  417. entt::registry<> registry;
  418. const auto e0 = registry.create();
  419. registry.assign<int>(e0);
  420. registry.assign<char>(e0);
  421. const auto e1 = registry.create();
  422. registry.assign<int>(e1);
  423. registry.assign<char>(e1);
  424. auto view = registry.view<int, char>();
  425. auto cview = std::as_const(registry).view<const int, const char>();
  426. std::size_t cnt = 0;
  427. view.each([&cnt](auto, int &, char &) { ++cnt; });
  428. ASSERT_EQ(cnt, std::size_t{2});
  429. cview.each([&cnt](auto, const int &, const char &) { --cnt; });
  430. ASSERT_EQ(cnt, std::size_t{0});
  431. }
  432. TEST(MultipleComponentView, EachWithHoles) {
  433. entt::registry<> registry;
  434. const auto e0 = registry.create();
  435. const auto e1 = registry.create();
  436. const auto e2 = registry.create();
  437. registry.assign<char>(e0, '0');
  438. registry.assign<char>(e1, '1');
  439. registry.assign<int>(e0, 0);
  440. registry.assign<int>(e2, 2);
  441. auto view = registry.view<char, int>();
  442. view.each([e0](auto entity, const char &c, const int &i) {
  443. if(e0 == entity) {
  444. ASSERT_EQ(c, '0');
  445. ASSERT_EQ(i, 0);
  446. } else {
  447. FAIL();
  448. }
  449. });
  450. }
  451. TEST(MultipleComponentView, ConstNonConstAndAllInBetween) {
  452. entt::registry<> registry;
  453. auto view = registry.view<int, const char>();
  454. ASSERT_TRUE((std::is_same_v<decltype(view.get<int>(0)), int &>));
  455. ASSERT_TRUE((std::is_same_v<decltype(view.get<const int>(0)), const int &>));
  456. ASSERT_TRUE((std::is_same_v<decltype(view.get<const char>(0)), const char &>));
  457. ASSERT_TRUE((std::is_same_v<decltype(view.get<int, const char>(0)), std::tuple<int &, const char &>>));
  458. ASSERT_TRUE((std::is_same_v<decltype(view.get<const int, const char>(0)), std::tuple<const int &, const char &>>));
  459. view.each([](auto, auto &&i, auto &&c) {
  460. ASSERT_TRUE((std::is_same_v<decltype(i), int &>));
  461. ASSERT_TRUE((std::is_same_v<decltype(c), const char &>));
  462. });
  463. }
  464. TEST(RawView, Functionalities) {
  465. entt::registry<> registry;
  466. auto view = registry.raw_view<char>();
  467. auto cview = std::as_const(registry).raw_view<const char>();
  468. ASSERT_TRUE(view.empty());
  469. const auto e0 = registry.create();
  470. const auto e1 = registry.create();
  471. registry.assign<int>(e1);
  472. registry.assign<char>(e1);
  473. ASSERT_FALSE(view.empty());
  474. ASSERT_NO_THROW(view.begin()++);
  475. ASSERT_NO_THROW(++cview.begin());
  476. ASSERT_NE(view.begin(), view.end());
  477. ASSERT_NE(cview.begin(), cview.end());
  478. ASSERT_EQ(view.size(), typename decltype(view)::size_type{1});
  479. registry.assign<char>(e0);
  480. ASSERT_EQ(view.size(), typename decltype(view)::size_type{2});
  481. registry.get<char>(e0) = '1';
  482. registry.get<char>(e1) = '2';
  483. for(auto &&component: view) {
  484. ASSERT_TRUE(component == '1' || component == '2');
  485. }
  486. ASSERT_EQ(*(view.data() + 0), e1);
  487. ASSERT_EQ(*(view.data() + 1), e0);
  488. ASSERT_EQ(*(view.raw() + 0), '2');
  489. ASSERT_EQ(*(cview.raw() + 1), '1');
  490. for(auto &&component: view) {
  491. // verifies that iterators return references to components
  492. component = '0';
  493. }
  494. for(auto &&component: cview) {
  495. ASSERT_TRUE(component == '0');
  496. }
  497. registry.remove<char>(e0);
  498. registry.remove<char>(e1);
  499. ASSERT_EQ(view.begin(), view.end());
  500. ASSERT_TRUE(view.empty());
  501. }
  502. TEST(RawView, ElementAccess) {
  503. entt::registry<> registry;
  504. auto view = registry.raw_view<int>();
  505. auto cview = std::as_const(registry).raw_view<const int>();
  506. const auto e0 = registry.create();
  507. registry.assign<int>(e0, 42);
  508. const auto e1 = registry.create();
  509. registry.assign<int>(e1, 3);
  510. for(typename decltype(view)::size_type i{}; i < view.size(); ++i) {
  511. ASSERT_EQ(view[i], i ? 42 : 3);
  512. ASSERT_EQ(cview[i], i ? 42 : 3);
  513. }
  514. }
  515. TEST(RawView, Empty) {
  516. entt::registry<> registry;
  517. const auto e0 = registry.create();
  518. registry.assign<char>(e0);
  519. registry.assign<double>(e0);
  520. const auto e1 = registry.create();
  521. registry.assign<char>(e1);
  522. auto view = registry.raw_view<int>();
  523. ASSERT_EQ(view.size(), entt::registry<>::size_type{0});
  524. for(auto &&component: view) {
  525. (void)component;
  526. FAIL();
  527. }
  528. }
  529. TEST(RawView, Each) {
  530. entt::registry<> registry;
  531. registry.assign<int>(registry.create(), 1);
  532. registry.assign<int>(registry.create(), 3);
  533. auto view = registry.raw_view<int>();
  534. auto cview = std::as_const(registry).raw_view<const int>();
  535. std::size_t cnt = 0;
  536. view.each([&cnt](int &v) { cnt += (v % 2); });
  537. ASSERT_EQ(cnt, std::size_t{2});
  538. cview.each([&cnt](const int &v) { cnt -= (v % 2); });
  539. ASSERT_EQ(cnt, std::size_t{0});
  540. }
  541. TEST(RawView, ConstNonConstAndAllInBetween) {
  542. entt::registry<> registry;
  543. auto view = registry.raw_view<int>();
  544. auto cview = registry.raw_view<const int>();
  545. ASSERT_TRUE((std::is_same_v<typename decltype(view)::raw_type, int>));
  546. ASSERT_TRUE((std::is_same_v<typename decltype(cview)::raw_type, const int>));
  547. ASSERT_TRUE((std::is_same_v<decltype(view[0]), int &>));
  548. ASSERT_TRUE((std::is_same_v<decltype(view.raw()), int *>));
  549. ASSERT_TRUE((std::is_same_v<decltype(cview[0]), const int &>));
  550. ASSERT_TRUE((std::is_same_v<decltype(cview.raw()), const int *>));
  551. view.each([](auto &&i) {
  552. ASSERT_TRUE((std::is_same_v<decltype(i), int &>));
  553. });
  554. cview.each([](auto &&i) {
  555. ASSERT_TRUE((std::is_same_v<decltype(i), const int &>));
  556. });
  557. for(auto &&i: view) {
  558. ASSERT_TRUE((std::is_same_v<decltype(i), int &>));
  559. }
  560. for(auto &&i: cview) {
  561. ASSERT_TRUE((std::is_same_v<decltype(i), const int &>));
  562. }
  563. }
  564. TEST(RuntimeView, Functionalities) {
  565. entt::registry<> registry;
  566. using component_type = typename decltype(registry)::component_type;
  567. // forces the creation of the pools
  568. registry.reserve<int>(0);
  569. registry.reserve<char>(0);
  570. component_type types[] = { registry.type<int>(), registry.type<char>() };
  571. auto view = registry.runtime_view(std::begin(types), std::end(types));
  572. ASSERT_TRUE(view.empty());
  573. const auto e0 = registry.create();
  574. registry.assign<char>(e0);
  575. const auto e1 = registry.create();
  576. registry.assign<int>(e1);
  577. ASSERT_FALSE(view.empty());
  578. registry.assign<char>(e1);
  579. auto it = registry.runtime_view(std::begin(types), std::end(types)).begin();
  580. ASSERT_EQ(*it, e1);
  581. ASSERT_EQ(++it, (registry.runtime_view(std::begin(types), std::end(types)).end()));
  582. ASSERT_NO_THROW((registry.runtime_view(std::begin(types), std::end(types)).begin()++));
  583. ASSERT_NO_THROW((++registry.runtime_view(std::begin(types), std::end(types)).begin()));
  584. ASSERT_NE(view.begin(), view.end());
  585. ASSERT_EQ(view.size(), decltype(view.size()){1});
  586. registry.get<char>(e0) = '1';
  587. registry.get<char>(e1) = '2';
  588. registry.get<int>(e1) = 42;
  589. for(auto entity: view) {
  590. ASSERT_EQ(registry.get<int>(entity), 42);
  591. ASSERT_EQ(registry.get<char>(entity), '2');
  592. }
  593. }
  594. TEST(RuntimeView, Iterator) {
  595. entt::registry<> registry;
  596. using component_type = typename decltype(registry)::component_type;
  597. const auto entity = registry.create();
  598. registry.assign<int>(entity);
  599. registry.assign<char>(entity);
  600. component_type types[] = { registry.type<int>(), registry.type<char>() };
  601. auto view = registry.runtime_view(std::begin(types), std::end(types));
  602. using iterator_type = typename decltype(view)::iterator_type;
  603. iterator_type end{view.begin()};
  604. iterator_type begin{};
  605. begin = view.end();
  606. std::swap(begin, end);
  607. ASSERT_EQ(begin, view.begin());
  608. ASSERT_EQ(end, view.end());
  609. ASSERT_NE(begin, end);
  610. ASSERT_EQ(view.begin()++, view.begin());
  611. ASSERT_EQ(++view.begin(), view.end());
  612. }
  613. TEST(RuntimeView, Contains) {
  614. entt::registry<> registry;
  615. using component_type = typename decltype(registry)::component_type;
  616. const auto e0 = registry.create();
  617. registry.assign<int>(e0);
  618. registry.assign<char>(e0);
  619. const auto e1 = registry.create();
  620. registry.assign<int>(e1);
  621. registry.assign<char>(e1);
  622. registry.destroy(e0);
  623. component_type types[] = { registry.type<int>(), registry.type<char>() };
  624. auto view = registry.runtime_view(std::begin(types), std::end(types));
  625. ASSERT_FALSE(view.contains(e0));
  626. ASSERT_TRUE(view.contains(e1));
  627. }
  628. TEST(RuntimeView, Empty) {
  629. entt::registry<> registry;
  630. using component_type = typename decltype(registry)::component_type;
  631. const auto e0 = registry.create();
  632. registry.assign<double>(e0);
  633. registry.assign<int>(e0);
  634. registry.assign<float>(e0);
  635. const auto e1 = registry.create();
  636. registry.assign<char>(e1);
  637. registry.assign<float>(e1);
  638. component_type types[] = { registry.type<char>(), registry.type<int>(), registry.type<float>() };
  639. auto view = registry.runtime_view(std::begin(types), std::end(types));
  640. for(auto entity: view) {
  641. (void)entity;
  642. FAIL();
  643. }
  644. }
  645. TEST(RuntimeView, Each) {
  646. entt::registry<> registry;
  647. using component_type = typename decltype(registry)::component_type;
  648. const auto e0 = registry.create();
  649. registry.assign<int>(e0);
  650. registry.assign<char>(e0);
  651. const auto e1 = registry.create();
  652. registry.assign<int>(e1);
  653. registry.assign<char>(e1);
  654. component_type types[] = { registry.type<int>(), registry.type<char>() };
  655. auto view = registry.runtime_view(std::begin(types), std::end(types));
  656. std::size_t cnt = 0;
  657. view.each([&cnt](auto) { ++cnt; });
  658. ASSERT_EQ(cnt, std::size_t{2});
  659. }
  660. TEST(RuntimeView, EachWithHoles) {
  661. entt::registry<> registry;
  662. using component_type = typename decltype(registry)::component_type;
  663. const auto e0 = registry.create();
  664. const auto e1 = registry.create();
  665. const auto e2 = registry.create();
  666. registry.assign<char>(e0, '0');
  667. registry.assign<char>(e1, '1');
  668. registry.assign<int>(e0, 0);
  669. registry.assign<int>(e2, 2);
  670. component_type types[] = { registry.type<int>(), registry.type<char>() };
  671. auto view = registry.runtime_view(std::begin(types), std::end(types));
  672. view.each([e0](auto entity) {
  673. ASSERT_EQ(e0, entity);
  674. });
  675. }
  676. TEST(RuntimeView, MissingPool) {
  677. entt::registry<> registry;
  678. using component_type = typename decltype(registry)::component_type;
  679. const auto e0 = registry.create();
  680. registry.assign<int>(e0);
  681. component_type types[] = { registry.type<int>(), registry.type<char>() };
  682. auto view = registry.runtime_view(std::begin(types), std::end(types));
  683. ASSERT_TRUE(view.empty());
  684. ASSERT_EQ(view.size(), decltype(view.size()){0});
  685. registry.assign<char>(e0);
  686. ASSERT_TRUE(view.empty());
  687. ASSERT_EQ(view.size(), decltype(view.size()){0});
  688. ASSERT_FALSE(view.contains(e0));
  689. view.each([](auto) { FAIL(); });
  690. for(auto entity: view) {
  691. (void)entity;
  692. FAIL();
  693. }
  694. }
  695. TEST(RuntimeView, EmptyRange) {
  696. entt::registry<> registry;
  697. using component_type = typename decltype(registry)::component_type;
  698. const auto e0 = registry.create();
  699. registry.assign<int>(e0);
  700. const component_type *ptr = nullptr;
  701. auto view = registry.runtime_view(ptr, ptr);
  702. ASSERT_TRUE(view.empty());
  703. ASSERT_EQ(view.size(), decltype(view.size()){0});
  704. ASSERT_FALSE(view.contains(e0));
  705. view.each([](auto) { FAIL(); });
  706. for(auto entity: view) {
  707. (void)entity;
  708. FAIL();
  709. }
  710. }