diff --git a/core/debugger/engine_debugger.cpp b/core/debugger/engine_debugger.cpp index 9d364659aac..00e6d959b33 100644 --- a/core/debugger/engine_debugger.cpp +++ b/core/debugger/engine_debugger.cpp @@ -127,7 +127,7 @@ void EngineDebugger::iteration(uint64_t p_frame_ticks, uint64_t p_process_ticks, singleton->poll_events(true); } -void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, const Vector &p_breakpoints, void (*p_allow_focus_steal_fn)()) { +void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, bool p_ignore_error_breaks, const Vector &p_breakpoints, void (*p_allow_focus_steal_fn)()) { register_uri_handler("tcp://", RemoteDebuggerPeerTCP::create); // TCP is the default protocol. Platforms/modules can add more. if (p_uri.is_empty()) { return; @@ -160,6 +160,7 @@ void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, co // There is a debugger, parse breakpoints. ScriptDebugger *singleton_script_debugger = singleton->get_script_debugger(); singleton_script_debugger->set_skip_breakpoints(p_skip_breakpoints); + singleton_script_debugger->set_ignore_error_breaks(p_ignore_error_breaks); for (int i = 0; i < p_breakpoints.size(); i++) { const String &bp = p_breakpoints[i]; diff --git a/core/debugger/engine_debugger.h b/core/debugger/engine_debugger.h index 0be50451b07..cfe1b6e3e9d 100644 --- a/core/debugger/engine_debugger.h +++ b/core/debugger/engine_debugger.h @@ -106,7 +106,7 @@ public: _FORCE_INLINE_ static ScriptDebugger *get_script_debugger() { return script_debugger; } - static void initialize(const String &p_uri, bool p_skip_breakpoints, const Vector &p_breakpoints, void (*p_allow_focus_steal_fn)()); + static void initialize(const String &p_uri, bool p_skip_breakpoints, bool p_ignore_error_breaks, const Vector &p_breakpoints, void (*p_allow_focus_steal_fn)()); static void deinitialize(); static void register_profiler(const StringName &p_name, const Profiler &p_profiler); static void unregister_profiler(const StringName &p_name); diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp index 01b4d32a85b..0cc79e744a4 100644 --- a/core/debugger/remote_debugger.cpp +++ b/core/debugger/remote_debugger.cpp @@ -413,17 +413,24 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { } ScriptLanguage *script_lang = script_debugger->get_break_language(); - const String error_str = script_lang ? script_lang->debug_get_error() : ""; - Array msg; - msg.push_back(p_can_continue); - msg.push_back(error_str); ERR_FAIL_NULL(script_lang); - msg.push_back(script_lang->debug_get_stack_level_count() > 0); - msg.push_back(Thread::get_caller_id()); - if (allow_focus_steal_fn) { - allow_focus_steal_fn(); + const bool can_break = !(p_is_error_breakpoint && script_debugger->is_ignoring_error_breaks()); + const String error_str = script_lang ? script_lang->debug_get_error() : ""; + + if (can_break) { + Array msg; + msg.push_back(p_can_continue); + msg.push_back(error_str); + msg.push_back(script_lang->debug_get_stack_level_count() > 0); + msg.push_back(Thread::get_caller_id()); + if (allow_focus_steal_fn) { + allow_focus_steal_fn(); + } + send_message("debug_enter", msg); + } else { + ERR_PRINT(error_str); + return; } - send_message("debug_enter", msg); Input::MouseMode mouse_mode = Input::MOUSE_MODE_VISIBLE; @@ -530,6 +537,9 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { } else if (command == "set_skip_breakpoints") { ERR_FAIL_COND(data.is_empty()); script_debugger->set_skip_breakpoints(data[0]); + } else if (command == "set_ignore_error_breaks") { + ERR_FAIL_COND(data.size() < 1); + script_debugger->set_ignore_error_breaks(data[0]); } else if (command == "evaluate") { String expression_str = data[0]; int frame = data[1]; @@ -669,6 +679,9 @@ Error RemoteDebugger::_core_capture(const String &p_cmd, const Array &p_data, bo } else if (p_cmd == "set_skip_breakpoints") { ERR_FAIL_COND_V(p_data.is_empty(), ERR_INVALID_DATA); script_debugger->set_skip_breakpoints(p_data[0]); + } else if (p_cmd == "set_ignore_error_breaks") { + ERR_FAIL_COND_V(p_data.size() < 1, ERR_INVALID_DATA); + script_debugger->set_ignore_error_breaks(p_data[0]); } else if (p_cmd == "break") { script_debugger->debug(script_debugger->get_break_language()); } else { diff --git a/core/debugger/script_debugger.cpp b/core/debugger/script_debugger.cpp index e7d8654a0b9..1533a85b32a 100644 --- a/core/debugger/script_debugger.cpp +++ b/core/debugger/script_debugger.cpp @@ -79,6 +79,14 @@ bool ScriptDebugger::is_skipping_breakpoints() { return skip_breakpoints; } +void ScriptDebugger::set_ignore_error_breaks(bool p_ignore) { + ignore_error_breaks = p_ignore; +} + +bool ScriptDebugger::is_ignoring_error_breaks() { + return ignore_error_breaks; +} + void ScriptDebugger::debug(ScriptLanguage *p_lang, bool p_can_continue, bool p_is_error_breakpoint) { ScriptLanguage *prev = break_lang; break_lang = p_lang; diff --git a/core/debugger/script_debugger.h b/core/debugger/script_debugger.h index 38d1a5b631a..0a5ffe78e31 100644 --- a/core/debugger/script_debugger.h +++ b/core/debugger/script_debugger.h @@ -39,6 +39,7 @@ class ScriptDebugger { typedef ScriptLanguage::StackInfo StackInfo; bool skip_breakpoints = false; + bool ignore_error_breaks = false; HashMap> breakpoints; @@ -63,6 +64,8 @@ public: ScriptLanguage *get_break_language() { return break_lang; } void set_skip_breakpoints(bool p_skip_breakpoints); bool is_skipping_breakpoints(); + void set_ignore_error_breaks(bool p_ignore); + bool is_ignoring_error_breaks(); void insert_breakpoint(int p_line, const StringName &p_source); void remove_breakpoint(int p_line, const StringName &p_source); _ALWAYS_INLINE_ bool is_breakpoint(int p_line, const StringName &p_source) const { diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp index b08f0cfbf90..ea100a0eb26 100644 --- a/editor/debugger/editor_debugger_node.cpp +++ b/editor/debugger/editor_debugger_node.cpp @@ -615,6 +615,10 @@ bool EditorDebuggerNode::is_skip_breakpoints() const { return get_current_debugger()->is_skip_breakpoints(); } +bool EditorDebuggerNode::is_ignore_error_breaks() const { + return get_default_debugger()->is_ignore_error_breaks(); +} + void EditorDebuggerNode::set_breakpoint(const String &p_path, int p_line, bool p_enabled) { breakpoints[Breakpoint(p_path, p_line)] = p_enabled; _for_all(tabs, [&](ScriptEditorDebugger *dbg) { diff --git a/editor/debugger/editor_debugger_node.h b/editor/debugger/editor_debugger_node.h index f2738b66a93..80e9de3baeb 100644 --- a/editor/debugger/editor_debugger_node.h +++ b/editor/debugger/editor_debugger_node.h @@ -188,6 +188,7 @@ public: bool get_debug_with_external_editor() { return debug_with_external_editor; } bool is_skip_breakpoints() const; + bool is_ignore_error_breaks() const; void set_breakpoint(const String &p_path, int p_line, bool p_enabled); void set_breakpoints(const String &p_path, const Array &p_lines); void reload_all_scripts(); diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp index a4a4d7ad490..c54e00e10c8 100644 --- a/editor/debugger/script_editor_debugger.cpp +++ b/editor/debugger/script_editor_debugger.cpp @@ -102,6 +102,19 @@ void ScriptEditorDebugger::debug_skip_breakpoints() { _put_msg("set_skip_breakpoints", msg, debugging_thread_id != Thread::UNASSIGNED_ID ? debugging_thread_id : Thread::MAIN_ID); } +void ScriptEditorDebugger::debug_ignore_error_breaks() { + ignore_error_breaks_value = !ignore_error_breaks_value; + if (ignore_error_breaks_value) { + ignore_error_breaks->set_button_icon(get_theme_icon(SNAME("NotificationDisabled"), SNAME("EditorIcons"))); + } else { + ignore_error_breaks->set_button_icon(get_theme_icon(SNAME("Notification"), SNAME("EditorIcons"))); + } + + Array msg; + msg.push_back(ignore_error_breaks_value); + _put_msg("set_ignore_error_breaks", msg); +} + void ScriptEditorDebugger::debug_next() { ERR_FAIL_COND(!is_breaked()); @@ -916,6 +929,11 @@ void ScriptEditorDebugger::_notification(int p_what) { tabs->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SNAME("DebuggerPanel"), EditorStringName(EditorStyles))); skip_breakpoints->set_button_icon(get_editor_theme_icon(skip_breakpoints_value ? SNAME("DebugSkipBreakpointsOn") : SNAME("DebugSkipBreakpointsOff"))); + ignore_error_breaks->set_button_icon(get_editor_theme_icon(ignore_error_breaks_value ? SNAME("NotificationDisabled") : SNAME("Notification"))); + ignore_error_breaks->add_theme_color_override("icon_normal_color", get_theme_color(SNAME("error_color"), SNAME("Editor"))); + ignore_error_breaks->add_theme_color_override("icon_hover_color", get_theme_color(SNAME("error_color"), SNAME("Editor"))); + ignore_error_breaks->add_theme_color_override("icon_pressed_color", get_theme_color(SNAME("error_color"), SNAME("Editor"))); + ignore_error_breaks->add_theme_color_override("icon_focus_color", get_theme_color(SNAME("error_color"), SNAME("Editor"))); copy->set_button_icon(get_editor_theme_icon(SNAME("ActionCopy"))); step->set_button_icon(get_editor_theme_icon(SNAME("DebugStep"))); next->set_button_icon(get_editor_theme_icon(SNAME("DebugNext"))); @@ -1592,10 +1610,14 @@ void ScriptEditorDebugger::reload_scripts(const Vector &p_script_paths) _put_msg("reload_scripts", Variant(p_script_paths).operator Array(), debugging_thread_id != Thread::UNASSIGNED_ID ? debugging_thread_id : Thread::MAIN_ID); } -bool ScriptEditorDebugger::is_skip_breakpoints() { +bool ScriptEditorDebugger::is_skip_breakpoints() const { return skip_breakpoints_value; } +bool ScriptEditorDebugger::is_ignore_error_breaks() const { + return ignore_error_breaks_value; +} + void ScriptEditorDebugger::_error_activated() { TreeItem *selected = error_tree->get_selected(); @@ -1895,6 +1917,12 @@ ScriptEditorDebugger::ScriptEditorDebugger() { skip_breakpoints->set_tooltip_text(TTR("Skip Breakpoints")); skip_breakpoints->connect(SceneStringName(pressed), callable_mp(this, &ScriptEditorDebugger::debug_skip_breakpoints)); + ignore_error_breaks = memnew(Button); + ignore_error_breaks->set_flat(true); + ignore_error_breaks->set_tooltip_text(TTR("Ignore Error Breaks")); + hbc->add_child(ignore_error_breaks); + ignore_error_breaks->connect("pressed", callable_mp(this, &ScriptEditorDebugger::debug_ignore_error_breaks)); + hbc->add_child(memnew(VSeparator)); copy = memnew(Button); diff --git a/editor/debugger/script_editor_debugger.h b/editor/debugger/script_editor_debugger.h index 2ba4849683b..ba06171792a 100644 --- a/editor/debugger/script_editor_debugger.h +++ b/editor/debugger/script_editor_debugger.h @@ -113,6 +113,7 @@ private: int warning_count; bool skip_breakpoints_value = false; + bool ignore_error_breaks_value = false; Ref