view.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949
  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. 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_THROW((view.begin()++));
  299. ASSERT_NO_THROW((++cview.begin()));
  300. ASSERT_NO_THROW(view.rbegin()++);
  301. ASSERT_NO_THROW(++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. }
  365. TEST(MultiComponentView, ReverseIterator) {
  366. entt::registry registry;
  367. const auto entity = registry.create();
  368. registry.emplace<int>(entity);
  369. registry.emplace<char>(entity);
  370. const auto view = registry.view<int, char>();
  371. using iterator = typename decltype(view)::reverse_iterator;
  372. iterator end{view.rbegin()};
  373. iterator begin{};
  374. begin = view.rend();
  375. std::swap(begin, end);
  376. ASSERT_EQ(begin, view.rbegin());
  377. ASSERT_EQ(end, view.rend());
  378. ASSERT_NE(begin, end);
  379. ASSERT_EQ(begin++, view.rbegin());
  380. ASSERT_EQ(begin--, view.rend());
  381. ASSERT_EQ(++begin, view.rend());
  382. ASSERT_EQ(--begin, view.rbegin());
  383. ASSERT_EQ(*begin, entity);
  384. ASSERT_EQ(*begin.operator->(), entity);
  385. }
  386. TEST(MultiComponentView, Contains) {
  387. entt::registry registry;
  388. const auto e0 = registry.create();
  389. registry.emplace<int>(e0);
  390. registry.emplace<char>(e0);
  391. const auto e1 = registry.create();
  392. registry.emplace<int>(e1);
  393. registry.emplace<char>(e1);
  394. registry.destroy(e0);
  395. auto view = registry.view<int, char>();
  396. ASSERT_FALSE(view.contains(e0));
  397. ASSERT_TRUE(view.contains(e1));
  398. }
  399. TEST(MultiComponentView, SizeHint) {
  400. entt::registry registry;
  401. const auto e0 = registry.create();
  402. registry.emplace<double>(e0);
  403. registry.emplace<int>(e0);
  404. registry.emplace<float>(e0);
  405. const auto e1 = registry.create();
  406. registry.emplace<char>(e1);
  407. registry.emplace<float>(e1);
  408. auto view = registry.view<char, int, float>();
  409. ASSERT_EQ(view.size_hint(), 1u);
  410. ASSERT_EQ(view.begin(), view.end());
  411. ASSERT_EQ(view.rbegin(), view.rend());
  412. }
  413. TEST(MultiComponentView, Each) {
  414. entt::registry registry;
  415. const auto e0 = registry.create();
  416. registry.emplace<int>(e0, 0);
  417. registry.emplace<char>(e0);
  418. const auto e1 = registry.create();
  419. registry.emplace<int>(e1, 1);
  420. registry.emplace<char>(e1);
  421. auto view = registry.view<int, char>();
  422. auto cview = std::as_const(registry).view<const int, const char>();
  423. std::size_t cnt = 0;
  424. for(auto first = cview.each().rbegin(), last = cview.each().rend(); first != last; ++first) {
  425. static_assert(std::is_same_v<decltype(*first), std::tuple<entt::entity, const int &, const char &>>);
  426. ASSERT_EQ(std::get<1>(*first), cnt++);
  427. }
  428. view.each([&cnt](auto, int &, char &) { ++cnt; });
  429. view.each([&cnt](int &, char &) { ++cnt; });
  430. ASSERT_EQ(cnt, std::size_t{6});
  431. cview.each([&cnt](const int &, const char &) { --cnt; });
  432. cview.each([&cnt](auto, const int &, const char &) { --cnt; });
  433. for(auto [entt, iv, cv]: view.each()) {
  434. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  435. static_assert(std::is_same_v<decltype(iv), int &>);
  436. static_assert(std::is_same_v<decltype(cv), char &>);
  437. ASSERT_EQ(iv, --cnt);
  438. }
  439. ASSERT_EQ(cnt, std::size_t{0});
  440. auto it = view.each().begin();
  441. auto rit = view.each().rbegin();
  442. ASSERT_EQ((it++, ++it), view.each().end());
  443. ASSERT_EQ((rit++, ++rit), view.each().rend());
  444. }
  445. TEST(MultiComponentView, EachWithSuggestedType) {
  446. entt::registry registry;
  447. for(auto i = 0; i < 3; ++i) {
  448. const auto entity = registry.create();
  449. registry.emplace<int>(entity, i);
  450. registry.emplace<char>(entity);
  451. }
  452. // makes char a better candidate during iterations
  453. const auto entity = registry.create();
  454. registry.emplace<int>(entity, 99);
  455. registry.view<int, char>().each<int>([value = 2](const auto curr, const auto) mutable {
  456. ASSERT_EQ(curr, value--);
  457. });
  458. registry.sort<int>([](const auto lhs, const auto rhs) {
  459. return lhs < rhs;
  460. });
  461. registry.view<int, char>().each<int>([value = 0](const auto curr, const auto) mutable {
  462. ASSERT_EQ(curr, value++);
  463. });
  464. registry.sort<int>([](const auto lhs, const auto rhs) {
  465. return lhs > rhs;
  466. });
  467. auto value = registry.view<int, char>().size_hint();
  468. for(auto &&curr: registry.view<int, char>().each()) {
  469. ASSERT_EQ(std::get<1>(curr), static_cast<int>(--value));
  470. }
  471. registry.sort<int>([](const auto lhs, const auto rhs) {
  472. return lhs < rhs;
  473. });
  474. value = {};
  475. for(auto &&curr: registry.view<int, char>().each<int>()) {
  476. ASSERT_EQ(std::get<1>(curr), static_cast<int>(value++));
  477. }
  478. }
  479. TEST(MultiComponentView, EachWithHoles) {
  480. entt::registry registry;
  481. const auto e0 = registry.create();
  482. const auto e1 = registry.create();
  483. const auto e2 = registry.create();
  484. registry.emplace<char>(e0, '0');
  485. registry.emplace<char>(e1, '1');
  486. registry.emplace<int>(e0, 0);
  487. registry.emplace<int>(e2, 2);
  488. auto view = registry.view<char, int>();
  489. view.each([e0](auto entity, const char &c, const int &i) {
  490. ASSERT_EQ(entity, e0);
  491. ASSERT_EQ(c, '0');
  492. ASSERT_EQ(i, 0);
  493. });
  494. for(auto &&curr: view.each()) {
  495. ASSERT_EQ(std::get<0>(curr), e0);
  496. ASSERT_EQ(std::get<1>(curr), '0');
  497. ASSERT_EQ(std::get<2>(curr), 0);
  498. }
  499. }
  500. TEST(MultiComponentView, ConstNonConstAndAllInBetween) {
  501. entt::registry registry;
  502. auto view = registry.view<int, empty_type, const char>();
  503. ASSERT_EQ(view.size_hint(), 0u);
  504. const auto entity = registry.create();
  505. registry.emplace<int>(entity, 0);
  506. registry.emplace<empty_type>(entity);
  507. registry.emplace<char>(entity, 'c');
  508. ASSERT_EQ(view.size_hint(), 1u);
  509. static_assert(std::is_same_v<decltype(view.get<int>({})), int &>);
  510. static_assert(std::is_same_v<decltype(view.get<const char>({})), const char &>);
  511. static_assert(std::is_same_v<decltype(view.get<int, const char>({})), std::tuple<int &, const char &>>);
  512. static_assert(std::is_same_v<decltype(view.get({})), std::tuple<int &, const char &>>);
  513. view.each([](auto &&i, auto &&c) {
  514. static_assert(std::is_same_v<decltype(i), int &>);
  515. static_assert(std::is_same_v<decltype(c), const char &>);
  516. });
  517. for(auto [entt, iv, cv]: view.each()) {
  518. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  519. static_assert(std::is_same_v<decltype(iv), int &>);
  520. static_assert(std::is_same_v<decltype(cv), const char &>);
  521. }
  522. }
  523. TEST(MultiComponentView, Find) {
  524. entt::registry registry;
  525. auto view = registry.view<int, const char>();
  526. const auto e0 = registry.create();
  527. registry.emplace<int>(e0);
  528. registry.emplace<char>(e0);
  529. const auto e1 = registry.create();
  530. registry.emplace<int>(e1);
  531. registry.emplace<char>(e1);
  532. const auto e2 = registry.create();
  533. registry.emplace<int>(e2);
  534. registry.emplace<char>(e2);
  535. const auto e3 = registry.create();
  536. registry.emplace<int>(e3);
  537. registry.emplace<char>(e3);
  538. registry.remove<int>(e1);
  539. ASSERT_NE(view.find(e0), view.end());
  540. ASSERT_EQ(view.find(e1), view.end());
  541. ASSERT_NE(view.find(e2), view.end());
  542. ASSERT_NE(view.find(e3), view.end());
  543. auto it = view.find(e2);
  544. ASSERT_EQ(*it, e2);
  545. ASSERT_EQ(*(++it), e3);
  546. ASSERT_EQ(*(++it), e0);
  547. ASSERT_EQ(++it, view.end());
  548. ASSERT_EQ(++view.find(e0), view.end());
  549. const auto e4 = registry.create();
  550. registry.destroy(e4);
  551. const auto e5 = registry.create();
  552. registry.emplace<int>(e5);
  553. registry.emplace<char>(e5);
  554. ASSERT_NE(view.find(e5), view.end());
  555. ASSERT_EQ(view.find(e4), view.end());
  556. }
  557. TEST(MultiComponentView, ExcludedComponents) {
  558. entt::registry registry;
  559. const auto e0 = registry.create();
  560. registry.emplace<int>(e0, 0);
  561. const auto e1 = registry.create();
  562. registry.emplace<int>(e1, 1);
  563. registry.emplace<char>(e1);
  564. const auto e2 = registry.create();
  565. registry.emplace<int>(e2, 2);
  566. const auto e3 = registry.create();
  567. registry.emplace<int>(e3, 3);
  568. registry.emplace<char>(e3);
  569. const auto view = std::as_const(registry).view<const int>(entt::exclude<char>);
  570. for(const auto entity: view) {
  571. ASSERT_TRUE(entity == e0 || entity == e2);
  572. if(entity == e0) {
  573. ASSERT_EQ(view.get<const int>(e0), 0);
  574. } else if(entity == e2) {
  575. ASSERT_EQ(std::get<0>(view.get(e2)), 2);
  576. }
  577. }
  578. registry.emplace<char>(e0);
  579. registry.emplace<char>(e2);
  580. registry.remove<char>(e1);
  581. registry.remove<char>(e3);
  582. for(const auto entity: view) {
  583. ASSERT_TRUE(entity == e1 || entity == e3);
  584. if(entity == e1) {
  585. ASSERT_EQ(std::get<0>(view.get(e1)), 1);
  586. } else if(entity == e3) {
  587. ASSERT_EQ(view.get<const int>(e3), 3);
  588. }
  589. }
  590. }
  591. TEST(MultiComponentView, EmptyTypes) {
  592. entt::registry registry;
  593. const auto entity = registry.create();
  594. registry.emplace<int>(entity);
  595. registry.emplace<char>(entity);
  596. registry.emplace<double>(entity);
  597. registry.emplace<empty_type>(entity);
  598. const auto other = registry.create();
  599. registry.emplace<int>(other);
  600. registry.emplace<char>(other);
  601. registry.view<int, char, empty_type>().each([entity](const auto entt, int, char) {
  602. ASSERT_EQ(entity, entt);
  603. });
  604. for(auto [entt, iv, cv]: registry.view<int, char, empty_type>().each()) {
  605. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  606. static_assert(std::is_same_v<decltype(iv), int &>);
  607. static_assert(std::is_same_v<decltype(cv), char &>);
  608. ASSERT_EQ(entity, entt);
  609. }
  610. registry.view<int, empty_type, char>().each([check = true](int, char) mutable {
  611. ASSERT_TRUE(check);
  612. check = false;
  613. });
  614. for(auto [entt, iv, cv]: registry.view<int, empty_type, char>().each()) {
  615. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  616. static_assert(std::is_same_v<decltype(iv), int &>);
  617. static_assert(std::is_same_v<decltype(cv), char &>);
  618. ASSERT_EQ(entity, entt);
  619. }
  620. registry.view<empty_type, int, char>().each([entity](const auto entt, int, char) {
  621. ASSERT_EQ(entity, entt);
  622. });
  623. for(auto [entt, iv, cv]: registry.view<empty_type, int, char>().each()) {
  624. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  625. static_assert(std::is_same_v<decltype(iv), int &>);
  626. static_assert(std::is_same_v<decltype(cv), char &>);
  627. ASSERT_EQ(entity, entt);
  628. }
  629. registry.view<empty_type, int, char>().each<empty_type>([entity](const auto entt, int, char) {
  630. ASSERT_EQ(entity, entt);
  631. });
  632. for(auto [entt, iv, cv]: registry.view<empty_type, int, char>().each<empty_type>()) {
  633. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  634. static_assert(std::is_same_v<decltype(iv), int &>);
  635. static_assert(std::is_same_v<decltype(cv), char &>);
  636. ASSERT_EQ(entity, entt);
  637. }
  638. registry.view<int, empty_type, char>().each<empty_type>([check = true](int, char) mutable {
  639. ASSERT_TRUE(check);
  640. check = false;
  641. });
  642. for(auto [entt, iv, cv]: registry.view<int, empty_type, char>().each<empty_type>()) {
  643. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  644. static_assert(std::is_same_v<decltype(iv), int &>);
  645. static_assert(std::is_same_v<decltype(cv), char &>);
  646. ASSERT_EQ(entity, entt);
  647. }
  648. registry.view<int, char, double>().each([entity](const auto entt, int, char, double) {
  649. ASSERT_EQ(entity, entt);
  650. });
  651. for(auto [entt, iv, cv, dv]: registry.view<int, char, double>().each()) {
  652. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  653. static_assert(std::is_same_v<decltype(iv), int &>);
  654. static_assert(std::is_same_v<decltype(cv), char &>);
  655. static_assert(std::is_same_v<decltype(dv), double &>);
  656. ASSERT_EQ(entity, entt);
  657. }
  658. }
  659. TEST(MultiComponentView, FrontBack) {
  660. entt::registry registry;
  661. auto view = registry.view<const int, const char>();
  662. ASSERT_EQ(view.front(), static_cast<entt::entity>(entt::null));
  663. ASSERT_EQ(view.back(), static_cast<entt::entity>(entt::null));
  664. const auto e0 = registry.create();
  665. registry.emplace<int>(e0);
  666. registry.emplace<char>(e0);
  667. const auto e1 = registry.create();
  668. registry.emplace<int>(e1);
  669. registry.emplace<char>(e1);
  670. const auto entity = registry.create();
  671. registry.emplace<char>(entity);
  672. ASSERT_EQ(view.front(), e1);
  673. ASSERT_EQ(view.back(), e0);
  674. }
  675. TEST(MultiComponentView, ExtendedGet) {
  676. using type = decltype(std::declval<entt::registry>().view<int, empty_type, char>().get({}));
  677. static_assert(std::tuple_size_v<type> == 2u);
  678. static_assert(std::is_same_v<std::tuple_element_t<0, type>, int &>);
  679. static_assert(std::is_same_v<std::tuple_element_t<1, type>, char &>);
  680. }
  681. TEST(MultiComponentView, DeductionGuide) {
  682. entt::registry registry;
  683. typename entt::storage_traits<entt::entity, int>::storage_type istorage;
  684. typename entt::storage_traits<entt::entity, double>::storage_type dstorage;
  685. static_assert(std::is_same_v<decltype(entt::basic_view{istorage, dstorage}), entt::basic_view<entt::entity, entt::exclude_t<>, int, double>>);
  686. 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>>);
  687. 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>>);
  688. 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>>);
  689. }
  690. TEST(View, Pipe) {
  691. entt::registry registry;
  692. const auto entity = registry.create();
  693. const auto other = registry.create();
  694. registry.emplace<int>(entity);
  695. registry.emplace<char>(entity);
  696. registry.emplace<double>(entity);
  697. registry.emplace<empty_type>(entity);
  698. registry.emplace<int>(other);
  699. registry.emplace<char>(other);
  700. const auto view1 = registry.view<int>(entt::exclude<double>);
  701. const auto view2 = registry.view<const char>(entt::exclude<float>);
  702. const auto view3 = registry.view<empty_type>();
  703. static_assert(std::is_same_v<decltype(view1 | view2), entt::basic_view<entt::entity, entt::exclude_t<double, float>, int, const char>>);
  704. static_assert(std::is_same_v<decltype(view2 | view1), entt::basic_view<entt::entity, entt::exclude_t<float, double>, const char, int>>);
  705. static_assert(std::is_same_v<decltype((view1 | view2) | view3), decltype(view1 | (view2 | view3))>);
  706. ASSERT_FALSE((view1 | view2).contains(entity));
  707. ASSERT_TRUE((view1 | view2).contains(other));
  708. ASSERT_TRUE((view2 | view3).contains(entity));
  709. ASSERT_FALSE((view2 | view3).contains(other));
  710. ASSERT_FALSE((view1 | view2 | view3).contains(entity));
  711. ASSERT_FALSE((view1 | view2 | view3).contains(other));
  712. }