mirror of
https://github.com/BlackMATov/ecs.hpp.git
synced 2025-12-13 10:35:39 +07:00
empty component storage optimization
This commit is contained in:
187
ecs.hpp
187
ecs.hpp
@@ -659,103 +659,142 @@ namespace ecs_hpp
|
||||
virtual std::size_t memory_usage() const noexcept = 0;
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
template < typename T, bool E = std::is_empty<T>::value >
|
||||
class component_storage final : public component_storage_base {
|
||||
public:
|
||||
component_storage(registry& owner);
|
||||
component_storage(registry& owner)
|
||||
: owner_(owner) {}
|
||||
|
||||
template < typename... Args >
|
||||
T& assign(entity_id id, Args&&... args);
|
||||
bool exists(entity_id id) const noexcept;
|
||||
bool remove(entity_id id) noexcept override;
|
||||
T& assign(entity_id id, Args&&... args) {
|
||||
components_.insert_or_assign(id, T(std::forward<Args>(args)...));
|
||||
return components_.get(id);
|
||||
}
|
||||
|
||||
T* find(entity_id id) noexcept;
|
||||
const T* find(entity_id id) const noexcept;
|
||||
bool exists(entity_id id) const noexcept {
|
||||
return components_.has(id);
|
||||
}
|
||||
|
||||
std::size_t count() const noexcept;
|
||||
bool has(entity_id id) const noexcept override;
|
||||
void clone(entity_id from, entity_id to) override;
|
||||
bool remove(entity_id id) noexcept override {
|
||||
return components_.unordered_erase(id);
|
||||
}
|
||||
|
||||
T* find(entity_id id) noexcept {
|
||||
return components_.find(id);
|
||||
}
|
||||
|
||||
const T* find(entity_id id) const noexcept {
|
||||
return components_.find(id);
|
||||
}
|
||||
|
||||
std::size_t count() const noexcept {
|
||||
return components_.size();
|
||||
}
|
||||
|
||||
bool has(entity_id id) const noexcept override {
|
||||
return components_.has(id);
|
||||
}
|
||||
|
||||
void clone(entity_id from, entity_id to) override {
|
||||
const T* c = components_.find(from);
|
||||
if ( c ) {
|
||||
components_.insert_or_assign(to, *c);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename F >
|
||||
void for_each_component(F&& f);
|
||||
template < typename F >
|
||||
void for_each_component(F&& f) const;
|
||||
void for_each_component(F&& f) {
|
||||
for ( const entity_id id : components_ ) {
|
||||
f(id, components_.get(id));
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t memory_usage() const noexcept override;
|
||||
template < typename F >
|
||||
void for_each_component(F&& f) const {
|
||||
for ( const entity_id id : components_ ) {
|
||||
f(id, components_.get(id));
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t memory_usage() const noexcept override {
|
||||
return components_.memory_usage();
|
||||
}
|
||||
private:
|
||||
registry& owner_;
|
||||
detail::sparse_map<entity_id, T, entity_id_indexer> components_;
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
component_storage<T>::component_storage(registry& owner)
|
||||
: owner_(owner) {}
|
||||
class component_storage<T, true> final : public component_storage_base {
|
||||
public:
|
||||
component_storage(registry& owner)
|
||||
: owner_(owner) {}
|
||||
|
||||
template < typename T >
|
||||
template < typename... Args >
|
||||
T& component_storage<T>::assign(entity_id id, Args&&... args) {
|
||||
components_.insert_or_assign(id, T(std::forward<Args>(args)...));
|
||||
return components_.get(id);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
bool component_storage<T>::exists(entity_id id) const noexcept {
|
||||
return components_.has(id);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
bool component_storage<T>::remove(entity_id id) noexcept {
|
||||
return components_.unordered_erase(id);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
T* component_storage<T>::find(entity_id id) noexcept {
|
||||
return components_.find(id);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
const T* component_storage<T>::find(entity_id id) const noexcept {
|
||||
return components_.find(id);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
std::size_t component_storage<T>::count() const noexcept {
|
||||
return components_.size();
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
bool component_storage<T>::has(entity_id id) const noexcept {
|
||||
return components_.has(id);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
void component_storage<T>::clone(entity_id from, entity_id to) {
|
||||
const T* c = components_.find(from);
|
||||
if ( c ) {
|
||||
components_.insert_or_assign(to, *c);
|
||||
template < typename... Args >
|
||||
T& assign(entity_id id, Args&&... args) {
|
||||
components_.insert(id);
|
||||
return empty_value_;
|
||||
}
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
template < typename F >
|
||||
void component_storage<T>::for_each_component(F&& f) {
|
||||
for ( const entity_id id : components_ ) {
|
||||
f(id, components_.get(id));
|
||||
bool exists(entity_id id) const noexcept {
|
||||
return components_.has(id);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
template < typename F >
|
||||
void component_storage<T>::for_each_component(F&& f) const {
|
||||
for ( const entity_id id : components_ ) {
|
||||
f(id, components_.get(id));
|
||||
bool remove(entity_id id) noexcept override {
|
||||
return components_.unordered_erase(id);
|
||||
}
|
||||
}
|
||||
|
||||
T* find(entity_id id) noexcept {
|
||||
return components_.has(id)
|
||||
? &empty_value_
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
const T* find(entity_id id) const noexcept {
|
||||
return components_.has(id)
|
||||
? &empty_value_
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
std::size_t count() const noexcept {
|
||||
return components_.size();
|
||||
}
|
||||
|
||||
bool has(entity_id id) const noexcept override {
|
||||
return components_.has(id);
|
||||
}
|
||||
|
||||
void clone(entity_id from, entity_id to) override {
|
||||
if ( components_.has(from) ) {
|
||||
components_.insert(to);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename F >
|
||||
void for_each_component(F&& f) {
|
||||
for ( const entity_id id : components_ ) {
|
||||
f(id, empty_value_);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename F >
|
||||
void for_each_component(F&& f) const {
|
||||
for ( const entity_id id : components_ ) {
|
||||
f(id, empty_value_);
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t memory_usage() const noexcept override {
|
||||
return components_.memory_usage();
|
||||
}
|
||||
private:
|
||||
registry& owner_;
|
||||
static T empty_value_;
|
||||
detail::sparse_set<entity_id, entity_id_indexer> components_;
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
std::size_t component_storage<T>::memory_usage() const noexcept {
|
||||
return components_.memory_usage();
|
||||
}
|
||||
T component_storage<T, true>::empty_value_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,10 @@ namespace
|
||||
velocity_c(int nx, int ny) : x(nx), y(ny) {}
|
||||
};
|
||||
|
||||
struct movable_c {
|
||||
};
|
||||
static_assert(std::is_empty<movable_c>::value, "!!!");
|
||||
|
||||
bool operator==(const position_c& l, const position_c& r) noexcept {
|
||||
return l.x == r.x
|
||||
&& l.y == r.y;
|
||||
@@ -1226,6 +1230,29 @@ TEST_CASE("registry") {
|
||||
3 * sizeof(std::size_t) +
|
||||
1 * sizeof(ecs::entity_id));
|
||||
}
|
||||
{
|
||||
ecs::registry w;
|
||||
auto e1 = w.create_entity();
|
||||
auto e2 = w.create_entity();
|
||||
e1.assign_component<movable_c>();
|
||||
e2.assign_component<movable_c>();
|
||||
REQUIRE(w.component_memory_usage<movable_c>() ==
|
||||
4 * sizeof(std::size_t) +
|
||||
2 * sizeof(ecs::entity_id));
|
||||
}
|
||||
}
|
||||
SECTION("empty_component") {
|
||||
ecs::registry w;
|
||||
auto e1 = w.create_entity();
|
||||
ecs::entity_filler(e1)
|
||||
.component<movable_c>()
|
||||
.component<position_c>(1, 2)
|
||||
.component<velocity_c>(3, 4);
|
||||
REQUIRE(w.exists_component<movable_c>(e1));
|
||||
REQUIRE(w.find_component<movable_c>(e1));
|
||||
w.for_joined_components<movable_c, position_c>([
|
||||
](const ecs::const_entity&, movable_c&, position_c&){
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user