From 330a19f36292436c6321baf9bba357d78c007a25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pa=CC=84vels=20Nadtoc=CC=8Cajevs?= <7645683+bruvzg@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:43:02 +0200 Subject: [PATCH] [Editor HelpBit] Open online documentation if script editor is not available. --- editor/doc/editor_help.cpp | 58 ++++++++++++++++++++++++++++++++++++-- editor/doc/editor_help.h | 1 + 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/editor/doc/editor_help.cpp b/editor/doc/editor_help.cpp index f7716cdf649..ee6f8c033c3 100644 --- a/editor/doc/editor_help.cpp +++ b/editor/doc/editor_help.cpp @@ -4218,9 +4218,63 @@ void EditorHelpBit::_update_labels() { } } +void EditorHelpBit::_go_to_url(const String &p_what) { + Vector parts; + { + int from = 0; + int buffer_start = 0; + while (true) { + const int pos = p_what.find_char(':', from); + if (pos < 0) { + parts.push_back(p_what.substr(buffer_start)); + break; + } + + if (pos + 1 < p_what.length() && p_what[pos + 1] == ':') { + // `::` used in built-in scripts. + from = pos + 2; + } else { + parts.push_back(p_what.substr(buffer_start, pos - buffer_start)); + from = pos + 1; + buffer_start = from; + } + } + } + + const String what = parts[0]; // `parts` is always non-empty. + const String clss = (parts.size() > 1) ? parts[1].to_lower() : String(); + const String name = (parts.size() > 2) ? parts[2].to_lower().replace_chars("/_", '-') : String(); + + String section = ""; + if (what == "class_desc") { + section = "#description"; + } else if (what == "class_signal") { + section = vformat("#class-%s-signal-%s", clss, name); + } else if (what == "class_method" || what == "class_method_desc") { + section = vformat("#class-%s-method-%s", clss, name); + } else if (what == "class_property") { + section = vformat("#class-%s-property-%s", clss, name); + } else if (what == "class_enum") { + section = vformat("#enum-%s-%s", clss, name); + } else if (what == "class_theme_item") { + section = vformat("#class-%s-theme-%s", clss, name); + } else if (what == "class_constant") { + section = vformat("#class-%s-constant-%s", clss, name); + } else if (what == "class_annotation") { + section = vformat("#%s", clss); + } + + String doc_url = clss.is_empty() ? String(GODOT_VERSION_DOCS_URL "/") : vformat(GODOT_VERSION_DOCS_URL "/classes/class_%s.html%s", clss, section); + OS::get_singleton()->shell_open(doc_url); +} + void EditorHelpBit::_go_to_help(const String &p_what) { - EditorNode::get_singleton()->get_editor_main_screen()->select(EditorMainScreen::EDITOR_SCRIPT); - ScriptEditor::get_singleton()->goto_help(p_what); + if (ScriptEditor::get_singleton()) { + EditorNode::get_singleton()->get_editor_main_screen()->select(EditorMainScreen::EDITOR_SCRIPT); + ScriptEditor::get_singleton()->goto_help(p_what); + } else { + _go_to_url(p_what); + } emit_signal(SNAME("request_hide")); } diff --git a/editor/doc/editor_help.h b/editor/doc/editor_help.h index 9ee4cf23be7..8eff4469efe 100644 --- a/editor/doc/editor_help.h +++ b/editor/doc/editor_help.h @@ -344,6 +344,7 @@ class EditorHelpBit : public VBoxContainer { void _add_type_to_title(const DocType &p_doc_type); void _update_labels(); void _go_to_help(const String &p_what); + void _go_to_url(const String &p_what); void _meta_clicked(const String &p_select); protected: