view.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937
  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_THROW(view.begin()++);
  18. ASSERT_NO_THROW(++cview.begin());
  19. ASSERT_NO_THROW([](auto it) { return it++; }(view.rbegin()));
  20. ASSERT_NO_THROW([](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. }
  149. TEST(SingleComponentView, ConstNonConstAndAllInBetween) {
  150. entt::registry registry;
  151. auto view = registry.view<int>();
  152. auto cview = std::as_const(registry).view<const int>();
  153. ASSERT_EQ(view.size(), 0u);
  154. ASSERT_EQ(cview.size(), 0u);
  155. registry.emplace<int>(registry.create(), 0);
  156. ASSERT_EQ(view.size(), 1u);
  157. ASSERT_EQ(cview.size(), 1u);
  158. static_assert(std::is_same_v<typename decltype(view)::raw_type, int>);
  159. static_assert(std::is_same_v<typename decltype(cview)::raw_type, const int>);
  160. static_assert(std::is_same_v<decltype(view.get<int>({})), int &>);
  161. static_assert(std::is_same_v<decltype(view.get({})), std::tuple<int &>>);
  162. static_assert(std::is_same_v<decltype(view.raw()), int *>);
  163. static_assert(std::is_same_v<decltype(cview.get<const int>({})), const int &>);
  164. static_assert(std::is_same_v<decltype(cview.get({})), std::tuple<const int &>>);
  165. static_assert(std::is_same_v<decltype(cview.raw()), const int *>);
  166. view.each([](auto &&i) {
  167. static_assert(std::is_same_v<decltype(i), int &>);
  168. });
  169. cview.each([](auto &&i) {
  170. static_assert(std::is_same_v<decltype(i), const int &>);
  171. });
  172. for(auto [entt, iv]: view.each()) {
  173. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  174. static_assert(std::is_same_v<decltype(iv), int &>);
  175. }
  176. for(auto [entt, iv]: cview.each()) {
  177. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  178. static_assert(std::is_same_v<decltype(iv), const int &>);
  179. }
  180. }
  181. TEST(SingleComponentView, ConstNonConstAndAllInBetweenWithEmptyType) {
  182. entt::registry registry;
  183. auto view = registry.view<empty_type>();
  184. auto cview = std::as_const(registry).view<const empty_type>();
  185. ASSERT_EQ(view.size(), 0u);
  186. ASSERT_EQ(cview.size(), 0u);
  187. registry.emplace<empty_type>(registry.create());
  188. ASSERT_EQ(view.size(), 1u);
  189. ASSERT_EQ(cview.size(), 1u);
  190. static_assert(std::is_same_v<typename decltype(view)::raw_type, empty_type>);
  191. static_assert(std::is_same_v<typename decltype(cview)::raw_type, const empty_type>);
  192. static_assert(std::is_same_v<decltype(view.get({})), std::tuple<>>);
  193. static_assert(std::is_same_v<decltype(cview.get({})), std::tuple<>>);
  194. for(auto [entt]: view.each()) {
  195. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  196. }
  197. for(auto [entt]: cview.each()) {
  198. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  199. }
  200. }
  201. TEST(SingleComponentView, Find) {
  202. entt::registry registry;
  203. auto view = registry.view<int>();
  204. const auto e0 = registry.create();
  205. registry.emplace<int>(e0);
  206. const auto e1 = registry.create();
  207. registry.emplace<int>(e1);
  208. const auto e2 = registry.create();
  209. registry.emplace<int>(e2);
  210. const auto e3 = registry.create();
  211. registry.emplace<int>(e3);
  212. registry.remove<int>(e1);
  213. ASSERT_NE(view.find(e0), view.end());
  214. ASSERT_EQ(view.find(e1), view.end());
  215. ASSERT_NE(view.find(e2), view.end());
  216. ASSERT_NE(view.find(e3), view.end());
  217. auto it = view.find(e2);
  218. ASSERT_EQ(*it, e2);
  219. ASSERT_EQ(*(++it), e3);
  220. ASSERT_EQ(*(++it), e0);
  221. ASSERT_EQ(++it, view.end());
  222. ASSERT_EQ(++view.find(e0), view.end());
  223. const auto e4 = registry.create();
  224. registry.destroy(e4);
  225. const auto e5 = registry.create();
  226. registry.emplace<int>(e5);
  227. ASSERT_NE(view.find(e5), view.end());
  228. ASSERT_EQ(view.find(e4), view.end());
  229. }
  230. TEST(SingleComponentView, EmptyTypes) {
  231. entt::registry registry;
  232. auto create = [&](auto... component) {
  233. const auto entt = registry.create();
  234. (registry.emplace<decltype(component)>(entt, component), ...);
  235. return entt;
  236. };
  237. const auto entity = create(0, empty_type{});
  238. create('c');
  239. registry.view<empty_type>().each([entity](const auto entt) {
  240. ASSERT_EQ(entity, entt);
  241. });
  242. registry.view<empty_type>().each([check = true]() mutable {
  243. ASSERT_TRUE(check);
  244. check = false;
  245. });
  246. for(auto [entt]: registry.view<empty_type>().each()) {
  247. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  248. ASSERT_EQ(entity, entt);
  249. }
  250. registry.view<int>().each([entity](const auto entt, int) {
  251. ASSERT_EQ(entity, entt);
  252. });
  253. registry.view<int>().each([check = true](int) mutable {
  254. ASSERT_TRUE(check);
  255. check = false;
  256. });
  257. for(auto [entt, iv]: registry.view<int>().each()) {
  258. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  259. static_assert(std::is_same_v<decltype(iv), int &>);
  260. ASSERT_EQ(entity, entt);
  261. }
  262. }
  263. TEST(SingleComponentView, FrontBack) {
  264. entt::registry registry;
  265. auto view = registry.view<const int>();
  266. ASSERT_EQ(view.front(), static_cast<entt::entity>(entt::null));
  267. ASSERT_EQ(view.back(), static_cast<entt::entity>(entt::null));
  268. const auto e0 = registry.create();
  269. registry.emplace<int>(e0);
  270. const auto e1 = registry.create();
  271. registry.emplace<int>(e1);
  272. ASSERT_EQ(view.front(), e1);
  273. ASSERT_EQ(view.back(), e0);
  274. }
  275. TEST(SingleComponentView, DeductionGuide) {
  276. entt::registry registry;
  277. typename entt::storage_traits<entt::entity, int>::storage_type storage;
  278. static_assert(std::is_same_v<decltype(entt::basic_view{storage}), entt::basic_view<entt::entity, entt::exclude_t<>, int>>);
  279. static_assert(std::is_same_v<decltype(entt::basic_view{std::as_const(storage)}), entt::basic_view<entt::entity, entt::exclude_t<>, const int>>);
  280. }
  281. TEST(MultiComponentView, Functionalities) {
  282. entt::registry registry;
  283. auto view = registry.view<int, char>();
  284. auto cview = std::as_const(registry).view<const int, const char>();
  285. const auto e0 = registry.create();
  286. registry.emplace<char>(e0, '1');
  287. const auto e1 = registry.create();
  288. registry.emplace<int>(e1, 42);
  289. registry.emplace<char>(e1, '2');
  290. ASSERT_EQ(*view.begin(), e1);
  291. ASSERT_EQ(*view.rbegin(), e1);
  292. ASSERT_EQ(++view.begin(), (view.end()));
  293. ASSERT_EQ(++view.rbegin(), (view.rend()));
  294. ASSERT_NO_THROW((view.begin()++));
  295. ASSERT_NO_THROW((++cview.begin()));
  296. ASSERT_NO_THROW(view.rbegin()++);
  297. ASSERT_NO_THROW(++cview.rbegin());
  298. ASSERT_NE(view.begin(), view.end());
  299. ASSERT_NE(cview.begin(), cview.end());
  300. ASSERT_NE(view.rbegin(), view.rend());
  301. ASSERT_NE(cview.rbegin(), cview.rend());
  302. ASSERT_EQ(view.size_hint(), 1u);
  303. for(auto entity: view) {
  304. ASSERT_EQ(std::get<0>(cview.get<const int, const char>(entity)), 42);
  305. ASSERT_EQ(std::get<1>(view.get<int, char>(entity)), '2');
  306. ASSERT_EQ(cview.get<const char>(entity), '2');
  307. }
  308. decltype(view) invalid{};
  309. ASSERT_TRUE(view);
  310. ASSERT_TRUE(cview);
  311. ASSERT_FALSE(invalid);
  312. }
  313. TEST(MultiComponentView, LazyTypesFromConstRegistry) {
  314. entt::registry registry{};
  315. auto view = std::as_const(registry).view<const empty_type, const int>();
  316. const auto entity = registry.create();
  317. registry.emplace<empty_type>(entity);
  318. registry.emplace<int>(entity);
  319. ASSERT_TRUE(view);
  320. ASSERT_EQ(view.size_hint(), 1u);
  321. ASSERT_TRUE(view.contains(entity));
  322. ASSERT_NE(view.begin(), view.end());
  323. ASSERT_NE(view.find(entity), view.end());
  324. ASSERT_EQ(view.front(), entity);
  325. ASSERT_EQ(view.back(), entity);
  326. }
  327. TEST(MultiComponentView, LazyExcludedTypeFromConstRegistry) {
  328. entt::registry registry;
  329. auto entity = registry.create();
  330. registry.emplace<int>(entity);
  331. auto view = std::as_const(registry).view<const int>(entt::exclude<char>);
  332. ASSERT_TRUE(view);
  333. ASSERT_EQ(view.size_hint(), 1u);
  334. ASSERT_TRUE(view.contains(entity));
  335. ASSERT_NE(view.begin(), view.end());
  336. ASSERT_NE(view.find(entity), view.end());
  337. ASSERT_EQ(view.front(), entity);
  338. ASSERT_EQ(view.back(), entity);
  339. }
  340. TEST(MultiComponentView, Iterator) {
  341. entt::registry registry;
  342. const auto entity = registry.create();
  343. registry.emplace<int>(entity);
  344. registry.emplace<char>(entity);
  345. const auto view = registry.view<int, char>();
  346. using iterator = typename decltype(view)::iterator;
  347. iterator end{view.begin()};
  348. iterator begin{};
  349. begin = view.end();
  350. std::swap(begin, end);
  351. ASSERT_EQ(begin, view.begin());
  352. ASSERT_EQ(end, view.end());
  353. ASSERT_NE(begin, end);
  354. ASSERT_EQ(begin++, view.begin());
  355. ASSERT_EQ(begin--, view.end());
  356. ASSERT_EQ(++begin, view.end());
  357. ASSERT_EQ(--begin, view.begin());
  358. ASSERT_EQ(*begin, entity);
  359. ASSERT_EQ(*begin.operator->(), entity);
  360. }
  361. TEST(MultiComponentView, ReverseIterator) {
  362. entt::registry registry;
  363. const auto entity = registry.create();
  364. registry.emplace<int>(entity);
  365. registry.emplace<char>(entity);
  366. const auto view = registry.view<int, char>();
  367. using iterator = typename decltype(view)::reverse_iterator;
  368. iterator end{view.rbegin()};
  369. iterator begin{};
  370. begin = view.rend();
  371. std::swap(begin, end);
  372. ASSERT_EQ(begin, view.rbegin());
  373. ASSERT_EQ(end, view.rend());
  374. ASSERT_NE(begin, end);
  375. ASSERT_EQ(begin++, view.rbegin());
  376. ASSERT_EQ(begin--, view.rend());
  377. ASSERT_EQ(++begin, view.rend());
  378. ASSERT_EQ(--begin, view.rbegin());
  379. ASSERT_EQ(*begin, entity);
  380. ASSERT_EQ(*begin.operator->(), entity);
  381. }
  382. TEST(MultiComponentView, Contains) {
  383. entt::registry registry;
  384. const auto e0 = registry.create();
  385. registry.emplace<int>(e0);
  386. registry.emplace<char>(e0);
  387. const auto e1 = registry.create();
  388. registry.emplace<int>(e1);
  389. registry.emplace<char>(e1);
  390. registry.destroy(e0);
  391. auto view = registry.view<int, char>();
  392. ASSERT_FALSE(view.contains(e0));
  393. ASSERT_TRUE(view.contains(e1));
  394. }
  395. TEST(MultiComponentView, SizeHint) {
  396. entt::registry registry;
  397. const auto e0 = registry.create();
  398. registry.emplace<double>(e0);
  399. registry.emplace<int>(e0);
  400. registry.emplace<float>(e0);
  401. const auto e1 = registry.create();
  402. registry.emplace<char>(e1);
  403. registry.emplace<float>(e1);
  404. auto view = registry.view<char, int, float>();
  405. ASSERT_EQ(view.size_hint(), 1u);
  406. ASSERT_EQ(view.begin(), view.end());
  407. ASSERT_EQ(view.rbegin(), view.rend());
  408. }
  409. TEST(MultiComponentView, Each) {
  410. entt::registry registry;
  411. const auto e0 = registry.create();
  412. registry.emplace<int>(e0, 0);
  413. registry.emplace<char>(e0);
  414. const auto e1 = registry.create();
  415. registry.emplace<int>(e1, 1);
  416. registry.emplace<char>(e1);
  417. auto view = registry.view<int, char>();
  418. auto cview = std::as_const(registry).view<const int, const char>();
  419. std::size_t cnt = 0;
  420. for(auto first = cview.each().rbegin(), last = cview.each().rend(); first != last; ++first) {
  421. static_assert(std::is_same_v<decltype(*first), std::tuple<entt::entity, const int &, const char &>>);
  422. ASSERT_EQ(std::get<1>(*first), cnt++);
  423. }
  424. view.each([&cnt](auto, int &, char &) { ++cnt; });
  425. view.each([&cnt](int &, char &) { ++cnt; });
  426. ASSERT_EQ(cnt, std::size_t{6});
  427. cview.each([&cnt](const int &, const char &) { --cnt; });
  428. cview.each([&cnt](auto, const int &, const char &) { --cnt; });
  429. for(auto [entt, iv, cv]: view.each()) {
  430. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  431. static_assert(std::is_same_v<decltype(iv), int &>);
  432. static_assert(std::is_same_v<decltype(cv), char &>);
  433. ASSERT_EQ(iv, --cnt);
  434. }
  435. ASSERT_EQ(cnt, std::size_t{0});
  436. }
  437. TEST(MultiComponentView, EachWithSuggestedType) {
  438. entt::registry registry;
  439. for(auto i = 0; i < 3; ++i) {
  440. const auto entity = registry.create();
  441. registry.emplace<int>(entity, i);
  442. registry.emplace<char>(entity);
  443. }
  444. // makes char a better candidate during iterations
  445. const auto entity = registry.create();
  446. registry.emplace<int>(entity, 99);
  447. registry.view<int, char>().each<int>([value = 2](const auto curr, const auto) mutable {
  448. ASSERT_EQ(curr, value--);
  449. });
  450. registry.sort<int>([](const auto lhs, const auto rhs) {
  451. return lhs < rhs;
  452. });
  453. registry.view<int, char>().each<int>([value = 0](const auto curr, const auto) mutable {
  454. ASSERT_EQ(curr, value++);
  455. });
  456. registry.sort<int>([](const auto lhs, const auto rhs) {
  457. return lhs > rhs;
  458. });
  459. auto value = registry.view<int, char>().size_hint();
  460. for(auto &&curr: registry.view<int, char>().each()) {
  461. ASSERT_EQ(std::get<1>(curr), static_cast<int>(--value));
  462. }
  463. registry.sort<int>([](const auto lhs, const auto rhs) {
  464. return lhs < rhs;
  465. });
  466. value = {};
  467. for(auto &&curr: registry.view<int, char>().each<int>()) {
  468. ASSERT_EQ(std::get<1>(curr), static_cast<int>(value++));
  469. }
  470. }
  471. TEST(MultiComponentView, EachWithHoles) {
  472. entt::registry registry;
  473. const auto e0 = registry.create();
  474. const auto e1 = registry.create();
  475. const auto e2 = registry.create();
  476. registry.emplace<char>(e0, '0');
  477. registry.emplace<char>(e1, '1');
  478. registry.emplace<int>(e0, 0);
  479. registry.emplace<int>(e2, 2);
  480. auto view = registry.view<char, int>();
  481. view.each([e0](auto entity, const char &c, const int &i) {
  482. ASSERT_EQ(entity, e0);
  483. ASSERT_EQ(c, '0');
  484. ASSERT_EQ(i, 0);
  485. });
  486. for(auto &&curr: view.each()) {
  487. ASSERT_EQ(std::get<0>(curr), e0);
  488. ASSERT_EQ(std::get<1>(curr), '0');
  489. ASSERT_EQ(std::get<2>(curr), 0);
  490. }
  491. }
  492. TEST(MultiComponentView, ConstNonConstAndAllInBetween) {
  493. entt::registry registry;
  494. auto view = registry.view<int, empty_type, const char>();
  495. ASSERT_EQ(view.size_hint(), 0u);
  496. const auto entity = registry.create();
  497. registry.emplace<int>(entity, 0);
  498. registry.emplace<empty_type>(entity);
  499. registry.emplace<char>(entity, 'c');
  500. ASSERT_EQ(view.size_hint(), 1u);
  501. static_assert(std::is_same_v<decltype(view.get<int>({})), int &>);
  502. static_assert(std::is_same_v<decltype(view.get<const char>({})), const char &>);
  503. static_assert(std::is_same_v<decltype(view.get<int, const char>({})), std::tuple<int &, const char &>>);
  504. static_assert(std::is_same_v<decltype(view.get({})), std::tuple<int &, const char &>>);
  505. view.each([](auto &&i, auto &&c) {
  506. static_assert(std::is_same_v<decltype(i), int &>);
  507. static_assert(std::is_same_v<decltype(c), const char &>);
  508. });
  509. for(auto [entt, iv, cv]: view.each()) {
  510. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  511. static_assert(std::is_same_v<decltype(iv), int &>);
  512. static_assert(std::is_same_v<decltype(cv), const char &>);
  513. }
  514. }
  515. TEST(MultiComponentView, Find) {
  516. entt::registry registry;
  517. auto view = registry.view<int, const char>();
  518. const auto e0 = registry.create();
  519. registry.emplace<int>(e0);
  520. registry.emplace<char>(e0);
  521. const auto e1 = registry.create();
  522. registry.emplace<int>(e1);
  523. registry.emplace<char>(e1);
  524. const auto e2 = registry.create();
  525. registry.emplace<int>(e2);
  526. registry.emplace<char>(e2);
  527. const auto e3 = registry.create();
  528. registry.emplace<int>(e3);
  529. registry.emplace<char>(e3);
  530. registry.remove<int>(e1);
  531. ASSERT_NE(view.find(e0), view.end());
  532. ASSERT_EQ(view.find(e1), view.end());
  533. ASSERT_NE(view.find(e2), view.end());
  534. ASSERT_NE(view.find(e3), view.end());
  535. auto it = view.find(e2);
  536. ASSERT_EQ(*it, e2);
  537. ASSERT_EQ(*(++it), e3);
  538. ASSERT_EQ(*(++it), e0);
  539. ASSERT_EQ(++it, view.end());
  540. ASSERT_EQ(++view.find(e0), view.end());
  541. const auto e4 = registry.create();
  542. registry.destroy(e4);
  543. const auto e5 = registry.create();
  544. registry.emplace<int>(e5);
  545. registry.emplace<char>(e5);
  546. ASSERT_NE(view.find(e5), view.end());
  547. ASSERT_EQ(view.find(e4), view.end());
  548. }
  549. TEST(MultiComponentView, ExcludedComponents) {
  550. entt::registry registry;
  551. const auto e0 = registry.create();
  552. registry.emplace<int>(e0, 0);
  553. const auto e1 = registry.create();
  554. registry.emplace<int>(e1, 1);
  555. registry.emplace<char>(e1);
  556. const auto e2 = registry.create();
  557. registry.emplace<int>(e2, 2);
  558. const auto e3 = registry.create();
  559. registry.emplace<int>(e3, 3);
  560. registry.emplace<char>(e3);
  561. const auto view = std::as_const(registry).view<const int>(entt::exclude<char>);
  562. for(const auto entity: view) {
  563. ASSERT_TRUE(entity == e0 || entity == e2);
  564. if(entity == e0) {
  565. ASSERT_EQ(view.get<const int>(e0), 0);
  566. } else if(entity == e2) {
  567. ASSERT_EQ(std::get<0>(view.get(e2)), 2);
  568. }
  569. }
  570. registry.emplace<char>(e0);
  571. registry.emplace<char>(e2);
  572. registry.remove<char>(e1);
  573. registry.remove<char>(e3);
  574. for(const auto entity: view) {
  575. ASSERT_TRUE(entity == e1 || entity == e3);
  576. if(entity == e1) {
  577. ASSERT_EQ(std::get<0>(view.get(e1)), 1);
  578. } else if(entity == e3) {
  579. ASSERT_EQ(view.get<const int>(e3), 3);
  580. }
  581. }
  582. }
  583. TEST(MultiComponentView, EmptyTypes) {
  584. entt::registry registry;
  585. const auto entity = registry.create();
  586. registry.emplace<int>(entity);
  587. registry.emplace<char>(entity);
  588. registry.emplace<double>(entity);
  589. registry.emplace<empty_type>(entity);
  590. const auto other = registry.create();
  591. registry.emplace<int>(other);
  592. registry.emplace<char>(other);
  593. registry.view<int, char, empty_type>().each([entity](const auto entt, int, char) {
  594. ASSERT_EQ(entity, entt);
  595. });
  596. for(auto [entt, iv, cv]: registry.view<int, char, empty_type>().each()) {
  597. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  598. static_assert(std::is_same_v<decltype(iv), int &>);
  599. static_assert(std::is_same_v<decltype(cv), char &>);
  600. ASSERT_EQ(entity, entt);
  601. }
  602. registry.view<int, empty_type, char>().each([check = true](int, char) mutable {
  603. ASSERT_TRUE(check);
  604. check = false;
  605. });
  606. for(auto [entt, iv, cv]: registry.view<int, empty_type, char>().each()) {
  607. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  608. static_assert(std::is_same_v<decltype(iv), int &>);
  609. static_assert(std::is_same_v<decltype(cv), char &>);
  610. ASSERT_EQ(entity, entt);
  611. }
  612. registry.view<empty_type, int, char>().each([entity](const auto entt, int, char) {
  613. ASSERT_EQ(entity, entt);
  614. });
  615. for(auto [entt, iv, cv]: registry.view<empty_type, int, char>().each()) {
  616. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  617. static_assert(std::is_same_v<decltype(iv), int &>);
  618. static_assert(std::is_same_v<decltype(cv), char &>);
  619. ASSERT_EQ(entity, entt);
  620. }
  621. registry.view<empty_type, int, char>().each<empty_type>([entity](const auto entt, int, char) {
  622. ASSERT_EQ(entity, entt);
  623. });
  624. for(auto [entt, iv, cv]: registry.view<empty_type, int, char>().each<empty_type>()) {
  625. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  626. static_assert(std::is_same_v<decltype(iv), int &>);
  627. static_assert(std::is_same_v<decltype(cv), char &>);
  628. ASSERT_EQ(entity, entt);
  629. }
  630. registry.view<int, empty_type, char>().each<empty_type>([check = true](int, char) mutable {
  631. ASSERT_TRUE(check);
  632. check = false;
  633. });
  634. for(auto [entt, iv, cv]: registry.view<int, empty_type, char>().each<empty_type>()) {
  635. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  636. static_assert(std::is_same_v<decltype(iv), int &>);
  637. static_assert(std::is_same_v<decltype(cv), char &>);
  638. ASSERT_EQ(entity, entt);
  639. }
  640. registry.view<int, char, double>().each([entity](const auto entt, int, char, double) {
  641. ASSERT_EQ(entity, entt);
  642. });
  643. for(auto [entt, iv, cv, dv]: registry.view<int, char, double>().each()) {
  644. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  645. static_assert(std::is_same_v<decltype(iv), int &>);
  646. static_assert(std::is_same_v<decltype(cv), char &>);
  647. static_assert(std::is_same_v<decltype(dv), double &>);
  648. ASSERT_EQ(entity, entt);
  649. }
  650. }
  651. TEST(MultiComponentView, FrontBack) {
  652. entt::registry registry;
  653. auto view = registry.view<const int, const char>();
  654. ASSERT_EQ(view.front(), static_cast<entt::entity>(entt::null));
  655. ASSERT_EQ(view.back(), static_cast<entt::entity>(entt::null));
  656. const auto e0 = registry.create();
  657. registry.emplace<int>(e0);
  658. registry.emplace<char>(e0);
  659. const auto e1 = registry.create();
  660. registry.emplace<int>(e1);
  661. registry.emplace<char>(e1);
  662. const auto entity = registry.create();
  663. registry.emplace<char>(entity);
  664. ASSERT_EQ(view.front(), e1);
  665. ASSERT_EQ(view.back(), e0);
  666. }
  667. TEST(MultiComponentView, ExtendedGet) {
  668. using type = decltype(std::declval<entt::registry>().view<int, empty_type, char>().get({}));
  669. static_assert(std::tuple_size_v<type> == 2u);
  670. static_assert(std::is_same_v<std::tuple_element_t<0, type>, int &>);
  671. static_assert(std::is_same_v<std::tuple_element_t<1, type>, char &>);
  672. }
  673. TEST(MultiComponentView, DeductionGuide) {
  674. entt::registry registry;
  675. typename entt::storage_traits<entt::entity, int>::storage_type istorage;
  676. typename entt::storage_traits<entt::entity, double>::storage_type dstorage;
  677. static_assert(std::is_same_v<decltype(entt::basic_view{istorage, dstorage}), entt::basic_view<entt::entity, entt::exclude_t<>, int, double>>);
  678. 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>>);
  679. 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>>);
  680. 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>>);
  681. }
  682. TEST(View, Pipe) {
  683. entt::registry registry;
  684. const auto entity = registry.create();
  685. const auto other = registry.create();
  686. registry.emplace<int>(entity);
  687. registry.emplace<char>(entity);
  688. registry.emplace<double>(entity);
  689. registry.emplace<empty_type>(entity);
  690. registry.emplace<int>(other);
  691. registry.emplace<char>(other);
  692. const auto view1 = registry.view<int>(entt::exclude<double>);
  693. const auto view2 = registry.view<const char>(entt::exclude<float>);
  694. const auto view3 = registry.view<empty_type>();
  695. static_assert(std::is_same_v<decltype(view1 | view2), entt::basic_view<entt::entity, entt::exclude_t<double, float>, int, const char>>);
  696. static_assert(std::is_same_v<decltype(view2 | view1), entt::basic_view<entt::entity, entt::exclude_t<float, double>, const char, int>>);
  697. static_assert(std::is_same_v<decltype((view1 | view2) | view3), decltype(view1 | (view2 | view3))>);
  698. ASSERT_FALSE((view1 | view2).contains(entity));
  699. ASSERT_TRUE((view1 | view2).contains(other));
  700. ASSERT_TRUE((view2 | view3).contains(entity));
  701. ASSERT_FALSE((view2 | view3).contains(other));
  702. ASSERT_FALSE((view1 | view2 | view3).contains(entity));
  703. ASSERT_FALSE((view1 | view2 | view3).contains(other));
  704. }