entity:
* sparse_set: stable virtual remove * basic_storage: fake get for empty types, * sigh_storage_mixin: use swap_and_pop, drop ::remove, ignore emptiness * poly_storage: ::remove is no longer part of its interface by default
This commit is contained in:
5
TODO
5
TODO
@@ -18,10 +18,13 @@
|
||||
- ...
|
||||
|
||||
WIP:
|
||||
* HP: as_ref should be a qualified function, not a global one (no breaking change, ADL makes it work anyway)
|
||||
* HP: remove storage category and get_as_tuple, make storage classes return tuple (+ view generator detect shared storage in future)?
|
||||
* HP: remove non-const registry::storage function?
|
||||
* HP: review registry::get, registry::try_get
|
||||
* HP: weak reference wrapper example with custom storage.
|
||||
* HP: review ENTT_PAGE_SIZE, seems "wrong" (see sparse_set)
|
||||
* HP: as_ref should be a qualified function, not a global one (no breaking change, ADL makes it work anyway)
|
||||
* HP: virtual sparse_set::poly_storage (and sparse_set * only in the registry)
|
||||
* HP: merge view and view pack
|
||||
* HP: invalid view auto-refresh
|
||||
* HP: paginate pools
|
||||
|
||||
@@ -18,15 +18,7 @@ namespace entt {
|
||||
* @tparam Entity A valid entity type (see entt_traits for more details).
|
||||
*/
|
||||
template<typename Entity>
|
||||
struct Storage: type_list<
|
||||
type_info() const ENTT_NOEXCEPT,
|
||||
void(const Entity *, const Entity *)
|
||||
> {
|
||||
/*! @brief Underlying entity identifier. */
|
||||
using entity_type = Entity;
|
||||
/*! @brief Unsigned integer type. */
|
||||
using size_type = std::size_t;
|
||||
|
||||
struct Storage: type_list<type_info() const ENTT_NOEXCEPT> {
|
||||
/**
|
||||
* @brief Concept definition.
|
||||
* @tparam Base Opaque base class from which to inherit.
|
||||
@@ -40,17 +32,6 @@ struct Storage: type_list<
|
||||
type_info value_type() const ENTT_NOEXCEPT {
|
||||
return poly_call<0>(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes entities from a storage.
|
||||
* @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(const entity_type *first, const entity_type *last) {
|
||||
poly_call<1>(*this, first, last);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -58,10 +39,7 @@ struct Storage: type_list<
|
||||
* @tparam Type Type for which to generate an implementation.
|
||||
*/
|
||||
template<typename Type>
|
||||
using impl = value_list<
|
||||
&type_id<typename Type::value_type>,
|
||||
&Type::template remove<const entity_type *>
|
||||
>;
|
||||
using impl = value_list<&type_id<typename Type::value_type>>;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -639,7 +639,7 @@ public:
|
||||
auto *cpool = assure<Component>();
|
||||
|
||||
return cpool->contains(entity)
|
||||
? cpool->patch(entity, [&args...](auto &curr) { curr = Component{std::forward<Args>(args)...}; })
|
||||
? cpool->patch(entity, [&args...](auto &... curr) { ((curr = Component{std::forward<Args>(args)...}), ...); })
|
||||
: cpool->emplace(entity, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
@@ -692,7 +692,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(entity, [&args...](auto &... curr) { ((curr = Component{std::forward<Args>(args)...}), ...); });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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(std::begin(wrap), std::end(wrap));
|
||||
pdata.pool->remove(std::begin(wrap), std::end(wrap));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -433,17 +433,18 @@ public:
|
||||
void remove(const entity_type entt) {
|
||||
ENTT_ASSERT(contains(entt));
|
||||
auto &ref = sparse[page(entt)][offset(entt)];
|
||||
const auto pos = size_type{to_integral(ref)};
|
||||
const auto other = packed.back();
|
||||
|
||||
// last chance to use the entity for derived classes and mixins, if any
|
||||
swap_and_pop(size_type{to_integral(ref)});
|
||||
|
||||
const auto other = packed.back();
|
||||
sparse[page(other)][offset(other)] = ref;
|
||||
// If it looks weird, imagine what the subtle bugs it prevents are
|
||||
// if it looks weird, imagine what the subtle bugs it prevents are
|
||||
ENTT_ASSERT((packed.back() = entt, true));
|
||||
packed[pos] = other;
|
||||
packed[size_type{to_integral(ref)}] = other;
|
||||
ref = null;
|
||||
|
||||
packed.pop_back();
|
||||
swap_and_pop(pos);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -512,6 +512,19 @@ public:
|
||||
/*! @brief Storage category. */
|
||||
using storage_category = empty_storage_tag;
|
||||
|
||||
/**
|
||||
* @brief Fake get function.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to use an entity that doesn't belong to the storage results in
|
||||
* undefined behavior.
|
||||
*
|
||||
* @param entt A valid entity identifier.
|
||||
*/
|
||||
void get([[maybe_unused]] const entity_type entt) const {
|
||||
ENTT_ASSERT(contains(entt));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns an entity to a storage and constructs its object.
|
||||
*
|
||||
@@ -570,6 +583,12 @@ class sigh_storage_mixin: public Type {
|
||||
return *static_cast<Owner *>(payload());
|
||||
}
|
||||
|
||||
protected:
|
||||
void swap_and_pop(const std::size_t pos) {
|
||||
destruction.publish(owner(), data()[pos]);
|
||||
Type::swap_and_pop(pos);
|
||||
}
|
||||
|
||||
public:
|
||||
/*! @brief Underlying value type. */
|
||||
using value_type = typename Type::value_type;
|
||||
@@ -654,10 +673,7 @@ public:
|
||||
decltype(auto) emplace(const entity_type entity, Args &&... args) {
|
||||
Type::emplace(entity, std::forward<Args>(args)...);
|
||||
construction.publish(owner(), entity);
|
||||
|
||||
if constexpr(!std::is_same_v<storage_category, empty_storage_tag>) {
|
||||
return this->get(entity);
|
||||
}
|
||||
return get(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -681,32 +697,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @copybrief storage_adapter_mixin::remove
|
||||
* @param entity A valid entity identifier.
|
||||
*/
|
||||
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 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(It first, It last) {
|
||||
if(!destruction.empty()) {
|
||||
for(auto it = first; it != last; ++it) {
|
||||
destruction.publish(owner(), *it);
|
||||
}
|
||||
}
|
||||
|
||||
Type::remove(first, last);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copybrief storage_adapter_mixin::patch
|
||||
* @tparam Func Types of the function objects to invoke.
|
||||
@@ -716,13 +706,9 @@ public:
|
||||
*/
|
||||
template<typename... 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);
|
||||
} else {
|
||||
Type::patch(entity, std::forward<Func>(func)...);
|
||||
update.publish(owner(), entity);
|
||||
return this->get(entity);
|
||||
}
|
||||
Type::patch(entity, std::forward<Func>(func)...);
|
||||
update.publish(owner(), entity);
|
||||
return get(entity);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -11,6 +11,7 @@ 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 *),
|
||||
const void *(const Entity) const,
|
||||
void(entt::basic_registry<Entity> &) const
|
||||
@@ -23,16 +24,20 @@ 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 emplace(const entity_type entity, const void *instance) {
|
||||
entt::poly_call<base + 0>(*this, entity, instance);
|
||||
entt::poly_call<base + 1>(*this, entity, instance);
|
||||
}
|
||||
|
||||
const void * get(const entity_type entity) const {
|
||||
return entt::poly_call<base + 1>(*this, entity);
|
||||
return entt::poly_call<base + 2>(*this, entity);
|
||||
}
|
||||
|
||||
void copy_to(entt::basic_registry<Entity> &other) const {
|
||||
entt::poly_call<base + 2>(*this, other);
|
||||
entt::poly_call<base + 3>(*this, other);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -55,6 +60,7 @@ struct PolyStorage: entt::type_list_cat_t<
|
||||
using impl = entt::value_list_cat_t<
|
||||
typename entt::Storage<Entity>::template impl<Type>,
|
||||
entt::value_list<
|
||||
&Type::template remove<const entity_type *>,
|
||||
&members<Type>::emplace,
|
||||
&members<Type>::get,
|
||||
&members<Type>::copy_to
|
||||
|
||||
Reference in New Issue
Block a user