201 lines
5.1 KiB
C++
201 lines
5.1 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);
|
|
column_uuid_set_.insert(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, 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, 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, 0, 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, column_uuid_set_, true);
|
|
}
|
|
|
|
void table::trigger_constructors(container & container, std::uint32_t row, util::hash_set<util::uuid> const & attached_components)
|
|
{
|
|
for (auto const & callback : *constructors_)
|
|
callback(container, *this, row, attached_components, false);
|
|
}
|
|
|
|
void table::trigger_destructors(container & container, std::uint32_t row)
|
|
{
|
|
for (auto const & callback : *destructors_)
|
|
callback(container, *this, row, column_uuid_set_, true);
|
|
}
|
|
|
|
void table::trigger_destructors(container & container, std::uint32_t row, util::hash_set<util::uuid> const & detached_components)
|
|
{
|
|
for (auto const & callback : *destructors_)
|
|
callback(container, *this, row, detached_components, false);
|
|
}
|
|
|
|
std::size_t table::memory_usage() const
|
|
{
|
|
std::size_t result = 0;
|
|
for (auto const & column : columns_)
|
|
result += column->memory_usage();
|
|
return result;
|
|
}
|
|
|
|
std::string table::describe(std::uint32_t row) const
|
|
{
|
|
std::string result;
|
|
for (std::size_t i = 0; i < columns_.size(); ++i)
|
|
{
|
|
if (i > 0)
|
|
result += ";";
|
|
result += columns_[i]->describe(row);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
}
|