registry.cpp 44 KB

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