EnTT 3.14.0
Loading...
Searching...
No Matches
observer.hpp
1#ifndef ENTT_ENTITY_OBSERVER_HPP
2#define ENTT_ENTITY_OBSERVER_HPP
3
4#include <cstddef>
5#include <cstdint>
6#include <limits>
7#include <type_traits>
8#include <utility>
9#include "../core/type_traits.hpp"
10#include "fwd.hpp"
11#include "storage.hpp"
12
13namespace entt {
14
16template<typename...>
17struct matcher {};
18
25template<typename...>
27
36template<>
44 template<typename... AllOf, typename... NoneOf>
45 static constexpr auto group(exclude_t<NoneOf...> = exclude_t{}) noexcept {
47 }
48
54 template<typename AnyOf>
55 static constexpr auto update() noexcept {
57 }
58};
59
68template<typename... Reject, typename... Require, typename... Rule, typename... Other>
69struct [[deprecated("use reactive mixin instead")]] basic_collector<matcher<type_list<Reject...>, type_list<Require...>, Rule...>, Other...> {
72
79 template<typename... AllOf, typename... NoneOf>
80 static constexpr auto group(exclude_t<NoneOf...> = exclude_t{}) noexcept {
81 return basic_collector<matcher<type_list<>, type_list<>, type_list<NoneOf...>, AllOf...>, current_type, Other...>{};
82 }
83
89 template<typename AnyOf>
90 static constexpr auto update() noexcept {
92 }
93
100 template<typename... AllOf, typename... NoneOf>
101 static constexpr auto where(exclude_t<NoneOf...> = exclude_t{}) noexcept {
102 using extended_type = matcher<type_list<Reject..., NoneOf...>, type_list<Require..., AllOf...>, Rule...>;
103 return basic_collector<extended_type, Other...>{};
104 }
105};
106
108inline constexpr basic_collector<> collector{};
109
159template<typename Registry, typename Allocator>
161 using mask_type = std::uint64_t;
163
164 template<std::size_t Index>
165 static void discard_if(storage_type &storage, Registry &, const typename Registry::entity_type entt) {
166 if(storage.contains(entt) && !(storage.get(entt) &= (~(1 << Index)))) {
168 }
169 }
170
171 template<typename>
172 struct matcher_handler;
173
174 template<typename... Reject, typename... Require, typename AnyOf>
175 struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, AnyOf>> {
176 template<std::size_t Index>
177 static void maybe_valid_if(storage_type &storage, Registry &parent, const typename Registry::entity_type entt) {
178 if(parent.template all_of<Require...>(entt) && !parent.template any_of<Reject...>(entt)) {
179 if(!storage.contains(entt)) {
181 }
182
183 storage.get(entt) |= (1 << Index);
184 }
185 }
186
187 template<std::size_t Index>
188 static void connect(storage_type &storage, Registry &parent) {
189 (parent.template on_destroy<Require>().template connect<&discard_if<Index>>(storage), ...);
190 (parent.template on_construct<Reject>().template connect<&discard_if<Index>>(storage), ...);
191 parent.template on_update<AnyOf>().template connect<&maybe_valid_if<Index>>(storage);
192 parent.template on_destroy<AnyOf>().template connect<&discard_if<Index>>(storage);
193 }
194
195 static void disconnect(storage_type &storage, Registry &parent) {
196 (parent.template on_destroy<Require>().disconnect(&storage), ...);
197 (parent.template on_construct<Reject>().disconnect(&storage), ...);
198 parent.template on_update<AnyOf>().disconnect(&storage);
199 parent.template on_destroy<AnyOf>().disconnect(&storage);
200 }
201 };
202
203 template<typename... Reject, typename... Require, typename... NoneOf, typename... AllOf>
204 struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, type_list<NoneOf...>, AllOf...>> {
205 template<std::size_t Index, typename... Ignore>
206 static void maybe_valid_if(storage_type &storage, Registry &parent, const typename Registry::entity_type entt) {
207 bool guard{};
208
209 if constexpr(sizeof...(Ignore) == 0) {
210 guard = parent.template all_of<AllOf..., Require...>(entt) && !parent.template any_of<NoneOf..., Reject...>(entt);
211 } else {
212 guard = parent.template all_of<AllOf..., Require...>(entt) && ((std::is_same_v<Ignore..., NoneOf> || !parent.template any_of<NoneOf>(entt)) && ...) && !parent.template any_of<Reject...>(entt);
213 }
214
215 if(guard) {
216 if(!storage.contains(entt)) {
218 }
219
220 storage.get(entt) |= (1 << Index);
221 }
222 }
223
224 template<std::size_t Index>
225 static void connect(storage_type &storage, Registry &parent) {
226 (parent.template on_destroy<Require>().template connect<&discard_if<Index>>(storage), ...);
227 (parent.template on_construct<Reject>().template connect<&discard_if<Index>>(storage), ...);
228 (parent.template on_construct<AllOf>().template connect<&maybe_valid_if<Index>>(storage), ...);
229 (parent.template on_destroy<NoneOf>().template connect<&maybe_valid_if<Index, NoneOf>>(storage), ...);
230 (parent.template on_destroy<AllOf>().template connect<&discard_if<Index>>(storage), ...);
231 (parent.template on_construct<NoneOf>().template connect<&discard_if<Index>>(storage), ...);
232 }
233
234 static void disconnect(storage_type &storage, Registry &parent) {
235 (parent.template on_destroy<Require>().disconnect(&storage), ...);
236 (parent.template on_construct<Reject>().disconnect(&storage), ...);
237 (parent.template on_construct<AllOf>().disconnect(&storage), ...);
238 (parent.template on_destroy<NoneOf>().disconnect(&storage), ...);
239 (parent.template on_destroy<AllOf>().disconnect(&storage), ...);
240 (parent.template on_construct<NoneOf>().disconnect(&storage), ...);
241 }
242 };
243
244 template<typename... Matcher>
245 static void disconnect(Registry &parent, storage_type &storage) {
246 (matcher_handler<Matcher>::disconnect(storage, parent), ...);
247 }
248
249 template<typename... Matcher, std::size_t... Index>
250 static void connect(Registry &parent, storage_type &storage, std::index_sequence<Index...>) {
251 static_assert(sizeof...(Matcher) < std::numeric_limits<mask_type>::digits, "Too many matchers");
252 (matcher_handler<Matcher>::template connect<Index>(storage, parent), ...);
253 }
254
255public:
257 using allocator_type = Allocator;
261 using entity_type = typename registry_type::entity_type;
263 using size_type = std::size_t;
265 using iterator = typename registry_type::common_type::iterator;
266
270
276 : release{},
277 parent{},
279
282
285
292 template<typename... Matcher>
294 : release{&basic_observer::disconnect<Matcher...>},
295 parent{&reg},
297 connect<Matcher...>(reg, storage, std::index_sequence_for<Matcher...>{});
298 }
299
301 ~basic_observer() = default;
302
308
314
320 template<typename... Matcher>
322 disconnect();
323 storage.clear();
324
325 parent = &reg;
326 release = &basic_observer::disconnect<Matcher...>;
327 connect<Matcher...>(reg, storage, std::index_sequence_for<Matcher...>{});
328 }
329
331 void disconnect() {
332 if(release) {
333 release(*parent, storage);
334 release = nullptr;
335 }
336 }
337
343 return storage.size();
344 }
345
351 return storage.empty();
352 }
353
367 return storage.data();
368 }
369
378 return storage.storage_type::base_type::begin();
379 }
380
387 return storage.storage_type::base_type::end();
388 }
389
392 storage.clear();
393 }
394
408 template<typename Func>
409 void each(Func func) const {
410 for(const auto entity: *this) {
411 func(entity);
412 }
413 }
414
424 template<typename Func>
425 void each(Func func) {
426 std::as_const(*this).each(std::move(func));
427 clear();
428 }
429
430private:
431 void (*release)(registry_type &, storage_type &);
432 registry_type *parent;
434};
435
436} // namespace entt
437
438#endif
bool empty() const noexcept
Checks whether an observer is empty.
Definition observer.hpp:350
typename registry_type::common_type::iterator iterator
Random access iterator type.
Definition observer.hpp:265
basic_observer()
Default constructor.
Definition observer.hpp:268
void clear() noexcept
Clears the underlying container.
Definition observer.hpp:391
iterator begin() const noexcept
Returns an iterator to the first entity of the observer.
Definition observer.hpp:377
typename registry_type::entity_type entity_type
Underlying entity identifier.
Definition observer.hpp:261
void connect(registry_type &reg, basic_collector< Matcher... >)
Connects an observer to a given registry.
Definition observer.hpp:321
basic_observer(const allocator_type &allocator)
Constructs an empty storage with a given allocator.
Definition observer.hpp:275
void disconnect()
Disconnects an observer from the registry it keeps track of.
Definition observer.hpp:331
basic_observer & operator=(basic_observer &&)=delete
Default move assignment operator, deleted on purpose.
basic_observer(basic_observer &&)=delete
Default move constructor, deleted on purpose.
void each(Func func)
Iterates entities and applies the given function object to them, then clears the observer.
Definition observer.hpp:425
~basic_observer()=default
Default destructor.
void each(Func func) const
Iterates entities and applies the given function object to them.
Definition observer.hpp:409
iterator end() const noexcept
Returns an iterator that is past the last entity of the observer.
Definition observer.hpp:386
basic_observer & operator=(const basic_observer &)=delete
Default copy assignment operator, deleted on purpose.
const entity_type * data() const noexcept
Direct access to the list of entities of the observer.
Definition observer.hpp:366
basic_observer(const basic_observer &)=delete
Default copy constructor, deleted on purpose.
std::size_t size_type
Unsigned integer type.
Definition observer.hpp:263
size_type size() const noexcept
Returns the number of elements in an observer.
Definition observer.hpp:342
basic_observer(registry_type &reg, basic_collector< Matcher... >, const allocator_type &allocator=allocator_type{})
Creates an observer and connects it to a given registry.
Definition observer.hpp:293
Allocator allocator_type
Allocator type.
Definition observer.hpp:257
void erase(const entity_type entt)
Erases an entity from a sparse set.
pointer data() const noexcept
Direct access to the internal packed array.
void clear()
Clears a sparse set.
size_type size() const noexcept
Returns the number of elements in a sparse set.
bool contains(const entity_type entt) const noexcept
Checks if a sparse set contains an entity.
bool empty() const noexcept
Checks whether a sparse set is empty.
const value_type & get(const entity_type entt) const noexcept
Returns the object assigned to an entity.
Definition storage.hpp:639
value_type & emplace(const entity_type entt, Args &&...args)
Assigns an entity to a storage and constructs its object.
Definition storage.hpp:675
EnTT default namespace.
Definition dense_map.hpp:22
entity
Default entity identifier.
Definition fwd.hpp:14
constexpr Type make_obj_using_allocator(const Allocator &allocator, Args &&...args)
Uses-allocator construction utility (waiting for C++20).
Definition memory.hpp:219
constexpr basic_collector collector
Variable template used to ease the definition of collectors.
Definition observer.hpp:108
static constexpr auto update() noexcept
Adds an observing matcher to the collector.
Definition observer.hpp:90
static constexpr auto group(exclude_t< NoneOf... >=exclude_t{}) noexcept
Adds a grouping matcher to the collector.
Definition observer.hpp:80
static constexpr auto where(exclude_t< NoneOf... >=exclude_t{}) noexcept
Updates the filter of the last added matcher.
Definition observer.hpp:101
static constexpr auto update() noexcept
Adds an observing matcher to the collector.
Definition observer.hpp:55
static constexpr auto group(exclude_t< NoneOf... >=exclude_t{}) noexcept
Adds a grouping matcher to the collector.
Definition observer.hpp:45
Alias for exclusion lists.
Definition fwd.hpp:141
Grouping matcher.
Definition observer.hpp:17
Provides a common way to define storage types.
Definition fwd.hpp:227
A class to use to push around lists of types, nothing more.