EnTT 3.13.0
Loading...
Searching...
No Matches
mixin.hpp
1#ifndef ENTT_ENTITY_MIXIN_HPP
2#define ENTT_ENTITY_MIXIN_HPP
3
4#include <type_traits>
5#include <utility>
6#include "../config/config.h"
7#include "../core/any.hpp"
8#include "../signal/sigh.hpp"
9#include "entity.hpp"
10#include "fwd.hpp"
11
12namespace entt {
13
28template<typename Type, typename Registry>
29class basic_sigh_mixin final: public Type {
30 using underlying_type = Type;
31 using owner_type = Registry;
32
34 using sigh_type = sigh<void(owner_type &, const typename underlying_type::entity_type), typename underlying_type::allocator_type>;
35 using underlying_iterator = typename underlying_type::base_type::basic_iterator;
36
37 static_assert(std::is_base_of_v<basic_registry_type, owner_type>, "Invalid registry type");
38
39 owner_type &owner_or_assert() const noexcept {
40 ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
41 return static_cast<owner_type &>(*owner);
42 }
43
44 void pop(underlying_iterator first, underlying_iterator last) final {
45 if(auto &reg = owner_or_assert(); destruction.empty()) {
46 underlying_type::pop(first, last);
47 } else {
48 for(; first != last; ++first) {
49 const auto entt = *first;
50 destruction.publish(reg, entt);
51 const auto it = underlying_type::find(entt);
52 underlying_type::pop(it, it + 1u);
53 }
54 }
55 }
56
57 void pop_all() final {
58 if(auto &reg = owner_or_assert(); !destruction.empty()) {
59 for(auto it = underlying_type::base_type::begin(0), last = underlying_type::base_type::end(0); it != last; ++it) {
60 if constexpr(std::is_same_v<typename underlying_type::value_type, typename underlying_type::entity_type>) {
61 destruction.publish(reg, *it);
62 } else {
63 if constexpr(underlying_type::traits_type::in_place_delete) {
64 if(const auto entt = *it; entt != tombstone) {
65 destruction.publish(reg, entt);
66 }
67 } else {
68 destruction.publish(reg, *it);
69 }
70 }
71 }
72 }
73
74 underlying_type::pop_all();
75 }
76
77 underlying_iterator try_emplace(const typename underlying_type::entity_type entt, const bool force_back, const void *value) final {
78 const auto it = underlying_type::try_emplace(entt, force_back, value);
79
80 if(auto &reg = owner_or_assert(); it != underlying_type::base_type::end()) {
81 construction.publish(reg, *it);
82 }
83
84 return it;
85 }
86
87public:
89 using allocator_type = typename underlying_type::allocator_type;
91 using entity_type = typename underlying_type::entity_type;
93 using registry_type = owner_type;
94
98
103 explicit basic_sigh_mixin(const allocator_type &allocator)
104 : underlying_type{allocator},
105 owner{},
106 construction{allocator},
107 destruction{allocator},
108 update{allocator} {}
109
115 : underlying_type{std::move(other)},
116 owner{other.owner},
117 construction{std::move(other.construction)},
118 destruction{std::move(other.destruction)},
119 update{std::move(other.update)} {}
120
126 basic_sigh_mixin(basic_sigh_mixin &&other, const allocator_type &allocator) noexcept
127 : underlying_type{std::move(other), allocator},
128 owner{other.owner},
129 construction{std::move(other.construction), allocator},
130 destruction{std::move(other.destruction), allocator},
131 update{std::move(other.update), allocator} {}
132
139 underlying_type::operator=(std::move(other));
140 owner = other.owner;
141 construction = std::move(other.construction);
142 destruction = std::move(other.destruction);
143 update = std::move(other.update);
144 return *this;
145 }
146
151 void swap(basic_sigh_mixin &other) {
152 using std::swap;
153 underlying_type::swap(other);
154 swap(owner, other.owner);
155 swap(construction, other.construction);
156 swap(destruction, other.destruction);
157 swap(update, other.update);
158 }
159
171 [[nodiscard]] auto on_construct() noexcept {
172 return sink{construction};
173 }
174
186 [[nodiscard]] auto on_update() noexcept {
187 return sink{update};
188 }
189
201 [[nodiscard]] auto on_destroy() noexcept {
202 return sink{destruction};
203 }
204
214 auto emplace() {
215 const auto entt = underlying_type::emplace();
216 construction.publish(owner_or_assert(), entt);
217 return entt;
218 }
219
232 template<typename... Args>
233 decltype(auto) emplace(const entity_type hint, Args &&...args) {
234 if constexpr(std::is_same_v<typename underlying_type::value_type, typename underlying_type::entity_type>) {
235 const auto entt = underlying_type::emplace(hint, std::forward<Args>(args)...);
236 construction.publish(owner_or_assert(), entt);
237 return entt;
238 } else {
239 underlying_type::emplace(hint, std::forward<Args>(args)...);
240 construction.publish(owner_or_assert(), hint);
241 return this->get(hint);
242 }
243 }
244
252 template<typename... Func>
253 decltype(auto) patch(const entity_type entt, Func &&...func) {
254 underlying_type::patch(entt, std::forward<Func>(func)...);
255 update.publish(owner_or_assert(), entt);
256 return this->get(entt);
257 }
258
272 template<typename It, typename... Args>
273 void insert(It first, It last, Args &&...args) {
274 underlying_type::insert(first, last, std::forward<Args>(args)...);
275
276 if(auto &reg = owner_or_assert(); !construction.empty()) {
277 for(; first != last; ++first) {
278 construction.publish(reg, *first);
279 }
280 }
281 }
282
287 void bind(any value) noexcept final {
288 auto *reg = any_cast<basic_registry_type>(&value);
289 owner = reg ? reg : owner;
290 underlying_type::bind(std::move(value));
291 }
292
293private:
294 basic_registry_type *owner;
295 sigh_type construction;
296 sigh_type destruction;
297 sigh_type update;
298};
299
300} // namespace entt
301
302#endif
Fast and reliable entity-component system.
Definition registry.hpp:233
Mixin type used to add signal support to storage types.
Definition mixin.hpp:29
auto on_update() noexcept
Returns a sink object.
Definition mixin.hpp:186
typename underlying_type::entity_type entity_type
Underlying entity identifier.
Definition mixin.hpp:91
auto on_construct() noexcept
Returns a sink object.
Definition mixin.hpp:171
decltype(auto) patch(const entity_type entt, Func &&...func)
Patches the given instance for an entity.
Definition mixin.hpp:253
auto emplace()
Emplace elements into a storage.
Definition mixin.hpp:214
basic_sigh_mixin(basic_sigh_mixin &&other, const allocator_type &allocator) noexcept
Allocator-extended move constructor.
Definition mixin.hpp:126
typename underlying_type::allocator_type allocator_type
Allocator type.
Definition mixin.hpp:89
basic_sigh_mixin & operator=(basic_sigh_mixin &&other) noexcept
Move assignment operator.
Definition mixin.hpp:138
basic_sigh_mixin(const allocator_type &allocator)
Constructs an empty storage with a given allocator.
Definition mixin.hpp:103
owner_type registry_type
Expected registry type.
Definition mixin.hpp:93
decltype(auto) emplace(const entity_type hint, Args &&...args)
Emplace elements into a storage.
Definition mixin.hpp:233
basic_sigh_mixin()
Default constructor.
Definition mixin.hpp:96
void swap(basic_sigh_mixin &other)
Exchanges the contents with those of a given storage.
Definition mixin.hpp:151
basic_sigh_mixin(basic_sigh_mixin &&other) noexcept
Move constructor.
Definition mixin.hpp:114
void insert(It first, It last, Args &&...args)
Emplace elements into a storage.
Definition mixin.hpp:273
auto on_destroy() noexcept
Returns a sink object.
Definition mixin.hpp:201
void bind(any value) noexcept final
Forwards variables to derived classes, if any.
Definition mixin.hpp:287
Sink class.
Definition fwd.hpp:22
EnTT default namespace.
Definition dense_map.hpp:21
constexpr tombstone_t tombstone
Compile-time constant for tombstone entities.
Definition entity.hpp:372
constexpr get_t< Type... > get
Variable template for lists of observed components.
Definition fwd.hpp:157