entt  2.6.1
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 
13 
14 namespace entt {
15 
16 
38 template<typename Entity>
39 class Prototype final {
40  using basic_fn_type = void(const Prototype &, Registry<Entity> &, const Entity);
41  using component_type = typename Registry<Entity>::component_type;
42 
43  template<typename Component>
44  struct Wrapper { Component component; };
45 
46  struct Handler {
47  basic_fn_type *accommodate;
48  basic_fn_type *assign;
49  };
50 
51  void release() {
52  if(registry->valid(entity)) {
53  registry->destroy(entity);
54  }
55  }
56 
57 public:
61  using entity_type = Entity;
63  using size_type = std::size_t;
64 
70  : registry{&registry},
71  entity{registry.create()}
72  {}
73 
78  release();
79  }
80 
82  Prototype(const Prototype &) = delete;
83 
94  : handlers{std::move(other.handlers)},
95  registry{other.registry},
96  entity{other.entity}
97  {
98  other.entity = ~entity_type{};
99  }
100 
102  Prototype & operator=(const Prototype &) = delete;
103 
115  if(this != &other) {
116  auto tmp{std::move(other)};
117  handlers.swap(tmp.handlers);
118  std::swap(registry, tmp.registry);
119  std::swap(entity, tmp.entity);
120  }
121 
122  return *this;
123  }
124 
132  template<typename Component, typename... Args>
133  Component & set(Args &&... args) {
134  basic_fn_type *accommodate = [](const Prototype &prototype, Registry<Entity> &other, const Entity dst) {
135  const auto &wrapper = prototype.registry->template get<Wrapper<Component>>(prototype.entity);
136  other.template accommodate<Component>(dst, wrapper.component);
137  };
138 
139  basic_fn_type *assign = [](const Prototype &prototype, Registry<Entity> &other, const Entity dst) {
140  if(!other.template has<Component>(dst)) {
141  const auto &wrapper = prototype.registry->template get<Wrapper<Component>>(prototype.entity);
142  other.template accommodate<Component>(dst, wrapper.component);
143  }
144  };
145 
146  handlers[registry->template type<Component>()] = Handler{accommodate, assign};
147  auto &wrapper = registry->template accommodate<Wrapper<Component>>(entity, Component{std::forward<Args>(args)...});
148  return wrapper.component;
149  }
150 
155  template<typename Component>
156  void unset() ENTT_NOEXCEPT {
157  registry->template reset<Wrapper<Component>>(entity);
158  handlers.erase(registry->template type<Component>());
159  }
160 
166  template<typename... Component>
167  bool has() const ENTT_NOEXCEPT {
168  return registry->template has<Wrapper<Component>...>(entity);
169  }
170 
183  template<typename Component>
184  const Component & get() const ENTT_NOEXCEPT {
185  return registry->template get<Wrapper<Component>>(entity).component;
186  }
187 
200  template<typename Component>
201  inline Component & get() ENTT_NOEXCEPT {
202  return const_cast<Component &>(const_cast<const Prototype *>(this)->get<Component>());
203  }
204 
217  template<typename... Component>
218  inline std::enable_if_t<(sizeof...(Component) > 1), std::tuple<const Component &...>>
219  get() const ENTT_NOEXCEPT {
220  return std::tuple<const Component &...>{get<Component>()...};
221  }
222 
235  template<typename... Component>
236  inline std::enable_if_t<(sizeof...(Component) > 1), std::tuple<Component &...>>
237  get() ENTT_NOEXCEPT {
238  return std::tuple<Component &...>{get<Component>()...};
239  }
240 
260  const auto entity = other.create();
261  assign(other, entity);
262  return entity;
263  }
264 
282  inline entity_type create() const {
283  return create(*registry);
284  }
285 
307  void assign(registry_type &other, const entity_type dst) const {
308  for(auto &handler: handlers) {
309  handler.second.assign(*this, other, dst);
310  }
311  }
312 
333  inline void assign(const entity_type dst) const {
334  assign(*registry, dst);
335  }
336 
356  void accommodate(registry_type &other, const entity_type dst) const {
357  for(auto &handler: handlers) {
358  handler.second.accommodate(*this, other, dst);
359  }
360  }
361 
380  inline void accommodate(const entity_type dst) const {
381  accommodate(*registry, dst);
382  }
383 
405  inline void operator()(registry_type &other, const entity_type dst) const ENTT_NOEXCEPT {
406  assign(other, dst);
407  }
408 
429  inline void operator()(const entity_type dst) const ENTT_NOEXCEPT {
430  assign(*registry, dst);
431  }
432 
451  inline entity_type operator()(registry_type &other) const ENTT_NOEXCEPT {
452  return create(other);
453  }
454 
472  inline entity_type operator()() const ENTT_NOEXCEPT {
473  return create(*registry);
474  }
475 
476 private:
477  std::unordered_map<component_type, Handler> handlers;
478  Registry<Entity> *registry;
479  entity_type entity;
480 };
481 
482 
491 
492 
493 }
494 
495 
496 #endif // ENTT_ENTITY_PROTOTYPE_HPP
std::size_t size_type
Unsigned integer type.
Definition: prototype.hpp:63
Entity entity_type
Underlying entity identifier.
Definition: prototype.hpp:61
Fast and reliable entity-component system.
Definition: registry.hpp:40
Prototype(Registry< Entity > &registry)
Constructs a prototype that is bound to a given registry.
Definition: prototype.hpp:69
void assign(const entity_type dst) const
Assigns the components of a prototype to a given entity.
Definition: prototype.hpp:333
Prototype(Prototype &&other)
Move constructor.
Definition: prototype.hpp:93
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:429
entity_type create() const
Creates a new entity using a given prototype.
Definition: prototype.hpp:282
void accommodate(registry_type &other, const entity_type dst) const
Assigns or replaces the components of a prototype for an entity.
Definition: prototype.hpp:356
void operator()(registry_type &other, const entity_type dst) const ENTT_NOEXCEPT
Assigns the components of a prototype to an entity.
Definition: prototype.hpp:405
~Prototype()
Releases all its resources.
Definition: prototype.hpp:77
void unset() ENTT_NOEXCEPT
Removes the given component from a prototype.
Definition: prototype.hpp:156
entity_type create()
Creates a new entity and returns it.
Definition: registry.hpp:402
entity_type operator()(registry_type &other) const ENTT_NOEXCEPT
Creates a new entity using a given prototype.
Definition: prototype.hpp:451
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:167
typename component_family::family_type component_type
Unsigned integer type.
Definition: registry.hpp:129
entity_type operator()() const ENTT_NOEXCEPT
Creates a new entity using a given prototype.
Definition: prototype.hpp:472
Prototype container for concepts.
Definition: prototype.hpp:39
void assign(registry_type &other, const entity_type dst) const
Assigns the components of a prototype to a given entity.
Definition: prototype.hpp:307
void accommodate(const entity_type dst) const
Assigns or replaces the components of a prototype for an entity.
Definition: prototype.hpp:380
Prototype & operator=(Prototype &&other)
Move assignment operator.
Definition: prototype.hpp:114
entity_type create(registry_type &other) const
Creates a new entity using a given prototype.
Definition: prototype.hpp:259