From 8f93c116ddee2ca6bce79a26430de90dc48cdbad Mon Sep 17 00:00:00 2001 From: Marcin Nowak Date: Wed, 4 Oct 2023 03:55:31 +0200 Subject: [PATCH] Revert of 0559fc5 as potential fix for #82756 --- editor/scene_tree_dock.cpp | 15 +---- editor/scene_tree_dock.h | 1 + scene/main/node.cpp | 111 +++++++++++++++++++++++++++++++++++++ scene/main/node.h | 2 + 4 files changed, 117 insertions(+), 12 deletions(-) diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 66dd19b500..9de70d7a15 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -2662,19 +2662,10 @@ void SceneTreeDock::_new_scene_from(String p_file) { Node *base = selection.front()->get(); - HashMap duplimap; - Node *copy = base->duplicate_from_editor(duplimap); - + HashMap reown; + reown[editor_data->get_edited_scene_root()] = base; + Node *copy = base->duplicate_and_reown(reown); if (copy) { - // Handle Unique Nodes. - for (int i = 0; i < copy->get_child_count(false); i++) { - if (copy->get_owner()) { - _set_node_owner_recursive(copy->get_child(i, false), copy); - } - } - // Root node cannot ever be unique name in its own Scene! - copy->set_unique_name_in_owner(false); - Ref sdata = memnew(PackedScene); Error err = sdata->pack(copy); memdelete(copy); diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index 9c111bce71..b884813663 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -233,6 +233,7 @@ class SceneTreeDock : public VBoxContainer { 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(); void _selection_changed(); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 421760b23f..698c5df861 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2692,6 +2692,74 @@ void Node::remap_nested_resources(Ref p_resource, const HashMap &p_reown_map) const { + if (get_owner() != get_parent()->get_owner()) { + return; + } + + Node *node = nullptr; + + if (get_scene_file_path() != "") { + Ref res = ResourceLoader::load(get_scene_file_path()); + ERR_FAIL_COND_MSG(res.is_null(), "Cannot load scene: " + get_scene_file_path()); + node = res->instantiate(); + ERR_FAIL_COND(!node); + } else { + Object *obj = ClassDB::instantiate(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 @@ -2752,6 +2820,49 @@ void Node::_duplicate_signals(const Node *p_original, Node *p_copy) const { } } +Node *Node::duplicate_and_reown(const HashMap &p_reown_map) const { + ERR_FAIL_COND_V(get_scene_file_path() != "", nullptr); + + Object *obj = ClassDB::instantiate(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 feda200b24..7a205c3ec8 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -239,6 +239,7 @@ private: void _duplicate_signals(const Node *p_original, Node *p_copy) const; Node *_duplicate(int p_flags, HashMap *r_duplimap = nullptr) const; + void _duplicate_and_reown(Node *p_new_parent, const HashMap &p_reown_map) const; TypedArray _get_groups() const; @@ -570,6 +571,7 @@ public: BitField get_process_thread_messages() const; Node *duplicate(int p_flags = DUPLICATE_GROUPS | DUPLICATE_SIGNALS | DUPLICATE_SCRIPTS) const; + Node *duplicate_and_reown(const HashMap &p_reown_map) const; #ifdef TOOLS_ENABLED Node *duplicate_from_editor(HashMap &r_duplimap) const; Node *duplicate_from_editor(HashMap &r_duplimap, const HashMap, Ref> &p_resource_remap) const; -- 2.42.0