From 3defc176464afa6113335da79d1fc70db19fb07c Mon Sep 17 00:00:00 2001 From: Saracen Date: Thu, 5 Oct 2023 17:45:27 +0100 Subject: [PATCH] Fix debugger behaviour with multi-session debugging: Fixes script editor debug menu on sessions other than 1 Fixes breakpoint toggle from menu in sessions other than 1 Removes execution display when switching to non-breaked sessions --- editor/debugger/editor_debugger_node.cpp | 63 +++++++++++++++++++++--- editor/debugger/editor_debugger_node.h | 5 ++ editor/plugins/script_editor_plugin.cpp | 4 +- 3 files changed, 64 insertions(+), 8 deletions(-) diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp index a327fd778bf38..8229abb5a027e 100644 --- a/editor/debugger/editor_debugger_node.cpp +++ b/editor/debugger/editor_debugger_node.cpp @@ -107,6 +107,8 @@ ScriptEditorDebugger *EditorDebuggerNode::_add_debugger() { node->connect("remote_object_updated", callable_mp(this, &EditorDebuggerNode::_remote_object_updated).bind(id)); node->connect("remote_object_property_updated", callable_mp(this, &EditorDebuggerNode::_remote_object_property_updated).bind(id)); node->connect("remote_object_requested", callable_mp(this, &EditorDebuggerNode::_remote_object_requested).bind(id)); + node->connect("set_breakpoint", callable_mp(this, &EditorDebuggerNode::_breakpoint_set_in_tree).bind(id)); + node->connect("clear_breakpoints", callable_mp(this, &EditorDebuggerNode::_breakpoints_cleared_in_tree).bind(id)); node->connect("errors_cleared", callable_mp(this, &EditorDebuggerNode::_update_errors)); if (tabs->get_tab_count() > 0) { @@ -168,6 +170,27 @@ void EditorDebuggerNode::_text_editor_stack_goto(const ScriptEditorDebugger *p_d stack_script.unref(); // Why?!? } +void EditorDebuggerNode::_text_editor_stack_clear(const ScriptEditorDebugger *p_debugger) { + String file = p_debugger->get_stack_script_file(); + if (file.is_empty()) { + return; + } + if (file.is_resource_file()) { + stack_script = ResourceLoader::load(file); + } else { + // If the script is built-in, it can be opened only if the scene is loaded in memory. + int i = file.find("::"); + int j = file.rfind("(", i); + if (j > -1) { // If the script is named, the string is "name (file)", so we need to extract the path. + file = file.substr(j + 1, file.find(")", i) - j - 1); + } + Ref ps = ResourceLoader::load(file.get_slice("::", 0)); + stack_script = ResourceLoader::load(file); + } + emit_signal(SNAME("clear_execution"), stack_script); + stack_script.unref(); // Why?!? +} + void EditorDebuggerNode::_bind_methods() { // LiveDebug. ClassDB::bind_method("live_debug_create_node", &EditorDebuggerNode::live_debug_create_node); @@ -183,6 +206,8 @@ void EditorDebuggerNode::_bind_methods() { ADD_SIGNAL(MethodInfo("clear_execution", PropertyInfo("script"))); ADD_SIGNAL(MethodInfo("breaked", PropertyInfo(Variant::BOOL, "reallydid"), PropertyInfo(Variant::BOOL, "can_debug"))); ADD_SIGNAL(MethodInfo("breakpoint_toggled", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "line"), PropertyInfo(Variant::BOOL, "enabled"))); + ADD_SIGNAL(MethodInfo("breakpoint_set_in_tree", PropertyInfo("script"), PropertyInfo(Variant::INT, "line"), PropertyInfo(Variant::BOOL, "enabled"), PropertyInfo(Variant::INT, "debugger"))); + ADD_SIGNAL(MethodInfo("breakpoints_cleared_in_tree", PropertyInfo(Variant::INT, "debugger"))); } void EditorDebuggerNode::register_undo_redo(UndoRedo *p_undo_redo) { @@ -198,6 +223,10 @@ ScriptEditorDebugger *EditorDebuggerNode::get_debugger(int p_id) const { return Object::cast_to(tabs->get_tab_control(p_id)); } +ScriptEditorDebugger *EditorDebuggerNode::get_previous_debugger() const { + return Object::cast_to(tabs->get_tab_control(tabs->get_previous_tab())); +} + ScriptEditorDebugger *EditorDebuggerNode::get_current_debugger() const { return Object::cast_to(tabs->get_tab_control(tabs->get_current_tab())); } @@ -436,12 +465,18 @@ void EditorDebuggerNode::_debugger_changed(int p_tab) { // Hopefully, in the future, we will have one inspector per debugger. EditorNode::get_singleton()->push_item(nullptr); } + + if (get_previous_debugger()) { + _text_editor_stack_clear(get_previous_debugger()); + } if (remote_scene_tree->is_visible_in_tree()) { get_current_debugger()->request_remote_tree(); } if (get_current_debugger()->is_breaked()) { _text_editor_stack_goto(get_current_debugger()); } + + _break_state_changed(); } void EditorDebuggerNode::set_script_debug_button(MenuButton *p_button) { @@ -533,7 +568,7 @@ void EditorDebuggerNode::_breaked(bool p_breaked, bool p_can_debug, String p_mes } bool EditorDebuggerNode::is_skip_breakpoints() const { - return get_default_debugger()->is_skip_breakpoints(); + return get_current_debugger()->is_skip_breakpoints(); } void EditorDebuggerNode::set_breakpoint(const String &p_path, int p_line, bool p_enabled) { @@ -565,23 +600,23 @@ void EditorDebuggerNode::reload_scripts() { } void EditorDebuggerNode::debug_next() { - get_default_debugger()->debug_next(); + get_current_debugger()->debug_next(); } void EditorDebuggerNode::debug_step() { - get_default_debugger()->debug_step(); + get_current_debugger()->debug_step(); } void EditorDebuggerNode::debug_break() { - get_default_debugger()->debug_break(); + get_current_debugger()->debug_break(); } void EditorDebuggerNode::debug_continue() { - get_default_debugger()->debug_continue(); + get_current_debugger()->debug_continue(); } String EditorDebuggerNode::get_var_value(const String &p_var) const { - return get_default_debugger()->get_var_value(p_var); + return get_current_debugger()->get_var_value(p_var); } // LiveEdit/Inspector @@ -655,6 +690,22 @@ void EditorDebuggerNode::_save_node_requested(ObjectID p_id, const String &p_fil get_current_debugger()->save_node(p_id, p_file); } +void EditorDebuggerNode::_breakpoint_set_in_tree(Ref p_script, int p_line, bool p_enabled, int p_debugger) { + if (p_debugger != tabs->get_current_tab()) { + return; + } + + emit_signal(SNAME("breakpoint_set_in_tree"), p_script, p_line, p_enabled); +} + +void EditorDebuggerNode::_breakpoints_cleared_in_tree(int p_debugger) { + if (p_debugger != tabs->get_current_tab()) { + return; + } + + emit_signal(SNAME("breakpoints_cleared_in_tree")); +} + // Remote inspector/edit. void EditorDebuggerNode::_method_changeds(void *p_ud, Object *p_base, const StringName &p_name, const Variant **p_args, int p_argcount) { if (!singleton) { diff --git a/editor/debugger/editor_debugger_node.h b/editor/debugger/editor_debugger_node.h index 8ca709dd9b2e0..4338f144b879f 100644 --- a/editor/debugger/editor_debugger_node.h +++ b/editor/debugger/editor_debugger_node.h @@ -138,11 +138,15 @@ class EditorDebuggerNode : public MarginContainer { void _remote_object_requested(ObjectID p_id, int p_debugger); void _save_node_requested(ObjectID p_id, const String &p_file, int p_debugger); + void _breakpoint_set_in_tree(Ref p_script, int p_line, bool p_enabled, int p_debugger); + void _breakpoints_cleared_in_tree(int p_debugger); + void _clear_execution(Ref p_script) { emit_signal(SNAME("clear_execution"), p_script); } void _text_editor_stack_goto(const ScriptEditorDebugger *p_debugger); + void _text_editor_stack_clear(const ScriptEditorDebugger *p_debugger); void _stack_frame_selected(int p_debugger); void _error_selected(const String &p_file, int p_line, int p_debugger); void _breaked(bool p_breaked, bool p_can_debug, String p_message, bool p_has_stackdump, int p_debugger); @@ -159,6 +163,7 @@ class EditorDebuggerNode : public MarginContainer { static EditorDebuggerNode *get_singleton() { return singleton; } void register_undo_redo(UndoRedo *p_undo_redo); + ScriptEditorDebugger *get_previous_debugger() const; ScriptEditorDebugger *get_current_debugger() const; ScriptEditorDebugger *get_default_debugger() const; ScriptEditorDebugger *get_debugger(int p_debugger) const; diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 901ac91a468d9..776d558d35655 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -4009,8 +4009,8 @@ ScriptEditor::ScriptEditor(WindowWrapper *p_wrapper) { debugger->connect("set_execution", callable_mp(this, &ScriptEditor::_set_execution)); debugger->connect("clear_execution", callable_mp(this, &ScriptEditor::_clear_execution)); debugger->connect("breaked", callable_mp(this, &ScriptEditor::_breaked)); - debugger->get_default_debugger()->connect("set_breakpoint", callable_mp(this, &ScriptEditor::_set_breakpoint)); - debugger->get_default_debugger()->connect("clear_breakpoints", callable_mp(this, &ScriptEditor::_clear_breakpoints)); + debugger->connect("breakpoint_set_in_tree", callable_mp(this, &ScriptEditor::_set_breakpoint)); + debugger->connect("breakpoints_cleared_in_tree", callable_mp(this, &ScriptEditor::_clear_breakpoints)); menu_hb->add_spacer();