diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 58589467a833..0975decefb7e 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -2321,10 +2321,14 @@ void SceneTreeDock::_new_scene_from(String p_file) { Node *base = selection.front()->get(); - Map reown; - reown[editor_data->get_edited_scene_root()] = base; - Node *copy = base->duplicate_and_reown(reown); + Map duplimap; + Node *copy = base->duplicate_from_editor(duplimap); + if (copy) { + for (int i = 0; i < copy->get_child_count(); i++) { + _set_node_owner_recursive(copy->get_child(i), copy); + } + Ref sdata = memnew(PackedScene); Error err = sdata->pack(copy); memdelete(copy); @@ -2354,6 +2358,16 @@ void SceneTreeDock::_new_scene_from(String p_file) { } } +void SceneTreeDock::_set_node_owner_recursive(Node *p_node, Node *p_owner) { + if (!p_node->get_owner()) { + p_node->set_owner(p_owner); + } + + for (int i = 0; i < p_node->get_child_count(); i++) { + _set_node_owner_recursive(p_node->get_child(i), p_owner); + } +} + static bool _is_node_visible(Node *p_node) { if (!p_node->get_owner()) { return false; diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index 3779b61c60f1..807e922418b3 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -203,6 +203,7 @@ class SceneTreeDock : public VBoxContainer { void _import_subscene(); void _new_scene_from(String p_file); + void _set_node_owner_recursive(Node *p_node, Node *p_owner); bool _validate_no_foreign(); bool _validate_no_instance(); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index df00af8f5ba5..9d8c7981e6a3 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2052,6 +2052,7 @@ Node *Node::_duplicate(int p_flags, Map *r_duplimap) const if (get_filename() != "") { //an instance node->set_filename(get_filename()); + node->data.editable_instance = data.editable_instance; } StringName script_property_name = CoreStringNames::get_singleton()->_script; @@ -2267,74 +2268,6 @@ void Node::remap_nested_resources(RES p_resource, const Map &p_resourc } #endif -void Node::_duplicate_and_reown(Node *p_new_parent, const Map &p_reown_map) const { - if (get_owner() != get_parent()->get_owner()) { - return; - } - - Node *node = nullptr; - - if (get_filename() != "") { - Ref res = ResourceLoader::load(get_filename()); - ERR_FAIL_COND_MSG(res.is_null(), "Cannot load scene: " + get_filename()); - node = res->instance(); - ERR_FAIL_COND(!node); - } else { - Object *obj = ClassDB::instance(get_class()); - ERR_FAIL_COND_MSG(!obj, "Node: Could not duplicate: " + String(get_class()) + "."); - node = Object::cast_to(obj); - if (!node) { - memdelete(obj); - ERR_FAIL_MSG("Node: Could not duplicate: " + String(get_class()) + "."); - } - } - - List plist; - - get_property_list(&plist); - - for (List::Element *E = plist.front(); E; E = E->next()) { - if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) { - continue; - } - String name = E->get().name; - - Variant value = get(name).duplicate(true); - - node->set(name, value); - } - - List groups; - get_groups(&groups); - - for (List::Element *E = groups.front(); E; E = E->next()) { - node->add_to_group(E->get().name, E->get().persistent); - } - - node->set_name(get_name()); - p_new_parent->add_child(node); - - Node *owner = get_owner(); - - if (p_reown_map.has(owner)) { - owner = p_reown_map[owner]; - } - - if (owner) { - NodePath p = get_path_to(owner); - if (owner != this) { - Node *new_owner = node->get_node(p); - if (new_owner) { - node->set_owner(new_owner); - } - } - } - - for (int i = 0; i < get_child_count(); i++) { - get_child(i)->_duplicate_and_reown(node, p_reown_map); - } -} - // Duplication of signals must happen after all the node descendants have been copied, // because re-targeting of connections from some descendant to another is not possible // if the emitter node comes later in tree order than the receiver @@ -2389,49 +2322,6 @@ void Node::_duplicate_signals(const Node *p_original, Node *p_copy) const { } } -Node *Node::duplicate_and_reown(const Map &p_reown_map) const { - ERR_FAIL_COND_V(get_filename() != "", nullptr); - - Object *obj = ClassDB::instance(get_class()); - ERR_FAIL_COND_V_MSG(!obj, nullptr, "Node: Could not duplicate: " + String(get_class()) + "."); - - Node *node = Object::cast_to(obj); - if (!node) { - memdelete(obj); - ERR_FAIL_V_MSG(nullptr, "Node: Could not duplicate: " + String(get_class()) + "."); - } - node->set_name(get_name()); - - List plist; - - get_property_list(&plist); - - for (List::Element *E = plist.front(); E; E = E->next()) { - if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) { - continue; - } - String name = E->get().name; - node->set(name, get(name)); - } - - List groups; - get_groups(&groups); - - for (List::Element *E = groups.front(); E; E = E->next()) { - node->add_to_group(E->get().name, E->get().persistent); - } - - for (int i = 0; i < get_child_count(); i++) { - get_child(i)->_duplicate_and_reown(node, p_reown_map); - } - - // Duplication of signals must happen after all the node descendants have been copied, - // because re-targeting of connections from some descendant to another is not possible - // if the emitter node comes later in tree order than the receiver - _duplicate_signals(this, node); - return node; -} - static void find_owned_by(Node *p_by, Node *p_node, List *p_owned) { if (p_node->get_owner() == p_by) { p_owned->push_back(p_node); diff --git a/scene/main/node.h b/scene/main/node.h index 249a0ff86e85..d47d271a106d 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -173,7 +173,6 @@ class Node : public Object { Array _get_node_and_resource(const NodePath &p_path); void _duplicate_signals(const Node *p_original, Node *p_copy) const; - void _duplicate_and_reown(Node *p_new_parent, const Map &p_reown_map) const; Node *_duplicate(int p_flags, Map *r_duplimap = nullptr) const; TypedArray _get_children() const; @@ -366,7 +365,6 @@ class Node : public Object { bool is_processing_unhandled_key_input() const; Node *duplicate(int p_flags = DUPLICATE_GROUPS | DUPLICATE_SIGNALS | DUPLICATE_SCRIPTS) const; - Node *duplicate_and_reown(const Map &p_reown_map) const; #ifdef TOOLS_ENABLED Node *duplicate_from_editor(Map &r_duplimap) const; Node *duplicate_from_editor(Map &r_duplimap, const Map &p_resource_remap) const;