registry.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. #ifndef ENTT_REGISTRY_HPP
  2. #define ENTT_REGISTRY_HPP
  3. #include <cassert>
  4. #include <memory>
  5. #include <vector>
  6. #include <utility>
  7. #include <cstddef>
  8. #include <iterator>
  9. #include <algorithm>
  10. #include "component_pool.hpp"
  11. namespace entt {
  12. template<typename...>
  13. class View;
  14. template<template<typename...> class Pool, typename Entity, typename... Components, typename Type, typename... Types>
  15. class View<Pool<Entity, Components...>, Type, Types...> final {
  16. using pool_type = Pool<Entity, Components...>;
  17. using entity_type = typename pool_type::entity_type;
  18. class ViewIterator {
  19. bool valid() const noexcept {
  20. using accumulator_type = bool[];
  21. bool check = pool.template has<Type>(entities[pos-1]);
  22. accumulator_type accumulator = { true, (check = check && pool.template has<Types>(entities[pos-1]))... };
  23. (void)accumulator;
  24. return check;
  25. }
  26. public:
  27. using value_type = entity_type;
  28. using difference_type = std::ptrdiff_t;
  29. using reference = entity_type &;
  30. using pointer = entity_type *;
  31. using iterator_category = std::input_iterator_tag;
  32. ViewIterator(pool_type &pool, const entity_type *entities, typename pool_type::size_type pos) noexcept
  33. : pool{pool}, entities{entities}, pos{pos}
  34. {
  35. if(this->pos) { while(!valid() && --this->pos); }
  36. }
  37. ViewIterator & operator++() noexcept {
  38. if(pos) { while(--pos && !valid()); }
  39. return *this;
  40. }
  41. ViewIterator operator++(int) noexcept {
  42. ViewIterator orig = *this;
  43. return this->operator++(), orig;
  44. }
  45. bool operator==(const ViewIterator &other) const noexcept {
  46. return other.entities == entities && other.pos == pos;
  47. }
  48. bool operator!=(const ViewIterator &other) const noexcept {
  49. return !(*this == other);
  50. }
  51. value_type operator*() const noexcept {
  52. return *(entities+pos-1);
  53. }
  54. private:
  55. pool_type &pool;
  56. const entity_type *entities;
  57. std::uint32_t pos;
  58. };
  59. template<typename Comp>
  60. void prefer() noexcept {
  61. auto sz = pool.template size<Comp>();
  62. if(sz < size) {
  63. entities = pool.template entities<Comp>();
  64. size = sz;
  65. }
  66. }
  67. public:
  68. using iterator_type = ViewIterator;
  69. using size_type = typename pool_type::size_type;
  70. explicit View(pool_type &pool) noexcept
  71. : entities{pool.template entities<Type>()},
  72. size{pool.template size<Type>()},
  73. pool{pool}
  74. {
  75. using accumulator_type = int[];
  76. accumulator_type accumulator = { 0, (prefer<Types>(), 0)... };
  77. (void)accumulator;
  78. }
  79. iterator_type begin() const noexcept {
  80. return ViewIterator{pool, entities, size};
  81. }
  82. iterator_type end() const noexcept {
  83. return ViewIterator{pool, entities, 0};
  84. }
  85. void reset() noexcept {
  86. using accumulator_type = int[];
  87. entities = pool.template entities<Type>();
  88. size = pool.template size<Type>();
  89. accumulator_type accumulator = { 0, (prefer<Types>(), 0)... };
  90. (void)accumulator;
  91. }
  92. private:
  93. const entity_type *entities;
  94. size_type size;
  95. pool_type &pool;
  96. };
  97. template<template<typename...> class Pool, typename Entity, typename... Components, typename Type>
  98. class View<Pool<Entity, Components...>, Type> final {
  99. using pool_type = Pool<Entity, Components...>;
  100. using entity_type = typename pool_type::entity_type;
  101. struct ViewIterator {
  102. using value_type = entity_type;
  103. using difference_type = std::ptrdiff_t;
  104. using reference = entity_type &;
  105. using pointer = entity_type *;
  106. using iterator_category = std::input_iterator_tag;
  107. ViewIterator(const entity_type *entities, typename pool_type::size_type pos) noexcept
  108. : entities{entities}, pos{pos}
  109. {}
  110. ViewIterator & operator++() noexcept {
  111. --pos;
  112. return *this;
  113. }
  114. ViewIterator operator++(int) noexcept {
  115. ViewIterator orig = *this;
  116. return this->operator++(), orig;
  117. }
  118. bool operator==(const ViewIterator &other) const noexcept {
  119. return other.entities == entities && other.pos == pos;
  120. }
  121. bool operator!=(const ViewIterator &other) const noexcept {
  122. return !(*this == other);
  123. }
  124. value_type operator*() const noexcept {
  125. return *(entities+pos-1);
  126. }
  127. private:
  128. const entity_type *entities;
  129. typename pool_type::size_type pos;
  130. };
  131. public:
  132. using iterator_type = ViewIterator;
  133. using size_type = typename pool_type::size_type;
  134. explicit View(pool_type &pool) noexcept: pool{pool} {}
  135. iterator_type begin() const noexcept {
  136. return ViewIterator{pool.template entities<Type>(), pool.template size<Type>()};
  137. }
  138. iterator_type end() const noexcept {
  139. return ViewIterator{pool.template entities<Type>(), 0};
  140. }
  141. size_type size() const noexcept {
  142. return pool.template size<Type>();
  143. }
  144. private:
  145. pool_type &pool;
  146. };
  147. template<typename>
  148. class Registry;
  149. template<template<typename...> class Pool, typename Entity, typename... Components>
  150. class Registry<Pool<Entity, Components...>> final {
  151. using pool_type = Pool<Entity, Components...>;
  152. public:
  153. static_assert(sizeof...(Components) > 1, "!");
  154. using entity_type = typename pool_type::entity_type;
  155. using size_type = std::size_t;
  156. private:
  157. template<typename Comp>
  158. void destroy(entity_type entity) {
  159. if(pool.template has<Comp>(entity)) {
  160. pool.template destroy<Comp>(entity);
  161. }
  162. }
  163. template<typename Comp>
  164. void clone(entity_type from, entity_type to) {
  165. if(pool.template has<Comp>(from)) {
  166. pool.template construct<Comp>(to, pool.template get<Comp>(from));
  167. }
  168. }
  169. template<typename Comp>
  170. void sync(entity_type from, entity_type to) {
  171. bool src = pool.template has<Comp>(from);
  172. bool dst = pool.template has<Comp>(to);
  173. if(src && dst) {
  174. copy<Comp>(from, to);
  175. } else if(src) {
  176. clone<Comp>(from, to);
  177. } else if(dst) {
  178. destroy(to);
  179. }
  180. }
  181. public:
  182. template<typename... Comp>
  183. using view_type = View<pool_type, Comp...>;
  184. template<typename... Args>
  185. Registry(Args&&... args)
  186. : count{0}, pool{std::forward<Args>(args)...}
  187. {}
  188. Registry(const Registry &) = delete;
  189. Registry(Registry &&) = delete;
  190. Registry & operator=(const Registry &) = delete;
  191. Registry & operator=(Registry &&) = delete;
  192. size_type size() const noexcept {
  193. return count - available.size();
  194. }
  195. size_type capacity() const noexcept {
  196. return count;
  197. }
  198. template<typename Comp>
  199. bool empty() const noexcept {
  200. return pool.template empty<Comp>();
  201. }
  202. bool empty() const noexcept {
  203. return available.size() == count;
  204. }
  205. template<typename... Comp>
  206. entity_type create() noexcept {
  207. using accumulator_type = int[];
  208. auto entity = create();
  209. accumulator_type accumulator = { 0, (assign<Comp>(entity), 0)... };
  210. (void)accumulator;
  211. return entity;
  212. }
  213. entity_type create() noexcept {
  214. entity_type entity;
  215. if(available.empty()) {
  216. entity = count++;
  217. } else {
  218. entity = available.back();
  219. available.pop_back();
  220. }
  221. return entity;
  222. }
  223. void destroy(entity_type entity) {
  224. using accumulator_type = int[];
  225. accumulator_type accumulator = { 0, (destroy<Components>(entity), 0)... };
  226. (void)accumulator;
  227. available.push_back(entity);
  228. }
  229. template<typename Comp, typename... Args>
  230. Comp & assign(entity_type entity, Args... args) {
  231. return pool.template construct<Comp>(entity, args...);
  232. }
  233. template<typename Comp>
  234. void remove(entity_type entity) {
  235. pool.template destroy<Comp>(entity);
  236. }
  237. template<typename... Comp>
  238. bool has(entity_type entity) const noexcept {
  239. using accumulator_type = bool[];
  240. bool all = true;
  241. accumulator_type accumulator = { true, (all = all && pool.template has<Comp>(entity))... };
  242. (void)accumulator;
  243. return all;
  244. }
  245. template<typename Comp>
  246. const Comp & get(entity_type entity) const noexcept {
  247. return pool.template get<Comp>(entity);
  248. }
  249. template<typename Comp>
  250. Comp & get(entity_type entity) noexcept {
  251. return pool.template get<Comp>(entity);
  252. }
  253. template<typename Comp, typename... Args>
  254. Comp & replace(entity_type entity, Args... args) {
  255. return (pool.template get<Comp>(entity) = Comp{args...});
  256. }
  257. template<typename Comp, typename... Args>
  258. Comp & accomodate(entity_type entity, Args... args) {
  259. return (pool.template has<Comp>(entity)
  260. ? this->template replace<Comp>(entity, std::forward<Args>(args)...)
  261. : this->template assign<Comp>(entity, std::forward<Args>(args)...));
  262. }
  263. entity_type clone(entity_type from) {
  264. auto to = create();
  265. using accumulator_type = int[];
  266. accumulator_type accumulator = { 0, (clone<Components>(from, to), 0)... };
  267. (void)accumulator;
  268. return to;
  269. }
  270. template<typename Comp>
  271. Comp & copy(entity_type from, entity_type to) {
  272. return (pool.template get<Comp>(to) = pool.template get<Comp>(from));
  273. }
  274. void copy(entity_type from, entity_type to) {
  275. using accumulator_type = int[];
  276. accumulator_type accumulator = { 0, (sync<Components>(from, to), 0)... };
  277. (void)accumulator;
  278. }
  279. template<typename Comp>
  280. void reset(entity_type entity) {
  281. if(pool.template has<Comp>(entity)) {
  282. pool.template destroy<Comp>(entity);
  283. }
  284. }
  285. template<typename Comp>
  286. void reset() {
  287. pool.template reset<Comp>();
  288. }
  289. void reset() {
  290. available.clear();
  291. count = 0;
  292. pool.reset();
  293. }
  294. template<typename... Comp>
  295. view_type<Comp...> view() {
  296. return view_type<Comp...>{pool};
  297. }
  298. private:
  299. std::vector<entity_type> available;
  300. entity_type count;
  301. pool_type pool;
  302. };
  303. template<typename Entity, typename... Components>
  304. using StandardRegistry = Registry<ComponentPool<Entity, Components...>>;
  305. template<typename... Components>
  306. using DefaultRegistry = Registry<ComponentPool<std::uint32_t, Components...>>;
  307. }
  308. #endif // ENTT_REGISTRY_HPP