mirror of
https://github.com/godotengine/godot
synced 2024-09-05 18:19:34 +00:00
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).
This commit is contained in:
parent
0a5cbca803
commit
a9b394d5bc
|
@ -35,6 +35,13 @@
|
|||
Emitted when the user requests a specific documentation page.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="go_to_method">
|
||||
<param index="0" name="script" type="Object" />
|
||||
<param index="1" name="method" type="String" />
|
||||
<description>
|
||||
Emitted when the user requests to view a specific method of a script, similar to [signal request_open_script_at_line].
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="name_changed">
|
||||
<description>
|
||||
Emitted after script validation or when the edited resource has changed.
|
||||
|
@ -56,7 +63,7 @@
|
|||
<param index="0" name="script" type="Object" />
|
||||
<param index="1" name="line" type="int" />
|
||||
<description>
|
||||
Emitted when the user requests a script.
|
||||
Emitted when the user requests to view a specific line of a script, similar to [signal go_to_method].
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="request_save_history">
|
||||
|
|
1
editor/icons/MethodOverride.svg
Normal file
1
editor/icons/MethodOverride.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg height="16" viewBox="0 0 4.2333332 4.2333332" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m.49005985 3.3580432.83285685-.0000001v-.7093212c.0027125-.6681099.2054076-1.1321001 1.0021593-1.1328214h.3207573v-.79375l1.3229167 1.0648649-1.3229167 1.0518017v-.79375h-.3364788c-.2888876 0-.4514151.2436282-.4573001.5980603 0 .2833012.0000193.4455045.0000289.7134508h.79375v.4907171l-2.15577345.00147z" fill="#5fb2ff"/></svg>
|
After Width: | Height: | Size: 434 B |
1
editor/icons/MethodOverrideAndSlot.svg
Normal file
1
editor/icons/MethodOverrideAndSlot.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg height="16" viewBox="0 0 4.2333332 4.2333332" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m.15761184 3.636193h.37155483l.004252-.7093212c.0027092-.6681099.12999225-1.1321001.92674393-1.1328214h.1273374l.0042585-.7357171 1.3186582 1.006832-1.3229167 1.0700676v-.8531081h-.1260545c-.2888876 0-.3972562.2847204-.4031411.6391525 0 .2833012.0000193.4455045.0000289.7134508h1.2412654v.4907171h-2.14198686z" fill="#5fb2ff"/><path d="m2.38125.79375h1.5875v2.6458333h-1.5875v-.5291666h1.0583333v-1.5875h-1.0583333z" fill="#5fff97"/></svg>
|
After Width: | Height: | Size: 546 B |
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
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;
|
||||
}
|
||||
|
||||
// All types currently need a method name.
|
||||
String method = meta.get("method", "");
|
||||
if (method.is_empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Node *base = get_tree()->get_edited_scene_root();
|
||||
if (!base) {
|
||||
return;
|
||||
}
|
||||
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);
|
||||
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) {
|
||||
|
|
Loading…
Reference in a new issue