registry: component signals return only the entity

This commit is contained in:
Michele Caini
2020-09-10 12:24:06 +02:00
parent 8c403f8795
commit 9da15826db
5 changed files with 66 additions and 65 deletions

View File

@@ -177,8 +177,8 @@ 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 basic_registry<Entity> &reg, const Entity entt) {
if(reg.template has<Require...>(entt) && !reg.template any<Reject...>(entt)) {
static void maybe_valid_if(basic_observer &obs, const Entity entt) {
if(obs.target->template has<Require...>(entt) && !obs.target->template any<Reject...>(entt)) {
if(auto *comp = obs.view.try_get(entt); !comp) {
obs.view.emplace(entt);
}
@@ -188,7 +188,7 @@ class basic_observer {
}
template<std::size_t Index>
static void discard_if(basic_observer &obs, const basic_registry<Entity> &, const Entity entt) {
static void discard_if(basic_observer &obs, const Entity entt) {
if(auto *value = obs.view.try_get(entt); value && !(*value &= (~(1 << Index)))) {
obs.view.erase(entt);
}
@@ -213,12 +213,12 @@ 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, typename... Ignore>
static void maybe_valid_if(basic_observer &obs, const basic_registry<Entity> &reg, const Entity entt) {
if([&reg, entt]() {
static void maybe_valid_if(basic_observer &obs, const Entity entt) {
if([&obs, entt]() {
if constexpr(sizeof...(Ignore) == 0) {
return reg.template has<AllOf..., Require...>(entt) && !reg.template any<NoneOf..., Reject...>(entt);
return obs.target->template has<AllOf..., Require...>(entt) && !obs.target->template any<NoneOf..., Reject...>(entt);
} else {
return reg.template has<AllOf..., Require...>(entt) && ((std::is_same_v<Ignore..., NoneOf> || !reg.template any<NoneOf>(entt)) && ...) && !reg.template any<Reject...>(entt);
return obs.target->template has<AllOf..., Require...>(entt) && ((std::is_same_v<Ignore..., NoneOf> || !obs.target->template any<NoneOf>(entt)) && ...) && !obs.target->template any<Reject...>(entt);
}
}())
{
@@ -231,7 +231,7 @@ class basic_observer {
}
template<std::size_t Index>
static void discard_if(basic_observer &obs, const basic_registry<Entity> &, const Entity entt) {
static void discard_if(basic_observer &obs, const Entity entt) {
if(auto *value = obs.view.try_get(entt); value && !(*value &= (~(1 << Index)))) {
obs.view.erase(entt);
}

View File

@@ -60,9 +60,9 @@ class basic_registry {
}
template<typename... Args>
decltype(auto) emplace(basic_registry &owner, const Entity entt, Args &&... args) {
decltype(auto) emplace(const Entity entt, Args &&... args) {
storage<entity_type, Component>::emplace(entt, std::forward<Args>(args)...);
construction.publish(owner, entt);
construction.publish(entt);
if constexpr(!is_eto_eligible_v<Component>) {
return this->get(entt);
@@ -70,57 +70,57 @@ class basic_registry {
}
template<typename It, typename... Args>
void insert(basic_registry &owner, It first, It last, Args &&... args) {
void insert(It first, It last, Args &&... args) {
storage<entity_type, Component>::insert(first, last, std::forward<Args>(args)...);
if(!construction.empty()) {
while(first != last) { construction.publish(owner, *(first++)); }
while(first != last) { construction.publish(*(first++)); }
}
}
void remove(basic_registry &owner, const Entity entt) {
destruction.publish(owner, entt);
void remove(const Entity entt) {
destruction.publish(entt);
this->erase(entt);
}
template<typename It>
void remove(basic_registry &owner, It first, It last) {
void remove(It first, It last) {
if(std::distance(first, last) == std::distance(this->begin(), this->end())) {
if(!destruction.empty()) {
while(first != last) { destruction.publish(owner, *(first++)); }
while(first != last) { destruction.publish(*(first++)); }
}
this->clear();
} else {
while(first != last) { this->remove(owner, *(first++)); }
while(first != last) { this->remove(*(first++)); }
}
}
template<typename... Func>
decltype(auto) patch(basic_registry &owner, const Entity entt, [[maybe_unused]] Func &&... func) {
decltype(auto) patch(const Entity entt, [[maybe_unused]] Func &&... func) {
if constexpr(is_eto_eligible_v<Component>) {
update.publish(owner, entt);
update.publish(entt);
} else {
(std::forward<Func>(func)(this->get(entt)), ...);
update.publish(owner, entt);
update.publish(entt);
return this->get(entt);
}
}
decltype(auto) replace(basic_registry &owner, const Entity entt, Component component) {
return patch(owner, entt, [&component](auto &&curr) { curr = std::move(component); });
decltype(auto) replace(const Entity entt, Component component) {
return patch(entt, [&component](auto &&curr) { curr = std::move(component); });
}
private:
sigh<void(basic_registry &, const Entity)> construction{};
sigh<void(basic_registry &, const Entity)> destruction{};
sigh<void(basic_registry &, const Entity)> update{};
sigh<void(const Entity)> construction{};
sigh<void(const Entity)> destruction{};
sigh<void(const Entity)> update{};
};
struct pool_data {
id_type type_id{};
std::unique_ptr<sparse_set<Entity>> pool{};
void(* remove)(sparse_set<Entity> &, basic_registry &, const Entity){};
void(* remove)(sparse_set<Entity> &, const Entity){};
};
template<typename...>
@@ -130,14 +130,19 @@ class basic_registry {
struct group_handler<exclude_t<Exclude...>, get_t<Get...>, Owned...> {
static_assert(std::conjunction_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>>...>, "One or more component types are invalid");
std::conditional_t<sizeof...(Owned) == 0, sparse_set<Entity>, std::size_t> current{};
basic_registry *owner;
group_handler(basic_registry &parent)
: owner{&parent}
{}
template<typename Component>
void maybe_valid_if(basic_registry &owner, const Entity entt) {
[[maybe_unused]] const auto cpools = std::forward_as_tuple(owner.assure<Owned>()...);
void maybe_valid_if(const Entity entt) {
[[maybe_unused]] const auto cpools = std::forward_as_tuple(owner->assure<Owned>()...);
const auto is_valid = ((std::is_same_v<Component, Owned> || std::get<pool_handler<Owned> &>(cpools).contains(entt)) && ...)
&& ((std::is_same_v<Component, Get> || owner.assure<Get>().contains(entt)) && ...)
&& ((std::is_same_v<Component, Exclude> || !owner.assure<Exclude>().contains(entt)) && ...);
&& ((std::is_same_v<Component, Get> || owner->assure<Get>().contains(entt)) && ...)
&& ((std::is_same_v<Component, Exclude> || !owner->assure<Exclude>().contains(entt)) && ...);
if constexpr(sizeof...(Owned) == 0) {
if(is_valid && !current.contains(entt)) {
@@ -151,13 +156,13 @@ class basic_registry {
}
}
void discard_if([[maybe_unused]] basic_registry &owner, const Entity entt) {
void discard_if(const Entity entt) {
if constexpr(sizeof...(Owned) == 0) {
if(current.contains(entt)) {
current.erase(entt);
}
} else {
if(const auto cpools = std::forward_as_tuple(owner.assure<Owned>()...); std::get<0>(cpools).contains(entt) && (std::get<0>(cpools).index(entt) < current)) {
if(const auto cpools = std::forward_as_tuple(owner->assure<Owned>()...); std::get<0>(cpools).contains(entt) && (std::get<0>(cpools).index(entt) < current)) {
const auto pos = --current;
(std::get<pool_handler<Owned> &>(cpools).swap(std::get<pool_handler<Owned> &>(cpools).data()[pos], entt), ...);
}
@@ -192,8 +197,8 @@ class basic_registry {
if(auto &&pdata = pools[index]; !pdata.pool) {
pdata.type_id = type_info<Component>::id();
pdata.pool.reset(new pool_handler<Component>());
pdata.remove = [](sparse_set<entity_type> &target, basic_registry &owner, const entity_type entt) {
static_cast<pool_handler<Component> &>(target).remove(owner, entt);
pdata.remove = [](sparse_set<entity_type> &target, const entity_type entt) {
static_cast<pool_handler<Component> &>(target).remove(entt);
};
}
@@ -203,8 +208,8 @@ class basic_registry {
cpool = pools.emplace_back(pool_data{
type_info<Component>::id(),
std::unique_ptr<sparse_set<entity_type>>{new pool_handler<Component>()},
[](sparse_set<entity_type> &target, basic_registry &owner, const entity_type entt) {
static_cast<pool_handler<Component> &>(target).remove(owner, entt);
[](sparse_set<entity_type> &target, const entity_type entt) {
static_cast<pool_handler<Component> &>(target).remove(entt);
}
}).pool.get();
} else {
@@ -644,7 +649,7 @@ public:
template<typename Component, typename... Args>
decltype(auto) emplace(const entity_type entity, Args &&... args) {
ENTT_ASSERT(valid(entity));
return assure<Component>().emplace(*this, entity, std::forward<Args>(args)...);
return assure<Component>().emplace(entity, std::forward<Args>(args)...);
}
/**
@@ -661,7 +666,7 @@ public:
template<typename Component, typename It>
void insert(It first, It last, const Component &value = {}) {
ENTT_ASSERT(std::all_of(first, last, [this](const auto entity) { return valid(entity); }));
assure<Component>().insert(*this, first, last, value);
assure<Component>().insert(first, last, value);
}
/**
@@ -681,7 +686,7 @@ public:
void insert(EIt first, EIt last, CIt from, CIt to) {
static_assert(std::is_constructible_v<Component, typename std::iterator_traits<CIt>::value_type>, "Invalid value type");
ENTT_ASSERT(std::all_of(first, last, [this](const auto entity) { return valid(entity); }));
assure<Component>().insert(*this, first, last, from, to);
assure<Component>().insert(first, last, from, to);
}
/**
@@ -712,8 +717,8 @@ public:
auto &cpool = assure<Component>();
return cpool.contains(entity)
? cpool.replace(*this, entity, Component{std::forward<Args>(args)...})
: cpool.emplace(*this, entity, std::forward<Args>(args)...);
? cpool.replace(entity, Component{std::forward<Args>(args)...})
: cpool.emplace(entity, std::forward<Args>(args)...);
}
/**
@@ -746,7 +751,7 @@ public:
template<typename Component, typename... Func>
decltype(auto) patch(const entity_type entity, Func &&... func) {
ENTT_ASSERT(valid(entity));
return assure<Component>().patch(*this, entity, std::forward<Func>(func)...);
return assure<Component>().patch(entity, std::forward<Func>(func)...);
}
/**
@@ -771,7 +776,7 @@ public:
*/
template<typename Component, typename... Args>
decltype(auto) replace(const entity_type entity, Args &&... args) {
return assure<Component>().replace(*this, entity, Component{std::forward<Args>(args)...});
return assure<Component>().replace(entity, Component{std::forward<Args>(args)...});
}
/**
@@ -790,7 +795,7 @@ public:
template<typename... Component>
void remove(const entity_type entity) {
ENTT_ASSERT(valid(entity));
(assure<Component>().remove(*this, entity), ...);
(assure<Component>().remove(entity), ...);
}
/**
@@ -806,7 +811,7 @@ public:
template<typename... Component, typename It>
void remove(It first, It last) {
ENTT_ASSERT(std::all_of(first, last, [this](const auto entity) { return valid(entity); }));
(assure<Component>().remove(*this, first, last), ...);
(assure<Component>().remove(first, last), ...);
}
/**
@@ -834,7 +839,7 @@ public:
ENTT_ASSERT(valid(entity));
return ([this, entity](auto &&cpool) {
return cpool.contains(entity) ? (cpool.remove(*this, entity), true) : false;
return cpool.contains(entity) ? (cpool.remove(entity), true) : false;
}(assure<Component>()) + ... + size_type{});
}
@@ -859,7 +864,7 @@ public:
for(auto pos = pools.size(); pos; --pos) {
if(auto &pdata = pools[pos-1]; pdata.pool && pdata.pool->contains(entity)) {
pdata.remove(*pdata.pool, *this, entity);
pdata.remove(*pdata.pool, entity);
}
}
}
@@ -966,7 +971,7 @@ public:
[[nodiscard]] decltype(auto) get_or_emplace(const entity_type entity, Args &&... args) {
ENTT_ASSERT(valid(entity));
auto &cpool = assure<Component>();
return cpool.contains(entity) ? cpool.get(entity) : cpool.emplace(*this, entity, std::forward<Args>(args)...);
return cpool.contains(entity) ? cpool.get(entity) : cpool.emplace(entity, std::forward<Args>(args)...);
}
/**
@@ -1015,7 +1020,7 @@ public:
each([this](const auto entity) { this->destroy(entity); });
} else {
([this](auto &&cpool) {
cpool.remove(*this, cpool.sparse_set<entity_type>::begin(), cpool.sparse_set<entity_type>::end());
cpool.remove(cpool.sparse_set<entity_type>::begin(), cpool.sparse_set<entity_type>::end());
}(assure<Component>()), ...);
}
}
@@ -1308,7 +1313,7 @@ public:
if(!handler) {
group_data candidate = {
size,
{ new handler_type{}, [](void *instance) { delete static_cast<handler_type *>(instance); } },
{ new handler_type{*this}, [](void *instance) { delete static_cast<handler_type *>(instance); } },
[]([[maybe_unused]] const id_type ctype) ENTT_NOEXCEPT { return ((ctype == type_info<std::decay_t<Owned>>::id()) || ...); },
[]([[maybe_unused]] const id_type ctype) ENTT_NOEXCEPT { return ((ctype == type_info<std::decay_t<Get>>::id()) || ...); },
[]([[maybe_unused]] const id_type ctype) ENTT_NOEXCEPT { return ((ctype == type_info<Exclude>::id()) || ...); },
@@ -1356,7 +1361,7 @@ public:
} else {
// we cannot iterate backwards because we want to leave behind valid entities in case of owned types
for(auto *first = std::get<0>(cpools).data(), *last = first + std::get<0>(cpools).size(); first != last; ++first) {
handler->template maybe_valid_if<std::tuple_element_t<0, std::tuple<std::decay_t<Owned>...>>>(*this, *first);
handler->template maybe_valid_if<std::tuple_element_t<0, std::tuple<std::decay_t<Owned>...>>>(*first);
}
}
}

View File

@@ -570,7 +570,7 @@ TEST(NonOwningGroup, FrontBack) {
TEST(NonOwningGroup, SignalRace) {
entt::registry registry;
registry.on_construct<double>().connect<&entt::registry::emplace_or_replace<int>>();
registry.on_construct<double>().connect<&entt::registry::emplace_or_replace<int>>(registry);
const auto group = registry.group(entt::get<int, double>);
auto entity = registry.create();
@@ -1227,7 +1227,7 @@ TEST(OwningGroup, FrontBack) {
TEST(OwningGroup, SignalRace) {
entt::registry registry;
registry.on_construct<double>().connect<&entt::registry::emplace_or_replace<int>>();
registry.on_construct<double>().connect<&entt::registry::emplace_or_replace<int>>(registry);
const auto group = registry.group<int>(entt::get<double>);
auto entity = registry.create();

View File

@@ -33,7 +33,7 @@ TEST(Helper, Invoke) {
entt::registry registry;
const auto entity = registry.create();
registry.on_construct<clazz>().connect<entt::invoke<&clazz::func>>();
registry.on_construct<clazz>().connect<entt::invoke<&clazz::func>>(registry);
registry.emplace<clazz>(entity);
ASSERT_EQ(entity, registry.get<clazz>(entity).entt);

View File

@@ -27,17 +27,13 @@ struct listener {
}
template<typename Component>
void incr(const entt::registry &registry, entt::entity entity) {
ASSERT_TRUE(registry.valid(entity));
ASSERT_TRUE(registry.has<Component>(entity));
void incr(entt::entity entity) {
last = entity;
++counter;
}
template<typename Component>
void decr(const entt::registry &registry, entt::entity entity) {
ASSERT_TRUE(registry.valid(entity));
ASSERT_TRUE(registry.has<Component>(entity));
void decr(entt::entity entity) {
last = entity;
--counter;
}
@@ -1378,8 +1374,8 @@ TEST(Registry, Dependencies) {
constexpr auto emplace_or_replace = &entt::registry::emplace_or_replace<double>;
constexpr auto remove = &entt::registry::remove<double>;
registry.on_construct<int>().connect<emplace_or_replace>();
registry.on_destroy<int>().connect<remove>();
registry.on_construct<int>().connect<emplace_or_replace>(registry);
registry.on_destroy<int>().connect<remove>(registry);
registry.emplace<double>(entity, .3);
ASSERT_FALSE(registry.has<int>(entity));
@@ -1394,8 +1390,8 @@ TEST(Registry, Dependencies) {
ASSERT_FALSE((registry.any<int, double>(entity)));
registry.on_construct<int>().disconnect<emplace_or_replace>();
registry.on_destroy<int>().disconnect<remove>();
registry.on_construct<int>().disconnect<emplace_or_replace>(registry);
registry.on_destroy<int>().disconnect<remove>(registry);
registry.emplace<int>(entity);
ASSERT_TRUE((registry.any<int, double>(entity)));
@@ -1404,7 +1400,7 @@ TEST(Registry, Dependencies) {
TEST(Registry, StableEmplace) {
entt::registry registry;
registry.on_construct<int>().connect<&listener::sort<int>>();
registry.on_construct<int>().connect<&listener::sort<int>>(registry);
registry.emplace<int>(registry.create(), 0);
ASSERT_EQ(registry.emplace<int>(registry.create(), 1), 1);