psemek/libs/ecs/source/detail/table.cpp
2023-12-16 23:01:06 +03:00

113 lines
2.6 KiB
C++

#include <psemek/ecs/detail/table.hpp>
#include <psemek/ecs/detail/component_hash.hpp>
namespace psemek::ecs::detail
{
table::table(std::vector<std::unique_ptr<detail::column>> columns)
{
component_hasher<true> hasher;
for (auto & column : columns)
{
auto uuid = column->uuid();
hasher(uuid);
component_uuid_to_column_.insert({uuid, column.get()});
}
hash_ = hasher.result;
columns_ = std::move(columns);
}
detail::column * table::column(util::uuid const & uuid) const
{
if (auto it = component_uuid_to_column_.find(uuid); it != component_uuid_to_column_.end())
return it->second;
return nullptr;
}
std::size_t table::push_row(handle handle)
{
for (auto & column : columns_)
column->push_row();
entity_handles_.push_back(handle);
return entity_handles_.size() - 1;
}
std::size_t table::move_row(handle handle, table * from, std::size_t from_row)
{
for (auto & column : columns_)
{
if (auto other_column = from->column(column->uuid()))
column->emplace_rows(other_column->data() + other_column->stride() * from_row, 1);
else
column->push_row();
}
entity_handles_.push_back(handle);
return entity_handles_.size() - 1;
}
void table::swap_rows(std::size_t row1, std::size_t row2)
{
for (auto & column : columns_)
column->swap_rows(row1, row2);
std::swap(entity_handles_[row1], entity_handles_[row2]);
}
void table::pop_row()
{
for (auto & column : columns_)
column->pop_row();
entity_handles_.pop_back();
}
void table::clear()
{
for (auto & column : columns_)
column->clear();
entity_handles_.clear();
}
void table::push_remove(std::uint32_t row)
{
remove_queue_.push_back(row);
}
std::vector<std::uint32_t> table::grab_remove_queue()
{
return std::move(remove_queue_);
}
std::unique_ptr<table> table::clone() const
{
std::vector<std::unique_ptr<detail::column>> columns;
for (auto const & column : columns_)
columns.push_back(column->clone());
return std::make_unique<table>(std::move(columns));
}
table * table::get_delayed_table()
{
if (!delayed_table_)
delayed_table_ = clone();
return delayed_table_.get();
}
util::span<handle const> table::flush_delayed()
{
if (!delayed_table_)
return {};
std::size_t count = delayed_table_->row_count();
for (std::size_t i = 0; i < columns_.size(); ++i)
{
auto * src_column = delayed_table_->columns_[i].get();
columns_[i]->emplace_rows(src_column->data(), count);
}
entity_handles_.insert(entity_handles_.end(), delayed_table_->entity_handles_.begin(), delayed_table_->entity_handles_.end());
delayed_table_->clear();
return {entity_handles_.data() + entity_handles_.size() - count, count};
}
}