registry: callbacks receive the registry as first argument (better dependencies)

This commit is contained in:
Michele Caini
2020-01-20 16:09:25 +01:00
parent f558797246
commit 6f696a026b
7 changed files with 35 additions and 34 deletions

1
TODO
View File

@@ -19,6 +19,7 @@
* any-of rule for views/groups (eg entity has A and any of B/C/D)
- get -> all, exclude -> none
* deprecate sigh::publish, use operator()
* merge entity/helper and entt/utility
* WIP: snapshot rework/deprecation
- remove snapshot/loader from registry, make them external (faster) tools

View File

@@ -333,7 +333,7 @@ The function type of a listener for the construction and destruction signals
should be equivalent to the following:
```cpp
void(entt::entity, entt::registry &);
void(entt::registry &, entt::entity);
```
In both cases, listeners are provided with the registry that triggered the
@@ -342,7 +342,7 @@ The function type of a listener that observes changes to components is slightly
different instead:
```cpp
void(entt::entity, entt::registry &, Component &);
void(entt::registry &, entt::entity, Component &);
```
In this case, `Component` is intuitively the type of component of interest. The
@@ -600,26 +600,27 @@ the other things.
### Dependencies
The `registry` class is designed to create short circuits between its functions.
This makes easy to define dependencies between different operations.<br/>
The `registry` class is designed to be able to create short circuits between its
functions. This simplifies the definition of _dependencies_ between different
operations.<br/>
For example, the following adds (or replaces) the component `a_type` whenever
`my_type` is assigned to an entity:
```cpp
registry.on_construct<my_type>().connect<&entt::registry::assign_or_replace<a_type>>(registry);
registry.on_construct<my_type>().connect<&entt::registry::assign_or_replace<a_type>>();
```
Similarly, the code shown below removes `a_type` from an entity whenever
`my_type` is assigned to it:
```cpp
registry.on_construct<my_type>().connect<&entt::registry::remove<a_type>>(registry);
registry.on_construct<my_type>().connect<&entt::registry::remove<a_type>>();
```
A dependency can also be easily broken as follows:
```cpp
registry.on_construct<my_type>().disconnect<&entt::registry::assign_or_replace<a_type>>(registry);
registry.on_construct<my_type>().disconnect<&entt::registry::assign_or_replace<a_type>>();
```
There are many other types of dependencies. In general, all functions that

View File

@@ -4,7 +4,6 @@
#include <type_traits>
#include "../config/config.h"
#include "../signal/sigh.hpp"
#include "registry.hpp"

View File

@@ -177,7 +177,7 @@ class basic_observer {
template<typename... Reject, typename... Require, typename AnyOf>
struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, AnyOf>> {
template<std::size_t Index>
static void maybe_valid_if(basic_observer &obs, const Entity entt, const basic_registry<Entity> &reg) {
static void maybe_valid_if(basic_observer &obs, const basic_registry<Entity> &reg, const Entity entt) {
if(reg.template has<Require...>(entt) && !(reg.template has<Reject>(entt) || ...)) {
if(auto *comp = obs.view.try_get(entt); !comp) {
obs.view.construct(entt);
@@ -188,7 +188,7 @@ class basic_observer {
}
template<std::size_t Index>
static void discard_if(basic_observer &obs, const Entity entt) {
static void discard_if(basic_observer &obs, const basic_registry<Entity> &, const Entity entt) {
if(auto *value = obs.view.try_get(entt); value && !(*value &= (~(1 << Index)))) {
obs.view.destroy(entt);
}
@@ -213,7 +213,7 @@ class basic_observer {
template<typename... Reject, typename... Require, typename... NoneOf, typename... AllOf>
struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, type_list<NoneOf...>, AllOf...>> {
template<std::size_t Index>
static void maybe_valid_if(basic_observer &obs, const Entity entt, const basic_registry<Entity> &reg) {
static void maybe_valid_if(basic_observer &obs, const basic_registry<Entity> &reg, const Entity entt) {
if(reg.template has<AllOf..., Require...>(entt) && !(reg.template has<NoneOf>(entt) || ...) && !(reg.template has<Reject>(entt) || ...)) {
if(auto *comp = obs.view.try_get(entt); !comp) {
obs.view.construct(entt);
@@ -224,7 +224,7 @@ class basic_observer {
}
template<std::size_t Index>
static void discard_if(basic_observer &obs, const Entity entt) {
static void discard_if(basic_observer &obs, const basic_registry<Entity> &, const Entity entt) {
if(auto *value = obs.view.try_get(entt); value && !(*value &= (~(1 << Index)))) {
obs.view.destroy(entt);
}

View File

@@ -69,7 +69,7 @@ class basic_registry {
template<typename... Args>
decltype(auto) assign(basic_registry &owner, const Entity entt, Args &&... args) {
this->construct(entt, std::forward<Args>(args)...);
construction.publish(entt, owner);
construction.publish(owner, entt);
return this->get(entt);
}
@@ -80,12 +80,12 @@ class basic_registry {
(func(this->raw() + this->size() - std::distance(first, last)), ...);
if(!construction.empty()) {
std::for_each(first, last, [this, &owner](const auto entt) { construction.publish(entt, owner); });
std::for_each(first, last, [this, &owner](const auto entt) { construction.publish(owner, entt); });
}
}
void remove(basic_registry &owner, const Entity entt) {
destruction.publish(entt, owner);
destruction.publish(owner, entt);
this->destroy(entt);
}
@@ -93,7 +93,7 @@ class basic_registry {
void remove(basic_registry &owner, It first, It last) {
if(std::distance(first, last) == std::distance(this->begin(), this->end())) {
if(!destruction.empty()) {
std::for_each(first, last, [this, &owner](const auto entt) { destruction.publish(entt, owner); });
std::for_each(first, last, [this, &owner](const auto entt) { destruction.publish(owner, entt); });
}
this->clear();
@@ -106,14 +106,14 @@ class basic_registry {
template<typename... Args>
decltype(auto) replace(basic_registry &owner, const Entity entt, Args &&... args) {
Component component{std::forward<Args>(args)...};
update.publish(entt, owner, component);
update.publish(owner, entt, component);
return (this->get(entt) = std::move(component));
}
private:
sigh<void(const Entity, basic_registry &)> construction{};
sigh<void(const Entity, basic_registry &)> destruction{};
sigh<void(const Entity, basic_registry &, decltype(std::declval<storage<Entity, Component>>().get({})))> update{};
sigh<void(basic_registry &, const Entity)> construction{};
sigh<void(basic_registry &, const Entity)> destruction{};
sigh<void(basic_registry &, const Entity, decltype(std::declval<storage<Entity, Component>>().get({})))> update{};
};
struct pool_data {
@@ -133,7 +133,7 @@ class basic_registry {
std::conditional_t<sizeof...(Owned) == 0, sparse_set<Entity>, std::size_t> current{};
template<typename Component>
void maybe_valid_if(const Entity entt, basic_registry &owner) {
void maybe_valid_if(basic_registry &owner, const Entity entt) {
static_assert(std::disjunction_v<std::is_same<Owned, std::decay_t<Owned>>..., std::is_same<Get, std::decay_t<Get>>..., std::is_same<Exclude, std::decay_t<Exclude>>...>);
[[maybe_unused]] const auto cpools = std::forward_as_tuple(owner.assure<Owned>()...);
@@ -153,7 +153,7 @@ class basic_registry {
}
}
void discard_if(const Entity entt, basic_registry &owner) {
void discard_if([[maybe_unused]] basic_registry &owner, const Entity entt) {
if constexpr(sizeof...(Owned) == 0) {
if(current.has(entt)) {
current.destroy(entt);
@@ -1021,7 +1021,7 @@ public:
* The function type for a listener is equivalent to:
*
* @code{.cpp}
* void(Entity, registry<Entity> &);
* void(registry<Entity> &, Entity);
* @endcode
*
* Listeners are invoked **after** the component has been assigned to the
@@ -1052,7 +1052,7 @@ public:
* The function type for a listener is equivalent to:
*
* @code{.cpp}
* void(Entity, registry<Entity> &, Component &);
* void(registry<Entity> &, Entity, Component &);
* @endcode
*
* Listeners are invoked **before** the component has been replaced.
@@ -1083,7 +1083,7 @@ public:
* The function type for a listener is equivalent to:
*
* @code{.cpp}
* void(Entity, registry<Entity> &);
* void(registry<Entity> &, Entity);
* @endcode
*
* Listeners are invoked **before** the component has been removed from the

View File

@@ -492,7 +492,7 @@ TEST(NonOwningGroup, Less) {
TEST(NonOwningGroup, SignalRace) {
entt::registry registry;
registry.on_construct<double>().connect<&entt::registry::assign_or_replace<int>>(registry);
registry.on_construct<double>().connect<&entt::registry::assign_or_replace<int>>();
registry.group(entt::get<int, double>);
auto entity = registry.create();
@@ -1068,7 +1068,7 @@ TEST(OwningGroup, Less) {
TEST(OwningGroup, SignalRace) {
entt::registry registry;
registry.on_construct<double>().connect<&entt::registry::assign_or_replace<int>>(registry);
registry.on_construct<double>().connect<&entt::registry::assign_or_replace<int>>();
registry.group<int>(entt::get<double>);
auto entity = registry.create();

View File

@@ -14,12 +14,12 @@ struct empty_type {};
struct listener {
template<typename Component>
static void sort(entt::entity, entt::registry &registry) {
static void sort(entt::registry &registry) {
registry.sort<Component>([](auto lhs, auto rhs) { return lhs < rhs; });
}
template<typename Component>
void incr(entt::entity entity, entt::registry &registry) {
void incr(const entt::registry &registry, entt::entity entity) {
ASSERT_TRUE(registry.valid(entity));
ASSERT_TRUE(registry.has<Component>(entity));
last = entity;
@@ -27,7 +27,7 @@ struct listener {
}
template<typename Component>
void decr(entt::entity entity, entt::registry &registry) {
void decr(const entt::registry &registry, entt::entity entity) {
ASSERT_TRUE(registry.valid(entity));
ASSERT_TRUE(registry.has<Component>(entity));
last = entity;
@@ -1562,8 +1562,8 @@ TEST(Registry, Dependencies) {
constexpr auto assign_or_replace = &entt::registry::assign_or_replace<double>;
constexpr auto remove = &entt::registry::remove<double>;
registry.on_construct<int>().connect<assign_or_replace>(registry);
registry.on_destroy<int>().connect<remove>(registry);
registry.on_construct<int>().connect<assign_or_replace>();
registry.on_destroy<int>().connect<remove>();
registry.assign<double>(entity, .3);
ASSERT_FALSE(registry.has<int>(entity));
@@ -1579,8 +1579,8 @@ TEST(Registry, Dependencies) {
ASSERT_FALSE(registry.has<int>(entity));
ASSERT_FALSE(registry.has<double>(entity));
registry.on_construct<int>().disconnect<assign_or_replace>(registry);
registry.on_destroy<int>().disconnect<remove>(registry);
registry.on_construct<int>().disconnect<assign_or_replace>();
registry.on_destroy<int>().disconnect<remove>();
registry.assign<int>(entity);
ASSERT_TRUE(registry.has<int>(entity));