sigh_storage_mixin:
* Owner as template parameter (to make it reusable in other contexts) * Use storage payload for retrieving the owner from the storage
This commit is contained in:
@@ -20,7 +20,7 @@ namespace entt {
|
||||
template<typename Entity>
|
||||
struct Storage: type_list<
|
||||
type_info() const ENTT_NOEXCEPT,
|
||||
void(basic_registry<Entity> &, const Entity *, const Entity *)
|
||||
void(const Entity *, const Entity *)
|
||||
> {
|
||||
/*! @brief Underlying entity identifier. */
|
||||
using entity_type = Entity;
|
||||
@@ -43,14 +43,13 @@ struct Storage: type_list<
|
||||
|
||||
/**
|
||||
* @brief Removes entities from a storage.
|
||||
* @param owner The registry that issued the request.
|
||||
* @param first An iterator to the first element of the range of
|
||||
* entities.
|
||||
* @param last An iterator past the last element of the range of
|
||||
* entities.
|
||||
*/
|
||||
void remove(basic_registry<entity_type> &owner, const entity_type *first, const entity_type *last) {
|
||||
poly_call<1>(*this, owner, first, last);
|
||||
void remove(const entity_type *first, const entity_type *last) {
|
||||
poly_call<1>(*this, first, last);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -573,7 +573,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)...);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -590,7 +590,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -610,7 +610,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -639,8 +639,8 @@ public:
|
||||
auto *cpool = assure<Component>();
|
||||
|
||||
return cpool->contains(entity)
|
||||
? cpool->patch(*this, entity, [&args...](auto &curr) { curr = Component{std::forward<Args>(args)...}; })
|
||||
: cpool->emplace(*this, entity, std::forward<Args>(args)...);
|
||||
? cpool->patch(entity, [&args...](auto &curr) { curr = Component{std::forward<Args>(args)...}; })
|
||||
: cpool->emplace(entity, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -670,7 +670,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)...);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -692,7 +692,7 @@ public:
|
||||
*/
|
||||
template<typename Component, typename... Args>
|
||||
decltype(auto) replace(const entity_type entity, Args &&... args) {
|
||||
return assure<Component>()->patch(*this, entity, [&args...](auto &curr) { curr = Component{std::forward<Args>(args)...}; });
|
||||
return assure<Component>()->patch(entity, [&args...](auto &curr) { curr = Component{std::forward<Args>(args)...}; });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -709,7 +709,7 @@ public:
|
||||
void remove(const entity_type entity) {
|
||||
ENTT_ASSERT(valid(entity));
|
||||
static_assert(sizeof...(Component) > 0, "Provide one or more component types");
|
||||
(assure<Component>()->remove(*this, entity), ...);
|
||||
(assure<Component>()->remove(entity), ...);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -726,7 +726,7 @@ public:
|
||||
void remove(It first, It last) {
|
||||
ENTT_ASSERT(std::all_of(first, last, [this](const auto entity) { return valid(entity); }));
|
||||
static_assert(sizeof...(Component) > 0, "Provide one or more component types");
|
||||
(assure<Component>()->remove(*this, first, last), ...);
|
||||
(assure<Component>()->remove(first, last), ...);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -752,7 +752,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{});
|
||||
}
|
||||
|
||||
@@ -776,7 +776,7 @@ public:
|
||||
|
||||
for(auto pos = pools.size(); pos; --pos) {
|
||||
if(auto &pdata = pools[pos-1]; pdata.pool && pdata.pool->contains(entity)) {
|
||||
pdata.poly->remove(*this, std::begin(wrap), std::end(wrap));
|
||||
pdata.poly->remove(std::begin(wrap), std::end(wrap));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -874,7 +874,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)...);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -926,7 +926,7 @@ public:
|
||||
each([this](const auto entity) { this->destroy(entity); });
|
||||
} else {
|
||||
([this](auto *cpool) {
|
||||
cpool->remove(*this, cpool->basic_sparse_set<entity_type>::begin(), cpool->basic_sparse_set<entity_type>::end());
|
||||
cpool->remove(cpool->basic_sparse_set<entity_type>::begin(), cpool->basic_sparse_set<entity_type>::end());
|
||||
}(assure<Component>()), ...);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -562,9 +562,15 @@ public:
|
||||
/**
|
||||
* @brief Mixin type to use to add signal support to storage types.
|
||||
* @tparam Type The type of the underlying storage.
|
||||
* @tparam Owner Expected owner type.
|
||||
*/
|
||||
template<typename Type>
|
||||
struct sigh_storage_mixin: Type {
|
||||
template<typename Type, typename Owner>
|
||||
class sigh_storage_mixin: public Type {
|
||||
Owner & owner() ENTT_NOEXCEPT {
|
||||
return *static_cast<Owner *>(payload());
|
||||
}
|
||||
|
||||
public:
|
||||
/*! @brief Underlying value type. */
|
||||
using value_type = typename Type::value_type;
|
||||
/*! @brief Underlying entity identifier. */
|
||||
@@ -640,15 +646,14 @@ struct sigh_storage_mixin: Type {
|
||||
/**
|
||||
* @copybrief storage_adapter_mixin::emplace
|
||||
* @tparam Args Types of arguments to use to construct the object.
|
||||
* @param owner The registry that issued the request.
|
||||
* @param entity A valid entity identifier.
|
||||
* @param args Parameters to use to initialize the object.
|
||||
* @return A reference to the newly created object.
|
||||
*/
|
||||
template<typename... Args>
|
||||
decltype(auto) emplace(basic_registry<entity_type> &owner, const entity_type entity, Args &&... args) {
|
||||
decltype(auto) emplace(const entity_type entity, Args &&... args) {
|
||||
Type::emplace(entity, std::forward<Args>(args)...);
|
||||
construction.publish(owner, entity);
|
||||
construction.publish(owner(), entity);
|
||||
|
||||
if constexpr(!std::is_same_v<storage_category, empty_storage_tag>) {
|
||||
return this->get(entity);
|
||||
@@ -660,45 +665,42 @@ struct sigh_storage_mixin: Type {
|
||||
* @tparam It Type of input iterator.
|
||||
* @tparam Args Types of arguments to use to construct the objects
|
||||
* associated with the entities.
|
||||
* @param owner The registry that issued the request.
|
||||
* @param first An iterator to the first element of the range of entities.
|
||||
* @param last An iterator past the last element of the range of entities.
|
||||
* @param args Parameters to use to initialize the objects associated with
|
||||
* the entities.
|
||||
*/
|
||||
template<typename It, typename... Args>
|
||||
void insert(basic_registry<entity_type> &owner, It first, It last, Args &&... args) {
|
||||
void insert(It first, It last, Args &&... args) {
|
||||
Type::insert(first, last, std::forward<Args>(args)...);
|
||||
|
||||
if(!construction.empty()) {
|
||||
for(; first != last; ++first) {
|
||||
construction.publish(owner, *first);
|
||||
construction.publish(owner(), *first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @copybrief storage_adapter_mixin::remove
|
||||
* @param owner The registry that issued the request.
|
||||
* @param entity A valid entity identifier.
|
||||
*/
|
||||
void remove(basic_registry<entity_type> &owner, const entity_type entity) {
|
||||
destruction.publish(owner, entity);
|
||||
void remove(const entity_type entity) {
|
||||
destruction.publish(owner(), entity);
|
||||
Type::remove(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copybrief storage_adapter_mixin::remove
|
||||
* @tparam It Type of input iterator.
|
||||
* @param owner The registry that issued the request.
|
||||
* @param first An iterator to the first element of the range of entities.
|
||||
* @param last An iterator past the last element of the range of entities.
|
||||
*/
|
||||
template<typename It>
|
||||
void remove(basic_registry<entity_type> &owner, It first, It last) {
|
||||
void remove(It first, It last) {
|
||||
if(!destruction.empty()) {
|
||||
for(auto it = first; it != last; ++it) {
|
||||
destruction.publish(owner, *it);
|
||||
destruction.publish(owner(), *it);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -708,18 +710,17 @@ struct sigh_storage_mixin: Type {
|
||||
/**
|
||||
* @copybrief storage_adapter_mixin::patch
|
||||
* @tparam Func Types of the function objects to invoke.
|
||||
* @param owner The registry that issued the request.
|
||||
* @param entity A valid entity identifier.
|
||||
* @param func Valid function objects.
|
||||
* @return A reference to the patched instance.
|
||||
*/
|
||||
template<typename... Func>
|
||||
decltype(auto) patch(basic_registry<entity_type> &owner, const entity_type entity, [[maybe_unused]] Func &&... func) {
|
||||
decltype(auto) patch(const entity_type entity, [[maybe_unused]] Func &&... func) {
|
||||
if constexpr(std::is_same_v<storage_category, empty_storage_tag>) {
|
||||
update.publish(owner, entity);
|
||||
update.publish(owner(), entity);
|
||||
} else {
|
||||
Type::patch(entity, std::forward<Func>(func)...);
|
||||
update.publish(owner, entity);
|
||||
update.publish(owner(), entity);
|
||||
return this->get(entity);
|
||||
}
|
||||
}
|
||||
@@ -747,7 +748,7 @@ private:
|
||||
template<typename Entity, typename Type, typename = void>
|
||||
struct storage_traits {
|
||||
/*! @brief Resulting type after component-to-storage conversion. */
|
||||
using storage_type = sigh_storage_mixin<basic_storage<Entity, Type>>;
|
||||
using storage_type = sigh_storage_mixin<basic_storage<Entity, Type>, entt::basic_registry<Entity>>;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@ template<typename Entity>
|
||||
struct PolyStorage: entt::type_list_cat_t<
|
||||
decltype(as_type_list(std::declval<entt::Storage<Entity>>())),
|
||||
entt::type_list<
|
||||
void(entt::basic_registry<Entity> &, const Entity, const void *),
|
||||
void(const Entity, const void *),
|
||||
const void *(const Entity) const,
|
||||
void(const entt::basic_registry<Entity> &, entt::basic_registry<Entity> &) const
|
||||
void(entt::basic_registry<Entity> &) const
|
||||
>
|
||||
> {
|
||||
using entity_type = Entity;
|
||||
@@ -23,30 +23,30 @@ struct PolyStorage: entt::type_list_cat_t<
|
||||
struct type: entt::Storage<Entity>::template type<Base> {
|
||||
static constexpr auto base = std::tuple_size_v<typename entt::poly_vtable<entt::Storage<Entity>>::type>;
|
||||
|
||||
void emplace(entt::basic_registry<entity_type> &owner, const entity_type entity, const void *instance) {
|
||||
entt::poly_call<base + 0>(*this, owner, entity, instance);
|
||||
void emplace(const entity_type entity, const void *instance) {
|
||||
entt::poly_call<base + 0>(*this, entity, instance);
|
||||
}
|
||||
|
||||
const void * get(const entity_type entity) const {
|
||||
return entt::poly_call<base + 1>(*this, entity);
|
||||
}
|
||||
|
||||
void copy(const entt::basic_registry<Entity> &owner, entt::basic_registry<Entity> &other) const {
|
||||
entt::poly_call<base + 2>(*this, owner, other);
|
||||
void copy_to(entt::basic_registry<Entity> &other) const {
|
||||
entt::poly_call<base + 2>(*this, other);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
struct members {
|
||||
static void emplace(Type &self, entt::basic_registry<entity_type> &owner, const entity_type entity, const void *instance) {
|
||||
self.emplace(owner, entity, *static_cast<const typename Type::value_type *>(instance));
|
||||
static void emplace(Type &self, const entity_type entity, const void *instance) {
|
||||
self.emplace(entity, *static_cast<const typename Type::value_type *>(instance));
|
||||
}
|
||||
|
||||
static const typename Type::value_type * get(const Type &self, const entity_type entity) {
|
||||
return &self.get(entity);
|
||||
}
|
||||
|
||||
static void copy(const Type &self, const entt::basic_registry<entity_type> &owner, entt::basic_registry<entity_type> &other) {
|
||||
static void copy_to(const Type &self, entt::basic_registry<entity_type> &other) {
|
||||
other.template insert<typename Type::value_type>(self.data(), self.data() + self.size(), self.raw(), self.raw() + self.size());
|
||||
}
|
||||
};
|
||||
@@ -57,7 +57,7 @@ struct PolyStorage: entt::type_list_cat_t<
|
||||
entt::value_list<
|
||||
&members<Type>::emplace,
|
||||
&members<Type>::get,
|
||||
&members<Type>::copy
|
||||
&members<Type>::copy_to
|
||||
>
|
||||
>;
|
||||
};
|
||||
@@ -80,7 +80,7 @@ TEST(PolyStorage, CopyEntity) {
|
||||
|
||||
registry.visit(entity, [&](const auto info) {
|
||||
auto &&storage = registry.storage(info);
|
||||
storage->emplace(registry, other, storage->get(entity));
|
||||
storage->emplace(other, storage->get(entity));
|
||||
});
|
||||
|
||||
ASSERT_TRUE((registry.all_of<int, char>(entity)));
|
||||
@@ -103,7 +103,7 @@ TEST(PolyStorage, CopyRegistry) {
|
||||
ASSERT_EQ(other.size(), 0u);
|
||||
|
||||
other.assign(registry.data(), registry.data() + registry.size(), registry.destroyed());
|
||||
registry.visit([&](const auto info) { std::as_const(registry).storage(info)->copy(registry, other); });
|
||||
registry.visit([&](const auto info) { std::as_const(registry).storage(info)->copy_to(other); });
|
||||
|
||||
ASSERT_EQ(registry.size(), other.size());
|
||||
ASSERT_EQ((registry.view<int, char>().size_hint()), (other.view<int, char>().size_hint()));
|
||||
@@ -125,11 +125,11 @@ TEST(PolyStorage, Constness) {
|
||||
// cannot invoke remove on a const storage, let's copy the returned value
|
||||
auto cstorage = cregistry.storage(entt::type_id<int>());
|
||||
|
||||
ASSERT_DEATH(cstorage->remove(registry, std::begin(entity), std::end(entity)), ".*");
|
||||
ASSERT_DEATH(cstorage->remove(std::begin(entity), std::end(entity)), ".*");
|
||||
ASSERT_TRUE(registry.all_of<int>(entity[0]));
|
||||
|
||||
auto &&storage = registry.storage(entt::type_id<int>());
|
||||
storage->remove(registry, std::begin(entity), std::end(entity));
|
||||
storage->remove(std::begin(entity), std::end(entity));
|
||||
|
||||
ASSERT_FALSE(registry.all_of<int>(entity[0]));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user