Przeglądaj źródła

Fix crash on node duplication

That happened when an instanced scene was being duplicated while it also contained nodes added to it in the scene holding the instance.

Plus:
- Add comments about the logic behind all this.
- Move the null guard to where it can protect the most, but consider it a runtime error rather that a situation we expect.

Fixes #13282.
Pedro J. Estébanez 7 lat temu
rodzic
commit
922cf9fbb0
1 zmienionych plików z 9 dodań i 3 usunięć
  1. 9 3
      scene/main/node.cpp

+ 9 - 3
scene/main/node.cpp

@@ -2114,8 +2114,16 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const
 	node_tree.push_front(this);
 	node_tree.push_front(this);
 
 
 	if (instanced) {
 	if (instanced) {
+		// Since nodes in the instanced hierarchy won't be duplicated explicitly, we need to make an inventory
+		// of all the nodes in the tree of the instanced scene in order to transfer the values of the properties
+
 		for (List<const Node *>::Element *N = node_tree.front(); N; N = N->next()) {
 		for (List<const Node *>::Element *N = node_tree.front(); N; N = N->next()) {
 			for (int i = 0; i < N->get()->get_child_count(); ++i) {
 			for (int i = 0; i < N->get()->get_child_count(); ++i) {
+
+				// Skip nodes not really belonging to the instanced hierarchy; they'll be processed normally later
+				if (get_child(i)->data.owner != this)
+					continue;
+
 				node_tree.push_back(N->get()->get_child(i));
 				node_tree.push_back(N->get()->get_child(i));
 			}
 			}
 		}
 		}
@@ -2124,6 +2132,7 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const
 	for (List<const Node *>::Element *N = node_tree.front(); N; N = N->next()) {
 	for (List<const Node *>::Element *N = node_tree.front(); N; N = N->next()) {
 
 
 		Node *current_node = node->get_node(get_path_to(N->get()));
 		Node *current_node = node->get_node(get_path_to(N->get()));
+		ERR_CONTINUE(!current_node);
 
 
 		if (p_flags & DUPLICATE_SCRIPTS) {
 		if (p_flags & DUPLICATE_SCRIPTS) {
 			bool is_valid = false;
 			bool is_valid = false;
@@ -2136,9 +2145,6 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const
 		List<PropertyInfo> plist;
 		List<PropertyInfo> plist;
 		N->get()->get_property_list(&plist);
 		N->get()->get_property_list(&plist);
 
 
-		if (!current_node)
-			continue;
-
 		for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
 		for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
 
 
 			if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
 			if (!(E->get().usage & PROPERTY_USAGE_STORAGE))