entity:
* sparse_set: added optional user data to ::remove and ::clear * sparse_set: remove the payload, it was really meh * storage: review sigh_storage_mixin, simplified storage_adapter_mixin * registry: pass itself twhen adding/patchin/removing components test: updated tests for sparse set and poly storage examples: added a test to avoid regressions on storage_adapter_mixin
This commit is contained in:
@@ -115,7 +115,6 @@ class basic_registry {
|
||||
if(auto &&pdata = pools[index]; !pdata.pool) {
|
||||
pdata.pool.reset(new storage_type<Component>());
|
||||
pdata.poly = std::ref(*static_cast<storage_type<Component> *>(pdata.pool.get()));
|
||||
pdata.pool->payload(this);
|
||||
}
|
||||
|
||||
return static_cast<storage_type<Component> *>(pools[index].pool.get());
|
||||
@@ -186,38 +185,11 @@ public:
|
||||
/*! @brief Default constructor. */
|
||||
basic_registry() = default;
|
||||
|
||||
/**
|
||||
* @brief Move constructor.
|
||||
* @param other The instance to move from.
|
||||
*/
|
||||
basic_registry(basic_registry &&other) ENTT_NOEXCEPT
|
||||
: vars(std::move(other.vars)), // we can't use {} here, thanks to GCC
|
||||
pools{std::move(other.pools)},
|
||||
groups{std::move(other.groups)},
|
||||
entities{std::move(other.entities)},
|
||||
available{other.available}
|
||||
{
|
||||
rebind_pools();
|
||||
}
|
||||
/*! @brief Default move constructor. */
|
||||
basic_registry(basic_registry &&) = default;
|
||||
|
||||
/**
|
||||
* @brief Move assignment operator.
|
||||
* @param other The instance to assign from.
|
||||
* @return This registry.
|
||||
*/
|
||||
basic_registry & operator=(basic_registry &&other) ENTT_NOEXCEPT {
|
||||
if(this != &other) {
|
||||
vars = std::move(other.vars);
|
||||
pools = std::move(other.pools);
|
||||
groups = std::move(other.groups);
|
||||
entities = std::move(other.entities);
|
||||
available = other.available;
|
||||
|
||||
rebind_pools();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
/*! @brief Default move assignment operator. @return This registry. */
|
||||
basic_registry & operator=(basic_registry &&) = default;
|
||||
|
||||
/**
|
||||
* @brief Prepares a pool for the given type if required.
|
||||
@@ -573,7 +545,7 @@ public:
|
||||
template<typename Component, typename... Args>
|
||||
decltype(auto) emplace(const entity_type entity, Args &&... args) {
|
||||
ENTT_ASSERT(valid(entity));
|
||||
return assure<Component>()->emplace(entity, std::forward<Args>(args)...);
|
||||
return assure<Component>()->emplace(*this, entity, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -590,7 +562,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(first, last, value);
|
||||
assure<Component>()->insert(*this, first, last, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -610,7 +582,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(first, last, from, to);
|
||||
assure<Component>()->insert(*this, first, last, from, to);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -639,8 +611,8 @@ public:
|
||||
auto *cpool = assure<Component>();
|
||||
|
||||
return cpool->contains(entity)
|
||||
? cpool->patch(entity, [&args...](auto &... curr) { ((curr = Component{std::forward<Args>(args)...}), ...); })
|
||||
: cpool->emplace(entity, std::forward<Args>(args)...);
|
||||
? cpool->patch(*this, entity, [&args...](auto &... curr) { ((curr = Component{std::forward<Args>(args)...}), ...); })
|
||||
: cpool->emplace(*this, entity, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -670,7 +642,7 @@ public:
|
||||
template<typename Component, typename... Func>
|
||||
decltype(auto) patch(const entity_type entity, Func &&... func) {
|
||||
ENTT_ASSERT(valid(entity));
|
||||
return assure<Component>()->patch(entity, std::forward<Func>(func)...);
|
||||
return assure<Component>()->patch(*this, entity, std::forward<Func>(func)...);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -692,7 +664,7 @@ public:
|
||||
*/
|
||||
template<typename Component, typename... Args>
|
||||
decltype(auto) replace(const entity_type entity, Args &&... args) {
|
||||
return assure<Component>()->patch(entity, [&args...](auto &... curr) { ((curr = Component{std::forward<Args>(args)...}), ...); });
|
||||
return assure<Component>()->patch(*this, entity, [&args...](auto &... curr) { ((curr = Component{std::forward<Args>(args)...}), ...); });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -709,7 +681,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(entity), ...);
|
||||
(assure<Component>()->remove(entity, this), ...);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -726,7 +698,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(first, last), ...);
|
||||
(assure<Component>()->remove(first, last, this), ...);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -751,8 +723,8 @@ public:
|
||||
size_type remove_if_exists(const entity_type entity) {
|
||||
ENTT_ASSERT(valid(entity));
|
||||
|
||||
return ([entity](auto *cpool) {
|
||||
return cpool->contains(entity) ? (cpool->remove(entity), true) : false;
|
||||
return ([this, entity](auto *cpool) {
|
||||
return cpool->contains(entity) ? (cpool->remove(entity, this), true) : false;
|
||||
}(assure<Component>()) + ... + size_type{});
|
||||
}
|
||||
|
||||
@@ -776,7 +748,7 @@ public:
|
||||
|
||||
for(auto pos = pools.size(); pos; --pos) {
|
||||
if(auto &pdata = pools[pos-1]; pdata.pool && pdata.pool->contains(entity)) {
|
||||
pdata.pool->remove(std::begin(wrap), std::end(wrap));
|
||||
pdata.pool->remove(std::begin(wrap), std::end(wrap), this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -874,7 +846,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(entity, std::forward<Args>(args)...);
|
||||
return cpool->contains(entity) ? cpool->get(entity) : cpool->emplace(*this, entity, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -924,14 +896,14 @@ public:
|
||||
if constexpr(sizeof...(Component) == 0) {
|
||||
for(auto pos = pools.size(); pos; --pos) {
|
||||
if(auto &pdata = pools[pos-1]; pdata.pool) {
|
||||
pdata.pool->clear();
|
||||
pdata.pool->clear(this);
|
||||
}
|
||||
}
|
||||
|
||||
each([this](const auto entity) { release_entity(entity, version(entity) + 1u); });
|
||||
} else {
|
||||
([](auto *cpool) {
|
||||
cpool->remove(cpool->basic_sparse_set<entity_type>::begin(), cpool->basic_sparse_set<entity_type>::end());
|
||||
([this](auto *cpool) {
|
||||
cpool->remove(cpool->basic_sparse_set<entity_type>::begin(), cpool->basic_sparse_set<entity_type>::end(), this);
|
||||
}(assure<Component>()), ...);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ protected:
|
||||
virtual void swap_at(const std::size_t, const std::size_t) {}
|
||||
|
||||
/*! @brief Attempts to remove an entity from the internal packed array. */
|
||||
virtual void swap_and_pop(const std::size_t) {}
|
||||
virtual void swap_and_pop(const std::size_t, void *) {}
|
||||
|
||||
public:
|
||||
/*! @brief Underlying entity identifier. */
|
||||
@@ -432,13 +432,14 @@ public:
|
||||
* results in undefined behavior.
|
||||
*
|
||||
* @param entt A valid entity identifier.
|
||||
* @param ud Optional user data that are forwarded as-is to derived classes.
|
||||
*/
|
||||
void remove(const entity_type entt) {
|
||||
void remove(const entity_type entt, void *ud = nullptr) {
|
||||
ENTT_ASSERT(contains(entt));
|
||||
auto &ref = sparse[page(entt)][offset(entt)];
|
||||
|
||||
// last chance to use the entity for derived classes and mixins, if any
|
||||
swap_and_pop(size_type{to_integral(ref)});
|
||||
swap_and_pop(size_type{to_integral(ref)}, ud);
|
||||
|
||||
const auto other = packed.back();
|
||||
sparse[page(other)][offset(other)] = ref;
|
||||
@@ -455,11 +456,12 @@ public:
|
||||
* @tparam It Type of input iterator.
|
||||
* @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 ud Optional user data that are forwarded as-is to derived classes.
|
||||
*/
|
||||
template<typename It>
|
||||
void remove(It first, It last) {
|
||||
void remove(It first, It last, void *ud = nullptr) {
|
||||
for(; first != last; ++first) {
|
||||
remove(*first);
|
||||
remove(*first, ud);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -588,32 +590,17 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/*! @brief Clears a sparse set. */
|
||||
void clear() ENTT_NOEXCEPT {
|
||||
remove(begin(), end());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the opaque payload associated with the sparse set, if any.
|
||||
* @return The opaque payload associated with the sparse set, if any.
|
||||
* @brief Clears a sparse set.
|
||||
* @param ud Optional user data that are forwarded as-is to derived classes.
|
||||
*/
|
||||
void * payload() const ENTT_NOEXCEPT {
|
||||
return user_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set an opaque payload, typically used to attach information that
|
||||
* are useful to storage mixins.
|
||||
* @param ud Opaque payload, a sparse set won't use this data in any case.
|
||||
*/
|
||||
void payload(void *ud) ENTT_NOEXCEPT {
|
||||
user_data = ud;
|
||||
void clear(void *ud = nullptr) ENTT_NOEXCEPT {
|
||||
remove(begin(), end(), ud);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<page_type> sparse;
|
||||
std::vector<entity_type> packed;
|
||||
void *user_data{};
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@ protected:
|
||||
* @copybrief basic_sparse_set::swap_and_pop
|
||||
* @param pos A valid position of an entity within storage.
|
||||
*/
|
||||
void swap_and_pop(const std::size_t pos) {
|
||||
void swap_and_pop(const std::size_t pos, void *) {
|
||||
auto other = std::move(instances.back());
|
||||
instances[pos] = std::move(other);
|
||||
instances.pop_back();
|
||||
@@ -393,7 +393,7 @@ public:
|
||||
* @return A reference to the updated instance.
|
||||
*/
|
||||
template<typename... Func>
|
||||
decltype(auto) patch(const entity_type entity, [[maybe_unused]] Func &&... func) {
|
||||
decltype(auto) patch(const entity_type entity, Func &&... func) {
|
||||
auto &&instance = instances[this->index(entity)];
|
||||
(std::forward<Func>(func)(instance), ...);
|
||||
return instance;
|
||||
@@ -559,7 +559,7 @@ public:
|
||||
* @param func Valid function objects.
|
||||
*/
|
||||
template<typename... Func>
|
||||
void patch([[maybe_unused]] const entity_type entity, [[maybe_unused]] Func &&... func) {
|
||||
void patch([[maybe_unused]] const entity_type entity, Func &&... func) {
|
||||
ENTT_ASSERT(this->contains(entity));
|
||||
(std::forward<Func>(func)(), ...);
|
||||
}
|
||||
@@ -583,21 +583,76 @@ public:
|
||||
|
||||
|
||||
/**
|
||||
* @brief Mixin type to use to add signal support to storage types.
|
||||
* @brief Mixin type to use to wrap basic storage classes.
|
||||
* @tparam Type The type of the underlying storage.
|
||||
* @tparam Owner Expected owner type.
|
||||
*/
|
||||
template<typename Type, typename Owner>
|
||||
class sigh_storage_mixin: public Type {
|
||||
Owner & owner() ENTT_NOEXCEPT {
|
||||
return *static_cast<Owner *>(this->payload());
|
||||
template<typename Type>
|
||||
struct storage_adapter_mixin: Type {
|
||||
static_assert(std::is_same_v<typename Type::value_type, std::decay_t<typename Type::value_type>>, "Invalid object type");
|
||||
|
||||
/*! @brief Type of the objects associated with the entities. */
|
||||
using value_type = typename Type::value_type;
|
||||
/*! @brief Underlying entity identifier. */
|
||||
using entity_type = typename Type::entity_type;
|
||||
/*! @brief Storage category. */
|
||||
using storage_category = typename Type::storage_category;
|
||||
|
||||
/**
|
||||
* @brief Assigns entities to a storage.
|
||||
* @tparam Args Types of arguments to use to construct the object.
|
||||
* @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> &, const entity_type entity, Args &&... args) {
|
||||
return Type::emplace(entity, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
protected:
|
||||
/*! @copydoc basic_storage::swap_and_pop */
|
||||
void swap_and_pop(const std::size_t pos) {
|
||||
destruction.publish(owner(), this->data()[pos]);
|
||||
Type::swap_and_pop(pos);
|
||||
/**
|
||||
* @brief Assigns entities to a storage.
|
||||
* @tparam It Type of input iterator.
|
||||
* @tparam Args Types of arguments to use to construct the objects
|
||||
* associated with the entities.
|
||||
* @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> &, It first, It last, Args &&... args) {
|
||||
Type::insert(first, last, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Patches the given instance for an entity.
|
||||
* @tparam Func Types of the function objects to invoke.
|
||||
* @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> &, const entity_type entity, Func &&... func) {
|
||||
return Type::patch(entity, std::forward<Func>(func)...);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Mixin type to use to add signal support to storage types.
|
||||
* @tparam Type The type of the underlying storage.
|
||||
*/
|
||||
template<typename Type>
|
||||
class sigh_storage_mixin final: public Type {
|
||||
/**
|
||||
* @copybrief basic_sparse_set::swap_and_pop
|
||||
* @param pos A valid position of an entity within storage.
|
||||
* @param ud Optional user data that are forwarded as-is to derived classes.
|
||||
*/
|
||||
void swap_and_pop(const std::size_t pos, void *ud) final {
|
||||
ENTT_ASSERT(ud != nullptr);
|
||||
destruction.publish(*static_cast<basic_registry<typename Type::entity_type> *>(ud), this->data()[pos]);
|
||||
Type::swap_and_pop(pos, ud);
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -676,14 +731,15 @@ public:
|
||||
/**
|
||||
* @brief Assigns entities to a storage.
|
||||
* @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(const entity_type entity, Args &&... args) {
|
||||
decltype(auto) emplace(basic_registry<entity_type> &owner, const entity_type entity, Args &&... args) {
|
||||
Type::emplace(entity, std::forward<Args>(args)...);
|
||||
construction.publish(owner(), entity);
|
||||
construction.publish(owner, entity);
|
||||
return this->get(entity);
|
||||
}
|
||||
|
||||
@@ -692,18 +748,19 @@ public:
|
||||
* @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(It first, It last, Args &&... args) {
|
||||
void insert(basic_registry<entity_type> &owner, 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -711,14 +768,15 @@ public:
|
||||
/**
|
||||
* @brief Patches the given instance for an entity.
|
||||
* @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(const entity_type entity, [[maybe_unused]] Func &&... func) {
|
||||
decltype(auto) patch(basic_registry<entity_type> &owner, const entity_type entity, Func &&... func) {
|
||||
Type::patch(entity, std::forward<Func>(func)...);
|
||||
update.publish(owner(), entity);
|
||||
update.publish(owner, entity);
|
||||
return this->get(entity);
|
||||
}
|
||||
|
||||
@@ -745,7 +803,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>, entt::basic_registry<Entity>>;
|
||||
using storage_type = sigh_storage_mixin<basic_storage<Entity, Type>>;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -97,6 +97,7 @@ endif()
|
||||
|
||||
if(ENTT_BUILD_EXAMPLE)
|
||||
SETUP_BASIC_TEST(custom_identifier example/custom_identifier.cpp)
|
||||
SETUP_BASIC_TEST(signal_less example/signal_less.cpp)
|
||||
endif()
|
||||
|
||||
# Test lib
|
||||
|
||||
@@ -11,8 +11,8 @@ template<typename Entity>
|
||||
struct PolyStorage: entt::type_list_cat_t<
|
||||
decltype(as_type_list(std::declval<entt::Storage<Entity>>())),
|
||||
entt::type_list<
|
||||
void(const Entity *, const Entity *),
|
||||
void(const Entity, const void *),
|
||||
void(const Entity *, const Entity *, void *),
|
||||
void(entt::basic_registry<Entity> &, const Entity, const void *),
|
||||
const void *(const Entity) const,
|
||||
void(entt::basic_registry<Entity> &) const
|
||||
>
|
||||
@@ -24,12 +24,12 @@ 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 remove(const entity_type *first, const entity_type *last) {
|
||||
entt::poly_call<base + 0>(*this, first, last);
|
||||
void remove(entt::basic_registry<Entity> &owner, const entity_type *first, const entity_type *last) {
|
||||
entt::poly_call<base + 0>(*this, first, last, &owner);
|
||||
}
|
||||
|
||||
void emplace(const entity_type entity, const void *instance) {
|
||||
entt::poly_call<base + 1>(*this, entity, instance);
|
||||
void emplace(entt::basic_registry<Entity> &owner, const entity_type entity, const void *instance) {
|
||||
entt::poly_call<base + 1>(*this, owner, entity, instance);
|
||||
}
|
||||
|
||||
const void * get(const entity_type entity) const {
|
||||
@@ -43,8 +43,8 @@ struct PolyStorage: entt::type_list_cat_t<
|
||||
|
||||
template<typename Type>
|
||||
struct members {
|
||||
static void emplace(Type &self, const entity_type entity, const void *instance) {
|
||||
self.emplace(entity, *static_cast<const typename Type::value_type *>(instance));
|
||||
static void emplace(Type &self, entt::basic_registry<Entity> &owner, const entity_type entity, const void *instance) {
|
||||
self.emplace(owner, entity, *static_cast<const typename Type::value_type *>(instance));
|
||||
}
|
||||
|
||||
static const typename Type::value_type * get(const Type &self, const entity_type entity) {
|
||||
@@ -86,7 +86,7 @@ TEST(PolyStorage, CopyEntity) {
|
||||
|
||||
registry.visit(entity, [&](const auto info) {
|
||||
auto &&storage = registry.storage(info);
|
||||
storage->emplace(other, storage->get(entity));
|
||||
storage->emplace(registry, other, storage->get(entity));
|
||||
});
|
||||
|
||||
ASSERT_TRUE((registry.all_of<int, char>(entity)));
|
||||
@@ -131,11 +131,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(std::begin(entity), std::end(entity)), ".*");
|
||||
ASSERT_DEATH(cstorage->remove(registry, std::begin(entity), std::end(entity)), ".*");
|
||||
ASSERT_TRUE(registry.all_of<int>(entity[0]));
|
||||
|
||||
auto &&storage = registry.storage(entt::type_id<int>());
|
||||
storage->remove(std::begin(entity), std::end(entity));
|
||||
storage->remove(registry, std::begin(entity), std::end(entity));
|
||||
|
||||
ASSERT_FALSE(registry.all_of<int>(entity[0]));
|
||||
}
|
||||
|
||||
@@ -14,12 +14,6 @@ struct boxed_int { int value; };
|
||||
TEST(SparseSet, Functionalities) {
|
||||
entt::sparse_set set;
|
||||
|
||||
ASSERT_EQ(set.payload(), nullptr);
|
||||
|
||||
set.payload(&set);
|
||||
|
||||
ASSERT_EQ(set.payload(), &set);
|
||||
|
||||
set.reserve(42);
|
||||
|
||||
ASSERT_EQ(set.capacity(), 42u);
|
||||
@@ -84,8 +78,6 @@ TEST(SparseSet, Functionalities) {
|
||||
ASSERT_EQ(other.begin(), other.end());
|
||||
ASSERT_FALSE(other.contains(entt::entity{0}));
|
||||
ASSERT_FALSE(other.contains(entt::entity{42}));
|
||||
|
||||
ASSERT_EQ(set.payload(), &set);
|
||||
}
|
||||
|
||||
TEST(SparseSet, Pagination) {
|
||||
|
||||
43
test/example/signal_less.cpp
Normal file
43
test/example/signal_less.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/entity/entity.hpp>
|
||||
#include <entt/entity/registry.hpp>
|
||||
|
||||
template<typename Entity, typename Type>
|
||||
struct entt::storage_traits<Entity, Type> {
|
||||
// no signal regardless of component type ...
|
||||
using storage_type = storage_adapter_mixin<basic_storage<Entity, Type>>;
|
||||
};
|
||||
|
||||
template<typename Entity>
|
||||
struct entt::storage_traits<Entity, char> {
|
||||
// ... unless it's char, because yes.
|
||||
using storage_type = sigh_storage_mixin<basic_storage<Entity, char>>;
|
||||
};
|
||||
|
||||
template<typename, typename, typename = void>
|
||||
struct has_on_construct: std::false_type {};
|
||||
|
||||
template<typename Entity, typename Type>
|
||||
struct has_on_construct<Entity, Type, std::void_t<decltype(&entt::storage_traits<Entity, Type>::storage_type::on_construct)>>: std::true_type {};
|
||||
|
||||
template<typename Entity, typename Type>
|
||||
inline constexpr auto has_on_construct_v = has_on_construct<Entity, Type>::value;
|
||||
|
||||
TEST(Example, SignalLess) {
|
||||
// invoking registry::on_construct<int> is a compile-time error
|
||||
static_assert(!has_on_construct_v<entt::entity, int>);
|
||||
static_assert(has_on_construct_v<entt::entity, char>);
|
||||
|
||||
entt::registry registry;
|
||||
const entt::entity entity[1u]{registry.create()};
|
||||
|
||||
// literally a test for storage_adapter_mixin
|
||||
registry.emplace<int>(entity[0], 0);
|
||||
registry.remove<int>(entity[0]);
|
||||
registry.insert<int>(std::begin(entity), std::end(entity), 3);
|
||||
registry.patch<int>(entity[0], [](auto &value) { value = 42; });
|
||||
|
||||
ASSERT_EQ(registry.get<int>(entity[0]), 42);
|
||||
}
|
||||
Reference in New Issue
Block a user