universal function argument for entity id

This commit is contained in:
2019-01-02 17:40:56 +07:00
parent d259c18f0d
commit 133f1fb0dc
3 changed files with 383 additions and 135 deletions

View File

@@ -35,15 +35,15 @@
```cpp
struct position_component {
float x{0};
float y{0};
float x;
float y;
position_component(float nx, float ny)
: x(nx), y(ny) {}
};
struct velocity_component {
float dx{0};
float dy{0};
float dx;
float dy;
velocity_component(float ndx, float ndy)
: dx(ndx), dy(ndy) {}
};

430
ecs.hpp
View File

@@ -197,7 +197,7 @@ namespace ecs_hpp
};
template < typename T >
class type_family : public type_family_base<> {
class type_family final : public type_family_base<> {
public:
static family_id id() noexcept {
static family_id self_id = ++last_id_;
@@ -234,7 +234,7 @@ namespace ecs_hpp
struct sparse_unsigned_indexer<T, false> {};
template < typename T >
struct sparse_indexer
struct sparse_indexer final
: public sparse_unsigned_indexer<T> {};
}
}
@@ -474,7 +474,9 @@ namespace ecs_hpp
std::enable_if_t<
std::is_nothrow_move_assignable<K>::value,
bool>
unordered_erase(const K& k) {
unordered_erase(const K& k)
noexcept(std::is_nothrow_move_assignable<T>::value)
{
if ( !keys_.has(k) ) {
return false;
}
@@ -540,7 +542,7 @@ namespace ecs_hpp
{
namespace detail
{
struct entity_id_indexer {
struct entity_id_indexer final {
std::size_t operator()(entity_id id) const noexcept {
return entity_id_index(id);
}
@@ -562,6 +564,7 @@ namespace ecs_hpp
public:
virtual ~component_storage_base() = default;
virtual bool remove(entity_id id) noexcept = 0;
virtual bool has(entity_id id) const noexcept = 0;
};
template < typename T >
@@ -577,6 +580,9 @@ namespace ecs_hpp
T* find(entity_id id) noexcept;
const T* find(entity_id id) const noexcept;
std::size_t count() const noexcept;
bool has(entity_id id) const noexcept override;
template < typename F >
void for_each_component(F&& f) noexcept;
template < typename F >
@@ -618,11 +624,21 @@ namespace ecs_hpp
return components_.find(id);
}
template < typename T >
std::size_t component_storage<T>::count() const noexcept {
return components_.size();
}
template < typename T >
bool component_storage<T>::has(entity_id id) const noexcept {
return components_.has(id);
}
template < typename T >
template < typename F >
void component_storage<T>::for_each_component(F&& f) noexcept {
for ( const auto id : components_ ) {
f(entity(owner_, id), components_.get(id));
f(id, components_.get(id));
}
}
@@ -630,7 +646,7 @@ namespace ecs_hpp
template < typename F >
void component_storage<T>::for_each_component(F&& f) const noexcept {
for ( const auto id : components_ ) {
f(const_entity(owner_, id), components_.get(id));
f(id, components_.get(id));
}
}
}
@@ -690,7 +706,7 @@ namespace ecs_hpp
template < typename... Ts >
std::tuple<const Ts*...> find_components() const noexcept;
private:
registry* owner_;
registry* owner_{nullptr};
entity_id id_{0u};
};
@@ -701,7 +717,7 @@ namespace ecs_hpp
namespace std
{
template <>
struct hash<ecs_hpp::entity>
struct hash<ecs_hpp::entity> final
: std::unary_function<const ecs_hpp::entity&, std::size_t>
{
std::size_t operator()(const ecs_hpp::entity& ent) const noexcept {
@@ -747,7 +763,7 @@ namespace ecs_hpp
template < typename... Ts >
std::tuple<const Ts*...> find_components() const noexcept;
private:
const registry* owner_;
const registry* owner_{nullptr};
entity_id id_{0u};
};
@@ -758,7 +774,7 @@ namespace ecs_hpp
namespace std
{
template <>
struct hash<ecs_hpp::const_entity>
struct hash<ecs_hpp::const_entity> final
: std::unary_function<const ecs_hpp::const_entity&, std::size_t>
{
std::size_t operator()(const ecs_hpp::const_entity& ent) const noexcept {
@@ -793,44 +809,92 @@ namespace ecs_hpp
namespace ecs_hpp
{
class registry final {
private:
class uentity {
public:
uentity(registry& owner, entity_id id) noexcept;
uentity(entity_id ent) noexcept;
uentity(entity ent) noexcept;
operator entity_id() const noexcept;
operator entity() const noexcept;
operator const_entity() const noexcept;
entity_id id() const noexcept;
registry* owner() noexcept;
const registry* owner() const noexcept;
bool check_owner(const registry* owner) const noexcept;
private:
entity_id id_{0u};
registry* owner_{nullptr};
};
class const_uentity {
public:
const_uentity(const registry& owner, entity_id id) noexcept;
const_uentity(entity_id ent) noexcept;
const_uentity(entity ent) noexcept;
const_uentity(const_entity ent) noexcept;
const_uentity(const uentity& ent) noexcept;
operator entity_id() const noexcept;
operator const_entity() const noexcept;
entity_id id() const noexcept;
const registry* owner() const noexcept;
bool check_owner(const registry* owner) const noexcept;
private:
entity_id id_{0u};
const registry* owner_{nullptr};
};
public:
registry() = default;
~registry() noexcept = default;
entity create_entity();
bool destroy_entity(const entity& ent);
bool alive_entity(const const_entity& ent) const noexcept;
bool destroy_entity(const uentity& ent);
bool alive_entity(const const_uentity& ent) const noexcept;
template < typename T, typename... Args >
bool assign_component(const entity& ent, Args&&... args);
bool assign_component(const uentity& ent, Args&&... args);
template < typename T >
bool remove_component(const entity& ent);
bool remove_component(const uentity& ent);
template < typename T >
bool exists_component(const const_entity& ent) const noexcept;
bool exists_component(const const_uentity& ent) const noexcept;
std::size_t remove_all_components(const entity& ent) noexcept;
std::size_t remove_all_components(const uentity& ent) noexcept;
template < typename T >
T& get_component(const entity& ent);
T& get_component(const uentity& ent);
template < typename T >
const T& get_component(const const_entity& ent) const;
const T& get_component(const const_uentity& ent) const;
template < typename T >
T* find_component(const entity& ent) noexcept;
T* find_component(const uentity& ent) noexcept;
template < typename T >
const T* find_component(const const_entity& ent) const noexcept;
const T* find_component(const const_uentity& ent) const noexcept;
template < typename... Ts >
std::tuple<Ts&...> get_components(const entity& ent);
std::tuple<Ts&...> get_components(const uentity& ent);
template < typename... Ts >
std::tuple<const Ts&...> get_components(const const_entity& ent) const;
std::tuple<const Ts&...> get_components(const const_uentity& ent) const;
template < typename... Ts >
std::tuple<Ts*...> find_components(const entity& ent) noexcept;
std::tuple<Ts*...> find_components(const uentity& ent) noexcept;
template < typename... Ts >
std::tuple<const Ts*...> find_components(const const_entity& ent) const noexcept;
std::tuple<const Ts*...> find_components(const const_uentity& ent) const noexcept;
template < typename T >
std::size_t component_count() const noexcept;
template < typename T >
std::size_t entity_component_count(const const_uentity& ent) const noexcept;
template < typename F >
void for_each_entity(F&& f);
@@ -853,22 +917,30 @@ namespace ecs_hpp
private:
template < typename T >
detail::component_storage<T>* find_storage_() noexcept;
template < typename T >
const detail::component_storage<T>* find_storage_() const noexcept;
template < typename T >
detail::component_storage<T>& get_or_create_storage_();
template < typename T >
T* find_component_impl_(const entity& ent) noexcept;
template < typename T >
const T* find_component_impl_(const const_entity& ent) const noexcept;
template < typename T
, typename... Ts
, typename F
, std::size_t I
, std::size_t... Is >
void for_joined_components_impl_(
F&& f,
std::index_sequence<I, Is...> iseq);
template < typename T, typename... Ts, typename F, std::size_t I, std::size_t... Is >
void for_joined_components_impl_(F&& f, std::index_sequence<I, Is...> iseq);
template < typename T, typename... Ts, typename F, std::size_t I, std::size_t... Is >
void for_joined_components_impl_(F&& f, std::index_sequence<I, Is...> iseq) const;
template < typename T
, typename... Ts
, typename F
, std::size_t I
, std::size_t... Is >
void for_joined_components_impl_(
F&& f,
std::index_sequence<I, Is...> iseq) const;
template < typename T
, typename... Ts
@@ -876,7 +948,7 @@ namespace ecs_hpp
, typename Ss
, typename... Cs >
void for_joined_components_impl_(
const entity& e,
const uentity& e,
const F& f,
const Ss& ss,
Cs&... cs);
@@ -887,21 +959,21 @@ namespace ecs_hpp
, typename Ss
, typename... Cs >
void for_joined_components_impl_(
const const_entity& e,
const const_uentity& e,
const F& f,
const Ss& ss,
const Cs&... cs) const;
template < typename F, typename... Cs >
void for_joined_components_impl_(
const entity& e,
const uentity& e,
const F& f,
const std::tuple<>& ss,
Cs&... cs);
template < typename F, typename... Cs >
void for_joined_components_impl_(
const const_entity& e,
const const_uentity& e,
const F& f,
const std::tuple<>& ss,
const Cs&... cs) const;
@@ -946,72 +1018,72 @@ namespace ecs_hpp
}
inline bool entity::destroy() {
return (*owner_).destroy_entity(*this);
return (*owner_).destroy_entity(id_);
}
inline bool entity::alive() const noexcept {
return detail::as_const(*owner_).alive_entity(*this);
return detail::as_const(*owner_).alive_entity(id_);
}
template < typename T, typename... Args >
bool entity::assign_component(Args&&... args) {
return (*owner_).assign_component<T>(
*this,
id_,
std::forward<Args>(args)...);
}
template < typename T >
bool entity::remove_component() {
return (*owner_).remove_component<T>(*this);
return (*owner_).remove_component<T>(id_);
}
template < typename T >
bool entity::exists_component() const noexcept {
return detail::as_const(*owner_).exists_component<T>(*this);
return detail::as_const(*owner_).exists_component<T>(id_);
}
inline std::size_t entity::remove_all_components() noexcept {
return (*owner_).remove_all_components(*this);
return (*owner_).remove_all_components(id_);
}
template < typename T >
T& entity::get_component() {
return (*owner_).get_component<T>(*this);
return (*owner_).get_component<T>(id_);
}
template < typename T >
const T& entity::get_component() const {
return detail::as_const(*owner_).get_component<T>(*this);
return detail::as_const(*owner_).get_component<T>(id_);
}
template < typename T >
T* entity::find_component() noexcept {
return (*owner_).find_component<T>(*this);
return (*owner_).find_component<T>(id_);
}
template < typename T >
const T* entity::find_component() const noexcept {
return detail::as_const(*owner_).find_component<T>(*this);
return detail::as_const(*owner_).find_component<T>(id_);
}
template < typename... Ts >
std::tuple<Ts&...> entity::get_components() {
return (*owner_).get_components<Ts...>(*this);
return (*owner_).get_components<Ts...>(id_);
}
template < typename... Ts >
std::tuple<const Ts&...> entity::get_components() const {
return detail::as_const(*owner_).get_components<Ts...>(*this);
return detail::as_const(*owner_).get_components<Ts...>(id_);
}
template < typename... Ts >
std::tuple<Ts*...> entity::find_components() noexcept {
return (*owner_).find_components<Ts...>(*this);
return (*owner_).find_components<Ts...>(id_);
}
template < typename... Ts >
std::tuple<const Ts*...> entity::find_components() const noexcept {
return detail::as_const(*owner_).find_components<Ts...>(*this);
return detail::as_const(*owner_).find_components<Ts...>(id_);
}
inline bool operator==(const entity& l, const entity& r) noexcept {
@@ -1052,32 +1124,32 @@ namespace ecs_hpp
}
inline bool const_entity::alive() const noexcept {
return (*owner_).alive_entity(*this);
return (*owner_).alive_entity(id_);
}
template < typename T >
bool const_entity::exists_component() const noexcept {
return (*owner_).exists_component<T>(*this);
return (*owner_).exists_component<T>(id_);
}
template < typename T >
const T& const_entity::get_component() const {
return (*owner_).get_component<T>(*this);
return (*owner_).get_component<T>(id_);
}
template < typename T >
const T* const_entity::find_component() const noexcept {
return (*owner_).find_component<T>(*this);
return (*owner_).find_component<T>(id_);
}
template < typename... Ts >
std::tuple<const Ts&...> const_entity::get_components() const {
return (*owner_).get_components<Ts...>(*this);
return (*owner_).get_components<Ts...>(id_);
}
template < typename... Ts >
std::tuple<const Ts*...> const_entity::find_components() const noexcept {
return (*owner_).find_components<Ts...>(*this);
return (*owner_).find_components<Ts...>(id_);
}
inline bool operator==(const const_entity& l, const const_entity& r) noexcept {
@@ -1098,86 +1170,184 @@ namespace ecs_hpp
namespace ecs_hpp
{
//
// registry::uentity
//
inline registry::uentity::uentity(registry& owner, entity_id id) noexcept
: id_(id)
, owner_(&owner) {}
inline registry::uentity::uentity(entity_id ent) noexcept
: id_(ent) {}
inline registry::uentity::uentity(entity ent) noexcept
: id_(ent.id())
, owner_(&ent.owner()) {}
inline registry::uentity::operator entity_id() const noexcept {
return id_;
}
inline registry::uentity::operator entity() const noexcept {
assert(owner_);
return {*owner_, id_};
}
inline registry::uentity::operator const_entity() const noexcept {
assert(owner_);
return {*owner_, id_};
}
inline entity_id registry::uentity::id() const noexcept {
return id_;
}
inline registry* registry::uentity::owner() noexcept {
return owner_;
}
inline const registry* registry::uentity::owner() const noexcept {
return owner_;
}
inline bool registry::uentity::check_owner(const registry* owner) const noexcept {
return !owner_ || owner_ == owner;
}
//
// registry::const_uentity
//
inline registry::const_uentity::const_uentity(const registry& owner, entity_id id) noexcept
: id_(id)
, owner_(&owner) {}
inline registry::const_uentity::const_uentity(entity_id ent) noexcept
: id_(ent) {}
inline registry::const_uentity::const_uentity(entity ent) noexcept
: id_(ent.id())
, owner_(&ent.owner()) {}
inline registry::const_uentity::const_uentity(const_entity ent) noexcept
: id_(ent.id())
, owner_(&ent.owner()) {}
inline registry::const_uentity::const_uentity(const uentity& ent) noexcept
: id_(ent.id())
, owner_(ent.owner()) {}
inline registry::const_uentity::operator entity_id() const noexcept {
return id_;
}
inline registry::const_uentity::operator const_entity() const noexcept {
assert(owner_);
return {*owner_, id_};
}
inline entity_id registry::const_uentity::id() const noexcept {
return id_;
}
inline const registry* registry::const_uentity::owner() const noexcept {
return owner_;
}
inline bool registry::const_uentity::check_owner(const registry* owner) const noexcept {
return !owner_ || owner_ == owner;
}
//
// registry
//
inline entity registry::create_entity() {
if ( !free_entity_ids_.empty() ) {
const auto free_ent_id = free_entity_ids_.back();
const auto new_ent_id = detail::upgrade_entity_id(free_ent_id);
auto ent = entity(*this, new_ent_id);
entity_ids_.insert(new_ent_id);
free_entity_ids_.pop_back();
return ent;
return {*this, new_ent_id};
}
if ( last_entity_id_ < detail::entity_id_index_mask ) {
auto ent = entity(*this, ++last_entity_id_);
entity_ids_.insert(ent.id());
return ent;
entity_ids_.insert(last_entity_id_ + 1);
return {*this, ++last_entity_id_};
}
throw std::logic_error("ecs_hpp::registry (entity index overlow)");
}
inline bool registry::destroy_entity(const entity& ent) {
inline bool registry::destroy_entity(const uentity& ent) {
assert(ent.check_owner(this));
remove_all_components(ent);
if ( entity_ids_.unordered_erase(ent.id()) ) {
free_entity_ids_.push_back(ent.id());
if ( entity_ids_.unordered_erase(ent) ) {
free_entity_ids_.push_back(ent);
return true;
}
return false;
}
inline bool registry::alive_entity(const const_entity& ent) const noexcept {
return entity_ids_.has(ent.id());
inline bool registry::alive_entity(const const_uentity& ent) const noexcept {
assert(ent.check_owner(this));
return entity_ids_.has(ent);
}
template < typename T, typename... Args >
bool registry::assign_component(const entity& ent, Args&&... args) {
bool registry::assign_component(const uentity& ent, Args&&... args) {
assert(ent.check_owner(this));
if ( !alive_entity(ent) ) {
return false;
}
get_or_create_storage_<T>().assign(
ent.id(),
ent,
std::forward<Args>(args)...);
return true;
}
template < typename T >
bool registry::remove_component(const entity& ent) {
bool registry::remove_component(const uentity& ent) {
assert(ent.check_owner(this));
if ( !alive_entity(ent) ) {
return false;
}
detail::component_storage<T>* storage = find_storage_<T>();
return storage
? storage->remove(ent.id())
? storage->remove(ent)
: false;
}
template < typename T >
bool registry::exists_component(const const_entity& ent) const noexcept {
bool registry::exists_component(const const_uentity& ent) const noexcept {
assert(ent.check_owner(this));
if ( !alive_entity(ent) ) {
return false;
}
const detail::component_storage<T>* storage = find_storage_<T>();
return storage
? storage->exists(ent.id())
? storage->exists(ent)
: false;
}
inline std::size_t registry::remove_all_components(const entity& ent) noexcept {
inline std::size_t registry::remove_all_components(const uentity& ent) noexcept {
assert(ent.check_owner(this));
if ( !alive_entity(ent) ) {
return 0u;
}
std::size_t removed_components = 0u;
std::size_t removed_count = 0u;
for ( const auto family_id : storages_ ) {
if ( storages_.get(family_id)->remove(ent.id()) ) {
++removed_components;
if ( storages_.get(family_id)->remove(ent) ) {
++removed_count;
}
}
return removed_components;
return removed_count;
}
template < typename T >
T& registry::get_component(const entity& ent) {
T* component = find_component_impl_<T>(ent);
T& registry::get_component(const uentity& ent) {
assert(ent.check_owner(this));
T* component = find_component<T>(ent);
if ( component ) {
return *component;
}
@@ -1185,8 +1355,9 @@ namespace ecs_hpp
}
template < typename T >
const T& registry::get_component(const const_entity& ent) const {
const T* component = find_component_impl_<T>(ent);
const T& registry::get_component(const const_uentity& ent) const {
assert(ent.check_owner(this));
const T* component = find_component<T>(ent);
if ( component ) {
return *component;
}
@@ -1194,46 +1365,81 @@ namespace ecs_hpp
}
template < typename T >
T* registry::find_component(const entity& ent) noexcept {
return find_component_impl_<T>(ent);
T* registry::find_component(const uentity& ent) noexcept {
assert(ent.check_owner(this));
detail::component_storage<T>* storage = find_storage_<T>();
return storage
? storage->find(ent)
: nullptr;
}
template < typename T >
const T* registry::find_component(const const_entity& ent) const noexcept {
return find_component_impl_<T>(ent);
const T* registry::find_component(const const_uentity& ent) const noexcept {
assert(ent.check_owner(this));
const detail::component_storage<T>* storage = find_storage_<T>();
return storage
? storage->find(ent)
: nullptr;
}
template < typename... Ts >
std::tuple<Ts&...> registry::get_components(const entity& ent) {
std::tuple<Ts&...> registry::get_components(const uentity& ent) {
assert(ent.check_owner(this));
return std::make_tuple(std::ref(get_component<Ts>(ent))...);
}
template < typename... Ts >
std::tuple<const Ts&...> registry::get_components(const const_entity& ent) const {
std::tuple<const Ts&...> registry::get_components(const const_uentity& ent) const {
assert(ent.check_owner(this));
return std::make_tuple(std::cref(get_component<Ts>(ent))...);
}
template < typename... Ts >
std::tuple<Ts*...> registry::find_components(const entity& ent) noexcept {
std::tuple<Ts*...> registry::find_components(const uentity& ent) noexcept {
assert(ent.check_owner(this));
return std::make_tuple(find_component<Ts>(ent)...);
}
template < typename... Ts >
std::tuple<const Ts*...> registry::find_components(const const_entity& ent) const noexcept {
std::tuple<const Ts*...> registry::find_components(const const_uentity& ent) const noexcept {
assert(ent.check_owner(this));
return std::make_tuple(find_component<Ts>(ent)...);
}
template < typename T >
std::size_t registry::component_count() const noexcept {
const detail::component_storage<T>* storage = find_storage_<T>();
return storage
? storage->count()
: 0u;
}
template < typename T >
std::size_t registry::entity_component_count(const const_uentity& ent) const noexcept {
assert(ent.check_owner(this));
if ( !alive_entity(ent) ) {
return 0u;
}
std::size_t component_count = 0u;
for ( const auto family_id : storages_ ) {
if ( storages_.get(family_id)->has(ent) ) {
++component_count;
}
}
return component_count;
}
template < typename F >
void registry::for_each_entity(F&& f) {
for ( const auto id : entity_ids_ ) {
f(entity(*this, id));
f({*this, id});
}
}
template < typename F >
void registry::for_each_entity(F&& f) const {
for ( const auto id : entity_ids_ ) {
f(const_entity(*this, id));
f({*this, id});
}
}
@@ -1241,7 +1447,9 @@ namespace ecs_hpp
void registry::for_each_component(F&& f) {
detail::component_storage<T>* storage = find_storage_<T>();
if ( storage ) {
storage->for_each_component(std::forward<F>(f));
storage->for_each_component([this, &f](const entity_id e, T& t){
f(uentity{*this, e}, t);
});
}
}
@@ -1249,7 +1457,9 @@ namespace ecs_hpp
void registry::for_each_component(F&& f) const {
const detail::component_storage<T>* storage = find_storage_<T>();
if ( storage ) {
storage->for_each_component(std::forward<F>(f));
storage->for_each_component([this, &f](const entity_id e, const T& t){
f(const_uentity{*this, e}, t);
});
}
}
@@ -1313,22 +1523,6 @@ namespace ecs_hpp
storages_.get(family).get());
}
template < typename T >
T* registry::find_component_impl_(const entity& ent) noexcept {
detail::component_storage<T>* storage = find_storage_<T>();
return storage
? storage->find(ent.id())
: nullptr;
}
template < typename T >
const T* registry::find_component_impl_(const const_entity& ent) const noexcept {
const detail::component_storage<T>* storage = find_storage_<T>();
return storage
? storage->find(ent.id())
: nullptr;
}
template < typename T
, typename... Ts
, typename F
@@ -1341,7 +1535,7 @@ namespace ecs_hpp
(void)iseq;
const auto ss = std::make_tuple(find_storage_<Ts>()...);
if ( !detail::tuple_contains(ss, nullptr) ) {
for_each_component<T>([this, &f, &ss](const entity& e, T& t) {
for_each_component<T>([this, &f, &ss](const uentity& e, T& t) {
for_joined_components_impl_<Ts...>(e, f, ss, t);
});
}
@@ -1359,7 +1553,7 @@ namespace ecs_hpp
(void)iseq;
const auto ss = std::make_tuple(find_storage_<Ts>()...);
if ( !detail::tuple_contains(ss, nullptr) ) {
for_each_component<T>([this, &f, &ss](const const_entity& e, const T& t) {
for_each_component<T>([this, &f, &ss](const const_uentity& e, const T& t) {
detail::as_const(*this).for_joined_components_impl_<Ts...>(e, f, ss, t);
});
}
@@ -1371,12 +1565,12 @@ namespace ecs_hpp
, typename Ss
, typename... Cs >
void registry::for_joined_components_impl_(
const entity& e,
const uentity& e,
const F& f,
const Ss& ss,
Cs&... cs)
{
T* c = std::get<0>(ss)->find(e.id());
T* c = std::get<0>(ss)->find(e);
if ( c ) {
for_joined_components_impl_<Ts...>(
e,
@@ -1393,12 +1587,12 @@ namespace ecs_hpp
, typename Ss
, typename... Cs >
void registry::for_joined_components_impl_(
const const_entity& e,
const const_uentity& e,
const F& f,
const Ss& ss,
const Cs&... cs) const
{
const T* c = std::get<0>(ss)->find(e.id());
const T* c = std::get<0>(ss)->find(e);
if ( c ) {
for_joined_components_impl_<Ts...>(
e,
@@ -1411,7 +1605,7 @@ namespace ecs_hpp
template < typename F, typename... Cs >
void registry::for_joined_components_impl_(
const entity& e,
const uentity& e,
const F& f,
const std::tuple<>& ss,
Cs&... cs)
@@ -1422,7 +1616,7 @@ namespace ecs_hpp
template < typename F, typename... Cs >
void registry::for_joined_components_impl_(
const const_entity& e,
const const_uentity& e,
const F& f,
const std::tuple<>& ss,
const Cs&... cs) const

View File

@@ -372,13 +372,21 @@ TEST_CASE("registry") {
{
REQUIRE_FALSE(w.exists_component<position_c>(e1));
REQUIRE_FALSE(w.exists_component<velocity_c>(e1));
REQUIRE_FALSE(w.component_count<position_c>());
REQUIRE_FALSE(w.entity_component_count<position_c>(e1));
REQUIRE(w.assign_component<position_c>(e1));
REQUIRE(w.exists_component<position_c>(e1));
REQUIRE_FALSE(w.exists_component<velocity_c>(e1));
REQUIRE(w.component_count<position_c>() == 1u);
REQUIRE(w.component_count<velocity_c>() == 0u);
REQUIRE(w.entity_component_count<position_c>(e1) == 1u);
REQUIRE(w.assign_component<velocity_c>(e1));
REQUIRE(w.component_count<position_c>() == 1u);
REQUIRE(w.component_count<velocity_c>() == 1u);
REQUIRE(w.entity_component_count<position_c>(e1) == 2u);
REQUIRE(w.exists_component<position_c>(e1));
REQUIRE(w.exists_component<velocity_c>(e1));
@@ -387,6 +395,9 @@ TEST_CASE("registry") {
REQUIRE_FALSE(w.exists_component<position_c>(e1));
REQUIRE_FALSE(w.exists_component<velocity_c>(e1));
REQUIRE_FALSE(w.component_count<position_c>());
REQUIRE_FALSE(w.component_count<velocity_c>());
REQUIRE_FALSE(w.entity_component_count<position_c>(e1));
}
{
@@ -402,6 +413,11 @@ TEST_CASE("registry") {
REQUIRE(e1.exists_component<position_c>());
REQUIRE(e1.exists_component<velocity_c>());
REQUIRE(e1.destroy());
REQUIRE_FALSE(e1.exists_component<position_c>());
REQUIRE_FALSE(e1.exists_component<velocity_c>());
}
}
{
@@ -608,6 +624,17 @@ TEST_CASE("registry") {
e2.assign_component<position_c>(5, 6);
e2.assign_component<velocity_c>(7, 8);
{
ecs::entity_id acc1 = 0;
int acc2 = 0;
w.for_each_component<position_c>([&acc1, &acc2](ecs::entity_id id, position_c& p){
acc1 += id;
acc2 += p.x;
});
REQUIRE(acc1 == e1.id() + e2.id());
REQUIRE(acc2 == 6);
}
{
ecs::entity_id acc1 = 0;
int acc2 = 0;
@@ -678,6 +705,19 @@ TEST_CASE("registry") {
e3.assign_component<position_c>(100, 500);
e4.assign_component<velocity_c>(500, 100);
{
ecs::entity_id acc1 = 0;
int acc2 = 0;
w.for_joined_components<position_c, velocity_c>([&acc1, &acc2](
ecs::entity_id id, const position_c& p, const velocity_c& v)
{
acc1 += id;
acc2 += p.x + v.x;
});
REQUIRE(acc1 == e1.id() + e2.id());
REQUIRE(acc2 == 16);
}
{
ecs::entity_id acc1 = 0;
int acc2 = 0;
@@ -693,16 +733,30 @@ TEST_CASE("registry") {
{
const ecs::registry& ww = w;
ecs::entity_id acc1 = 0;
int acc2 = 0;
ww.for_joined_components<position_c, velocity_c>([&acc1, &acc2](
ecs::const_entity e, const position_c& p, const velocity_c& v)
{
acc1 += e.id();
acc2 += p.x + v.x;
});
REQUIRE(acc1 == e1.id() + e2.id());
REQUIRE(acc2 == 16);
ecs::entity_id acc1 = 0;
int acc2 = 0;
ww.for_joined_components<position_c, velocity_c>([&acc1, &acc2](
ecs::entity_id id, const position_c& p, const velocity_c& v)
{
acc1 += id;
acc2 += p.x + v.x;
});
REQUIRE(acc1 == e1.id() + e2.id());
REQUIRE(acc2 == 16);
}
{
ecs::entity_id acc1 = 0;
int acc2 = 0;
ww.for_joined_components<position_c, velocity_c>([&acc1, &acc2](
ecs::const_entity e, const position_c& p, const velocity_c& v)
{
acc1 += e.id();
acc2 += p.x + v.x;
});
REQUIRE(acc1 == e1.id() + e2.id());
REQUIRE(acc2 == 16);
}
}
}
{
@@ -753,15 +807,15 @@ TEST_CASE("registry") {
TEST_CASE("example") {
struct position_component {
float x{0};
float y{0};
float x;
float y;
position_component(float nx, float ny)
: x(nx), y(ny) {}
};
struct velocity_component {
float dx{0};
float dy{0};
float dx;
float dy;
velocity_component(float ndx, float ndy)
: dx(ndx), dy(ndy) {}
};