diff options
Diffstat (limited to 'editor')
34 files changed, 470 insertions, 183 deletions
diff --git a/editor/SCsub b/editor/SCsub index 35c215b663..5dcc253e8b 100644 --- a/editor/SCsub +++ b/editor/SCsub @@ -99,6 +99,8 @@ if env["tools"]: # Fonts flist = glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.ttf") flist.extend(glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.otf")) + flist.extend(glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.woff")) + flist.extend(glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.woff2")) flist.sort() env.Depends("#editor/builtin_fonts.gen.h", flist) env.CommandNoCache( diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp index ea51e1f399..96931efd3b 100644 --- a/editor/action_map_editor.cpp +++ b/editor/action_map_editor.cpp @@ -1100,6 +1100,31 @@ void ActionMapEditor::update_action_list(const Vector<ActionInfo> &p_action_info event_item->set_meta("__event", event); event_item->set_meta("__index", evnt_idx); + // First Column - Icon + Ref<InputEventKey> k = event; + if (k.is_valid()) { + if (k->get_physical_keycode() == Key::NONE) { + event_item->set_icon(0, action_tree->get_theme_icon(SNAME("Keyboard"), SNAME("EditorIcons"))); + } else { + event_item->set_icon(0, action_tree->get_theme_icon(SNAME("KeyboardPhysical"), SNAME("EditorIcons"))); + } + } + + Ref<InputEventMouseButton> mb = event; + if (mb.is_valid()) { + event_item->set_icon(0, action_tree->get_theme_icon(SNAME("Mouse"), SNAME("EditorIcons"))); + } + + Ref<InputEventJoypadButton> jb = event; + if (jb.is_valid()) { + event_item->set_icon(0, action_tree->get_theme_icon(SNAME("JoyButton"), SNAME("EditorIcons"))); + } + + Ref<InputEventJoypadMotion> jm = event; + if (jm.is_valid()) { + event_item->set_icon(0, action_tree->get_theme_icon(SNAME("JoyAxis"), SNAME("EditorIcons"))); + } + // Third Column - Buttons event_item->add_button(2, action_tree->get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), BUTTON_EDIT_EVENT, false, TTR("Edit Event")); event_item->add_button(2, action_tree->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), BUTTON_REMOVE_EVENT, false, TTR("Remove Event")); diff --git a/editor/editor_builders.py b/editor/editor_builders.py index 67d4b8534f..e73fbc6107 100644 --- a/editor/editor_builders.py +++ b/editor/editor_builders.py @@ -5,6 +5,10 @@ All such functions are invoked in a subprocess on Windows to prevent build flaki """ import os import os.path +import shutil +import subprocess +import tempfile +import uuid from platform_methods import subprocess_main @@ -89,10 +93,40 @@ def make_translations_header(target, source, env, category): sorted_paths = sorted(source, key=lambda path: os.path.splitext(os.path.basename(path))[0]) + msgfmt_available = shutil.which("msgfmt") is not None + + if not msgfmt_available: + print("WARNING: msgfmt is not found, using .po files instead of .mo") + xl_names = [] for i in range(len(sorted_paths)): - with open(sorted_paths[i], "rb") as f: - buf = f.read() + if msgfmt_available: + mo_path = os.path.join(tempfile.gettempdir(), uuid.uuid4().hex + ".mo") + cmd = "msgfmt " + sorted_paths[i] + " --no-hash -o " + mo_path + try: + subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE).communicate() + with open(mo_path, "rb") as f: + buf = f.read() + except OSError as e: + print( + "WARNING: msgfmt execution failed, using .po file instead of .mo: path=%r; [%s] %s" + % (sorted_paths[i], e.__class__.__name__, e) + ) + with open(sorted_paths[i], "rb") as f: + buf = f.read() + finally: + try: + os.remove(mo_path) + except OSError as e: + # Do not fail the entire build if it cannot delete a temporary file + print( + "WARNING: Could not delete temporary .mo file: path=%r; [%s] %s" + % (mo_path, e.__class__.__name__, e) + ) + else: + with open(sorted_paths[i], "rb") as f: + buf = f.read() + decomp_size = len(buf) # Use maximum zlib compression level to further reduce file size # (at the cost of initial build times). diff --git a/editor/editor_dir_dialog.cpp b/editor/editor_dir_dialog.cpp index 32ef87a4ab..866f28c03b 100644 --- a/editor/editor_dir_dialog.cpp +++ b/editor/editor_dir_dialog.cpp @@ -156,10 +156,15 @@ void EditorDirDialog::_make_dir_confirm() { String dir = ti->get_metadata(0); + if (EditorFileSystem::get_singleton()->get_filesystem_path(dir + makedirname->get_text())) { + mkdirerr->set_text(TTR("Could not create folder. File with that name already exists.")); + mkdirerr->popup_centered(); + return; + } + DirAccessRef d = DirAccess::open(dir); ERR_FAIL_COND_MSG(!d, "Cannot open directory '" + dir + "'."); Error err = d->make_dir(makedirname->get_text()); - if (err != OK) { mkdirerr->popup_centered(Size2(250, 80) * EDSCALE); } else { diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index afb5bd9d4d..a1081fcbfb 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -1760,8 +1760,9 @@ void EditorExportPlatformPC::get_preset_features(const Ref<EditorExportPreset> & } void EditorExportPlatformPC::get_export_options(List<ExportOption> *r_options) { - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE), "")); + String ext_filter = (get_os_name() == "Windows") ? "*.exe" : ""; + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, ext_filter), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, ext_filter), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "debug/export_console_script", PROPERTY_HINT_ENUM, "No,Debug Only,Debug and Release"), 1)); @@ -1794,8 +1795,8 @@ bool EditorExportPlatformPC::can_export(const Ref<EditorExportPreset> &p_preset, // Look for export templates (first official, and if defined custom templates). bool use64 = p_preset->get("binary_format/64_bits"); - bool dvalid = exists_export_template(use64 ? debug_file_64 : debug_file_32, &err); - bool rvalid = exists_export_template(use64 ? release_file_64 : release_file_32, &err); + bool dvalid = exists_export_template(get_template_file_name("debug", use64 ? "64" : "32"), &err); + bool rvalid = exists_export_template(get_template_file_name("release", use64 ? "64" : "32"), &err); if (p_preset->get("custom_template/debug") != "") { dvalid = FileAccess::exists(p_preset->get("custom_template/debug")); @@ -1830,19 +1831,7 @@ Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_pr template_path = template_path.strip_edges(); if (template_path.is_empty()) { - if (p_preset->get("binary_format/64_bits")) { - if (p_debug) { - template_path = find_export_template(debug_file_64); - } else { - template_path = find_export_template(release_file_64); - } - } else { - if (p_debug) { - template_path = find_export_template(debug_file_32); - } else { - template_path = find_export_template(release_file_32); - } - } + template_path = find_export_template(get_template_file_name(p_debug ? "debug" : "release", p_preset->get("binary_format/64_bits") ? "64" : "32")); } if (!template_path.is_empty() && !FileAccess::exists(template_path)) { @@ -1878,7 +1867,6 @@ Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_pr if (err == OK && !so_files.is_empty()) { // If shared object files, copy them. - da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); for (int i = 0; i < so_files.size() && err == OK; i++) { String src_path = ProjectSettings::get_singleton()->globalize_path(so_files[i].path); String target_path; @@ -1922,22 +1910,6 @@ void EditorExportPlatformPC::set_logo(const Ref<Texture2D> &p_logo) { logo = p_logo; } -void EditorExportPlatformPC::set_release_64(const String &p_file) { - release_file_64 = p_file; -} - -void EditorExportPlatformPC::set_release_32(const String &p_file) { - release_file_32 = p_file; -} - -void EditorExportPlatformPC::set_debug_64(const String &p_file) { - debug_file_64 = p_file; -} - -void EditorExportPlatformPC::set_debug_32(const String &p_file) { - debug_file_32 = p_file; -} - void EditorExportPlatformPC::get_platform_features(List<String> *r_features) { r_features->push_back("pc"); //all pcs support "pc" r_features->push_back("s3tc"); //all pcs support "s3tc" compression diff --git a/editor/editor_export.h b/editor/editor_export.h index 108abab29b..7c61e7cff6 100644 --- a/editor/editor_export.h +++ b/editor/editor_export.h @@ -426,11 +426,6 @@ private: String name; String os_name; - String release_file_32; - String release_file_64; - String debug_file_32; - String debug_file_64; - int chmod_flags = -1; public: @@ -445,17 +440,13 @@ public: virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const override; virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override; virtual Error sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path); + virtual String get_template_file_name(const String &p_target, const String &p_arch) const = 0; void set_name(const String &p_name); void set_os_name(const String &p_name); void set_logo(const Ref<Texture2D> &p_logo); - void set_release_64(const String &p_file); - void set_release_32(const String &p_file); - void set_debug_64(const String &p_file); - void set_debug_32(const String &p_file); - void add_platform_feature(const String &p_feature); virtual void get_platform_features(List<String> *r_features) override; virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) override; diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index 31f2f24066..fe19e73db9 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -781,12 +781,19 @@ void EditorFileDialog::update_file_list() { continue; } - if (show_hidden_files || !dir_access->current_is_hidden()) { + if (show_hidden_files) { if (!dir_access->current_is_dir()) { files.push_back(item); } else { dirs.push_back(item); } + } else if (!dir_access->current_is_hidden()) { + String full_path = cdir == "res://" ? item : dir_access->get_current_dir() + "/" + item; + if (dir_access->current_is_dir() && !EditorFileSystem::_should_skip_directory(full_path)) { + dirs.push_back(item); + } else { + files.push_back(item); + } } item = dir_access->get_next(); } @@ -1092,6 +1099,13 @@ EditorFileDialog::Access EditorFileDialog::get_access() const { } void EditorFileDialog::_make_dir_confirm() { + if (EditorFileSystem::get_singleton()->get_filesystem_path(makedirname->get_text().strip_edges())) { + error_dialog->set_text(TTR("Could not create folder. File with that name already exists.")); + error_dialog->popup_centered(Size2(250, 50) * EDSCALE); + makedirname->set_text(""); // Reset label. + return; + } + Error err = dir_access->make_dir(makedirname->get_text().strip_edges()); if (err == OK) { dir_access->change_dir(makedirname->get_text().strip_edges()); diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp index 7b72e09bd7..66fe3c4838 100644 --- a/editor/editor_fonts.cpp +++ b/editor/editor_fonts.cpp @@ -52,6 +52,23 @@ m_name->add_data(FontJapanese); \ m_name->add_data(FontFallback); +// Note: In some languages, the use of italic/slanted fonts is controversial. Therefore, we are limiting simulated slant to the main font (Latin, Cyrillic, and Greek) and using bold fonts for the rest. + +#define MAKE_FALLBACKS_SLANTED(m_name) \ + m_name->add_data(FontArabicBold); \ + m_name->add_data(FontBengaliBold); \ + m_name->add_data(FontDevanagariBold); \ + m_name->add_data(FontGeorgianBold); \ + m_name->add_data(FontHebrewBold); \ + m_name->add_data(FontMalayalamBold); \ + m_name->add_data(FontOriyaBold); \ + m_name->add_data(FontSinhalaBold); \ + m_name->add_data(FontTamilBold); \ + m_name->add_data(FontTeluguBold); \ + m_name->add_data(FontThaiBold); \ + m_name->add_data(FontJapaneseBold); \ + m_name->add_data(FontFallbackBold); + #define MAKE_FALLBACKS_BOLD(m_name) \ m_name->add_data(FontArabicBold); \ m_name->add_data(FontBengaliBold); \ @@ -93,6 +110,33 @@ m_name->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); \ MAKE_FALLBACKS(m_name); +#define MAKE_SLANTED_FONT(m_name, m_variations) \ + Ref<Font> m_name; \ + m_name.instantiate(); \ + m_name.instantiate(); \ + if (CustomFontSlanted.is_valid()) { \ + m_name->add_data(CustomFontSlanted); \ + m_name->add_data(DefaultFontSlanted); \ + } else { \ + m_name->add_data(DefaultFontSlanted); \ + } \ + { \ + Dictionary variations; \ + if (!m_variations.is_empty()) { \ + Vector<String> variation_tags = m_variations.split(","); \ + for (int i = 0; i < variation_tags.size(); i++) { \ + Vector<String> tokens = variation_tags[i].split("="); \ + if (tokens.size() == 2) { \ + variations[tokens[0]] = tokens[1].to_float(); \ + } \ + } \ + } \ + m_name->set_variation_coordinates(variations); \ + } \ + m_name->set_spacing(TextServer::SPACING_TOP, -EDSCALE); \ + m_name->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); \ + MAKE_FALLBACKS_SLANTED(m_name); + #define MAKE_BOLD_FONT(m_name, m_variations) \ Ref<Font> m_name; \ m_name.instantiate(); \ @@ -217,6 +261,12 @@ void editor_register_fonts(Ref<Theme> p_theme) { EditorSettings::get_singleton()->set_manually("interface/editor/main_font", ""); } + Ref<FontData> CustomFontSlanted; + if (CustomFont.is_valid()) { + CustomFontSlanted = CustomFont->duplicate(); + CustomFontSlanted->set_transform(Transform2D(1.0, 0.4, 0.0, 1.0, 0.0, 0.0)); + } + /* Custom Bold font */ String custom_font_path_bold = EditorSettings::get_singleton()->get("interface/editor/main_font_bold"); @@ -269,6 +319,9 @@ void editor_register_fonts(Ref<Theme> p_theme) { Ref<FontData> FontThai = load_cached_internal_font(_font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning); Ref<FontData> FontThaiBold = load_cached_internal_font(_font_NotoSansThaiUI_Bold, _font_NotoSansThaiUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning); + Ref<FontData> DefaultFontSlanted = DefaultFont->duplicate(); + DefaultFontSlanted->set_transform(Transform2D(1.0, 0.3, 0.0, 1.0, 0.0, 0.0)); + /* Droid Sans */ Ref<FontData> FontFallback = load_cached_internal_font(_font_DroidSansFallback, _font_DroidSansFallback_size, font_hinting, font_antialiased, true, font_subpixel_positioning); @@ -296,6 +349,7 @@ void editor_register_fonts(Ref<Theme> p_theme) { // Bold font MAKE_BOLD_FONT(df_bold, String()); + MAKE_SLANTED_FONT(df_italic, String()); p_theme->set_font_size("bold_size", "EditorFonts", default_font_size); p_theme->set_font("bold", "EditorFonts", df_bold); @@ -325,8 +379,8 @@ void editor_register_fonts(Ref<Theme> p_theme) { MAKE_SOURCE_FONT(df_code, code_font_custom_variations); p_theme->set_font_size("doc_size", "EditorFonts", int(EDITOR_GET("text_editor/help/help_font_size")) * EDSCALE); p_theme->set_font("doc", "EditorFonts", df); - p_theme->set_font_size("doc_bold_size", "EditorFonts", int(EDITOR_GET("text_editor/help/help_font_size")) * EDSCALE); p_theme->set_font("doc_bold", "EditorFonts", df_bold); + p_theme->set_font("doc_italic", "EditorFonts", df_italic); p_theme->set_font_size("doc_title_size", "EditorFonts", int(EDITOR_GET("text_editor/help/help_title_font_size")) * EDSCALE); p_theme->set_font("doc_title", "EditorFonts", df_bold); p_theme->set_font_size("doc_source_size", "EditorFonts", int(EDITOR_GET("text_editor/help/help_source_font_size")) * EDSCALE); diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 622547f0a8..75dbe74e01 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -1476,10 +1476,10 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) { Ref<Font> doc_font = p_rt->get_theme_font(SNAME("doc"), SNAME("EditorFonts")); Ref<Font> doc_bold_font = p_rt->get_theme_font(SNAME("doc_bold"), SNAME("EditorFonts")); + Ref<Font> doc_italic_font = p_rt->get_theme_font(SNAME("doc_italic"), SNAME("EditorFonts")); Ref<Font> doc_code_font = p_rt->get_theme_font(SNAME("doc_source"), SNAME("EditorFonts")); Ref<Font> doc_kbd_font = p_rt->get_theme_font(SNAME("doc_keyboard"), SNAME("EditorFonts")); - Color headline_color = p_rt->get_theme_color(SNAME("headline_color"), SNAME("EditorHelp")); Color link_color = p_rt->get_theme_color(SNAME("link_color"), SNAME("EditorHelp")); Color code_color = p_rt->get_theme_color(SNAME("code_color"), SNAME("EditorHelp")); Color kbd_color = p_rt->get_theme_color(SNAME("kbd_color"), SNAME("EditorHelp")); @@ -1633,7 +1633,7 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) { tag_stack.push_front(tag); } else if (tag == "i") { //use italics font - p_rt->push_color(headline_color); + p_rt->push_font(doc_italic_font); pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag == "code" || tag == "codeblock") { diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 9601eaf5f5..18c9a9f495 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -40,6 +40,7 @@ #include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "multi_node_edit.h" +#include "scene/gui/center_container.h" #include "scene/property_utils.h" #include "scene/resources/packed_scene.h" @@ -2506,7 +2507,7 @@ void EditorInspector::update_tree() { List<PropertyInfo>::Element *N = E_property->next(); bool valid = true; while (N) { - if (N->get().usage & PROPERTY_USAGE_EDITOR && (!restrict_to_basic || (N->get().usage & PROPERTY_USAGE_EDITOR_BASIC_SETTING))) { + if (!N->get().name.begins_with("metadata/_") && N->get().usage & PROPERTY_USAGE_EDITOR && (!restrict_to_basic || (N->get().usage & PROPERTY_USAGE_EDITOR_BASIC_SETTING))) { break; } if (N->get().usage & PROPERTY_USAGE_CATEGORY) { @@ -2580,7 +2581,7 @@ void EditorInspector::update_tree() { continue; - } else if (!(p.usage & PROPERTY_USAGE_EDITOR) || _is_property_disabled_by_feature_profile(p.name) || (restrict_to_basic && !(p.usage & PROPERTY_USAGE_EDITOR_BASIC_SETTING))) { + } else if (p.name.begins_with("metadata/_") || !(p.usage & PROPERTY_USAGE_EDITOR) || _is_property_disabled_by_feature_profile(p.name) || (restrict_to_basic && !(p.usage & PROPERTY_USAGE_EDITOR_BASIC_SETTING))) { // Ignore properties that are not supposed to be in the inspector. continue; } @@ -2915,7 +2916,7 @@ void EditorInspector::update_tree() { ep->set_checked(checked); ep->set_keying(keying); ep->set_read_only(property_read_only); - ep->set_deletable(deletable_properties); + ep->set_deletable(deletable_properties || p.name.begins_with("metadata/")); } current_vbox->add_child(F.property_editor); @@ -2956,6 +2957,15 @@ void EditorInspector::update_tree() { } } + if (!hide_metadata) { + Button *add_md = memnew(Button); + add_md->set_text(TTR("Add Metadata")); + add_md->set_focus_mode(Control::FOCUS_NONE); + add_md->set_icon(get_theme_icon("Add", "EditorIcons")); + add_md->connect("pressed", callable_mp(this, &EditorInspector::_show_add_meta_dialog)); + main_vbox->add_child(add_md); + } + // Get the lists of to add at the end. for (Ref<EditorInspectorPlugin> &ped : valid_plugins) { ped->parse_end(object); @@ -3055,6 +3065,11 @@ void EditorInspector::set_hide_script(bool p_hide) { update_tree(); } +void EditorInspector::set_hide_metadata(bool p_hide) { + hide_metadata = p_hide; + update_tree(); +} + void EditorInspector::set_use_filter(bool p_use) { use_filter = p_use; update_tree(); @@ -3323,6 +3338,14 @@ void EditorInspector::_property_deleted(const String &p_path) { return; } + if (p_path.begins_with("metadata/")) { + String name = p_path.replace_first("metadata/", ""); + undo_redo->create_action(vformat(TTR("Remove metadata %s"), name)); + undo_redo->add_do_method(object, "remove_meta", name); + undo_redo->add_undo_method(object, "set_meta", name, object->get_meta(name)); + undo_redo->commit_action(); + } + emit_signal(SNAME("property_deleted"), p_path); } @@ -3650,6 +3673,81 @@ Variant EditorInspector::get_property_clipboard() const { return property_clipboard; } +void EditorInspector::_add_meta_confirm() { + String name = add_meta_name->get_text(); + + object->editor_set_section_unfold("metadata", true); // Ensure metadata is unfolded when adding a new metadata. + + Variant defval; + Callable::CallError ce; + Variant::construct(Variant::Type(add_meta_type->get_selected_id()), defval, nullptr, 0, ce); + undo_redo->create_action(vformat(TTR("Add metadata %s"), name)); + undo_redo->add_do_method(object, "set_meta", name, defval); + undo_redo->add_undo_method(object, "remove_meta", name); + undo_redo->commit_action(); +} + +void EditorInspector::_check_meta_name(String name) { + String error; + + if (name == "") { + error = TTR("Metadata can't be empty."); + } else if (!name.is_valid_identifier()) { + error = TTR("Invalid metadata identifier."); + } else if (object->has_meta(name)) { + error = TTR("Metadata already exists."); + } + + if (error != "") { + add_meta_error->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor"))); + add_meta_error->set_text(error); + add_meta_dialog->get_ok_button()->set_disabled(true); + } else { + add_meta_error->add_theme_color_override("font_color", get_theme_color(SNAME("success_color"), SNAME("Editor"))); + add_meta_error->set_text(TTR("Metadata name is valid.")); + add_meta_dialog->get_ok_button()->set_disabled(false); + } +} + +void EditorInspector::_show_add_meta_dialog() { + if (!add_meta_dialog) { + add_meta_dialog = memnew(ConfirmationDialog); + add_meta_dialog->set_title(TTR("Add Metadata Property")); + VBoxContainer *vbc = memnew(VBoxContainer); + add_meta_dialog->add_child(vbc); + HBoxContainer *hbc = memnew(HBoxContainer); + vbc->add_child(hbc); + hbc->add_child(memnew(Label(TTR("Name:")))); + add_meta_name = memnew(LineEdit); + add_meta_name->set_custom_minimum_size(Size2(200 * EDSCALE, 1)); + hbc->add_child(add_meta_name); + hbc->add_child(memnew(Label(TTR("Type:")))); + add_meta_type = memnew(OptionButton); + for (int i = 0; i < Variant::VARIANT_MAX; i++) { + if (i == Variant::NIL || i == Variant::RID || i == Variant::CALLABLE || i == Variant::SIGNAL) { + continue; //not editable by inspector. + } + String type = i == Variant::OBJECT ? String("Resource") : Variant::get_type_name(Variant::Type(i)); + + add_meta_type->add_icon_item(get_theme_icon(type, "EditorIcons"), type, i); + } + hbc->add_child(add_meta_type); + add_meta_dialog->get_ok_button()->set_text(TTR("Add")); + add_child(add_meta_dialog); + add_meta_dialog->register_text_enter(add_meta_name); + add_meta_dialog->connect("confirmed", callable_mp(this, &EditorInspector::_add_meta_confirm)); + add_meta_error = memnew(Label); + vbc->add_child(add_meta_error); + + add_meta_name->connect("text_changed", callable_mp(this, &EditorInspector::_check_meta_name)); + } + + add_meta_dialog->popup_centered(); + add_meta_name->set_text(""); + _check_meta_name(""); + add_meta_name->grab_focus(); +} + void EditorInspector::_bind_methods() { ClassDB::bind_method("_edit_request_change", &EditorInspector::_edit_request_change); diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index 3c482a07e7..d625a8043c 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -35,6 +35,7 @@ #include "scene/gui/button.h" #include "scene/gui/dialogs.h" #include "scene/gui/line_edit.h" +#include "scene/gui/option_button.h" #include "scene/gui/panel_container.h" #include "scene/gui/scroll_container.h" #include "scene/gui/texture_rect.h" @@ -445,6 +446,7 @@ class EditorInspector : public ScrollContainer { LineEdit *search_box; bool show_categories = false; bool hide_script = true; + bool hide_metadata = true; bool use_doc_hints = false; bool capitalize_paths = true; bool use_filter = false; @@ -511,6 +513,15 @@ class EditorInspector : public ScrollContainer { void _update_inspector_bg(); + ConfirmationDialog *add_meta_dialog = nullptr; + LineEdit *add_meta_name = nullptr; + OptionButton *add_meta_type = nullptr; + Label *add_meta_error = nullptr; + + void _add_meta_confirm(); + void _show_add_meta_dialog(); + void _check_meta_name(String name); + protected: static void _bind_methods(); void _notification(int p_what); @@ -541,6 +552,7 @@ public: void set_show_categories(bool p_show); void set_use_doc_hints(bool p_enable); void set_hide_script(bool p_hide); + void set_hide_metadata(bool p_hide); void set_use_filter(bool p_use); void register_text_enter(Node *p_line_edit); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index bf118b8e16..305fe5f6ff 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -1885,6 +1885,7 @@ void EditorNode::_dialog_action(String p_file) { case FILE_CLOSE: case FILE_CLOSE_ALL_AND_QUIT: case FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER: + case FILE_CLOSE_ALL_AND_RELOAD_CURRENT_PROJECT: case SCENE_TAB_CLOSE: case FILE_SAVE_SCENE: case FILE_SAVE_AS_SCENE: { @@ -2524,17 +2525,23 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { _scene_tab_closed(editor_data.get_edited_scene()); } break; case FILE_CLOSE_ALL_AND_QUIT: - case FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER: { + case FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER: + case FILE_CLOSE_ALL_AND_RELOAD_CURRENT_PROJECT: { if (!p_confirmed) { tab_closing = _next_unsaved_scene(false); _scene_tab_changed(tab_closing); - if (unsaved_cache || p_option == FILE_CLOSE_ALL_AND_QUIT || p_option == FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER) { + if (unsaved_cache || p_option == FILE_CLOSE_ALL_AND_QUIT || p_option == FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER || p_option == FILE_CLOSE_ALL_AND_RELOAD_CURRENT_PROJECT) { Node *scene_root = editor_data.get_edited_scene_root(tab_closing); if (scene_root) { String scene_filename = scene_root->get_scene_file_path(); - save_confirmation->get_ok_button()->set_text(TTR("Save & Close")); - save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), !scene_filename.is_empty() ? scene_filename : "unsaved scene")); + if (p_option == FILE_CLOSE_ALL_AND_RELOAD_CURRENT_PROJECT) { + save_confirmation->get_ok_button()->set_text(TTR("Save & Reload")); + save_confirmation->set_text(vformat(TTR("Save changes to '%s' before reloading?"), !scene_filename.is_empty() ? scene_filename : "unsaved scene")); + } else { + save_confirmation->get_ok_button()->set_text(TTR("Save & Quit")); + save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), !scene_filename.is_empty() ? scene_filename : "unsaved scene")); + } save_confirmation->popup_centered(); break; } @@ -2820,11 +2827,9 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { case FILE_EXPLORE_ANDROID_BUILD_TEMPLATES: { OS::get_singleton()->shell_open("file://" + ProjectSettings::get_singleton()->get_resource_path().plus_file("android")); } break; - case RUN_RELOAD_CURRENT_PROJECT: { - restart_editor(); - } break; case FILE_QUIT: - case RUN_PROJECT_MANAGER: { + case RUN_PROJECT_MANAGER: + case RELOAD_CURRENT_PROJECT: { if (!p_confirmed) { bool save_each = EDITOR_GET("interface/editor/save_each_scene_on_quit"); if (_next_unsaved_scene(!save_each) == -1) { @@ -2832,7 +2837,13 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { break; } else { if (save_each) { - _menu_option_confirm(p_option == FILE_QUIT ? FILE_CLOSE_ALL_AND_QUIT : FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER, false); + if (p_option == RELOAD_CURRENT_PROJECT) { + _menu_option_confirm(FILE_CLOSE_ALL_AND_RELOAD_CURRENT_PROJECT, false); + } else if (p_option == FILE_QUIT) { + _menu_option_confirm(FILE_CLOSE_ALL_AND_QUIT, false); + } else { + _menu_option_confirm(FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER, false); + } } else { String unsaved_scenes; int i = _next_unsaved_scene(true, 0); @@ -2840,9 +2851,13 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { unsaved_scenes += "\n " + editor_data.get_edited_scene_root(i)->get_scene_file_path(); i = _next_unsaved_scene(true, ++i); } - - save_confirmation->get_ok_button()->set_text(TTR("Save & Quit")); - save_confirmation->set_text((p_option == FILE_QUIT ? TTR("Save changes to the following scene(s) before quitting?") : TTR("Save changes to the following scene(s) before opening Project Manager?")) + unsaved_scenes); + if (p_option == RELOAD_CURRENT_PROJECT) { + save_confirmation->get_ok_button()->set_text(TTR("Save & Reload")); + save_confirmation->set_text(TTR("Save changes to the following scene(s) before reloading?") + unsaved_scenes); + } else { + save_confirmation->get_ok_button()->set_text(TTR("Save & Quit")); + save_confirmation->set_text((p_option == FILE_QUIT ? TTR("Save changes to the following scene(s) before quitting?") : TTR("Save changes to the following scene(s) before opening Project Manager?")) + unsaved_scenes); + } save_confirmation->popup_centered(); } } @@ -3039,6 +3054,7 @@ void EditorNode::_discard_changes(const String &p_str) { switch (current_option) { case FILE_CLOSE_ALL_AND_QUIT: case FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER: + case FILE_CLOSE_ALL_AND_RELOAD_CURRENT_PROJECT: case FILE_CLOSE: case FILE_CLOSE_OTHERS: case FILE_CLOSE_RIGHT: @@ -3055,13 +3071,19 @@ void EditorNode::_discard_changes(const String &p_str) { _remove_scene(tab_closing); _update_scene_tabs(); - if (current_option == FILE_CLOSE_ALL_AND_QUIT || current_option == FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER) { + if (current_option == FILE_CLOSE_ALL_AND_QUIT || current_option == FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER || current_option == FILE_CLOSE_ALL_AND_RELOAD_CURRENT_PROJECT) { // If restore tabs is enabled, reopen the scene that has just been closed, so it's remembered properly. if (bool(EDITOR_GET("interface/scene_tabs/restore_scenes_on_load"))) { _menu_option_confirm(FILE_OPEN_PREV, true); } if (_next_unsaved_scene(false) == -1) { - current_option = current_option == FILE_CLOSE_ALL_AND_QUIT ? FILE_QUIT : RUN_PROJECT_MANAGER; + if (current_option == FILE_CLOSE_ALL_AND_RELOAD_CURRENT_PROJECT) { + current_option = RELOAD_CURRENT_PROJECT; + } else if (current_option == FILE_CLOSE_ALL_AND_QUIT) { + current_option = FILE_QUIT; + } else { + current_option = RUN_PROJECT_MANAGER; + } _discard_changes(); } else { _menu_option_confirm(current_option, false); @@ -3098,6 +3120,9 @@ void EditorNode::_discard_changes(const String &p_str) { Error err = OS::get_singleton()->create_instance(args); ERR_FAIL_COND(err); } break; + case RELOAD_CURRENT_PROJECT: { + restart_editor(); + } break; } } @@ -6463,7 +6488,7 @@ EditorNode::EditorNode() { tool_menu->add_item(TTR("Orphan Resource Explorer..."), TOOLS_ORPHAN_RESOURCES); p->add_separator(); - p->add_shortcut(ED_SHORTCUT("editor/reload_current_project", TTR("Reload Current Project")), RUN_RELOAD_CURRENT_PROJECT); + p->add_shortcut(ED_SHORTCUT("editor/reload_current_project", TTR("Reload Current Project")), RELOAD_CURRENT_PROJECT); ED_SHORTCUT_AND_COMMAND("editor/quit_to_project_list", TTR("Quit to Project List"), KeyModifierMask::CMD + KeyModifierMask::SHIFT + Key::Q); ED_SHORTCUT_OVERRIDE("editor/quit_to_project_list", "macos", KeyModifierMask::SHIFT + KeyModifierMask::ALT + Key::Q); p->add_shortcut(ED_GET_SHORTCUT("editor/quit_to_project_list"), RUN_PROJECT_MANAGER, true); diff --git a/editor/editor_node.h b/editor/editor_node.h index 0b6dbaec49..0c9df16b2e 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -153,6 +153,7 @@ private: FILE_CLOSE_ALL, FILE_CLOSE_ALL_AND_QUIT, FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER, + FILE_CLOSE_ALL_AND_RELOAD_CURRENT_PROJECT, FILE_QUIT, FILE_EXTERNAL_OPEN_SCENE, EDIT_UNDO, @@ -169,7 +170,7 @@ private: RUN_PLAY_CUSTOM_SCENE, RUN_SETTINGS, RUN_USER_DATA_FOLDER, - RUN_RELOAD_CURRENT_PROJECT, + RELOAD_CURRENT_PROJECT, RUN_PROJECT_MANAGER, RUN_VCS_METADATA, RUN_VCS_SETTINGS, diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp index a7b2a4cfa6..53f1a689d6 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -327,6 +327,13 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) { case OBJ_MENU_PASTE: { edited_resource = EditorSettings::get_singleton()->get_resource_clipboard(); + if (edited_resource->is_built_in() && EditorNode::get_singleton()->get_edited_scene() && + edited_resource->get_path().get_slice("::", 0) != EditorNode::get_singleton()->get_edited_scene()->get_scene_file_path()) { + // Automatically make resource unique if it belongs to another scene. + _edit_menu_cbk(OBJ_MENU_MAKE_UNIQUE); + return; + } + emit_signal(SNAME("resource_changed"), edited_resource); _update_resource(); } break; diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 08cc957ec7..1364f7891e 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -422,9 +422,9 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { #endif EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_subpixel_positioning", 1, "Disabled,Auto,One half of a pixel,One quarter of a pixel") - EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "interface/editor/main_font", "", "*.ttf,*.otf") - EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "interface/editor/main_font_bold", "", "*.ttf,*.otf") - EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "interface/editor/code_font", "", "*.ttf,*.otf") + EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "interface/editor/main_font", "", "*.ttf,*.otf,*.woff,*.woff2,*.pfb,*.pfm") + EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "interface/editor/main_font_bold", "", "*.ttf,*.otf,*.woff,*.woff2,*.pfb,*.pfm") + EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "interface/editor/code_font", "", "*.ttf,*.otf,*.woff,*.woff2,*.pfb,*.pfm") EDITOR_SETTING_USAGE(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/editor/low_processor_mode_sleep_usec", 6900, "1,100000,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) // Default unfocused usec sleep is for 10 FPS. Allow an unfocused FPS limit // as low as 1 FPS for those who really need low power usage (but don't need @@ -711,7 +711,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "network/debug/remote_port", 6007, "1,65535,1") // SSL - EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "network/ssl/editor_ssl_certificates", _SYSTEM_CERTS_PATH, "*.crt,*.pem") + EDITOR_SETTING_USAGE(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "network/ssl/editor_ssl_certificates", _SYSTEM_CERTS_PATH, "*.crt,*.pem", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); // Profiler _initial_set("debugger/profiler_frame_history_size", 600); diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp index 9bf3c4c590..32d28cd3a7 100644 --- a/editor/editor_spin_slider.cpp +++ b/editor/editor_spin_slider.cpp @@ -81,7 +81,7 @@ void EditorSpinSlider::gui_input(const Ref<InputEvent> &p_event) { if (grabbing_spinner_attempt) { if (grabbing_spinner) { Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); - Input::get_singleton()->warp_mouse_position(grabbing_spinner_mouse_pos); + Input::get_singleton()->warp_mouse(grabbing_spinner_mouse_pos); update(); } else { _focus_entered(); @@ -414,7 +414,7 @@ void EditorSpinSlider::_draw_spin_slider() { grabber->set_position(get_global_position() + (grabber_rect.get_center() - grabber->get_size() * 0.5) * scale); if (mousewheel_over_grabber) { - Input::get_singleton()->warp_mouse_position(grabber->get_position() + grabber_rect.size); + Input::get_singleton()->warp_mouse(grabber->get_position() + grabber_rect.size); } grabber_range = width; diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 28feac5d2b..1fea759a90 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -288,17 +288,40 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme = dark_icon_color_dictionary[Color::html("#5fff97")] = success_color; dark_icon_color_dictionary[Color::html("#ffdd65")] = warning_color; + // Use the accent color for some icons (checkbox, radio, toggle, etc.). + Dictionary accent_color_icon_color_dictionary; + Set<StringName> accent_color_icons; + + const Color accent_color = p_theme->get_color(SNAME("accent_color"), SNAME("Editor")); + accent_color_icon_color_dictionary[Color::html("699ce8")] = accent_color; + if (accent_color.get_luminance() > 0.75) { + accent_color_icon_color_dictionary[Color::html("ffffff")] = Color(0.2, 0.2, 0.2); + } + + accent_color_icons.insert("GuiChecked"); + accent_color_icons.insert("GuiRadioChecked"); + accent_color_icons.insert("GuiIndeterminate"); + accent_color_icons.insert("GuiToggleOn"); + accent_color_icons.insert("GuiToggleOnMirrored"); + accent_color_icons.insert("PlayOverlay"); + // Generate icons. if (!p_only_thumbs) { for (int i = 0; i < editor_icons_count; i++) { - float saturation = p_icon_saturation; + Ref<ImageTexture> icon; - if (strcmp(editor_icons_names[i], "DefaultProjectIcon") == 0 || strcmp(editor_icons_names[i], "Godot") == 0 || strcmp(editor_icons_names[i], "Logo") == 0) { - saturation = 1.0; - } + if (accent_color_icons.has(editor_icons_names[i])) { + icon = editor_generate_icon(i, true, EDSCALE, 1.0, accent_color_icon_color_dictionary); + } else { + float saturation = p_icon_saturation; - const int is_exception = exceptions.has(editor_icons_names[i]); - const Ref<ImageTexture> icon = editor_generate_icon(i, !is_exception, EDSCALE, saturation, dark_icon_color_dictionary); + if (strcmp(editor_icons_names[i], "DefaultProjectIcon") == 0 || strcmp(editor_icons_names[i], "Godot") == 0 || strcmp(editor_icons_names[i], "Logo") == 0) { + saturation = 1.0; + } + + const int is_exception = exceptions.has(editor_icons_names[i]); + icon = editor_generate_icon(i, !is_exception, EDSCALE, saturation, dark_icon_color_dictionary); + } p_theme->set_icon(editor_icons_names[i], SNAME("EditorIcons"), icon); } @@ -514,8 +537,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // Register icons + font - // The resolution and the icon color (dark_theme bool) has not changed, so we do not regenerate the icons. - if (p_theme != nullptr && fabs(p_theme->get_constant(SNAME("scale"), SNAME("Editor")) - EDSCALE) < 0.00001 && (bool)p_theme->get_constant(SNAME("dark_theme"), SNAME("Editor")) == dark_theme && prev_icon_saturation == icon_saturation) { + // The editor scale, icon color (dark_theme bool), icon saturation, and accent color has not changed, so we do not regenerate the icons. + if (p_theme != nullptr && fabs(p_theme->get_constant(SNAME("scale"), SNAME("Editor")) - EDSCALE) < 0.00001 && (bool)p_theme->get_constant(SNAME("dark_theme"), SNAME("Editor")) == dark_theme && prev_icon_saturation == icon_saturation && p_theme->get_color(SNAME("accent_color"), SNAME("Editor")) == accent_color) { // Register already generated icons. for (int i = 0; i < editor_icons_count; i++) { theme->set_icon(editor_icons_names[i], SNAME("EditorIcons"), p_theme->get_icon(editor_icons_names[i], SNAME("EditorIcons"))); @@ -612,7 +635,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { style_tab_selected->set_border_width_all(0); style_tab_selected->set_border_width(SIDE_TOP, Math::round(2 * EDSCALE)); // Make the highlight line prominent, but not too prominent as to not be distracting. - style_tab_selected->set_border_color(dark_color_2.lerp(accent_color, 0.75)); + Color tab_highlight = dark_color_2.lerp(accent_color, 0.75); + style_tab_selected->set_border_color(tab_highlight); // Don't round the top corners to avoid creating a small blank space between the tabs and the main panel. // This also makes the top highlight look better. style_tab_selected->set_corner_radius_all(0); @@ -1056,17 +1080,19 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("tab_selected", "TabBar", style_tab_selected); theme->set_stylebox("tab_unselected", "TabBar", style_tab_unselected); theme->set_stylebox("tab_disabled", "TabBar", style_tab_disabled); + theme->set_stylebox("button_pressed", "TabBar", style_menu); + theme->set_stylebox("button_highlight", "TabBar", style_menu); + theme->set_stylebox("SceneTabFG", "EditorStyles", style_tab_selected); + theme->set_stylebox("SceneTabBG", "EditorStyles", style_tab_unselected); theme->set_color("font_selected_color", "TabContainer", font_color); theme->set_color("font_unselected_color", "TabContainer", font_disabled_color); theme->set_color("font_selected_color", "TabBar", font_color); theme->set_color("font_unselected_color", "TabBar", font_disabled_color); + theme->set_color("drop_mark_color", "TabContainer", tab_highlight); + theme->set_color("drop_mark_color", "TabBar", tab_highlight); theme->set_icon("menu", "TabContainer", theme->get_icon(SNAME("GuiTabMenu"), SNAME("EditorIcons"))); theme->set_icon("menu_highlight", "TabContainer", theme->get_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons"))); - theme->set_stylebox("SceneTabFG", "EditorStyles", style_tab_selected); - theme->set_stylebox("SceneTabBG", "EditorStyles", style_tab_unselected); theme->set_icon("close", "TabBar", theme->get_icon(SNAME("GuiClose"), SNAME("EditorIcons"))); - theme->set_stylebox("button_pressed", "TabBar", style_menu); - theme->set_stylebox("button_highlight", "TabBar", style_menu); theme->set_icon("increment", "TabContainer", theme->get_icon(SNAME("GuiScrollArrowRight"), SNAME("EditorIcons"))); theme->set_icon("decrement", "TabContainer", theme->get_icon(SNAME("GuiScrollArrowLeft"), SNAME("EditorIcons"))); theme->set_icon("increment", "TabBar", theme->get_icon(SNAME("GuiScrollArrowRight"), SNAME("EditorIcons"))); @@ -1075,6 +1101,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_icon("decrement_highlight", "TabBar", theme->get_icon(SNAME("GuiScrollArrowLeftHl"), SNAME("EditorIcons"))); theme->set_icon("increment_highlight", "TabContainer", theme->get_icon(SNAME("GuiScrollArrowRightHl"), SNAME("EditorIcons"))); theme->set_icon("decrement_highlight", "TabContainer", theme->get_icon(SNAME("GuiScrollArrowLeftHl"), SNAME("EditorIcons"))); + theme->set_icon("drop_mark", "TabContainer", theme->get_icon(SNAME("GuiTabDropMark"), SNAME("EditorIcons"))); + theme->set_icon("drop_mark", "TabBar", theme->get_icon(SNAME("GuiTabDropMark"), SNAME("EditorIcons"))); theme->set_constant("hseparation", "TabBar", 4 * EDSCALE); // Content of each tab diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 038cc2ab2f..2100a787c8 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -1413,6 +1413,12 @@ void FileSystemDock::_make_dir_confirm() { if (!directory.ends_with("/")) { directory = directory.get_base_dir(); } + + if (EditorFileSystem::get_singleton()->get_filesystem_path(directory + dir_name)) { + EditorNode::get_singleton()->show_warning(TTR("Could not create folder. File with that name already exists.")); + return; + } + print_verbose("Making folder " + dir_name + " in " + directory); DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); Error err = da->change_dir(directory); diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp index 4b3a7a8313..37d535aed2 100644 --- a/editor/groups_editor.cpp +++ b/editor/groups_editor.cpp @@ -416,6 +416,8 @@ void GroupDialog::_bind_methods() { ClassDB::bind_method("_rename_group_item", &GroupDialog::_rename_group_item); + ClassDB::bind_method("_group_selected", &GroupDialog::_group_selected); + ADD_SIGNAL(MethodInfo("group_edited")); } diff --git a/editor/icons/GuiTabDropMark.svg b/editor/icons/GuiTabDropMark.svg new file mode 100644 index 0000000000..c85b165c71 --- /dev/null +++ b/editor/icons/GuiTabDropMark.svg @@ -0,0 +1 @@ +<svg height="32" viewBox="0 0 16 32" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m5 2h6v30h-6z" fill="#fff"/></svg> diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index 3b5a82b2c3..69fa64c24c 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -994,13 +994,12 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ImporterMesh> &p Array a = p_morph_meshes[mi]->get_surface_arrays(surface); //add valid weight and bone arrays if they exist, TODO check if they are unique to shape (generally not) - if (has_weights) { - a[Mesh::ARRAY_WEIGHTS] = d[Mesh::ARRAY_WEIGHTS]; - a[Mesh::ARRAY_BONES] = d[Mesh::ARRAY_BONES]; + // Enforce blend shape mask array format + for (int mj = 0; mj < Mesh::ARRAY_MAX; mj++) { + if (!(Mesh::ARRAY_FORMAT_BLEND_SHAPE_MASK & (1 << mj))) { + a[mj] = Variant(); + } } - - a[Mesh::ARRAY_INDEX] = Variant(); - //a.resize(Mesh::ARRAY_MAX); //no need for index mr.push_back(a); } diff --git a/editor/import/resource_importer_dynamic_font.cpp b/editor/import/resource_importer_dynamic_font.cpp index 077b94bb4e..a7f6d09aed 100644 --- a/editor/import/resource_importer_dynamic_font.cpp +++ b/editor/import/resource_importer_dynamic_font.cpp @@ -52,7 +52,7 @@ void ResourceImporterDynamicFont::get_recognized_extensions(List<String> *p_exte p_extensions->push_back("ttf"); p_extensions->push_back("otf"); p_extensions->push_back("woff"); - //p_extensions->push_back("woff2"); + p_extensions->push_back("woff2"); p_extensions->push_back("pfb"); p_extensions->push_back("pfm"); #endif diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp index 8cb9a47fb5..68d1d23dd8 100644 --- a/editor/import/resource_importer_wav.cpp +++ b/editor/import/resource_importer_wav.cpp @@ -63,6 +63,11 @@ bool ResourceImporterWAV::get_option_visibility(const String &p_path, const Stri return false; } + // Don't show begin/end loop points if loop mode is auto-detected or disabled. + if ((int)p_options["edit/loop_mode"] < 2 && (p_option == "edit/loop_begin" || p_option == "edit/loop_end")) { + return false; + } + return true; } @@ -81,7 +86,10 @@ void ResourceImporterWAV::get_import_options(const String &p_path, List<ImportOp r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "force/max_rate_hz", PROPERTY_HINT_RANGE, "11025,192000,1,exp"), 44100)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "edit/trim"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "edit/normalize"), false)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "edit/loop"), false)); + // Keep the `edit/loop_mode` enum in sync with AudioStreamSample::LoopMode (note: +1 offset due to "Detect From WAV"). + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "edit/loop_mode", PROPERTY_HINT_ENUM, "Detect From WAV,Disabled,Forward,Ping-Pong,Backward", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "edit/loop_begin"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "edit/loop_end"), -1)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/mode", PROPERTY_HINT_ENUM, "Disabled,RAM (Ima-ADPCM)"), 0)); } @@ -119,10 +127,14 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "Not a WAV file (no WAVE RIFF header)."); } + // Let users override potential loop points from the WAV. + // We parse the WAV loop points only with "Detect From WAV" (0). + int import_loop_mode = p_options["edit/loop_mode"]; + int format_bits = 0; int format_channels = 0; - AudioStreamSample::LoopMode loop = AudioStreamSample::LOOP_DISABLED; + AudioStreamSample::LoopMode loop_mode = AudioStreamSample::LOOP_DISABLED; uint16_t compression_code = 1; bool format_found = false; bool data_found = false; @@ -248,8 +260,8 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s } } - if (chunkID[0] == 's' && chunkID[1] == 'm' && chunkID[2] == 'p' && chunkID[3] == 'l') { - //loop point info! + if (import_loop_mode == 0 && chunkID[0] == 's' && chunkID[1] == 'm' && chunkID[2] == 'p' && chunkID[3] == 'l') { + // Loop point info! /** * Consider exploring next document: @@ -270,11 +282,11 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s int loop_type = file->get_32(); if (loop_type == 0x00 || loop_type == 0x01 || loop_type == 0x02) { if (loop_type == 0x00) { - loop = AudioStreamSample::LOOP_FORWARD; + loop_mode = AudioStreamSample::LOOP_FORWARD; } else if (loop_type == 0x01) { - loop = AudioStreamSample::LOOP_PINGPONG; + loop_mode = AudioStreamSample::LOOP_PINGPONG; } else if (loop_type == 0x02) { - loop = AudioStreamSample::LOOP_BACKWARD; + loop_mode = AudioStreamSample::LOOP_BACKWARD; } loop_begin = file->get_32(); loop_end = file->get_32(); @@ -346,7 +358,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s } } - if (loop) { + if (loop_mode) { loop_begin = (int)(loop_begin * (float)new_data_frames / (float)frames); loop_end = (int)(loop_end * (float)new_data_frames / (float)frames); } @@ -377,7 +389,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s bool trim = p_options["edit/trim"]; - if (trim && !loop && format_channels > 0) { + if (trim && (loop_mode != AudioStreamSample::LOOP_DISABLED) && format_channels > 0) { int first = 0; int last = (frames / format_channels) - 1; bool found = false; @@ -421,12 +433,17 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s } } - bool make_loop = p_options["edit/loop"]; - - if (make_loop && !loop) { - loop = AudioStreamSample::LOOP_FORWARD; - loop_begin = 0; - loop_end = frames; + if (import_loop_mode >= 2) { + loop_mode = (AudioStreamSample::LoopMode)(import_loop_mode - 1); + loop_begin = p_options["edit/loop_begin"]; + loop_end = p_options["edit/loop_end"]; + // Wrap around to max frames, so `-1` can be used to select the end, etc. + if (loop_begin < 0) { + loop_begin = CLAMP(loop_begin + frames + 1, 0, frames); + } + if (loop_end < 0) { + loop_end = CLAMP(loop_end + frames + 1, 0, frames); + } } int compression = p_options["compress/mode"]; @@ -512,7 +529,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s sample->set_data(dst_data); sample->set_format(dst_format); sample->set_mix_rate(rate); - sample->set_loop_mode(loop); + sample->set_loop_mode(loop_mode); sample->set_loop_begin(loop_begin); sample->set_loop_end(loop_end); sample->set_stereo(format_channels == 2); diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index 087e51b0cb..9ebea79435 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -679,6 +679,7 @@ InspectorDock::InspectorDock(EditorData &p_editor_data) { inspector->set_v_size_flags(Control::SIZE_EXPAND_FILL); inspector->set_use_doc_hints(true); inspector->set_hide_script(false); + inspector->set_hide_metadata(false); inspector->set_enable_capitalize_paths(bool(EDITOR_GET("interface/inspector/capitalize_properties"))); inspector->set_use_folding(!bool(EDITOR_GET("interface/inspector/disable_folding"))); inspector->register_text_enter(search); diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index 1468d63daf..20bd145299 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -997,7 +997,7 @@ HBoxContainer *EditorAssetLibrary::_make_pages(int p_page, int p_page_count, int hbc->add_theme_constant_override("separation", 5 * EDSCALE); Button *first = memnew(Button); - first->set_text(TTR("First")); + first->set_text(TTR("First", "Pagination")); if (p_page != 0) { first->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search), varray(0)); } else { @@ -1007,7 +1007,7 @@ HBoxContainer *EditorAssetLibrary::_make_pages(int p_page, int p_page_count, int hbc->add_child(first); Button *prev = memnew(Button); - prev->set_text(TTR("Previous")); + prev->set_text(TTR("Previous", "Pagination")); if (p_page > 0) { prev->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search), varray(p_page - 1)); } else { @@ -1037,7 +1037,7 @@ HBoxContainer *EditorAssetLibrary::_make_pages(int p_page, int p_page_count, int } Button *next = memnew(Button); - next->set_text(TTR("Next")); + next->set_text(TTR("Next", "Pagination")); if (p_page < p_page_count - 1) { next->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search), varray(p_page + 1)); } else { @@ -1048,7 +1048,7 @@ HBoxContainer *EditorAssetLibrary::_make_pages(int p_page, int p_page_count, int hbc->add_child(next); Button *last = memnew(Button); - last->set_text(TTR("Last")); + last->set_text(TTR("Last", "Pagination")); if (p_page != p_page_count - 1) { last->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search), varray(p_page_count - 1)); } else { diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index d713e70251..764f467192 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -4324,8 +4324,8 @@ void CanvasItemEditor::_popup_callback(int p_op) { undo_redo->add_do_method(this, "emit_signal", "item_lock_status_changed"); undo_redo->add_undo_method(this, "emit_signal", "item_lock_status_changed"); } - undo_redo->add_do_method(viewport, "update", Variant()); - undo_redo->add_undo_method(viewport, "update", Variant()); + undo_redo->add_do_method(viewport, "update"); + undo_redo->add_undo_method(viewport, "update"); undo_redo->commit_action(); } break; case UNLOCK_SELECTED: { @@ -4346,8 +4346,8 @@ void CanvasItemEditor::_popup_callback(int p_op) { undo_redo->add_do_method(this, "emit_signal", "item_lock_status_changed"); undo_redo->add_undo_method(this, "emit_signal", "item_lock_status_changed"); } - undo_redo->add_do_method(viewport, "update", Variant()); - undo_redo->add_undo_method(viewport, "update", Variant()); + undo_redo->add_do_method(viewport, "update"); + undo_redo->add_undo_method(viewport, "update"); undo_redo->commit_action(); } break; case GROUP_SELECTED: { @@ -4368,8 +4368,8 @@ void CanvasItemEditor::_popup_callback(int p_op) { undo_redo->add_do_method(this, "emit_signal", "item_group_status_changed"); undo_redo->add_undo_method(this, "emit_signal", "item_group_status_changed"); } - undo_redo->add_do_method(viewport, "update", Variant()); - undo_redo->add_undo_method(viewport, "update", Variant()); + undo_redo->add_do_method(viewport, "update"); + undo_redo->add_undo_method(viewport, "update"); undo_redo->commit_action(); } break; case UNGROUP_SELECTED: { @@ -4390,8 +4390,8 @@ void CanvasItemEditor::_popup_callback(int p_op) { undo_redo->add_do_method(this, "emit_signal", "item_group_status_changed"); undo_redo->add_undo_method(this, "emit_signal", "item_group_status_changed"); } - undo_redo->add_do_method(viewport, "update", Variant()); - undo_redo->add_undo_method(viewport, "update", Variant()); + undo_redo->add_do_method(viewport, "update"); + undo_redo->add_undo_method(viewport, "update"); undo_redo->commit_action(); } break; diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp index 41e3471a78..423ec5f4ed 100644 --- a/editor/plugins/mesh_library_editor_plugin.cpp +++ b/editor/plugins/mesh_library_editor_plugin.cpp @@ -271,7 +271,7 @@ MeshLibraryEditor::MeshLibraryEditor() { menu = memnew(MenuButton); Node3DEditor::get_singleton()->add_control_to_menu_panel(menu); menu->set_position(Point2(1, 1)); - menu->set_text(TTR("Mesh Library")); + menu->set_text(TTR("MeshLibrary")); menu->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("MeshLibrary"), SNAME("EditorIcons"))); menu->get_popup()->add_item(TTR("Add Item"), MENU_OPTION_ADD_ITEM); menu->get_popup()->add_item(TTR("Remove Selected Item"), MENU_OPTION_REMOVE_ITEM); diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 52e60b606c..ea119a33fa 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -205,7 +205,7 @@ void ViewportRotationControl::gui_input(const Ref<InputEvent> &p_event) { orbiting = false; if (Input::get_singleton()->get_mouse_mode() == Input::MOUSE_MODE_CAPTURED) { Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); - Input::get_singleton()->warp_mouse_position(orbiting_mouse_start); + Input::get_singleton()->warp_mouse(orbiting_mouse_start); } } } diff --git a/editor/plugins/ot_features_plugin.cpp b/editor/plugins/ot_features_plugin.cpp index 9cd428a2d4..27b35d803c 100644 --- a/editor/plugins/ot_features_plugin.cpp +++ b/editor/plugins/ot_features_plugin.cpp @@ -96,10 +96,19 @@ OpenTypeFeaturesEditor::OpenTypeFeaturesEditor() { /*************************************************************************/ void OpenTypeFeaturesAdd::_add_feature(int p_option) { - get_edited_object()->set("opentype_features/" + TS->tag_to_name(p_option), 1); + edited_object->set("opentype_features/" + TS->tag_to_name(p_option), 1); } -void OpenTypeFeaturesAdd::update_property() { +void OpenTypeFeaturesAdd::_features_menu() { + Size2 size = get_size(); + menu->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y)); + menu->reset_size(); + menu->popup(); +} + +void OpenTypeFeaturesAdd::setup(Object *p_object) { + edited_object = p_object; + menu->clear(); menu_ss->clear(); menu_cv->clear(); @@ -107,7 +116,7 @@ void OpenTypeFeaturesAdd::update_property() { bool have_ss = false; bool have_cv = false; bool have_cu = false; - Dictionary features = Object::cast_to<Control>(get_edited_object())->get_theme_font(SNAME("font"))->get_feature_list(); + Dictionary features = Object::cast_to<Control>(edited_object)->get_theme_font(SNAME("font"))->get_feature_list(); for (const Variant *ftr = features.next(nullptr); ftr != nullptr; ftr = features.next(ftr)) { String ftr_name = TS->tag_to_name(*ftr); if (ftr_name.begins_with("stylistic_set_")) { @@ -134,20 +143,11 @@ void OpenTypeFeaturesAdd::update_property() { } } -void OpenTypeFeaturesAdd::_features_menu() { - Size2 size = get_size(); - menu->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y)); - menu->reset_size(); - menu->popup(); -} - void OpenTypeFeaturesAdd::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_ENTER_TREE: { - set_label(""); - button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); - button->set_size(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))->get_size()); + set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); } break; } } @@ -156,6 +156,8 @@ void OpenTypeFeaturesAdd::_bind_methods() { } OpenTypeFeaturesAdd::OpenTypeFeaturesAdd() { + set_text(TTR("Add Feature...")); + menu = memnew(PopupMenu); add_child(menu); @@ -171,13 +173,7 @@ OpenTypeFeaturesAdd::OpenTypeFeaturesAdd() { menu_cu->set_name("CUMenu"); menu->add_child(menu_cu); - button = memnew(Button); - button->set_flat(true); - button->set_text(RTR("Add feature...")); - button->set_tooltip(RTR("Add feature...")); - add_child(button); - - button->connect("pressed", callable_mp(this, &OpenTypeFeaturesAdd::_features_menu)); + connect("pressed", callable_mp(this, &OpenTypeFeaturesAdd::_features_menu)); menu->connect("id_pressed", callable_mp(this, &OpenTypeFeaturesAdd::_add_feature)); menu_cv->connect("id_pressed", callable_mp(this, &OpenTypeFeaturesAdd::_add_feature)); menu_ss->connect("id_pressed", callable_mp(this, &OpenTypeFeaturesAdd::_add_feature)); @@ -193,7 +189,8 @@ bool EditorInspectorPluginOpenTypeFeatures::can_handle(Object *p_object) { bool EditorInspectorPluginOpenTypeFeatures::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { if (p_path == "opentype_features/_new") { OpenTypeFeaturesAdd *editor = memnew(OpenTypeFeaturesAdd); - add_property_editor(p_path, editor); + editor->setup(p_object); + add_custom_control(editor); return true; } else if (p_path.begins_with("opentype_features")) { OpenTypeFeaturesEditor *editor = memnew(OpenTypeFeaturesEditor); diff --git a/editor/plugins/ot_features_plugin.h b/editor/plugins/ot_features_plugin.h index 8c38d888de..fcbc8692ca 100644 --- a/editor/plugins/ot_features_plugin.h +++ b/editor/plugins/ot_features_plugin.h @@ -56,10 +56,10 @@ public: /*************************************************************************/ -class OpenTypeFeaturesAdd : public EditorProperty { - GDCLASS(OpenTypeFeaturesAdd, EditorProperty); +class OpenTypeFeaturesAdd : public Button { + GDCLASS(OpenTypeFeaturesAdd, Button); - Button *button = nullptr; + Object *edited_object = nullptr; PopupMenu *menu = nullptr; PopupMenu *menu_ss = nullptr; PopupMenu *menu_cv = nullptr; @@ -73,7 +73,7 @@ protected: static void _bind_methods(); public: - virtual void update_property() override; + void setup(Object *p_object); OpenTypeFeaturesAdd(); }; diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index d011d7a7e7..cd95f97286 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -2872,10 +2872,17 @@ ProjectManager::ProjectManager() { if (scale_factor > 1.0) { Vector2i window_size = DisplayServer::get_singleton()->window_get_size(); Vector2i screen_size = DisplayServer::get_singleton()->screen_get_size(); - window_size *= scale_factor; + Vector2i screen_position = DisplayServer::get_singleton()->screen_get_position(); + + // Consider the editor display scale. + window_size.x = round((float)window_size.x * scale_factor); + window_size.y = round((float)window_size.y * scale_factor); + + // Make the window centered on the screen. Vector2i window_position; - window_position.x = (screen_size.x - window_size.x) / 2; - window_position.y = (screen_size.y - window_size.y) / 2; + window_position.x = screen_position.x + (screen_size.x - window_size.x) / 2; + window_position.y = screen_position.y + (screen_size.y - window_size.y) / 2; + DisplayServer::get_singleton()->window_set_size(window_size); DisplayServer::get_singleton()->window_set_position(window_position); } diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index 3b8c540592..44eb5c670d 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -96,8 +96,8 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i if (n->is_class("CanvasItem") || n->is_class("Node3D")) { undo_redo->add_do_method(n, "remove_meta", "_edit_lock_"); undo_redo->add_undo_method(n, "set_meta", "_edit_lock_", true); - undo_redo->add_do_method(this, "_update_tree", Variant()); - undo_redo->add_undo_method(this, "_update_tree", Variant()); + undo_redo->add_do_method(this, "_update_tree"); + undo_redo->add_undo_method(this, "_update_tree"); undo_redo->add_do_method(this, "emit_signal", "node_changed"); undo_redo->add_undo_method(this, "emit_signal", "node_changed"); } @@ -114,8 +114,8 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i if (n->is_class("CanvasItem") || n->is_class("Node3D")) { undo_redo->add_do_method(n, "remove_meta", "_edit_group_"); undo_redo->add_undo_method(n, "set_meta", "_edit_group_", true); - undo_redo->add_do_method(this, "_update_tree", Variant()); - undo_redo->add_undo_method(this, "_update_tree", Variant()); + undo_redo->add_do_method(this, "_update_tree"); + undo_redo->add_undo_method(this, "_update_tree"); undo_redo->add_do_method(this, "emit_signal", "node_changed"); undo_redo->add_undo_method(this, "emit_signal", "node_changed"); } diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index baafef8639..72f77c859b 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -106,15 +106,7 @@ static Vector<String> _get_hierarchy(String p_class_name) { void ScriptCreateDialog::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: - case NOTIFICATION_THEME_CHANGED: { - for (int i = 0; i < ScriptServer::get_language_count(); i++) { - Ref<Texture2D> 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); - } - } - + case NOTIFICATION_ENTER_TREE: { 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++) { @@ -127,9 +119,15 @@ 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); + + [[fallthrough]]; + } + case NOTIFICATION_THEME_CHANGED: { + for (int i = 0; i < ScriptServer::get_language_count(); i++) { + Ref<Texture2D> 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); + } } path_button->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"))); @@ -332,13 +330,8 @@ void ScriptCreateDialog::_template_changed(int p_template) { 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); + // Save template info to editor dictionary (not a project template). + templates_dictionary[parent_name->get_text()] = sinfo.get_hash(); // 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())) { @@ -479,7 +472,6 @@ void ScriptCreateDialog::_built_in_pressed() { void ScriptCreateDialog::_use_template_pressed() { is_using_templates = use_templates->is_pressed(); - EditorSettings::get_singleton()->set_meta("script_setup/use_script_templates", is_using_templates); _update_dialog(); } @@ -597,10 +589,6 @@ void ScriptCreateDialog::_update_template_menu() { if (is_language_using_templates) { // Get the latest templates used for each type of node from project settings then global settings. Dictionary last_local_templates = EditorSettings::get_singleton()->get_project_metadata("script_setup", "templates_dictionary", Dictionary()); - Dictionary last_global_templates; - if (EditorSettings::get_singleton()->has_meta("script_setup/templates_dictionary")) { - last_global_templates = (Dictionary)EditorSettings::get_singleton()->get_meta("script_setup/templates_dictionary"); - } String inherits_base_type = parent_name->get_text(); // If it inherits from a script, get its parent class first. @@ -655,7 +643,7 @@ void ScriptCreateDialog::_update_template_menu() { // Check for last used template for this node in project settings then in global settings. if (last_local_templates.has(parent_name->get_text()) && t.get_hash() == String(last_local_templates[parent_name->get_text()])) { last_used_template = id; - } else if (last_used_template == -1 && last_global_templates.has(parent_name->get_text()) && t.get_hash() == String(last_global_templates[parent_name->get_text()])) { + } else if (last_used_template == -1 && templates_dictionary.has(parent_name->get_text()) && t.get_hash() == String(templates_dictionary[parent_name->get_text()])) { last_used_template = id; } t.id = id; diff --git a/editor/script_create_dialog.h b/editor/script_create_dialog.h index d7c43f322c..e9f634e2c0 100644 --- a/editor/script_create_dialog.h +++ b/editor/script_create_dialog.h @@ -83,6 +83,7 @@ class ScriptCreateDialog : public ConfirmationDialog { int current_language; int default_language; bool re_check_path = false; + Dictionary templates_dictionary; Control *path_controls[2]; Control *name_controls[2]; |