From 89e0bac901a99564bbeb82b9a92a05ec787ae710 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 19 Mar 2020 07:36:20 +0700 Subject: [PATCH] little world instantiate refactoring --- headers/enduro2d/high/world.hpp | 9 +- .../bin/library/scripts/emmy/high/world.lua | 5 + .../high/bindings/high_binds/world_binds.cpp | 15 ++ sources/enduro2d/high/node.cpp | 24 ++-- sources/enduro2d/high/world.cpp | 134 +++++++++--------- 5 files changed, 103 insertions(+), 84 deletions(-) diff --git a/headers/enduro2d/high/world.hpp b/headers/enduro2d/high/world.hpp index 6b6888a5..386a26b4 100644 --- a/headers/enduro2d/high/world.hpp +++ b/headers/enduro2d/high/world.hpp @@ -23,12 +23,15 @@ namespace e2d const ecs::registry& registry() const noexcept; gobject instantiate(); - gobject instantiate(const prefab& prefab); + gobject instantiate(const t2f& transform); gobject instantiate(const node_iptr& parent); - gobject instantiate(const prefab& prefab, const node_iptr& parent); - gobject instantiate(const node_iptr& parent, const t2f& transform); + + gobject instantiate(const prefab& prefab); + gobject instantiate(const prefab& prefab, const t2f& transform); + + gobject instantiate(const prefab& prefab, const node_iptr& parent); gobject instantiate(const prefab& prefab, const node_iptr& parent, const t2f& transform); void destroy_instance(gobject inst) noexcept; diff --git a/samples/bin/library/scripts/emmy/high/world.lua b/samples/bin/library/scripts/emmy/high/world.lua index 43cfd182..052c60ae 100644 --- a/samples/bin/library/scripts/emmy/high/world.lua +++ b/samples/bin/library/scripts/emmy/high/world.lua @@ -2,7 +2,12 @@ local world = { } +---@overload fun(): gobject +---@overload fun(transform: t2f): gobject +---@overload fun(parent: node): gobject +---@overload fun(parent: node, transform: t2f): gobject ---@overload fun(prefab: prefab): gobject +---@overload fun(prefab: prefab, transform: t2f): gobject ---@overload fun(prefab: prefab, parent: node): gobject ---@overload fun(prefab: prefab, parent: node, transform: t2f): gobject ---@return gobject diff --git a/sources/enduro2d/high/bindings/high_binds/world_binds.cpp b/sources/enduro2d/high/bindings/high_binds/world_binds.cpp index 71b74fc4..ae898564 100644 --- a/sources/enduro2d/high/bindings/high_binds/world_binds.cpp +++ b/sources/enduro2d/high/bindings/high_binds/world_binds.cpp @@ -15,9 +15,24 @@ namespace e2d::bindings::high sol::no_constructor, "instantiate", sol::overload( + [](world& w) -> gobject { + return w.instantiate(); + }, + [](world& w, const t2f& transform) -> gobject { + return w.instantiate(transform); + }, + [](world& w, const node_iptr& parent) -> gobject { + return w.instantiate(parent); + }, + [](world& w, const node_iptr& parent, const t2f& transform) -> gobject { + return w.instantiate(parent, transform); + }, [](world& w, const prefab& prefab) -> gobject { return w.instantiate(prefab); }, + [](world& w, const prefab& prefab, const t2f& transform) -> gobject { + return w.instantiate(prefab, transform); + }, [](world& w, const prefab& prefab, const node_iptr& parent) -> gobject { return w.instantiate(prefab, parent); }, diff --git a/sources/enduro2d/high/node.cpp b/sources/enduro2d/high/node.cpp index e35f24a7..162ef303 100644 --- a/sources/enduro2d/high/node.cpp +++ b/sources/enduro2d/high/node.cpp @@ -21,9 +21,9 @@ namespace e2d } node_iptr node::create(const t2f& transform) { - node_iptr n = create(); - n->transform(transform); - return n; + node_iptr child = create(); + child->transform(transform); + return child; } node_iptr node::create(const node_iptr& parent) { @@ -35,9 +35,9 @@ namespace e2d } node_iptr node::create(const node_iptr& parent, const t2f& transform) { - node_iptr n = create(parent); - n->transform(transform); - return n; + node_iptr child = create(parent); + child->transform(transform); + return child; } node_iptr node::create(gobject owner) { @@ -45,9 +45,9 @@ namespace e2d } node_iptr node::create(gobject owner, const t2f& transform) { - node_iptr n = create(owner); - n->transform(transform); - return n; + node_iptr child = create(std::move(owner)); + child->transform(transform); + return child; } node_iptr node::create(gobject owner, const node_iptr& parent) { @@ -59,9 +59,9 @@ namespace e2d } node_iptr node::create(gobject owner, const node_iptr& parent, const t2f& transform) { - node_iptr n = create(owner, parent); - n->transform(transform); - return n; + node_iptr child = create(std::move(owner), parent); + child->transform(transform); + return child; } void node::owner(gobject owner) noexcept { diff --git a/sources/enduro2d/high/world.cpp b/sources/enduro2d/high/world.cpp index 44d485fd..6a8a8540 100644 --- a/sources/enduro2d/high/world.cpp +++ b/sources/enduro2d/high/world.cpp @@ -72,7 +72,7 @@ namespace if ( inst_n ) { inst_n->remove_from_parent(); - while ( node_iptr child = inst_n->first_child() ) { + while ( const node_iptr& child = inst_n->first_child() ) { delete_instance(child->owner()); } } @@ -85,60 +85,49 @@ namespace } } - gobject new_instance(world& world, const prefab& prefab) { - gobject inst; - ecs::entity ent = world.registry().create_entity(prefab.prototype()); - - try { - inst = gobject{make_intrusive(world, ent)}; - } catch (...) { + gobject new_instance(world& world, const prefab& root_prefab) { + ecs::entity ent = world.registry().create_entity(root_prefab.prototype()); + auto ent_defer = make_error_defer([&ent](){ ent.destroy(); - throw; - } + }); - try { - auto n = node::create(inst); - gcomponent inst_a{inst}; - if ( inst_a && inst_a->node() ) { - n->transform(inst_a->node()->transform()); + gobject root_i(make_intrusive(world, ent)); + E2D_ERROR_DEFER([&root_i](){ + delete_instance(root_i); + }); + + ent_defer.dismiss(); + + { + gcomponent root_a{root_i}; + node_iptr new_root_node = node::create(root_i); + if ( root_a && root_a->node() ) { + new_root_node->transform(root_a->node()->transform()); } - inst_a.assign(std::move(n)); - } catch (...) { - delete_instance(inst); - throw; + root_a.ensure().node(new_root_node); } - try { - gcomponent inst_b{inst}; - if ( inst_b && inst_b->script() ) { - const behaviours::fill_result r = behaviours::fill_meta_table(*inst_b); + { + gcomponent root_b{root_i}; + if ( root_b && root_b->script() ) { + const behaviours::fill_result r = behaviours::fill_meta_table(*root_b); if ( r == behaviours::fill_result::failed ) { - inst.component>().ensure(); + root_i.component>().ensure(); } } - } catch (...) { - delete_instance(inst); - throw; } - try { - for ( const auto& child_prefab : prefab.children() ) { - auto child = new_instance(world, child_prefab); - try { - gcomponent inst_a{inst}; - gcomponent child_a{child}; - inst_a->node()->add_child(child_a->node()); - } catch (...) { - delete_instance(child); - throw; - } - } - } catch (...) { - delete_instance(inst); - throw; + for ( const prefab& child_prefab : root_prefab.children() ) { + gobject child_i = new_instance(world, child_prefab); + E2D_ERROR_DEFER([&child_i](){ + delete_instance(child_i); + }); + gcomponent root_a{root_i}; + gcomponent child_a{child_i}; + root_a->node()->add_child(child_a->node()); } - return inst; + return root_i; } void shutdown_instance(gobject& inst) noexcept { @@ -188,57 +177,64 @@ namespace e2d } gobject world::instantiate() { - return instantiate(nullptr); + return instantiate(prefab(), nullptr); } - gobject world::instantiate(const prefab& prefab) { - return instantiate(prefab, nullptr); + gobject world::instantiate(const t2f& transform) { + return instantiate(prefab(), nullptr, transform); } gobject world::instantiate(const node_iptr& parent) { return instantiate(prefab(), parent); } + gobject world::instantiate(const node_iptr& parent, const t2f& transform) { + return instantiate(prefab(), parent, transform); + } + + gobject world::instantiate(const prefab& prefab) { + return instantiate(prefab, nullptr); + } + + gobject world::instantiate(const prefab& prefab, const t2f& transform) { + return instantiate(prefab, nullptr, transform); + } + gobject world::instantiate(const prefab& prefab, const node_iptr& parent) { E2D_PROFILER_SCOPE("world.instantiate"); gobject inst = new_instance(*this, prefab); - - if ( parent ) { - parent->add_child(inst.component()->node()); - } - - try { - start_instance(inst); - } catch (...) { + E2D_ERROR_DEFER([inst](){ delete_instance(inst); - throw; + }); + + if ( const node_iptr& node = inst.component()->node() ) { + if ( parent ) { + parent->add_child(node); + } } + start_instance(inst); return inst; } - gobject world::instantiate(const node_iptr& parent, const t2f& transform) { - return instantiate(prefab(), parent, transform); - } - gobject world::instantiate(const prefab& prefab, const node_iptr& parent, const t2f& transform) { E2D_PROFILER_SCOPE("world.instantiate"); gobject inst = new_instance(*this, prefab); - inst.component()->node()->transform(transform); - - if ( parent ) { - parent->add_child(inst.component()->node()); - } - - try { - start_instance(inst); - } catch (...) { + E2D_ERROR_DEFER([inst](){ delete_instance(inst); - throw; + }); + + if ( const node_iptr& node = inst.component()->node() ) { + node->transform(transform); + + if ( parent ) { + parent->add_child(node); + } } + start_instance(inst); return inst; }