Parcourir la source

Fix signal duplication bug when duplicating node with instanced children

Change error checking in `duplicate_signals()` to check for path to
`p_original`, thus adhering to the method used in `duplicate`, instead
of checking for ownership.
Maganty Rushyendra il y a 5 ans
Parent
commit
0df5d74e6e
1 fichiers modifiés avec 33 ajouts et 24 suppressions
  1. 33 24
      scene/main/node.cpp

+ 33 - 24
scene/main/node.cpp

@@ -2247,42 +2247,51 @@ void Node::_duplicate_and_reown(Node *p_new_parent, const Map<Node *, Node *> &p
 // if the emitter node comes later in tree order than the receiver
 void Node::_duplicate_signals(const Node *p_original, Node *p_copy) const {
 
-	if (this != p_original && (get_owner() != p_original && get_owner() != p_original->get_owner()))
+	if ((this != p_original) && !(p_original->is_a_parent_of(this))) {
 		return;
+	}
 
-	List<Connection> conns;
-	get_all_signal_connections(&conns);
+	List<const Node *> process_list;
+	process_list.push_back(this);
+	while (!process_list.empty()) {
 
-	for (List<Connection>::Element *E = conns.front(); E; E = E->next()) {
+		const Node *n = process_list.front()->get();
+		process_list.pop_front();
 
-		if (E->get().flags & CONNECT_PERSIST) {
-			//user connected
-			NodePath p = p_original->get_path_to(this);
-			Node *copy = p_copy->get_node(p);
+		List<Connection> conns;
+		n->get_all_signal_connections(&conns);
 
-			Node *target = Object::cast_to<Node>(E->get().target);
-			if (!target) {
-				continue;
-			}
-			NodePath ptarget = p_original->get_path_to(target);
+		for (List<Connection>::Element *E = conns.front(); E; E = E->next()) {
+			if (E->get().flags & CONNECT_PERSIST) {
+				//user connected
+				NodePath p = p_original->get_path_to(n);
+				Node *copy = p_copy->get_node(p);
 
-			Node *copytarget = target;
+				Node *target = Object::cast_to<Node>(E->get().target);
+				if (!target) {
+					continue;
+				}
+				NodePath ptarget = p_original->get_path_to(target);
 
-			// Atempt to find a path to the duplicate target, if it seems it's not part
-			// of the duplicated and not yet parented hierarchy then at least try to connect
-			// to the same target as the original
+				Node *copytarget = target;
 
-			if (p_copy->has_node(ptarget))
-				copytarget = p_copy->get_node(ptarget);
+				// Attempt to find a path to the duplicate target, if it seems it's not part
+				// of the duplicated and not yet parented hierarchy then at least try to connect
+				// to the same target as the original
 
-			if (copy && copytarget && !copy->is_connected(E->get().signal, copytarget, E->get().method)) {
-				copy->connect(E->get().signal, copytarget, E->get().method, E->get().binds, E->get().flags);
+				if (p_copy->has_node(ptarget)) {
+					copytarget = p_copy->get_node(ptarget);
+				}
+
+				if (copy && copytarget && !copy->is_connected(E->get().signal, copytarget, E->get().method)) {
+					copy->connect(E->get().signal, copytarget, E->get().method, E->get().binds, E->get().flags);
+				}
 			}
 		}
-	}
 
-	for (int i = 0; i < get_child_count(); i++) {
-		get_child(i)->_duplicate_signals(p_original, p_copy);
+		for (int i = 0; i < n->get_child_count(); i++) {
+			process_list.push_back(n->get_child(i));
+		}
 	}
 }