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

168 lines
4.2 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 (std::size_t i = 0; i < columns.size(); ++i)
{
auto const & column = columns[i];
auto uuid = column->uuid();
hasher(uuid);
component_uuid_to_column_index_.insert({uuid, i});
if (!column->copy_constructible())
non_copyable_components_.push_back(column->type());
}
hash_ = hasher.result;
columns_ = std::move(columns);
constructors_ = std::make_shared<std::vector<table_callback>>();
destructors_ = std::make_shared<std::vector<table_callback>>();
}
std::optional<std::size_t> table::column_index(util::uuid const & uuid) const
{
if (auto it = component_uuid_to_column_index_.find(uuid); it != component_uuid_to_column_index_.end())
return it->second;
return std::nullopt;
}
column * table::column(util::uuid const & uuid) const
{
if (auto index = column_index(uuid))
return columns_[*index].get();
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;
}
std::size_t table::copy_row(handle handle, table * from, std::size_t from_row)
{
for (std::size_t i = 0; i < columns_.size(); ++i)
{
auto from_column = from->columns_[i].get();
columns_[i]->insert_rows(from_column->data() + from_column->stride() * from_row, 1);
}
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());
auto result = std::make_unique<table>(std::move(columns));
result->constructors_ = constructors_;
result->destructors_ = destructors_;
return result;
}
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};
}
std::vector<std::type_index> const & table::non_copyable_components() const
{
return non_copyable_components_;
}
void table::add_constructor(table_callback callback)
{
constructors_->push_back(std::move(callback));
}
void table::add_destructor(table_callback callback)
{
destructors_->push_back(std::move(callback));
}
void table::trigger_constructors(container & container, std::uint32_t row)
{
for (auto const & callback : *constructors_)
callback(container, *this, row);
}
void table::trigger_destructors(container & container, std::uint32_t row)
{
for (auto const & callback : *destructors_)
callback(container, *this, row);
}
}