Merge pull request #86447 from Maran23/performance-create-new-dialog

Improve performance of the 'Create New Node' dialog
This commit is contained in:
Rémi Verschelde 2024-05-15 22:41:45 +02:00
commit 2749645d2a
No known key found for this signature in database
GPG Key ID: C3336907360768E1
3 changed files with 49 additions and 70 deletions

View File

@ -85,7 +85,7 @@ void CreateDialog::_fill_type_list() {
EditorData &ed = EditorNode::get_editor_data(); EditorData &ed = EditorNode::get_editor_data();
for (List<StringName>::Element *I = complete_type_list.front(); I; I = I->next()) { for (List<StringName>::Element *I = complete_type_list.front(); I; I = I->next()) {
String type = I->get(); StringName type = I->get();
if (!_should_hide_type(type)) { if (!_should_hide_type(type)) {
type_list.push_back(type); type_list.push_back(type);
@ -118,12 +118,12 @@ bool CreateDialog::_is_class_disabled_by_feature_profile(const StringName &p_cla
return !profile.is_null() && profile->is_class_disabled(p_class); return !profile.is_null() && profile->is_class_disabled(p_class);
} }
bool CreateDialog::_should_hide_type(const String &p_type) const { bool CreateDialog::_should_hide_type(const StringName &p_type) const {
if (_is_class_disabled_by_feature_profile(p_type)) { if (_is_class_disabled_by_feature_profile(p_type)) {
return true; return true;
} }
if (is_base_type_node && p_type.begins_with("Editor")) { if (is_base_type_node && p_type.operator String().begins_with("Editor")) {
return true; // Do not show editor nodes. return true; // Do not show editor nodes.
} }
@ -146,12 +146,12 @@ bool CreateDialog::_should_hide_type(const String &p_type) const {
} }
} }
} else { } else {
if (!EditorNode::get_editor_data().script_class_is_parent(p_type, base_type)) {
return true; // Wrong inheritance.
}
if (!ScriptServer::is_global_class(p_type)) { if (!ScriptServer::is_global_class(p_type)) {
return true; return true;
} }
if (!EditorNode::get_editor_data().script_class_is_parent(p_type, base_type)) {
return true; // Wrong inheritance.
}
StringName native_type = ScriptServer::get_global_class_native_base(p_type); StringName native_type = ScriptServer::get_global_class_native_base(p_type);
if (ClassDB::class_exists(native_type) && !ClassDB::can_instantiate(native_type)) { if (ClassDB::class_exists(native_type) && !ClassDB::can_instantiate(native_type)) {
@ -182,24 +182,30 @@ void CreateDialog::_update_search() {
const String search_text = search_box->get_text(); const String search_text = search_box->get_text();
bool empty_search = search_text.is_empty(); bool empty_search = search_text.is_empty();
// Filter all candidate results. float highest_score = 0.0f;
Vector<String> candidates; StringName best_match;
for (List<StringName>::Element *I = type_list.front(); I; I = I->next()) {
if (empty_search || search_text.is_subsequence_ofn(I->get())) {
candidates.push_back(I->get());
}
}
// Build the type tree. for (List<StringName>::Element *I = type_list.front(); I; I = I->next()) {
for (int i = 0; i < candidates.size(); i++) { StringName candidate = I->get();
_add_type(candidates[i], ClassDB::class_exists(candidates[i]) ? TypeCategory::CPP_TYPE : TypeCategory::OTHER_TYPE); if (empty_search || search_text.is_subsequence_ofn(candidate)) {
_add_type(candidate, ClassDB::class_exists(candidate) ? TypeCategory::CPP_TYPE : TypeCategory::OTHER_TYPE);
// Determine the best match for an non-empty search.
if (!empty_search) {
float score = _score_type(candidate.operator String().get_slicec(' ', 0), search_text);
if (score > highest_score) {
highest_score = score;
best_match = candidate;
}
}
}
} }
// Select the best result. // Select the best result.
if (empty_search) { if (empty_search) {
select_type(base_type); select_type(base_type);
} else if (candidates.size() > 0) { } else if (best_match != StringName()) {
select_type(_top_result(candidates, search_text)); select_type(best_match);
} else { } else {
favorite->set_disabled(true); favorite->set_disabled(true);
help_bit->set_custom_text(String(), String(), vformat(TTR("No results for \"%s\"."), search_text.replace("[", "[lb]"))); help_bit->set_custom_text(String(), String(), vformat(TTR("No results for \"%s\"."), search_text.replace("[", "[lb]")));
@ -208,52 +214,43 @@ void CreateDialog::_update_search() {
} }
} }
void CreateDialog::_add_type(const String &p_type, const TypeCategory p_type_category) { void CreateDialog::_add_type(const StringName &p_type, TypeCategory p_type_category) {
if (search_options_types.has(p_type)) { if (search_options_types.has(p_type)) {
return; return;
} }
String inherits;
TypeCategory inherited_type = TypeCategory::OTHER_TYPE; TypeCategory inherited_type = TypeCategory::OTHER_TYPE;
StringName inherits;
if (p_type_category == TypeCategory::CPP_TYPE) { if (p_type_category == TypeCategory::CPP_TYPE) {
inherits = ClassDB::get_parent_class(p_type); inherits = ClassDB::get_parent_class(p_type);
inherited_type = TypeCategory::CPP_TYPE; inherited_type = TypeCategory::CPP_TYPE;
} else if (p_type_category == TypeCategory::PATH_TYPE) {
ERR_FAIL_COND(!ResourceLoader::exists(p_type, "Script"));
Ref<Script> scr = ResourceLoader::load(p_type, "Script");
ERR_FAIL_COND(scr.is_null());
Ref<Script> base = scr->get_base_script();
if (base.is_null()) {
String extends;
scr->get_language()->get_global_class_name(scr->get_path(), &extends);
inherits = extends;
inherited_type = TypeCategory::CPP_TYPE;
} else {
inherits = scr->get_language()->get_global_class_name(base->get_path());
if (inherits.is_empty()) {
inherits = base->get_path();
inherited_type = TypeCategory::PATH_TYPE;
}
}
} else { } else {
if (ScriptServer::is_global_class(p_type)) { if (p_type_category == TypeCategory::PATH_TYPE || ScriptServer::is_global_class(p_type)) {
Ref<Script> scr = EditorNode::get_editor_data().script_class_load_script(p_type); Ref<Script> scr;
if (p_type_category == TypeCategory::PATH_TYPE) {
ERR_FAIL_COND(!ResourceLoader::exists(p_type, "Script"));
scr = ResourceLoader::load(p_type, "Script");
} else {
scr = EditorNode::get_editor_data().script_class_load_script(p_type);
}
ERR_FAIL_COND(scr.is_null()); ERR_FAIL_COND(scr.is_null());
Ref<Script> base = scr->get_base_script(); Ref<Script> base = scr->get_base_script();
if (base.is_null()) { if (base.is_null()) {
String extends; // Must be a native base type.
scr->get_language()->get_global_class_name(scr->get_path(), &extends); StringName extends = scr->get_instance_base_type();
if (extends == StringName()) {
// Not a valid script (has compile errors), we therefore ignore it as it can not be instantiated anyway (when selected).
return;
}
inherits = extends; inherits = extends;
inherited_type = TypeCategory::CPP_TYPE; inherited_type = TypeCategory::CPP_TYPE;
} else { } else {
inherits = scr->get_language()->get_global_class_name(base->get_path()); inherits = base->get_global_name();
if (inherits.is_empty()) {
if (inherits == StringName()) {
inherits = base->get_path(); inherits = base->get_path();
inherited_type = TypeCategory::PATH_TYPE; inherited_type = TypeCategory::PATH_TYPE;
} }
@ -267,7 +264,7 @@ void CreateDialog::_add_type(const String &p_type, const TypeCategory p_type_cat
} }
// Should never happen, but just in case... // Should never happen, but just in case...
ERR_FAIL_COND(inherits.is_empty()); ERR_FAIL_COND(inherits == StringName());
_add_type(inherits, inherited_type); _add_type(inherits, inherited_type);
@ -276,7 +273,7 @@ void CreateDialog::_add_type(const String &p_type, const TypeCategory p_type_cat
_configure_search_option_item(item, p_type, p_type_category); _configure_search_option_item(item, p_type, p_type_category);
} }
void CreateDialog::_configure_search_option_item(TreeItem *r_item, const String &p_type, const TypeCategory p_type_category) { void CreateDialog::_configure_search_option_item(TreeItem *r_item, const StringName &p_type, TypeCategory p_type_category) {
bool script_type = ScriptServer::is_global_class(p_type); bool script_type = ScriptServer::is_global_class(p_type);
bool is_abstract = false; bool is_abstract = false;
if (p_type_category == TypeCategory::CPP_TYPE) { if (p_type_category == TypeCategory::CPP_TYPE) {
@ -342,20 +339,6 @@ void CreateDialog::_configure_search_option_item(TreeItem *r_item, const String
} }
} }
String CreateDialog::_top_result(const Vector<String> &p_candidates, const String &p_search_text) const {
float highest_score = 0;
int highest_index = 0;
for (int i = 0; i < p_candidates.size(); i++) {
float score = _score_type(p_candidates[i].get_slicec(' ', 0), p_search_text);
if (score > highest_score) {
highest_score = score;
highest_index = i;
}
}
return p_candidates[highest_index];
}
float CreateDialog::_score_type(const String &p_type, const String &p_search) const { float CreateDialog::_score_type(const String &p_type, const String &p_search) const {
if (p_type == p_search) { if (p_type == p_search) {
// Always favor an exact match (case-sensitive), since clicking a favorite will set the search text to the type. // Always favor an exact match (case-sensitive), since clicking a favorite will set the search text to the type.

View File

@ -68,10 +68,9 @@ class CreateDialog : public ConfirmationDialog {
HashSet<StringName> type_blacklist; HashSet<StringName> type_blacklist;
void _update_search(); void _update_search();
bool _should_hide_type(const String &p_type) const; bool _should_hide_type(const StringName &p_type) const;
void _add_type(const String &p_type, const TypeCategory p_type_category); void _add_type(const StringName &p_type, TypeCategory p_type_category);
void _configure_search_option_item(TreeItem *r_item, const String &p_type, const TypeCategory p_type_category); void _configure_search_option_item(TreeItem *r_item, const StringName &p_type, TypeCategory p_type_category);
String _top_result(const Vector<String> &p_candidates, const String &p_search_text) const;
float _score_type(const String &p_type, const String &p_search) const; float _score_type(const String &p_type, const String &p_search) const;
bool _is_type_preferred(const String &p_type) const; bool _is_type_preferred(const String &p_type) const;

View File

@ -3533,7 +3533,6 @@ void EditorNode::add_extension_editor_plugin(const StringName &p_class_name) {
EditorPlugin *plugin = Object::cast_to<EditorPlugin>(ClassDB::instantiate(p_class_name)); EditorPlugin *plugin = Object::cast_to<EditorPlugin>(ClassDB::instantiate(p_class_name));
singleton->editor_data.add_extension_editor_plugin(p_class_name, plugin); singleton->editor_data.add_extension_editor_plugin(p_class_name, plugin);
add_editor_plugin(plugin); add_editor_plugin(plugin);
plugin->enable_plugin();
} }
void EditorNode::remove_extension_editor_plugin(const StringName &p_class_name) { void EditorNode::remove_extension_editor_plugin(const StringName &p_class_name) {
@ -7273,9 +7272,7 @@ EditorNode::EditorNode() {
add_editor_plugin(memnew(AudioBusesEditorPlugin(audio_bus_editor))); add_editor_plugin(memnew(AudioBusesEditorPlugin(audio_bus_editor)));
for (int i = 0; i < EditorPlugins::get_plugin_count(); i++) { for (int i = 0; i < EditorPlugins::get_plugin_count(); i++) {
EditorPlugin *plugin = EditorPlugins::create(i); add_editor_plugin(EditorPlugins::create(i));
add_editor_plugin(plugin);
plugin->enable_plugin();
} }
for (const StringName &extension_class_name : GDExtensionEditorPlugins::get_extension_classes()) { for (const StringName &extension_class_name : GDExtensionEditorPlugins::get_extension_classes()) {