EnTT  3.2.2
observer.hpp
1 #ifndef ENTT_ENTITY_OBSERVER_HPP
2 #define ENTT_ENTITY_OBSERVER_HPP
3 
4 
5 #include <limits>
6 #include <cstddef>
7 #include <cstdint>
8 #include <utility>
9 #include <algorithm>
10 #include <type_traits>
11 #include "../config/config.h"
12 #include "../core/type_traits.hpp"
13 #include "registry.hpp"
14 #include "storage.hpp"
15 #include "entity.hpp"
16 #include "fwd.hpp"
17 
18 
19 namespace entt {
20 
21 
23 template<typename...>
24 struct matcher {};
25 
26 
33 template<typename...>
35 
36 
45 template<>
53  template<typename... AllOf, typename... NoneOf>
54  static constexpr auto group(exclude_t<NoneOf...> = {}) ENTT_NOEXCEPT {
55  return basic_collector<matcher<type_list<>, type_list<>, type_list<NoneOf...>, AllOf...>>{};
56  }
57 
63  template<typename AnyOf>
64  static constexpr auto replace() ENTT_NOEXCEPT {
66  }
67 };
68 
77 template<typename... Reject, typename... Require, typename... Rule, typename... Other>
78 struct basic_collector<matcher<type_list<Reject...>, type_list<Require...>, Rule...>, Other...> {
80  using current_type = matcher<type_list<Reject...>, type_list<Require...>, Rule...>;
81 
88  template<typename... AllOf, typename... NoneOf>
89  static constexpr auto group(exclude_t<NoneOf...> = {}) ENTT_NOEXCEPT {
90  return basic_collector<matcher<type_list<>, type_list<>, type_list<NoneOf...>, AllOf...>, current_type, Other...>{};
91  }
92 
98  template<typename AnyOf>
99  static constexpr auto replace() ENTT_NOEXCEPT {
100  return basic_collector<matcher<type_list<>, type_list<>, AnyOf>, current_type, Other...>{};
101  }
102 
109  template<typename... AllOf, typename... NoneOf>
110  static constexpr auto where(exclude_t<NoneOf...> = {}) ENTT_NOEXCEPT {
111  using extended_type = matcher<type_list<Reject..., NoneOf...>, type_list<Require..., AllOf...>, Rule...>;
112  return basic_collector<extended_type, Other...>{};
113  }
114 };
115 
116 
119 
120 
170 template<typename Entity>
171 class basic_observer {
172  using payload_type = std::uint32_t;
173 
174  template<typename>
175  struct matcher_handler;
176 
177  template<typename... Reject, typename... Require, typename AnyOf>
178  struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, AnyOf>> {
179  template<std::size_t Index>
180  static void maybe_valid_if(basic_observer &obs, const Entity entt, const basic_registry<Entity> &reg) {
181  if(reg.template has<Require...>(entt) && !(reg.template has<Reject>(entt) || ...)) {
182  auto *comp = obs.view.try_get(entt);
183  (comp ? *comp : obs.view.construct(entt)) |= (1 << Index);
184  }
185  }
186 
187  template<std::size_t Index>
188  static void discard_if(basic_observer &obs, const Entity entt) {
189  if(auto *value = obs.view.try_get(entt); value && !(*value &= (~(1 << Index)))) {
190  obs.view.destroy(entt);
191  }
192  }
193 
194  template<std::size_t Index>
195  static void connect(basic_observer &obs, basic_registry<Entity> &reg) {
196  (reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
197  (reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
198  reg.template on_replace<AnyOf>().template connect<&maybe_valid_if<Index>>(obs);
199  reg.template on_destroy<AnyOf>().template connect<&discard_if<Index>>(obs);
200  }
201 
202  static void disconnect(basic_observer &obs, basic_registry<Entity> &reg) {
203  (reg.template on_destroy<Require>().disconnect(obs), ...);
204  (reg.template on_construct<Reject>().disconnect(obs), ...);
205  reg.template on_replace<AnyOf>().disconnect(obs);
206  reg.template on_destroy<AnyOf>().disconnect(obs);
207  }
208  };
209 
210  template<typename... Reject, typename... Require, typename... NoneOf, typename... AllOf>
211  struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, type_list<NoneOf...>, AllOf...>> {
212  template<std::size_t Index>
213  static void maybe_valid_if(basic_observer &obs, const Entity entt, const basic_registry<Entity> &reg) {
214  if(reg.template has<AllOf..., Require...>(entt) && !(reg.template has<NoneOf>(entt) || ...) && !(reg.template has<Reject>(entt) || ...)) {
215  auto *comp = obs.view.try_get(entt);
216  (comp ? *comp : obs.view.construct(entt)) |= (1 << Index);
217  }
218  }
219 
220  template<std::size_t Index>
221  static void discard_if(basic_observer &obs, const Entity entt) {
222  if(auto *value = obs.view.try_get(entt); value && !(*value &= (~(1 << Index)))) {
223  obs.view.destroy(entt);
224  }
225  }
226 
227  template<std::size_t Index>
228  static void connect(basic_observer &obs, basic_registry<Entity> &reg) {
229  (reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
230  (reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
231  (reg.template on_construct<AllOf>().template connect<&maybe_valid_if<Index>>(obs), ...);
232  (reg.template on_destroy<NoneOf>().template connect<&maybe_valid_if<Index>>(obs), ...);
233  (reg.template on_destroy<AllOf>().template connect<&discard_if<Index>>(obs), ...);
234  (reg.template on_construct<NoneOf>().template connect<&discard_if<Index>>(obs), ...);
235  }
236 
237  static void disconnect(basic_observer &obs, basic_registry<Entity> &reg) {
238  (reg.template on_destroy<Require>().disconnect(obs), ...);
239  (reg.template on_construct<Reject>().disconnect(obs), ...);
240  (reg.template on_construct<AllOf>().disconnect(obs), ...);
241  (reg.template on_destroy<NoneOf>().disconnect(obs), ...);
242  (reg.template on_destroy<AllOf>().disconnect(obs), ...);
243  (reg.template on_construct<NoneOf>().disconnect(obs), ...);
244  }
245  };
246 
247  template<typename... Matcher>
248  static void disconnect(basic_observer &obs, basic_registry<Entity> &reg) {
249  (matcher_handler<Matcher>::disconnect(obs, reg), ...);
250  }
251 
252  template<typename... Matcher, std::size_t... Index>
253  void connect(basic_registry<Entity> &reg, std::index_sequence<Index...>) {
254  static_assert(sizeof...(Matcher) < std::numeric_limits<payload_type>::digits);
255  (matcher_handler<Matcher>::template connect<Index>(*this, reg), ...);
256  release = &basic_observer::disconnect<Matcher...>;
257  }
258 
259 public:
261  using entity_type = Entity;
263  using size_type = std::size_t;
266 
268  basic_observer() ENTT_NOEXCEPT
269  : target{}, release{}, view{}
270  {}
271 
273  basic_observer(const basic_observer &) = delete;
275  basic_observer(basic_observer &&) = delete;
276 
282  template<typename... Matcher>
284  : target{&reg},
285  release{},
286  view{}
287  {
288  connect<Matcher...>(reg, std::index_sequence_for<Matcher...>{});
289  }
290 
292  ~basic_observer() = default;
293 
298  basic_observer & operator=(const basic_observer &) = delete;
299 
304  basic_observer & operator=(basic_observer &&) = delete;
305 
311  template<typename... Matcher>
313  disconnect();
314  connect<Matcher...>(reg, std::index_sequence_for<Matcher...>{});
315  target = &reg;
316  view.reset();
317  }
318 
320  void disconnect() {
321  if(release) {
322  release(*this, *target);
323  release = nullptr;
324  }
325  }
326 
331  size_type size() const ENTT_NOEXCEPT {
332  return view.size();
333  }
334 
339  bool empty() const ENTT_NOEXCEPT {
340  return view.empty();
341  }
342 
355  const entity_type * data() const ENTT_NOEXCEPT {
356  return view.data();
357  }
358 
367  iterator_type begin() const ENTT_NOEXCEPT {
368  return view.sparse_set<entity_type>::begin();
369  }
370 
381  iterator_type end() const ENTT_NOEXCEPT {
382  return view.sparse_set<entity_type>::end();
383  }
384 
386  void clear() {
387  view.reset();
388  }
389 
404  template<typename Func>
405  void each(Func func) const {
406  static_assert(std::is_invocable_v<Func, entity_type>);
407  std::for_each(begin(), end(), std::move(func));
408  }
409 
424  template<typename Func>
425  void each(Func func) {
426  std::as_const(*this).each(std::move(func));
427  clear();
428  }
429 
430 private:
432  void(* release)(basic_observer &, basic_registry<entity_type> &);
434 };
435 
436 
437 }
438 
439 
440 #endif // ENTT_ENTITY_OBSERVER_HPP
entt::basic_observer
Observer.
Definition: fwd.hpp:29
entt::type_list
A class to use to push around lists of types, nothing more.
Definition: type_traits.hpp:42
entt::basic_collector<>
Collector.
Definition: observer.hpp:46
entt::basic_observer::basic_observer
basic_observer() ENTT_NOEXCEPT
Default constructor.
Definition: observer.hpp:268
entt::basic_observer::end
iterator_type end() const ENTT_NOEXCEPT
Returns an iterator that is past the last entity of the observer.
Definition: observer.hpp:381
entt::matcher
Grouping matcher.
Definition: observer.hpp:24
entt::basic_observer::each
void each(Func func)
Iterates entities and applies the given function object to them, then clears the observer.
Definition: observer.hpp:425
entt::basic_observer::empty
bool empty() const ENTT_NOEXCEPT
Checks whether an observer is empty.
Definition: observer.hpp:339
entt::exclude_t
Alias for exclusion lists.
Definition: utility.hpp:16
entt::basic_observer::entity_type
Entity entity_type
Underlying entity identifier.
Definition: observer.hpp:261
entt::basic_observer::begin
iterator_type begin() const ENTT_NOEXCEPT
Returns an iterator to the first entity of the observer.
Definition: observer.hpp:367
entt::basic_collector< matcher< type_list< Reject... >, type_list< Require... >, Rule... >, Other... >::where
static constexpr auto where(exclude_t< NoneOf... >={}) ENTT_NOEXCEPT
Updates the filter of the last added matcher.
Definition: observer.hpp:110
entt::basic_observer::each
void each(Func func) const
Iterates entities and applies the given function object to them, then clears the observer.
Definition: observer.hpp:405
entt::basic_observer::basic_observer
basic_observer(basic_registry< entity_type > &reg, basic_collector< Matcher... >) ENTT_NOEXCEPT
Creates an observer and connects it to a given registry.
Definition: observer.hpp:283
entt
EnTT default namespace.
Definition: algorithm.hpp:12
entt::basic_observer::data
const entity_type * data() const ENTT_NOEXCEPT
Direct access to the list of entities of the observer.
Definition: observer.hpp:355
entt::storage< entity_type, payload_type >
entt::basic_collector
Collector.
Definition: observer.hpp:34
entt::basic_observer::~basic_observer
~basic_observer()=default
Default destructor.
entt::collector
constexpr basic_collector collector
Variable template used to ease the definition of collectors.
Definition: observer.hpp:118
entt::basic_observer::size_type
std::size_t size_type
Unsigned integer type.
Definition: observer.hpp:263
entt::basic_collector< matcher< type_list< Reject... >, type_list< Require... >, Rule... >, Other... >::group
static constexpr auto group(exclude_t< NoneOf... >={}) ENTT_NOEXCEPT
Adds a grouping matcher to the collector.
Definition: observer.hpp:89
entt::basic_registry< entity_type >
entt::basic_collector<>::group
static constexpr auto group(exclude_t< NoneOf... >={}) ENTT_NOEXCEPT
Adds a grouping matcher to the collector.
Definition: observer.hpp:54
entt::basic_observer::clear
void clear()
Resets the underlying container.
Definition: observer.hpp:386
entt::basic_observer::connect
void connect(basic_registry< entity_type > &reg, basic_collector< Matcher... >)
Connects an observer to a given registry.
Definition: observer.hpp:312
entt::basic_collector<>::replace
static constexpr auto replace() ENTT_NOEXCEPT
Adds an observing matcher to the collector.
Definition: observer.hpp:64
entt::basic_view
View.
Definition: fwd.hpp:17
entt::basic_collector< matcher< type_list< Reject... >, type_list< Require... >, Rule... >, Other... >::replace
static constexpr auto replace() ENTT_NOEXCEPT
Adds an observing matcher to the collector.
Definition: observer.hpp:99
entt::basic_observer::operator=
basic_observer & operator=(const basic_observer &)=delete
Default copy assignment operator, deleted on purpose.
entt::basic_observer::size
size_type size() const ENTT_NOEXCEPT
Returns the number of elements in an observer.
Definition: observer.hpp:331
entt::sparse_set::iterator_type
iterator iterator_type
Random access iterator type.
Definition: sparse_set.hpp:182
entt::basic_observer::disconnect
void disconnect()
Disconnects an observer from the registry it keeps track of.
Definition: observer.hpp:320
entt::basic_observer::iterator_type
typename sparse_set< Entity >::iterator_type iterator_type
Input iterator type.
Definition: observer.hpp:265