updated entity module
This commit is contained in:
@@ -102,6 +102,35 @@ class Registry {
|
||||
return pool<Component>();
|
||||
}
|
||||
|
||||
template<typename... Component>
|
||||
SparseSet<Entity> & handler() {
|
||||
static_assert(sizeof...(Component) > 1, "!");
|
||||
const auto vtype = view_family::type<Component...>();
|
||||
|
||||
if(!(vtype < handlers.size())) {
|
||||
handlers.resize(vtype + 1);
|
||||
}
|
||||
|
||||
if(!handlers[vtype]) {
|
||||
using accumulator_type = int[];
|
||||
|
||||
auto set = std::make_unique<SparseSet<Entity>>();
|
||||
|
||||
for(auto entity: view<Component...>()) {
|
||||
set->construct(entity);
|
||||
}
|
||||
|
||||
accumulator_type accumulator = {
|
||||
(ensure<Component>().append(*set, &Registry::has<Component...>), 0)...
|
||||
};
|
||||
|
||||
handlers[vtype] = std::move(set);
|
||||
(void)accumulator;
|
||||
}
|
||||
|
||||
return *handlers[vtype];
|
||||
}
|
||||
|
||||
public:
|
||||
/*! @brief Underlying entity identifier. */
|
||||
using entity_type = typename traits_type::entity_type;
|
||||
@@ -110,20 +139,18 @@ public:
|
||||
/*! @brief Unsigned integer type. */
|
||||
using size_type = std::size_t;
|
||||
|
||||
/*! @brief Default constructor, explicit on purpose. */
|
||||
explicit Registry() = default;
|
||||
/*! @brief Default destructor. */
|
||||
~Registry() = default;
|
||||
/*! @brief Default constructor. */
|
||||
Registry() = default;
|
||||
|
||||
/*! @brief Copying a registry isn't allowed. */
|
||||
Registry(const Registry &) = delete;
|
||||
/*! @brief Moving a registry isn't allowed. */
|
||||
Registry(Registry &&) = delete;
|
||||
/*! @brief Default move constructor. */
|
||||
Registry(Registry &&) = default;
|
||||
|
||||
/*! @brief Copying a registry isn't allowed. @return This registry. */
|
||||
Registry & operator=(const Registry &) = delete;
|
||||
/*! @brief Moving a registry isn't allowed. @return This registry. */
|
||||
Registry & operator=(Registry &&) = delete;
|
||||
/*! @brief Default move assignment operator. @return This registry. */
|
||||
Registry & operator=(Registry &&) = default;
|
||||
|
||||
/**
|
||||
* @brief Returns the number of existing components of the given type.
|
||||
@@ -171,7 +198,7 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Verifies if the entity identifier still refers to a valid entity.
|
||||
* @brief Verifies if an entity identifier still refers to a valid entity.
|
||||
* @param entity An entity identifier, either valid or not.
|
||||
* @return True if the identifier is still valid, false otherwise.
|
||||
*/
|
||||
@@ -181,16 +208,16 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the version stored along with the given entity identifier.
|
||||
* @brief Returns the version stored along with an entity identifier.
|
||||
* @param entity An entity identifier, either valid or not.
|
||||
* @return Version stored along with the given entity identifier.
|
||||
*/
|
||||
version_type version(entity_type entity) const noexcept {
|
||||
return version_type((entity >> traits_type::version_shift) & traits_type::version_mask);
|
||||
return version_type((entity >> traits_type::entity_shift) & traits_type::version_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the actual version for the given entity identifier.
|
||||
* @brief Returns the actual version for an entity identifier.
|
||||
*
|
||||
* In case entity identifers are stored around, this function can be used to
|
||||
* know if they are still valid or the entity has been destroyed and
|
||||
@@ -209,13 +236,14 @@ public:
|
||||
version_type current(entity_type entity) const noexcept {
|
||||
const auto entt = entity & traits_type::entity_mask;
|
||||
assert(entt < entities.size());
|
||||
return version_type((entities[entt] >> traits_type::version_shift) & traits_type::version_mask);
|
||||
return version_type((entities[entt] >> traits_type::entity_shift) & traits_type::version_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a new entity initialized with the given components.
|
||||
*
|
||||
* There are two kinds of entity identifiers:
|
||||
*
|
||||
* * Newly created ones in case no entities have been previously destroyed.
|
||||
* * Recycled one with updated versions.
|
||||
*
|
||||
@@ -243,6 +271,7 @@ public:
|
||||
* @brief Returns a new entity to which the given components are assigned.
|
||||
*
|
||||
* There are two kinds of entity identifiers:
|
||||
*
|
||||
* * Newly created ones in case no entities have been previously destroyed.
|
||||
* * Recycled one with updated versions.
|
||||
*
|
||||
@@ -269,6 +298,7 @@ public:
|
||||
* @brief Creates a new entity and returns it.
|
||||
*
|
||||
* There are two kinds of entity identifiers:
|
||||
*
|
||||
* * Newly created ones in case no entities have been previously destroyed.
|
||||
* * Recycled one with updated versions.
|
||||
*
|
||||
@@ -287,7 +317,7 @@ public:
|
||||
if(available.empty()) {
|
||||
entity = entity_type(entities.size());
|
||||
assert(entity < traits_type::entity_mask);
|
||||
assert((entity >> traits_type::version_shift) == entity_type{});
|
||||
assert((entity >> traits_type::entity_shift) == entity_type{});
|
||||
entities.push_back(entity);
|
||||
} else {
|
||||
entity = available.back();
|
||||
@@ -316,8 +346,8 @@ public:
|
||||
assert(valid(entity));
|
||||
|
||||
const auto entt = entity & traits_type::entity_mask;
|
||||
const auto version = 1 + ((entity >> traits_type::version_shift) & traits_type::version_mask);
|
||||
const auto next = entt | (version << traits_type::version_shift);
|
||||
const auto version = 1 + ((entity >> traits_type::entity_shift) & traits_type::version_mask);
|
||||
const auto next = entt | (version << traits_type::entity_shift);
|
||||
entities[entt] = next;
|
||||
available.push_back(next);
|
||||
|
||||
@@ -329,7 +359,7 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns the given component to the given entity.
|
||||
* @brief Assigns the given component to an entity.
|
||||
*
|
||||
* A new instance of the given component is created and initialized with the
|
||||
* arguments provided (the component must have a proper constructor or be of
|
||||
@@ -355,7 +385,7 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes the given component from the given entity.
|
||||
* @brief Removes the given component from an entity.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to use an invalid entity or to remove a component from an
|
||||
@@ -370,11 +400,11 @@ public:
|
||||
template<typename Component>
|
||||
void remove(entity_type entity) {
|
||||
assert(valid(entity));
|
||||
return pool<Component>().destroy(entity);
|
||||
pool<Component>().destroy(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if the given entity has all the given components.
|
||||
* @brief Checks if an entity has all the given components.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to use an invalid entity results in undefined behavior.<br/>
|
||||
@@ -397,7 +427,7 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a reference to the given component owned by the given entity.
|
||||
* @brief Returns a reference to the given component for an entity.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to use an invalid entity or to get a component from an entity
|
||||
@@ -417,7 +447,7 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a reference to the given component owned by the given entity.
|
||||
* @brief Returns a reference to the given component for an entity.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to use an invalid entity or to get a component from an entity
|
||||
@@ -436,7 +466,7 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Replaces the given component for the given entity.
|
||||
* @brief Replaces the given component for an entity.
|
||||
*
|
||||
* A new instance of the given component is created and initialized with the
|
||||
* arguments provided (the component must have a proper constructor or be of
|
||||
@@ -462,7 +492,7 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns or replaces the given component to the given entity.
|
||||
* @brief Assigns or replaces the given component for an entity.
|
||||
*
|
||||
* Equivalent to the following snippet (pseudocode):
|
||||
*
|
||||
@@ -499,7 +529,7 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sorts the pool of the given component.
|
||||
* @brief Sorts the pool of entities for the given component.
|
||||
*
|
||||
* The order of the elements in a pool is highly affected by assignements
|
||||
* of components to entities and deletions. Components are arranged to
|
||||
@@ -568,7 +598,7 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resets the given component for the given entity.
|
||||
* @brief Resets the given component for an entity.
|
||||
*
|
||||
* If the entity has an instance of the component, this function removes the
|
||||
* component from the entity. Otherwise it does nothing.
|
||||
@@ -616,7 +646,7 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resets the whole registry.
|
||||
* @brief Resets a whole registry.
|
||||
*
|
||||
* Destroys all the entities. After a call to `reset`, all the entities
|
||||
* previously created are recycled with a new version number. In case entity
|
||||
@@ -628,8 +658,8 @@ public:
|
||||
pools.clear();
|
||||
|
||||
for(auto &&entity: entities) {
|
||||
const auto version = 1 + ((entity >> traits_type::version_shift) & traits_type::version_mask);
|
||||
entity = (entity & traits_type::entity_mask) | (version << traits_type::version_shift);
|
||||
const auto version = 1 + ((entity >> traits_type::entity_shift) & traits_type::version_mask);
|
||||
entity = (entity & traits_type::entity_mask) | (version << traits_type::entity_shift);
|
||||
available.push_back(entity);
|
||||
}
|
||||
}
|
||||
@@ -646,6 +676,7 @@ public:
|
||||
*
|
||||
* Standard views do their best to iterate the smallest set of candidate
|
||||
* entites. In particular:
|
||||
*
|
||||
* * Single component views are incredibly fast and iterate a packed array
|
||||
* of entities, all of which has the given component.
|
||||
* * Multi component views look at the number of entities available for each
|
||||
@@ -662,7 +693,7 @@ public:
|
||||
* @see View<Entity, Component>
|
||||
* @see PersistentView
|
||||
*
|
||||
* @tparam Component Type of the components used to construct the view.
|
||||
* @tparam Component Type of components used to construct the view.
|
||||
* @return A newly created standard view.
|
||||
*/
|
||||
template<typename... Component>
|
||||
@@ -684,33 +715,11 @@ public:
|
||||
* can be prepared with this function. Just use the same set of components
|
||||
* that would have been used otherwise to contruct the view.
|
||||
*
|
||||
* @tparam Component Types of the components used to prepare the view.
|
||||
* @tparam Component Types of components used to prepare the view.
|
||||
*/
|
||||
template<typename... Component>
|
||||
void prepare() {
|
||||
static_assert(sizeof...(Component) > 1, "!");
|
||||
const auto vtype = view_family::type<Component...>();
|
||||
|
||||
if(!(vtype < handlers.size())) {
|
||||
handlers.resize(vtype + 1);
|
||||
}
|
||||
|
||||
if(!handlers[vtype]) {
|
||||
using accumulator_type = int[];
|
||||
|
||||
auto handler = std::make_unique<SparseSet<Entity>>();
|
||||
|
||||
for(auto entity: view<Component...>()) {
|
||||
handler->construct(entity);
|
||||
}
|
||||
|
||||
accumulator_type accumulator = {
|
||||
(ensure<Component>().append(*handler, &Registry::has<Component...>), 0)...
|
||||
};
|
||||
|
||||
handlers[vtype] = std::move(handler);
|
||||
(void)accumulator;
|
||||
}
|
||||
handler<Component...>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -727,6 +736,7 @@ public:
|
||||
* of components grows up and the most of the entities have all the given
|
||||
* components.<br/>
|
||||
* However they have also drawbacks:
|
||||
*
|
||||
* * Each kind of persistent view requires a dedicated data structure that
|
||||
* is allocated within the registry and it increases memory pressure.
|
||||
* * Internal data structures used to construct persistent views must be
|
||||
@@ -746,14 +756,12 @@ public:
|
||||
* @see View<Entity, Component>
|
||||
* @see PersistentView
|
||||
*
|
||||
* @tparam Component Types of the components used to construct the view.
|
||||
* @tparam Component Types of components used to construct the view.
|
||||
* @return A newly created persistent view.
|
||||
*/
|
||||
template<typename... Component>
|
||||
PersistentView<Entity, Component...> persistent() {
|
||||
static_assert(sizeof...(Component) > 1, "!");
|
||||
prepare<Component...>();
|
||||
return PersistentView<Entity, Component...>{*handlers[view_family::type<Component...>()], ensure<Component>()...};
|
||||
return PersistentView<Entity, Component...>{handler<Component...>(), ensure<Component>()...};
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -87,6 +87,8 @@ class SparseSet<Entity> {
|
||||
std::size_t pos;
|
||||
};
|
||||
|
||||
static constexpr Entity in_use = 1 << traits_type::entity_shift;
|
||||
|
||||
public:
|
||||
/*! @brief Underlying entity identifier. */
|
||||
using entity_type = Entity;
|
||||
@@ -97,24 +99,24 @@ public:
|
||||
/*! @brief Input iterator type. */
|
||||
using iterator_type = Iterator;
|
||||
|
||||
/*! @brief Default constructor, explicit on purpose. */
|
||||
explicit SparseSet() noexcept = default;
|
||||
/*! @brief Default constructor. */
|
||||
SparseSet() noexcept = default;
|
||||
|
||||
/*! @brief Default destructor. */
|
||||
virtual ~SparseSet() noexcept = default;
|
||||
|
||||
/*! @brief Copying a sparse set isn't allowed. */
|
||||
SparseSet(const SparseSet &) = delete;
|
||||
/*! @brief Default move constructor. */
|
||||
SparseSet(SparseSet &&) = default;
|
||||
|
||||
/*! @brief Default destructor. */
|
||||
virtual ~SparseSet() noexcept = default;
|
||||
|
||||
/*! @brief Copying a sparse set isn't allowed. @return This sparse set. */
|
||||
SparseSet & operator=(const SparseSet &) = delete;
|
||||
/*! @brief Default move assignment operator. @return This sparse set. */
|
||||
SparseSet & operator=(SparseSet &&) = default;
|
||||
|
||||
/**
|
||||
* @brief Returns the number of elements in the sparse set.
|
||||
* @brief Returns the number of elements in a sparse set.
|
||||
*
|
||||
* The number of elements is also the size of the internal packed array.
|
||||
* There is no guarantee that the internal sparse array has the same size.
|
||||
@@ -128,8 +130,8 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks whether the sparse set is empty.
|
||||
* @return True is the sparse set is empty, false otherwise.
|
||||
* @brief Checks whether a sparse set is empty.
|
||||
* @return True if the sparse set is empty, false otherwise.
|
||||
*/
|
||||
bool empty() const noexcept {
|
||||
return direct.empty();
|
||||
@@ -188,17 +190,18 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if the sparse set contains the given entity.
|
||||
* @brief Checks if a sparse set contains an entity.
|
||||
* @param entity A valid entity identifier.
|
||||
* @return True if the sparse set contains the entity, false otherwise.
|
||||
*/
|
||||
bool has(entity_type entity) const noexcept {
|
||||
const auto entt = entity & traits_type::entity_mask;
|
||||
return entt < reverse.size() && reverse[entt] < direct.size() && direct[reverse[entt]] == entity;
|
||||
// the in-use control bit permits to avoid accessing the direct vector
|
||||
return (entt < reverse.size()) && (reverse[entt] & in_use);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the position of the entity in the sparse set.
|
||||
* @brief Returns the position of an entity in a sparse set.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to get the position of an entity that doesn't belong to the
|
||||
@@ -211,11 +214,13 @@ public:
|
||||
*/
|
||||
pos_type get(entity_type entity) const noexcept {
|
||||
assert(has(entity));
|
||||
return reverse[entity & traits_type::entity_mask];
|
||||
const auto entt = entity & traits_type::entity_mask;
|
||||
// we must get rid of the in-use bit for it's not part of the position
|
||||
return reverse[entt] & ~in_use;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns an entity to the sparse set.
|
||||
* @brief Assigns an entity to a sparse set.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to assign an entity that already belongs to the sparse set
|
||||
@@ -224,25 +229,23 @@ public:
|
||||
* sparse set already contains the given entity.
|
||||
*
|
||||
* @param entity A valid entity identifier.
|
||||
* @return The position of the entity in the internal packed array.
|
||||
*/
|
||||
pos_type construct(entity_type entity) {
|
||||
void construct(entity_type entity) {
|
||||
assert(!has(entity));
|
||||
const auto entt = entity & traits_type::entity_mask;
|
||||
|
||||
if(!(entt < reverse.size())) {
|
||||
reverse.resize(entt+1);
|
||||
reverse.resize(entt+1, pos_type{});
|
||||
}
|
||||
|
||||
const auto pos = pos_type(direct.size());
|
||||
reverse[entt] = pos;
|
||||
// we exploit the fact that pos_type is equal to entity_type and pos has
|
||||
// traits_type::version_mask bits unused we can use to mark it as in-use
|
||||
reverse[entt] = pos_type(direct.size()) | in_use;
|
||||
direct.emplace_back(entity);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes the given entity from the sparse set.
|
||||
* @brief Removes an entity from a sparse set.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to remove an entity that doesn't belong to the sparse set
|
||||
@@ -256,14 +259,18 @@ public:
|
||||
assert(has(entity));
|
||||
const auto entt = entity & traits_type::entity_mask;
|
||||
const auto back = direct.back() & traits_type::entity_mask;
|
||||
const auto pos = reverse[entt];
|
||||
reverse[back] = pos;
|
||||
const auto pos = reverse[entt] & ~in_use;
|
||||
// the order matters: if back and entt are the same (for the sparse set
|
||||
// has size 1), switching the two lines below doesn't work as expected
|
||||
reverse[back] = pos | in_use;
|
||||
reverse[entt] = pos;
|
||||
// swap-and-pop the last element with the selected ont
|
||||
direct[pos] = direct.back();
|
||||
direct.pop_back();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Swaps the position of the entities in the internal packed array.
|
||||
* @brief Swaps the position of two entities in the internal packed array.
|
||||
*
|
||||
* For what it's worth, this function affects both the internal sparse array
|
||||
* and the internal packed array. Users should not care of that anyway.
|
||||
@@ -280,10 +287,11 @@ public:
|
||||
virtual void swap(entity_type lhs, entity_type rhs) {
|
||||
assert(has(lhs));
|
||||
assert(has(rhs));
|
||||
const auto le = lhs & traits_type::entity_mask;
|
||||
const auto re = rhs & traits_type::entity_mask;
|
||||
std::swap(direct[reverse[le]], direct[reverse[re]]);
|
||||
std::swap(reverse[le], reverse[re]);
|
||||
auto &le = reverse[lhs & traits_type::entity_mask];
|
||||
auto &re = reverse[rhs & traits_type::entity_mask];
|
||||
// we must get rid of the in-use bit for it's not part of the position
|
||||
std::swap(direct[le & ~in_use], direct[re & ~in_use]);
|
||||
std::swap(le, re);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -316,7 +324,7 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sort entities according to their order in the given sparse set.
|
||||
* @brief Sort entities according to their order in a sparse set.
|
||||
*
|
||||
* Entities that are part of both the sparse sets are ordered internally
|
||||
* according to the order they have in `other`. All the other entities goes
|
||||
@@ -363,7 +371,7 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resets the sparse set.
|
||||
* @brief Resets a sparse set.
|
||||
*/
|
||||
virtual void reset() {
|
||||
reverse.clear();
|
||||
@@ -371,7 +379,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<entity_type> reverse;
|
||||
std::vector<pos_type> reverse;
|
||||
std::vector<entity_type> direct;
|
||||
};
|
||||
|
||||
@@ -414,8 +422,8 @@ public:
|
||||
/*! @brief Input iterator type. */
|
||||
using iterator_type = typename underlying_type::iterator_type;
|
||||
|
||||
/*! @brief Default constructor, explicit on purpose. */
|
||||
explicit SparseSet() noexcept = default;
|
||||
/*! @brief Default constructor. */
|
||||
SparseSet() noexcept = default;
|
||||
|
||||
/*! @brief Copying a sparse set isn't allowed. */
|
||||
SparseSet(const SparseSet &) = delete;
|
||||
@@ -466,7 +474,7 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the object associated to the given entity.
|
||||
* @brief Returns the object associated to an entity.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to use an entity that doesn't belong to the sparse set results
|
||||
@@ -482,7 +490,7 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the object associated to the given entity.
|
||||
* @brief Returns the object associated to an entity.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to use an entity that doesn't belong to the sparse set results
|
||||
@@ -498,7 +506,7 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns an entity to the sparse set and constructs its object.
|
||||
* @brief Assigns an entity to a sparse set and constructs its object.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to use an entity that already belongs to the sparse set
|
||||
@@ -519,7 +527,7 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes an entity from the sparse set and destroies its object.
|
||||
* @brief Removes an entity from a sparse set and destroies its object.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to use an entity that doesn't belong to the sparse set results
|
||||
@@ -530,13 +538,14 @@ public:
|
||||
* @param entity A valid entity identifier.
|
||||
*/
|
||||
void destroy(entity_type entity) override {
|
||||
// swaps isn't required here, we are getting rid of the last element
|
||||
instances[underlying_type::get(entity)] = std::move(instances.back());
|
||||
instances.pop_back();
|
||||
underlying_type::destroy(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Swaps the two entities and their objects.
|
||||
* @brief Swaps two entities and their objects.
|
||||
*
|
||||
* @note
|
||||
* This function doesn't swap objects between entities. It exchanges entity
|
||||
@@ -557,7 +566,7 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resets the sparse set.
|
||||
* @brief Resets a sparse set.
|
||||
*/
|
||||
void reset() override {
|
||||
underlying_type::reset();
|
||||
|
||||
@@ -22,6 +22,7 @@ struct entt_traits;
|
||||
* @brief Entity traits for a 16 bits entity identifier.
|
||||
*
|
||||
* A 16 bits entity identifier guarantees:
|
||||
*
|
||||
* * 12 bits for the entity number (up to 4k entities).
|
||||
* * 4 bit for the version (resets in [0-15]).
|
||||
*/
|
||||
@@ -37,7 +38,7 @@ struct entt_traits<std::uint16_t> {
|
||||
/*! @brief Mask to use to get the version out of an identifier. */
|
||||
static constexpr auto version_mask = 0xF;
|
||||
/*! @brief Extent of the entity number within an identifier. */
|
||||
static constexpr auto version_shift = 12;
|
||||
static constexpr auto entity_shift = 12;
|
||||
};
|
||||
|
||||
|
||||
@@ -45,6 +46,7 @@ struct entt_traits<std::uint16_t> {
|
||||
* @brief Entity traits for a 32 bits entity identifier.
|
||||
*
|
||||
* A 32 bits entity identifier guarantees:
|
||||
*
|
||||
* * 24 bits for the entity number (suitable for almost all the games).
|
||||
* * 8 bit for the version (resets in [0-255]).
|
||||
*/
|
||||
@@ -60,7 +62,7 @@ struct entt_traits<std::uint32_t> {
|
||||
/*! @brief Mask to use to get the version out of an identifier. */
|
||||
static constexpr auto version_mask = 0xFF;
|
||||
/*! @brief Extent of the entity number within an identifier. */
|
||||
static constexpr auto version_shift = 24;
|
||||
static constexpr auto entity_shift = 24;
|
||||
};
|
||||
|
||||
|
||||
@@ -68,6 +70,7 @@ struct entt_traits<std::uint32_t> {
|
||||
* @brief Entity traits for a 64 bits entity identifier.
|
||||
*
|
||||
* A 64 bits entity identifier guarantees:
|
||||
*
|
||||
* * 40 bits for the entity number (an indecently large number).
|
||||
* * 24 bit for the version (an indecently large number).
|
||||
*/
|
||||
@@ -83,7 +86,7 @@ struct entt_traits<std::uint64_t> {
|
||||
/*! @brief Mask to use to get the version out of an identifier. */
|
||||
static constexpr auto version_mask = 0xFFFFFF;
|
||||
/*! @brief Extent of the entity number within an identifier. */
|
||||
static constexpr auto version_shift = 40;
|
||||
static constexpr auto entity_shift = 40;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ public:
|
||||
* @brief Constructs a persistent view around a dedicated pool of entities.
|
||||
*
|
||||
* A persistent view is created out of:
|
||||
*
|
||||
* * A dedicated pool of entities that is shared between all the persistent
|
||||
* views of the same type.
|
||||
* * A bunch of pools of components to which to refer to get instances.
|
||||
@@ -77,7 +78,7 @@ public:
|
||||
* @param view Shared reference to a dedicated pool of entities.
|
||||
* @param pools References to pools of components.
|
||||
*/
|
||||
explicit PersistentView(view_type &view, pool_type<Component>&... pools) noexcept
|
||||
PersistentView(view_type &view, pool_type<Component>&... pools) noexcept
|
||||
: view{view}, pools{pools...}
|
||||
{}
|
||||
|
||||
@@ -240,9 +241,9 @@ public:
|
||||
*
|
||||
* @note
|
||||
* The shared pool of entities and thus its order is affected by the changes
|
||||
* to each and every pool of components that it tracks. Therefore changes to
|
||||
* the pools of components can quickly ruin the order imposed to the pool of
|
||||
* entities shared between the persistent views.
|
||||
* to each and every pool that it tracks. Therefore changes to those pools
|
||||
* can quickly ruin the order imposed to the pool of entities shared between
|
||||
* the persistent views.
|
||||
*
|
||||
* @tparam Comp Type of the component to use to impose the order.
|
||||
*/
|
||||
@@ -368,7 +369,7 @@ public:
|
||||
* @param pool A reference to a pool of components.
|
||||
* @param other Other references to pools of components.
|
||||
*/
|
||||
explicit View(pool_type<First> &pool, pool_type<Other>&... other) noexcept
|
||||
View(pool_type<First> &pool, pool_type<Other>&... other) noexcept
|
||||
: pools{pool, other...}, view{nullptr}
|
||||
{
|
||||
reset();
|
||||
@@ -576,7 +577,7 @@ public:
|
||||
* @brief Constructs a view out of a pool of components.
|
||||
* @param pool A reference to a pool of components.
|
||||
*/
|
||||
explicit View(pool_type &pool) noexcept
|
||||
View(pool_type &pool) noexcept
|
||||
: pool{pool}
|
||||
{}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ private:
|
||||
std::chrono::time_point<std::chrono::system_clock> start;
|
||||
};
|
||||
|
||||
TEST(DefaultRegistry, Construct) {
|
||||
TEST(Benchmark, Construct) {
|
||||
entt::DefaultRegistry registry;
|
||||
|
||||
std::cout << "Constructing 10000000 entities" << std::endl;
|
||||
@@ -44,7 +44,7 @@ TEST(DefaultRegistry, Construct) {
|
||||
timer.elapsed();
|
||||
}
|
||||
|
||||
TEST(DefaultRegistry, Destroy) {
|
||||
TEST(Benchmark, Destroy) {
|
||||
entt::DefaultRegistry registry;
|
||||
std::vector<entt::DefaultRegistry::entity_type> entities{};
|
||||
|
||||
@@ -63,7 +63,7 @@ TEST(DefaultRegistry, Destroy) {
|
||||
timer.elapsed();
|
||||
}
|
||||
|
||||
TEST(DefaultRegistry, IterateCreateDeleteSingleComponent) {
|
||||
TEST(Benchmark, IterateCreateDeleteSingleComponent) {
|
||||
entt::DefaultRegistry registry;
|
||||
|
||||
std::cout << "Looping 10000 times creating and deleting a random number of entities" << std::endl;
|
||||
@@ -87,7 +87,7 @@ TEST(DefaultRegistry, IterateCreateDeleteSingleComponent) {
|
||||
timer.elapsed();
|
||||
}
|
||||
|
||||
TEST(DefaultRegistry, IterateSingleComponent10M) {
|
||||
TEST(Benchmark, IterateSingleComponent10M) {
|
||||
entt::DefaultRegistry registry;
|
||||
|
||||
std::cout << "Iterating over 10000000 entities, one component" << std::endl;
|
||||
@@ -101,7 +101,7 @@ TEST(DefaultRegistry, IterateSingleComponent10M) {
|
||||
timer.elapsed();
|
||||
}
|
||||
|
||||
TEST(DefaultRegistry, IterateTwoComponents10M) {
|
||||
TEST(Benchmark, IterateTwoComponents10M) {
|
||||
entt::DefaultRegistry registry;
|
||||
|
||||
std::cout << "Iterating over 10000000 entities, two components" << std::endl;
|
||||
@@ -115,7 +115,7 @@ TEST(DefaultRegistry, IterateTwoComponents10M) {
|
||||
timer.elapsed();
|
||||
}
|
||||
|
||||
TEST(DefaultRegistry, IterateTwoComponents10MHalf) {
|
||||
TEST(Benchmark, IterateTwoComponents10MHalf) {
|
||||
entt::DefaultRegistry registry;
|
||||
|
||||
std::cout << "Iterating over 10000000 entities, two components, half of the entities have all the components" << std::endl;
|
||||
@@ -130,7 +130,7 @@ TEST(DefaultRegistry, IterateTwoComponents10MHalf) {
|
||||
timer.elapsed();
|
||||
}
|
||||
|
||||
TEST(DefaultRegistry, IterateTwoComponents10MOne) {
|
||||
TEST(Benchmark, IterateTwoComponents10MOne) {
|
||||
entt::DefaultRegistry registry;
|
||||
|
||||
std::cout << "Iterating over 10000000 entities, two components, only one entity has all the components" << std::endl;
|
||||
@@ -145,7 +145,7 @@ TEST(DefaultRegistry, IterateTwoComponents10MOne) {
|
||||
timer.elapsed();
|
||||
}
|
||||
|
||||
TEST(DefaultRegistry, IterateTwoComponentsPersistent10M) {
|
||||
TEST(Benchmark, IterateTwoComponentsPersistent10M) {
|
||||
entt::DefaultRegistry registry;
|
||||
registry.prepare<Position, Velocity>();
|
||||
|
||||
@@ -160,7 +160,7 @@ TEST(DefaultRegistry, IterateTwoComponentsPersistent10M) {
|
||||
timer.elapsed();
|
||||
}
|
||||
|
||||
TEST(DefaultRegistry, IterateTwoComponentsPersistent10MHalf) {
|
||||
TEST(Benchmark, IterateTwoComponentsPersistent10MHalf) {
|
||||
entt::DefaultRegistry registry;
|
||||
registry.prepare<Position, Velocity>();
|
||||
|
||||
@@ -176,7 +176,7 @@ TEST(DefaultRegistry, IterateTwoComponentsPersistent10MHalf) {
|
||||
timer.elapsed();
|
||||
}
|
||||
|
||||
TEST(DefaultRegistry, IterateTwoComponentsPersistent10MOne) {
|
||||
TEST(Benchmark, IterateTwoComponentsPersistent10MOne) {
|
||||
entt::DefaultRegistry registry;
|
||||
registry.prepare<Position, Velocity>();
|
||||
|
||||
@@ -192,7 +192,7 @@ TEST(DefaultRegistry, IterateTwoComponentsPersistent10MOne) {
|
||||
timer.elapsed();
|
||||
}
|
||||
|
||||
TEST(DefaultRegistry, IterateFiveComponents10M) {
|
||||
TEST(Benchmark, IterateFiveComponents10M) {
|
||||
entt::DefaultRegistry registry;
|
||||
|
||||
std::cout << "Iterating over 10000000 entities, five components" << std::endl;
|
||||
@@ -206,7 +206,7 @@ TEST(DefaultRegistry, IterateFiveComponents10M) {
|
||||
timer.elapsed();
|
||||
}
|
||||
|
||||
TEST(DefaultRegistry, IterateTenComponents10M) {
|
||||
TEST(Benchmark, IterateTenComponents10M) {
|
||||
entt::DefaultRegistry registry;
|
||||
|
||||
std::cout << "Iterating over 10000000 entities, ten components" << std::endl;
|
||||
@@ -220,7 +220,7 @@ TEST(DefaultRegistry, IterateTenComponents10M) {
|
||||
timer.elapsed();
|
||||
}
|
||||
|
||||
TEST(DefaultRegistry, IterateTenComponents10MHalf) {
|
||||
TEST(Benchmark, IterateTenComponents10MHalf) {
|
||||
entt::DefaultRegistry registry;
|
||||
|
||||
std::cout << "Iterating over 10000000 entities, ten components, half of the entities have all the components" << std::endl;
|
||||
@@ -235,7 +235,7 @@ TEST(DefaultRegistry, IterateTenComponents10MHalf) {
|
||||
timer.elapsed();
|
||||
}
|
||||
|
||||
TEST(DefaultRegistry, IterateTenComponents10MOne) {
|
||||
TEST(Benchmark, IterateTenComponents10MOne) {
|
||||
entt::DefaultRegistry registry;
|
||||
|
||||
std::cout << "Iterating over 10000000 entities, ten components, only one entity has all the components" << std::endl;
|
||||
@@ -250,7 +250,7 @@ TEST(DefaultRegistry, IterateTenComponents10MOne) {
|
||||
timer.elapsed();
|
||||
}
|
||||
|
||||
TEST(DefaultRegistry, IterateFiveComponentsPersistent10M) {
|
||||
TEST(Benchmark, IterateFiveComponentsPersistent10M) {
|
||||
entt::DefaultRegistry registry;
|
||||
registry.prepare<Position, Velocity, Comp<1>, Comp<2>, Comp<3>>();
|
||||
|
||||
@@ -265,7 +265,7 @@ TEST(DefaultRegistry, IterateFiveComponentsPersistent10M) {
|
||||
timer.elapsed();
|
||||
}
|
||||
|
||||
TEST(DefaultRegistry, IterateTenComponentsPersistent10M) {
|
||||
TEST(Benchmark, IterateTenComponentsPersistent10M) {
|
||||
entt::DefaultRegistry registry;
|
||||
registry.prepare<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>();
|
||||
|
||||
@@ -280,7 +280,7 @@ TEST(DefaultRegistry, IterateTenComponentsPersistent10M) {
|
||||
timer.elapsed();
|
||||
}
|
||||
|
||||
TEST(DefaultRegistry, IterateTenComponentsPersistent10MHalf) {
|
||||
TEST(Benchmark, IterateTenComponentsPersistent10MHalf) {
|
||||
entt::DefaultRegistry registry;
|
||||
registry.prepare<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>();
|
||||
|
||||
@@ -296,7 +296,7 @@ TEST(DefaultRegistry, IterateTenComponentsPersistent10MHalf) {
|
||||
timer.elapsed();
|
||||
}
|
||||
|
||||
TEST(DefaultRegistry, IterateTenComponentsPersistent10MOne) {
|
||||
TEST(Benchmark, IterateTenComponentsPersistent10MOne) {
|
||||
entt::DefaultRegistry registry;
|
||||
registry.prepare<Position, Velocity, Comp<1>, Comp<2>, Comp<3>, Comp<4>, Comp<5>, Comp<6>, Comp<7>, Comp<8>>();
|
||||
|
||||
@@ -312,7 +312,7 @@ TEST(DefaultRegistry, IterateTenComponentsPersistent10MOne) {
|
||||
timer.elapsed();
|
||||
}
|
||||
|
||||
TEST(DefaultRegistry, SortSingle) {
|
||||
TEST(Benchmark, SortSingle) {
|
||||
entt::DefaultRegistry registry;
|
||||
std::vector<entt::DefaultRegistry::entity_type> entities{};
|
||||
|
||||
@@ -332,7 +332,7 @@ TEST(DefaultRegistry, SortSingle) {
|
||||
timer.elapsed();
|
||||
}
|
||||
|
||||
TEST(DefaultRegistry, SortMulti) {
|
||||
TEST(Benchmark, SortMulti) {
|
||||
entt::DefaultRegistry registry;
|
||||
std::vector<entt::DefaultRegistry::entity_type> entities{};
|
||||
|
||||
|
||||
@@ -10,7 +10,9 @@ TEST(SparseSetNoType, Functionalities) {
|
||||
ASSERT_FALSE(set.has(0));
|
||||
ASSERT_FALSE(set.has(42));
|
||||
|
||||
ASSERT_EQ(set.construct(42), 0u);
|
||||
set.construct(42);
|
||||
|
||||
ASSERT_EQ(set.get(42), 0u);
|
||||
|
||||
ASSERT_FALSE(set.empty());
|
||||
ASSERT_EQ(set.size(), 1u);
|
||||
@@ -27,7 +29,9 @@ TEST(SparseSetNoType, Functionalities) {
|
||||
ASSERT_FALSE(set.has(0));
|
||||
ASSERT_FALSE(set.has(42));
|
||||
|
||||
ASSERT_EQ(set.construct(42), 0u);
|
||||
set.construct(42);
|
||||
|
||||
ASSERT_EQ(set.get(42), 0u);
|
||||
|
||||
set.reset();
|
||||
|
||||
@@ -45,9 +49,13 @@ TEST(SparseSetNoType, Functionalities) {
|
||||
TEST(SparseSetNoType, DataBeginEnd) {
|
||||
entt::SparseSet<unsigned int> set;
|
||||
|
||||
ASSERT_EQ(set.construct(3), 0u);
|
||||
ASSERT_EQ(set.construct(12), 1u);
|
||||
ASSERT_EQ(set.construct(42), 2u);
|
||||
set.construct(3);
|
||||
set.construct(12);
|
||||
set.construct(42);
|
||||
|
||||
ASSERT_EQ(set.get(3), 0u);
|
||||
ASSERT_EQ(set.get(12), 1u);
|
||||
ASSERT_EQ(set.get(42), 2u);
|
||||
|
||||
ASSERT_EQ(*(set.data() + 0u), 3u);
|
||||
ASSERT_EQ(*(set.data() + 1u), 12u);
|
||||
@@ -62,6 +70,12 @@ TEST(SparseSetNoType, DataBeginEnd) {
|
||||
ASSERT_EQ(begin, end);
|
||||
}
|
||||
|
||||
TEST(SparseSetWithType, AggregatesMustWork) {
|
||||
struct AggregateType { int value; };
|
||||
// the goal of this test is to enforce the requirements for aggregate types
|
||||
entt::SparseSet<unsigned int, AggregateType>{}.construct(0, 42);
|
||||
}
|
||||
|
||||
TEST(SparseSetWithType, Functionalities) {
|
||||
entt::SparseSet<unsigned int, int> set;
|
||||
|
||||
@@ -71,8 +85,9 @@ TEST(SparseSetWithType, Functionalities) {
|
||||
ASSERT_FALSE(set.has(0));
|
||||
ASSERT_FALSE(set.has(42));
|
||||
|
||||
ASSERT_EQ(set.construct(42, 3), 3);
|
||||
set.construct(42, 3);
|
||||
|
||||
ASSERT_EQ(set.get(42), 3);
|
||||
ASSERT_FALSE(set.empty());
|
||||
ASSERT_EQ(set.size(), 1u);
|
||||
ASSERT_NE(set.begin(), set.end());
|
||||
@@ -88,7 +103,9 @@ TEST(SparseSetWithType, Functionalities) {
|
||||
ASSERT_FALSE(set.has(0));
|
||||
ASSERT_FALSE(set.has(42));
|
||||
|
||||
ASSERT_EQ(set.construct(42, 12), 12);
|
||||
set.construct(42, 12);
|
||||
|
||||
ASSERT_EQ(set.get(42), 12);
|
||||
|
||||
set.reset();
|
||||
|
||||
@@ -106,9 +123,13 @@ TEST(SparseSetWithType, Functionalities) {
|
||||
TEST(SparseSetWithType, RawBeginEnd) {
|
||||
entt::SparseSet<unsigned int, int> set;
|
||||
|
||||
ASSERT_EQ(set.construct(3, 3), 3);
|
||||
ASSERT_EQ(set.construct(12, 6), 6);
|
||||
ASSERT_EQ(set.construct(42, 9), 9);
|
||||
set.construct(3, 3);
|
||||
set.construct(12, 6);
|
||||
set.construct(42, 9);
|
||||
|
||||
ASSERT_EQ(set.get(3), 3);
|
||||
ASSERT_EQ(set.get(12), 6);
|
||||
ASSERT_EQ(set.get(42), 9);
|
||||
|
||||
ASSERT_EQ(*(set.raw() + 0u), 3);
|
||||
ASSERT_EQ(*(set.raw() + 1u), 6);
|
||||
@@ -126,11 +147,17 @@ TEST(SparseSetWithType, RawBeginEnd) {
|
||||
TEST(SparseSetWithType, SortOrdered) {
|
||||
entt::SparseSet<unsigned int, int> set;
|
||||
|
||||
ASSERT_EQ(set.construct(12, 12), 12);
|
||||
ASSERT_EQ(set.construct(42, 9), 9);
|
||||
ASSERT_EQ(set.construct(7, 6), 6);
|
||||
ASSERT_EQ(set.construct(3, 3), 3);
|
||||
ASSERT_EQ(set.construct(9, 1), 1);
|
||||
set.construct(12, 12);
|
||||
set.construct(42, 9);
|
||||
set.construct(7, 6);
|
||||
set.construct(3, 3);
|
||||
set.construct(9, 1);
|
||||
|
||||
ASSERT_EQ(set.get(12), 12);
|
||||
ASSERT_EQ(set.get(42), 9);
|
||||
ASSERT_EQ(set.get(7), 6);
|
||||
ASSERT_EQ(set.get(3), 3);
|
||||
ASSERT_EQ(set.get(9), 1);
|
||||
|
||||
set.sort([&set](auto lhs, auto rhs) {
|
||||
return set.get(lhs) < set.get(rhs);
|
||||
@@ -156,11 +183,17 @@ TEST(SparseSetWithType, SortOrdered) {
|
||||
TEST(SparseSetWithType, SortReverse) {
|
||||
entt::SparseSet<unsigned int, int> set;
|
||||
|
||||
ASSERT_EQ(set.construct(12, 1), 1);
|
||||
ASSERT_EQ(set.construct(42, 3), 3);
|
||||
ASSERT_EQ(set.construct(7, 6), 6);
|
||||
ASSERT_EQ(set.construct(3, 9), 9);
|
||||
ASSERT_EQ(set.construct(9, 12), 12);
|
||||
set.construct(12, 1);
|
||||
set.construct(42, 3);
|
||||
set.construct(7, 6);
|
||||
set.construct(3, 9);
|
||||
set.construct(9, 12);
|
||||
|
||||
ASSERT_EQ(set.get(12), 1);
|
||||
ASSERT_EQ(set.get(42), 3);
|
||||
ASSERT_EQ(set.get(7), 6);
|
||||
ASSERT_EQ(set.get(3), 9);
|
||||
ASSERT_EQ(set.get(9), 12);
|
||||
|
||||
set.sort([&set](auto lhs, auto rhs) {
|
||||
return set.get(lhs) < set.get(rhs);
|
||||
@@ -186,11 +219,17 @@ TEST(SparseSetWithType, SortReverse) {
|
||||
TEST(SparseSetWithType, SortUnordered) {
|
||||
entt::SparseSet<unsigned int, int> set;
|
||||
|
||||
ASSERT_EQ(set.construct(12, 6), 6);
|
||||
ASSERT_EQ(set.construct(42, 3), 3);
|
||||
ASSERT_EQ(set.construct(7, 1), 1);
|
||||
ASSERT_EQ(set.construct(3, 9), 9);
|
||||
ASSERT_EQ(set.construct(9, 12), 12);
|
||||
set.construct(12, 6);
|
||||
set.construct(42, 3);
|
||||
set.construct(7, 1);
|
||||
set.construct(3, 9);
|
||||
set.construct(9, 12);
|
||||
|
||||
ASSERT_EQ(set.get(12), 6);
|
||||
ASSERT_EQ(set.get(42), 3);
|
||||
ASSERT_EQ(set.get(7), 1);
|
||||
ASSERT_EQ(set.get(3), 9);
|
||||
ASSERT_EQ(set.get(9), 12);
|
||||
|
||||
set.sort([&set](auto lhs, auto rhs) {
|
||||
return set.get(lhs) < set.get(rhs);
|
||||
@@ -218,9 +257,13 @@ TEST(SparseSetWithType, RespectDisjoint) {
|
||||
entt::SparseSet<unsigned int, int> rhs;
|
||||
const auto &clhs = lhs;
|
||||
|
||||
ASSERT_EQ(lhs.construct(3, 3), 3);
|
||||
ASSERT_EQ(lhs.construct(12, 6), 6);
|
||||
ASSERT_EQ(lhs.construct(42, 9), 9);
|
||||
lhs.construct(3, 3);
|
||||
lhs.construct(12, 6);
|
||||
lhs.construct(42, 9);
|
||||
|
||||
ASSERT_EQ(lhs.get(3), 3);
|
||||
ASSERT_EQ(lhs.get(12), 6);
|
||||
ASSERT_EQ(lhs.get(42), 9);
|
||||
|
||||
lhs.respect(rhs);
|
||||
|
||||
@@ -242,10 +285,15 @@ TEST(SparseSetWithType, RespectOverlap) {
|
||||
entt::SparseSet<unsigned int, int> rhs;
|
||||
const auto &clhs = lhs;
|
||||
|
||||
ASSERT_EQ(lhs.construct(3, 3), 3);
|
||||
ASSERT_EQ(lhs.construct(12, 6), 6);
|
||||
ASSERT_EQ(lhs.construct(42, 9), 9);
|
||||
ASSERT_EQ(rhs.construct(12, 6), 6);
|
||||
lhs.construct(3, 3);
|
||||
lhs.construct(12, 6);
|
||||
lhs.construct(42, 9);
|
||||
rhs.construct(12, 6);
|
||||
|
||||
ASSERT_EQ(lhs.get(3), 3);
|
||||
ASSERT_EQ(lhs.get(12), 6);
|
||||
ASSERT_EQ(lhs.get(42), 9);
|
||||
ASSERT_EQ(rhs.get(12), 6);
|
||||
|
||||
lhs.respect(rhs);
|
||||
|
||||
@@ -266,18 +314,31 @@ TEST(SparseSetWithType, RespectOrdered) {
|
||||
entt::SparseSet<unsigned int, int> lhs;
|
||||
entt::SparseSet<unsigned int, int> rhs;
|
||||
|
||||
ASSERT_EQ(lhs.construct(1, 0), 0);
|
||||
ASSERT_EQ(lhs.construct(2, 0), 0);
|
||||
ASSERT_EQ(lhs.construct(3, 0), 0);
|
||||
ASSERT_EQ(lhs.construct(4, 0), 0);
|
||||
ASSERT_EQ(lhs.construct(5, 0), 0);
|
||||
lhs.construct(1, 0);
|
||||
lhs.construct(2, 0);
|
||||
lhs.construct(3, 0);
|
||||
lhs.construct(4, 0);
|
||||
lhs.construct(5, 0);
|
||||
|
||||
ASSERT_EQ(rhs.construct(6, 0), 0);
|
||||
ASSERT_EQ(rhs.construct(1, 0), 0);
|
||||
ASSERT_EQ(rhs.construct(2, 0), 0);
|
||||
ASSERT_EQ(rhs.construct(3, 0), 0);
|
||||
ASSERT_EQ(rhs.construct(4, 0), 0);
|
||||
ASSERT_EQ(rhs.construct(5, 0), 0);
|
||||
ASSERT_EQ(lhs.get(1), 0);
|
||||
ASSERT_EQ(lhs.get(2), 0);
|
||||
ASSERT_EQ(lhs.get(3), 0);
|
||||
ASSERT_EQ(lhs.get(4), 0);
|
||||
ASSERT_EQ(lhs.get(5), 0);
|
||||
|
||||
rhs.construct(6, 0);
|
||||
rhs.construct(1, 0);
|
||||
rhs.construct(2, 0);
|
||||
rhs.construct(3, 0);
|
||||
rhs.construct(4, 0);
|
||||
rhs.construct(5, 0);
|
||||
|
||||
ASSERT_EQ(rhs.get(6), 0);
|
||||
ASSERT_EQ(rhs.get(1), 0);
|
||||
ASSERT_EQ(rhs.get(2), 0);
|
||||
ASSERT_EQ(rhs.get(3), 0);
|
||||
ASSERT_EQ(rhs.get(4), 0);
|
||||
ASSERT_EQ(rhs.get(5), 0);
|
||||
|
||||
rhs.respect(lhs);
|
||||
|
||||
@@ -299,18 +360,31 @@ TEST(SparseSetWithType, RespectReverse) {
|
||||
entt::SparseSet<unsigned int, int> lhs;
|
||||
entt::SparseSet<unsigned int, int> rhs;
|
||||
|
||||
ASSERT_EQ(lhs.construct(1, 0), 0);
|
||||
ASSERT_EQ(lhs.construct(2, 0), 0);
|
||||
ASSERT_EQ(lhs.construct(3, 0), 0);
|
||||
ASSERT_EQ(lhs.construct(4, 0), 0);
|
||||
ASSERT_EQ(lhs.construct(5, 0), 0);
|
||||
lhs.construct(1, 0);
|
||||
lhs.construct(2, 0);
|
||||
lhs.construct(3, 0);
|
||||
lhs.construct(4, 0);
|
||||
lhs.construct(5, 0);
|
||||
|
||||
ASSERT_EQ(rhs.construct(5, 0), 0);
|
||||
ASSERT_EQ(rhs.construct(4, 0), 0);
|
||||
ASSERT_EQ(rhs.construct(3, 0), 0);
|
||||
ASSERT_EQ(rhs.construct(2, 0), 0);
|
||||
ASSERT_EQ(rhs.construct(1, 0), 0);
|
||||
ASSERT_EQ(rhs.construct(6, 0), 0);
|
||||
ASSERT_EQ(lhs.get(1), 0);
|
||||
ASSERT_EQ(lhs.get(2), 0);
|
||||
ASSERT_EQ(lhs.get(3), 0);
|
||||
ASSERT_EQ(lhs.get(4), 0);
|
||||
ASSERT_EQ(lhs.get(5), 0);
|
||||
|
||||
rhs.construct(5, 0);
|
||||
rhs.construct(4, 0);
|
||||
rhs.construct(3, 0);
|
||||
rhs.construct(2, 0);
|
||||
rhs.construct(1, 0);
|
||||
rhs.construct(6, 0);
|
||||
|
||||
ASSERT_EQ(rhs.get(5), 0);
|
||||
ASSERT_EQ(rhs.get(4), 0);
|
||||
ASSERT_EQ(rhs.get(3), 0);
|
||||
ASSERT_EQ(rhs.get(2), 0);
|
||||
ASSERT_EQ(rhs.get(1), 0);
|
||||
ASSERT_EQ(rhs.get(6), 0);
|
||||
|
||||
rhs.respect(lhs);
|
||||
|
||||
@@ -332,18 +406,31 @@ TEST(SparseSetWithType, RespectUnordered) {
|
||||
entt::SparseSet<unsigned int, int> lhs;
|
||||
entt::SparseSet<unsigned int, int> rhs;
|
||||
|
||||
ASSERT_EQ(lhs.construct(1, 0), 0);
|
||||
ASSERT_EQ(lhs.construct(2, 0), 0);
|
||||
ASSERT_EQ(lhs.construct(3, 0), 0);
|
||||
ASSERT_EQ(lhs.construct(4, 0), 0);
|
||||
ASSERT_EQ(lhs.construct(5, 0), 0);
|
||||
lhs.construct(1, 0);
|
||||
lhs.construct(2, 0);
|
||||
lhs.construct(3, 0);
|
||||
lhs.construct(4, 0);
|
||||
lhs.construct(5, 0);
|
||||
|
||||
ASSERT_EQ(rhs.construct(3, 0), 0);
|
||||
ASSERT_EQ(rhs.construct(2, 0), 0);
|
||||
ASSERT_EQ(rhs.construct(6, 0), 0);
|
||||
ASSERT_EQ(rhs.construct(1, 0), 0);
|
||||
ASSERT_EQ(rhs.construct(4, 0), 0);
|
||||
ASSERT_EQ(rhs.construct(5, 0), 0);
|
||||
ASSERT_EQ(lhs.get(1), 0);
|
||||
ASSERT_EQ(lhs.get(2), 0);
|
||||
ASSERT_EQ(lhs.get(3), 0);
|
||||
ASSERT_EQ(lhs.get(4), 0);
|
||||
ASSERT_EQ(lhs.get(5), 0);
|
||||
|
||||
rhs.construct(3, 0);
|
||||
rhs.construct(2, 0);
|
||||
rhs.construct(6, 0);
|
||||
rhs.construct(1, 0);
|
||||
rhs.construct(4, 0);
|
||||
rhs.construct(5, 0);
|
||||
|
||||
ASSERT_EQ(rhs.get(3), 0);
|
||||
ASSERT_EQ(rhs.get(2), 0);
|
||||
ASSERT_EQ(rhs.get(6), 0);
|
||||
ASSERT_EQ(rhs.get(1), 0);
|
||||
ASSERT_EQ(rhs.get(4), 0);
|
||||
ASSERT_EQ(rhs.get(5), 0);
|
||||
|
||||
rhs.respect(lhs);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user