From 9d5b80705912d85c3c7301ac0ea0afbf9372a660 Mon Sep 17 00:00:00 2001 From: fabriceci Date: Mon, 11 Oct 2021 11:30:59 +0200 Subject: Improve editor template workflow Co-Authored-By: jmb462 --- editor/script_create_dialog.cpp | 575 +++++++++++++++++++++++++--------------- 1 file changed, 361 insertions(+), 214 deletions(-) (limited to 'editor/script_create_dialog.cpp') diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index 0e96a1d247..a1e3f5aabe 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -33,7 +33,6 @@ #include "core/config/project_settings.h" #include "core/io/file_access.h" #include "core/io/resource_saver.h" -#include "core/object/script_language.h" #include "core/string/string_builder.h" #include "editor/create_dialog.h" #include "editor/editor_node.h" @@ -45,17 +44,16 @@ void ScriptCreateDialog::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { for (int i = 0; i < ScriptServer::get_language_count(); i++) { - String lang = ScriptServer::get_language(i)->get_type(); - Ref lang_icon = get_theme_icon(lang, SNAME("EditorIcons")); - if (lang_icon.is_valid()) { - language_menu->set_item_icon(i, lang_icon); + Ref language_icon = get_theme_icon(ScriptServer::get_language(i)->get_type(), SNAME("EditorIcons")); + if (language_icon.is_valid()) { + language_menu->set_item_icon(i, language_icon); } } - String last_lang = EditorSettings::get_singleton()->get_project_metadata("script_setup", "last_selected_language", ""); - if (!last_lang.is_empty()) { + String last_language = EditorSettings::get_singleton()->get_project_metadata("script_setup", "last_selected_language", ""); + if (!last_language.is_empty()) { for (int i = 0; i < language_menu->get_item_count(); i++) { - if (language_menu->get_item_text(i) == last_lang) { + if (language_menu->get_item_text(i) == last_language) { language_menu->select(i); current_language = i; break; @@ -64,6 +62,10 @@ void ScriptCreateDialog::_notification(int p_what) { } else { language_menu->select(default_language); } + if (EditorSettings::get_singleton()->has_meta("script_setup/use_script_templates")) { + is_using_templates = bool(EditorSettings::get_singleton()->get_meta("script_setup/use_script_templates")); + use_templates->set_pressed(is_using_templates); + } path_button->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"))); parent_browse_button->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"))); @@ -114,7 +116,7 @@ void ScriptCreateDialog::config(const String &p_base_name, const String &p_base_ built_in_enabled = p_built_in_enabled; load_enabled = p_load_enabled; - _lang_changed(current_language); + _language_changed(current_language); _class_name_changed(""); _path_changed(file_path->get_text()); } @@ -145,8 +147,9 @@ bool ScriptCreateDialog::_validate_class(const String &p_string) { for (int i = 0; i < p_string.length(); i++) { if (i == 0) { + // Cannot start with a number. if (p_string[0] >= '0' && p_string[0] <= '9') { - return false; // no start with number plz + return false; } } @@ -170,6 +173,10 @@ String ScriptCreateDialog::_validate_path(const String &p_path, bool p_file_must return TTR("Filename is empty."); } + if (!p.get_file().get_basename().is_valid_filename()) { + return TTR("Filename is invalid."); + } + p = ProjectSettings::get_singleton()->localize_path(p); if (!p.begins_with("res://")) { return TTR("Path is not local."); @@ -178,11 +185,11 @@ String ScriptCreateDialog::_validate_path(const String &p_path, bool p_file_must DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES); if (d->change_dir(p.get_base_dir()) != OK) { memdelete(d); - return TTR("Invalid base path."); + return TTR("Base path is invalid."); } memdelete(d); - /* Does file already exist */ + // Check if file exists. DirAccess *f = DirAccess::create(DirAccess::ACCESS_RESOURCES); if (f->dir_exists(p)) { memdelete(f); @@ -193,11 +200,11 @@ String ScriptCreateDialog::_validate_path(const String &p_path, bool p_file_must } memdelete(f); - /* Check file extension */ + // Check file extension. String extension = p.get_extension(); List extensions; - // get all possible extensions for script + // Get all possible extensions for script. for (int l = 0; l < language_menu->get_item_count(); l++) { ScriptServer::get_language(l)->get_recognized_extensions(&extensions); } @@ -207,8 +214,6 @@ String ScriptCreateDialog::_validate_path(const String &p_path, bool p_file_must int index = 0; for (const String &E : extensions) { if (E.nocasecmp_to(extension) == 0) { - //FIXME (?) - changing language this way doesn't update controls, needs rework - //language_menu->select(index); // change Language option by extension found = true; if (E == ScriptServer::get_language(language_menu->get_selected())->get_extension()) { match = true; @@ -222,16 +227,16 @@ String ScriptCreateDialog::_validate_path(const String &p_path, bool p_file_must return TTR("Invalid extension."); } if (!match) { - return TTR("Wrong extension chosen."); + return TTR("Extension doesn't match chosen language."); } - /* Let ScriptLanguage do custom validation */ + // Let ScriptLanguage do custom validation. String path_error = ScriptServer::get_language(language_menu->get_selected())->validate_path(p); if (!path_error.is_empty()) { return path_error; } - /* All checks passed */ + // All checks passed. return ""; } @@ -244,40 +249,49 @@ String ScriptCreateDialog::_get_class_name() const { } void ScriptCreateDialog::_class_name_changed(const String &p_name) { - if (_validate_class(class_name->get_text())) { - is_class_name_valid = true; - } else { - is_class_name_valid = false; - } + is_class_name_valid = _validate_class(class_name->get_text()); _update_dialog(); } void ScriptCreateDialog::_parent_name_changed(const String &p_parent) { - if (_validate_parent(parent_name->get_text())) { - is_parent_name_valid = true; - } else { - is_parent_name_valid = false; - } + is_parent_name_valid = _validate_parent(parent_name->get_text()); _update_dialog(); } void ScriptCreateDialog::_template_changed(int p_template) { - String selected_template = p_template == 0 ? "" : template_menu->get_item_text(p_template); - EditorSettings::get_singleton()->set_project_metadata("script_setup", "last_selected_template", selected_template); - if (p_template == 0) { - //default - script_template = ""; - return; - } - int selected_id = template_menu->get_selected_id(); - - for (int i = 0; i < template_list.size(); i++) { - const ScriptTemplateInfo &sinfo = template_list[i]; - if (sinfo.id == selected_id) { - script_template = sinfo.dir.plus_file(sinfo.name + "." + sinfo.extension); - break; + const ScriptLanguage::ScriptTemplate &sinfo = _get_current_template(); + // Update last used dictionaries + if (is_using_templates && !parent_name->get_text().begins_with("\"res:")) { + if (sinfo.origin == ScriptLanguage::TemplateLocation::TEMPLATE_PROJECT) { + // Save the last used template for this node into the project dictionary. + Dictionary dic_templates_project = EditorSettings::get_singleton()->get_project_metadata("script_setup", "templates_dictionary", Dictionary()); + dic_templates_project[parent_name->get_text()] = sinfo.get_hash(); + EditorSettings::get_singleton()->set_project_metadata("script_setup", "templates_dictionary", dic_templates_project); + } else { + // Save template into to editor dictionary (not a project template). + Dictionary dic_templates; + if (EditorSettings::get_singleton()->has_meta("script_setup/templates_dictionary")) { + dic_templates = (Dictionary)EditorSettings::get_singleton()->get_meta("script_setup/templates_dictionary"); + } + dic_templates[parent_name->get_text()] = sinfo.get_hash(); + EditorSettings::get_singleton()->set_meta("script_setup/templates_dictionary", dic_templates); + // Remove template from project dictionary as we last used an editor level template. + Dictionary dic_templates_project = EditorSettings::get_singleton()->get_project_metadata("script_setup", "templates_dictionary", Dictionary()); + if (dic_templates_project.has(parent_name->get_text())) { + dic_templates_project.erase(parent_name->get_text()); + EditorSettings::get_singleton()->set_project_metadata("script_setup", "templates_dictionary", dic_templates_project); + } } } + // Update template label information. + String template_info = String::utf8("• "); + template_info += TTR("Template:"); + template_info += " " + sinfo.name; + if (!sinfo.description.is_empty()) { + template_info += " - " + sinfo.description; + } + template_info_label->set_text(template_info); + template_info_label->add_theme_color_override("font_color", get_theme_color(SNAME("success_color"), SNAME("Editor"))); } void ScriptCreateDialog::ok_pressed() { @@ -287,6 +301,7 @@ void ScriptCreateDialog::ok_pressed() { _load_exist(); } + EditorSettings::get_singleton()->save(); is_new_script_created = true; _update_dialog(); } @@ -295,18 +310,10 @@ void ScriptCreateDialog::_create_new() { String cname_param = _get_class_name(); Ref