|
@@ -31,6 +31,7 @@
|
|
|
#include "connections_dialog.h"
|
|
|
|
|
|
#include "core/config/project_settings.h"
|
|
|
+#include "core/templates/hash_set.h"
|
|
|
#include "editor/doc_tools.h"
|
|
|
#include "editor/editor_help.h"
|
|
|
#include "editor/editor_inspector.h"
|
|
@@ -1239,60 +1240,102 @@ void ConnectionsDock::update_tree() {
|
|
|
}
|
|
|
|
|
|
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();
|
|
|
+
|
|
|
+ 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;
|
|
|
+
|
|
|
+ if (script_base.is_valid()) {
|
|
|
+ // Try script global name.
|
|
|
+ class_name = script_base->get_global_name();
|
|
|
+ if (!class_name.is_empty()) {
|
|
|
+ HashMap<String, DocData::ClassDoc>::ConstIterator F = doc_data->class_list.find(class_name);
|
|
|
+ if (F) {
|
|
|
+ class_doc = &F->value;
|
|
|
+ doc_class_name = class_name;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- List<MethodInfo> node_signals;
|
|
|
-
|
|
|
- selected_node->get_signal_list(&node_signals);
|
|
|
+ // 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- bool did_script = false;
|
|
|
- StringName base = selected_node->get_class();
|
|
|
+ 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"));
|
|
|
+ }
|
|
|
|
|
|
- while (base) {
|
|
|
- List<MethodInfo> node_signals2;
|
|
|
- Ref<Texture2D> icon;
|
|
|
- String name;
|
|
|
+ script_base->get_script_signal_list(&class_signals);
|
|
|
|
|
|
- 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();
|
|
|
+ // 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);
|
|
|
}
|
|
|
-
|
|
|
- if (has_theme_icon(scr->get_class(), SNAME("EditorIcons"))) {
|
|
|
- icon = get_theme_icon(scr->get_class(), SNAME("EditorIcons"));
|
|
|
+ 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 {
|
|
|
- ClassDB::get_signal_list(base, &node_signals2, true);
|
|
|
- if (has_theme_icon(base, SNAME("EditorIcons"))) {
|
|
|
- icon = get_theme_icon(base, SNAME("EditorIcons"));
|
|
|
+ class_name = native_base;
|
|
|
+
|
|
|
+ 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()) {
|
|
|
- icon = get_theme_icon(SNAME("Object"), SNAME("EditorIcons"));
|
|
|
+ if (class_icon.is_null()) {
|
|
|
+ class_icon = get_theme_icon(SNAME("Object"), SNAME("EditorIcons"));
|
|
|
}
|
|
|
|
|
|
TreeItem *section_item = nullptr;
|
|
|
|
|
|
// Create subsections.
|
|
|
- if (node_signals2.size()) {
|
|
|
+ if (!class_signals.is_empty()) {
|
|
|
+ class_signals.sort();
|
|
|
+
|
|
|
section_item = tree->create_item(root);
|
|
|
- section_item->set_text(0, name);
|
|
|
- section_item->set_icon(0, icon);
|
|
|
+ section_item->set_text(0, class_name);
|
|
|
+ section_item->set_icon(0, class_icon);
|
|
|
section_item->set_selectable(0, false);
|
|
|
section_item->set_editable(0, false);
|
|
|
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;
|
|
|
if (!search_box->get_text().is_subsequence_ofn(signal_name)) {
|
|
|
continue;
|
|
@@ -1320,9 +1363,9 @@ void ConnectionsDock::update_tree() {
|
|
|
String descr;
|
|
|
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) {
|
|
|
- HashMap<StringName, String>::Iterator F = G->value.find(signal_name);
|
|
|
+ HashMap<StringName, String>::ConstIterator F = G->value.find(signal_name);
|
|
|
if (F) {
|
|
|
found = true;
|
|
|
descr = F->value;
|
|
@@ -1330,22 +1373,15 @@ void ConnectionsDock::update_tree() {
|
|
|
}
|
|
|
|
|
|
if (!found) {
|
|
|
- DocTools *dd = EditorHelp::get_doc_data();
|
|
|
- HashMap<String, DocData::ClassDoc>::Iterator F = dd->class_list.find(base);
|
|
|
- while (F && descr.is_empty()) {
|
|
|
- for (int i = 0; i < F->value.signals.size(); i++) {
|
|
|
- if (F->value.signals[i].name == signal_name.operator String()) {
|
|
|
- descr = DTR(F->value.signals[i].description);
|
|
|
+ if (class_doc) {
|
|
|
+ for (int i = 0; i < class_doc->signals.size(); i++) {
|
|
|
+ if (class_doc->signals[i].name == signal_name.operator String()) {
|
|
|
+ descr = DTR(class_doc->signals[i].description);
|
|
|
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.
|
|
@@ -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..."));
|