Skip to content

Commit 9851c1b

Browse files
warriormaster12Alexander Streng
authored andcommitted
Fix property duplication when duplicating a parent node
1 parent dad6c77 commit 9851c1b

File tree

2 files changed

+45
-18
lines changed

2 files changed

+45
-18
lines changed

scene/main/node.cpp

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2737,25 +2737,9 @@ Node *Node::_duplicate(int p_flags, HashMap<const Node *, Node *> *r_duplimap) c
27372737
}
27382738

27392739
} else {
2740-
// If property points to a node which is owned by a node we are duplicating, update its path.
2741-
if (value.get_type() == Variant::OBJECT) {
2742-
Node *property_node = Object::cast_to<Node>(value);
2743-
if (property_node && is_ancestor_of(property_node)) {
2744-
value = current_node->get_node_or_null(get_path_to(property_node));
2745-
}
2746-
} else if (value.get_type() == Variant::ARRAY) {
2747-
Array arr = value;
2748-
if (arr.get_typed_builtin() == Variant::OBJECT) {
2749-
for (int i = 0; i < arr.size(); i++) {
2750-
Node *property_node = Object::cast_to<Node>(arr[i]);
2751-
if (property_node && is_ancestor_of(property_node)) {
2752-
arr[i] = current_node->get_node_or_null(get_path_to(property_node));
2753-
}
2754-
}
2755-
value = arr;
2756-
}
2740+
if (value.get_type() != Variant::OBJECT && (value.get_type() != Variant::ARRAY || static_cast<Array>(value).get_typed_builtin() != Variant::OBJECT)) {
2741+
current_node->set(name, value);
27572742
}
2758-
current_node->set(name, value);
27592743
}
27602744
}
27612745
}
@@ -2771,6 +2755,8 @@ Node *Node::duplicate(int p_flags) const {
27712755
_duplicate_signals(this, dupe);
27722756
}
27732757

2758+
_duplicate_properties_node(this, this, dupe);
2759+
27742760
return dupe;
27752761
}
27762762

@@ -2792,6 +2778,8 @@ Node *Node::duplicate_from_editor(HashMap<const Node *, Node *> &r_duplimap, con
27922778
// if the emitter node comes later in tree order than the receiver
27932779
_duplicate_signals(this, dupe);
27942780

2781+
_duplicate_properties_node(this, this, dupe);
2782+
27952783
return dupe;
27962784
}
27972785

@@ -2844,6 +2832,44 @@ void Node::remap_nested_resources(Ref<Resource> p_resource, const HashMap<Ref<Re
28442832
}
28452833
#endif
28462834

2835+
// Duplicates properties that store a Node.
2836+
// This has to be called after nodes have been duplicated since
2837+
// only then do we get a full picture of how the duplicated node tree looks like.
2838+
void Node::_duplicate_properties_node(const Node *p_root, const Node *p_original, Node *p_copy) const {
2839+
List<PropertyInfo> props;
2840+
p_copy->get_property_list(&props);
2841+
for (const PropertyInfo &E : props) {
2842+
if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
2843+
continue;
2844+
}
2845+
String name = E.name;
2846+
Variant value = p_original->get(name).duplicate(true);
2847+
if (value.get_type() == Variant::OBJECT) {
2848+
Node *property_node = Object::cast_to<Node>(value);
2849+
if (property_node && (p_root == property_node || p_root->is_ancestor_of(property_node))) {
2850+
value = p_copy->get_node_or_null(p_original->get_path_to(property_node));
2851+
p_copy->set(name, value);
2852+
}
2853+
} else if (value.get_type() == Variant::ARRAY) {
2854+
Array arr = value;
2855+
if (arr.get_typed_builtin() == Variant::OBJECT) {
2856+
for (int i = 0; i < arr.size(); i++) {
2857+
Node *property_node = Object::cast_to<Node>(arr[i]);
2858+
if (property_node && (p_root == property_node || p_root->is_ancestor_of(property_node))) {
2859+
arr[i] = p_copy->get_node_or_null(p_original->get_path_to(property_node));
2860+
}
2861+
}
2862+
value = arr;
2863+
p_copy->set(name, value);
2864+
}
2865+
}
2866+
}
2867+
2868+
for (int i = 0; i < p_copy->get_child_count(); i++) {
2869+
_duplicate_properties_node(p_root, p_original->get_child(i), p_copy->get_child(i));
2870+
}
2871+
}
2872+
28472873
// Duplication of signals must happen after all the node descendants have been copied,
28482874
// because re-targeting of connections from some descendant to another is not possible
28492875
// if the emitter node comes later in tree order than the receiver

scene/main/node.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ class Node : public Object {
247247
void _propagate_groups_dirty();
248248
Array _get_node_and_resource(const NodePath &p_path);
249249

250+
void _duplicate_properties_node(const Node *p_root, const Node *p_original, Node *p_copy) const;
250251
void _duplicate_signals(const Node *p_original, Node *p_copy) const;
251252
Node *_duplicate(int p_flags, HashMap<const Node *, Node *> *r_duplimap = nullptr) const;
252253

0 commit comments

Comments
 (0)