Refactor ecs::entity_container & add documentation

This commit is contained in:
Nikita Lisitsa 2023-08-22 22:36:04 +03:00
parent c1991cbb57
commit 82682c0317
2 changed files with 116 additions and 79 deletions

View file

@ -15,8 +15,47 @@ namespace psemek::ecs
struct entity_container struct entity_container
{ {
// Create an entity with the specified components
// NB: equivalent to create() followed by a
// series of attach() calls, but faster
template <typename ... Components> template <typename ... Components>
entity_handle create(Components && ... components) entity_handle create(Components && ... components);
// Check if an entity handle refers to an active entity
// UB if the handle wasn't obtained by a create() call
bool alive(entity_handle const & entity) const;
// Destroy an entity
// UB if the handle wasn't obtained by a create() call
// or if the entity was already destroyed
void destroy(entity_handle const & entity);
// Get an entity accessor for an entity
// UB if the handle wasn't obtained by a create() call
// or if the entity isn't active
entity_accessor get(entity_handle const & entity);
// Create a query cache that can be used for the
// apply() call to speed it up
template <typename ... Components>
query_cache cache();
// Apply a function to all entities having the specified
// components. The function signature is void(entity_handle, components...)
// An optional query cache can be supplied to speed up the call
// UB if the cache wasn't created with the exact same component sequence
template <typename ... Components, typename Function>
void apply(Function && function, query_cache cache = {});
private:
detail::entity_list entity_list_;
mutable detail::component_index component_index_;
detail::table_container table_container_;
detail::query_cache_container query_cache_container_;
};
template <typename ... Components>
entity_handle entity_container::create(Components && ... components)
{ {
detail::component_uuid_holder<Components...> uuids; detail::component_uuid_holder<Components...> uuids;
detail::component_mask mask = component_index_.make_component_mask(uuids.get()); detail::component_mask mask = component_index_.make_component_mask(uuids.get());
@ -42,27 +81,8 @@ namespace psemek::ecs
return handle; return handle;
} }
bool alive(entity_handle const & entity) const
{
return entity_list_.get_entities()[entity.id].epoch == entity.epoch;
}
void destroy(entity_handle const & entity)
{
// Swap with the last row in that table
auto entities = entity_list_.get_entities();
auto & data = entities[entity.id];
auto table_entity_ids = data.table->get_entity_ids();
data.table->swap_rows(data.row, table_entity_ids.size() - 1);
data.table->pop_row();
auto swap_id = table_entity_ids[data.row];
auto & swap_data = entities[swap_id];
swap_data.row = data.row;
entity_list_.destroy(entity.id);
}
template <typename ... Components> template <typename ... Components>
query_cache cache() query_cache entity_container::cache()
{ {
detail::component_uuid_holder<Components...> uuids; detail::component_uuid_holder<Components...> uuids;
detail::component_mask mask = component_index_.make_component_mask(uuids.get()); detail::component_mask mask = component_index_.make_component_mask(uuids.get());
@ -77,7 +97,7 @@ namespace psemek::ecs
} }
template <typename ... Components, typename Function> template <typename ... Components, typename Function>
void apply(Function && function, query_cache cache = {}) void entity_container::apply(Function && function, query_cache cache)
{ {
if (!cache) if (!cache)
cache = this->cache<Components...>(); cache = this->cache<Components...>();
@ -96,18 +116,4 @@ namespace psemek::ecs
} }
} }
} }
entity_accessor get(entity_handle const & entity)
{
auto const & data = entity_list_.get_entities()[entity.id];
return {data.table, data.row};
}
private:
detail::entity_list entity_list_;
mutable detail::component_index component_index_;
detail::table_container table_container_;
detail::query_cache_container query_cache_container_;
};
} }

View file

@ -0,0 +1,31 @@
#include <psemek/ecs/entity_container.hpp>
namespace psemek::ecs
{
bool entity_container::alive(entity_handle const & entity) const
{
return entity_list_.get_entities()[entity.id].epoch == entity.epoch;
}
void entity_container::destroy(entity_handle const & entity)
{
// Swap with the last row in that table
auto entities = entity_list_.get_entities();
auto & data = entities[entity.id];
auto table_entity_ids = data.table->get_entity_ids();
data.table->swap_rows(data.row, table_entity_ids.size() - 1);
data.table->pop_row();
auto swap_id = table_entity_ids[data.row];
auto & swap_data = entities[swap_id];
swap_data.row = data.row;
entity_list_.destroy(entity.id);
}
entity_accessor entity_container::get(entity_handle const & entity)
{
auto const & data = entity_list_.get_entities()[entity.id];
return {data.table, data.row};
}
}