#include #include #include namespace psemek::ecs::detail { table::table(std::vector> columns) { unordered_component_hasher 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>(); destructors_ = std::make_shared>(); } std::optional 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 table::grab_remove_queue() { return std::move(remove_queue_); } std::unique_ptr table::clone() const { std::vector> columns; for (auto const & column : columns_) columns.push_back(column->clone()); auto result = std::make_unique
(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 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 const & table::non_copyable_components() const { return non_copyable_components_; } void table::add_constructor(ordered_table_callback callback) { auto it = std::upper_bound(constructors_->begin(), constructors_->end(), callback); constructors_->insert(it, std::move(callback)); } void table::add_destructor(ordered_table_callback callback) { auto it = std::upper_bound(destructors_->begin(), destructors_->end(), callback); destructors_->insert(it, std::move(callback)); } void table::trigger_constructors(container & container, std::uint32_t row) { for (auto const & callback : *constructors_) callback.callback(container, *this, row, column_uuid_set_, true); } void table::trigger_constructors(container & container, std::uint32_t row, util::hash_set const & attached_components) { for (auto const & callback : *constructors_) callback.callback(container, *this, row, attached_components, false); } void table::trigger_destructors(container & container, std::uint32_t row) { for (auto const & callback : *destructors_) callback.callback(container, *this, row, column_uuid_set_, true); } void table::trigger_destructors(container & container, std::uint32_t row, util::hash_set const & detached_components) { for (auto const & callback : *destructors_) callback.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() const { std::string result; for (std::size_t i = 0; i < columns_.size(); ++i) { if (i > 0) result += ";"; result += columns_[i]->describe(); } 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; } }