registry.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. #ifndef ENTT_REGISTRY_HPP
  2. #define ENTT_REGISTRY_HPP
  3. #include <tuple>
  4. #include <vector>
  5. #include <bitset>
  6. #include <utility>
  7. #include <cstddef>
  8. #include <iterator>
  9. #include <cassert>
  10. #include <type_traits>
  11. #include "sparse_set.hpp"
  12. #include "ident.hpp"
  13. namespace entt {
  14. template<typename, std::size_t...>
  15. class View;
  16. template<typename Pool, std::size_t Ident, std::size_t... Other>
  17. class View<Pool, Ident, Other...> final {
  18. using pool_type = Pool;
  19. using mask_type = std::bitset<std::tuple_size<Pool>::value + 1>;
  20. using underlying_iterator_type = typename std::tuple_element_t<Ident, Pool>::iterator_type;
  21. class ViewIterator;
  22. public:
  23. using iterator_type = ViewIterator;
  24. using entity_type = typename std::tuple_element_t<Ident, Pool>::index_type;
  25. using size_type = typename std::tuple_element_t<Ident, Pool>::size_type;
  26. private:
  27. class ViewIterator {
  28. inline bool valid() const noexcept {
  29. return ((mask[*begin] & bitmask) == bitmask);
  30. }
  31. public:
  32. using value_type = entity_type;
  33. ViewIterator(underlying_iterator_type begin, underlying_iterator_type end, const mask_type &bitmask, const mask_type *mask) noexcept
  34. : begin{begin}, end{end}, bitmask{bitmask}, mask{mask}
  35. {
  36. if(begin != end && !valid()) {
  37. ++(*this);
  38. }
  39. }
  40. ViewIterator & operator++() noexcept {
  41. ++begin;
  42. while(begin != end && !valid()) { ++begin; }
  43. return *this;
  44. }
  45. ViewIterator operator++(int) noexcept {
  46. ViewIterator orig = *this;
  47. return ++(*this), orig;
  48. }
  49. bool operator==(const ViewIterator &other) const noexcept {
  50. return other.begin == begin;
  51. }
  52. bool operator!=(const ViewIterator &other) const noexcept {
  53. return !(*this == other);
  54. }
  55. value_type operator*() const noexcept {
  56. return *begin;
  57. }
  58. private:
  59. underlying_iterator_type begin;
  60. underlying_iterator_type end;
  61. const mask_type bitmask;
  62. const mask_type *mask;
  63. };
  64. template<std::size_t Idx>
  65. void prefer(size_type &size) noexcept {
  66. auto &&cpool = std::get<Idx>(*pool);
  67. auto sz = cpool.size();
  68. if(sz < size) {
  69. from = cpool.begin();
  70. to = cpool.end();
  71. size = sz;
  72. }
  73. }
  74. public:
  75. explicit View(const pool_type *pool, const mask_type *mask) noexcept
  76. : from{std::get<Ident>(*pool).begin()},
  77. to{std::get<Ident>(*pool).end()},
  78. pool{pool},
  79. mask{mask}
  80. {
  81. using accumulator_type = int[];
  82. size_type size = std::get<Ident>(*pool).size();
  83. bitmask.set(Ident);
  84. accumulator_type types = { 0, (bitmask.set(Other), 0)... };
  85. accumulator_type pref = { 0, (prefer<Other>(size), 0)... };
  86. (void)types, (void)pref;
  87. }
  88. iterator_type begin() const noexcept {
  89. return ViewIterator{from, to, bitmask, mask};
  90. }
  91. iterator_type end() const noexcept {
  92. return ViewIterator{to, to, bitmask, mask};
  93. }
  94. void reset() noexcept {
  95. using accumulator_type = int[];
  96. auto &&cpool = std::get<Ident>(*pool);
  97. from = cpool.begin();
  98. to = cpool.end();
  99. size_type size = cpool.size();
  100. accumulator_type accumulator = { 0, (prefer<Other>(size), 0)... };
  101. (void)accumulator;
  102. }
  103. private:
  104. underlying_iterator_type from;
  105. underlying_iterator_type to;
  106. const pool_type *pool;
  107. const mask_type *mask;
  108. mask_type bitmask;
  109. };
  110. template<typename Pool, std::size_t Ident>
  111. class View<Pool, Ident> final {
  112. using pool_type = std::tuple_element_t<Ident, Pool>;
  113. public:
  114. using iterator_type = typename pool_type::iterator_type;
  115. using entity_type = typename pool_type::index_type;
  116. using size_type = typename pool_type::size_type;
  117. using raw_type = typename pool_type::type;
  118. explicit View(const Pool *pool) noexcept
  119. : pool{&std::get<Ident>(*pool)}
  120. {}
  121. raw_type * raw() noexcept {
  122. return pool->raw();
  123. }
  124. const raw_type * raw() const noexcept {
  125. return pool->raw();
  126. }
  127. const entity_type * data() const noexcept {
  128. return pool->data();
  129. }
  130. size_type size() const noexcept {
  131. return pool->size();
  132. }
  133. iterator_type begin() const noexcept {
  134. return pool->begin();
  135. }
  136. iterator_type end() const noexcept {
  137. return pool->end();
  138. }
  139. private:
  140. const pool_type *pool;
  141. };
  142. template<typename Entity, typename... Component>
  143. class Registry {
  144. using pool_type = std::tuple<SparseSet<Entity, Component>...>;
  145. using mask_type = std::bitset<sizeof...(Component)+1>;
  146. static constexpr auto validity_bit = sizeof...(Component);
  147. public:
  148. using entity_type = Entity;
  149. using size_type = typename std::vector<mask_type>::size_type;
  150. template<typename... Comp>
  151. using view_type = View<pool_type, ident<Component...>.template get<Comp>()...>;
  152. private:
  153. template<typename Comp>
  154. void clone(entity_type to, entity_type from) {
  155. constexpr auto index = ident<Component...>.template get<Comp>();
  156. if(entities[from].test(index)) {
  157. assign<Comp>(to, std::get<index>(pool).get(from));
  158. }
  159. }
  160. template<typename Comp>
  161. void sync(entity_type to, entity_type from) {
  162. constexpr auto index = ident<Component...>.template get<Comp>();
  163. bool src = entities[from].test(index);
  164. bool dst = entities[to].test(index);
  165. if(src && dst) {
  166. copy<Comp>(to, from);
  167. } else if(src) {
  168. clone<Comp>(to, from);
  169. } else if(dst) {
  170. remove<Comp>(to);
  171. }
  172. }
  173. public:
  174. explicit Registry() = default;
  175. ~Registry() = default;
  176. Registry(const Registry &) = delete;
  177. Registry(Registry &&) = delete;
  178. Registry & operator=(const Registry &) = delete;
  179. Registry & operator=(Registry &&) = delete;
  180. template<typename Comp>
  181. size_type size() const noexcept {
  182. constexpr auto index = ident<Component...>.template get<Comp>();
  183. return std::get<index>(pool).size();
  184. }
  185. size_type size() const noexcept {
  186. return entities.size() - available.size();
  187. }
  188. template<typename Comp>
  189. size_type capacity() const noexcept {
  190. constexpr auto index = ident<Component...>.template get<Comp>();
  191. return std::get<index>(pool).capacity();
  192. }
  193. size_type capacity() const noexcept {
  194. return entities.size();
  195. }
  196. template<typename Comp>
  197. bool empty() const noexcept {
  198. constexpr auto index = ident<Component...>.template get<Comp>();
  199. return std::get<index>(pool).empty();
  200. }
  201. bool empty() const noexcept {
  202. return entities.empty();
  203. }
  204. bool valid(entity_type entity) const noexcept {
  205. return (entity < entities.size() && entities[entity].test(validity_bit));
  206. }
  207. template<typename... Comp>
  208. entity_type create() noexcept {
  209. using accumulator_type = int[];
  210. auto entity = create();
  211. accumulator_type accumulator = { 0, (assign<Comp>(entity), 0)... };
  212. (void)accumulator;
  213. return entity;
  214. }
  215. entity_type create() noexcept {
  216. entity_type entity;
  217. if(available.empty()) {
  218. entity = entity_type(entities.size());
  219. entities.emplace_back();
  220. } else {
  221. entity = available.back();
  222. available.pop_back();
  223. }
  224. entities[entity].set(validity_bit);
  225. return entity;
  226. }
  227. void destroy(entity_type entity) {
  228. assert(valid(entity));
  229. using accumulator_type = int[];
  230. accumulator_type accumulator = { 0, (reset<Component>(entity), 0)... };
  231. available.push_back(entity);
  232. entities[entity].reset();
  233. (void)accumulator;
  234. }
  235. template<typename Comp, typename... Args>
  236. Comp & assign(entity_type entity, Args... args) {
  237. assert(valid(entity));
  238. constexpr auto index = ident<Component...>.template get<Comp>();
  239. entities[entity].set(index);
  240. return std::get<index>(pool).construct(entity, args...);
  241. }
  242. template<typename Comp>
  243. void remove(entity_type entity) {
  244. assert(valid(entity));
  245. constexpr auto index = ident<Component...>.template get<Comp>();
  246. entities[entity].reset(index);
  247. std::get<index>(pool).destroy(entity);
  248. }
  249. template<typename... Comp>
  250. bool has(entity_type entity) const noexcept {
  251. assert(valid(entity));
  252. using accumulator_type = bool[];
  253. bool all = true;
  254. auto &mask = entities[entity];
  255. accumulator_type accumulator = { true, (all = all && mask.test(ident<Component...>.template get<Comp>()))... };
  256. (void)accumulator;
  257. return all;
  258. }
  259. template<typename Comp>
  260. const Comp & get(entity_type entity) const noexcept {
  261. assert(valid(entity));
  262. constexpr auto index = ident<Component...>.template get<Comp>();
  263. return std::get<index>(pool).get(entity);
  264. }
  265. template<typename Comp>
  266. Comp & get(entity_type entity) noexcept {
  267. assert(valid(entity));
  268. constexpr auto index = ident<Component...>.template get<Comp>();
  269. return std::get<index>(pool).get(entity);
  270. }
  271. template<typename Comp, typename... Args>
  272. Comp & replace(entity_type entity, Args... args) {
  273. assert(valid(entity));
  274. constexpr auto index = ident<Component...>.template get<Comp>();
  275. return (std::get<index>(pool).get(entity) = Comp{args...});
  276. }
  277. template<typename Comp, typename... Args>
  278. Comp & accomodate(entity_type entity, Args... args) {
  279. assert(valid(entity));
  280. constexpr auto index = ident<Component...>.template get<Comp>();
  281. return (entities[entity].test(index)
  282. ? this->template replace<Comp>(entity, std::forward<Args>(args)...)
  283. : this->template assign<Comp>(entity, std::forward<Args>(args)...));
  284. }
  285. entity_type clone(entity_type from) {
  286. assert(valid(from));
  287. using accumulator_type = int[];
  288. auto to = create();
  289. accumulator_type accumulator = { 0, (clone<Component>(to, from), 0)... };
  290. (void)accumulator;
  291. return to;
  292. }
  293. template<typename Comp>
  294. Comp & copy(entity_type to, entity_type from) {
  295. assert(valid(to));
  296. assert(valid(from));
  297. constexpr auto index = ident<Component...>.template get<Comp>();
  298. auto &&cpool = std::get<index>(pool);
  299. return (cpool.get(to) = cpool.get(from));
  300. }
  301. void copy(entity_type to, entity_type from) {
  302. assert(valid(to));
  303. assert(valid(from));
  304. using accumulator_type = int[];
  305. accumulator_type accumulator = { 0, (sync<Component>(to, from), 0)... };
  306. (void)accumulator;
  307. }
  308. template<typename Comp>
  309. void swap(entity_type lhs, entity_type rhs) {
  310. assert(valid(lhs));
  311. assert(valid(rhs));
  312. std::get<ident<Component...>.template get<Comp>()>(pool).swap(lhs, rhs);
  313. }
  314. template<typename Comp, typename Compare>
  315. void sort(Compare compare) {
  316. std::get<ident<Component...>.template get<Comp>()>(pool).sort(std::move(compare));
  317. }
  318. template<typename To, typename From>
  319. void sort() {
  320. auto &&to = std::get<ident<Component...>.template get<To>()>(pool);
  321. auto &&from = std::get<ident<Component...>.template get<From>()>(pool);
  322. to.respect(from);
  323. }
  324. template<typename Comp>
  325. void reset(entity_type entity) {
  326. assert(valid(entity));
  327. constexpr auto index = ident<Component...>.template get<Comp>();
  328. if(entities[entity].test(index)) {
  329. remove<Comp>(entity);
  330. }
  331. }
  332. template<typename Comp>
  333. void reset() {
  334. constexpr auto index = ident<Component...>.template get<Comp>();
  335. for(entity_type entity = 0, last = entity_type(entities.size()); entity < last; ++entity) {
  336. if(entities[entity].test(index)) {
  337. remove<Comp>(entity);
  338. }
  339. }
  340. }
  341. void reset() {
  342. using accumulator_type = int[];
  343. accumulator_type acc = { 0, (std::get<ident<Component...>.template get<Component>()>(pool).reset(), 0)... };
  344. entities.clear();
  345. available.clear();
  346. (void)acc;
  347. }
  348. template<typename... Comp>
  349. std::enable_if_t<(sizeof...(Comp) == 1), view_type<Comp...>>
  350. view() noexcept { return view_type<Comp...>{&pool}; }
  351. template<typename... Comp>
  352. std::enable_if_t<(sizeof...(Comp) > 1), view_type<Comp...>>
  353. view() noexcept { return view_type<Comp...>{&pool, entities.data()}; }
  354. private:
  355. std::vector<mask_type> entities;
  356. std::vector<entity_type> available;
  357. pool_type pool;
  358. };
  359. template<typename... Component>
  360. using DefaultRegistry = Registry<std::uint32_t, Component...>;
  361. }
  362. #endif // ENTT_REGISTRY_HPP