summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/SCsub2
-rw-r--r--editor/action_map_editor.cpp25
-rw-r--r--editor/editor_builders.py38
-rw-r--r--editor/editor_dir_dialog.cpp7
-rw-r--r--editor/editor_export.cpp40
-rw-r--r--editor/editor_export.h11
-rw-r--r--editor/editor_file_dialog.cpp16
-rw-r--r--editor/editor_inspector.cpp104
-rw-r--r--editor/editor_inspector.h12
-rw-r--r--editor/editor_resource_picker.cpp7
-rw-r--r--editor/editor_settings.cpp8
-rw-r--r--editor/editor_themes.cpp54
-rw-r--r--editor/filesystem_dock.cpp6
-rw-r--r--editor/groups_editor.cpp2
-rw-r--r--editor/icons/GuiTabDropMark.svg1
-rw-r--r--editor/import/editor_import_collada.cpp11
-rw-r--r--editor/inspector_dock.cpp1
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp8
-rw-r--r--editor/plugins/mesh_library_editor_plugin.cpp2
-rw-r--r--editor/plugins/ot_features_plugin.cpp39
-rw-r--r--editor/plugins/ot_features_plugin.h8
-rw-r--r--editor/project_manager.cpp13
22 files changed, 308 insertions, 107 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_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_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_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/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/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/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);
}