EnTT  3.1.0
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 #include "fwd.hpp"
14 
15 
16 namespace entt {
17 
18 
40 template<typename Entity>
41 class basic_prototype {
42  using basic_fn_type = void(const basic_prototype &, basic_registry<Entity> &, const Entity);
43  using component_type = typename basic_registry<Entity>::component_type;
44 
45  template<typename Component>
46  struct component_wrapper { Component component; };
47 
48  struct component_handler {
49  basic_fn_type *assign_or_replace;
50  basic_fn_type *assign;
51  };
52 
53  void release() {
54  if(reg->valid(entity)) {
55  reg->destroy(entity);
56  }
57  }
58 
59 public:
63  using entity_type = Entity;
65  using size_type = std::size_t;
66 
72  : reg{&ref},
73  entity{ref.create()}
74  {}
75 
80  release();
81  }
82 
93  : handlers{std::move(other.handlers)},
94  reg{other.reg},
95  entity{other.entity}
96  {
97  other.entity = null;
98  }
99 
111  if(this != &other) {
112  auto tmp{std::move(other)};
113  handlers.swap(tmp.handlers);
114  std::swap(reg, tmp.reg);
115  std::swap(entity, tmp.entity);
116  }
117 
118  return *this;
119  }
120 
128  template<typename Component, typename... Args>
129  Component & set(Args &&... args) {
130  component_handler handler;
131 
132  handler.assign_or_replace = [](const basic_prototype &proto, registry_type &other, const Entity dst) {
133  const auto &wrapper = proto.reg->template get<component_wrapper<Component>>(proto.entity);
134  other.template assign_or_replace<Component>(dst, wrapper.component);
135  };
136 
137  handler.assign = [](const basic_prototype &proto, registry_type &other, const Entity dst) {
138  if(!other.template has<Component>(dst)) {
139  const auto &wrapper = proto.reg->template get<component_wrapper<Component>>(proto.entity);
140  other.template assign<Component>(dst, wrapper.component);
141  }
142  };
143 
144  handlers[reg->template type<Component>()] = handler;
145  auto &wrapper = reg->template assign_or_replace<component_wrapper<Component>>(entity, Component{std::forward<Args>(args)...});
146  return wrapper.component;
147  }
148 
153  template<typename Component>
154  void unset() ENTT_NOEXCEPT {
155  reg->template reset<component_wrapper<Component>>(entity);
156  handlers.erase(reg->template type<Component>());
157  }
158 
164  template<typename... Component>
165  bool has() const ENTT_NOEXCEPT {
166  return reg->template has<component_wrapper<Component>...>(entity);
167  }
168 
181  template<typename... Component>
182  decltype(auto) get() const ENTT_NOEXCEPT {
183  if constexpr(sizeof...(Component) == 1) {
184  return (std::as_const(*reg).template get<component_wrapper<Component...>>(entity).component);
185  } else {
186  return std::tuple<std::add_const_t<Component> &...>{get<Component>()...};
187  }
188  }
189 
191  template<typename... Component>
192  decltype(auto) get() ENTT_NOEXCEPT {
193  if constexpr(sizeof...(Component) == 1) {
194  return (const_cast<Component &>(std::as_const(*this).template get<Component>()), ...);
195  } else {
196  return std::tuple<Component &...>{get<Component>()...};
197  }
198  }
199 
205  template<typename... Component>
206  auto try_get() const ENTT_NOEXCEPT {
207  if constexpr(sizeof...(Component) == 1) {
208  const auto *wrapper = reg->template try_get<component_wrapper<Component...>>(entity);
209  return wrapper ? &wrapper->component : nullptr;
210  } else {
211  return std::tuple<std::add_const_t<Component> *...>{try_get<Component>()...};
212  }
213  }
214 
216  template<typename... Component>
217  auto try_get() ENTT_NOEXCEPT {
218  if constexpr(sizeof...(Component) == 1) {
219  return (const_cast<Component *>(std::as_const(*this).template try_get<Component>()), ...);
220  } else {
221  return std::tuple<Component *...>{try_get<Component>()...};
222  }
223  }
224 
244  const auto entt = other.create();
245  assign(other, entt);
246  return entt;
247  }
248 
266  entity_type create() const {
267  return create(*reg);
268  }
269 
291  void assign(registry_type &other, const entity_type dst) const {
292  for(auto &handler: handlers) {
293  handler.second.assign(*this, other, dst);
294  }
295  }
296 
317  void assign(const entity_type dst) const {
318  assign(*reg, dst);
319  }
320 
340  void assign_or_replace(registry_type &other, const entity_type dst) const {
341  for(auto &handler: handlers) {
342  handler.second.assign_or_replace(*this, other, dst);
343  }
344  }
345 
364  void assign_or_replace(const entity_type dst) const {
365  assign_or_replace(*reg, dst);
366  }
367 
389  void operator()(registry_type &other, const entity_type dst) const ENTT_NOEXCEPT {
390  assign(other, dst);
391  }
392 
413  void operator()(const entity_type dst) const ENTT_NOEXCEPT {
414  assign(*reg, dst);
415  }
416 
435  entity_type operator()(registry_type &other) const ENTT_NOEXCEPT {
436  return create(other);
437  }
438 
456  entity_type operator()() const ENTT_NOEXCEPT {
457  return create(*reg);
458  }
459 
464  const registry_type & backend() const ENTT_NOEXCEPT {
465  return *reg;
466  }
467 
469  registry_type & backend() ENTT_NOEXCEPT {
470  return const_cast<registry_type &>(std::as_const(*this).backend());
471  }
472 
473 private:
474  std::unordered_map<component_type, component_handler> handlers;
475  registry_type *reg;
476  entity_type entity;
477 };
478 
479 
480 }
481 
482 
483 #endif // ENTT_ENTITY_PROTOTYPE_HPP
basic_prototype(basic_prototype &&other)
Move constructor.
Definition: prototype.hpp:92
void assign_or_replace(const entity_type dst) const
Assigns or replaces the components of a prototype for an entity.
Definition: prototype.hpp:364
entity_type create(registry_type &other) const
Creates a new entity using a given prototype.
Definition: prototype.hpp:243
Entity entity_type
Underlying entity identifier.
Definition: prototype.hpp:63
std::size_t size_type
Unsigned integer type.
Definition: prototype.hpp:65
EnTT default namespace.
Definition: algorithm.hpp:10
~basic_prototype()
Releases all its resources.
Definition: prototype.hpp:79
void operator()(const entity_type dst) const ENTT_NOEXCEPT
Assigns the components of a prototype to an entity.
Definition: prototype.hpp:413
decltype(auto) create()
Creates a new entity and returns it.
Definition: registry.hpp:559
void assign(const entity_type dst) const
Assigns the components of a prototype to a given entity.
Definition: prototype.hpp:317
basic_prototype(registry_type &ref)
Constructs a prototype that is bound to a given registry.
Definition: prototype.hpp:71
void operator()(registry_type &other, const entity_type dst) const ENTT_NOEXCEPT
Assigns the components of a prototype to an entity.
Definition: prototype.hpp:389
entity_type create() const
Creates a new entity using a given prototype.
Definition: prototype.hpp:266
constexpr auto null
Null entity.
Definition: entity.hpp:165
entity_type operator()() const ENTT_NOEXCEPT
Creates a new entity using a given prototype.
Definition: prototype.hpp:456
ENTT_ID_TYPE component_type
Unsigned integer type.
Definition: registry.hpp:312
Fast and reliable entity-component system.
Definition: fwd.hpp:14
auto try_get() ENTT_NOEXCEPT
Returns pointers to the given components.
Definition: prototype.hpp:217
void unset() ENTT_NOEXCEPT
Removes the given component from a prototype.
Definition: prototype.hpp:154
void assign_or_replace(registry_type &other, const entity_type dst) const
Assigns or replaces the components of a prototype for an entity.
Definition: prototype.hpp:340
void assign(registry_type &other, const entity_type dst) const
Assigns the components of a prototype to a given entity.
Definition: prototype.hpp:291
Prototype container for concepts.
Definition: fwd.hpp:38
const registry_type & backend() const ENTT_NOEXCEPT
Returns a reference to the underlying registry.
Definition: prototype.hpp:464
registry_type & backend() ENTT_NOEXCEPT
Returns a reference to the underlying registry.
Definition: prototype.hpp:469
entity_type operator()(registry_type &other) const ENTT_NOEXCEPT
Creates a new entity using a given prototype.
Definition: prototype.hpp:435
decltype(auto) get() const ENTT_NOEXCEPT
Returns references to the given components.
Definition: prototype.hpp:182
auto try_get() const ENTT_NOEXCEPT
Returns pointers to the given components.
Definition: prototype.hpp:206
bool has() const ENTT_NOEXCEPT
Checks if a prototype owns all the given components.
Definition: prototype.hpp:165
basic_prototype & operator=(basic_prototype &&other)
Move assignment operator.
Definition: prototype.hpp:110