Implement util::ecs packed/sparse policy
This commit is contained in:
parent
0cb197a6c4
commit
70f3b68077
1 changed files with 124 additions and 39 deletions
|
|
@ -63,8 +63,6 @@ namespace psemek::util
|
|||
|
||||
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;
|
||||
|
||||
|
|
@ -112,26 +110,40 @@ namespace psemek::util
|
|||
|
||||
auto list = get_free_list();
|
||||
|
||||
std::size_t const count = list_size();
|
||||
|
||||
for (std::size_t i = 0; i < count; ++i)
|
||||
if (list)
|
||||
{
|
||||
if (*list == i)
|
||||
// sparse
|
||||
std::size_t const size = list_size();
|
||||
for (std::size_t i = 0; i < size; ++i)
|
||||
{
|
||||
if (*list == i)
|
||||
{
|
||||
ctx.entity = i;
|
||||
std::apply(visit, cptrs);
|
||||
}
|
||||
std::apply(increment, cptrs);
|
||||
++list;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// packed
|
||||
std::size_t const size = entity_count();
|
||||
for (std::size_t i = 0; i < size; ++i)
|
||||
{
|
||||
ctx.entity = i;
|
||||
std::apply(visit, cptrs);
|
||||
std::apply(increment, cptrs);
|
||||
}
|
||||
std::apply(increment, cptrs);
|
||||
++list;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ... Components>
|
||||
struct species_impl
|
||||
struct species_impl_base
|
||||
: species_base
|
||||
{
|
||||
species_impl(std::string name, handle id, Components && ... components)
|
||||
species_impl_base(std::string name, handle id, Components && ... components)
|
||||
: species_base(std::move(name), id)
|
||||
, species_components_{std::move(components)...}
|
||||
{}
|
||||
|
|
@ -149,6 +161,37 @@ namespace psemek::util
|
|||
return get_entity_component_impl(component_type, std::make_index_sequence<sizeof...(Components)>{});
|
||||
}
|
||||
|
||||
protected:
|
||||
std::tuple<Components...> species_components_;
|
||||
std::tuple<std::vector<typename Components::data>...> entity_components_;
|
||||
|
||||
template <std::size_t ... I>
|
||||
void * get_species_component_impl(std::type_index component_type, std::index_sequence<I...>)
|
||||
{
|
||||
void * result = nullptr;
|
||||
|
||||
((result = (component_type == typeid(std::tuple_element_t<I, std::tuple<Components...>>)) ? &std::get<I>(species_components_) : result), ...);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <std::size_t ... I>
|
||||
void * get_entity_component_impl(std::type_index component_type, std::index_sequence<I...>)
|
||||
{
|
||||
void * result = nullptr;
|
||||
|
||||
((result = (component_type == typeid(std::tuple_element_t<I, std::tuple<Components...>>)) ? std::get<I>(entity_components_).data() : result), ...);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ... Components>
|
||||
struct sparse_species_impl final
|
||||
: species_impl_base<Components...>
|
||||
{
|
||||
using species_impl_base<Components...>::species_impl_base;
|
||||
|
||||
static constexpr handle null = static_cast<handle>(-1);
|
||||
|
||||
handle entity_count() const override
|
||||
{
|
||||
return entity_count_;
|
||||
|
|
@ -177,30 +220,10 @@ namespace psemek::util
|
|||
}
|
||||
|
||||
private:
|
||||
std::tuple<Components...> species_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>
|
||||
void * get_species_component_impl(std::type_index component_type, std::index_sequence<I...>)
|
||||
{
|
||||
void * result = nullptr;
|
||||
|
||||
((result = (component_type == typeid(std::tuple_element_t<I, std::tuple<Components...>>)) ? &std::get<I>(species_components_) : result), ...);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <std::size_t ... I>
|
||||
void * get_entity_component_impl(std::type_index component_type, std::index_sequence<I...>)
|
||||
{
|
||||
void * result = nullptr;
|
||||
|
||||
((result = (component_type == typeid(std::tuple_element_t<I, std::tuple<Components...>>)) ? std::get<I>(entity_components_).data() : result), ...);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <std::size_t ... I>
|
||||
handle add_entity_impl(std::index_sequence<I...>)
|
||||
{
|
||||
|
|
@ -215,12 +238,12 @@ namespace psemek::util
|
|||
list_[new_size - 1] = null;
|
||||
list_head_ = old_size;
|
||||
|
||||
((std::get<I>(entity_components_).resize(new_size)), ...);
|
||||
((std::get<I>(this->entity_components_).resize(new_size)), ...);
|
||||
}
|
||||
|
||||
auto result = list_head_;
|
||||
|
||||
((std::get<I>(entity_components_)[result] = {}), ...);
|
||||
((std::get<I>(this->entity_components_)[result] = {}), ...);
|
||||
|
||||
list_head_ = list_[list_head_];
|
||||
list_[result] = result;
|
||||
|
|
@ -229,6 +252,59 @@ namespace psemek::util
|
|||
}
|
||||
};
|
||||
|
||||
template <typename ... Components>
|
||||
struct packed_species_impl final
|
||||
: species_impl_base<Components...>
|
||||
{
|
||||
using species_impl_base<Components...>::species_impl_base;
|
||||
|
||||
handle entity_count() const override
|
||||
{
|
||||
return std::get<0>(this->entity_components_).size();
|
||||
}
|
||||
|
||||
handle add_entity() override
|
||||
{
|
||||
return add_entity_impl(std::make_index_sequence<sizeof...(Components)>{});
|
||||
}
|
||||
|
||||
void remove_entity(handle h) override
|
||||
{
|
||||
remove_entity_impl(h, std::make_index_sequence<sizeof...(Components)>{});
|
||||
}
|
||||
|
||||
handle const * get_free_list() override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::size_t list_size() const override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template <std::size_t ... I>
|
||||
handle add_entity_impl(std::index_sequence<I...>)
|
||||
{
|
||||
handle result = entity_count();
|
||||
((std::get<I>(this->entity_components_).emplace_back()), ...);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <std::size_t ... I>
|
||||
void remove_entity_impl(handle h, std::index_sequence<I...>)
|
||||
{
|
||||
if (h + 1 != entity_count())
|
||||
{
|
||||
(std::swap(std::get<I>(this->entity_components_)[h], std::get<I>(this->entity_components_).back()), ...);
|
||||
}
|
||||
|
||||
((std::get<I>(this->entity_components_).pop_back()), ...);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
struct ecs
|
||||
|
|
@ -257,8 +333,14 @@ namespace psemek::util
|
|||
|
||||
using handle = ecs_detail::handle;
|
||||
|
||||
enum class policy
|
||||
{
|
||||
sparse,
|
||||
packed,
|
||||
};
|
||||
|
||||
template <typename ... Components>
|
||||
handle register_species(std::string name, Components && ... components);
|
||||
handle register_species(std::string name, policy p, Components && ... components);
|
||||
|
||||
handle species_count() const { return species_.size(); }
|
||||
|
||||
|
|
@ -296,20 +378,23 @@ namespace psemek::util
|
|||
typename Component::data const * get_if(handle species, handle entity) const;
|
||||
|
||||
template <typename Behavior>
|
||||
void apply(Behavior && behavior) const;
|
||||
void apply(Behavior && behavior);
|
||||
|
||||
template <typename Behavior>
|
||||
void apply(Behavior && behavior, handle species) const;
|
||||
void apply(Behavior && behavior, handle species);
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<ecs_detail::species_base>> species_;
|
||||
};
|
||||
|
||||
template <typename ... Components>
|
||||
ecs::handle ecs::register_species(std::string name, Components && ... components)
|
||||
ecs::handle ecs::register_species(std::string name, policy p, Components && ... components)
|
||||
{
|
||||
handle result = species_.size();
|
||||
species_.push_back(std::make_unique<ecs_detail::species_impl<Components...>>(std::move(name), result, std::move(components)...));
|
||||
if (p == policy::sparse)
|
||||
species_.push_back(std::make_unique<ecs_detail::sparse_species_impl<Components...>>(std::move(name), result, std::move(components)...));
|
||||
else
|
||||
species_.push_back(std::make_unique<ecs_detail::packed_species_impl<Components...>>(std::move(name), result, std::move(components)...));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -391,14 +476,14 @@ namespace psemek::util
|
|||
}
|
||||
|
||||
template <typename Behavior>
|
||||
void ecs::apply(Behavior && behavior) const
|
||||
void ecs::apply(Behavior && behavior)
|
||||
{
|
||||
for (auto & s : species_)
|
||||
s->apply(behavior);
|
||||
}
|
||||
|
||||
template <typename Behavior>
|
||||
void ecs::apply(Behavior && behavior, handle species) const
|
||||
void ecs::apply(Behavior && behavior, handle species)
|
||||
{
|
||||
species_[species]->apply(behavior);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue