Support entity removal & explicit traversal in util::ecs

This commit is contained in:
Nikita Lisitsa 2021-07-22 10:51:03 +03:00
parent 37d1c3c3fd
commit f55fd29b58

View file

@ -43,6 +43,12 @@ namespace psemek::util
virtual handle entity_count() const = 0; virtual handle entity_count() const = 0;
virtual handle add_entity() = 0; virtual handle add_entity() = 0;
virtual void remove_entity(handle h) = 0;
bool entity_active(handle h)
{
return get_free_list()[h] == h;
}
template <typename Behavior> template <typename Behavior>
void apply(Behavior & behavior) void apply(Behavior & behavior)
@ -52,6 +58,11 @@ namespace psemek::util
virtual ~species_base() {} virtual ~species_base() {}
static constexpr handle null = static_cast<handle>(-1);
virtual handle const * get_free_list() = 0;
virtual std::size_t list_size() const = 0;
private: private:
template <typename Behavior, typename ... Components> template <typename Behavior, typename ... Components>
@ -90,12 +101,16 @@ namespace psemek::util
((++ptrs), ...); ((++ptrs), ...);
}; };
std::size_t const count = entity_count(); auto list = get_free_list();
std::size_t const count = list_size();
for (std::size_t i = 0; i < count; ++i) for (std::size_t i = 0; i < count; ++i)
{ {
if (*list == i)
std::apply(visit, cptrs); std::apply(visit, cptrs);
std::apply(increment, cptrs); std::apply(increment, cptrs);
++list;
} }
} }
}; };
@ -129,20 +144,38 @@ namespace psemek::util
handle entity_count() const override handle entity_count() const override
{ {
return std::get<0>(entity_components_).size(); return entity_count_;
} }
handle add_entity() override handle add_entity() override
{ {
handle result = entity_count(); return add_entity_impl(std::make_index_sequence<sizeof...(Components)>{});
add_entity_impl(std::make_index_sequence<sizeof...(Components)>{}); }
return result;
void remove_entity(handle h) override
{
list_[h] = list_head_;
list_head_ = h;
--entity_count_;
}
handle const * get_free_list() override
{
return list_.data();
}
std::size_t list_size() const override
{
return list_.size();
} }
private: private:
std::string name_; std::string name_;
std::tuple<Components...> species_components_; std::tuple<Components...> species_components_;
std::tuple<std::vector<typename Components::data>...> entity_components_; std::tuple<std::vector<typename Components::data>...> entity_components_;
std::vector<handle> list_;
handle list_head_ = null;
std::size_t entity_count_ = 0;
template <std::size_t ... I> template <std::size_t ... I>
void * get_species_component_impl(std::type_index component_type, std::index_sequence<I...>) void * get_species_component_impl(std::type_index component_type, std::index_sequence<I...>)
@ -163,44 +196,28 @@ namespace psemek::util
} }
template <std::size_t ... I> template <std::size_t ... I>
void add_entity_impl(std::index_sequence<I...>) handle add_entity_impl(std::index_sequence<I...>)
{ {
((std::get<I>(entity_components_).emplace_back()), ...); if (list_head_ == null)
} {
}; std::size_t const old_size = list_.size();
std::size_t const new_size = std::max<std::size_t>(16, old_size * 2);
template <> list_.resize(new_size);
struct species_impl<> for (std::size_t i = old_size; i + 1 < new_size; ++i)
: species_base list_[i] = i + 1;
{ list_[new_size - 1] = null;
species_impl(std::string name) list_head_ = old_size;
: name_(std::move(name))
{}
std::string_view name() const override ((std::get<I>(entity_components_).resize(new_size)), ...);
{
return name_;
} }
using species_base::get_species_component; auto result = list_head_;
using species_base::get_entity_component; list_head_ = list_[list_head_];
list_[result] = result;
void * get_species_component(std::type_index) override { return nullptr; } entity_count_++;
void * get_entity_component(std::type_index) override { return nullptr; } return result;
virtual handle entity_count() const
{
return entity_count_;
} }
virtual handle add_entity()
{
return entity_count_++;
}
private:
std::string name_;
std::size_t entity_count_ = 0;
}; };
template <typename Behavior> template <typename Behavior>
@ -227,6 +244,10 @@ namespace psemek::util
handle add_entity(handle species); handle add_entity(handle species);
handle entity_count(handle species) const; handle entity_count(handle species) const;
void remove_entity(handle species, handle entity);
bool entity_active(handle species, handle entity);
handle capacity(handle species) const { return species_[species]->list_size(); }
template <typename Component> template <typename Component>
Component & get(handle species); Component & get(handle species);
@ -265,6 +286,16 @@ namespace psemek::util
return species_[species]->entity_count(); return species_[species]->entity_count();
} }
inline void ecs::remove_entity(handle species, handle entity)
{
species_[species]->remove_entity(entity);
}
inline bool ecs::entity_active(handle species, handle entity)
{
return species_[species]->entity_active(entity);
}
template <typename Component> template <typename Component>
Component & ecs::get(handle species) Component & ecs::get(handle species)
{ {