Support entity removal & explicit traversal in util::ecs
This commit is contained in:
parent
37d1c3c3fd
commit
f55fd29b58
1 changed files with 73 additions and 42 deletions
|
|
@ -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)
|
||||||
{
|
{
|
||||||
std::apply(visit, cptrs);
|
if (*list == i)
|
||||||
|
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,46 +196,30 @@ 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);
|
||||||
|
|
||||||
|
list_.resize(new_size);
|
||||||
|
for (std::size_t i = old_size; i + 1 < new_size; ++i)
|
||||||
|
list_[i] = i + 1;
|
||||||
|
list_[new_size - 1] = null;
|
||||||
|
list_head_ = old_size;
|
||||||
|
|
||||||
|
((std::get<I>(entity_components_).resize(new_size)), ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = list_head_;
|
||||||
|
list_head_ = list_[list_head_];
|
||||||
|
list_[result] = result;
|
||||||
|
entity_count_++;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
|
||||||
struct species_impl<>
|
|
||||||
: species_base
|
|
||||||
{
|
|
||||||
species_impl(std::string name)
|
|
||||||
: name_(std::move(name))
|
|
||||||
{}
|
|
||||||
|
|
||||||
std::string_view name() const override
|
|
||||||
{
|
|
||||||
return name_;
|
|
||||||
}
|
|
||||||
|
|
||||||
using species_base::get_species_component;
|
|
||||||
using species_base::get_entity_component;
|
|
||||||
|
|
||||||
void * get_species_component(std::type_index) override { return nullptr; }
|
|
||||||
void * get_entity_component(std::type_index) override { return nullptr; }
|
|
||||||
|
|
||||||
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>
|
||||||
using prepare_helper = decltype(std::declval<Behavior>().prepare());
|
using prepare_helper = decltype(std::declval<Behavior>().prepare());
|
||||||
|
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue