diff --git a/headers/enduro2d/high/gobject.hpp b/headers/enduro2d/high/gobject.hpp index af764d8c..347e6319 100644 --- a/headers/enduro2d/high/gobject.hpp +++ b/headers/enduro2d/high/gobject.hpp @@ -11,43 +11,309 @@ namespace e2d { class gobject; - using gobject_iptr = intrusive_ptr; - using const_gobject_iptr = intrusive_ptr; + + template < typename T > + class gcomponent; + + template < typename T > + class const_gcomponent; } namespace e2d { - class gobject final - : private noncopyable - , public ref_counter { + class gobject final { public: - gobject(ecs::registry& registry); - gobject(ecs::registry& registry, const ecs::prototype& proto); - ~gobject() noexcept; + class state; + using state_iptr = intrusive_ptr; + const state_iptr& internal_state() const noexcept; + public: + gobject() = default; + explicit gobject(state_iptr state); - ecs::entity entity() noexcept; - ecs::const_entity entity() const noexcept; - ecs::entity_filler entity_filler() noexcept; + bool valid() const noexcept; + explicit operator bool() const noexcept; template < typename T > - ecs::component get_component() noexcept; + gcomponent component() noexcept; template < typename T > - ecs::const_component get_component() const noexcept; + const_gcomponent component() const noexcept; + public: + ecs::entity raw_entity() noexcept; + ecs::const_entity raw_entity() const noexcept; + + template < typename T > + ecs::component raw_component() noexcept; + template < typename T > + ecs::const_component raw_component() const noexcept; private: - ecs::entity entity_; + state_iptr state_; + }; + + template < typename T > + class gcomponent final { + public: + gcomponent() = default; + gcomponent(gobject owner); + + bool valid() const noexcept; + bool exists() const noexcept; + + template < typename... Args > + T& assign(Args&&... args); + + template < typename... Args > + T& ensure(Args&&... args); + + bool remove() noexcept; + + T& get(); + const T& get() const; + + T* find() noexcept; + const T* find() const noexcept; + + T& operator*() noexcept; + const T& operator*() const noexcept; + + T* operator->() noexcept; + const T* operator->() const noexcept; + + const gobject& owner() const noexcept; + explicit operator bool() const noexcept; + private: + gobject owner_; + }; + + template < typename T > + class const_gcomponent final { + public: + const_gcomponent() = default; + const_gcomponent(gobject owner); + const_gcomponent(const gcomponent& comp); + + bool valid() const noexcept; + bool exists() const noexcept; + + const T& get() const; + const T* find() const noexcept; + + const T& operator*() const noexcept; + const T* operator->() const noexcept; + + const gobject& owner() const noexcept; + explicit operator bool() const noexcept; + private: + gobject owner_; }; } namespace e2d { - template < typename T > - ecs::component gobject::get_component() noexcept { - return ecs::component(entity_); + class gobject::state + : private noncopyable + , public ref_counter { + public: + virtual ~state() noexcept {} + virtual bool valid() const noexcept = 0; + virtual ecs::entity raw_entity() noexcept = 0; + virtual ecs::const_entity raw_entity() const noexcept = 0; + }; + + inline const gobject::state_iptr& gobject::internal_state() const noexcept { + return state_; + } + + inline gobject::gobject(state_iptr state) + : state_(std::move(state)) {} + + inline bool gobject::valid() const noexcept { + return state_ && state_->valid(); + } + + inline gobject::operator bool() const noexcept { + return valid(); } template < typename T > - ecs::const_component gobject::get_component() const noexcept { - return ecs::const_component(entity_); + gcomponent gobject::component() noexcept { + return gcomponent(*this); + } + + template < typename T > + const_gcomponent gobject::component() const noexcept { + return const_gcomponent(*this); + } + + inline ecs::entity gobject::raw_entity() noexcept { + E2D_ASSERT(valid()); + return state_->raw_entity(); + } + + inline ecs::const_entity gobject::raw_entity() const noexcept { + E2D_ASSERT(valid()); + return state_->raw_entity(); + } + + template < typename T > + ecs::component gobject::raw_component() noexcept { + E2D_ASSERT(valid()); + return ecs::component(raw_entity()); + } + + template < typename T > + ecs::const_component gobject::raw_component() const noexcept { + E2D_ASSERT(valid()); + return ecs::const_component(raw_entity()); + } +} + +namespace e2d +{ + template < typename T > + gcomponent::gcomponent(gobject owner) + : owner_(std::move(owner)) {} + + template < typename T > + bool gcomponent::valid() const noexcept { + return owner_.valid(); + } + + template < typename T > + bool gcomponent::exists() const noexcept { + return owner_.valid() + && owner_.raw_component().exists(); + } + + template < typename T > + template < typename... Args > + T& gcomponent::assign(Args&&... args) { + E2D_ASSERT(owner_.valid()); + return owner_.raw_component().assign(std::forward(args)...); + } + + template < typename T > + template < typename... Args > + T& gcomponent::ensure(Args&&... args) { + E2D_ASSERT(owner_.valid()); + return owner_.raw_component().ensure(std::forward(args)...); + } + + template < typename T > + bool gcomponent::remove() noexcept { + return owner_.valid() + ? owner_.raw_component().remove() + : false; + } + + template < typename T > + T& gcomponent::get() { + E2D_ASSERT(owner_.valid()); + return owner_.raw_component().get(); + } + + template < typename T > + const T& gcomponent::get() const { + E2D_ASSERT(owner_.valid()); + return owner_.raw_component().get(); + } + + template < typename T > + T* gcomponent::find() noexcept { + return owner_.valid() + ? owner_.raw_component().find() + : nullptr; + } + + template < typename T > + const T* gcomponent::find() const noexcept { + return owner_.valid() + ? owner_.raw_component().find() + : nullptr; + } + + template < typename T > + T& gcomponent::operator*() noexcept { + return get(); + } + + template < typename T > + const T& gcomponent::operator*() const noexcept { + return get(); + } + + template < typename T > + T* gcomponent::operator->() noexcept { + return find(); + } + + template < typename T > + const T* gcomponent::operator->() const noexcept { + return find(); + } + + template < typename T > + const gobject& gcomponent::owner() const noexcept { + return owner_; + } + + template < typename T > + gcomponent::operator bool() const noexcept { + return exists(); + } +} + +namespace e2d +{ + template < typename T > + const_gcomponent::const_gcomponent(gobject owner) + : owner_(std::move(owner)) {} + + template < typename T > + const_gcomponent::const_gcomponent(const gcomponent& comp) + : owner_(comp.owner()) {} + + template < typename T > + bool const_gcomponent::valid() const noexcept { + return owner_.valid(); + } + + template < typename T > + bool const_gcomponent::exists() const noexcept { + return owner_.valid() + && owner_.raw_component().exists(); + } + + template < typename T > + const T& const_gcomponent::get() const { + E2D_ASSERT(owner_.valid()); + return owner_.raw_component().get(); + } + + template < typename T > + const T* const_gcomponent::find() const noexcept { + return owner_.valid() + ? owner_.raw_component().find() + : nullptr; + } + + template < typename T > + const T& const_gcomponent::operator*() const noexcept { + return get(); + } + + template < typename T > + const T* const_gcomponent::operator->() const noexcept { + return find(); + } + + template < typename T > + const gobject& const_gcomponent::owner() const noexcept { + return owner_; + } + + template < typename T > + const_gcomponent::operator bool() const noexcept { + return exists(); } } diff --git a/headers/enduro2d/high/node.hpp b/headers/enduro2d/high/node.hpp index a1e5f62f..fbc3b63a 100644 --- a/headers/enduro2d/high/node.hpp +++ b/headers/enduro2d/high/node.hpp @@ -30,15 +30,19 @@ namespace e2d virtual ~node() noexcept; static node_iptr create(); + static node_iptr create(const t3f& transform); + static node_iptr create(const node_iptr& parent); + static node_iptr create(const node_iptr& parent, const t3f& transform); - static node_iptr create(const gobject_iptr& owner); - static node_iptr create(const gobject_iptr& owner, const node_iptr& parent); + static node_iptr create(gobject owner); + static node_iptr create(gobject owner, const t3f& transform); - void owner(const gobject_iptr& owner) noexcept; + static node_iptr create(gobject owner, const node_iptr& parent); + static node_iptr create(gobject owner, const node_iptr& parent, const t3f& transform); - gobject_iptr owner() noexcept; - const_gobject_iptr owner() const noexcept; + void owner(gobject owner) noexcept; + const gobject& owner() const noexcept; void transform(const t3f& transform) noexcept; const t3f& transform() const noexcept; @@ -132,7 +136,7 @@ namespace e2d std::size_t extract_all_nodes(Iter iter) const; protected: node() = default; - node(const gobject_iptr& owner); + node(gobject owner); private: enum flag_masks : u32 { fm_dirty_local_matrix = 1u << 0, @@ -144,7 +148,7 @@ namespace e2d void update_world_matrix_() const noexcept; private: t3f transform_; - gobject_iptr owner_; + gobject owner_; node* parent_{nullptr}; node_children children_; private: diff --git a/headers/enduro2d/high/world.hpp b/headers/enduro2d/high/world.hpp index f894f740..e1811fbe 100644 --- a/headers/enduro2d/high/world.hpp +++ b/headers/enduro2d/high/world.hpp @@ -8,6 +8,7 @@ #include "_high.hpp" +#include "node.hpp" #include "prefab.hpp" #include "gobject.hpp" @@ -35,14 +36,27 @@ namespace e2d ecs::registry& registry() noexcept; const ecs::registry& registry() const noexcept; - gobject_iptr instantiate(); - gobject_iptr instantiate(const prefab& prefab); - void destroy_instance(const gobject_iptr& inst) noexcept; + gobject instantiate(); + gobject instantiate(const prefab& prefab); - gobject_iptr resolve(ecs::entity_id ent) const noexcept; - gobject_iptr resolve(const ecs::const_entity& ent) const noexcept; + gobject instantiate(const gobject& parent); + gobject instantiate(const node_iptr& parent); + + gobject instantiate(const prefab& prefab, const gobject& parent); + gobject instantiate(const prefab& prefab, const node_iptr& parent); + + gobject instantiate(const gobject& parent, const t3f& transform); + gobject instantiate(const node_iptr& parent, const t3f& transform); + + gobject instantiate(const prefab& prefab, const gobject& parent, const t3f& transform); + gobject instantiate(const prefab& prefab, const node_iptr& parent, const t3f& transform); + + void destroy_instance(const gobject& inst) noexcept; + + gobject resolve(ecs::entity_id ent) const noexcept; + gobject resolve(const ecs::const_entity& ent) const noexcept; private: ecs::registry registry_; - hash_map gobjects_; + hash_map gobjects_; }; } diff --git a/samples/sources/sample_03/sample_03.cpp b/samples/sources/sample_03/sample_03.cpp index 77d68f29..2cc7fc32 100644 --- a/samples/sources/sample_03/sample_03.cpp +++ b/samples/sources/sample_03/sample_03.cpp @@ -83,60 +83,64 @@ namespace } auto scene_i = the().instantiate(); - - scene_i->entity_filler() - .component() - .component(node::create(scene_i)); - - node_iptr scene_r = scene_i->get_component().get().node(); + scene_i.component().assign(); { - auto model_i = the().instantiate(); - - model_i->entity_filler() + prefab prefab; + prefab.prototype() .component(rotator{v3f::unit_y()}) - .component(node::create(model_i, scene_r)) - .component(renderer() - .materials({model_mat})) + .component(renderer().materials({model_mat})) .component(model_res); - node_iptr model_n = model_i->get_component().get().node(); - model_n->scale(v3f{20.f}); - model_n->translation(v3f{0.f,50.f,0.f}); + the().instantiate( + prefab, + scene_i, + make_trs3(v3f{0,50.f,0}, q4f::identity(), v3f{20.f})); } { - auto sprite_i = the().instantiate(); - - sprite_i->entity_filler() + prefab prefab; + prefab.prototype() .component(rotator{v3f::unit_z()}) - .component(node::create(sprite_i, scene_r)) .component() .component(sprite_renderer(sprite_res) .materials({{"normal", sprite_mat}})); - node_iptr sprite_n = sprite_i->get_component().get().node(); - sprite_n->translation(v3f{0,-50.f,0}); + the().instantiate( + prefab, + scene_i, + math::make_translation_trs3(v3f{0,-50.f,0})); } { + prefab prefab_a; + prefab_a.prototype() + .component(rotator{v3f::unit_z()}) + .component() + .component(sprite_renderer() + .filtering(false) + .materials({{"normal", sprite_mat}})) + .component(flipbook_player(flipbook_res) + .play("idle") + .looped(true)); + for ( std::size_t i = 0; i < 2; ++i ) for ( std::size_t j = 0; j < 5; ++j ) { - auto flipbook_i = the().instantiate(); + t3f trans{ + {-80.f + j * 40.f, -200.f + i * 40.f, 0}, + q4f::identity(), + {2.f,2.f,1.f}}; + gobject inst = the().instantiate(prefab_a, scene_i, trans); - flipbook_i->entity_filler() - .component(node::create(flipbook_i, scene_r)) - .component() - .component(sprite_renderer() - .filtering(false) - .materials({{"normal", sprite_mat}})) - .component(flipbook_player(flipbook_res) - .play("idle") - .looped(true)); + prefab prefab_b = prefab_a; + prefab_b.prototype() + .component(rotator{v3f::unit_z()}) + .component(node::create(make_trs3( + v3f{20.f,0.f,0.f}, + q4f::identity(), + v3f{0.3f,0.3f,3.f}))); - node_iptr flipbook_n = flipbook_i->get_component().get().node(); - flipbook_n->scale(v3f(2.f,2.f,1.f)); - flipbook_n->translation(v3f{-80.f + j * 40.f, -200.f + i * 40.f, 0}); + the().instantiate(prefab_b, inst); } } @@ -145,10 +149,9 @@ namespace bool create_camera() { auto camera_i = the().instantiate(); - camera_i->entity_filler() - .component(camera() - .background({1.f, 0.4f, 0.f, 1.f})) - .component(node::create(camera_i)); + camera_i.component().assign(camera() + .background({1.f, 0.4f, 0.f, 1.f})); + camera_i.component().assign(node::create(camera_i)); return true; } diff --git a/samples/sources/sample_04/sample_04.cpp b/samples/sources/sample_04/sample_04.cpp index 435f48ef..d2d40e29 100644 --- a/samples/sources/sample_04/sample_04.cpp +++ b/samples/sources/sample_04/sample_04.cpp @@ -55,8 +55,8 @@ namespace auto scene_prefab_res = the().load_asset("scenes/scene_prefab.json"); auto scene_go = scene_prefab_res ? the().instantiate(scene_prefab_res->content()) - : nullptr; - return !!scene_go; + : gobject(); + return scene_go.valid(); } bool create_systems() { diff --git a/samples/sources/sample_06/sample_06.cpp b/samples/sources/sample_06/sample_06.cpp index c8c64dfb..6ab50f14 100644 --- a/samples/sources/sample_06/sample_06.cpp +++ b/samples/sources/sample_06/sample_06.cpp @@ -94,8 +94,8 @@ namespace auto scene_prefab_res = the().load_asset("scenes/spine_scene_prefab.json"); auto scene_go = scene_prefab_res ? the().instantiate(scene_prefab_res->content()) - : nullptr; - return !!scene_go; + : gobject(); + return scene_go.valid(); } bool create_systems() { diff --git a/sources/enduro2d/high/gobject.cpp b/sources/enduro2d/high/gobject.cpp deleted file mode 100644 index 2c00b9ce..00000000 --- a/sources/enduro2d/high/gobject.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/******************************************************************************* - * This file is part of the "Enduro2D" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2018-2019, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#include - -namespace e2d -{ - gobject::gobject(ecs::registry& registry) - : entity_(registry.create_entity()) {} - - gobject::gobject(ecs::registry& registry, const ecs::prototype& proto) - : entity_(registry.create_entity(proto)) {} - - gobject::~gobject() noexcept { - entity_.destroy(); - } - - ecs::entity gobject::entity() noexcept { - return entity_; - } - - ecs::const_entity gobject::entity() const noexcept { - return entity_; - } - - ecs::entity_filler gobject::entity_filler() noexcept { - return ecs::entity_filler(entity_); - } -} diff --git a/sources/enduro2d/high/node.cpp b/sources/enduro2d/high/node.cpp index b3a3dc94..659e4442 100644 --- a/sources/enduro2d/high/node.cpp +++ b/sources/enduro2d/high/node.cpp @@ -9,8 +9,8 @@ namespace e2d { - node::node(const gobject_iptr& owner) - : owner_(owner) {} + node::node(gobject owner) + : owner_(std::move(owner)) {} node::~node() noexcept { E2D_ASSERT(!parent_); @@ -21,6 +21,12 @@ namespace e2d return node_iptr(new node()); } + node_iptr node::create(const t3f& transform) { + node_iptr n = create(); + n->transform(transform); + return n; + } + node_iptr node::create(const node_iptr& parent) { node_iptr child = create(); if ( parent ) { @@ -29,27 +35,41 @@ namespace e2d return child; } - node_iptr node::create(const gobject_iptr& owner) { - return node_iptr(new node(owner)); + node_iptr node::create(const node_iptr& parent, const t3f& transform) { + node_iptr n = create(parent); + n->transform(transform); + return n; } - node_iptr node::create(const gobject_iptr& owner, const node_iptr& parent) { - node_iptr child = create(owner); + node_iptr node::create(gobject owner) { + return node_iptr(new node(std::move(owner))); + } + + node_iptr node::create(gobject owner, const t3f& transform) { + node_iptr n = create(owner); + n->transform(transform); + return n; + } + + node_iptr node::create(gobject owner, const node_iptr& parent) { + node_iptr child = create(std::move(owner)); if ( parent ) { parent->add_child(child); } return child; } - void node::owner(const gobject_iptr& owner) noexcept { - owner_ = owner; + node_iptr node::create(gobject owner, const node_iptr& parent, const t3f& transform) { + node_iptr n = create(owner, parent); + n->transform(transform); + return n; } - gobject_iptr node::owner() noexcept { - return owner_; + void node::owner(gobject owner) noexcept { + owner_ = std::move(owner); } - const_gobject_iptr node::owner() const noexcept { + const gobject& node::owner() const noexcept { return owner_; } diff --git a/sources/enduro2d/high/systems/render_system_impl/render_system_drawer.cpp b/sources/enduro2d/high/systems/render_system_impl/render_system_drawer.cpp index 0d9d8718..95acc19c 100644 --- a/sources/enduro2d/high/systems/render_system_impl/render_system_drawer.cpp +++ b/sources/enduro2d/high/systems/render_system_impl/render_system_drawer.cpp @@ -86,20 +86,23 @@ namespace e2d::render_system_impl return; } - E2D_ASSERT(node->owner()->entity().valid()); - ecs::const_entity node_e = node->owner()->entity(); - const renderer* node_r = node_e.find_component(); + const gobject& owner = node->owner(); + gcomponent node_r{owner}; - if ( node_r && node_r->enabled() ) { - if ( auto mdl_r = node_e.find_component() ) { - draw(node, *node_r, *mdl_r); - } - if ( auto spn_p = node_e.find_component() ) { - draw(node, *node_r, *spn_p); - } - if ( auto spr_r = node_e.find_component() ) { - draw(node, *node_r, *spr_r); - } + if ( !node_r || !node_r->enabled() ) { + return; + } + + if ( auto mdl_r = gcomponent{owner} ) { + draw(node, *node_r, *mdl_r); + } + + if ( auto spn_p = gcomponent{owner} ) { + draw(node, *node_r, *spn_p); + } + + if ( auto spr_r = gcomponent{owner} ) { + draw(node, *node_r, *spr_r); } } diff --git a/sources/enduro2d/high/world.cpp b/sources/enduro2d/high/world.cpp index 6710ca6e..6dd1a833 100644 --- a/sources/enduro2d/high/world.cpp +++ b/sources/enduro2d/high/world.cpp @@ -6,9 +6,50 @@ #include -#include #include +namespace +{ + using namespace e2d; + + class gobject_state final : public gobject::state { + public: + gobject_state(ecs::registry& registry) + : entity_(registry.create_entity()) {} + + gobject_state(ecs::registry& registry, const ecs::prototype& proto) + : entity_(registry.create_entity(proto)) {} + + ~gobject_state() final { + destroy(); + } + + void destroy() noexcept { + if ( valid() ) { + entity_.destroy(); + valid_ = false; + } + } + + bool valid() const noexcept final { + return valid_; + } + + ecs::entity raw_entity() noexcept final { + E2D_ASSERT(valid()); + return entity_; + } + + ecs::const_entity raw_entity() const noexcept final { + E2D_ASSERT(valid()); + return entity_; + } + private: + bool valid_{true}; + ecs::entity entity_; + }; +} + namespace e2d { world::~world() noexcept { @@ -25,17 +66,17 @@ namespace e2d return registry_; } - gobject_iptr world::instantiate() { - auto inst = make_intrusive(registry_); - gobjects_.emplace(inst->entity().id(), inst); + gobject world::instantiate() { + gobject inst{make_intrusive(registry_)}; + gobjects_.emplace(inst.raw_entity().id(), inst); try { - auto inst_n = node::create(inst); - auto inst_a = inst->get_component(); + auto n = node::create(inst); + gcomponent inst_a{inst}; if ( inst_a && inst_a->node() ) { - inst_n->transform(inst_a->node()->transform()); + n->transform(inst_a->node()->transform()); } - inst_a.assign(inst_n); + inst_a.assign(n); } catch (...) { destroy_instance(inst); throw; @@ -44,17 +85,17 @@ namespace e2d return inst; } - gobject_iptr world::instantiate(const prefab& prefab) { - auto inst = make_intrusive(registry_, prefab.prototype()); - gobjects_.emplace(inst->entity().id(), inst); + gobject world::instantiate(const prefab& prefab) { + gobject inst{make_intrusive(registry_, prefab.prototype())}; + gobjects_.emplace(inst.raw_entity().id(), inst); try { - auto inst_n = node::create(inst); - auto inst_a = inst->get_component(); + auto n = node::create(inst); + gcomponent inst_a{inst}; if ( inst_a && inst_a->node() ) { - inst_n->transform(inst_a->node()->transform()); + n->transform(inst_a->node()->transform()); } - inst_a.assign(inst_n); + inst_a.assign(n); } catch (...) { destroy_instance(inst); throw; @@ -64,8 +105,8 @@ namespace e2d for ( const auto& child_prefab : prefab.children() ) { auto child = instantiate(child_prefab); try { - auto inst_a = inst->get_component(); - auto child_a = child->get_component(); + gcomponent inst_a{inst}; + gcomponent child_a{child}; inst_a->node()->add_child(child_a->node()); } catch (...) { destroy_instance(child); @@ -80,34 +121,113 @@ namespace e2d return inst; } - void world::destroy_instance(const gobject_iptr& inst) noexcept { - node_iptr inst_n = inst && inst->get_component() - ? inst->get_component()->node() - : nullptr; + gobject world::instantiate(const gobject& parent) { + gobject go = instantiate(); + if ( go && parent ) { + gcomponent parent_a{parent}; + if ( !parent_a ) { + parent_a.assign(node::create(parent)); + } + if ( !parent_a->node() ) { + parent_a->node(node::create(parent)); + } + parent_a->node()->add_child(gcomponent{go}->node()); + } + return go; + } + + gobject world::instantiate(const node_iptr& parent) { + gobject go = instantiate(); + if ( go && parent ) { + parent->add_child(gcomponent{go}->node()); + } + return go; + } + + gobject world::instantiate(const prefab& prefab, const gobject& parent) { + gobject go = instantiate(prefab); + if ( go && parent ) { + gcomponent parent_a{parent}; + if ( !parent_a ) { + parent_a.assign(node::create(parent)); + } + if ( !parent_a->node() ) { + parent_a->node(node::create(parent)); + } + parent_a->node()->add_child(gcomponent{go}->node()); + } + return go; + } + + gobject world::instantiate(const prefab& prefab, const node_iptr& parent) { + gobject go = instantiate(prefab); + if ( go && parent ) { + parent->add_child(gcomponent{go}->node()); + } + return go; + } + + gobject world::instantiate(const gobject& parent, const t3f& transform) { + gobject go = instantiate(parent); + if ( go ) { + gcomponent{go}->node()->transform(transform); + } + return go; + } + + gobject world::instantiate(const node_iptr& parent, const t3f& transform) { + gobject go = instantiate(parent); + if ( go ) { + gcomponent{go}->node()->transform(transform); + } + return go; + } + + gobject world::instantiate(const prefab& prefab, const gobject& parent, const t3f& transform) { + gobject go = instantiate(prefab, parent); + if ( go ) { + gcomponent{go}->node()->transform(transform); + } + return go; + } + + gobject world::instantiate(const prefab& prefab, const node_iptr& parent, const t3f& transform) { + gobject go = instantiate(prefab, parent); + if ( go ) { + gcomponent{go}->node()->transform(transform); + } + return go; + } + + void world::destroy_instance(const gobject& inst) noexcept { + gcomponent inst_a{inst}; + auto inst_n = inst_a ? inst_a->node() : nullptr; + if ( inst_n ) { - inst_n->for_each_child([this](const node_iptr& child_n){ + inst_n->for_each_child([this](const const_node_iptr& child_n){ destroy_instance(child_n->owner()); }); } + if ( inst ) { - inst->entity().remove_all_components(); - gobjects_.erase(inst->entity().id()); + gobjects_.erase(inst.raw_entity().id()); + dynamic_pointer_cast(inst.internal_state())->destroy(); } } - gobject_iptr world::resolve(ecs::entity_id ent) const noexcept { + gobject world::resolve(ecs::entity_id ent) const noexcept { E2D_ASSERT(registry_.valid_entity(ent)); const auto iter = gobjects_.find(ent); return iter != gobjects_.end() ? iter->second - : nullptr; + : gobject(); } - gobject_iptr world::resolve(const ecs::const_entity& ent) const noexcept { + gobject world::resolve(const ecs::const_entity& ent) const noexcept { E2D_ASSERT(registry_.valid_entity(ent)); const auto iter = gobjects_.find(ent.id()); return iter != gobjects_.end() ? iter->second - : nullptr; + : gobject(); } } diff --git a/untests/sources/untests_high/node.cpp b/untests/sources/untests_high/node.cpp index ef84c48d..4079a4ce 100644 --- a/untests/sources/untests_high/node.cpp +++ b/untests/sources/untests_high/node.cpp @@ -28,7 +28,7 @@ namespace ++s_ctor_count; } - fake_node(const gobject_iptr& owner) : node(owner) { + fake_node(gobject owner) : node(std::move(owner)) { ++s_ctor_count; }