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"
52 template<
typename... AllOf,
typename... NoneOf>
62 template<
typename AnyOf>
63 static constexpr
auto replace() ENTT_NOEXCEPT {
76 template<
typename... Reject,
typename... Require,
typename... Rule,
typename... Other>
87 template<
typename... AllOf,
typename... NoneOf>
97 template<
typename AnyOf>
98 static constexpr
auto replace() ENTT_NOEXCEPT {
108 template<
typename... AllOf,
typename... NoneOf>
169 template<
typename Entity>
170 class basic_observer {
171 using payload_type = std::uint32_t;
174 struct matcher_handler;
176 template<
typename... Reject,
typename... Require,
typename AnyOf>
177 struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, AnyOf>> {
178 template<std::
size_t Index>
179 static void maybe_valid_if(
basic_observer &obs,
const basic_registry<Entity> ®,
const Entity
entt) {
180 if(reg.template has<Require...>(
entt) && !reg.template any<Reject...>(
entt)) {
181 if(
auto *comp = obs.view.try_get(
entt); !comp) {
182 obs.view.construct(
entt);
185 obs.view.get(
entt) |= (1 << Index);
189 template<std::
size_t Index>
190 static void discard_if(
basic_observer &obs,
const basic_registry<Entity> &,
const Entity
entt) {
191 if(
auto *value = obs.view.try_get(
entt); value && !(*value &= (~(1 << Index)))) {
192 obs.view.destroy(
entt);
196 template<std::
size_t Index>
197 static void connect(
basic_observer &obs, basic_registry<Entity> ®) {
198 (reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
199 (reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
200 reg.template on_replace<AnyOf>().template connect<&maybe_valid_if<Index>>(obs);
201 reg.template on_destroy<AnyOf>().template connect<&discard_if<Index>>(obs);
205 (reg.template on_destroy<Require>().disconnect(obs), ...);
206 (reg.template on_construct<Reject>().disconnect(obs), ...);
207 reg.template on_replace<AnyOf>().disconnect(obs);
208 reg.template on_destroy<AnyOf>().disconnect(obs);
212 template<
typename... Reject,
typename... Require,
typename... NoneOf,
typename... AllOf>
213 struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, type_list<NoneOf...>, AllOf...>> {
214 template<std::
size_t Index>
215 static void maybe_valid_if(
basic_observer &obs,
const basic_registry<Entity> ®,
const Entity
entt) {
216 if(reg.template has<AllOf..., Require...>(
entt) && !reg.template any<NoneOf..., Reject...>(
entt)) {
217 if(
auto *comp = obs.view.try_get(
entt); !comp) {
218 obs.view.construct(
entt);
221 obs.view.get(
entt) |= (1 << Index);
225 template<std::
size_t Index>
226 static void discard_if(
basic_observer &obs,
const basic_registry<Entity> &,
const Entity
entt) {
227 if(
auto *value = obs.view.try_get(
entt); value && !(*value &= (~(1 << Index)))) {
228 obs.view.destroy(
entt);
232 template<std::
size_t Index>
233 static void connect(
basic_observer &obs, basic_registry<Entity> ®) {
234 (reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
235 (reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
236 (reg.template on_construct<AllOf>().template connect<&maybe_valid_if<Index>>(obs), ...);
237 (reg.template on_destroy<NoneOf>().template connect<&maybe_valid_if<Index>>(obs), ...);
238 (reg.template on_destroy<AllOf>().template connect<&discard_if<Index>>(obs), ...);
239 (reg.template on_construct<NoneOf>().template connect<&discard_if<Index>>(obs), ...);
243 (reg.template on_destroy<Require>().disconnect(obs), ...);
244 (reg.template on_construct<Reject>().disconnect(obs), ...);
245 (reg.template on_construct<AllOf>().disconnect(obs), ...);
246 (reg.template on_destroy<NoneOf>().disconnect(obs), ...);
247 (reg.template on_destroy<AllOf>().disconnect(obs), ...);
248 (reg.template on_construct<NoneOf>().disconnect(obs), ...);
252 template<
typename... Matcher>
254 (matcher_handler<Matcher>::disconnect(obs, reg), ...);
257 template<
typename... Matcher, std::size_t... Index>
258 void connect(basic_registry<Entity> ®, std::index_sequence<Index...>) {
259 static_assert(
sizeof...(Matcher) < std::numeric_limits<payload_type>::digits);
260 (matcher_handler<Matcher>::template connect<Index>(*
this, reg), ...);
274 : target{}, release{}, view{}
287 template<
typename... Matcher>
293 connect<Matcher...>(reg, std::index_sequence_for<Matcher...>{});
316 template<
typename... Matcher>
319 connect<Matcher...>(reg, std::index_sequence_for<Matcher...>{});
327 release(*
this, *target);
373 return view.sparse_set<entity_type>::begin();
387 return view.sparse_set<entity_type>::end();
408 template<
typename Func>
410 static_assert(std::is_invocable_v<Func, entity_type>);
412 for(
const auto entity: *
this) {
426 template<
typename Func>
428 std::as_const(*this).each(std::move(func));