psemek/libs/ecs/source/container.cpp
2023-12-18 12:45:42 +03:00

99 lines
2.8 KiB
C++

#include <psemek/ecs/container.hpp>
namespace psemek::ecs
{
bool container::alive(handle const & entity) const
{
return entity_list_.get_entities()[entity.id].epoch == entity.epoch;
}
void container::destroy(handle const & entity)
{
do_destroy(entity);
entity_list_.destroy(entity.id);
}
accessor container::get(handle const & entity)
{
auto const data = entity_list_.get_entities()[entity.id];
return {data.table, data.row};
}
bool container::can_clone(handle const & entity) const
{
return entity_list_.get_entities()[entity.id].table->non_copyable_components().empty();
}
handle container::clone(handle const & entity)
{
auto const data = entity_list_.get_entities()[entity.id];
if (!data.table->non_copyable_components().empty())
throw entity_not_cloneable(entity, data.table->non_copyable_components());
auto table = data.table;
if (table->get_iteration_data())
table = table->get_delayed_table();
auto id = entity_list_.create(table, table->row_count());
handle handle{id, entity_list_.get_entities()[id].epoch};
table->copy_row(handle, data.table, data.row);
return handle;
}
std::optional<handle> container::try_clone(handle const & entity)
{
auto const data = entity_list_.get_entities()[entity.id];
if (!data.table->non_copyable_components().empty())
return std::nullopt;
auto table = data.table;
if (table->get_iteration_data())
table = table->get_delayed_table();
auto id = entity_list_.create(table, table->row_count());
handle handle{id, entity_list_.get_entities()[id].epoch};
table->copy_row(handle, data.table, data.row);
return handle;
}
detail::table * container::insert_table(std::vector<std::unique_ptr<detail::column>> columns)
{
auto table = table_container_.insert(std::make_unique<detail::table>(std::move(columns)));
query_cache_container_.apply([table](detail::query_cache & cache){
cache.add(table);
}, [table](util::uuid const & uuid){ return table->column(uuid) != nullptr; });
return table;
}
void container::do_destroy(handle const & entity)
{
auto entities = entity_list_.get_entities();
auto & data = entities[entity.id];
auto & iteration_data = data.table->get_iteration_data();
data.table->trigger_destructors(*this, data.row);
if (!iteration_data || iteration_data->current_row < data.row)
remove_row(*data.table, data.row, entities);
else
data.table->push_remove(data.row);
}
void container::remove_row(detail::table & table, std::uint32_t row, util::span<detail::entity_data> entities)
{
// Swap with the last row in that table
auto table_entity_handles = table.entity_handles();
table.swap_rows(row, table_entity_handles.size() - 1);
table.pop_row();
auto swap_handle = table_entity_handles[row];
entities[swap_handle.id].row = row;
}
}