Editor: Improve Signal Dock for script classes
* Add signal documentation for script classes. * Use separate sections for script class inheritance.
This commit is contained in:
parent
90f90cbcb0
commit
1d5539cf77
1 changed files with 85 additions and 55 deletions
|
@ -31,6 +31,7 @@
|
||||||
#include "connections_dialog.h"
|
#include "connections_dialog.h"
|
||||||
|
|
||||||
#include "core/config/project_settings.h"
|
#include "core/config/project_settings.h"
|
||||||
|
#include "core/templates/hash_set.h"
|
||||||
#include "editor/doc_tools.h"
|
#include "editor/doc_tools.h"
|
||||||
#include "editor/editor_help.h"
|
#include "editor/editor_help.h"
|
||||||
#include "editor/editor_inspector.h"
|
#include "editor/editor_inspector.h"
|
||||||
|
@ -1239,60 +1240,102 @@ void ConnectionsDock::update_tree() {
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeItem *root = tree->create_item();
|
TreeItem *root = tree->create_item();
|
||||||
|
DocTools *doc_data = EditorHelp::get_doc_data();
|
||||||
|
EditorData &editor_data = EditorNode::get_editor_data();
|
||||||
|
StringName native_base = selected_node->get_class();
|
||||||
|
Ref<Script> script_base = selected_node->get_script();
|
||||||
|
|
||||||
List<MethodInfo> node_signals;
|
while (native_base != StringName()) {
|
||||||
|
String class_name;
|
||||||
|
String doc_class_name;
|
||||||
|
Ref<Texture2D> class_icon;
|
||||||
|
List<MethodInfo> class_signals;
|
||||||
|
const DocData::ClassDoc *class_doc = nullptr;
|
||||||
|
|
||||||
selected_node->get_signal_list(&node_signals);
|
if (script_base.is_valid()) {
|
||||||
|
// Try script global name.
|
||||||
bool did_script = false;
|
class_name = script_base->get_global_name();
|
||||||
StringName base = selected_node->get_class();
|
if (!class_name.is_empty()) {
|
||||||
|
HashMap<String, DocData::ClassDoc>::ConstIterator F = doc_data->class_list.find(class_name);
|
||||||
while (base) {
|
if (F) {
|
||||||
List<MethodInfo> node_signals2;
|
class_doc = &F->value;
|
||||||
Ref<Texture2D> icon;
|
doc_class_name = class_name;
|
||||||
String name;
|
|
||||||
|
|
||||||
if (!did_script) {
|
|
||||||
// Get script signals (including signals from any base scripts).
|
|
||||||
Ref<Script> scr = selected_node->get_script();
|
|
||||||
if (scr.is_valid()) {
|
|
||||||
scr->get_script_signal_list(&node_signals2);
|
|
||||||
if (scr->get_path().is_resource_file()) {
|
|
||||||
name = scr->get_path().get_file();
|
|
||||||
} else {
|
|
||||||
name = scr->get_class();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_theme_icon(scr->get_class(), SNAME("EditorIcons"))) {
|
|
||||||
icon = get_theme_icon(scr->get_class(), SNAME("EditorIcons"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try script path.
|
||||||
|
if (class_name.is_empty()) {
|
||||||
|
class_name = script_base->get_path().get_file();
|
||||||
|
}
|
||||||
|
if (!class_doc) {
|
||||||
|
doc_class_name = script_base->get_path().trim_prefix("res://").quote();
|
||||||
|
HashMap<String, DocData::ClassDoc>::ConstIterator F = doc_data->class_list.find(doc_class_name);
|
||||||
|
if (F) {
|
||||||
|
class_doc = &F->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class_icon = editor_data.get_script_icon(script_base);
|
||||||
|
if (class_icon.is_null() && has_theme_icon(native_base, SNAME("EditorIcons"))) {
|
||||||
|
class_icon = get_theme_icon(native_base, SNAME("EditorIcons"));
|
||||||
|
}
|
||||||
|
|
||||||
|
script_base->get_script_signal_list(&class_signals);
|
||||||
|
|
||||||
|
// TODO: Core: Add optional parameter to ignore base classes (no_inheritance like in ClassDB).
|
||||||
|
Ref<Script> base = script_base->get_base_script();
|
||||||
|
if (base.is_valid()) {
|
||||||
|
List<MethodInfo> base_signals;
|
||||||
|
base->get_script_signal_list(&base_signals);
|
||||||
|
HashSet<String> base_signal_names;
|
||||||
|
for (List<MethodInfo>::Element *F = base_signals.front(); F; F = F->next()) {
|
||||||
|
base_signal_names.insert(F->get().name);
|
||||||
|
}
|
||||||
|
for (List<MethodInfo>::Element *F = class_signals.front(); F; F = F->next()) {
|
||||||
|
if (base_signal_names.has(F->get().name)) {
|
||||||
|
class_signals.erase(F);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
script_base = base;
|
||||||
} else {
|
} else {
|
||||||
ClassDB::get_signal_list(base, &node_signals2, true);
|
class_name = native_base;
|
||||||
if (has_theme_icon(base, SNAME("EditorIcons"))) {
|
|
||||||
icon = get_theme_icon(base, SNAME("EditorIcons"));
|
if (has_theme_icon(native_base, SNAME("EditorIcons"))) {
|
||||||
|
class_icon = get_theme_icon(native_base, SNAME("EditorIcons"));
|
||||||
}
|
}
|
||||||
name = base;
|
|
||||||
|
ClassDB::get_signal_list(native_base, &class_signals, true);
|
||||||
|
|
||||||
|
HashMap<String, DocData::ClassDoc>::ConstIterator F = doc_data->class_list.find(class_name);
|
||||||
|
if (F) {
|
||||||
|
class_doc = &F->value;
|
||||||
|
doc_class_name = class_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
native_base = ClassDB::get_parent_class(native_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (icon.is_null()) {
|
if (class_icon.is_null()) {
|
||||||
icon = get_theme_icon(SNAME("Object"), SNAME("EditorIcons"));
|
class_icon = get_theme_icon(SNAME("Object"), SNAME("EditorIcons"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeItem *section_item = nullptr;
|
TreeItem *section_item = nullptr;
|
||||||
|
|
||||||
// Create subsections.
|
// Create subsections.
|
||||||
if (node_signals2.size()) {
|
if (!class_signals.is_empty()) {
|
||||||
|
class_signals.sort();
|
||||||
|
|
||||||
section_item = tree->create_item(root);
|
section_item = tree->create_item(root);
|
||||||
section_item->set_text(0, name);
|
section_item->set_text(0, class_name);
|
||||||
section_item->set_icon(0, icon);
|
section_item->set_icon(0, class_icon);
|
||||||
section_item->set_selectable(0, false);
|
section_item->set_selectable(0, false);
|
||||||
section_item->set_editable(0, false);
|
section_item->set_editable(0, false);
|
||||||
section_item->set_custom_bg_color(0, get_theme_color(SNAME("prop_subsection"), SNAME("Editor")));
|
section_item->set_custom_bg_color(0, get_theme_color(SNAME("prop_subsection"), SNAME("Editor")));
|
||||||
node_signals2.sort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (MethodInfo &mi : node_signals2) {
|
for (MethodInfo &mi : class_signals) {
|
||||||
const StringName signal_name = mi.name;
|
const StringName signal_name = mi.name;
|
||||||
if (!search_box->get_text().is_subsequence_ofn(signal_name)) {
|
if (!search_box->get_text().is_subsequence_ofn(signal_name)) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -1320,9 +1363,9 @@ void ConnectionsDock::update_tree() {
|
||||||
String descr;
|
String descr;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
HashMap<StringName, HashMap<StringName, String>>::Iterator G = descr_cache.find(base);
|
HashMap<StringName, HashMap<StringName, String>>::ConstIterator G = descr_cache.find(doc_class_name);
|
||||||
if (G) {
|
if (G) {
|
||||||
HashMap<StringName, String>::Iterator F = G->value.find(signal_name);
|
HashMap<StringName, String>::ConstIterator F = G->value.find(signal_name);
|
||||||
if (F) {
|
if (F) {
|
||||||
found = true;
|
found = true;
|
||||||
descr = F->value;
|
descr = F->value;
|
||||||
|
@ -1330,22 +1373,15 @@ void ConnectionsDock::update_tree() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
DocTools *dd = EditorHelp::get_doc_data();
|
if (class_doc) {
|
||||||
HashMap<String, DocData::ClassDoc>::Iterator F = dd->class_list.find(base);
|
for (int i = 0; i < class_doc->signals.size(); i++) {
|
||||||
while (F && descr.is_empty()) {
|
if (class_doc->signals[i].name == signal_name.operator String()) {
|
||||||
for (int i = 0; i < F->value.signals.size(); i++) {
|
descr = DTR(class_doc->signals[i].description);
|
||||||
if (F->value.signals[i].name == signal_name.operator String()) {
|
|
||||||
descr = DTR(F->value.signals[i].description);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!F->value.inherits.is_empty()) {
|
|
||||||
F = dd->class_list.find(F->value.inherits);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
descr_cache[base][signal_name] = descr;
|
descr_cache[doc_class_name][signal_name] = descr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// "::" separators used in make_custom_tooltip for formatting.
|
// "::" separators used in make_custom_tooltip for formatting.
|
||||||
|
@ -1400,12 +1436,6 @@ void ConnectionsDock::update_tree() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!did_script) {
|
|
||||||
did_script = true;
|
|
||||||
} else {
|
|
||||||
base = ClassDB::get_parent_class(base);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
connect_button->set_text(TTR("Connect..."));
|
connect_button->set_text(TTR("Connect..."));
|
||||||
|
|
Loading…
Reference in a new issue