return component reference from assign. rename alive to valid. fix entity component_count function.

This commit is contained in:
2019-04-10 03:56:30 +07:00
parent 24bfcaf7eb
commit 783376c6fc
2 changed files with 85 additions and 121 deletions

104
ecs.hpp
View File

@@ -597,7 +597,7 @@ namespace ecs_hpp
component_storage(registry& owner);
template < typename... Args >
void assign(entity_id id, Args&&... args);
T& assign(entity_id id, Args&&... args);
bool exists(entity_id id) const noexcept;
bool remove(entity_id id) noexcept override;
@@ -623,8 +623,9 @@ namespace ecs_hpp
template < typename T >
template < typename... Args >
void component_storage<T>::assign(entity_id id, Args&&... args) {
T& component_storage<T>::assign(entity_id id, Args&&... args) {
components_.insert_or_assign(id, T(std::forward<Args>(args)...));
return components_.get(id);
}
template < typename T >
@@ -708,11 +709,11 @@ namespace ecs_hpp
entity_id id() const noexcept;
bool destroy();
bool alive() const noexcept;
entity clone() const;
bool valid() const noexcept;
template < typename T, typename... Args >
bool assign_component(Args&&... args);
T& assign_component(Args&&... args);
template < typename T >
bool remove_component();
@@ -743,6 +744,8 @@ namespace ecs_hpp
std::tuple<Ts*...> find_components() noexcept;
template < typename... Ts >
std::tuple<const Ts*...> find_components() const noexcept;
std::size_t component_count() const noexcept;
private:
registry* owner_{nullptr};
entity_id id_{0u};
@@ -795,7 +798,7 @@ namespace ecs_hpp
const registry& owner() const noexcept;
entity_id id() const noexcept;
bool alive() const noexcept;
bool valid() const noexcept;
template < typename T >
bool exists_component() const noexcept;
@@ -811,6 +814,8 @@ namespace ecs_hpp
template < typename... Ts >
std::tuple<const Ts*...> find_components() const noexcept;
std::size_t component_count() const noexcept;
private:
const registry* owner_{nullptr};
entity_id id_{0u};
@@ -865,7 +870,7 @@ namespace ecs_hpp
bool exists() const noexcept;
template < typename... Args >
bool assign(Args&&... args);
T& assign(Args&&... args);
T& get();
const T& get() const;
@@ -1046,10 +1051,10 @@ namespace ecs_hpp
entity create_entity(const const_uentity& prototype);
bool destroy_entity(const uentity& ent);
bool alive_entity(const const_uentity& ent) const noexcept;
bool valid_entity(const const_uentity& ent) const noexcept;
template < typename T, typename... Args >
bool assign_component(const uentity& ent, Args&&... args);
T& assign_component(const uentity& ent, Args&&... args);
template < typename T >
bool remove_component(const uentity& ent);
@@ -1081,7 +1086,6 @@ namespace ecs_hpp
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 >
@@ -1252,16 +1256,16 @@ namespace ecs_hpp
return (*owner_).destroy_entity(id_);
}
inline bool entity::alive() const noexcept {
return detail::as_const(*owner_).alive_entity(id_);
}
inline entity entity::clone() const {
return (*owner_).create_entity(id_);
}
inline bool entity::valid() const noexcept {
return detail::as_const(*owner_).valid_entity(id_);
}
template < typename T, typename... Args >
bool entity::assign_component(Args&&... args) {
T& entity::assign_component(Args&&... args) {
return (*owner_).assign_component<T>(
id_,
std::forward<Args>(args)...);
@@ -1321,6 +1325,10 @@ namespace ecs_hpp
return detail::as_const(*owner_).find_components<Ts...>(id_);
}
inline std::size_t entity::component_count() const noexcept {
return detail::as_const(*owner_).entity_component_count(id_);
}
inline bool operator<(const entity& l, const entity& r) noexcept {
return (&l.owner() < &r.owner())
|| (&l.owner() == &r.owner() && l.id() < r.id());
@@ -1372,8 +1380,8 @@ namespace ecs_hpp
return id_;
}
inline bool const_entity::alive() const noexcept {
return (*owner_).alive_entity(id_);
inline bool const_entity::valid() const noexcept {
return (*owner_).valid_entity(id_);
}
template < typename T >
@@ -1401,6 +1409,10 @@ namespace ecs_hpp
return (*owner_).find_components<Ts...>(id_);
}
inline std::size_t const_entity::component_count() const noexcept {
return (*owner_).entity_component_count(id_);
}
inline bool operator<(const const_entity& l, const const_entity& r) noexcept {
return (&l.owner() < &r.owner())
|| (&l.owner() == &r.owner() && l.id() < r.id());
@@ -1459,7 +1471,7 @@ namespace ecs_hpp
template < typename T >
template < typename... Args >
bool component<T>::assign(Args&&... args) {
T& component<T>::assign(Args&&... args) {
return owner_.assign_component<T>(
std::forward<Args>(args)...);
}
@@ -1708,11 +1720,8 @@ namespace ecs_hpp
}
inline entity registry::create_entity(const const_uentity& prototype) {
assert(prototype.check_owner(this));
assert(valid_entity(prototype));
entity ent = create_entity();
if ( !alive_entity(prototype) ) {
return ent;
}
try {
for ( const auto family_id : storages_ ) {
storages_.get(family_id)->clone(prototype, ent.id());
@@ -1725,7 +1734,7 @@ namespace ecs_hpp
}
inline bool registry::destroy_entity(const uentity& ent) {
assert(ent.check_owner(this));
assert(valid_entity(ent));
remove_all_components(ent);
if ( entity_ids_.unordered_erase(ent) ) {
free_entity_ids_.push_back(ent);
@@ -1734,29 +1743,22 @@ namespace ecs_hpp
return false;
}
inline bool registry::alive_entity(const const_uentity& ent) const noexcept {
inline bool registry::valid_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 uentity& ent, Args&&... args) {
assert(ent.check_owner(this));
if ( !alive_entity(ent) ) {
return false;
}
get_or_create_storage_<T>().assign(
T& registry::assign_component(const uentity& ent, Args&&... args) {
assert(valid_entity(ent));
return get_or_create_storage_<T>().assign(
ent,
std::forward<Args>(args)...);
return true;
}
template < typename T >
bool registry::remove_component(const uentity& ent) {
assert(ent.check_owner(this));
if ( !alive_entity(ent) ) {
return false;
}
assert(valid_entity(ent));
detail::component_storage<T>* storage = find_storage_<T>();
return storage
? storage->remove(ent)
@@ -1765,10 +1767,7 @@ namespace ecs_hpp
template < typename T >
bool registry::exists_component(const const_uentity& ent) const noexcept {
assert(ent.check_owner(this));
if ( !alive_entity(ent) ) {
return false;
}
assert(valid_entity(ent));
const detail::component_storage<T>* storage = find_storage_<T>();
return storage
? storage->exists(ent)
@@ -1776,10 +1775,7 @@ namespace ecs_hpp
}
inline std::size_t registry::remove_all_components(const uentity& ent) noexcept {
assert(ent.check_owner(this));
if ( !alive_entity(ent) ) {
return 0u;
}
assert(valid_entity(ent));
std::size_t removed_count = 0u;
for ( const auto family_id : storages_ ) {
if ( storages_.get(family_id)->remove(ent) ) {
@@ -1791,7 +1787,7 @@ namespace ecs_hpp
template < typename T >
T& registry::get_component(const uentity& ent) {
assert(ent.check_owner(this));
assert(valid_entity(ent));
T* component = find_component<T>(ent);
if ( component ) {
return *component;
@@ -1801,7 +1797,7 @@ namespace ecs_hpp
template < typename T >
const T& registry::get_component(const const_uentity& ent) const {
assert(ent.check_owner(this));
assert(valid_entity(ent));
const T* component = find_component<T>(ent);
if ( component ) {
return *component;
@@ -1811,7 +1807,7 @@ namespace ecs_hpp
template < typename T >
T* registry::find_component(const uentity& ent) noexcept {
assert(ent.check_owner(this));
assert(valid_entity(ent));
detail::component_storage<T>* storage = find_storage_<T>();
return storage
? storage->find(ent)
@@ -1820,7 +1816,7 @@ namespace ecs_hpp
template < typename T >
const T* registry::find_component(const const_uentity& ent) const noexcept {
assert(ent.check_owner(this));
assert(valid_entity(ent));
const detail::component_storage<T>* storage = find_storage_<T>();
return storage
? storage->find(ent)
@@ -1829,25 +1825,25 @@ namespace ecs_hpp
template < typename... Ts >
std::tuple<Ts&...> registry::get_components(const uentity& ent) {
assert(ent.check_owner(this));
assert(valid_entity(ent));
return std::make_tuple(std::ref(get_component<Ts>(ent))...);
}
template < typename... Ts >
std::tuple<const Ts&...> registry::get_components(const const_uentity& ent) const {
assert(ent.check_owner(this));
assert(valid_entity(ent));
return std::make_tuple(std::cref(get_component<Ts>(ent))...);
}
template < typename... Ts >
std::tuple<Ts*...> registry::find_components(const uentity& ent) noexcept {
assert(ent.check_owner(this));
assert(valid_entity(ent));
return std::make_tuple(find_component<Ts>(ent)...);
}
template < typename... Ts >
std::tuple<const Ts*...> registry::find_components(const const_uentity& ent) const noexcept {
assert(ent.check_owner(this));
assert(valid_entity(ent));
return std::make_tuple(find_component<Ts>(ent)...);
}
@@ -1859,12 +1855,8 @@ namespace ecs_hpp
: 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;
}
inline std::size_t registry::entity_component_count(const const_uentity& ent) const noexcept {
assert(valid_entity(ent));
std::size_t component_count = 0u;
for ( const auto family_id : storages_ ) {
if ( storages_.get(family_id)->has(ent) ) {

View File

@@ -330,12 +330,9 @@ TEST_CASE("registry") {
REQUIRE_FALSE(e1 != e2);
REQUIRE_FALSE(e2 != e3);
REQUIRE_FALSE(w.alive_entity(e1));
REQUIRE_FALSE(w.alive_entity(e2));
REQUIRE_FALSE(w.alive_entity(e3));
REQUIRE_FALSE(w.destroy_entity(e1));
REQUIRE_FALSE(w.destroy_entity(e2));
REQUIRE_FALSE(w.valid_entity(e1));
REQUIRE_FALSE(w.valid_entity(e2));
REQUIRE_FALSE(w.valid_entity(e3));
}
{
ecs::registry w;
@@ -353,26 +350,22 @@ TEST_CASE("registry") {
REQUIRE_FALSE(e2 == e3);
REQUIRE(e3 == ee3);
REQUIRE(w.alive_entity(e1));
REQUIRE(w.alive_entity(e2));
REQUIRE(w.alive_entity(e3));
REQUIRE(w.alive_entity(ee3));
REQUIRE(w.valid_entity(e1));
REQUIRE(w.valid_entity(e2));
REQUIRE(w.valid_entity(e3));
REQUIRE(w.valid_entity(ee3));
REQUIRE(w.destroy_entity(e1));
REQUIRE_FALSE(w.alive_entity(e1));
REQUIRE(w.alive_entity(e2));
REQUIRE_FALSE(w.valid_entity(e1));
REQUIRE(w.valid_entity(e2));
REQUIRE(w.destroy_entity(e2));
REQUIRE_FALSE(w.alive_entity(e1));
REQUIRE_FALSE(w.alive_entity(e2));
REQUIRE_FALSE(w.valid_entity(e1));
REQUIRE_FALSE(w.valid_entity(e2));
REQUIRE(w.destroy_entity(ee3));
REQUIRE_FALSE(w.alive_entity(e3));
REQUIRE_FALSE(w.alive_entity(ee3));
REQUIRE_FALSE(w.destroy_entity(e1));
REQUIRE_FALSE(w.destroy_entity(e2));
REQUIRE_FALSE(w.destroy_entity(ee3));
REQUIRE_FALSE(w.valid_entity(e3));
REQUIRE_FALSE(w.valid_entity(ee3));
}
{
ecs::registry w;
@@ -469,7 +462,7 @@ TEST_CASE("registry") {
REQUIRE_THROWS_AS(c1.get(), std::logic_error);
REQUIRE_THROWS_AS(c2.get(), std::logic_error);
REQUIRE(c1.assign(4,2));
REQUIRE(c1.assign(4,2) == position_c(4,2));
REQUIRE(c1.exists());
REQUIRE(c2.exists());
@@ -482,7 +475,7 @@ TEST_CASE("registry") {
REQUIRE(c2.get().x == 4);
REQUIRE(c2.get().y == 2);
REQUIRE(c1.assign(2,4));
REQUIRE(&c1.assign(2,4) == &c1.get());
REQUIRE(c1.find()->x == 2);
REQUIRE(c1.find()->y == 4);
@@ -514,20 +507,23 @@ 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_FALSE(w.entity_component_count(e1));
REQUIRE_FALSE(e1.component_count());
REQUIRE(w.assign_component<position_c>(e1));
REQUIRE(w.assign_component<position_c>(e1) == position_c());
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.entity_component_count(e1) == 1u);
REQUIRE(e1.component_count() == 1u);
REQUIRE(w.assign_component<velocity_c>(e1));
REQUIRE(w.assign_component<velocity_c>(e1) == velocity_c());
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.entity_component_count(e1) == 2u);
REQUIRE(e1.component_count() == 2u);
REQUIRE(w.exists_component<position_c>(e1));
REQUIRE(w.exists_component<velocity_c>(e1));
@@ -538,30 +534,28 @@ TEST_CASE("registry") {
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));
REQUIRE_FALSE(w.entity_component_count(e1));
REQUIRE_FALSE(e1.component_count());
}
{
REQUIRE_FALSE(e1.exists_component<position_c>());
REQUIRE_FALSE(e1.exists_component<velocity_c>());
REQUIRE(e1.assign_component<position_c>());
REQUIRE(e1.assign_component<position_c>() == position_c());
REQUIRE(e1.exists_component<position_c>());
REQUIRE_FALSE(e1.exists_component<velocity_c>());
REQUIRE(e1.assign_component<velocity_c>());
REQUIRE(e1.assign_component<velocity_c>() == velocity_c());
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>());
REQUIRE_FALSE(w.component_count<position_c>());
REQUIRE_FALSE(w.component_count<velocity_c>());
REQUIRE_FALSE(w.entity_component_count<position_c>(e1));
}
}
{
@@ -570,37 +564,30 @@ TEST_CASE("registry") {
auto e1 = w.create_entity();
auto e2 = w.create_entity();
REQUIRE(w.assign_component<position_c>(e1));
REQUIRE(w.assign_component<velocity_c>(e1));
w.assign_component<position_c>(e1);
w.assign_component<velocity_c>(e1);
REQUIRE(w.assign_component<position_c>(e2));
REQUIRE(w.assign_component<velocity_c>(e2));
w.assign_component<position_c>(e2);
w.assign_component<velocity_c>(e2);
REQUIRE(w.destroy_entity(e1));
REQUIRE_FALSE(w.exists_component<position_c>(e1));
REQUIRE_FALSE(w.exists_component<velocity_c>(e1));
REQUIRE(w.exists_component<position_c>(e2));
REQUIRE(w.exists_component<velocity_c>(e2));
}
{
ecs::registry w;
auto e1 = w.create_entity();
REQUIRE(e1.destroy());
REQUIRE_FALSE(e1.assign_component<position_c>());
REQUIRE_FALSE(w.exists_component<position_c>(e1));
}
{
ecs::registry w;
auto e1 = w.create_entity();
auto e2 = w.create_entity();
REQUIRE(w.assign_component<position_c>(e1));
const position_c& e1_pos = w.assign_component<position_c>(e1);
REQUIRE(&e1_pos == &w.get_component<position_c>(e1));
REQUIRE(w.assign_component<position_c>(e2));
REQUIRE(w.assign_component<velocity_c>(e2));
const position_c& e2_pos = w.assign_component<position_c>(e2);
const velocity_c& e2_vel = w.assign_component<velocity_c>(e2);
REQUIRE(&e2_pos == &w.get_component<position_c>(e2));
REQUIRE(&e2_vel == &w.get_component<velocity_c>(e2));
REQUIRE(e1.destroy());
}
@@ -759,21 +746,6 @@ TEST_CASE("registry") {
REQUIRE_FALSE(e3.exists_component<velocity_c>());
REQUIRE(e3.get_component<position_c>() == position_c(1, 2));
}
{
ecs::registry w;
auto e1 = w.create_entity();
ecs::entity_filler(e1)
.component<position_c>(1, 2)
.component<velocity_c>(3, 4);
e1.destroy();
auto e2 = e1.clone();
REQUIRE_FALSE(e2.exists_component<position_c>());
REQUIRE_FALSE(e2.exists_component<velocity_c>());
REQUIRE(w.component_count<position_c>() == 0);
REQUIRE(w.component_count<velocity_c>() == 0);
}
}
SECTION("for_each_entity") {
{