Merge pull request #8 from BlackMATov/dev

Dev
This commit is contained in:
BlackMat MATov
2018-12-29 07:43:50 +07:00
committed by GitHub
3 changed files with 286 additions and 131 deletions

View File

@@ -80,6 +80,7 @@ private:
ecs_hpp::registry world; ecs_hpp::registry world;
world.add_system<movement_system>(); world.add_system<movement_system>();
world.add_system<gravity_system>(9.8f);
auto entity_one = world.create_entity(); auto entity_one = world.create_entity();
world.assign_component<position_component>(entity_one, 4.f, 2.f); world.assign_component<position_component>(entity_one, 4.f, 2.f);

351
ecs.hpp
View File

@@ -29,6 +29,8 @@
namespace ecs_hpp namespace ecs_hpp
{ {
class entity; class entity;
class const_entity;
class system; class system;
class registry; class registry;
@@ -115,19 +117,29 @@ namespace ecs_hpp
// tuple_contains // tuple_contains
// //
template < typename V > namespace impl
bool tuple_contains(const std::tuple<>& t, const V& v) { {
(void)t; template < size_t I, typename V, typename... Ts >
(void)v; std::enable_if_t<I == sizeof...(Ts), bool>
return false; tuple_contains_impl(const std::tuple<Ts...>& t, const V& v) {
(void)t;
(void)v;
return false;
}
template < size_t I, typename V, typename... Ts >
std::enable_if_t<I != sizeof...(Ts), bool>
tuple_contains_impl(const std::tuple<Ts...>& t, const V& v) {
if ( std::get<I>(t) == v ) {
return true;
}
return tuple_contains_impl<I + 1>(t, v);
}
} }
template < typename V, typename T, typename... Ts > template < typename V, typename... Ts >
bool tuple_contains(const std::tuple<T, Ts...>& t, const V& v) { bool tuple_contains(const std::tuple<Ts...>& t, const V& v) {
if ( std::get<0>(t) == v ) { return impl::tuple_contains_impl<0>(t, v);
return true;
}
return tuple_contains(tuple_tail(t), v);
} }
// //
@@ -202,7 +214,8 @@ namespace ecs_hpp
namespace detail namespace detail
{ {
template < typename T template < typename T
, bool = std::is_unsigned<T>::value && sizeof(T) <= sizeof(std::size_t) > , bool = std::is_unsigned<T>::value
&& sizeof(T) <= sizeof(std::size_t) >
struct sparse_unsigned_indexer { struct sparse_unsigned_indexer {
std::size_t operator()(const T v) const noexcept { std::size_t operator()(const T v) const noexcept {
return static_cast<std::size_t>(v); return static_cast<std::size_t>(v);
@@ -240,8 +253,7 @@ namespace ecs_hpp
} }
iterator end() noexcept { iterator end() noexcept {
using dt = typename std::iterator_traits<iterator>::difference_type; return dense_.end();
return begin() + static_cast<dt>(size_);
} }
const_iterator begin() const noexcept { const_iterator begin() const noexcept {
@@ -249,8 +261,7 @@ namespace ecs_hpp
} }
const_iterator end() const noexcept { const_iterator end() const noexcept {
using dt = typename std::iterator_traits<const_iterator>::difference_type; return dense_.end();
return begin() + static_cast<dt>(size_);
} }
const_iterator cbegin() const noexcept { const_iterator cbegin() const noexcept {
@@ -258,8 +269,7 @@ namespace ecs_hpp
} }
const_iterator cend() const noexcept { const_iterator cend() const noexcept {
using dt = typename std::iterator_traits<const_iterator>::difference_type; return dense_.cend();
return cbegin() + static_cast<dt>(size_);
} }
public: public:
sparse_set(const Indexer& indexer = Indexer()) sparse_set(const Indexer& indexer = Indexer())
@@ -270,12 +280,11 @@ namespace ecs_hpp
return false; return false;
} }
const std::size_t vi = indexer_(v); const std::size_t vi = indexer_(v);
if ( vi >= capacity_ ) { if ( vi >= sparse_.size() ) {
reserve(new_capacity_for_(vi + 1u)); sparse_.resize(new_sparse_size_for_(vi + 1u));
} }
dense_[size_] = std::move(v); dense_.push_back(std::move(v));
sparse_[vi] = size_; sparse_[vi] = dense_.size() - 1u;
++size_;
return true; return true;
} }
@@ -284,12 +293,11 @@ namespace ecs_hpp
return false; return false;
} }
const std::size_t vi = indexer_(v); const std::size_t vi = indexer_(v);
if ( vi >= capacity_ ) { if ( vi >= sparse_.size() ) {
reserve(new_capacity_for_(vi + 1u)); sparse_.resize(new_sparse_size_for_(vi + 1u));
} }
dense_[size_] = v; dense_.push_back(v);
sparse_[vi] = size_; sparse_[vi] = dense_.size() - 1u;
++size_;
return true; return true;
} }
@@ -305,21 +313,21 @@ namespace ecs_hpp
return false; return false;
} }
const std::size_t vi = indexer_(v); const std::size_t vi = indexer_(v);
const std::size_t index = sparse_[vi]; const std::size_t dense_index = sparse_[vi];
dense_[index] = std::move(dense_[size_ - 1u]); dense_[dense_index] = std::move(dense_.back());
sparse_[indexer_(dense_[index])] = index; sparse_[indexer_(dense_[dense_index])] = dense_index;
--size_; dense_.pop_back();
return true; return true;
} }
void clear() noexcept { void clear() noexcept {
size_ = 0u; dense_.clear();
} }
bool has(const T& v) const noexcept { bool has(const T& v) const noexcept {
const std::size_t vi = indexer_(v); const std::size_t vi = indexer_(v);
return vi < capacity_ return vi < sparse_.size()
&& sparse_[vi] < size_ && sparse_[vi] < dense_.size()
&& dense_[sparse_[vi]] == v; && dense_[sparse_[vi]] == v;
} }
@@ -345,49 +353,27 @@ namespace ecs_hpp
} }
bool empty() const noexcept { bool empty() const noexcept {
return size_ == 0u; return dense_.empty();
}
void reserve(std::size_t ncapacity) {
if ( ncapacity > capacity_ ) {
std::vector<T> ndense(ncapacity);
std::vector<std::size_t> nsparse(ncapacity);
std::copy(dense_.begin(), dense_.end(), ndense.begin());
std::copy(sparse_.begin(), sparse_.end(), nsparse.begin());
ndense.swap(dense_);
nsparse.swap(sparse_);
capacity_ = ncapacity;
}
} }
std::size_t size() const noexcept { std::size_t size() const noexcept {
return size_; return dense_.size();
}
std::size_t max_size() const noexcept {
return std::min(dense_.max_size(), sparse_.max_size());
}
std::size_t capacity() const noexcept {
return capacity_;
} }
private: private:
std::size_t new_capacity_for_(std::size_t nsize) const { std::size_t new_sparse_size_for_(std::size_t nsize) const {
const std::size_t ms = max_size(); const std::size_t ms = sparse_.max_size();
if ( nsize > ms ) { if ( nsize > ms ) {
throw std::length_error("ecs_hpp::sparse_set"); throw std::length_error("ecs_hpp::sparse_set");
} }
if ( capacity_ >= ms / 2u ) { if ( sparse_.size() >= ms / 2u ) {
return ms; return ms;
} }
return std::max(capacity_ * 2u, nsize); return std::max(sparse_.size() * 2u, nsize);
} }
private: private:
Indexer indexer_; Indexer indexer_;
std::vector<T> dense_; std::vector<T> dense_;
std::vector<std::size_t> sparse_; std::vector<std::size_t> sparse_;
std::size_t size_{0u};
std::size_t capacity_{0u};
}; };
} }
} }
@@ -484,8 +470,8 @@ namespace ecs_hpp
if ( !keys_.has(k) ) { if ( !keys_.has(k) ) {
return false; return false;
} }
const std::size_t index = keys_.get_dense_index(k); const std::size_t value_index = keys_.get_dense_index(k);
values_[index] = std::move(values_.back()); values_[value_index] = std::move(values_.back());
values_.pop_back(); values_.pop_back();
keys_.unordered_erase(k); keys_.unordered_erase(k);
return true; return true;
@@ -509,16 +495,16 @@ namespace ecs_hpp
} }
T* find(const K& k) noexcept { T* find(const K& k) noexcept {
const auto ip = keys_.find_dense_index(k); const auto value_index_p = keys_.find_dense_index(k);
return ip.second return value_index_p.second
? &values_[ip.first] ? &values_[value_index_p.first]
: nullptr; : nullptr;
} }
const T* find(const K& k) const noexcept { const T* find(const K& k) const noexcept {
const auto ip = keys_.find_dense_index(k); const auto value_index_p = keys_.find_dense_index(k);
return ip.second return value_index_p.second
? &values_[ip.first] ? &values_[value_index_p.first]
: nullptr; : nullptr;
} }
@@ -526,22 +512,9 @@ namespace ecs_hpp
return values_.empty(); return values_.empty();
} }
void reserve(std::size_t ncapacity) {
keys_.reserve(ncapacity);
values_.reserve(ncapacity);
}
std::size_t size() const noexcept { std::size_t size() const noexcept {
return values_.size(); return values_.size();
} }
std::size_t max_size() const noexcept {
return std::min(keys_.max_size(), values_.max_size());
}
std::size_t capacity() const noexcept {
return values_.capacity();
}
private: private:
sparse_set<K, Indexer> keys_; sparse_set<K, Indexer> keys_;
std::vector<T> values_; std::vector<T> values_;
@@ -649,7 +622,7 @@ namespace ecs_hpp
template < typename F > template < typename F >
void component_storage<T>::for_each_component(F&& f) const noexcept { void component_storage<T>::for_each_component(F&& f) const noexcept {
for ( const auto id : components_ ) { for ( const auto id : components_ ) {
f(entity(owner_, id), components_.get(id)); f(const_entity(owner_, id), components_.get(id));
} }
} }
} }
@@ -665,8 +638,8 @@ namespace ecs_hpp
{ {
class entity final { class entity final {
public: public:
entity(registry& owner); entity(registry& owner) noexcept;
entity(registry& owner, entity_id id); entity(registry& owner, entity_id id) noexcept;
const registry& owner() const noexcept; const registry& owner() const noexcept;
entity_id id() const noexcept; entity_id id() const noexcept;
@@ -727,6 +700,61 @@ namespace std
}; };
} }
// -----------------------------------------------------------------------------
//
// const_entity
//
// -----------------------------------------------------------------------------
namespace ecs_hpp
{
class const_entity final {
public:
const_entity(const entity& ent) noexcept;
const_entity(const registry& owner) noexcept;
const_entity(const registry& owner, entity_id id) noexcept;
const registry& owner() const noexcept;
entity_id id() const noexcept;
bool is_alive() const noexcept;
template < typename T >
bool exists_component() const noexcept;
template < typename T >
const T& get_component() const;
template < typename T >
const T* find_component() const noexcept;
template < typename... Ts >
std::tuple<const Ts&...> get_components() const;
template < typename... Ts >
std::tuple<const Ts*...> find_components() const noexcept;
private:
const registry* owner_;
entity_id id_{0u};
};
bool operator==(const const_entity& l, const const_entity& r) noexcept;
bool operator!=(const const_entity& l, const const_entity& r) noexcept;
}
namespace std
{
template <>
struct hash<ecs_hpp::const_entity>
: std::unary_function<const ecs_hpp::const_entity&, std::size_t>
{
std::size_t operator()(const ecs_hpp::const_entity& ent) const noexcept {
return std::hash<ecs_hpp::entity_id>()(ent.id());
}
};
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// //
// system // system
@@ -757,7 +785,7 @@ namespace ecs_hpp
entity create_entity(); entity create_entity();
bool destroy_entity(const entity& ent); bool destroy_entity(const entity& ent);
bool is_entity_alive(const entity& ent) const noexcept; bool is_entity_alive(const const_entity& ent) const noexcept;
template < typename T, typename... Args > template < typename T, typename... Args >
bool assign_component(const entity& ent, Args&&... args); bool assign_component(const entity& ent, Args&&... args);
@@ -766,29 +794,34 @@ namespace ecs_hpp
bool remove_component(const entity& ent); bool remove_component(const entity& ent);
template < typename T > template < typename T >
bool exists_component(const entity& ent) const noexcept; bool exists_component(const const_entity& ent) const noexcept;
std::size_t remove_all_components(const entity& ent) const noexcept; std::size_t remove_all_components(const entity& ent) noexcept;
template < typename T > template < typename T >
T& get_component(const entity& ent); T& get_component(const entity& ent);
template < typename T > template < typename T >
const T& get_component(const entity& ent) const; const T& get_component(const const_entity& ent) const;
template < typename T > template < typename T >
T* find_component(const entity& ent) noexcept; T* find_component(const entity& ent) noexcept;
template < typename T > template < typename T >
const T* find_component(const entity& ent) const noexcept; const T* find_component(const const_entity& ent) const noexcept;
template < typename... Ts > template < typename... Ts >
std::tuple<Ts&...> get_components(const entity& ent); std::tuple<Ts&...> get_components(const entity& ent);
template < typename... Ts > template < typename... Ts >
std::tuple<const Ts&...> get_components(const entity& ent) const; std::tuple<const Ts&...> get_components(const const_entity& ent) const;
template < typename... Ts > template < typename... Ts >
std::tuple<Ts*...> find_components(const entity& ent) noexcept; std::tuple<Ts*...> find_components(const entity& ent) noexcept;
template < typename... Ts > template < typename... Ts >
std::tuple<const Ts*...> find_components(const entity& ent) const noexcept; std::tuple<const Ts*...> find_components(const const_entity& ent) const noexcept;
template < typename F >
void for_each_entity(F&& f);
template < typename F >
void for_each_entity(F&& f) const;
template < typename T, typename F > template < typename T, typename F >
void for_each_component(F&& f); void for_each_component(F&& f);
@@ -812,13 +845,13 @@ namespace ecs_hpp
template < typename T > template < typename T >
detail::component_storage<T>& get_or_create_storage_(); detail::component_storage<T>& get_or_create_storage_();
bool is_entity_alive_impl_(const entity& ent) const noexcept; bool is_entity_alive_impl_(const const_entity& ent) const noexcept;
std::size_t remove_all_components_impl_(const entity& ent) const noexcept; std::size_t remove_all_components_impl_(const entity& ent) noexcept;
template < typename T > template < typename T >
T* find_component_impl_(const entity& ent) noexcept; T* find_component_impl_(const entity& ent) noexcept;
template < typename T > template < typename T >
const T* find_component_impl_(const entity& ent) const noexcept; 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 > 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); void for_joined_components_impl_(F&& f, std::index_sequence<I, Is...> iseq);
@@ -843,7 +876,7 @@ namespace ecs_hpp
, typename Ss , typename Ss
, typename... Cs > , typename... Cs >
void for_joined_components_impl_( void for_joined_components_impl_(
const entity& e, const const_entity& e,
const F& f, const F& f,
const Ss& ss, const Ss& ss,
const Cs&... cs) const; const Cs&... cs) const;
@@ -857,7 +890,7 @@ namespace ecs_hpp
template < typename F, typename... Cs > template < typename F, typename... Cs >
void for_joined_components_impl_( void for_joined_components_impl_(
const entity& e, const const_entity& e,
const F& f, const F& f,
const std::tuple<>& ss, const std::tuple<>& ss,
const Cs&... cs) const; const Cs&... cs) const;
@@ -882,10 +915,10 @@ namespace ecs_hpp
namespace ecs_hpp namespace ecs_hpp
{ {
inline entity::entity(registry& owner) inline entity::entity(registry& owner) noexcept
: owner_(&owner) {} : owner_(&owner) {}
inline entity::entity(registry& owner, entity_id id) inline entity::entity(registry& owner, entity_id id) noexcept
: owner_(&owner) : owner_(&owner)
, id_(id) {} , id_(id) {}
@@ -976,6 +1009,72 @@ namespace ecs_hpp
} }
} }
// -----------------------------------------------------------------------------
//
// const_entity impl
//
// -----------------------------------------------------------------------------
namespace ecs_hpp
{
inline const_entity::const_entity(const entity& ent) noexcept
: owner_(&ent.owner())
, id_(ent.id()) {}
inline const_entity::const_entity(const registry& owner) noexcept
: owner_(&owner) {}
inline const_entity::const_entity(const registry& owner, entity_id id) noexcept
: owner_(&owner)
, id_(id) {}
inline const registry& const_entity::owner() const noexcept {
return *owner_;
}
inline entity_id const_entity::id() const noexcept {
return id_;
}
inline bool const_entity::is_alive() const noexcept {
return (*owner_).is_entity_alive(*this);
}
template < typename T >
bool const_entity::exists_component() const noexcept {
return (*owner_).exists_component<T>(*this);
}
template < typename T >
const T& const_entity::get_component() const {
return (*owner_).get_component<T>(*this);
}
template < typename T >
const T* const_entity::find_component() const noexcept {
return (*owner_).find_component<T>(*this);
}
template < typename... Ts >
std::tuple<const Ts&...> const_entity::get_components() const {
return (*owner_).get_components<Ts...>(*this);
}
template < typename... Ts >
std::tuple<const Ts*...> const_entity::find_components() const noexcept {
return (*owner_).find_components<Ts...>(*this);
}
inline bool operator==(const const_entity& l, const const_entity& r) noexcept {
return &l.owner() == &r.owner()
&& l.id() == r.id();
}
inline bool operator!=(const const_entity& l, const const_entity& r) noexcept {
return !(l == r);
}
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// //
// registry impl // registry impl
@@ -1011,7 +1110,7 @@ namespace ecs_hpp
return false; return false;
} }
inline bool registry::is_entity_alive(const entity& ent) const noexcept { inline bool registry::is_entity_alive(const const_entity& ent) const noexcept {
return is_entity_alive_impl_(ent); return is_entity_alive_impl_(ent);
} }
@@ -1038,7 +1137,7 @@ namespace ecs_hpp
} }
template < typename T > template < typename T >
bool registry::exists_component(const entity& ent) const noexcept { bool registry::exists_component(const const_entity& ent) const noexcept {
if ( !is_entity_alive_impl_(ent) ) { if ( !is_entity_alive_impl_(ent) ) {
return false; return false;
} }
@@ -1048,7 +1147,7 @@ namespace ecs_hpp
: false; : false;
} }
inline std::size_t registry::remove_all_components(const entity& ent) const noexcept { inline std::size_t registry::remove_all_components(const entity& ent) noexcept {
return remove_all_components_impl_(ent); return remove_all_components_impl_(ent);
} }
@@ -1062,7 +1161,7 @@ namespace ecs_hpp
} }
template < typename T > template < typename T >
const T& registry::get_component(const entity& ent) const { const T& registry::get_component(const const_entity& ent) const {
const T* component = find_component_impl_<T>(ent); const T* component = find_component_impl_<T>(ent);
if ( component ) { if ( component ) {
return *component; return *component;
@@ -1076,7 +1175,7 @@ namespace ecs_hpp
} }
template < typename T > template < typename T >
const T* registry::find_component(const entity& ent) const noexcept { const T* registry::find_component(const const_entity& ent) const noexcept {
return find_component_impl_<T>(ent); return find_component_impl_<T>(ent);
} }
@@ -1086,7 +1185,7 @@ namespace ecs_hpp
} }
template < typename... Ts > template < typename... Ts >
std::tuple<const Ts&...> registry::get_components(const entity& ent) const { std::tuple<const Ts&...> registry::get_components(const const_entity& ent) const {
return std::make_tuple(std::cref(get_component<Ts>(ent))...); return std::make_tuple(std::cref(get_component<Ts>(ent))...);
} }
@@ -1096,10 +1195,24 @@ namespace ecs_hpp
} }
template < typename... Ts > template < typename... Ts >
std::tuple<const Ts*...> registry::find_components(const entity& ent) const noexcept { std::tuple<const Ts*...> registry::find_components(const const_entity& ent) const noexcept {
return std::make_tuple(find_component<Ts>(ent)...); return std::make_tuple(find_component<Ts>(ent)...);
} }
template < typename F >
void registry::for_each_entity(F&& f) {
for ( const auto id : entity_ids_ ) {
f(entity(*this, id));
}
}
template < typename F >
void registry::for_each_entity(F&& f) const {
for ( const auto id : entity_ids_ ) {
f(const_entity(*this, id));
}
}
template < typename T, typename F > template < typename T, typename F >
void registry::for_each_component(F&& f) { void registry::for_each_component(F&& f) {
detail::component_storage<T>* storage = find_storage_<T>(); detail::component_storage<T>* storage = find_storage_<T>();
@@ -1146,8 +1259,9 @@ namespace ecs_hpp
detail::component_storage<T>* registry::find_storage_() noexcept { detail::component_storage<T>* registry::find_storage_() noexcept {
const auto family = detail::type_family<T>::id(); const auto family = detail::type_family<T>::id();
using raw_storage_ptr = detail::component_storage<T>*; using raw_storage_ptr = detail::component_storage<T>*;
return storages_.has(family) const storage_uptr* storage_uptr_ptr = storages_.find(family);
? static_cast<raw_storage_ptr>(storages_.get(family).get()) return storage_uptr_ptr && *storage_uptr_ptr
? static_cast<raw_storage_ptr>(storage_uptr_ptr->get())
: nullptr; : nullptr;
} }
@@ -1155,8 +1269,9 @@ namespace ecs_hpp
const detail::component_storage<T>* registry::find_storage_() const noexcept { const detail::component_storage<T>* registry::find_storage_() const noexcept {
const auto family = detail::type_family<T>::id(); const auto family = detail::type_family<T>::id();
using raw_storage_ptr = const detail::component_storage<T>*; using raw_storage_ptr = const detail::component_storage<T>*;
return storages_.has(family) const storage_uptr* storage_uptr_ptr = storages_.find(family);
? static_cast<raw_storage_ptr>(storages_.get(family).get()) return storage_uptr_ptr && *storage_uptr_ptr
? static_cast<raw_storage_ptr>(storage_uptr_ptr->get())
: nullptr; : nullptr;
} }
@@ -1174,11 +1289,11 @@ namespace ecs_hpp
storages_.get(family).get()); storages_.get(family).get());
} }
inline bool registry::is_entity_alive_impl_(const entity& ent) const noexcept { inline bool registry::is_entity_alive_impl_(const const_entity& ent) const noexcept {
return entity_ids_.has(ent.id()); return entity_ids_.has(ent.id());
} }
inline std::size_t registry::remove_all_components_impl_(const entity& ent) const noexcept { inline std::size_t registry::remove_all_components_impl_(const entity& ent) noexcept {
if ( !is_entity_alive_impl_(ent) ) { if ( !is_entity_alive_impl_(ent) ) {
return 0u; return 0u;
} }
@@ -1200,7 +1315,7 @@ namespace ecs_hpp
} }
template < typename T > template < typename T >
const T* registry::find_component_impl_(const entity& ent) const noexcept { const T* registry::find_component_impl_(const const_entity& ent) const noexcept {
const detail::component_storage<T>* storage = find_storage_<T>(); const detail::component_storage<T>* storage = find_storage_<T>();
return storage return storage
? storage->find(ent.id()) ? storage->find(ent.id())
@@ -1237,7 +1352,7 @@ namespace ecs_hpp
(void)iseq; (void)iseq;
const auto ss = std::make_tuple(find_storage_<Ts>()...); const auto ss = std::make_tuple(find_storage_<Ts>()...);
if ( !detail::tuple_contains(ss, nullptr) ) { if ( !detail::tuple_contains(ss, nullptr) ) {
for_each_component<T>([this, &f, &ss](const entity& e, const T& t) { for_each_component<T>([this, &f, &ss](const const_entity& e, const T& t) {
detail::as_const(*this).for_joined_components_impl_<Ts...>(e, f, ss, t); detail::as_const(*this).for_joined_components_impl_<Ts...>(e, f, ss, t);
}); });
} }
@@ -1271,7 +1386,7 @@ namespace ecs_hpp
, typename Ss , typename Ss
, typename... Cs > , typename... Cs >
void registry::for_joined_components_impl_( void registry::for_joined_components_impl_(
const entity& e, const const_entity& e,
const F& f, const F& f,
const Ss& ss, const Ss& ss,
const Cs&... cs) const const Cs&... cs) const
@@ -1300,7 +1415,7 @@ namespace ecs_hpp
template < typename F, typename... Cs > template < typename F, typename... Cs >
void registry::for_joined_components_impl_( void registry::for_joined_components_impl_(
const entity& e, const const_entity& e,
const F& f, const F& f,
const std::tuple<>& ss, const std::tuple<>& ss,
const Cs&... cs) const const Cs&... cs) const

View File

@@ -80,6 +80,31 @@ TEST_CASE("detail") {
REQUIRE(tuple_tail(t3) == std::make_tuple(2, 3)); REQUIRE(tuple_tail(t3) == std::make_tuple(2, 3));
} }
} }
SECTION("tuple_contains") {
using namespace ecs::detail;
{
REQUIRE_FALSE(tuple_contains(std::make_tuple(), nullptr));
REQUIRE_FALSE(tuple_contains(std::make_tuple(1), 0));
REQUIRE_FALSE(tuple_contains(std::make_tuple(1), 2));
REQUIRE(tuple_contains(std::make_tuple(1), 1));
REQUIRE(tuple_contains(std::make_tuple(1,2,3), 1));
REQUIRE(tuple_contains(std::make_tuple(1,2,3), 2));
REQUIRE(tuple_contains(std::make_tuple(1,2,3), 3));
REQUIRE_FALSE(tuple_contains(std::make_tuple(1,2,3), 0));
REQUIRE_FALSE(tuple_contains(std::make_tuple(1,2,3), 4));
}
}
SECTION("entity_id") {
using namespace ecs::detail;
{
REQUIRE(entity_id_index(entity_id_join(10u, 20u)) == 10u);
REQUIRE(entity_id_version(entity_id_join(10u, 20u)) == 20u);
REQUIRE(upgrade_entity_id(entity_id_join(10u, 20u)) == entity_id_join(10u, 21u));
REQUIRE(upgrade_entity_id(entity_id_join(0u, 1023u)) == entity_id_join(0u, 0u));
REQUIRE(upgrade_entity_id(entity_id_join(1u, 1023u)) == entity_id_join(1u, 0u));
REQUIRE(upgrade_entity_id(entity_id_join(2048u, 1023u)) == entity_id_join(2048u, 0u));
}
}
SECTION("sparse_set") { SECTION("sparse_set") {
using namespace ecs::detail; using namespace ecs::detail;
{ {
@@ -87,7 +112,6 @@ TEST_CASE("detail") {
REQUIRE(s.empty()); REQUIRE(s.empty());
REQUIRE_FALSE(s.size()); REQUIRE_FALSE(s.size());
REQUIRE(s.capacity() == 0u);
REQUIRE_FALSE(s.has(42u)); REQUIRE_FALSE(s.has(42u));
REQUIRE(s.find(42u) == s.end()); REQUIRE(s.find(42u) == s.end());
REQUIRE_FALSE(s.find_dense_index(42u).second); REQUIRE_FALSE(s.find_dense_index(42u).second);
@@ -97,7 +121,6 @@ TEST_CASE("detail") {
REQUIRE_FALSE(s.empty()); REQUIRE_FALSE(s.empty());
REQUIRE(s.size() == 1u); REQUIRE(s.size() == 1u);
REQUIRE(s.capacity() == 85u);
REQUIRE(s.has(42u)); REQUIRE(s.has(42u));
REQUIRE_FALSE(s.has(84u)); REQUIRE_FALSE(s.has(84u));
@@ -121,7 +144,6 @@ TEST_CASE("detail") {
REQUIRE_FALSE(s.has(84u)); REQUIRE_FALSE(s.has(84u));
REQUIRE(s.empty()); REQUIRE(s.empty());
REQUIRE_FALSE(s.size()); REQUIRE_FALSE(s.size());
REQUIRE(s.capacity() == 85u * 2);
s.insert(42u); s.insert(42u);
s.insert(84u); s.insert(84u);
@@ -175,7 +197,6 @@ TEST_CASE("detail") {
REQUIRE(m.empty()); REQUIRE(m.empty());
REQUIRE_FALSE(m.size()); REQUIRE_FALSE(m.size());
REQUIRE(m.capacity() == 0u);
REQUIRE_FALSE(m.has(42u)); REQUIRE_FALSE(m.has(42u));
REQUIRE_THROWS(m.get(42u)); REQUIRE_THROWS(m.get(42u));
REQUIRE_THROWS(as_const(m).get(42u)); REQUIRE_THROWS(as_const(m).get(42u));
@@ -198,7 +219,6 @@ TEST_CASE("detail") {
REQUIRE_FALSE(m.empty()); REQUIRE_FALSE(m.empty());
REQUIRE(m.size() == 3u); REQUIRE(m.size() == 3u);
REQUIRE(m.capacity() >= 3u);
REQUIRE(m.has(21u)); REQUIRE(m.has(21u));
REQUIRE(m.has(42u)); REQUIRE(m.has(42u));
REQUIRE(m.has(84u)); REQUIRE(m.has(84u));
@@ -459,12 +479,6 @@ TEST_CASE("registry") {
REQUIRE_THROWS_AS(ww.get_component<velocity_c>(e1), std::logic_error); REQUIRE_THROWS_AS(ww.get_component<velocity_c>(e1), std::logic_error);
REQUIRE_THROWS_AS(ww.get_component<position_c>(e2), std::logic_error); REQUIRE_THROWS_AS(ww.get_component<position_c>(e2), std::logic_error);
ww.remove_all_components(e1);
ww.remove_all_components(e2);
REQUIRE_FALSE(ww.find_component<position_c>(e1));
REQUIRE_FALSE(ww.find_component<velocity_c>(e2));
} }
} }
{ {
@@ -545,6 +559,30 @@ TEST_CASE("registry") {
REQUIRE(e1.get_component<velocity_c>().y == 40); REQUIRE(e1.get_component<velocity_c>().y == 40);
} }
} }
SECTION("for_each_entity") {
{
ecs::registry w;
auto e1 = w.create_entity();
auto e2 = w.create_entity();
{
ecs::entity_id acc1 = 0;
w.for_each_entity([&acc1](const ecs::entity& e){
acc1 += e.id();
});
REQUIRE(acc1 == e1.id() + e2.id());
}
{
const ecs::registry& ww = w;
ecs::entity_id acc1 = 0;
ww.for_each_entity([&acc1](const ecs::const_entity& e){
acc1 += e.id();
});
REQUIRE(acc1 == e1.id() + e2.id());
}
}
}
SECTION("for_each_component") { SECTION("for_each_component") {
{ {
ecs::registry w; ecs::registry w;
@@ -572,7 +610,7 @@ TEST_CASE("registry") {
const ecs::registry& ww = w; const ecs::registry& ww = w;
ecs::entity_id acc1 = 0; ecs::entity_id acc1 = 0;
int acc2 = 0; int acc2 = 0;
ww.for_each_component<position_c>([&acc1, &acc2](ecs::entity e, const position_c& p){ ww.for_each_component<position_c>([&acc1, &acc2](ecs::const_entity e, const position_c& p){
acc1 += e.id(); acc1 += e.id();
acc2 += p.x; acc2 += p.x;
}); });
@@ -645,7 +683,7 @@ TEST_CASE("registry") {
ecs::entity_id acc1 = 0; ecs::entity_id acc1 = 0;
int acc2 = 0; int acc2 = 0;
ww.for_joined_components<position_c, velocity_c>([&acc1, &acc2]( ww.for_joined_components<position_c, velocity_c>([&acc1, &acc2](
ecs::entity e, const position_c& p, const velocity_c& v) ecs::const_entity e, const position_c& p, const velocity_c& v)
{ {
acc1 += e.id(); acc1 += e.id();
acc2 += p.x + v.x; acc2 += p.x + v.x;
@@ -747,6 +785,7 @@ TEST_CASE("example") {
ecs_hpp::registry world; ecs_hpp::registry world;
world.add_system<movement_system>(); world.add_system<movement_system>();
world.add_system<gravity_system>(9.8f);
auto entity_one = world.create_entity(); auto entity_one = world.create_entity();
world.assign_component<position_component>(entity_one, 4.f, 2.f); world.assign_component<position_component>(entity_one, 4.f, 2.f);