1 #ifndef ENTT_ENTITY_OBSERVER_HPP
2 #define ENTT_ENTITY_OBSERVER_HPP
10 #include "../config/config.h"
11 #include "../core/type_traits.hpp"
12 #include "registry.hpp"
13 #include "storage.hpp"
14 #include "utility.hpp"
53 template<
typename... AllOf,
typename... NoneOf>
63 template<
typename AnyOf>
64 static constexpr
auto update() ENTT_NOEXCEPT {
77 template<
typename... Reject,
typename... Require,
typename... Rule,
typename... Other>
88 template<
typename... AllOf,
typename... NoneOf>
98 template<
typename AnyOf>
99 static constexpr
auto update() ENTT_NOEXCEPT {
109 template<
typename... AllOf,
typename... NoneOf>
170 template<
typename Entity>
171 class basic_observer {
172 using payload_type = std::uint32_t;
175 struct matcher_handler;
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 basic_registry<Entity> ®,
const Entity
entt) {
181 if(reg.template has<Require...>(
entt) && !reg.template any<Reject...>(
entt)) {
182 if(
auto *comp = obs.view.try_get(
entt); !comp) {
183 obs.view.emplace(
entt);
186 obs.view.get(
entt) |= (1 << Index);
190 template<std::
size_t Index>
191 static void discard_if(
basic_observer &obs,
const basic_registry<Entity> &,
const Entity
entt) {
192 if(
auto *value = obs.view.try_get(
entt); value && !(*value &= (~(1 << Index)))) {
193 obs.view.erase(
entt);
197 template<std::
size_t Index>
198 static void connect(
basic_observer &obs, basic_registry<Entity> ®) {
199 (reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
200 (reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
201 reg.template on_update<AnyOf>().template connect<&maybe_valid_if<Index>>(obs);
202 reg.template on_destroy<AnyOf>().template connect<&discard_if<Index>>(obs);
206 (reg.template on_destroy<Require>().disconnect(obs), ...);
207 (reg.template on_construct<Reject>().disconnect(obs), ...);
208 reg.template on_update<AnyOf>().disconnect(obs);
209 reg.template on_destroy<AnyOf>().disconnect(obs);
213 template<
typename... Reject,
typename... Require,
typename... NoneOf,
typename... AllOf>
214 struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, type_list<NoneOf...>, AllOf...>> {
215 template<std::
size_t Index>
216 static void maybe_valid_if(
basic_observer &obs,
const basic_registry<Entity> ®,
const Entity
entt) {
217 if(reg.template has<AllOf..., Require...>(
entt) && !reg.template any<NoneOf..., Reject...>(
entt)) {
218 if(
auto *comp = obs.view.try_get(
entt); !comp) {
219 obs.view.emplace(
entt);
222 obs.view.get(
entt) |= (1 << Index);
226 template<std::
size_t Index>
227 static void discard_if(
basic_observer &obs,
const basic_registry<Entity> &,
const Entity
entt) {
228 if(
auto *value = obs.view.try_get(
entt); value && !(*value &= (~(1 << Index)))) {
229 obs.view.erase(
entt);
233 template<std::
size_t Index>
234 static void connect(
basic_observer &obs, basic_registry<Entity> ®) {
235 (reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
236 (reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
237 (reg.template on_construct<AllOf>().template connect<&maybe_valid_if<Index>>(obs), ...);
238 (reg.template on_destroy<NoneOf>().template connect<&maybe_valid_if<Index>>(obs), ...);
239 (reg.template on_destroy<AllOf>().template connect<&discard_if<Index>>(obs), ...);
240 (reg.template on_construct<NoneOf>().template connect<&discard_if<Index>>(obs), ...);
244 (reg.template on_destroy<Require>().disconnect(obs), ...);
245 (reg.template on_construct<Reject>().disconnect(obs), ...);
246 (reg.template on_construct<AllOf>().disconnect(obs), ...);
247 (reg.template on_destroy<NoneOf>().disconnect(obs), ...);
248 (reg.template on_destroy<AllOf>().disconnect(obs), ...);
249 (reg.template on_construct<NoneOf>().disconnect(obs), ...);
253 template<
typename... Matcher>
255 (matcher_handler<Matcher>::disconnect(obs, reg), ...);
258 template<
typename... Matcher, std::size_t... Index>
259 void connect(basic_registry<Entity> ®, std::index_sequence<Index...>) {
260 static_assert(
sizeof...(Matcher) < std::numeric_limits<payload_type>::digits,
"Too many matchers");
261 (matcher_handler<Matcher>::template connect<Index>(*
this, reg), ...);
275 : target{}, release{}, view{}
288 template<
typename... Matcher>
294 connect<Matcher...>(reg, std::index_sequence_for<Matcher...>{});
317 template<
typename... Matcher>
320 connect<Matcher...>(reg, std::index_sequence_for<Matcher...>{});
328 release(*
this, *target);
345 [[nodiscard]]
bool empty() const ENTT_NOEXCEPT {
374 return view.sparse_set<entity_type>::begin();
388 return view.sparse_set<entity_type>::end();
409 template<
typename Func>
411 for(
const auto entity: *
this) {
425 template<
typename Func>
427 std::as_const(*this).each(std::move(func));