EnTT  2.7.3
prototype.hpp
1 #ifndef ENTT_ENTITY_PROTOTYPE_HPP
2 #define ENTT_ENTITY_PROTOTYPE_HPP
3 
4 
5 #include <tuple>
6 #include <utility>
7 #include <cstddef>
8 #include <type_traits>
9 #include <unordered_map>
10 #include "../config/config.h"
11 #include "registry.hpp"
12 #include "entity.hpp"
13 
14 
15 namespace entt {
16 
17 
39 template<typename Entity>
40 class Prototype final {
41  using basic_fn_type = void(const Prototype &, Registry<Entity> &, const Entity);
42  using component_type = typename Registry<Entity>::component_type;
43 
44  template<typename Component>
45  struct Wrapper { Component component; };
46 
47  struct Handler {
48  basic_fn_type *accommodate;
49  basic_fn_type *assign;
50  };
51 
52  void release() {
53  if(registry->valid(entity)) {
54  registry->destroy(entity);
55  }
56  }
57 
58 public:
62  using entity_type = Entity;
64  using size_type = std::size_t;
65 
71  : registry{&registry},
72  entity{registry.create()}
73  {}
74 
79  release();
80  }
81 
83  Prototype(const Prototype &) = delete;
84 
95  : handlers{std::move(other.handlers)},
96  registry{other.registry},
97  entity{other.entity}
98  {
99  other.entity = entt::null;
100  }
101 
103  Prototype & operator=(const Prototype &) = delete;
104 
116  if(this != &other) {
117  auto tmp{std::move(other)};
118  handlers.swap(tmp.handlers);
119  std::swap(registry, tmp.registry);
120  std::swap(entity, tmp.entity);
121  }
122 
123  return *this;
124  }
125 
133  template<typename Component, typename... Args>
134  Component & set(Args &&... args) {
135  basic_fn_type *accommodate = [](const Prototype &prototype, Registry<Entity> &other, const Entity dst) {
136  const auto &wrapper = prototype.registry->template get<Wrapper<Component>>(prototype.entity);
137  other.template accommodate<Component>(dst, wrapper.component);
138  };
139 
140  basic_fn_type *assign = [](const Prototype &prototype, Registry<Entity> &other, const Entity dst) {
141  if(!other.template has<Component>(dst)) {
142  const auto &wrapper = prototype.registry->template get<Wrapper<Component>>(prototype.entity);
143  other.template assign<Component>(dst, wrapper.component);
144  }
145  };
146 
147  handlers[registry->template type<Component>()] = Handler{accommodate, assign};
148  auto &wrapper = registry->template accommodate<Wrapper<Component>>(entity, Component{std::forward<Args>(args)...});
149  return wrapper.component;
150  }
151 
156  template<typename Component>
157  void unset() ENTT_NOEXCEPT {
158  registry->template reset<Wrapper<Component>>(entity);
159  handlers.erase(registry->template type<Component>());
160  }
161 
167  template<typename... Component>
168  bool has() const ENTT_NOEXCEPT {
169  return registry->template has<Wrapper<Component>...>(entity);
170  }
171 
184  template<typename Component>
185  const Component & get() const ENTT_NOEXCEPT {
186  return registry->template get<Wrapper<Component>>(entity).component;
187  }
188 
201  template<typename Component>
202  inline Component & get() ENTT_NOEXCEPT {
203  return const_cast<Component &>(const_cast<const Prototype *>(this)->get<Component>());
204  }
205 
218  template<typename... Component>
219  inline std::enable_if_t<(sizeof...(Component) > 1), std::tuple<const Component &...>>
220  get() const ENTT_NOEXCEPT {
221  return std::tuple<const Component &...>{get<Component>()...};
222  }
223 
236  template<typename... Component>
237  inline std::enable_if_t<(sizeof...(Component) > 1), std::tuple<Component &...>>
238  get() ENTT_NOEXCEPT {
239  return std::tuple<Component &...>{get<Component>()...};
240  }
241 
261  const auto entity = other.create();
262  assign(other, entity);
263  return entity;
264  }
265 
283  inline entity_type create() const {
284  return create(*registry);
285  }
286 
308  void assign(registry_type &other, const entity_type dst) const {
309  for(auto &handler: handlers) {
310  handler.second.assign(*this, other, dst);
311  }
312  }
313 
334  inline void assign(const entity_type dst) const {
335  assign(*registry, dst);
336  }
337 
357  void accommodate(registry_type &other, const entity_type dst) const {
358  for(auto &handler: handlers) {
359  handler.second.accommodate(*this, other, dst);
360  }
361  }
362 
381  inline void accommodate(const entity_type dst) const {
382  accommodate(*registry, dst);
383  }
384 
406  inline void operator()(registry_type &other, const entity_type dst) const ENTT_NOEXCEPT {
407  assign(other, dst);
408  }
409 
430  inline void operator()(const entity_type dst) const ENTT_NOEXCEPT {
431  assign(*registry, dst);
432  }
433 
452  inline entity_type operator()(registry_type &other) const ENTT_NOEXCEPT {
453  return create(other);
454  }
455 
473  inline entity_type operator()() const ENTT_NOEXCEPT {
474  return create(*registry);
475  }
476 
477 private:
478  std::unordered_map<component_type, Handler> handlers;
479  Registry<Entity> *registry;
480  entity_type entity;
481 };
482 
483 
492 
493 
494 }
495 
496 
497 #endif // ENTT_ENTITY_PROTOTYPE_HPP
std::size_t size_type
Unsigned integer type.
Definition: prototype.hpp:64
Entity entity_type
Underlying entity identifier.
Definition: prototype.hpp:62
Fast and reliable entity-component system.
Definition: registry.hpp:42
Prototype(Registry< Entity > &registry)
Constructs a prototype that is bound to a given registry.
Definition: prototype.hpp:70
void assign(const entity_type dst) const
Assigns the components of a prototype to a given entity.
Definition: prototype.hpp:334
Prototype(Prototype &&other)
Move constructor.
Definition: prototype.hpp:94
EnTT default namespace.
Definition: algorithm.hpp:10
void operator()(const entity_type dst) const ENTT_NOEXCEPT
Assigns the components of a prototype to an entity.
Definition: prototype.hpp:430
entity_type create() const
Creates a new entity using a given prototype.
Definition: prototype.hpp:283
void accommodate(registry_type &other, const entity_type dst) const
Assigns or replaces the components of a prototype for an entity.
Definition: prototype.hpp:357
void operator()(registry_type &other, const entity_type dst) const ENTT_NOEXCEPT
Assigns the components of a prototype to an entity.
Definition: prototype.hpp:406
constexpr auto null
Null entity.
Definition: entity.hpp:78
~Prototype()
Releases all its resources.
Definition: prototype.hpp:78
void unset() ENTT_NOEXCEPT
Removes the given component from a prototype.
Definition: prototype.hpp:157
entity_type create()
Creates a new entity and returns it.
Definition: registry.hpp:521
entity_type operator()(registry_type &other) const ENTT_NOEXCEPT
Creates a new entity using a given prototype.
Definition: prototype.hpp:452
Prototype & operator=(const Prototype &)=delete
Copying a prototype isn&#39;t allowed.
bool has() const ENTT_NOEXCEPT
Checks if a prototype owns all the given components.
Definition: prototype.hpp:168
typename component_family::family_type component_type
Unsigned integer type.
Definition: registry.hpp:231
entity_type operator()() const ENTT_NOEXCEPT
Creates a new entity using a given prototype.
Definition: prototype.hpp:473
Prototype container for concepts.
Definition: prototype.hpp:40
void assign(registry_type &other, const entity_type dst) const
Assigns the components of a prototype to a given entity.
Definition: prototype.hpp:308
void accommodate(const entity_type dst) const
Assigns or replaces the components of a prototype for an entity.
Definition: prototype.hpp:381
Prototype & operator=(Prototype &&other)
Move assignment operator.
Definition: prototype.hpp:115
entity_type create(registry_type &other) const
Creates a new entity using a given prototype.
Definition: prototype.hpp:260