view.cpp 29 KB

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