From d04abf6e56cd756b2e9d48afffb02e071f02f00b Mon Sep 17 00:00:00 2001 From: Wilson Kazuo Mizutani Date: Sun, 20 Jul 2025 00:10:25 -0300 Subject: [PATCH] Fix crash from selected nodes when closing scene Fixes #108783 In a recent change, the `SceneTreedock` node started keeping track of selected nodes so it could disconnect some signals from them whenever the selection changed. However, when a scene is closed, its nodes are deleted before the selection change can complete, causing invalid access to dangling pointers. To fix it, the editor now explicitly tells the scene tree dock to clean after itself when the currently edited scene is closing. Rationale for implementation decisions: 1. I added and called a method on `SceneTreeDock` (as opposed to using a signal) because `EditorNode` already calls many methods directly on the dock. 2. I call the new method on `EditorNode::_remove_edited_scene()` since it seems to be the most specific to the situation at hand. Simply closing any scene does not cause the problem, since tracked nodes come from the selection, which applies only to the currently edited scene. --- editor/docks/scene_tree_dock.cpp | 4 ++++ editor/docks/scene_tree_dock.h | 1 + editor/editor_node.cpp | 1 + 3 files changed, 6 insertions(+) diff --git a/editor/docks/scene_tree_dock.cpp b/editor/docks/scene_tree_dock.cpp index 6e3a174ef7ba..b48f6e68bd0b 100644 --- a/editor/docks/scene_tree_dock.cpp +++ b/editor/docks/scene_tree_dock.cpp @@ -3361,6 +3361,10 @@ void SceneTreeDock::set_edited_scene(Node *p_scene) { edited_scene = p_scene; } +void SceneTreeDock::close_edited_scene() { + node_previous_selection.clear(); +} + static bool _is_same_selection(const Vector &p_first, const List &p_second) { if (p_first.size() != p_second.size()) { return false; diff --git a/editor/docks/scene_tree_dock.h b/editor/docks/scene_tree_dock.h index aa1002420c73..d9c6f4f00e7b 100644 --- a/editor/docks/scene_tree_dock.h +++ b/editor/docks/scene_tree_dock.h @@ -322,6 +322,7 @@ class SceneTreeDock : public VBoxContainer { void add_root_node(Node *p_node); void set_edited_scene(Node *p_scene); + void close_edited_scene(); void instantiate(const String &p_file); void instantiate_scenes(const Vector &p_files, Node *p_parent = nullptr); void set_selection(const Vector &p_nodes); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index a0a629cd2ff9..ff6196498b0e 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -4100,6 +4100,7 @@ void EditorNode::_remove_edited_scene(bool p_change_tab) { if (p_change_tab) { _set_current_scene(new_index); } + SceneTreeDock::get_singleton()->close_edited_scene(); editor_data.remove_scene(old_index); _update_title(); scene_tabs->update_scene_tabs();