1
0
mirror of https://github.com/godotengine/godot.git synced 2025-12-31 18:41:20 +00:00

Fix lost connections when saving branch as scene

This commit is contained in:
kobewi
2025-09-11 22:39:26 +02:00
parent 9b50ea8ade
commit cc571676b9
2 changed files with 44 additions and 16 deletions

View File

@@ -436,9 +436,9 @@ void SceneTreeDock::_perform_create_audio_stream_players(const Vector<String> &p
undo_redo->commit_action();
}
void SceneTreeDock::_replace_with_branch_scene(const String &p_file, Node *base) {
void SceneTreeDock::_replace_with_branch_scene(const String &p_file, Node *p_base) {
// `move_child` + `get_index` doesn't really work for internal nodes.
ERR_FAIL_COND_MSG(base->is_internal(), "Trying to replace internal node, this is not supported.");
ERR_FAIL_COND_MSG(p_base->is_internal(), "Trying to replace internal node, this is not supported.");
Ref<PackedScene> sdata = ResourceLoader::load(p_file);
if (sdata.is_null()) {
@@ -454,10 +454,10 @@ void SceneTreeDock::_replace_with_branch_scene(const String &p_file, Node *base)
return;
}
instantiated_scene->set_unique_name_in_owner(base->is_unique_name_in_owner());
instantiated_scene->set_unique_name_in_owner(p_base->is_unique_name_in_owner());
Node2D *copy_2d = Object::cast_to<Node2D>(instantiated_scene);
Node2D *base_2d = Object::cast_to<Node2D>(base);
Node2D *base_2d = Object::cast_to<Node2D>(p_base);
if (copy_2d && base_2d) {
copy_2d->set_position(base_2d->get_position());
copy_2d->set_rotation(base_2d->get_rotation());
@@ -465,27 +465,55 @@ void SceneTreeDock::_replace_with_branch_scene(const String &p_file, Node *base)
}
Node3D *copy_3d = Object::cast_to<Node3D>(instantiated_scene);
Node3D *base_3d = Object::cast_to<Node3D>(base);
Node3D *base_3d = Object::cast_to<Node3D>(p_base);
if (copy_3d && base_3d) {
copy_3d->set_position(base_3d->get_position());
copy_3d->set_rotation(base_3d->get_rotation());
copy_3d->set_scale(base_3d->get_scale());
}
// Ensure that local signals are still connected.
List<MethodInfo> signal_list;
p_base->get_signal_list(&signal_list);
for (const MethodInfo &meth : signal_list) {
List<Object::Connection> connection_list;
p_base->get_signal_connection_list(meth.name, &connection_list);
List<Object::Connection> other;
instantiated_scene->get_signal_connection_list(meth.name, &other);
for (const Object::Connection &con : connection_list) {
if (!(con.flags & Object::CONNECT_PERSIST)) {
continue;
}
// May be already connected if the connection was saved with the scene.
bool already_connected = false; // Can't use is_connected(), because of different targets.
for (const Object::Connection &otcon : other) {
if (otcon.signal.get_name() == con.signal.get_name() && otcon.callable.get_method() == con.callable.get_method()) {
already_connected = true;
break;
}
}
if (!already_connected) {
instantiated_scene->connect(con.signal.get_name(), con.callable, con.flags);
}
}
}
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
undo_redo->create_action(TTR("Replace with Branch Scene"));
Node *parent = base->get_parent();
int pos = base->get_index(false);
undo_redo->add_do_method(parent, "remove_child", base);
Node *parent = p_base->get_parent();
int pos = p_base->get_index(false);
undo_redo->add_do_method(parent, "remove_child", p_base);
undo_redo->add_undo_method(parent, "remove_child", instantiated_scene);
undo_redo->add_do_method(parent, "add_child", instantiated_scene, true);
undo_redo->add_undo_method(parent, "add_child", base, true);
undo_redo->add_undo_method(parent, "add_child", p_base, true);
undo_redo->add_do_method(parent, "move_child", instantiated_scene, pos);
undo_redo->add_undo_method(parent, "move_child", base, pos);
undo_redo->add_undo_method(parent, "move_child", p_base, pos);
List<Node *> owned;
base->get_owned_by(base->get_owner(), &owned);
p_base->get_owned_by(p_base->get_owner(), &owned);
Array owners;
for (Node *F : owned) {
owners.push_back(F);
@@ -496,12 +524,12 @@ void SceneTreeDock::_replace_with_branch_scene(const String &p_file, Node *base)
undo_redo->add_do_method(editor_selection, "clear");
undo_redo->add_undo_method(editor_selection, "clear");
undo_redo->add_do_method(editor_selection, "add_node", instantiated_scene);
undo_redo->add_undo_method(editor_selection, "add_node", base);
undo_redo->add_undo_method(editor_selection, "add_node", p_base);
undo_redo->add_do_property(scene_tree, "set_selected", instantiated_scene);
undo_redo->add_undo_property(scene_tree, "set_selected", base);
undo_redo->add_undo_property(scene_tree, "set_selected", p_base);
undo_redo->add_do_reference(instantiated_scene);
undo_redo->add_undo_reference(base);
undo_redo->add_undo_reference(p_base);
undo_redo->commit_action();
}
@@ -3228,7 +3256,7 @@ void SceneTreeDock::_replace_node(Node *p_node, Node *p_by_node, bool p_keep_pro
if (!(c.flags & Object::CONNECT_PERSIST)) {
continue;
}
newnode->connect(c.signal.get_name(), c.callable, Object::CONNECT_PERSIST);
newnode->connect(c.signal.get_name(), c.callable, c.flags);
}
}

View File

@@ -273,7 +273,7 @@ class SceneTreeDock : public VBoxContainer {
void _perform_instantiate_scenes(const Vector<String> &p_files, Node *p_parent, int p_pos);
void _perform_create_audio_stream_players(const Vector<String> &p_files, Node *p_parent, int p_pos);
void _replace_with_branch_scene(const String &p_file, Node *base);
void _replace_with_branch_scene(const String &p_file, Node *p_base);
void _remote_tree_selected();
void _local_tree_selected();