diff options
author | RedMser <redmser.jj2@gmail.com> | 2022-09-09 16:36:07 +0200 |
---|---|---|
committer | RedMser <redmser.jj2@gmail.com> | 2022-09-21 01:49:54 +0200 |
commit | a9b394d5bcd551d7ccb16cf19d6e40f675c9d07b (patch) | |
tree | 8a1403e9cc692864db93044a30c21af8f7036ca3 /editor/plugins | |
parent | 0a5cbca803b58d0bdf2b8d0cc1f348ca5de214b4 (diff) |
Show method override icon in script editor gutter
Combines with the connection slot icon when both apply.
Can be clicked to jump to the method declaration (or documentation for
built-in classes).
Diffstat (limited to 'editor/plugins')
-rw-r--r-- | editor/plugins/script_editor_plugin.cpp | 2 | ||||
-rw-r--r-- | editor/plugins/script_text_editor.cpp | 97 |
2 files changed, 88 insertions, 11 deletions
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 0a111aeb49..9386c17dd5 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -227,6 +227,7 @@ void ScriptEditorBase::_bind_methods() { // TODO: This signal is no use for VisualScript. ADD_SIGNAL(MethodInfo("search_in_files_requested", PropertyInfo(Variant::STRING, "text"))); ADD_SIGNAL(MethodInfo("replace_in_files_requested", PropertyInfo(Variant::STRING, "text"))); + ADD_SIGNAL(MethodInfo("go_to_method", PropertyInfo(Variant::OBJECT, "script"), PropertyInfo(Variant::STRING, "method"))); } class EditorScriptCodeCompletionCache : public ScriptCodeCompletionCache { @@ -2380,6 +2381,7 @@ bool ScriptEditor::edit(const Ref<Resource> &p_resource, int p_line, int p_col, se->connect("request_save_history", callable_mp(this, &ScriptEditor::_save_history)); se->connect("search_in_files_requested", callable_mp(this, &ScriptEditor::_on_find_in_files_requested)); se->connect("replace_in_files_requested", callable_mp(this, &ScriptEditor::_on_replace_in_files_requested)); + se->connect("go_to_method", callable_mp(this, &ScriptEditor::script_goto_method)); //test for modification, maybe the script was not edited but was loaded diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 42dcfb8b1f..a7a5e512f5 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -956,10 +956,7 @@ void ScriptTextEditor::_update_connected_methods() { CodeEdit *text_edit = code_editor->get_text_editor(); text_edit->set_gutter_width(connection_gutter, text_edit->get_line_height()); for (int i = 0; i < text_edit->get_line_count(); i++) { - if (text_edit->get_line_gutter_metadata(i, connection_gutter) == "") { - continue; - } - text_edit->set_line_gutter_metadata(i, connection_gutter, ""); + text_edit->set_line_gutter_metadata(i, connection_gutter, Dictionary()); text_edit->set_line_gutter_icon(i, connection_gutter, nullptr); text_edit->set_line_gutter_clickable(i, connection_gutter, false); } @@ -974,6 +971,7 @@ void ScriptTextEditor::_update_connected_methods() { return; } + // Add connection icons to methods. Vector<Node *> nodes = _find_all_node_for_script(base, base, script); HashSet<StringName> methods_found; for (int i = 0; i < nodes.size(); i++) { @@ -1002,8 +1000,11 @@ void ScriptTextEditor::_update_connected_methods() { for (int j = 0; j < functions.size(); j++) { String name = functions[j].get_slice(":", 0); if (name == method) { + Dictionary line_meta; + line_meta["type"] = "connection"; + line_meta["method"] = method; line = functions[j].get_slice(":", 1).to_int() - 1; - text_edit->set_line_gutter_metadata(line, connection_gutter, method); + text_edit->set_line_gutter_metadata(line, connection_gutter, line_meta); text_edit->set_line_gutter_icon(line, connection_gutter, get_parent_control()->get_theme_icon(SNAME("Slot"), SNAME("EditorIcons"))); text_edit->set_line_gutter_clickable(line, connection_gutter, true); methods_found.insert(method); @@ -1033,6 +1034,58 @@ void ScriptTextEditor::_update_connected_methods() { } } } + + // Add override icons to methods. + methods_found.clear(); + for (int i = 0; i < functions.size(); i++) { + StringName name = StringName(functions[i].get_slice(":", 0)); + if (methods_found.has(name)) { + continue; + } + + String found_base_class; + StringName base_class = script->get_instance_base_type(); + Ref<Script> inherited_script = script->get_base_script(); + while (!inherited_script.is_null()) { + if (inherited_script->has_method(name)) { + found_base_class = "script:" + inherited_script->get_path(); + break; + } + + base_class = inherited_script->get_instance_base_type(); + inherited_script = inherited_script->get_base_script(); + } + + if (found_base_class.is_empty() && base_class) { + List<MethodInfo> methods; + ClassDB::get_method_list(base_class, &methods); + for (int j = 0; j < methods.size(); j++) { + if (methods[j].name == name) { + found_base_class = "builtin:" + base_class; + break; + } + } + } + + if (!found_base_class.is_empty()) { + int line = functions[i].get_slice(":", 1).to_int() - 1; + + Dictionary line_meta = text_edit->get_line_gutter_metadata(line, connection_gutter); + if (line_meta.is_empty()) { + // Add override icon to gutter. + line_meta["type"] = "inherits"; + line_meta["method"] = name; + line_meta["base_class"] = found_base_class; + text_edit->set_line_gutter_icon(line, connection_gutter, get_parent_control()->get_theme_icon(SNAME("MethodOverride"), SNAME("EditorIcons"))); + text_edit->set_line_gutter_clickable(line, connection_gutter, true); + } else { + // If method is also connected to signal, then merge icons and keep the click behavior of the slot. + text_edit->set_line_gutter_icon(line, connection_gutter, get_parent_control()->get_theme_icon(SNAME("MethodOverrideAndSlot"), SNAME("EditorIcons"))); + } + + methods_found.insert(name); + } + } } void ScriptTextEditor::_update_gutter_indexes() { @@ -1054,18 +1107,40 @@ void ScriptTextEditor::_gutter_clicked(int p_line, int p_gutter) { return; } - String method = code_editor->get_text_editor()->get_line_gutter_metadata(p_line, p_gutter); - if (method.is_empty()) { + Dictionary meta = code_editor->get_text_editor()->get_line_gutter_metadata(p_line, p_gutter); + String type = meta.get("type", ""); + if (type.is_empty()) { return; } - Node *base = get_tree()->get_edited_scene_root(); - if (!base) { + // All types currently need a method name. + String method = meta.get("method", ""); + if (method.is_empty()) { return; } - Vector<Node *> nodes = _find_all_node_for_script(base, base, script); - connection_info_dialog->popup_connections(method, nodes); + if (type == "connection") { + Node *base = get_tree()->get_edited_scene_root(); + if (!base) { + return; + } + + Vector<Node *> nodes = _find_all_node_for_script(base, base, script); + connection_info_dialog->popup_connections(method, nodes); + } else if (type == "inherits") { + String base_class_raw = meta["base_class"]; + PackedStringArray base_class_split = base_class_raw.split(":", true, 1); + + if (base_class_split[0] == "script") { + // Go to function declaration. + Ref<Script> base_script = ResourceLoader::load(base_class_split[1]); + ERR_FAIL_COND(!base_script.is_valid()); + emit_signal(SNAME("go_to_method"), base_script, method); + } else if (base_class_split[0] == "builtin") { + // Open method documentation. + emit_signal(SNAME("go_to_help"), "class_method:" + base_class_split[1] + ":" + method); + } + } } void ScriptTextEditor::_edit_option(int p_op) { |