ECS handles refactor: handle includes species & version
This commit is contained in:
parent
b05e209c6d
commit
f22b45c5e8
1 changed files with 199 additions and 102 deletions
|
|
@ -10,6 +10,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
#include <experimental/type_traits>
|
#include <experimental/type_traits>
|
||||||
|
|
||||||
|
|
@ -19,11 +20,43 @@ namespace psemek::util
|
||||||
namespace ecs_detail
|
namespace ecs_detail
|
||||||
{
|
{
|
||||||
|
|
||||||
using handle = std::uint32_t;
|
using species_handle = std::uint16_t;
|
||||||
|
|
||||||
|
// Entity id within it's species
|
||||||
|
using entity_id = std::uint32_t;
|
||||||
|
|
||||||
|
using entity_version = std::uint32_t;
|
||||||
|
|
||||||
|
// From highest to lowest bits:
|
||||||
|
// 12: species id
|
||||||
|
// 20: entity id (within species)
|
||||||
|
// 32: entity version
|
||||||
|
using entity_handle = std::uint64_t;
|
||||||
|
|
||||||
|
struct unpacked_handle
|
||||||
|
{
|
||||||
|
species_handle species;
|
||||||
|
entity_id entity;
|
||||||
|
entity_version version;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline unpacked_handle unpack(entity_handle h)
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
h >> 52,
|
||||||
|
(h >> 32) & 0xFFFFFu,
|
||||||
|
h & 0xFFFFFFFFu
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline entity_handle pack(species_handle species, entity_id id, entity_version version)
|
||||||
|
{
|
||||||
|
return (static_cast<entity_handle>(species) << 52) | (static_cast<entity_handle>(id) << 32) | static_cast<entity_handle>(version);
|
||||||
|
}
|
||||||
|
|
||||||
struct species_base
|
struct species_base
|
||||||
{
|
{
|
||||||
species_base(std::string name, handle id)
|
species_base(std::string name, species_handle id)
|
||||||
: name_(std::move(name))
|
: name_(std::move(name))
|
||||||
, id_(id)
|
, id_(id)
|
||||||
{}
|
{}
|
||||||
|
|
@ -45,15 +78,12 @@ namespace psemek::util
|
||||||
return reinterpret_cast<typename Component::data *>(get_entity_component(typeid(Component)));
|
return reinterpret_cast<typename Component::data *>(get_entity_component(typeid(Component)));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual handle entity_count() const = 0;
|
virtual entity_id entity_count() const = 0;
|
||||||
|
|
||||||
virtual handle add_entity() = 0;
|
virtual entity_handle add_entity() = 0;
|
||||||
virtual void remove_entity(handle h) = 0;
|
virtual void remove_entity(entity_handle h) = 0;
|
||||||
|
|
||||||
bool entity_active(handle h)
|
virtual bool entity_active(entity_handle h) const = 0;
|
||||||
{
|
|
||||||
return get_free_list()[h] == h;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Behavior>
|
template <typename Behavior>
|
||||||
void apply(Behavior & behavior)
|
void apply(Behavior & behavior)
|
||||||
|
|
@ -63,12 +93,14 @@ namespace psemek::util
|
||||||
|
|
||||||
virtual ~species_base() {}
|
virtual ~species_base() {}
|
||||||
|
|
||||||
virtual handle const * get_free_list() = 0;
|
virtual entity_id const * get_free_list() const = 0;
|
||||||
virtual std::size_t list_size() const = 0;
|
virtual entity_id list_size() const = 0;
|
||||||
|
|
||||||
private:
|
virtual entity_version const * get_version_list() const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
std::string name_;
|
std::string name_;
|
||||||
handle id_;
|
species_handle id_;
|
||||||
|
|
||||||
template <typename Behavior, typename ... Components, std::size_t ... Is>
|
template <typename Behavior, typename ... Components, std::size_t ... Is>
|
||||||
void apply_impl(Behavior & behavior, std::tuple<Components...> *, std::index_sequence<Is...>)
|
void apply_impl(Behavior & behavior, std::tuple<Components...> *, std::index_sequence<Is...>)
|
||||||
|
|
@ -86,8 +118,6 @@ namespace psemek::util
|
||||||
return;
|
return;
|
||||||
|
|
||||||
typename Behavior::context ctx;
|
typename Behavior::context ctx;
|
||||||
ctx.species = id_;
|
|
||||||
ctx.species_name = name_;
|
|
||||||
|
|
||||||
((std::get<Components *>(ctx.components) = get_species_component<Components>()), ...);
|
((std::get<Components *>(ctx.components) = get_species_component<Components>()), ...);
|
||||||
|
|
||||||
|
|
@ -113,19 +143,21 @@ namespace psemek::util
|
||||||
if (list)
|
if (list)
|
||||||
{
|
{
|
||||||
// sparse
|
// sparse
|
||||||
std::size_t const size = list_size();
|
auto const size = list_size();
|
||||||
for (std::size_t i = 0; i < size; ++i)
|
auto version = get_version_list();
|
||||||
|
for (entity_id i = 0; i < size; ++i)
|
||||||
{
|
{
|
||||||
if (*list == i)
|
if (*list == i)
|
||||||
{
|
{
|
||||||
ctx.entity = i;
|
ctx.entity.value = pack(id_, i, *version);
|
||||||
ctx.remove = false;
|
ctx.remove = false;
|
||||||
std::apply(visit, cptrs);
|
std::apply(visit, cptrs);
|
||||||
if (ctx.remove)
|
if (ctx.remove)
|
||||||
remove_entity(i);
|
remove_entity(ctx.entity.value);
|
||||||
}
|
}
|
||||||
std::apply(increment, cptrs);
|
std::apply(increment, cptrs);
|
||||||
++list;
|
++list;
|
||||||
|
++version;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -133,11 +165,11 @@ namespace psemek::util
|
||||||
// packed
|
// packed
|
||||||
for (std::size_t i = 0; i < entity_count();)
|
for (std::size_t i = 0; i < entity_count();)
|
||||||
{
|
{
|
||||||
ctx.entity = i;
|
ctx.entity.value = pack(id_, i, 0);
|
||||||
ctx.remove = false;
|
ctx.remove = false;
|
||||||
std::apply(visit, cptrs);
|
std::apply(visit, cptrs);
|
||||||
if (ctx.remove)
|
if (ctx.remove)
|
||||||
remove_entity(i);
|
remove_entity(ctx.entity.value);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::apply(increment, cptrs);
|
std::apply(increment, cptrs);
|
||||||
|
|
@ -152,7 +184,7 @@ namespace psemek::util
|
||||||
struct species_impl_base
|
struct species_impl_base
|
||||||
: species_base
|
: species_base
|
||||||
{
|
{
|
||||||
species_impl_base(std::string name, handle id, Components && ... components)
|
species_impl_base(std::string name, species_handle id, Components && ... components)
|
||||||
: species_base(std::move(name), id)
|
: species_base(std::move(name), id)
|
||||||
, species_components_{std::move(components)...}
|
, species_components_{std::move(components)...}
|
||||||
{}
|
{}
|
||||||
|
|
@ -199,42 +231,58 @@ namespace psemek::util
|
||||||
{
|
{
|
||||||
using species_impl_base<Components...>::species_impl_base;
|
using species_impl_base<Components...>::species_impl_base;
|
||||||
|
|
||||||
static constexpr handle null = static_cast<handle>(-1);
|
static constexpr entity_id null = static_cast<entity_id>(-1);
|
||||||
|
|
||||||
handle entity_count() const override
|
entity_id entity_count() const override
|
||||||
{
|
{
|
||||||
return entity_count_;
|
return entity_count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle add_entity() override
|
entity_handle add_entity() override
|
||||||
{
|
{
|
||||||
return add_entity_impl(std::make_index_sequence<sizeof...(Components)>{});
|
return add_entity_impl(std::make_index_sequence<sizeof...(Components)>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove_entity(handle h) override
|
void remove_entity(entity_handle h) override
|
||||||
{
|
{
|
||||||
list_[h] = list_head_;
|
auto id = unpack(h).entity;
|
||||||
list_head_ = h;
|
list_[id] = list_head_;
|
||||||
|
list_head_ = id;
|
||||||
|
destroyed_at_[id] = ++version_;
|
||||||
--entity_count_;
|
--entity_count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle const * get_free_list() override
|
bool entity_active(entity_handle h) const override
|
||||||
|
{
|
||||||
|
auto u = unpack(h);
|
||||||
|
return list_[u.entity] == u.entity && u.version >= destroyed_at_[u.entity];
|
||||||
|
}
|
||||||
|
|
||||||
|
entity_id const * get_free_list() const override
|
||||||
{
|
{
|
||||||
return list_.data();
|
return list_.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t list_size() const override
|
entity_id list_size() const override
|
||||||
{
|
{
|
||||||
return list_.size();
|
return list_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity_version const * get_version_list() const override
|
||||||
|
{
|
||||||
|
return created_at_.data();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<handle> list_;
|
std::vector<entity_id> list_;
|
||||||
handle list_head_ = null;
|
entity_id list_head_ = null;
|
||||||
std::size_t entity_count_ = 0;
|
entity_id entity_count_ = 0;
|
||||||
|
std::vector<entity_version> created_at_;
|
||||||
|
std::vector<entity_version> destroyed_at_;
|
||||||
|
entity_version version_ = 0;
|
||||||
|
|
||||||
template <std::size_t ... I>
|
template <std::size_t ... I>
|
||||||
handle add_entity_impl(std::index_sequence<I...>)
|
entity_handle add_entity_impl(std::index_sequence<I...>)
|
||||||
{
|
{
|
||||||
if (list_head_ == null)
|
if (list_head_ == null)
|
||||||
{
|
{
|
||||||
|
|
@ -242,6 +290,8 @@ namespace psemek::util
|
||||||
std::size_t const new_size = std::max<std::size_t>(16, old_size * 2);
|
std::size_t const new_size = std::max<std::size_t>(16, old_size * 2);
|
||||||
|
|
||||||
list_.resize(new_size);
|
list_.resize(new_size);
|
||||||
|
created_at_.resize(new_size, 0);
|
||||||
|
destroyed_at_.resize(new_size, 0);
|
||||||
for (std::size_t i = old_size; i + 1 < new_size; ++i)
|
for (std::size_t i = old_size; i + 1 < new_size; ++i)
|
||||||
list_[i] = i + 1;
|
list_[i] = i + 1;
|
||||||
list_[new_size - 1] = null;
|
list_[new_size - 1] = null;
|
||||||
|
|
@ -250,14 +300,15 @@ namespace psemek::util
|
||||||
((std::get<I>(this->entity_components_).resize(new_size)), ...);
|
((std::get<I>(this->entity_components_).resize(new_size)), ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = list_head_;
|
auto id = list_head_;
|
||||||
|
|
||||||
((std::get<I>(this->entity_components_)[result] = {}), ...);
|
((std::get<I>(this->entity_components_)[id] = {}), ...);
|
||||||
|
|
||||||
list_head_ = list_[list_head_];
|
list_head_ = list_[list_head_];
|
||||||
list_[result] = result;
|
list_[id] = id;
|
||||||
entity_count_++;
|
entity_count_++;
|
||||||
return result;
|
created_at_[id] = version_;
|
||||||
|
return pack(this->id_, id, version_);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -267,47 +318,58 @@ namespace psemek::util
|
||||||
{
|
{
|
||||||
using species_impl_base<Components...>::species_impl_base;
|
using species_impl_base<Components...>::species_impl_base;
|
||||||
|
|
||||||
handle entity_count() const override
|
entity_id entity_count() const override
|
||||||
{
|
{
|
||||||
return std::get<0>(this->entity_components_).size();
|
return std::get<0>(this->entity_components_).size();
|
||||||
}
|
}
|
||||||
|
|
||||||
handle add_entity() override
|
entity_handle add_entity() override
|
||||||
{
|
{
|
||||||
return add_entity_impl(std::make_index_sequence<sizeof...(Components)>{});
|
return add_entity_impl(std::make_index_sequence<sizeof...(Components)>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove_entity(handle h) override
|
void remove_entity(entity_handle h) override
|
||||||
{
|
{
|
||||||
remove_entity_impl(h, std::make_index_sequence<sizeof...(Components)>{});
|
remove_entity_impl(h, std::make_index_sequence<sizeof...(Components)>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
handle const * get_free_list() override
|
bool entity_active(entity_handle h) const override
|
||||||
|
{
|
||||||
|
return unpack(h).entity < entity_count();
|
||||||
|
}
|
||||||
|
|
||||||
|
entity_id const * get_free_list() const override
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t list_size() const override
|
entity_id list_size() const override
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity_version const * get_version_list() const override
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
template <std::size_t ... I>
|
template <std::size_t ... I>
|
||||||
handle add_entity_impl(std::index_sequence<I...>)
|
entity_handle add_entity_impl(std::index_sequence<I...>)
|
||||||
{
|
{
|
||||||
handle result = entity_count();
|
entity_id id = entity_count();
|
||||||
((std::get<I>(this->entity_components_).emplace_back()), ...);
|
((std::get<I>(this->entity_components_).emplace_back()), ...);
|
||||||
return result;
|
return pack(this->id_, id, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::size_t ... I>
|
template <std::size_t ... I>
|
||||||
void remove_entity_impl(handle h, std::index_sequence<I...>)
|
void remove_entity_impl(entity_handle h, std::index_sequence<I...>)
|
||||||
{
|
{
|
||||||
if (h + 1 != entity_count())
|
auto u = unpack(h);
|
||||||
|
if (u.entity + 1 != entity_count())
|
||||||
{
|
{
|
||||||
(std::swap(std::get<I>(this->entity_components_)[h], std::get<I>(this->entity_components_).back()), ...);
|
(std::swap(std::get<I>(this->entity_components_)[u.entity], std::get<I>(this->entity_components_).back()), ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
((std::get<I>(this->entity_components_).pop_back()), ...);
|
((std::get<I>(this->entity_components_).pop_back()), ...);
|
||||||
|
|
@ -318,6 +380,20 @@ namespace psemek::util
|
||||||
|
|
||||||
struct ecs
|
struct ecs
|
||||||
{
|
{
|
||||||
|
struct species_handle
|
||||||
|
{
|
||||||
|
ecs_detail::species_handle value;
|
||||||
|
|
||||||
|
friend auto operator <=> (species_handle const &, species_handle const &) = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct entity_handle
|
||||||
|
{
|
||||||
|
ecs_detail::entity_handle value;
|
||||||
|
|
||||||
|
friend auto operator <=> (entity_handle const &, entity_handle const &) = default;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename ... Components>
|
template <typename ... Components>
|
||||||
struct behavior
|
struct behavior
|
||||||
{
|
{
|
||||||
|
|
@ -326,9 +402,7 @@ namespace psemek::util
|
||||||
|
|
||||||
struct context
|
struct context
|
||||||
{
|
{
|
||||||
ecs_detail::handle species;
|
entity_handle entity;
|
||||||
std::string_view species_name;
|
|
||||||
ecs_detail::handle entity;
|
|
||||||
|
|
||||||
component_ptrs components;
|
component_ptrs components;
|
||||||
|
|
||||||
|
|
@ -342,8 +416,6 @@ namespace psemek::util
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
using handle = ecs_detail::handle;
|
|
||||||
|
|
||||||
enum class policy
|
enum class policy
|
||||||
{
|
{
|
||||||
sparse,
|
sparse,
|
||||||
|
|
@ -351,139 +423,141 @@ namespace psemek::util
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename ... Components>
|
template <typename ... Components>
|
||||||
handle register_species(std::string name, policy p, Components && ... components);
|
species_handle register_species(std::string name, policy p, Components && ... components);
|
||||||
|
|
||||||
handle species_count() const { return species_.size(); }
|
ecs_detail::species_handle species_count() const { return species_.size(); }
|
||||||
|
|
||||||
std::string_view species_name(handle species) const { return species_[species]->name(); }
|
std::string_view species_name(species_handle species) const { return species_[species.value]->name(); }
|
||||||
|
|
||||||
handle add_entity(handle species);
|
species_handle entity_species(entity_handle entity) const { return {ecs_detail::unpack(entity.value).species}; }
|
||||||
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(); }
|
entity_handle add_entity(species_handle species);
|
||||||
|
ecs_detail::entity_id entity_count(species_handle species) const;
|
||||||
|
void remove_entity(entity_handle entity);
|
||||||
|
bool entity_active(entity_handle entity);
|
||||||
|
|
||||||
template <typename Component>
|
template <typename Component>
|
||||||
Component & get(handle species);
|
Component & get(species_handle species);
|
||||||
|
|
||||||
template <typename Component>
|
template <typename Component>
|
||||||
Component const & get(handle species) const;
|
Component const & get(species_handle species) const;
|
||||||
|
|
||||||
template <typename Component>
|
template <typename Component>
|
||||||
typename Component::data & get(handle species, handle entity);
|
typename Component::data & get(entity_handle entity);
|
||||||
|
|
||||||
template <typename Component>
|
template <typename Component>
|
||||||
typename Component::data const & get(handle species, handle entity) const;
|
typename Component::data const & get(entity_handle entity) const;
|
||||||
|
|
||||||
template <typename Component>
|
template <typename Component>
|
||||||
Component * get_if(handle species);
|
Component * get_if(species_handle species);
|
||||||
|
|
||||||
template <typename Component>
|
template <typename Component>
|
||||||
Component const * get_if(handle species) const;
|
Component const * get_if(species_handle species) const;
|
||||||
|
|
||||||
template <typename Component>
|
template <typename Component>
|
||||||
typename Component::data * get_if(handle species, handle entity);
|
typename Component::data * get_if(entity_handle entity);
|
||||||
|
|
||||||
template <typename Component>
|
template <typename Component>
|
||||||
typename Component::data const * get_if(handle species, handle entity) const;
|
typename Component::data const * get_if(entity_handle entity) const;
|
||||||
|
|
||||||
template <typename Behavior>
|
template <typename Behavior>
|
||||||
void apply(Behavior && behavior);
|
void apply(Behavior && behavior);
|
||||||
|
|
||||||
template <typename Behavior>
|
template <typename Behavior>
|
||||||
void apply(Behavior && behavior, handle species);
|
void apply(Behavior && behavior, species_handle species);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::unique_ptr<ecs_detail::species_base>> species_;
|
std::vector<std::unique_ptr<ecs_detail::species_base>> species_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename ... Components>
|
template <typename ... Components>
|
||||||
ecs::handle ecs::register_species(std::string name, policy p, Components && ... components)
|
ecs::species_handle ecs::register_species(std::string name, policy p, Components && ... components)
|
||||||
{
|
{
|
||||||
handle result = species_.size();
|
auto result = species_count();
|
||||||
if (p == policy::sparse)
|
if (p == policy::sparse)
|
||||||
species_.push_back(std::make_unique<ecs_detail::sparse_species_impl<Components...>>(std::move(name), result, std::move(components)...));
|
species_.push_back(std::make_unique<ecs_detail::sparse_species_impl<Components...>>(std::move(name), result, std::move(components)...));
|
||||||
else
|
else
|
||||||
species_.push_back(std::make_unique<ecs_detail::packed_species_impl<Components...>>(std::move(name), result, std::move(components)...));
|
species_.push_back(std::make_unique<ecs_detail::packed_species_impl<Components...>>(std::move(name), result, std::move(components)...));
|
||||||
return result;
|
return {result};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ecs::handle ecs::add_entity(handle species)
|
inline ecs::entity_handle ecs::add_entity(species_handle species)
|
||||||
{
|
{
|
||||||
return species_[species]->add_entity();
|
return {species_[species.value]->add_entity()};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ecs::handle ecs::entity_count(handle species) const
|
inline ecs_detail::entity_id ecs::entity_count(species_handle species) const
|
||||||
{
|
{
|
||||||
return species_[species]->entity_count();
|
return species_[species.value]->entity_count();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void ecs::remove_entity(handle species, handle entity)
|
inline void ecs::remove_entity(entity_handle entity)
|
||||||
{
|
{
|
||||||
species_[species]->remove_entity(entity);
|
species_[ecs_detail::unpack(entity.value).species]->remove_entity(entity.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool ecs::entity_active(handle species, handle entity)
|
inline bool ecs::entity_active(entity_handle entity)
|
||||||
{
|
{
|
||||||
return species_[species]->entity_active(entity);
|
return species_[ecs_detail::unpack(entity.value).species]->entity_active(entity.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Component>
|
template <typename Component>
|
||||||
Component & ecs::get(handle species)
|
Component & ecs::get(species_handle species)
|
||||||
{
|
{
|
||||||
auto p = species_[species]->get_species_component<Component>();
|
auto p = species_[species.value]->get_species_component<Component>();
|
||||||
if (!p)
|
if (!p)
|
||||||
throw std::runtime_error(util::to_string("Component ", type_name<Component>(), " is not present in species ", species_[species]->name()));
|
throw std::runtime_error(util::to_string("Component ", type_name<Component>(), " is not present in species ", species_[species.value]->name()));
|
||||||
return *p;
|
return *p;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Component>
|
template <typename Component>
|
||||||
Component const & ecs::get(handle species) const
|
Component const & ecs::get(species_handle species) const
|
||||||
{
|
{
|
||||||
return const_cast<Component const &>(const_cast<ecs *>(this)->get<Component>(species));
|
return const_cast<Component const &>(const_cast<ecs *>(this)->get<Component>(species));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Component>
|
template <typename Component>
|
||||||
typename Component::data & ecs::get(handle species, handle entity)
|
typename Component::data & ecs::get(entity_handle entity)
|
||||||
{
|
{
|
||||||
auto p = species_[species]->get_entity_component<Component>();
|
auto u = ecs_detail::unpack(entity.value);
|
||||||
|
auto p = species_[u.species]->get_entity_component<Component>();
|
||||||
if (!p)
|
if (!p)
|
||||||
throw std::runtime_error(util::to_string("Component ", type_name<Component>(), " is not present in species ", species_[species]->name()));
|
throw std::runtime_error(util::to_string("Component ", type_name<Component>(), " is not present in species ", species_[u.species]->name()));
|
||||||
return p[entity];
|
return p[u.entity];
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Component>
|
template <typename Component>
|
||||||
typename Component::data const & ecs::get(handle species, handle entity) const
|
typename Component::data const & ecs::get(entity_handle entity) const
|
||||||
{
|
{
|
||||||
return const_cast<typename Component::data const &>(const_cast<ecs *>(this)->get<Component>(species, entity));
|
return const_cast<typename Component::data const &>(const_cast<ecs *>(this)->get<Component>(entity));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Component>
|
template <typename Component>
|
||||||
Component * ecs::get_if(handle species)
|
Component * ecs::get_if(species_handle species)
|
||||||
{
|
{
|
||||||
return species_[species]->get_species_component<Component>();
|
return species_[species.value]->get_species_component<Component>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Component>
|
template <typename Component>
|
||||||
Component const * ecs::get_if(handle species) const
|
Component const * ecs::get_if(species_handle species) const
|
||||||
{
|
{
|
||||||
return const_cast<typename Component::data const *>(const_cast<ecs *>(this)->get<Component>(species));
|
return const_cast<typename Component::data const *>(const_cast<ecs *>(this)->get<Component>(species));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Component>
|
template <typename Component>
|
||||||
typename Component::data * ecs::get_if(handle species, handle entity)
|
typename Component::data * ecs::get_if(entity_handle entity)
|
||||||
{
|
{
|
||||||
auto p = species_[species]->get_entity_component<Component>();
|
auto u = ecs_detail::unpack(entity.value);
|
||||||
|
auto p = species_[u.species]->get_entity_component<Component>();
|
||||||
if (p)
|
if (p)
|
||||||
return p + entity;
|
return p + u.entity;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Component>
|
template <typename Component>
|
||||||
typename Component::data const * ecs::get_if(handle species, handle entity) const
|
typename Component::data const * ecs::get_if(entity_handle entity) const
|
||||||
{
|
{
|
||||||
return const_cast<typename Component::data const *>(const_cast<ecs *>(this)->get_if<Component>(species, entity));
|
return const_cast<typename Component::data const *>(const_cast<ecs *>(this)->get_if<Component>(entity));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Behavior>
|
template <typename Behavior>
|
||||||
|
|
@ -494,9 +568,32 @@ namespace psemek::util
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Behavior>
|
template <typename Behavior>
|
||||||
void ecs::apply(Behavior && behavior, handle species)
|
void ecs::apply(Behavior && behavior, species_handle species)
|
||||||
{
|
{
|
||||||
species_[species]->apply(behavior);
|
species_[species.value]->apply(behavior);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct hash<::psemek::util::ecs::species_handle>
|
||||||
|
{
|
||||||
|
std::size_t operator()(::psemek::util::ecs::species_handle h) const
|
||||||
|
{
|
||||||
|
return std::hash<::psemek::util::ecs_detail::species_handle>()(h.value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct hash<::psemek::util::ecs::entity_handle>
|
||||||
|
{
|
||||||
|
std::size_t operator()(::psemek::util::ecs::entity_handle h) const
|
||||||
|
{
|
||||||
|
return std::hash<::psemek::util::ecs_detail::entity_handle>()(h.value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue