From 9851c1bdd893a6194fdbf1820d2fa07449d4f9fb Mon Sep 17 00:00:00 2001 From: warriormaster12 Date: Fri, 19 Jan 2024 22:57:31 +0200 Subject: [PATCH] Fix property duplication when duplicating a parent node --- scene/main/node.cpp | 62 ++++++++++++++++++++++++++++++++------------- scene/main/node.h | 1 + 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 906c397b5cd..604a322a8b1 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2737,25 +2737,9 @@ Node *Node::_duplicate(int p_flags, HashMap *r_duplimap) c } } else { - // If property points to a node which is owned by a node we are duplicating, update its path. - if (value.get_type() == Variant::OBJECT) { - Node *property_node = Object::cast_to(value); - if (property_node && is_ancestor_of(property_node)) { - value = current_node->get_node_or_null(get_path_to(property_node)); - } - } else if (value.get_type() == Variant::ARRAY) { - Array arr = value; - if (arr.get_typed_builtin() == Variant::OBJECT) { - for (int i = 0; i < arr.size(); i++) { - Node *property_node = Object::cast_to(arr[i]); - if (property_node && is_ancestor_of(property_node)) { - arr[i] = current_node->get_node_or_null(get_path_to(property_node)); - } - } - value = arr; - } + if (value.get_type() != Variant::OBJECT && (value.get_type() != Variant::ARRAY || static_cast(value).get_typed_builtin() != Variant::OBJECT)) { + current_node->set(name, value); } - current_node->set(name, value); } } } @@ -2771,6 +2755,8 @@ Node *Node::duplicate(int p_flags) const { _duplicate_signals(this, dupe); } + _duplicate_properties_node(this, this, dupe); + return dupe; } @@ -2792,6 +2778,8 @@ Node *Node::duplicate_from_editor(HashMap &r_duplimap, con // if the emitter node comes later in tree order than the receiver _duplicate_signals(this, dupe); + _duplicate_properties_node(this, this, dupe); + return dupe; } @@ -2844,6 +2832,44 @@ void Node::remap_nested_resources(Ref p_resource, const HashMap props; + p_copy->get_property_list(&props); + for (const PropertyInfo &E : props) { + if (!(E.usage & PROPERTY_USAGE_STORAGE)) { + continue; + } + String name = E.name; + Variant value = p_original->get(name).duplicate(true); + if (value.get_type() == Variant::OBJECT) { + Node *property_node = Object::cast_to(value); + if (property_node && (p_root == property_node || p_root->is_ancestor_of(property_node))) { + value = p_copy->get_node_or_null(p_original->get_path_to(property_node)); + p_copy->set(name, value); + } + } else if (value.get_type() == Variant::ARRAY) { + Array arr = value; + if (arr.get_typed_builtin() == Variant::OBJECT) { + for (int i = 0; i < arr.size(); i++) { + Node *property_node = Object::cast_to(arr[i]); + if (property_node && (p_root == property_node || p_root->is_ancestor_of(property_node))) { + arr[i] = p_copy->get_node_or_null(p_original->get_path_to(property_node)); + } + } + value = arr; + p_copy->set(name, value); + } + } + } + + for (int i = 0; i < p_copy->get_child_count(); i++) { + _duplicate_properties_node(p_root, p_original->get_child(i), p_copy->get_child(i)); + } +} + // 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 diff --git a/scene/main/node.h b/scene/main/node.h index 7cc0f7b370b..15d68b1c3b1 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -247,6 +247,7 @@ private: void _propagate_groups_dirty(); Array _get_node_and_resource(const NodePath &p_path); + void _duplicate_properties_node(const Node *p_root, const Node *p_original, Node *p_copy) const; void _duplicate_signals(const Node *p_original, Node *p_copy) const; Node *_duplicate(int p_flags, HashMap *r_duplimap = nullptr) const;