diff --git a/editor/docks/scene_tree_dock.cpp b/editor/docks/scene_tree_dock.cpp index 364492390a2..722501a9b87 100644 --- a/editor/docks/scene_tree_dock.cpp +++ b/editor/docks/scene_tree_dock.cpp @@ -439,9 +439,9 @@ void SceneTreeDock::_perform_create_audio_stream_players(const Vector &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 sdata = ResourceLoader::load(p_file); if (sdata.is_null()) { @@ -457,10 +457,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(instantiated_scene); - Node2D *base_2d = Object::cast_to(base); + Node2D *base_2d = Object::cast_to(p_base); if (copy_2d && base_2d) { copy_2d->set_position(base_2d->get_position()); copy_2d->set_rotation(base_2d->get_rotation()); @@ -468,27 +468,55 @@ void SceneTreeDock::_replace_with_branch_scene(const String &p_file, Node *base) } Node3D *copy_3d = Object::cast_to(instantiated_scene); - Node3D *base_3d = Object::cast_to(base); + Node3D *base_3d = Object::cast_to(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 signal_list; + p_base->get_signal_list(&signal_list); + for (const MethodInfo &meth : signal_list) { + List connection_list; + p_base->get_signal_connection_list(meth.name, &connection_list); + + List 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 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); @@ -499,12 +527,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(); } @@ -3242,7 +3270,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); } } diff --git a/editor/docks/scene_tree_dock.h b/editor/docks/scene_tree_dock.h index 36832b95dca..983b24e16b8 100644 --- a/editor/docks/scene_tree_dock.h +++ b/editor/docks/scene_tree_dock.h @@ -276,7 +276,7 @@ class SceneTreeDock : public EditorDock { void _perform_instantiate_scenes(const Vector &p_files, Node *p_parent, int p_pos); void _perform_create_audio_stream_players(const Vector &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();