registry::create_entity from prototype

This commit is contained in:
2019-04-12 04:22:02 +07:00
parent b7bbd986a0
commit 73896bdd24
2 changed files with 59 additions and 42 deletions

70
ecs.hpp
View File

@@ -37,9 +37,14 @@ namespace ecs_hpp
template < typename T > template < typename T >
class const_component; class const_component;
class prototype;
class system; class system;
class registry; class registry;
class entity_filler;
class registry_filler;
using family_id = std::uint16_t; using family_id = std::uint16_t;
using entity_id = std::uint32_t; using entity_id = std::uint32_t;
using priority_t = std::int32_t; using priority_t = std::int32_t;
@@ -427,8 +432,12 @@ namespace ecs_hpp
std::vector<std::size_t> sparse_; std::vector<std::size_t> sparse_;
}; };
template < typename T, typename Indexer > template < typename T
void swap(sparse_set<T,Indexer>& l, sparse_set<T,Indexer>& r) noexcept { , typename Indexer >
void swap(
sparse_set<T, Indexer>& l,
sparse_set<T, Indexer>& r) noexcept
{
l.swap(r); l.swap(r);
} }
} }
@@ -591,8 +600,13 @@ namespace ecs_hpp
std::vector<T> values_; std::vector<T> values_;
}; };
template < typename K, typename T, typename Indexer > template < typename K
void swap(sparse_map<K,T,Indexer>& l, sparse_map<K,T,Indexer>& r) noexcept { , typename T
, typename Indexer >
void swap(
sparse_map<K, T, Indexer>& l,
sparse_map<K, T, Indexer>& r) noexcept
{
l.swap(r); l.swap(r);
} }
} }
@@ -752,7 +766,7 @@ namespace ecs_hpp
entity_id id() const noexcept; entity_id id() const noexcept;
entity clone() const; entity clone() const;
bool destroy() noexcept; void destroy() noexcept;
bool valid() const noexcept; bool valid() const noexcept;
template < typename T, typename... Args > template < typename T, typename... Args >
@@ -1055,14 +1069,13 @@ namespace ecs_hpp
template < typename T, typename... Args > template < typename T, typename... Args >
prototype& assign_component(Args&&... args) &; prototype& assign_component(Args&&... args) &;
template < typename T, typename... Args > template < typename T, typename... Args >
prototype&& assign_component(Args&&... args) &&; prototype&& assign_component(Args&&... args) &&;
prototype& merge(const prototype& other, bool override) &; prototype& merge(const prototype& other, bool override) &;
prototype&& merge(const prototype& other, bool override) &&; prototype&& merge(const prototype& other, bool override) &&;
entity create_entity(registry& owner) const; void apply(entity& ent, bool override) const;
private: private:
detail::sparse_map< detail::sparse_map<
family_id, family_id,
@@ -1157,9 +1170,10 @@ namespace ecs_hpp
const_component<T> wrap_component(const const_uentity& ent) const noexcept; const_component<T> wrap_component(const const_uentity& ent) const noexcept;
entity create_entity(); entity create_entity();
entity create_entity(const const_uentity& prototype); entity create_entity(const prototype& proto);
entity create_entity(const const_uentity& proto);
bool destroy_entity(const uentity& ent) noexcept; void destroy_entity(const uentity& ent) noexcept;
bool valid_entity(const const_uentity& ent) const noexcept; bool valid_entity(const const_uentity& ent) const noexcept;
template < typename T, typename... Args > template < typename T, typename... Args >
@@ -1366,8 +1380,8 @@ namespace ecs_hpp
return (*owner_).create_entity(id_); return (*owner_).create_entity(id_);
} }
inline bool entity::destroy() noexcept { inline void entity::destroy() noexcept {
return (*owner_).destroy_entity(id_); (*owner_).destroy_entity(id_);
} }
inline bool entity::valid() const noexcept { inline bool entity::valid() const noexcept {
@@ -1799,17 +1813,10 @@ namespace ecs_hpp
return std::move(*this); return std::move(*this);
} }
inline entity prototype::create_entity(registry& owner) const { inline void prototype::apply(entity& ent, bool override) const {
auto ent = owner.create_entity(); for ( const auto family_id : appliers_ ) {
try { appliers_.get(family_id)->apply(ent, override);
for ( const auto family_id : appliers_ ) {
appliers_.get(family_id)->apply(ent, true);
}
} catch (...) {
owner.destroy_entity(ent);
throw;
} }
return ent;
} }
inline void swap(prototype& l, prototype& r) noexcept { inline void swap(prototype& l, prototype& r) noexcept {
@@ -1959,12 +1966,23 @@ namespace ecs_hpp
return wrap_entity(++last_entity_id_); return wrap_entity(++last_entity_id_);
} }
inline entity registry::create_entity(const const_uentity& prototype) { inline entity registry::create_entity(const prototype& proto) {
assert(valid_entity(prototype)); auto ent = create_entity();
try {
proto.apply(ent, true);
} catch (...) {
destroy_entity(ent);
throw;
}
return ent;
}
inline entity registry::create_entity(const const_uentity& proto) {
assert(valid_entity(proto));
entity ent = create_entity(); entity ent = create_entity();
try { try {
for ( const auto family_id : storages_ ) { for ( const auto family_id : storages_ ) {
storages_.get(family_id)->clone(prototype, ent.id()); storages_.get(family_id)->clone(proto, ent.id());
} }
} catch (...) { } catch (...) {
destroy_entity(ent); destroy_entity(ent);
@@ -1973,15 +1991,13 @@ namespace ecs_hpp
return ent; return ent;
} }
inline bool registry::destroy_entity(const uentity& ent) noexcept { inline void registry::destroy_entity(const uentity& ent) noexcept {
assert(valid_entity(ent)); assert(valid_entity(ent));
remove_all_components(ent); remove_all_components(ent);
if ( entity_ids_.unordered_erase(ent) ) { if ( entity_ids_.unordered_erase(ent) ) {
assert(free_entity_ids_.size() < free_entity_ids_.capacity()); assert(free_entity_ids_.size() < free_entity_ids_.capacity());
free_entity_ids_.push_back(ent); free_entity_ids_.push_back(ent);
return true;
} }
return false;
} }
inline bool registry::valid_entity(const const_uentity& ent) const noexcept { inline bool registry::valid_entity(const const_uentity& ent) const noexcept {

View File

@@ -118,6 +118,7 @@ TEST_CASE("detail") {
REQUIRE_THROWS(s.get_dense_index(42u)); REQUIRE_THROWS(s.get_dense_index(42u));
REQUIRE(s.insert(42u)); REQUIRE(s.insert(42u));
REQUIRE_FALSE(s.insert(42u));
REQUIRE_FALSE(s.empty()); REQUIRE_FALSE(s.empty());
REQUIRE(s.size() == 1u); REQUIRE(s.size() == 1u);
@@ -355,15 +356,15 @@ TEST_CASE("registry") {
REQUIRE(w.valid_entity(e3)); REQUIRE(w.valid_entity(e3));
REQUIRE(w.valid_entity(ee3)); REQUIRE(w.valid_entity(ee3));
REQUIRE(w.destroy_entity(e1)); w.destroy_entity(e1);
REQUIRE_FALSE(w.valid_entity(e1)); REQUIRE_FALSE(w.valid_entity(e1));
REQUIRE(w.valid_entity(e2)); REQUIRE(w.valid_entity(e2));
REQUIRE(w.destroy_entity(e2)); w.destroy_entity(e2);
REQUIRE_FALSE(w.valid_entity(e1)); REQUIRE_FALSE(w.valid_entity(e1));
REQUIRE_FALSE(w.valid_entity(e2)); REQUIRE_FALSE(w.valid_entity(e2));
REQUIRE(w.destroy_entity(ee3)); w.destroy_entity(ee3);
REQUIRE_FALSE(w.valid_entity(e3)); REQUIRE_FALSE(w.valid_entity(e3));
REQUIRE_FALSE(w.valid_entity(ee3)); REQUIRE_FALSE(w.valid_entity(ee3));
} }
@@ -520,8 +521,8 @@ TEST_CASE("registry") {
p.assign_component<position_c>(1, 2); p.assign_component<position_c>(1, 2);
ecs::registry w; ecs::registry w;
const auto e1 = p.create_entity(w); const auto e1 = w.create_entity(p);
const auto e2 = p.create_entity(w); const auto e2 = w.create_entity(p);
REQUIRE(w.entity_count() == 2u); REQUIRE(w.entity_count() == 2u);
REQUIRE(w.component_count<position_c>() == 2u); REQUIRE(w.component_count<position_c>() == 2u);
@@ -539,8 +540,8 @@ TEST_CASE("registry") {
.assign_component<velocity_c>(3,4); .assign_component<velocity_c>(3,4);
ecs::registry w; ecs::registry w;
const auto e1 = p.create_entity(w); const auto e1 = w.create_entity(p);
const auto e2 = p.create_entity(w); const auto e2 = w.create_entity(p);
REQUIRE(w.entity_count() == 2u); REQUIRE(w.entity_count() == 2u);
REQUIRE(w.component_count<position_c>() == 2u); REQUIRE(w.component_count<position_c>() == 2u);
@@ -564,7 +565,7 @@ TEST_CASE("registry") {
p3 = p2; p3 = p2;
ecs::registry w; ecs::registry w;
const auto e3 = p3.create_entity(w); const auto e3 = w.create_entity(p3);
REQUIRE(e3.get_component<position_c>() == position_c(1,2)); REQUIRE(e3.get_component<position_c>() == position_c(1,2));
REQUIRE(e3.get_component<velocity_c>() == velocity_c(3,4)); REQUIRE(e3.get_component<velocity_c>() == velocity_c(3,4));
} }
@@ -587,15 +588,15 @@ TEST_CASE("registry") {
ecs::registry w; ecs::registry w;
const auto e1 = p1.create_entity(w); const auto e1 = w.create_entity(p1);
REQUIRE(e1.get_component<position_c>() == position_c(1,2)); REQUIRE(e1.get_component<position_c>() == position_c(1,2));
const auto e2 = p2.create_entity(w); const auto e2 = w.create_entity(p2);
REQUIRE(e2.get_component<position_c>() == position_c(3,4)); REQUIRE(e2.get_component<position_c>() == position_c(3,4));
const auto e3 = p3.create_entity(w); const auto e3 = w.create_entity(p3);
REQUIRE(e3.get_component<position_c>() == position_c(1,2)); REQUIRE(e3.get_component<position_c>() == position_c(1,2));
REQUIRE(e3.get_component<velocity_c>() == velocity_c(3,4)); REQUIRE(e3.get_component<velocity_c>() == velocity_c(3,4));
const auto e4 = p4.create_entity(w); const auto e4 = w.create_entity(p4);
REQUIRE(e4.get_component<position_c>() == position_c(1,2)); REQUIRE(e4.get_component<position_c>() == position_c(1,2));
REQUIRE(e4.get_component<velocity_c>() == velocity_c(3,4)); REQUIRE(e4.get_component<velocity_c>() == velocity_c(3,4));
} }
@@ -654,7 +655,7 @@ TEST_CASE("registry") {
REQUIRE(e1.exists_component<position_c>()); REQUIRE(e1.exists_component<position_c>());
REQUIRE(e1.exists_component<velocity_c>()); REQUIRE(e1.exists_component<velocity_c>());
REQUIRE(e1.destroy()); e1.destroy();
REQUIRE_FALSE(w.component_count<position_c>()); REQUIRE_FALSE(w.component_count<position_c>());
REQUIRE_FALSE(w.component_count<velocity_c>()); REQUIRE_FALSE(w.component_count<velocity_c>());
@@ -672,7 +673,7 @@ TEST_CASE("registry") {
w.assign_component<position_c>(e2); w.assign_component<position_c>(e2);
w.assign_component<velocity_c>(e2); w.assign_component<velocity_c>(e2);
REQUIRE(w.destroy_entity(e1)); w.destroy_entity(e1);
REQUIRE(w.exists_component<position_c>(e2)); REQUIRE(w.exists_component<position_c>(e2));
REQUIRE(w.exists_component<velocity_c>(e2)); REQUIRE(w.exists_component<velocity_c>(e2));
@@ -691,7 +692,7 @@ TEST_CASE("registry") {
REQUIRE(&e2_pos == &w.get_component<position_c>(e2)); REQUIRE(&e2_pos == &w.get_component<position_c>(e2));
REQUIRE(&e2_vel == &w.get_component<velocity_c>(e2)); REQUIRE(&e2_vel == &w.get_component<velocity_c>(e2));
REQUIRE(e1.destroy()); e1.destroy();
} }
} }
SECTION("component_accessing") { SECTION("component_accessing") {