summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/config/project_settings.cpp12
-rw-r--r--core/core_bind.cpp34
-rw-r--r--core/core_constants.cpp1
-rw-r--r--core/io/dir_access.cpp6
-rw-r--r--core/io/dir_access.h2
-rw-r--r--core/io/logger.cpp10
-rw-r--r--core/io/resource_format_binary.cpp22
-rw-r--r--core/object/object.h1
-rw-r--r--core/os/os.cpp8
-rw-r--r--doc/classes/@GlobalScope.xml5
-rw-r--r--doc/classes/CompressedTexture2D.xml6
-rw-r--r--doc/classes/FontData.xml7
-rw-r--r--doc/classes/ProjectSettings.xml3
-rw-r--r--doc/classes/ResourceFormatLoader.xml2
-rw-r--r--doc/classes/TextServer.xml31
-rw-r--r--doc/classes/TextServerExtension.xml31
-rw-r--r--editor/animation_track_editor.cpp16
-rw-r--r--editor/animation_track_editor.h2
-rw-r--r--editor/animation_track_editor_plugins.cpp17
-rw-r--r--editor/animation_track_editor_plugins.h3
-rw-r--r--editor/dependency_editor.cpp3
-rw-r--r--editor/editor_asset_installer.cpp4
-rw-r--r--editor/editor_file_system.cpp3
-rw-r--r--editor/editor_fonts.cpp4
-rw-r--r--editor/editor_properties.cpp9
-rw-r--r--editor/editor_properties_array_dict.cpp232
-rw-r--r--editor/editor_properties_array_dict.h36
-rw-r--r--editor/editor_settings.cpp9
-rw-r--r--editor/export_template_manager.cpp3
-rw-r--r--editor/filesystem_dock.cpp31
-rw-r--r--editor/icons/CompressedTexture2D.svg (renamed from editor/icons/StreamTexture.svg)0
-rw-r--r--editor/import/dynamic_font_import_settings.cpp14
-rw-r--r--editor/import/resource_importer_dynamic_font.cpp6
-rw-r--r--editor/import/resource_importer_layered_texture.cpp16
-rw-r--r--editor/import/resource_importer_layered_texture.h2
-rw-r--r--editor/import/resource_importer_texture.cpp14
-rw-r--r--editor/import/resource_importer_texture.h4
-rw-r--r--editor/plugin_config_dialog.cpp2
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp5
-rw-r--r--editor/project_export.cpp2
-rw-r--r--editor/project_manager.cpp32
-rw-r--r--editor/script_create_dialog.cpp35
-rw-r--r--main/main.cpp12
-rw-r--r--misc/dist/osx_template.app/Contents/Info.plist2
-rw-r--r--misc/dist/osx_tools.app/Contents/Info.plist2
-rw-r--r--modules/csg/csg_shape.cpp6
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp3
-rw-r--r--modules/openxr/openxr_interface.cpp5
-rw-r--r--modules/text_server_adv/text_server_adv.cpp69
-rw-r--r--modules/text_server_adv/text_server_adv.h10
-rw-r--r--modules/text_server_fb/text_server_fb.cpp70
-rw-r--r--modules/text_server_fb/text_server_fb.h10
-rw-r--r--platform/android/export/export_plugin.cpp6
-rw-r--r--platform/android/export/gradle_export_util.cpp9
-rw-r--r--platform/iphone/export/export_plugin.cpp181
-rw-r--r--platform/iphone/os_iphone.mm4
-rw-r--r--platform/javascript/api/javascript_tools_editor_plugin.cpp2
-rw-r--r--platform/javascript/export/export_plugin.cpp22
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp3
-rw-r--r--platform/osx/export/codesign.cpp4
-rw-r--r--platform/osx/export/export_plugin.cpp118
-rw-r--r--scene/gui/file_dialog.h1
-rw-r--r--scene/resources/default_theme/default_theme.cpp37
-rw-r--r--scene/resources/default_theme/default_theme.h2
-rw-r--r--scene/resources/font.cpp42
-rw-r--r--scene/resources/font.h8
-rw-r--r--scene/resources/resource_format_text.cpp3
-rw-r--r--scene/resources/texture.cpp76
-rw-r--r--servers/text/text_server_extension.cpp30
-rw-r--r--servers/text/text_server_extension.h10
-rw-r--r--servers/text_server.cpp6
-rw-r--r--servers/text_server.h6
72 files changed, 1035 insertions, 409 deletions
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index 83f58311f1..93c1abe7b5 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -145,7 +145,7 @@ String ProjectSettings::localize_path(const String &p_path) const {
return p_path.simplify_path();
}
- DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
String path = p_path.replace("\\", "/").simplify_path();
@@ -153,8 +153,6 @@ String ProjectSettings::localize_path(const String &p_path) const {
String cwd = dir->get_current_dir();
cwd = cwd.replace("\\", "/");
- memdelete(dir);
-
// Ensure that we end with a '/'.
// This is important to ensure that we do not wrongly localize the resource path
// in an absolute path that just happens to contain this string but points to a
@@ -173,8 +171,6 @@ String ProjectSettings::localize_path(const String &p_path) const {
return cwd.replace_first(res_path, "res://");
} else {
- memdelete(dir);
-
int sep = path.rfind("/");
if (sep == -1) {
return "res://" + path;
@@ -541,7 +537,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
// Nothing was found, try to find a project file in provided path (`p_path`)
// or, if requested (`p_upwards`) in parent directories.
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
ERR_FAIL_COND_V_MSG(!d, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_path + "'.");
d->change_dir(p_path);
@@ -573,8 +569,6 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
}
}
- memdelete(d);
-
if (!found) {
return err;
}
@@ -1199,6 +1193,8 @@ ProjectSettings::ProjectSettings() {
singleton = this;
GLOBAL_DEF_BASIC("application/config/name", "");
+ GLOBAL_DEF_BASIC("application/config/name_localized", Dictionary());
+ custom_prop_info["application/config/name_localized"] = PropertyInfo(Variant::DICTIONARY, "application/config/name_localized", PROPERTY_HINT_LOCALIZABLE_STRING);
GLOBAL_DEF_BASIC("application/config/description", "");
custom_prop_info["application/config/description"] = PropertyInfo(Variant::STRING, "application/config/description", PROPERTY_HINT_MULTILINE_TEXT);
GLOBAL_DEF_BASIC("application/run/main_scene", "");
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index 590d1c12c6..2d0eaadbdf 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -1569,10 +1569,8 @@ String Directory::get_current_dir() {
Error Directory::make_dir(String p_dir) {
ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory is not configured properly.");
if (!p_dir.is_relative_path()) {
- DirAccess *d = DirAccess::create_for_path(p_dir);
- Error err = d->make_dir(p_dir);
- memdelete(d);
- return err;
+ DirAccessRef da = DirAccess::create_for_path(p_dir);
+ return da->make_dir(p_dir);
}
return d->make_dir(p_dir);
}
@@ -1580,10 +1578,8 @@ Error Directory::make_dir(String p_dir) {
Error Directory::make_dir_recursive(String p_dir) {
ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory is not configured properly.");
if (!p_dir.is_relative_path()) {
- DirAccess *d = DirAccess::create_for_path(p_dir);
- Error err = d->make_dir_recursive(p_dir);
- memdelete(d);
- return err;
+ DirAccessRef da = DirAccess::create_for_path(p_dir);
+ return da->make_dir_recursive(p_dir);
}
return d->make_dir_recursive(p_dir);
}
@@ -1593,19 +1589,14 @@ bool Directory::file_exists(String p_file) {
if (!p_file.is_relative_path()) {
return FileAccess::exists(p_file);
}
-
return d->file_exists(p_file);
}
bool Directory::dir_exists(String p_dir) {
ERR_FAIL_COND_V_MSG(!d, false, "Directory is not configured properly.");
if (!p_dir.is_relative_path()) {
- DirAccess *d = DirAccess::create_for_path(p_dir);
- bool exists = d->dir_exists(p_dir);
- memdelete(d);
- return exists;
+ return DirAccess::exists(p_dir);
}
-
return d->dir_exists(p_dir);
}
@@ -1624,11 +1615,9 @@ Error Directory::rename(String p_from, String p_to) {
ERR_FAIL_COND_V_MSG(p_from.is_empty() || p_from == "." || p_from == "..", ERR_INVALID_PARAMETER, "Invalid path to rename.");
if (!p_from.is_relative_path()) {
- DirAccess *d = DirAccess::create_for_path(p_from);
- ERR_FAIL_COND_V_MSG(!d->file_exists(p_from) && !d->dir_exists(p_from), ERR_DOES_NOT_EXIST, "File or directory does not exist.");
- Error err = d->rename(p_from, p_to);
- memdelete(d);
- return err;
+ DirAccessRef da = DirAccess::create_for_path(p_from);
+ ERR_FAIL_COND_V_MSG(!da->file_exists(p_from) && !da->dir_exists(p_from), ERR_DOES_NOT_EXIST, "File or directory does not exist.");
+ return da->rename(p_from, p_to);
}
ERR_FAIL_COND_V_MSG(!d->file_exists(p_from) && !d->dir_exists(p_from), ERR_DOES_NOT_EXIST, "File or directory does not exist.");
@@ -1638,10 +1627,8 @@ Error Directory::rename(String p_from, String p_to) {
Error Directory::remove(String p_name) {
ERR_FAIL_COND_V_MSG(!is_open(), ERR_UNCONFIGURED, "Directory must be opened before use.");
if (!p_name.is_relative_path()) {
- DirAccess *d = DirAccess::create_for_path(p_name);
- Error err = d->remove(p_name);
- memdelete(d);
- return err;
+ DirAccessRef da = DirAccess::create_for_path(p_name);
+ return da->remove(p_name);
}
return d->remove(p_name);
@@ -1664,7 +1651,6 @@ void Directory::_bind_methods() {
ClassDB::bind_method(D_METHOD("make_dir_recursive", "path"), &Directory::make_dir_recursive);
ClassDB::bind_method(D_METHOD("file_exists", "path"), &Directory::file_exists);
ClassDB::bind_method(D_METHOD("dir_exists", "path"), &Directory::dir_exists);
- //ClassDB::bind_method(D_METHOD("get_modified_time","file"),&Directory::get_modified_time);
ClassDB::bind_method(D_METHOD("get_space_left"), &Directory::get_space_left);
ClassDB::bind_method(D_METHOD("copy", "from", "to"), &Directory::copy);
ClassDB::bind_method(D_METHOD("rename", "from", "to"), &Directory::rename);
diff --git a/core/core_constants.cpp b/core/core_constants.cpp
index 89926ee81b..98b720ab65 100644
--- a/core/core_constants.cpp
+++ b/core/core_constants.cpp
@@ -591,6 +591,7 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_INT_IS_POINTER);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ARRAY_TYPE);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LOCALE_ID);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LOCALIZABLE_STRING);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_MAX);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NONE);
diff --git a/core/io/dir_access.cpp b/core/io/dir_access.cpp
index 86d8dea3d9..840f236708 100644
--- a/core/io/dir_access.cpp
+++ b/core/io/dir_access.cpp
@@ -414,8 +414,6 @@ Error DirAccess::copy_dir(String p_from, String p_to, int p_chmod_flags, bool p_
}
bool DirAccess::exists(String p_dir) {
- DirAccess *da = DirAccess::create_for_path(p_dir);
- bool valid = da->change_dir(p_dir) == OK;
- memdelete(da);
- return valid;
+ DirAccessRef da = DirAccess::create_for_path(p_dir);
+ return da->change_dir(p_dir) == OK;
}
diff --git a/core/io/dir_access.h b/core/io/dir_access.h
index 8154f5366c..d63453e947 100644
--- a/core/io/dir_access.h
+++ b/core/io/dir_access.h
@@ -134,7 +134,7 @@ struct DirAccessRef {
operator bool() const { return f != nullptr; }
- DirAccess *f;
+ DirAccess *f = nullptr;
DirAccessRef(DirAccess *fa) { f = fa; }
~DirAccessRef() {
diff --git a/core/io/logger.cpp b/core/io/logger.cpp
index cb6369ae3d..2b6f230434 100644
--- a/core/io/logger.cpp
+++ b/core/io/logger.cpp
@@ -128,7 +128,7 @@ void RotatedFileLogger::clear_old_backups() {
String basename = base_path.get_file().get_basename();
String extension = base_path.get_extension();
- DirAccess *da = DirAccess::open(base_path.get_base_dir());
+ DirAccessRef da = DirAccess::open(base_path.get_base_dir());
if (!da) {
return;
}
@@ -152,8 +152,6 @@ void RotatedFileLogger::clear_old_backups() {
da->remove(E->get());
}
}
-
- memdelete(da);
}
void RotatedFileLogger::rotate_file() {
@@ -167,18 +165,16 @@ void RotatedFileLogger::rotate_file() {
backup_name += "." + base_path.get_extension();
}
- DirAccess *da = DirAccess::open(base_path.get_base_dir());
+ DirAccessRef da = DirAccess::open(base_path.get_base_dir());
if (da) {
da->copy(base_path, backup_name);
- memdelete(da);
}
clear_old_backups();
}
} else {
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_USERDATA);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_USERDATA);
if (da) {
da->make_dir_recursive(base_path.get_base_dir());
- memdelete(da);
}
}
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index ee59a916f1..b65993e3dd 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -1032,7 +1032,6 @@ RES ResourceFormatLoaderBinary::load(const String &p_path, const String &p_origi
String path = !p_original_path.is_empty() ? p_original_path : p_path;
loader.local_path = ProjectSettings::get_singleton()->localize_path(path);
loader.res_path = loader.local_path;
- //loader.set_local_path( Globals::get_singleton()->localize_path(p_path) );
loader.open(f);
err = loader.load();
@@ -1086,17 +1085,14 @@ void ResourceFormatLoaderBinary::get_dependencies(const String &p_path, List<Str
ResourceLoaderBinary loader;
loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
loader.res_path = loader.local_path;
- //loader.set_local_path( Globals::get_singleton()->localize_path(p_path) );
loader.get_dependencies(f, p_dependencies, p_add_types);
}
Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, const Map<String, String> &p_map) {
- //Error error=OK;
-
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot open file '" + p_path + "'.");
- FileAccess *fw = nullptr; //=FileAccess::open(p_path+".depren");
+ FileAccess *fw = nullptr;
String local_path = p_path.get_base_dir();
@@ -1158,10 +1154,12 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
if (ver_format < FORMAT_VERSION_CAN_RENAME_DEPS) {
memdelete(f);
memdelete(fw);
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- da->remove(p_path + ".depren");
- memdelete(da);
- //use the old approach
+ {
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ da->remove(p_path + ".depren");
+ }
+
+ // Use the old approach.
WARN_PRINT("This file is old, so it can't refactor dependencies, opening and resaving '" + p_path + "'.");
@@ -1174,7 +1172,6 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
loader.res_path = loader.local_path;
loader.remaps = p_map;
- //loader.set_local_path( Globals::get_singleton()->localize_path(p_path) );
loader.open(f);
err = loader.load();
@@ -1304,10 +1301,9 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
return ERR_CANT_CREATE;
}
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
da->remove(p_path);
da->rename(p_path + ".depren", p_path);
- memdelete(da);
return OK;
}
@@ -1320,7 +1316,6 @@ String ResourceFormatLoaderBinary::get_resource_type(const String &p_path) const
ResourceLoaderBinary loader;
loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
loader.res_path = loader.local_path;
- //loader.set_local_path( Globals::get_singleton()->localize_path(p_path) );
String r = loader.recognize(f);
return ClassDB::get_compatibility_remapped_class(r);
}
@@ -1339,7 +1334,6 @@ ResourceUID::ID ResourceFormatLoaderBinary::get_resource_uid(const String &p_pat
ResourceLoaderBinary loader;
loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
loader.res_path = loader.local_path;
- //loader.set_local_path( Globals::get_singleton()->localize_path(p_path) );
loader.open(f, true);
if (loader.error != OK) {
return ResourceUID::INVALID_ID; //could not read
diff --git a/core/object/object.h b/core/object/object.h
index 3aa7e3f9f2..6b4f1c81e6 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -88,6 +88,7 @@ enum PropertyHint {
PROPERTY_HINT_ARRAY_TYPE,
PROPERTY_HINT_INT_IS_POINTER,
PROPERTY_HINT_LOCALE_ID,
+ PROPERTY_HINT_LOCALIZABLE_STRING,
PROPERTY_HINT_MAX,
// When updating PropertyHint, also sync the hardcoded list in VisualScriptEditorVariableEdit
};
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 9837b6e0aa..2e5db145a4 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -328,17 +328,13 @@ void OS::yield() {
void OS::ensure_user_data_dir() {
String dd = get_user_data_dir();
- DirAccess *da = DirAccess::open(dd);
- if (da) {
- memdelete(da);
+ if (DirAccess::exists(dd)) {
return;
}
- da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
Error err = da->make_dir_recursive(dd);
ERR_FAIL_COND_MSG(err != OK, "Error attempting to create data dir: " + dd + ".");
-
- memdelete(da);
}
String OS::get_model_name() const {
diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml
index 1228cd771c..f692a49ba1 100644
--- a/doc/classes/@GlobalScope.xml
+++ b/doc/classes/@GlobalScope.xml
@@ -2516,7 +2516,10 @@
<constant name="PROPERTY_HINT_LOCALE_ID" value="41" enum="PropertyHint">
Hints that a string property is a locale code. Editing it will show a locale dialog for picking language and country.
</constant>
- <constant name="PROPERTY_HINT_MAX" value="42" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_LOCALIZABLE_STRING" value="42" enum="PropertyHint">
+ Hints that a dictionary property is string translation map. Dictionary keys are locale codes and, values are translated strings.
+ </constant>
+ <constant name="PROPERTY_HINT_MAX" value="43" enum="PropertyHint">
</constant>
<constant name="PROPERTY_USAGE_NONE" value="0" enum="PropertyUsageFlags">
</constant>
diff --git a/doc/classes/CompressedTexture2D.xml b/doc/classes/CompressedTexture2D.xml
index c99fcf2280..5f73b55f69 100644
--- a/doc/classes/CompressedTexture2D.xml
+++ b/doc/classes/CompressedTexture2D.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CompressedTexture2D" inherits="Texture2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
- A [code].stex[/code] texture.
+ A [code].ctex[/code] texture.
</brief_description>
<description>
- A texture that is loaded from a [code].stex[/code] file.
+ A texture that is loaded from a [code].ctex[/code] file.
</description>
<tutorials>
</tutorials>
@@ -19,7 +19,7 @@
</methods>
<members>
<member name="load_path" type="String" setter="load" getter="get_load_path" default="&quot;&quot;">
- The CompressedTexture's file path to a [code].stex[/code] file.
+ The CompressedTexture's file path to a [code].ctex[/code] file.
</member>
</members>
</class>
diff --git a/doc/classes/FontData.xml b/doc/classes/FontData.xml
index ccaefc60ee..9344a1fe80 100644
--- a/doc/classes/FontData.xml
+++ b/doc/classes/FontData.xml
@@ -567,6 +567,9 @@
<member name="data" type="PackedByteArray" setter="set_data" getter="get_data" default="PackedByteArray()">
Contents of the dynamic font source file.
</member>
+ <member name="embolden" type="float" setter="set_embolden" getter="get_embolden" default="0.0">
+ If is not equal to zero, emboldens the font outlines. Negative values reduce the outline thickness.
+ </member>
<member name="fixed_size" type="int" setter="set_fixed_size" getter="get_fixed_size" default="0">
Font size, used only for the bitmap fonts.
</member>
@@ -603,5 +606,9 @@
<member name="subpixel_positioning" type="int" setter="set_subpixel_positioning" getter="get_subpixel_positioning" enum="TextServer.SubpixelPositioning" default="1">
Font glyph sub-pixel positioning mode. Subpixel positioning provides shaper text and better kerning for smaller font sizes, at the cost of memory usage and font rasterization speed. Use [constant TextServer.SUBPIXEL_POSITIONING_AUTO] to automatically enable it based on the font size.
</member>
+ <member name="transform" type="Transform2D" setter="set_transform" getter="get_transform" default="Transform2D(1, 0, 0, 1, 0, 0)">
+ 2D transform, applied to the font outlines, can be used for slanting, flipping and rotating glyphs.
+ For example, to simulate italic typeface by slanting, apply the following transform [code]Transform2D(1.0, slant, 0.0, 1.0, 0.0, 0.0)[/code].
+ </member>
</members>
</class>
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 701e947fd1..068b2c7757 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -226,6 +226,9 @@
The project's name. It is used both by the Project Manager and by exporters. The project name can be translated by translating its value in localization files. The window title will be set to match the project name automatically on startup.
[b]Note:[/b] Changing this value will also change the user data folder's path if [member application/config/use_custom_user_dir] is [code]false[/code]. After renaming the project, you will no longer be able to access existing data in [code]user://[/code] unless you rename the old folder to match the new project name. See [url=$DOCS_URL/tutorials/io/data_paths.html]Data paths[/url] in the documentation for more information.
</member>
+ <member name="application/config/name_localized" type="Dictionary" setter="" getter="" default="{}">
+ Translations of the project's name. This setting is used by OS tools to translate application name on Android, iOS and macOS.
+ </member>
<member name="application/config/project_settings_override" type="String" setter="" getter="" default="&quot;&quot;">
Specifies a file to override project settings. For example: [code]user://custom_settings.cfg[/code]. See "Overriding" in the [ProjectSettings] class description at the top for more information.
[b]Note:[/b] Regardless of this setting's value, [code]res://override.cfg[/code] will still be read to override the project settings.
diff --git a/doc/classes/ResourceFormatLoader.xml b/doc/classes/ResourceFormatLoader.xml
index 983a05800f..36b64f5a86 100644
--- a/doc/classes/ResourceFormatLoader.xml
+++ b/doc/classes/ResourceFormatLoader.xml
@@ -6,7 +6,7 @@
<description>
Godot loads resources in the editor or in exported games using ResourceFormatLoaders. They are queried automatically via the [ResourceLoader] singleton, or when a resource with internal dependencies is loaded. Each file type may load as a different resource type, so multiple ResourceFormatLoaders are registered in the engine.
Extending this class allows you to define your own loader. Be sure to respect the documented return types and values. You should give it a global class name with [code]class_name[/code] for it to be registered. Like built-in ResourceFormatLoaders, it will be called automatically when loading resources of its handled type(s). You may also implement a [ResourceFormatSaver].
- [b]Note:[/b] You can also extend [EditorImportPlugin] if the resource type you need exists but Godot is unable to load its format. Choosing one way over another depends on if the format is suitable or not for the final exported game. For example, it's better to import [code].png[/code] textures as [code].stex[/code] ([CompressedTexture2D]) first, so they can be loaded with better efficiency on the graphics card.
+ [b]Note:[/b] You can also extend [EditorImportPlugin] if the resource type you need exists but Godot is unable to load its format. Choosing one way over another depends on if the format is suitable or not for the final exported game. For example, it's better to import [code].png[/code] textures as [code].ctex[/code] ([CompressedTexture2D]) first, so they can be loaded with better efficiency on the graphics card.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml
index 3157eea436..020c30b9cd 100644
--- a/doc/classes/TextServer.xml
+++ b/doc/classes/TextServer.xml
@@ -112,6 +112,13 @@
Returns the font descent (number of pixels below the baseline).
</description>
</method>
+ <method name="font_get_embolden" qualifiers="const">
+ <return type="float" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns font embolden strength.
+ </description>
+ </method>
<method name="font_get_fixed_size" qualifiers="const">
<return type="int" />
<argument index="0" name="font_rid" type="RID" />
@@ -368,6 +375,13 @@
Returns array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty.
</description>
</method>
+ <method name="font_get_transform" qualifiers="const">
+ <return type="Transform2D" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns 2D transform applied to the font outlines.
+ </description>
+ </method>
<method name="font_get_underline_position" qualifiers="const">
<return type="float" />
<argument index="0" name="font_rid" type="RID" />
@@ -542,6 +556,14 @@
Sets the font descent (number of pixels below the baseline).
</description>
</method>
+ <method name="font_set_embolden">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="strength" type="float" />
+ <description>
+ Sets font embolden strength. If [code]strength[/code] is not equal to zero, emboldens the font outlines. Negative values reduce the outline thickness.
+ </description>
+ </method>
<method name="font_set_fixed_size">
<return type="void" />
<argument index="0" name="font_rid" type="RID" />
@@ -765,6 +787,15 @@
Sets array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty.
</description>
</method>
+ <method name="font_set_transform">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="transform" type="Transform2D" />
+ <description>
+ Sets 2D transform, applied to the font outlines, can be used for slanting, flipping and rotating glyphs.
+ For example, to simulate italic typeface by slanting, apply the following transform [code]Transform2D(1.0, slant, 0.0, 1.0, 0.0, 0.0)[/code].
+ </description>
+ </method>
<method name="font_set_underline_position">
<return type="void" />
<argument index="0" name="font_rid" type="RID" />
diff --git a/doc/classes/TextServerExtension.xml b/doc/classes/TextServerExtension.xml
index f730f28e79..5ffd80bf63 100644
--- a/doc/classes/TextServerExtension.xml
+++ b/doc/classes/TextServerExtension.xml
@@ -112,6 +112,13 @@
Returns the font descent (number of pixels below the baseline).
</description>
</method>
+ <method name="_font_get_embolden" qualifiers="virtual const">
+ <return type="float" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns font embolden strength.
+ </description>
+ </method>
<method name="_font_get_fixed_size" qualifiers="virtual const">
<return type="int" />
<argument index="0" name="font_rid" type="RID" />
@@ -368,6 +375,13 @@
Returns array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty.
</description>
</method>
+ <method name="_font_get_transform" qualifiers="virtual const">
+ <return type="Transform2D" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Retruns 2D transform applied to the font outlines.
+ </description>
+ </method>
<method name="_font_get_underline_position" qualifiers="virtual const">
<return type="float" />
<argument index="0" name="font_rid" type="RID" />
@@ -551,6 +565,14 @@
Sets bitmap font fixed size. If set to value greater than zero, same cache entry will be used for all font sizes.
</description>
</method>
+ <method name="_font_set_embolden" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="strength" type="float" />
+ <description>
+ Sets font embolden strength. If [code]strength[/code] is not equal to zero, emboldens the font outlines. Negative values reduce the outline thickness.
+ </description>
+ </method>
<method name="_font_set_fixed_size" qualifiers="virtual">
<return type="void" />
<argument index="0" name="font_rid" type="RID" />
@@ -773,6 +795,15 @@
Sets array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty.
</description>
</method>
+ <method name="_font_set_transform" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="transform" type="Transform2D" />
+ <description>
+ Sets 2D transform, applied to the font outlines, can be used for slanting, flipping and rotating glyphs.
+ For example, to simulate italic typeface by slanting, apply the following transform [code]Transform2D(1.0, slant, 0.0, 1.0, 0.0, 0.0)[/code].
+ </description>
+ </method>
<method name="_font_set_underline_position" qualifiers="virtual">
<return type="void" />
<argument index="0" name="font_rid" type="RID" />
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 11995e8cb4..af25403736 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -1814,13 +1814,6 @@ void AnimationTimelineEdit::gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseMotion> mm = p_event;
if (mm.is_valid()) {
- if (hsize_rect.has_point(mm->get_position())) {
- // Change the cursor to indicate that the track name column's width can be adjusted
- set_default_cursor_shape(Control::CURSOR_HSIZE);
- } else {
- set_default_cursor_shape(Control::CURSOR_ARROW);
- }
-
if (dragging_hsize) {
int ofs = mm->get_position().x - dragging_hsize_from;
name_limit = dragging_hsize_at + ofs;
@@ -1836,6 +1829,15 @@ void AnimationTimelineEdit::gui_input(const Ref<InputEvent> &p_event) {
}
}
+Control::CursorShape AnimationTimelineEdit::get_cursor_shape(const Point2 &p_pos) const {
+ if (dragging_hsize || hsize_rect.has_point(p_pos)) {
+ // Indicate that the track name column's width can be adjusted
+ return Control::CURSOR_HSIZE;
+ } else {
+ return get_default_cursor_shape();
+ }
+}
+
void AnimationTimelineEdit::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) {
// Timeline has no vertical scroll, so we change it to horizontal.
p_scroll_vec.x += p_scroll_vec.y;
diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h
index 5f803ae796..ab3a6f682a 100644
--- a/editor/animation_track_editor.h
+++ b/editor/animation_track_editor.h
@@ -121,6 +121,8 @@ public:
void set_hscroll(HScrollBar *p_hscroll);
+ virtual CursorShape get_cursor_shape(const Point2 &p_pos) const override;
+
AnimationTimelineEdit();
};
diff --git a/editor/animation_track_editor_plugins.cpp b/editor/animation_track_editor_plugins.cpp
index e87678a51b..9fd42a8ab8 100644
--- a/editor/animation_track_editor_plugins.cpp
+++ b/editor/animation_track_editor_plugins.cpp
@@ -1080,12 +1080,7 @@ void AnimationTrackEditTypeAudio::gui_input(const Ref<InputEvent> &p_event) {
len_resizing_index = i;
}
}
-
- if (use_hsize_cursor) {
- set_default_cursor_shape(CURSOR_HSIZE);
- } else {
- set_default_cursor_shape(CURSOR_ARROW);
- }
+ over_drag_position = use_hsize_cursor;
}
if (len_resizing && mm.is_valid()) {
@@ -1097,7 +1092,7 @@ void AnimationTrackEditTypeAudio::gui_input(const Ref<InputEvent> &p_event) {
}
Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT && get_default_cursor_shape() == CURSOR_HSIZE) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT && over_drag_position) {
len_resizing = true;
len_resizing_start = mb->is_shift_pressed();
len_resizing_from_px = mb->get_position().x;
@@ -1134,6 +1129,14 @@ void AnimationTrackEditTypeAudio::gui_input(const Ref<InputEvent> &p_event) {
AnimationTrackEdit::gui_input(p_event);
}
+Control::CursorShape AnimationTrackEditTypeAudio::get_cursor_shape(const Point2 &p_pos) const {
+ if (over_drag_position || len_resizing) {
+ return Control::CURSOR_HSIZE;
+ } else {
+ return get_default_cursor_shape();
+ }
+}
+
////////////////////
/// SUB ANIMATION ///
diff --git a/editor/animation_track_editor_plugins.h b/editor/animation_track_editor_plugins.h
index 271c1a000b..7022f524c5 100644
--- a/editor/animation_track_editor_plugins.h
+++ b/editor/animation_track_editor_plugins.h
@@ -119,6 +119,7 @@ class AnimationTrackEditTypeAudio : public AnimationTrackEdit {
int len_resizing_index;
float len_resizing_from_px;
float len_resizing_rel;
+ bool over_drag_position = false;
protected:
static void _bind_methods();
@@ -134,6 +135,8 @@ public:
virtual bool is_key_selectable_by_distance() const override;
virtual void draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right) override;
+ virtual CursorShape get_cursor_shape(const Point2 &p_pos) const override;
+
AnimationTrackEditTypeAudio();
};
diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp
index 1802bdec93..95b3a02631 100644
--- a/editor/dependency_editor.cpp
+++ b/editor/dependency_editor.cpp
@@ -749,12 +749,11 @@ void OrphanResourcesDialog::_find_to_delete(TreeItem *p_item, List<String> &path
}
void OrphanResourcesDialog::_delete_confirm() {
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
for (const String &E : paths) {
da->remove(E);
EditorFileSystem::get_singleton()->update_file(E);
}
- memdelete(da);
refresh();
}
diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp
index 3835399c99..4a51f7c6c2 100644
--- a/editor/editor_asset_installer.cpp
+++ b/editor/editor_asset_installer.cpp
@@ -277,10 +277,8 @@ void EditorAssetInstaller::ok_pressed() {
dirpath = dirpath.substr(0, dirpath.length() - 1);
}
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
da->make_dir(dirpath);
- memdelete(da);
-
} else {
Vector<uint8_t> data;
data.resize(info.uncompressed_size);
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index 0c46cebec0..45362896ca 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -1094,12 +1094,11 @@ void EditorFileSystem::_delete_internal_files(String p_file) {
if (FileAccess::exists(p_file + ".import")) {
List<String> paths;
ResourceFormatImporter::get_singleton()->get_internal_resource_path_list(p_file, &paths);
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
for (const String &E : paths) {
da->remove(E);
}
da->remove(p_file + ".import");
- memdelete(da);
}
}
diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp
index d80ee1d569..853278c5fc 100644
--- a/editor/editor_fonts.cpp
+++ b/editor/editor_fonts.cpp
@@ -174,7 +174,7 @@ Ref<FontData> load_cached_internal_font(const uint8_t *p_data, size_t p_size, Te
}
void editor_register_fonts(Ref<Theme> p_theme) {
- DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
/* Custom font */
@@ -236,8 +236,6 @@ void editor_register_fonts(Ref<Theme> p_theme) {
EditorSettings::get_singleton()->set_manually("interface/editor/code_font", "");
}
- memdelete(dir);
-
/* Noto Sans */
Ref<FontData> DefaultFont = load_cached_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index 1a4d507eef..4b07897459 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -3738,8 +3738,13 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
} break;
case Variant::DICTIONARY: {
- EditorPropertyDictionary *editor = memnew(EditorPropertyDictionary);
- return editor;
+ if (p_hint == PROPERTY_HINT_LOCALIZABLE_STRING) {
+ EditorPropertyLocalizableString *editor = memnew(EditorPropertyLocalizableString);
+ return editor;
+ } else {
+ EditorPropertyDictionary *editor = memnew(EditorPropertyDictionary);
+ return editor;
+ }
} break;
case Variant::ARRAY: {
EditorPropertyArray *editor = memnew(EditorPropertyArray);
diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
index d354be9af5..533ecc196f 100644
--- a/editor/editor_properties_array_dict.cpp
+++ b/editor/editor_properties_array_dict.cpp
@@ -742,7 +742,7 @@ void EditorPropertyDictionary::_property_changed(const String &p_property, Varia
emit_changed(get_edited_property(), dict, "", true);
- dict = dict.duplicate(); // Duplicate, so undo/redo works better\.
+ dict = dict.duplicate(); // Duplicate, so undo/redo works better.
object->set_dict(dict);
}
}
@@ -805,7 +805,7 @@ void EditorPropertyDictionary::_change_type_menu(int p_index) {
emit_changed(get_edited_property(), dict, "", false);
- dict = dict.duplicate(); // Duplicate, so undo/redo works better\.
+ dict = dict.duplicate(); // Duplicate, so undo/redo works better.
object->set_dict(dict);
update_property();
}
@@ -814,7 +814,7 @@ void EditorPropertyDictionary::update_property() {
Variant updated_val = get_edited_object()->get(get_edited_property());
if (updated_val.get_type() == Variant::NIL) {
- edit->set_text("Dictionary (Nil)"); // This provides symmetry with the array property.
+ edit->set_text(TTR("Dictionary (Nil)")); // This provides symmetry with the array property.
edit->set_pressed(false);
if (vbox) {
set_bottom_editor(nullptr);
@@ -826,7 +826,7 @@ void EditorPropertyDictionary::update_property() {
Dictionary dict = updated_val;
- edit->set_text("Dictionary (size " + itos(dict.size()) + ")");
+ edit->set_text(vformat(TTR("Dictionary (size %d)"), dict.size()));
bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property());
if (edit->is_pressed() != unfolded) {
@@ -1144,6 +1144,7 @@ void EditorPropertyDictionary::update_property() {
if (vbox) {
set_bottom_editor(nullptr);
memdelete(vbox);
+ button_add_item = nullptr;
vbox = nullptr;
}
}
@@ -1216,3 +1217,226 @@ EditorPropertyDictionary::EditorPropertyDictionary() {
change_type->connect("id_pressed", callable_mp(this, &EditorPropertyDictionary::_change_type_menu));
changing_type_index = -1;
}
+
+///////////////////// LOCALIZABLE STRING ///////////////////////////
+
+void EditorPropertyLocalizableString::_property_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) {
+ if (p_property.begins_with("indices")) {
+ int index = p_property.get_slice("/", 1).to_int();
+ Dictionary dict = object->get_dict();
+ Variant key = dict.get_key_at_index(index);
+ dict[key] = p_value;
+
+ emit_changed(get_edited_property(), dict, "", true);
+
+ dict = dict.duplicate(); // Duplicate, so undo/redo works better.
+ object->set_dict(dict);
+ }
+}
+
+void EditorPropertyLocalizableString::_add_locale_popup() {
+ locale_select->popup_locale_dialog();
+}
+
+void EditorPropertyLocalizableString::_add_locale(const String &p_locale) {
+ Dictionary dict = object->get_dict();
+
+ object->set_new_item_key(p_locale);
+ object->set_new_item_value(String());
+ dict[object->get_new_item_key()] = object->get_new_item_value();
+
+ emit_changed(get_edited_property(), dict, "", false);
+
+ dict = dict.duplicate(); // Duplicate, so undo/redo works better.
+ object->set_dict(dict);
+ update_property();
+}
+
+void EditorPropertyLocalizableString::_remove_item(Object *p_button, int p_index) {
+ Dictionary dict = object->get_dict();
+
+ Variant key = dict.get_key_at_index(p_index);
+ dict.erase(key);
+
+ emit_changed(get_edited_property(), dict, "", false);
+
+ dict = dict.duplicate(); // Duplicate, so undo/redo works better.
+ object->set_dict(dict);
+ update_property();
+}
+
+void EditorPropertyLocalizableString::update_property() {
+ Variant updated_val = get_edited_object()->get(get_edited_property());
+
+ if (updated_val.get_type() == Variant::NIL) {
+ edit->set_text(TTR("Localizable String (Nil)")); // This provides symmetry with the array property.
+ edit->set_pressed(false);
+ if (vbox) {
+ set_bottom_editor(nullptr);
+ memdelete(vbox);
+ vbox = nullptr;
+ }
+ return;
+ }
+
+ Dictionary dict = updated_val;
+
+ edit->set_text(vformat(TTR("Localizable String (size %d)"), dict.size()));
+
+ bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property());
+ if (edit->is_pressed() != unfolded) {
+ edit->set_pressed(unfolded);
+ }
+
+ if (unfolded) {
+ updating = true;
+
+ if (!vbox) {
+ vbox = memnew(VBoxContainer);
+ add_child(vbox);
+ set_bottom_editor(vbox);
+
+ property_vbox = memnew(VBoxContainer);
+ property_vbox->set_h_size_flags(SIZE_EXPAND_FILL);
+ vbox->add_child(property_vbox);
+
+ paginator = memnew(EditorPaginator);
+ paginator->connect("page_changed", callable_mp(this, &EditorPropertyLocalizableString::_page_changed));
+ vbox->add_child(paginator);
+ } else {
+ // Queue children for deletion, deleting immediately might cause errors.
+ for (int i = property_vbox->get_child_count() - 1; i >= 0; i--) {
+ property_vbox->get_child(i)->queue_delete();
+ }
+ }
+
+ int size = dict.size();
+
+ int max_page = MAX(0, size - 1) / page_length;
+ page_index = MIN(page_index, max_page);
+
+ paginator->update(page_index, max_page);
+ paginator->set_visible(max_page > 0);
+
+ int offset = page_index * page_length;
+
+ int amount = MIN(size - offset, page_length);
+
+ dict = dict.duplicate();
+
+ object->set_dict(dict);
+
+ for (int i = 0; i < amount; i++) {
+ String prop_name;
+ Variant key;
+ Variant value;
+
+ prop_name = "indices/" + itos(i + offset);
+ key = dict.get_key_at_index(i + offset);
+ value = dict.get_value_at_index(i + offset);
+
+ EditorProperty *prop = memnew(EditorPropertyText);
+
+ prop->set_object_and_property(object.ptr(), prop_name);
+ int remove_index = 0;
+
+ String cs = key.get_construct_string();
+ prop->set_label(cs);
+ prop->set_tooltip(cs);
+ remove_index = i + offset;
+
+ prop->set_selectable(false);
+ prop->connect("property_changed", callable_mp(this, &EditorPropertyLocalizableString::_property_changed));
+ prop->connect("object_id_selected", callable_mp(this, &EditorPropertyLocalizableString::_object_id_selected));
+
+ HBoxContainer *hbox = memnew(HBoxContainer);
+ property_vbox->add_child(hbox);
+ hbox->add_child(prop);
+ prop->set_h_size_flags(SIZE_EXPAND_FILL);
+ Button *edit = memnew(Button);
+ edit->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
+ hbox->add_child(edit);
+ edit->connect("pressed", callable_mp(this, &EditorPropertyLocalizableString::_remove_item), varray(edit, remove_index));
+
+ prop->update_property();
+ }
+
+ if (page_index == max_page) {
+ button_add_item = memnew(Button);
+ button_add_item->set_text(TTR("Add Translation"));
+ button_add_item->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
+ button_add_item->connect("pressed", callable_mp(this, &EditorPropertyLocalizableString::_add_locale_popup));
+ property_vbox->add_child(button_add_item);
+ }
+
+ updating = false;
+
+ } else {
+ if (vbox) {
+ set_bottom_editor(nullptr);
+ memdelete(vbox);
+ button_add_item = nullptr;
+ vbox = nullptr;
+ }
+ }
+}
+
+void EditorPropertyLocalizableString::_object_id_selected(const StringName &p_property, ObjectID p_id) {
+ emit_signal(SNAME("object_id_selected"), p_property, p_id);
+}
+
+void EditorPropertyLocalizableString::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_THEME_CHANGED:
+ case NOTIFICATION_ENTER_TREE: {
+ if (Object::cast_to<Button>(button_add_item)) {
+ button_add_item->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
+ }
+ } break;
+ }
+}
+
+void EditorPropertyLocalizableString::_edit_pressed() {
+ Variant prop_val = get_edited_object()->get(get_edited_property());
+ if (prop_val.get_type() == Variant::NIL) {
+ Callable::CallError ce;
+ Variant::construct(Variant::DICTIONARY, prop_val, nullptr, 0, ce);
+ get_edited_object()->set(get_edited_property(), prop_val);
+ }
+
+ get_edited_object()->editor_set_section_unfold(get_edited_property(), edit->is_pressed());
+ update_property();
+}
+
+void EditorPropertyLocalizableString::_page_changed(int p_page) {
+ if (updating) {
+ return;
+ }
+ page_index = p_page;
+ update_property();
+}
+
+void EditorPropertyLocalizableString::_bind_methods() {
+}
+
+EditorPropertyLocalizableString::EditorPropertyLocalizableString() {
+ object.instantiate();
+ page_length = int(EDITOR_GET("interface/inspector/max_array_dictionary_items_per_page"));
+
+ edit = memnew(Button);
+ edit->set_h_size_flags(SIZE_EXPAND_FILL);
+ edit->set_clip_text(true);
+ edit->connect("pressed", callable_mp(this, &EditorPropertyLocalizableString::_edit_pressed));
+ edit->set_toggle_mode(true);
+ add_child(edit);
+ add_focusable(edit);
+
+ vbox = nullptr;
+ button_add_item = nullptr;
+ paginator = nullptr;
+ updating = false;
+
+ locale_select = memnew(EditorLocaleDialog);
+ locale_select->connect("locale_selected", callable_mp(this, &EditorPropertyLocalizableString::_add_locale));
+ add_child(locale_select);
+}
diff --git a/editor/editor_properties_array_dict.h b/editor/editor_properties_array_dict.h
index 292de6d6db..6c22f7f606 100644
--- a/editor/editor_properties_array_dict.h
+++ b/editor/editor_properties_array_dict.h
@@ -32,6 +32,7 @@
#define EDITOR_PROPERTIES_ARRAY_DICT_H
#include "editor/editor_inspector.h"
+#include "editor/editor_locale_dialog.h"
#include "editor/editor_spin_slider.h"
#include "editor/filesystem_dock.h"
#include "scene/gui/button.h"
@@ -169,4 +170,39 @@ public:
EditorPropertyDictionary();
};
+class EditorPropertyLocalizableString : public EditorProperty {
+ GDCLASS(EditorPropertyLocalizableString, EditorProperty);
+
+ EditorLocaleDialog *locale_select;
+
+ bool updating;
+
+ Ref<EditorPropertyDictionaryObject> object;
+ int page_length = 20;
+ int page_index = 0;
+ Button *edit;
+ VBoxContainer *vbox;
+ VBoxContainer *property_vbox;
+ EditorSpinSlider *size_slider;
+ Button *button_add_item;
+ EditorPaginator *paginator;
+
+ void _page_changed(int p_page);
+ void _edit_pressed();
+ void _remove_item(Object *p_button, int p_index);
+ void _property_changed(const String &p_property, Variant p_value, const String &p_name = "", bool p_changing = false);
+
+ void _add_locale_popup();
+ void _add_locale(const String &p_locale);
+ void _object_id_selected(const StringName &p_property, ObjectID p_id);
+
+protected:
+ static void _bind_methods();
+ void _notification(int p_what);
+
+public:
+ virtual void update_property() override;
+ EditorPropertyLocalizableString();
+};
+
#endif // EDITOR_PROPERTIES_ARRAY_DICT_H
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 45685b8fb2..179a88dc60 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -1222,7 +1222,7 @@ bool EditorSettings::is_dark_theme() {
void EditorSettings::list_text_editor_themes() {
String themes = "Default,Godot 2,Custom";
- DirAccess *d = DirAccess::open(get_text_editor_themes_dir());
+ DirAccessRef d = DirAccess::open(get_text_editor_themes_dir());
if (d) {
List<String> custom_themes;
d->list_dir_begin();
@@ -1234,7 +1234,6 @@ void EditorSettings::list_text_editor_themes() {
file = d->get_next();
}
d->list_dir_end();
- memdelete(d);
custom_themes.sort();
for (const String &E : custom_themes) {
@@ -1289,10 +1288,9 @@ bool EditorSettings::import_text_editor_theme(String p_file) {
return false;
}
- DirAccess *d = DirAccess::open(get_text_editor_themes_dir());
+ DirAccessRef d = DirAccess::open(get_text_editor_themes_dir());
if (d) {
d->copy(p_file, get_text_editor_themes_dir().plus_file(p_file.get_file()));
- memdelete(d);
return true;
}
}
@@ -1342,7 +1340,7 @@ Vector<String> EditorSettings::get_script_templates(const String &p_extension, c
if (!p_custom_path.is_empty()) {
template_dir = p_custom_path;
}
- DirAccess *d = DirAccess::open(template_dir);
+ DirAccessRef d = DirAccess::open(template_dir);
if (d) {
d->list_dir_begin();
String file = d->get_next();
@@ -1353,7 +1351,6 @@ Vector<String> EditorSettings::get_script_templates(const String &p_extension, c
file = d->get_next();
}
d->list_dir_end();
- memdelete(d);
}
return templates;
}
diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp
index 0a8d35aff1..df3e73267e 100644
--- a/editor/export_template_manager.cpp
+++ b/editor/export_template_manager.cpp
@@ -44,7 +44,7 @@
void ExportTemplateManager::_update_template_status() {
// Fetch installed templates from the file system.
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
const String &templates_dir = EditorSettings::get_singleton()->get_templates_dir();
Error err = da->change_dir(templates_dir);
@@ -62,7 +62,6 @@ void ExportTemplateManager::_update_template_status() {
}
}
da->list_dir_end();
- memdelete(da);
// Update the state of the current version.
String current_version = VERSION_FULL_CONFIG;
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index e8a2a46dd2..58074207ff 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -525,16 +525,14 @@ void FileSystemDock::_navigate_to_path(const String &p_path, bool p_select_in_fa
if (target_path.ends_with("/")) {
target_path = target_path.substr(0, target_path.length() - 1);
}
- DirAccess *dirAccess = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- if (dirAccess->file_exists(p_path)) {
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ if (da->file_exists(p_path)) {
path = target_path;
- } else if (dirAccess->dir_exists(p_path)) {
+ } else if (da->dir_exists(p_path)) {
path = target_path + "/";
} else {
- memdelete(dirAccess);
ERR_FAIL_MSG(vformat("Cannot navigate to '%s' as it has not been found in the file system!", p_path));
}
- memdelete(dirAccess);
}
_set_current_path_text(path);
@@ -1171,7 +1169,7 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_
_get_all_items_in_dir(EditorFileSystem::get_singleton()->get_filesystem_path(old_path), file_changed_paths, folder_changed_paths);
}
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
print_verbose("Moving " + old_path + " -> " + new_path);
Error err = da->rename(old_path, new_path);
if (err == OK) {
@@ -1211,7 +1209,6 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_
} else {
EditorNode::get_singleton()->add_io_error(TTR("Error moving:") + "\n" + old_path + "\n");
}
- memdelete(da);
}
void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const String &p_new_path) const {
@@ -1230,7 +1227,7 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin
return;
}
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
print_verbose("Duplicating " + old_path + " -> " + new_path);
Error err = p_item.is_file ? da->copy(old_path, new_path) : da->copy_dir(old_path, new_path);
if (err == OK) {
@@ -1268,7 +1265,6 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin
} else {
EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:") + "\n" + old_path + "\n");
}
- memdelete(da);
}
void FileSystemDock::_update_resource_paths_after_move(const Map<String, String> &p_renames) const {
@@ -1418,12 +1414,11 @@ void FileSystemDock::_make_dir_confirm() {
directory = directory.get_base_dir();
}
print_verbose("Making folder " + dir_name + " in " + directory);
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
Error err = da->change_dir(directory);
if (err == OK) {
err = da->make_dir(dir_name);
}
- memdelete(da);
if (err == OK) {
print_verbose("FileSystem: calling rescan.");
@@ -1464,13 +1459,11 @@ void FileSystemDock::_make_scene_confirm() {
scene_name = directory.plus_file(scene_name);
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (da->file_exists(scene_name)) {
EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists."));
- memdelete(da);
return;
}
- memdelete(da);
int idx = EditorNode::get_singleton()->new_scene();
EditorNode::get_singleton()->get_editor_data().set_scene_path(idx, scene_name);
@@ -1533,7 +1526,7 @@ void FileSystemDock::_rename_operation_confirm() {
}
// Present a more user friendly warning for name conflict.
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
#if defined(WINDOWS_ENABLED) || defined(UWP_ENABLED)
// Workaround case insensitivity on Windows.
if ((da->file_exists(new_path) || da->dir_exists(new_path)) && new_path.to_lower() != old_path.to_lower()) {
@@ -1541,10 +1534,8 @@ void FileSystemDock::_rename_operation_confirm() {
if (da->file_exists(new_path) || da->dir_exists(new_path)) {
#endif
EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists."));
- memdelete(da);
return;
}
- memdelete(da);
Map<String, String> file_renames;
Map<String, String> folder_renames;
@@ -1588,13 +1579,11 @@ void FileSystemDock::_duplicate_operation_confirm() {
String new_path = base_dir.plus_file(new_name);
// Present a more user friendly warning for name conflict
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (da->file_exists(new_path) || da->dir_exists(new_path)) {
EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists."));
- memdelete(da);
return;
}
- memdelete(da);
_try_duplicate_item(to_duplicate, new_path);
@@ -2818,7 +2807,7 @@ void FileSystemDock::_get_imported_files(const String &p_path, Vector<String> &f
return;
}
- DirAccess *da = DirAccess::open(p_path);
+ DirAccessRef da = DirAccess::open(p_path);
da->list_dir_begin();
String n = da->get_next();
while (!n.is_empty()) {
diff --git a/editor/icons/StreamTexture.svg b/editor/icons/CompressedTexture2D.svg
index 068f65dead..068f65dead 100644
--- a/editor/icons/StreamTexture.svg
+++ b/editor/icons/CompressedTexture2D.svg
diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp
index f0a2d7d553..2ecc483938 100644
--- a/editor/import/dynamic_font_import_settings.cpp
+++ b/editor/import/dynamic_font_import_settings.cpp
@@ -484,6 +484,14 @@ void DynamicFontImportSettings::_main_prop_changed(const String &p_edited_proper
if (font_preview->get_data_count() > 0) {
font_preview->get_data(0)->set_subpixel_positioning((TextServer::SubpixelPositioning)import_settings_data->get("subpixel_positioning").operator int());
}
+ } else if (p_edited_property == "embolden") {
+ if (font_preview->get_data_count() > 0) {
+ font_preview->get_data(0)->set_embolden(import_settings_data->get("embolden"));
+ }
+ } else if (p_edited_property == "transform") {
+ if (font_preview->get_data_count() > 0) {
+ font_preview->get_data(0)->set_transform(import_settings_data->get("transform"));
+ }
} else if (p_edited_property == "oversampling") {
if (font_preview->get_data_count() > 0) {
font_preview->get_data(0)->set_oversampling(import_settings_data->get("oversampling"));
@@ -924,6 +932,8 @@ void DynamicFontImportSettings::_re_import() {
main_settings["force_autohinter"] = import_settings_data->get("force_autohinter");
main_settings["hinting"] = import_settings_data->get("hinting");
main_settings["subpixel_positioning"] = import_settings_data->get("subpixel_positioning");
+ main_settings["embolden"] = import_settings_data->get("embolden");
+ main_settings["transform"] = import_settings_data->get("transform");
main_settings["oversampling"] = import_settings_data->get("oversampling");
main_settings["compress"] = import_settings_data->get("compress");
@@ -1275,6 +1285,8 @@ void DynamicFontImportSettings::open_settings(const String &p_path) {
font_preview->get_data(0)->set_force_autohinter(import_settings_data->get("force_autohinter"));
font_preview->get_data(0)->set_hinting((TextServer::Hinting)import_settings_data->get("hinting").operator int());
font_preview->get_data(0)->set_subpixel_positioning((TextServer::SubpixelPositioning)import_settings_data->get("subpixel_positioning").operator int());
+ font_preview->get_data(0)->set_embolden(import_settings_data->get("embolden"));
+ font_preview->get_data(0)->set_transform(import_settings_data->get("transform"));
font_preview->get_data(0)->set_oversampling(import_settings_data->get("oversampling"));
}
font_preview_label->add_theme_font_override("font", font_preview);
@@ -1334,6 +1346,8 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "force_autohinter"), false));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), 1));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel"), 1));
+ options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::FLOAT, "embolden", PROPERTY_HINT_RANGE, "-2,2,0.01"), 0.f));
+ options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::TRANSFORM2D, "transform"), Transform2D()));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), 0.0));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "compress", PROPERTY_HINT_NONE, ""), false));
diff --git a/editor/import/resource_importer_dynamic_font.cpp b/editor/import/resource_importer_dynamic_font.cpp
index 70fc87ea3f..077b94bb4e 100644
--- a/editor/import/resource_importer_dynamic_font.cpp
+++ b/editor/import/resource_importer_dynamic_font.cpp
@@ -109,6 +109,8 @@ void ResourceImporterDynamicFont::get_import_options(const String &p_path, List<
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "force_autohinter"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), 1));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel"), 1));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "embolden", PROPERTY_HINT_RANGE, "-2,2,0.01"), 0.f));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::TRANSFORM2D, "transform"), Transform2D()));
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), 0.0));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress"), true));
@@ -186,6 +188,8 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str
int hinting = p_options["hinting"];
int subpixel_positioning = p_options["subpixel_positioning"];
real_t oversampling = p_options["oversampling"];
+ real_t embolden = p_options["embolden"];
+ Transform2D transform = p_options["transform"];
// Load base font data.
Vector<uint8_t> data = FileAccess::get_file_as_array(p_source_file);
@@ -202,6 +206,8 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str
font->set_fixed_size(0);
font->set_force_autohinter(autohinter);
font->set_subpixel_positioning((TextServer::SubpixelPositioning)subpixel_positioning);
+ font->set_embolden(embolden);
+ font->set_transform(transform);
font->set_hinting((TextServer::Hinting)hinting);
font->set_oversampling(oversampling);
diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp
index 197cc49a95..9ddee9c058 100644
--- a/editor/import/resource_importer_layered_texture.cpp
+++ b/editor/import/resource_importer_layered_texture.cpp
@@ -85,16 +85,16 @@ void ResourceImporterLayeredTexture::get_recognized_extensions(List<String> *p_e
String ResourceImporterLayeredTexture::get_save_extension() const {
switch (mode) {
case MODE_CUBEMAP: {
- return "scube";
+ return "ccube";
} break;
case MODE_2D_ARRAY: {
- return "stexarray";
+ return "ctexarray";
} break;
case MODE_CUBEMAP_ARRAY: {
- return "scubearray";
+ return "ccubearray";
} break;
case MODE_3D: {
- return "stex3d";
+ return "ctex3d";
} break;
}
@@ -274,11 +274,11 @@ void ResourceImporterLayeredTexture::_save_tex(Vector<Ref<Image>> p_images, cons
f->store_32(0);
for (int i = 0; i < p_images.size(); i++) {
- ResourceImporterTexture::save_to_stex_format(f, p_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_lossy);
+ ResourceImporterTexture::save_to_ctex_format(f, p_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_lossy);
}
for (int i = 0; i < mipmap_images.size(); i++) {
- ResourceImporterTexture::save_to_stex_format(f, mipmap_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_lossy);
+ ResourceImporterTexture::save_to_ctex_format(f, mipmap_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_lossy);
}
f->close();
@@ -393,7 +393,7 @@ Error ResourceImporterLayeredTexture::import(const String &p_source_file, const
texture_import->bptc_ldr = bptc_ldr;
texture_import->mipmaps = mipmaps;
texture_import->used_channels = used_channels;
- _check_compress_stex(texture_import);
+ _check_compress_ctex(texture_import);
if (r_metadata) {
Dictionary metadata;
metadata["vram_texture"] = compress_mode == COMPRESS_VRAM_COMPRESSED;
@@ -474,7 +474,7 @@ ResourceImporterLayeredTexture::ResourceImporterLayeredTexture() {
ResourceImporterLayeredTexture::~ResourceImporterLayeredTexture() {
}
-void ResourceImporterLayeredTexture::_check_compress_stex(Ref<LayeredTextureImport> r_texture_import) {
+void ResourceImporterLayeredTexture::_check_compress_ctex(Ref<LayeredTextureImport> r_texture_import) {
String extension = get_save_extension();
ERR_FAIL_NULL(r_texture_import->csource);
if (r_texture_import->compress_mode != COMPRESS_VRAM_COMPRESSED) {
diff --git a/editor/import/resource_importer_layered_texture.h b/editor/import/resource_importer_layered_texture.h
index 58e5c47d8d..5791914a9b 100644
--- a/editor/import/resource_importer_layered_texture.h
+++ b/editor/import/resource_importer_layered_texture.h
@@ -87,7 +87,7 @@ protected:
static ResourceImporterLayeredTexture *singleton;
public:
- void _check_compress_stex(Ref<LayeredTextureImport> r_texture_import);
+ void _check_compress_ctex(Ref<LayeredTextureImport> r_texture_import);
static ResourceImporterLayeredTexture *get_singleton() { return singleton; }
virtual String get_importer_name() const override;
diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp
index e672fe2dee..1dec4b00bb 100644
--- a/editor/import/resource_importer_texture.cpp
+++ b/editor/import/resource_importer_texture.cpp
@@ -225,7 +225,7 @@ void ResourceImporterTexture::get_import_options(const String &p_path, List<Impo
}
}
-void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality) {
+void ResourceImporterTexture::save_to_ctex_format(FileAccess *f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality) {
switch (p_compress_mode) {
case COMPRESS_LOSSLESS: {
bool lossless_force_png = ProjectSettings::get_singleton()->get("rendering/textures/lossless_compression/force_png") ||
@@ -317,7 +317,7 @@ void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Ref<Image
}
}
-void ResourceImporterTexture::_save_stex(const Ref<Image> &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_roughness, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref<Image> &p_normal, Image::RoughnessChannel p_roughness_channel) {
+void ResourceImporterTexture::_save_ctex(const Ref<Image> &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_roughness, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref<Image> &p_normal, Image::RoughnessChannel p_roughness_channel) {
FileAccess *f = FileAccess::open(p_to_path, FileAccess::WRITE);
ERR_FAIL_NULL(f);
f->store_8('G');
@@ -394,7 +394,7 @@ void ResourceImporterTexture::_save_stex(const Ref<Image> &p_image, const String
Image::UsedChannels used_channels = image->detect_used_channels(csource);
- save_to_stex_format(f, image, p_compress_mode, used_channels, p_vram_compression, p_lossy_quality);
+ save_to_ctex_format(f, image, p_compress_mode, used_channels, p_vram_compression, p_lossy_quality);
memdelete(f);
}
@@ -540,19 +540,19 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String
if (!bptc_ldr && can_s3tc && is_ldr) {
image_compress_mode = Image::COMPRESS_S3TC;
}
- _save_stex(image, p_save_path + ".s3tc.ctex", compress_mode, lossy, image_compress_mode, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel);
+ _save_ctex(image, p_save_path + ".s3tc.ctex", compress_mode, lossy, image_compress_mode, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel);
r_platform_variants->push_back("s3tc");
formats_imported.push_back("s3tc");
}
if (ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc2")) {
- _save_stex(image, p_save_path + ".etc2.ctex", compress_mode, lossy, Image::COMPRESS_ETC2, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel);
+ _save_ctex(image, p_save_path + ".etc2.ctex", compress_mode, lossy, Image::COMPRESS_ETC2, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel);
r_platform_variants->push_back("etc2");
formats_imported.push_back("etc2");
}
if (ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc")) {
- _save_stex(image, p_save_path + ".etc.ctex", compress_mode, lossy, Image::COMPRESS_ETC, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel);
+ _save_ctex(image, p_save_path + ".etc.ctex", compress_mode, lossy, Image::COMPRESS_ETC, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel);
r_platform_variants->push_back("etc");
formats_imported.push_back("etc");
}
@@ -562,7 +562,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String
}
} else {
//import normally
- _save_stex(image, p_save_path + ".ctex", compress_mode, lossy, Image::COMPRESS_S3TC /*this is ignored */, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel);
+ _save_ctex(image, p_save_path + ".ctex", compress_mode, lossy, Image::COMPRESS_S3TC /*this is ignored */, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel);
}
if (r_metadata) {
diff --git a/editor/import/resource_importer_texture.h b/editor/import/resource_importer_texture.h
index bd43eaef58..b3a68260fc 100644
--- a/editor/import/resource_importer_texture.h
+++ b/editor/import/resource_importer_texture.h
@@ -74,10 +74,10 @@ protected:
static ResourceImporterTexture *singleton;
static const char *compression_formats[];
- void _save_stex(const Ref<Image> &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_srgb, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref<Image> &p_normal, Image::RoughnessChannel p_roughness_channel);
+ void _save_ctex(const Ref<Image> &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_srgb, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref<Image> &p_normal, Image::RoughnessChannel p_roughness_channel);
public:
- static void save_to_stex_format(FileAccess *f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality);
+ static void save_to_ctex_format(FileAccess *f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality);
static ResourceImporterTexture *get_singleton() { return singleton; }
virtual String get_importer_name() const override;
diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp
index d5e7c312d9..02cc95e14a 100644
--- a/editor/plugin_config_dialog.cpp
+++ b/editor/plugin_config_dialog.cpp
@@ -50,7 +50,7 @@ void PluginConfigDialog::_on_confirmed() {
String path = "res://addons/" + subfolder_edit->get_text();
if (!_edit_mode) {
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (!d || d->make_dir_recursive(path) != OK) {
return;
}
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index fba6d8e57f..f983492f7f 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -897,11 +897,6 @@ void AnimationPlayerEditor::_update_player() {
}
void AnimationPlayerEditor::_update_animation_list_icons() {
- List<StringName> animlist;
- if (player) {
- player->get_animation_list(&animlist);
- }
-
for (int i = 0; i < animation->get_item_count(); i++) {
String name = animation->get_item_text(i);
diff --git a/editor/project_export.cpp b/editor/project_export.cpp
index 17db955cc7..401d579c23 100644
--- a/editor/project_export.cpp
+++ b/editor/project_export.cpp
@@ -1153,7 +1153,7 @@ ProjectExportDialog::ProjectExportDialog() {
enc_ex_filters = memnew(LineEdit);
enc_ex_filters->connect("text_changed", callable_mp(this, &ProjectExportDialog::_enc_filters_changed));
sec_vb->add_margin_child(
- TTR("Filters to exclude files/folders\n(comma-separated, e.g: *.stex, *.import, music/*)"),
+ TTR("Filters to exclude files/folders\n(comma-separated, e.g: *.ctex, *.import, music/*)"),
enc_ex_filters);
script_key = memnew(LineEdit);
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 78f6fe58d0..35902fd354 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -147,7 +147,7 @@ private:
}
String _test_path() {
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
String valid_path, valid_install_path;
if (d->change_dir(project_path->get_text()) == OK) {
valid_path = project_path->get_text();
@@ -165,7 +165,6 @@ private:
if (valid_path.is_empty()) {
set_message(TTR("The path specified doesn't exist."), MESSAGE_ERROR);
- memdelete(d);
get_ok_button()->set_disabled(true);
return "";
}
@@ -179,7 +178,6 @@ private:
if (valid_install_path.is_empty()) {
set_message(TTR("The path specified doesn't exist."), MESSAGE_ERROR, INSTALL_PATH);
- memdelete(d);
get_ok_button()->set_disabled(true);
return "";
}
@@ -194,7 +192,6 @@ private:
unzFile pkg = unzOpen2(valid_path.utf8().get_data(), &io);
if (!pkg) {
set_message(TTR("Error opening package file (it's not in ZIP format)."), MESSAGE_ERROR);
- memdelete(d);
get_ok_button()->set_disabled(true);
unzClose(pkg);
return "";
@@ -215,7 +212,6 @@ private:
if (ret == UNZ_END_OF_LIST_OF_FILE) {
set_message(TTR("Invalid \".zip\" project file; it doesn't contain a \"project.godot\" file."), MESSAGE_ERROR);
- memdelete(d);
get_ok_button()->set_disabled(true);
unzClose(pkg);
return "";
@@ -242,14 +238,12 @@ private:
if (!is_folder_empty) {
set_message(TTR("Please choose an empty folder."), MESSAGE_WARNING, INSTALL_PATH);
- memdelete(d);
get_ok_button()->set_disabled(true);
return "";
}
} else {
set_message(TTR("Please choose a \"project.godot\" or \".zip\" file."), MESSAGE_ERROR);
- memdelete(d);
install_path_container->hide();
get_ok_button()->set_disabled(true);
return "";
@@ -257,7 +251,6 @@ private:
} else if (valid_path.ends_with("zip")) {
set_message(TTR("This directory already contains a Godot project."), MESSAGE_ERROR, INSTALL_PATH);
- memdelete(d);
get_ok_button()->set_disabled(true);
return "";
}
@@ -282,7 +275,6 @@ private:
if (!is_folder_empty) {
set_message(TTR("The selected path is not empty. Choosing an empty folder is highly recommended."), MESSAGE_WARNING);
- memdelete(d);
get_ok_button()->set_disabled(false);
return valid_path;
}
@@ -290,7 +282,6 @@ private:
set_message("");
set_message("", MESSAGE_SUCCESS, INSTALL_PATH);
- memdelete(d);
get_ok_button()->set_disabled(false);
return valid_path;
}
@@ -389,7 +380,7 @@ private:
return;
}
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (d->change_dir(project_path->get_text()) == OK) {
if (!d->dir_exists(project_name_no_edges)) {
if (d->make_dir(project_name_no_edges) == OK) {
@@ -408,8 +399,6 @@ private:
dialog_error->popup_centered();
}
}
-
- memdelete(d);
}
void _text_changed(const String &p_text) {
@@ -551,14 +540,11 @@ private:
if (path.is_empty() || path == zip_root || !zip_root.is_subsequence_of(path)) {
//
} else if (path.ends_with("/")) { // a dir
-
path = path.substr(0, path.length() - 1);
String rel_path = path.substr(zip_root.length());
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
da->make_dir(dir.plus_file(rel_path));
- memdelete(da);
-
} else {
Vector<uint8_t> data;
data.resize(info.uncompressed_size);
@@ -620,9 +606,8 @@ private:
void _remove_created_folder() {
if (!created_folder_path.is_empty()) {
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
d->remove(created_folder_path);
- memdelete(d);
create_dir->set_disabled(false);
created_folder_path = "";
@@ -725,10 +710,9 @@ public:
project_path->set_text(fav_dir);
fdialog->set_current_dir(fav_dir);
} else {
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
project_path->set_text(d->get_current_dir());
fdialog->set_current_dir(d->get_current_dir());
- memdelete(d);
}
String proj = TTR("New Game Project");
project_name->set_text(proj);
@@ -2411,12 +2395,11 @@ void ProjectManager::_files_dropped(PackedStringArray p_files, int p_screen) {
return;
}
Set<String> folders_set;
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
for (int i = 0; i < p_files.size(); i++) {
String file = p_files[i];
folders_set.insert(da->dir_exists(file) ? file : file.get_base_dir());
}
- memdelete(da);
if (folders_set.size() > 0) {
PackedStringArray folders;
for (Set<String>::Element *E = folders_set.front(); E; E = E->next()) {
@@ -2425,7 +2408,7 @@ void ProjectManager::_files_dropped(PackedStringArray p_files, int p_screen) {
bool confirm = true;
if (folders.size() == 1) {
- DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (dir->change_dir(folders[0]) == OK) {
dir->list_dir_begin();
String file = dir->get_next();
@@ -2437,7 +2420,6 @@ void ProjectManager::_files_dropped(PackedStringArray p_files, int p_screen) {
}
dir->list_dir_end();
}
- memdelete(dir);
}
if (confirm) {
multi_scan_ask->get_ok_button()->disconnect("pressed", callable_mp(this, &ProjectManager::_scan_multiple_folders));
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
index bf43e11cdb..055b30dae2 100644
--- a/editor/script_create_dialog.cpp
+++ b/editor/script_create_dialog.cpp
@@ -247,23 +247,22 @@ String ScriptCreateDialog::_validate_path(const String &p_path, bool p_file_must
return TTR("Path is not local.");
}
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- if (d->change_dir(p.get_base_dir()) != OK) {
- memdelete(d);
- return TTR("Base path is invalid.");
+ {
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ if (da->change_dir(p.get_base_dir()) != OK) {
+ return TTR("Base path is invalid.");
+ }
}
- memdelete(d);
- // Check if file exists.
- DirAccess *f = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- if (f->dir_exists(p)) {
- memdelete(f);
- return TTR("A directory with the same name exists.");
- } else if (p_file_must_exist && !f->file_exists(p)) {
- memdelete(f);
- return TTR("File does not exist.");
+ {
+ // Check if file exists.
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ if (da->dir_exists(p)) {
+ return TTR("A directory with the same name exists.");
+ } else if (p_file_must_exist && !da->file_exists(p)) {
+ return TTR("File does not exist.");
+ }
}
- memdelete(f);
// Check file extension.
String extension = p.get_extension();
@@ -556,13 +555,12 @@ void ScriptCreateDialog::_path_changed(const String &p_path) {
}
// Check if file exists.
- DirAccess *f = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
String p = ProjectSettings::get_singleton()->localize_path(p_path.strip_edges());
- if (f->file_exists(p)) {
+ if (da->file_exists(p)) {
is_new_script_created = false;
_msg_path_valid(true, TTR("File exists, it will be reused."));
}
- memdelete(f);
is_path_valid = true;
_update_dialog();
@@ -838,7 +836,7 @@ Vector<ScriptLanguage::ScriptTemplate> ScriptCreateDialog::_get_user_templates(c
String dir_path = p_dir.plus_file(p_object);
- DirAccess *d = DirAccess::open(dir_path);
+ DirAccessRef d = DirAccess::open(dir_path);
if (d) {
d->list_dir_begin();
String file = d->get_next();
@@ -849,7 +847,6 @@ Vector<ScriptLanguage::ScriptTemplate> ScriptCreateDialog::_get_user_templates(c
file = d->get_next();
}
d->list_dir_end();
- memdelete(d);
}
return user_templates;
}
diff --git a/main/main.cpp b/main/main.cpp
index 97794ece1a..ccd48a9343 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -2099,9 +2099,8 @@ bool Main::start() {
checked_paths.insert(path);
// Create the module documentation directory if it doesn't exist
- DirAccess *da = DirAccess::create_for_path(path);
+ DirAccessRef da = DirAccess::create_for_path(path);
err = da->make_dir_recursive(path);
- memdelete(da);
ERR_FAIL_COND_V_MSG(err != OK, false, "Error: Can't create directory: " + path + ": " + itos(err));
print_line("Loading docs from: " + path);
@@ -2112,9 +2111,8 @@ bool Main::start() {
String index_path = doc_tool_path.plus_file("doc/classes");
// Create the main documentation directory if it doesn't exist
- DirAccess *da = DirAccess::create_for_path(index_path);
+ DirAccessRef da = DirAccess::create_for_path(index_path);
err = da->make_dir_recursive(index_path);
- memdelete(da);
ERR_FAIL_COND_V_MSG(err != OK, false, "Error: Can't create index directory: " + index_path + ": " + itos(err));
print_line("Loading classes from: " + index_path);
@@ -2452,15 +2450,13 @@ bool Main::start() {
int sep = local_game_path.rfind("/");
if (sep == -1) {
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
local_game_path = da->get_current_dir().plus_file(local_game_path);
- memdelete(da);
} else {
- DirAccess *da = DirAccess::open(local_game_path.substr(0, sep));
+ DirAccessRef da = DirAccess::open(local_game_path.substr(0, sep));
if (da) {
local_game_path = da->get_current_dir().plus_file(
local_game_path.substr(sep + 1, local_game_path.length()));
- memdelete(da);
}
}
}
diff --git a/misc/dist/osx_template.app/Contents/Info.plist b/misc/dist/osx_template.app/Contents/Info.plist
index 43399ec6ce..542146cdb8 100644
--- a/misc/dist/osx_template.app/Contents/Info.plist
+++ b/misc/dist/osx_template.app/Contents/Info.plist
@@ -10,8 +10,6 @@
<string>$name</string>
<key>CFBundleDisplayName</key>
<string>$name</string>
- <key>CFBundleGetInfoString</key>
- <string>$info</string>
<key>CFBundleIconFile</key>
<string>icon.icns</string>
<key>CFBundleIdentifier</key>
diff --git a/misc/dist/osx_tools.app/Contents/Info.plist b/misc/dist/osx_tools.app/Contents/Info.plist
index 221c4b7a81..886df87cc6 100644
--- a/misc/dist/osx_tools.app/Contents/Info.plist
+++ b/misc/dist/osx_tools.app/Contents/Info.plist
@@ -8,8 +8,6 @@
<string>Godot</string>
<key>CFBundleName</key>
<string>Godot</string>
- <key>CFBundleGetInfoString</key>
- <string>(c) 2007-2022 Juan Linietsky, Ariel Manzur &amp; Godot Engine contributors</string>
<key>CFBundleIconFile</key>
<string>Godot.icns</string>
<key>CFBundleIdentifier</key>
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index 137df52215..34f3ba9296 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -1530,6 +1530,9 @@ CSGBrush *CSGTorus3D::_build_brush() {
for (int i = 0; i < sides; i++) {
float inci = float(i) / sides;
float inci_n = float((i + 1)) / sides;
+ if (i == sides - 1) {
+ inci_n = 0;
+ }
float angi = inci * Math_TAU;
float angi_n = inci_n * Math_TAU;
@@ -1540,6 +1543,9 @@ CSGBrush *CSGTorus3D::_build_brush() {
for (int j = 0; j < ring_sides; j++) {
float incj = float(j) / ring_sides;
float incj_n = float((j + 1)) / ring_sides;
+ if (j == ring_sides - 1) {
+ incj_n = 0;
+ }
float angj = incj * Math_TAU;
float angj_n = incj_n * Math_TAU;
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index 4cd4772d2c..424b74906f 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -643,9 +643,8 @@ bool GDMono::copy_prebuilt_api_assembly(ApiAssemblyInfo::Type p_api_type, const
// Create destination directory if needed
if (!DirAccess::exists(dst_dir)) {
- DirAccess *da = DirAccess::create_for_path(dst_dir);
+ DirAccessRef da = DirAccess::create_for_path(dst_dir);
Error err = da->make_dir_recursive(dst_dir);
- memdelete(da);
if (err != OK) {
ERR_PRINT("Failed to create destination directory for the API assemblies. Error: " + itos(err) + ".");
diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp
index b89171543f..39f9153f0d 100644
--- a/modules/openxr/openxr_interface.cpp
+++ b/modules/openxr/openxr_interface.cpp
@@ -760,8 +760,9 @@ OpenXRInterface::OpenXRInterface() {
}
OpenXRInterface::~OpenXRInterface() {
- // should already have been called but just in case...
- uninitialize();
+ if (is_initialized()) {
+ uninitialize();
+ }
if (openxr_api) {
openxr_api->set_xr_interface(nullptr);
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index 1b4512dc60..72a87e5503 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -704,7 +704,7 @@ String TextServerAdvanced::tag_to_name(int32_t p_tag) const {
/* Font Glyph Rendering */
/*************************************************************************/
-_FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_texture_pos_for_glyph(FontDataForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height) const {
+_FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_texture_pos_for_glyph(FontDataForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const {
FontTexturePosition ret;
ret.index = -1;
@@ -769,8 +769,11 @@ _FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_
}
texsize = next_power_of_2(texsize);
-
- texsize = MIN(texsize, 4096);
+ if (p_msdf) {
+ texsize = MIN(texsize, 2048);
+ } else {
+ texsize = MIN(texsize, 1024);
+ }
FontTexture tex;
tex.texture_w = texsize;
@@ -935,10 +938,10 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf(
int mw = w + p_rect_margin * 2;
int mh = h + p_rect_margin * 2;
- ERR_FAIL_COND_V(mw > 4096, FontGlyph());
- ERR_FAIL_COND_V(mh > 4096, FontGlyph());
+ ERR_FAIL_COND_V(mw > 1024, FontGlyph());
+ ERR_FAIL_COND_V(mh > 1024, FontGlyph());
- FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, 4, Image::FORMAT_RGBA8, mw, mh);
+ FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, 4, Image::FORMAT_RGBA8, mw, mh, true);
ERR_FAIL_COND_V(tex_pos.index < 0, FontGlyph());
FontTexture &tex = p_data->textures.write[tex_pos.index];
@@ -1013,13 +1016,13 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma
int mw = w + p_rect_margin * 2;
int mh = h + p_rect_margin * 2;
- ERR_FAIL_COND_V(mw > 4096, FontGlyph());
- ERR_FAIL_COND_V(mh > 4096, FontGlyph());
+ ERR_FAIL_COND_V(mw > 1024, FontGlyph());
+ ERR_FAIL_COND_V(mh > 1024, FontGlyph());
int color_size = bitmap.pixel_mode == FT_PIXEL_MODE_BGRA ? 4 : 2;
Image::Format require_format = color_size == 4 ? Image::FORMAT_RGBA8 : Image::FORMAT_LA8;
- FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, color_size, require_format, mw, mh);
+ FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, color_size, require_format, mw, mh, false);
ERR_FAIL_COND_V(tex_pos.index < 0, FontGlyph());
// Fit character in char texture.
@@ -1155,6 +1158,16 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontDataAdvanced *p_font_d
}
}
+ if (p_font_data->embolden != 0.f) {
+ FT_Pos strength = p_font_data->embolden * p_size.x * 4; // 26.6 fractional units (1 / 64).
+ FT_Outline_Embolden(&fd->face->glyph->outline, strength);
+ }
+
+ if (p_font_data->transform != Transform2D()) {
+ FT_Matrix mat = { FT_Fixed(p_font_data->transform[0][0] * 65536), FT_Fixed(p_font_data->transform[0][1] * 65536), FT_Fixed(p_font_data->transform[1][0] * 65536), FT_Fixed(p_font_data->transform[1][1] * 65536) }; // 16.16 fractional units (1 / 65536).
+ FT_Outline_Transform(&fd->face->glyph->outline, &mat);
+ }
+
if (!outline) {
if (!p_font_data->msdf) {
error = FT_Render_Glyph(fd->face->glyph, p_font_data->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO);
@@ -1874,6 +1887,44 @@ TextServer::SubpixelPositioning TextServerAdvanced::font_get_subpixel_positionin
return fd->subpixel_positioning;
}
+void TextServerAdvanced::font_set_embolden(RID p_font_rid, float p_strength) {
+ FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND(!fd);
+
+ MutexLock lock(fd->mutex);
+ if (fd->embolden != p_strength) {
+ _font_clear_cache(fd);
+ fd->embolden = p_strength;
+ }
+}
+
+float TextServerAdvanced::font_get_embolden(RID p_font_rid) const {
+ FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, 0.f);
+
+ MutexLock lock(fd->mutex);
+ return fd->embolden;
+}
+
+void TextServerAdvanced::font_set_transform(RID p_font_rid, Transform2D p_transform) {
+ FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND(!fd);
+
+ MutexLock lock(fd->mutex);
+ if (fd->transform != p_transform) {
+ _font_clear_cache(fd);
+ fd->transform = p_transform;
+ }
+}
+
+Transform2D TextServerAdvanced::font_get_transform(RID p_font_rid) const {
+ FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, Transform2D());
+
+ MutexLock lock(fd->mutex);
+ return fd->transform;
+}
+
void TextServerAdvanced::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h
index 7841a15cd3..f63ff645bf 100644
--- a/modules/text_server_adv/text_server_adv.h
+++ b/modules/text_server_adv/text_server_adv.h
@@ -177,6 +177,8 @@ class TextServerAdvanced : public TextServer {
TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
Dictionary variation_coordinates;
float oversampling = 0.f;
+ float embolden = 0.f;
+ Transform2D transform;
uint32_t style_flags = 0;
String font_name;
@@ -208,7 +210,7 @@ class TextServerAdvanced : public TextServer {
}
};
- _FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontDataForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height) const;
+ _FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontDataForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const;
#ifdef MODULE_MSDFGEN_ENABLED
_FORCE_INLINE_ FontGlyph rasterize_msdf(FontDataAdvanced *p_font_data, FontDataForSizeAdvanced *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const;
#endif
@@ -383,6 +385,12 @@ public:
virtual void font_set_subpixel_positioning(RID p_font_rid, SubpixelPositioning p_subpixel) override;
virtual SubpixelPositioning font_get_subpixel_positioning(RID p_font_rid) const override;
+ virtual void font_set_embolden(RID p_font_rid, float p_strength) override;
+ virtual float font_get_embolden(RID p_font_rid) const override;
+
+ virtual void font_set_transform(RID p_font_rid, Transform2D p_transform) override;
+ virtual Transform2D font_get_transform(RID p_font_rid) const override;
+
virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override;
virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override;
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index e6f9bcf131..5a4b20b2ef 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -155,7 +155,7 @@ String TextServerFallback::tag_to_name(int32_t p_tag) const {
/* Font Glyph Rendering */
/*************************************************************************/
-_FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_texture_pos_for_glyph(FontDataForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height) const {
+_FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_texture_pos_for_glyph(FontDataForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const {
FontTexturePosition ret;
ret.index = -1;
@@ -221,7 +221,11 @@ _FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_
texsize = next_power_of_2(texsize);
- texsize = MIN(texsize, 4096);
+ if (p_msdf) {
+ texsize = MIN(texsize, 2048);
+ } else {
+ texsize = MIN(texsize, 1024);
+ }
FontTexture tex;
tex.texture_w = texsize;
@@ -386,10 +390,10 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf(
int mw = w + p_rect_margin * 2;
int mh = h + p_rect_margin * 2;
- ERR_FAIL_COND_V(mw > 4096, FontGlyph());
- ERR_FAIL_COND_V(mh > 4096, FontGlyph());
+ ERR_FAIL_COND_V(mw > 1024, FontGlyph());
+ ERR_FAIL_COND_V(mh > 1024, FontGlyph());
- FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, 4, Image::FORMAT_RGBA8, mw, mh);
+ FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, 4, Image::FORMAT_RGBA8, mw, mh, true);
ERR_FAIL_COND_V(tex_pos.index < 0, FontGlyph());
FontTexture &tex = p_data->textures.write[tex_pos.index];
@@ -464,13 +468,13 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitma
int mw = w + p_rect_margin * 2;
int mh = h + p_rect_margin * 2;
- ERR_FAIL_COND_V(mw > 4096, FontGlyph());
- ERR_FAIL_COND_V(mh > 4096, FontGlyph());
+ ERR_FAIL_COND_V(mw > 1024, FontGlyph());
+ ERR_FAIL_COND_V(mh > 1024, FontGlyph());
int color_size = bitmap.pixel_mode == FT_PIXEL_MODE_BGRA ? 4 : 2;
Image::Format require_format = color_size == 4 ? Image::FORMAT_RGBA8 : Image::FORMAT_LA8;
- FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, color_size, require_format, mw, mh);
+ FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, color_size, require_format, mw, mh, false);
ERR_FAIL_COND_V(tex_pos.index < 0, FontGlyph());
// Fit character in char texture.
@@ -586,6 +590,8 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontDataFallback *p_font_d
flags |= FT_LOAD_COLOR;
}
+ glyph_index = FT_Get_Char_Index(fd->face, glyph_index);
+
FT_Fixed v, h;
FT_Get_Advance(fd->face, glyph_index, flags, &h);
FT_Get_Advance(fd->face, glyph_index, flags | FT_LOAD_VERTICAL_LAYOUT, &v);
@@ -606,6 +612,16 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontDataFallback *p_font_d
}
}
+ if (p_font_data->embolden != 0.f) {
+ FT_Pos strength = p_font_data->embolden * p_size.x * 4; // 26.6 fractional units (1 / 64).
+ FT_Outline_Embolden(&fd->face->glyph->outline, strength);
+ }
+
+ if (p_font_data->transform != Transform2D()) {
+ FT_Matrix mat = { FT_Fixed(p_font_data->transform[0][0] * 65536), FT_Fixed(p_font_data->transform[0][1] * 65536), FT_Fixed(p_font_data->transform[1][0] * 65536), FT_Fixed(p_font_data->transform[1][1] * 65536) }; // 16.16 fractional units (1 / 65536).
+ FT_Outline_Transform(&fd->face->glyph->outline, &mat);
+ }
+
if (!outline) {
if (!p_font_data->msdf) {
error = FT_Render_Glyph(fd->face->glyph, p_font_data->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO);
@@ -1044,6 +1060,44 @@ TextServer::SubpixelPositioning TextServerFallback::font_get_subpixel_positionin
return fd->subpixel_positioning;
}
+void TextServerFallback::font_set_embolden(RID p_font_rid, float p_strength) {
+ FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND(!fd);
+
+ MutexLock lock(fd->mutex);
+ if (fd->embolden != p_strength) {
+ _font_clear_cache(fd);
+ fd->embolden = p_strength;
+ }
+}
+
+float TextServerFallback::font_get_embolden(RID p_font_rid) const {
+ FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, 0.f);
+
+ MutexLock lock(fd->mutex);
+ return fd->embolden;
+}
+
+void TextServerFallback::font_set_transform(RID p_font_rid, Transform2D p_transform) {
+ FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND(!fd);
+
+ MutexLock lock(fd->mutex);
+ if (fd->transform != p_transform) {
+ _font_clear_cache(fd);
+ fd->transform = p_transform;
+ }
+}
+
+Transform2D TextServerFallback::font_get_transform(RID p_font_rid) const {
+ FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, Transform2D());
+
+ MutexLock lock(fd->mutex);
+ return fd->transform;
+}
+
void TextServerFallback::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h
index 91afd02ae9..d4c7b5666e 100644
--- a/modules/text_server_fb/text_server_fb.h
+++ b/modules/text_server_fb/text_server_fb.h
@@ -142,6 +142,8 @@ class TextServerFallback : public TextServer {
TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
Dictionary variation_coordinates;
float oversampling = 0.f;
+ float embolden = 0.f;
+ Transform2D transform;
uint32_t style_flags = 0;
String font_name;
@@ -172,7 +174,7 @@ class TextServerFallback : public TextServer {
}
};
- _FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontDataForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height) const;
+ _FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontDataForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const;
#ifdef MODULE_MSDFGEN_ENABLED
_FORCE_INLINE_ FontGlyph rasterize_msdf(FontDataFallback *p_font_data, FontDataForSizeFallback *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const;
#endif
@@ -294,6 +296,12 @@ public:
virtual void font_set_subpixel_positioning(RID p_font_rid, SubpixelPositioning p_subpixel) override;
virtual SubpixelPositioning font_get_subpixel_positioning(RID p_font_rid) const override;
+ virtual void font_set_embolden(RID p_font_rid, float p_strength) override;
+ virtual float font_get_embolden(RID p_font_rid) const override;
+
+ virtual void font_set_transform(RID p_font_rid, Transform2D p_transform) override;
+ virtual Transform2D font_get_transform(RID p_font_rid) const override;
+
virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override;
virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override;
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index ca6a45cb83..4220c57cae 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -1387,6 +1387,7 @@ void EditorExportPlatformAndroid::_fix_resources(const Ref<EditorExportPreset> &
Vector<String> string_table;
String package_name = p_preset->get("package/name");
+ Dictionary appnames = ProjectSettings::get_singleton()->get("application/config/name_localized");
for (uint32_t i = 0; i < string_count; i++) {
uint32_t offset = decode_uint32(&r_manifest[string_table_begins + i * 4]);
@@ -1401,9 +1402,8 @@ void EditorExportPlatformAndroid::_fix_resources(const Ref<EditorExportPreset> &
} else {
String lang = str.substr(str.rfind("-") + 1, str.length()).replace("-", "_");
- String prop = "application/config/name_" + lang;
- if (ProjectSettings::get_singleton()->has_setting(prop)) {
- str = ProjectSettings::get_singleton()->get(prop);
+ if (appnames.has(lang)) {
+ str = appnames[lang];
} else {
str = get_project_name(package_name);
}
diff --git a/platform/android/export/gradle_export_util.cpp b/platform/android/export/gradle_export_util.cpp
index 9598d2f9fd..ab915a5f85 100644
--- a/platform/android/export/gradle_export_util.cpp
+++ b/platform/android/export/gradle_export_util.cpp
@@ -75,11 +75,10 @@ String _get_android_orientation_label(DisplayServer::ScreenOrientation screen_or
// Utility method used to create a directory.
Error create_directory(const String &p_dir) {
if (!DirAccess::exists(p_dir)) {
- DirAccess *filesystem_da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef filesystem_da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
ERR_FAIL_COND_V_MSG(!filesystem_da, ERR_CANT_CREATE, "Cannot create directory '" + p_dir + "'.");
Error err = filesystem_da->make_dir_recursive(p_dir);
ERR_FAIL_COND_V_MSG(err, ERR_CANT_CREATE, "Cannot create directory '" + p_dir + "'.");
- memdelete(filesystem_da);
}
return OK;
}
@@ -161,6 +160,7 @@ Error _create_project_name_strings_files(const Ref<EditorExportPreset> &p_preset
return ERR_CANT_OPEN;
}
da->list_dir_begin();
+ Dictionary appnames = ProjectSettings::get_singleton()->get("application/config/name_localized");
while (true) {
String file = da->get_next();
if (file.is_empty()) {
@@ -171,10 +171,9 @@ Error _create_project_name_strings_files(const Ref<EditorExportPreset> &p_preset
continue;
}
String locale = file.replace("values-", "").replace("-r", "_");
- String property_name = "application/config/name_" + locale;
String locale_directory = "res://android/build/res/" + file + "/godot_project_name_string.xml";
- if (ProjectSettings::get_singleton()->has_setting(property_name)) {
- String locale_project_name = ProjectSettings::get_singleton()->get(property_name);
+ if (appnames.has(locale)) {
+ String locale_project_name = appnames[locale];
String processed_xml_string = vformat(godot_project_name_xml_string, _android_xml_escape(locale_project_name));
print_verbose("Storing project name for locale " + locale + " under " + locale_directory);
store_string_at_path(locale_directory, processed_xml_string);
diff --git a/platform/iphone/export/export_plugin.cpp b/platform/iphone/export/export_plugin.cpp
index 2eaf5e47ac..26c5acb13e 100644
--- a/platform/iphone/export/export_plugin.cpp
+++ b/platform/iphone/export/export_plugin.cpp
@@ -92,13 +92,10 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/targeted_device_family", PROPERTY_HINT_ENUM, "iPhone,iPad,iPhone & iPad"), 2));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/info"), "Made with Godot Engine"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/bundle_identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0"));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), ""));
Vector<PluginConfigIOS> found_plugins = get_plugins();
for (int i = 0; i < found_plugins.size(); i++) {
@@ -139,8 +136,11 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "user_data/accessible_from_itunes_sharing"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/camera_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the camera"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/camera_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/microphone_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the microphone"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/microphone_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/photolibrary_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need access to the photo library"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/photolibrary_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_120x120", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPhone/iPod Touch with Retina display
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_180x180", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPhone with Retina HD display
@@ -200,8 +200,6 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
strnew += lines[i].replace("$modules_buildgrp", p_config.modules_buildgrp) + "\n";
} else if (lines[i].find("$name") != -1) {
strnew += lines[i].replace("$name", p_config.pkg_name) + "\n";
- } else if (lines[i].find("$info") != -1) {
- strnew += lines[i].replace("$info", p_preset->get("application/info")) + "\n";
} else if (lines[i].find("$bundle_identifier") != -1) {
strnew += lines[i].replace("$bundle_identifier", p_preset->get("application/bundle_identifier")) + "\n";
} else if (lines[i].find("$short_version") != -1) {
@@ -210,8 +208,6 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
strnew += lines[i].replace("$version", p_preset->get("application/version")) + "\n";
} else if (lines[i].find("$signature") != -1) {
strnew += lines[i].replace("$signature", p_preset->get("application/signature")) + "\n";
- } else if (lines[i].find("$copyright") != -1) {
- strnew += lines[i].replace("$copyright", p_preset->get("application/copyright")) + "\n";
} else if (lines[i].find("$team_id") != -1) {
strnew += lines[i].replace("$team_id", p_preset->get("application/app_store_team_id")) + "\n";
} else if (lines[i].find("$default_build_config") != -1) {
@@ -534,7 +530,7 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
String json_description = "{\"images\":[";
String sizes;
- DirAccess *da = DirAccess::open(p_iconset_dir);
+ DirAccessRef da = DirAccess::open(p_iconset_dir);
ERR_FAIL_COND_V_MSG(!da, ERR_CANT_OPEN, "Cannot open directory '" + p_iconset_dir + "'.");
for (uint64_t i = 0; i < (sizeof(icon_infos) / sizeof(icon_infos[0])); ++i) {
@@ -574,7 +570,6 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
}
if (err) {
- memdelete(da);
String err_str = String("Failed to export icon(" + String(info.preset_key) + "): '" + icon_path + "'.");
ERR_PRINT(err_str.utf8().get_data());
return err;
@@ -592,7 +587,6 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
json_description += String("}");
}
json_description += "]}";
- memdelete(da);
FileAccess *json_file = FileAccess::open(p_iconset_dir + "Contents.json", FileAccess::WRITE);
ERR_FAIL_COND_V(!json_file, ERR_CANT_CREATE);
@@ -678,7 +672,7 @@ Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref<EditorExpor
}
Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref<EditorExportPreset> &p_preset, const String &p_dest_dir) {
- DirAccess *da = DirAccess::open(p_dest_dir);
+ DirAccessRef da = DirAccess::open(p_dest_dir);
ERR_FAIL_COND_V_MSG(!da, ERR_CANT_OPEN, "Cannot open directory '" + p_dest_dir + "'.");
for (uint64_t i = 0; i < sizeof(loading_screen_infos) / sizeof(loading_screen_infos[0]); ++i) {
@@ -716,7 +710,6 @@ Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref<EditorExp
err = da->copy(loading_screen_file, p_dest_dir + info.export_name);
}
if (err) {
- memdelete(da);
String err_str = String("Failed to export loading screen (") + info.preset_key + ") from path '" + loading_screen_file + "'.";
ERR_PRINT(err_str.utf8().get_data());
return err;
@@ -764,7 +757,6 @@ Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref<EditorExp
}
}
}
- memdelete(da);
return OK;
}
@@ -970,21 +962,15 @@ void EditorExportPlatformIOS::_add_assets_to_project(const Ref<EditorExportPrese
}
Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String &p_asset, const String *p_custom_file_name, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets) {
- DirAccess *filesystem_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- ERR_FAIL_COND_V_MSG(!filesystem_da, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_out_dir + "'.");
-
String binary_name = p_out_dir.get_file().get_basename();
- DirAccess *da = DirAccess::create_for_path(p_asset);
+ DirAccessRef da = DirAccess::create_for_path(p_asset);
if (!da) {
- memdelete(filesystem_da);
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Can't create directory: " + p_asset + ".");
}
bool file_exists = da->file_exists(p_asset);
bool dir_exists = da->dir_exists(p_asset);
if (!file_exists && !dir_exists) {
- memdelete(da);
- memdelete(filesystem_da);
return ERR_FILE_NOT_FOUND;
}
@@ -1044,19 +1030,18 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String
destination = p_out_dir.plus_file(asset_path);
}
+ DirAccessRef filesystem_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ ERR_FAIL_COND_V_MSG(!filesystem_da, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_out_dir + "'.");
+
if (!filesystem_da->dir_exists(destination_dir)) {
Error make_dir_err = filesystem_da->make_dir_recursive(destination_dir);
if (make_dir_err) {
- memdelete(da);
- memdelete(filesystem_da);
return make_dir_err;
}
}
Error err = dir_exists ? da->copy_dir(p_asset, destination) : da->copy(p_asset, destination);
- memdelete(da);
if (err) {
- memdelete(filesystem_da);
return err;
}
IOSExportAsset exported_asset = { binary_name.plus_file(asset_path), p_is_framework, p_should_embed };
@@ -1121,8 +1106,6 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String
}
}
- memdelete(filesystem_da);
-
return OK;
}
@@ -1427,29 +1410,29 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
return ERR_FILE_BAD_PATH;
}
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- if (da) {
- String current_dir = da->get_current_dir();
-
- // remove leftovers from last export so they don't interfere
- // in case some files are no longer needed
- if (da->change_dir(dest_dir + binary_name + ".xcodeproj") == OK) {
- da->erase_contents_recursive();
- }
- if (da->change_dir(dest_dir + binary_name) == OK) {
- da->erase_contents_recursive();
- }
+ {
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ if (da) {
+ String current_dir = da->get_current_dir();
+
+ // remove leftovers from last export so they don't interfere
+ // in case some files are no longer needed
+ if (da->change_dir(dest_dir + binary_name + ".xcodeproj") == OK) {
+ da->erase_contents_recursive();
+ }
+ if (da->change_dir(dest_dir + binary_name) == OK) {
+ da->erase_contents_recursive();
+ }
- da->change_dir(current_dir);
+ da->change_dir(current_dir);
- if (!da->dir_exists(dest_dir + binary_name)) {
- Error err = da->make_dir(dest_dir + binary_name);
- if (err) {
- memdelete(da);
- return err;
+ if (!da->dir_exists(dest_dir + binary_name)) {
+ Error err = da->make_dir(dest_dir + binary_name);
+ if (err) {
+ return err;
+ }
}
}
- memdelete(da);
}
if (ep.step("Making .pck", 0)) {
@@ -1470,9 +1453,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
print_line("Static framework: " + library_to_use);
String pkg_name;
- if (p_preset->get("application/name") != "") {
- pkg_name = p_preset->get("application/name"); // app_name
- } else if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") {
+ if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") {
pkg_name = String(ProjectSettings::get_singleton()->get("application/config/name"));
} else {
pkg_name = "Unnamed";
@@ -1507,7 +1488,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
Vector<IOSExportAsset> assets;
- DirAccess *tmp_app_path = DirAccess::create_for_path(dest_dir);
+ DirAccessRef tmp_app_path = DirAccess::create_for_path(dest_dir);
ERR_FAIL_COND_V(!tmp_app_path, ERR_CANT_CREATE);
print_line("Unzipping...");
@@ -1586,7 +1567,6 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
if (dir_err) {
ERR_PRINT("Can't create '" + dir_name + "'.");
unzClose(src_pkg_zip);
- memdelete(tmp_app_path);
return ERR_CANT_CREATE;
}
}
@@ -1596,7 +1576,6 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
if (!f) {
ERR_PRINT("Can't write '" + file + "'.");
unzClose(src_pkg_zip);
- memdelete(tmp_app_path);
return ERR_CANT_CREATE;
};
f->store_buffer(data.ptr(), data.size());
@@ -1619,28 +1598,48 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
if (!found_library) {
ERR_PRINT("Requested template library '" + library_to_use + "' not found. It might be missing from your template archive.");
- memdelete(tmp_app_path);
return ERR_FILE_NOT_FOUND;
}
+ Dictionary appnames = ProjectSettings::get_singleton()->get("application/config/name_localized");
+ Dictionary camera_usage_descriptions = p_preset->get("privacy/camera_usage_description_localized");
+ Dictionary microphone_usage_descriptions = p_preset->get("privacy/microphone_usage_description_localized");
+ Dictionary photolibrary_usage_descriptions = p_preset->get("privacy/photolibrary_usage_description_localized");
+
Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations");
if (translations.size() > 0) {
{
String fname = dest_dir + binary_name + "/en.lproj";
tmp_app_path->make_dir_recursive(fname);
FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
+ f->store_line("/* Localized versions of Info.plist keys */");
+ f->store_line("");
f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get("application/config/name").operator String() + "\";");
+ f->store_line("NSCameraUsageDescription = \"" + p_preset->get("privacy/camera_usage_description").operator String() + "\";");
+ f->store_line("NSMicrophoneUsageDescription = \"" + p_preset->get("privacy/microphone_usage_description").operator String() + "\";");
+ f->store_line("NSPhotoLibraryUsageDescription = \"" + p_preset->get("privacy/photolibrary_usage_description").operator String() + "\";");
}
for (const String &E : translations) {
Ref<Translation> tr = ResourceLoader::load(E);
if (tr.is_valid()) {
- String fname = dest_dir + binary_name + "/" + tr->get_locale() + ".lproj";
+ String lang = tr->get_locale();
+ String fname = dest_dir + binary_name + "/" + lang + ".lproj";
tmp_app_path->make_dir_recursive(fname);
FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
- String prop = "application/config/name_" + tr->get_locale();
- if (ProjectSettings::get_singleton()->has_setting(prop)) {
- f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get(prop).operator String() + "\";");
+ f->store_line("/* Localized versions of Info.plist keys */");
+ f->store_line("");
+ if (appnames.has(lang)) {
+ f->store_line("CFBundleDisplayName = \"" + appnames[lang].operator String() + "\";");
+ }
+ if (camera_usage_descriptions.has(lang)) {
+ f->store_line("NSCameraUsageDescription = \"" + camera_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (microphone_usage_descriptions.has(lang)) {
+ f->store_line("NSMicrophoneUsageDescription = \"" + microphone_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (photolibrary_usage_descriptions.has(lang)) {
+ f->store_line("NSPhotoLibraryUsageDescription = \"" + photolibrary_usage_descriptions[lang].operator String() + "\";");
}
}
}
@@ -1656,7 +1655,6 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
Error lib_copy_err = tmp_app_path->copy(static_lib_path, dest_lib_file_path);
if (lib_copy_err != OK) {
ERR_PRINT("Can't copy '" + static_lib_path + "'.");
- memdelete(tmp_app_path);
return lib_copy_err;
}
}
@@ -1667,7 +1665,6 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
if (!tmp_app_path->dir_exists(iconset_dir)) {
err = tmp_app_path->make_dir_recursive(iconset_dir);
}
- memdelete(tmp_app_path);
if (err) {
return err;
}
@@ -1677,43 +1674,43 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
return err;
}
- bool use_storyboard = p_preset->get("storyboard/use_launch_screen_storyboard");
+ {
+ bool use_storyboard = p_preset->get("storyboard/use_launch_screen_storyboard");
- String launch_image_path = dest_dir + binary_name + "/Images.xcassets/LaunchImage.launchimage/";
- String splash_image_path = dest_dir + binary_name + "/Images.xcassets/SplashImage.imageset/";
+ String launch_image_path = dest_dir + binary_name + "/Images.xcassets/LaunchImage.launchimage/";
+ String splash_image_path = dest_dir + binary_name + "/Images.xcassets/SplashImage.imageset/";
- DirAccess *launch_screen_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef launch_screen_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- if (!launch_screen_da) {
- return ERR_CANT_CREATE;
- }
+ if (!launch_screen_da) {
+ return ERR_CANT_CREATE;
+ }
- if (use_storyboard) {
- print_line("Using Launch Storyboard");
+ if (use_storyboard) {
+ print_line("Using Launch Storyboard");
- if (launch_screen_da->change_dir(launch_image_path) == OK) {
- launch_screen_da->erase_contents_recursive();
- launch_screen_da->remove(launch_image_path);
- }
+ if (launch_screen_da->change_dir(launch_image_path) == OK) {
+ launch_screen_da->erase_contents_recursive();
+ launch_screen_da->remove(launch_image_path);
+ }
- err = _export_loading_screen_file(p_preset, splash_image_path);
- } else {
- print_line("Using Launch Images");
+ err = _export_loading_screen_file(p_preset, splash_image_path);
+ } else {
+ print_line("Using Launch Images");
- const String launch_screen_path = dest_dir + binary_name + "/Launch Screen.storyboard";
+ const String launch_screen_path = dest_dir + binary_name + "/Launch Screen.storyboard";
- launch_screen_da->remove(launch_screen_path);
+ launch_screen_da->remove(launch_screen_path);
- if (launch_screen_da->change_dir(splash_image_path) == OK) {
- launch_screen_da->erase_contents_recursive();
- launch_screen_da->remove(splash_image_path);
- }
+ if (launch_screen_da->change_dir(splash_image_path) == OK) {
+ launch_screen_da->erase_contents_recursive();
+ launch_screen_da->remove(splash_image_path);
+ }
- err = _export_loading_screen_images(p_preset, launch_image_path);
+ err = _export_loading_screen_images(p_preset, launch_image_path);
+ }
}
- memdelete(launch_screen_da);
-
if (err) {
return err;
}
@@ -1732,15 +1729,17 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
memdelete(f);
#ifdef OSX_ENABLED
- if (ep.step("Code-signing dylibs", 2)) {
- return ERR_SKIP;
+ {
+ if (ep.step("Code-signing dylibs", 2)) {
+ return ERR_SKIP;
+ }
+ DirAccess *dylibs_dir = DirAccess::open(dest_dir + binary_name + "/dylibs");
+ ERR_FAIL_COND_V(!dylibs_dir, ERR_CANT_OPEN);
+ CodesignData codesign_data(p_preset, p_debug);
+ err = _walk_dir_recursive(dylibs_dir, _codesign, &codesign_data);
+ memdelete(dylibs_dir);
+ ERR_FAIL_COND_V(err, err);
}
- DirAccess *dylibs_dir = DirAccess::open(dest_dir + binary_name + "/dylibs");
- ERR_FAIL_COND_V(!dylibs_dir, ERR_CANT_OPEN);
- CodesignData codesign_data(p_preset, p_debug);
- err = _walk_dir_recursive(dylibs_dir, _codesign, &codesign_data);
- memdelete(dylibs_dir);
- ERR_FAIL_COND_V(err, err);
if (ep.step("Making .xcarchive", 3)) {
return ERR_SKIP;
diff --git a/platform/iphone/os_iphone.mm b/platform/iphone/os_iphone.mm
index 56cb49318c..1d990b5625 100644
--- a/platform/iphone/os_iphone.mm
+++ b/platform/iphone/os_iphone.mm
@@ -259,11 +259,9 @@ Error OSIPhone::shell_open(String p_uri) {
}
void OSIPhone::set_user_data_dir(String p_dir) {
- DirAccess *da = DirAccess::open(p_dir);
-
+ DirAccessRef da = DirAccess::open(p_dir);
user_data_dir = da->get_current_dir();
printf("setting data dir to %s from %s\n", user_data_dir.utf8().get_data(), p_dir.utf8().get_data());
- memdelete(da);
}
String OSIPhone::get_user_data_dir() const {
diff --git a/platform/javascript/api/javascript_tools_editor_plugin.cpp b/platform/javascript/api/javascript_tools_editor_plugin.cpp
index bea54ae1cb..0442a1eaeb 100644
--- a/platform/javascript/api/javascript_tools_editor_plugin.cpp
+++ b/platform/javascript/api/javascript_tools_editor_plugin.cpp
@@ -124,7 +124,7 @@ void JavaScriptToolsEditorPlugin::_zip_file(String p_path, String p_base_path, z
}
void JavaScriptToolsEditorPlugin::_zip_recursive(String p_path, String p_base_path, zipFile p_zip) {
- DirAccess *dir = DirAccess::open(p_path);
+ DirAccessRef dir = DirAccess::open(p_path);
if (!dir) {
WARN_PRINT("Unable to open directory for zipping: " + p_path);
return;
diff --git a/platform/javascript/export/export_plugin.cpp b/platform/javascript/export/export_plugin.cpp
index c7e503732d..e7855acf60 100644
--- a/platform/javascript/export/export_plugin.cpp
+++ b/platform/javascript/export/export_plugin.cpp
@@ -252,7 +252,7 @@ Error EditorExportPlatformJavaScript::_build_pwa(const Ref<EditorExportPreset> &
// Custom offline page
const String offline_page = p_preset->get("progressive_web_app/offline_page");
if (!offline_page.is_empty()) {
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
const String offline_dest = dir.plus_file(name + ".offline.html");
err = da->copy(ProjectSettings::get_singleton()->globalize_path(offline_page), offline_dest);
if (err != OK) {
@@ -445,18 +445,18 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese
EditorNode::get_singleton()->show_warning(TTR("Could not write file:") + "\n" + pck_path);
return error;
}
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- for (int i = 0; i < shared_objects.size(); i++) {
- String dst = base_dir.plus_file(shared_objects[i].path.get_file());
- error = da->copy(shared_objects[i].path, dst);
- if (error != OK) {
- EditorNode::get_singleton()->show_warning(TTR("Could not write file:") + "\n" + shared_objects[i].path.get_file());
- memdelete(da);
- return error;
+
+ {
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ for (int i = 0; i < shared_objects.size(); i++) {
+ String dst = base_dir.plus_file(shared_objects[i].path.get_file());
+ error = da->copy(shared_objects[i].path, dst);
+ if (error != OK) {
+ EditorNode::get_singleton()->show_warning(TTR("Could not write file:") + "\n" + shared_objects[i].path.get_file());
+ return error;
+ }
}
}
- memdelete(da);
- da = nullptr;
// Extract templates.
error = _extract_template(template_path, base_dir, base_name, pwa);
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index 140368987c..86874687ad 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -535,9 +535,8 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
// Issue an error if "mv" failed to move the given resource to the trash can.
if (err != OK || retval != 0) {
ERR_PRINT("move_to_trash: Could not move the resource \"" + path + "\" to the trash can \"" + trash_path + "/files\"");
- DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
err = dir_access->rename(renamed_path, path);
- memdelete(dir_access);
ERR_FAIL_COND_V_MSG(err != OK, err, "Could not rename \"" + renamed_path + "\" back to its original name: \"" + path + "\"");
return FAILED;
}
diff --git a/platform/osx/export/codesign.cpp b/platform/osx/export/codesign.cpp
index 1a2ad2bee6..b609a21c44 100644
--- a/platform/osx/export/codesign.cpp
+++ b/platform/osx/export/codesign.cpp
@@ -1208,7 +1208,7 @@ Error CodeSign::_codesign_file(bool p_use_hardened_runtime, bool p_force, const
String id;
String main_exe = p_exe_path;
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (!da) {
r_error_msg = TTR("Can't get filesystem access.");
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "CodeSign: Can't get filesystem access.");
@@ -1522,7 +1522,7 @@ Error CodeSign::_codesign_file(bool p_use_hardened_runtime, bool p_force, const
}
Error CodeSign::codesign(bool p_use_hardened_runtime, bool p_force, const String &p_path, const String &p_ent_path, String &r_error_msg) {
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (!da) {
r_error_msg = TTR("Can't get filesystem access.");
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "CodeSign: Can't get filesystem access.");
diff --git a/platform/osx/export/export_plugin.cpp b/platform/osx/export/export_plugin.cpp
index 4d0fc9add6..0f4477d312 100644
--- a/platform/osx/export/export_plugin.cpp
+++ b/platform/osx/export/export_plugin.cpp
@@ -72,8 +72,6 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/info"), "Made with Godot Engine"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.png,*.icns"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/bundle_identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), ""));
@@ -81,18 +79,30 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "application/copyright_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "display/high_res"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/microphone_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the microphone"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/microphone_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/camera_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the camera"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/camera_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/location_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the location information"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/location_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/address_book_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the address book"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/address_book_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/calendar_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the calendar"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/calendar_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/photos_library_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the photo library"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/photos_library_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/desktop_folder_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use Desktop folder"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/desktop_folder_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/documents_folder_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use Documents folder"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/documents_folder_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/downloads_folder_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use Downloads folder"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/downloads_folder_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/network_volumes_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use network volumes"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/network_volumes_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/removable_volumes_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use removable volumes"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/removable_volumes_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/enable"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_PLACEHOLDER_TEXT, "Type: Name (ID)"), ""));
@@ -316,9 +326,7 @@ void EditorExportPlatformOSX::_fix_plist(const Ref<EditorExportPreset> &p_preset
if (lines[i].find("$binary") != -1) {
strnew += lines[i].replace("$binary", p_binary) + "\n";
} else if (lines[i].find("$name") != -1) {
- strnew += lines[i].replace("$name", p_binary) + "\n";
- } else if (lines[i].find("$info") != -1) {
- strnew += lines[i].replace("$info", p_preset->get("application/info")) + "\n";
+ strnew += lines[i].replace("$name", ProjectSettings::get_singleton()->get("application/config/name")) + "\n";
} else if (lines[i].find("$bundle_identifier") != -1) {
strnew += lines[i].replace("$bundle_identifier", p_preset->get("application/bundle_identifier")) + "\n";
} else if (lines[i].find("$short_version") != -1) {
@@ -713,9 +721,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
String binary_to_use = "godot_osx_" + String(p_debug ? "debug" : "release") + ".64";
String pkg_name;
- if (p_preset->get("application/name") != "") {
- pkg_name = p_preset->get("application/name"); // app_name
- } else if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") {
+ if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") {
pkg_name = String(ProjectSettings::get_singleton()->get("application/config/name"));
} else {
pkg_name = "Unnamed";
@@ -781,24 +787,112 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
err = tmp_app_dir->make_dir_recursive(tmp_app_path_name + "/Contents/Resources");
}
+ Dictionary appnames = ProjectSettings::get_singleton()->get("application/config/name_localized");
+ Dictionary microphone_usage_descriptions = p_preset->get("privacy/microphone_usage_description_localized");
+ Dictionary camera_usage_descriptions = p_preset->get("privacy/camera_usage_description_localized");
+ Dictionary location_usage_descriptions = p_preset->get("privacy/location_usage_description_localized");
+ Dictionary address_book_usage_descriptions = p_preset->get("privacy/address_book_usage_description_localized");
+ Dictionary calendar_usage_descriptions = p_preset->get("privacy/calendar_usage_description_localized");
+ Dictionary photos_library_usage_descriptions = p_preset->get("privacy/photos_library_usage_description_localized");
+ Dictionary desktop_folder_usage_descriptions = p_preset->get("privacy/desktop_folder_usage_description_localized");
+ Dictionary documents_folder_usage_descriptions = p_preset->get("privacy/documents_folder_usage_description_localized");
+ Dictionary downloads_folder_usage_descriptions = p_preset->get("privacy/downloads_folder_usage_description_localized");
+ Dictionary network_volumes_usage_descriptions = p_preset->get("privacy/network_volumes_usage_description_localized");
+ Dictionary removable_volumes_usage_descriptions = p_preset->get("privacy/removable_volumes_usage_description_localized");
+ Dictionary copyrights = p_preset->get("application/copyright_localized");
+
Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations");
if (translations.size() > 0) {
{
String fname = tmp_app_path_name + "/Contents/Resources/en.lproj";
tmp_app_dir->make_dir_recursive(fname);
FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
+ f->store_line("/* Localized versions of Info.plist keys */");
+ f->store_line("");
f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get("application/config/name").operator String() + "\";");
+ if (!((String)p_preset->get("privacy/microphone_usage_description")).is_empty()) {
+ f->store_line("NSMicrophoneUsageDescription = \"" + p_preset->get("privacy/microphone_usage_description").operator String() + "\";");
+ }
+ if (!((String)p_preset->get("privacy/camera_usage_description")).is_empty()) {
+ f->store_line("NSCameraUsageDescription = \"" + p_preset->get("privacy/camera_usage_description").operator String() + "\";");
+ }
+ if (!((String)p_preset->get("privacy/location_usage_description")).is_empty()) {
+ f->store_line("NSLocationUsageDescription = \"" + p_preset->get("privacy/location_usage_description").operator String() + "\";");
+ }
+ if (!((String)p_preset->get("privacy/address_book_usage_description")).is_empty()) {
+ f->store_line("NSContactsUsageDescription = \"" + p_preset->get("privacy/address_book_usage_description").operator String() + "\";");
+ }
+ if (!((String)p_preset->get("privacy/calendar_usage_description")).is_empty()) {
+ f->store_line("NSCalendarsUsageDescription = \"" + p_preset->get("privacy/calendar_usage_description").operator String() + "\";");
+ }
+ if (!((String)p_preset->get("privacy/photos_library_usage_description")).is_empty()) {
+ f->store_line("NSPhotoLibraryUsageDescription = \"" + p_preset->get("privacy/photos_library_usage_description").operator String() + "\";");
+ }
+ if (!((String)p_preset->get("privacy/desktop_folder_usage_description")).is_empty()) {
+ f->store_line("NSDesktopFolderUsageDescription = \"" + p_preset->get("privacy/desktop_folder_usage_description").operator String() + "\";");
+ }
+ if (!((String)p_preset->get("privacy/documents_folder_usage_description")).is_empty()) {
+ f->store_line("NSDocumentsFolderUsageDescription = \"" + p_preset->get("privacy/documents_folder_usage_description").operator String() + "\";");
+ }
+ if (!((String)p_preset->get("privacy/downloads_folder_usage_description")).is_empty()) {
+ f->store_line("NSDownloadsFolderUsageDescription = \"" + p_preset->get("privacy/downloads_folder_usage_description").operator String() + "\";");
+ }
+ if (!((String)p_preset->get("privacy/network_volumes_usage_description")).is_empty()) {
+ f->store_line("NSNetworkVolumesUsageDescription = \"" + p_preset->get("privacy/network_volumes_usage_description").operator String() + "\";");
+ }
+ if (!((String)p_preset->get("privacy/removable_volumes_usage_description")).is_empty()) {
+ f->store_line("NSRemovableVolumesUsageDescription = \"" + p_preset->get("privacy/removable_volumes_usage_description").operator String() + "\";");
+ }
+ f->store_line("NSHumanReadableCopyright = \"" + p_preset->get("application/copyright").operator String() + "\";");
}
for (const String &E : translations) {
Ref<Translation> tr = ResourceLoader::load(E);
if (tr.is_valid()) {
- String fname = tmp_app_path_name + "/Contents/Resources/" + tr->get_locale() + ".lproj";
+ String lang = tr->get_locale();
+ String fname = tmp_app_path_name + "/Contents/Resources/" + lang + ".lproj";
tmp_app_dir->make_dir_recursive(fname);
FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
- String prop = "application/config/name_" + tr->get_locale();
- if (ProjectSettings::get_singleton()->has_setting(prop)) {
- f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get(prop).operator String() + "\";");
+ f->store_line("/* Localized versions of Info.plist keys */");
+ f->store_line("");
+ if (appnames.has(lang)) {
+ f->store_line("CFBundleDisplayName = \"" + appnames[lang].operator String() + "\";");
+ }
+ if (microphone_usage_descriptions.has(lang)) {
+ f->store_line("NSMicrophoneUsageDescription = \"" + microphone_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (camera_usage_descriptions.has(lang)) {
+ f->store_line("NSCameraUsageDescription = \"" + camera_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (location_usage_descriptions.has(lang)) {
+ f->store_line("NSLocationUsageDescription = \"" + location_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (address_book_usage_descriptions.has(lang)) {
+ f->store_line("NSContactsUsageDescription = \"" + address_book_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (calendar_usage_descriptions.has(lang)) {
+ f->store_line("NSCalendarsUsageDescription = \"" + calendar_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (photos_library_usage_descriptions.has(lang)) {
+ f->store_line("NSPhotoLibraryUsageDescription = \"" + photos_library_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (desktop_folder_usage_descriptions.has(lang)) {
+ f->store_line("NSDesktopFolderUsageDescription = \"" + desktop_folder_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (documents_folder_usage_descriptions.has(lang)) {
+ f->store_line("NSDocumentsFolderUsageDescription = \"" + documents_folder_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (downloads_folder_usage_descriptions.has(lang)) {
+ f->store_line("NSDownloadsFolderUsageDescription = \"" + downloads_folder_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (network_volumes_usage_descriptions.has(lang)) {
+ f->store_line("NSNetworkVolumesUsageDescription = \"" + network_volumes_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (removable_volumes_usage_descriptions.has(lang)) {
+ f->store_line("NSRemovableVolumesUsageDescription = \"" + removable_volumes_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (copyrights.has(lang)) {
+ f->store_line("NSHumanReadableCopyright = \"" + copyrights[lang].operator String() + "\";");
}
}
}
diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h
index 36a6b262b0..7a50efe40f 100644
--- a/scene/gui/file_dialog.h
+++ b/scene/gui/file_dialog.h
@@ -70,7 +70,6 @@ private:
Button *makedir;
Access access = ACCESS_RESOURCES;
- //Button *action;
VBoxContainer *vbox;
FileMode mode;
LineEdit *dir;
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 61114333fb..da37228ed9 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -103,7 +103,7 @@ static Ref<StyleBox> make_empty_stylebox(float p_margin_left = -1, float p_margi
return style;
}
-void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale) {
+void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &bold_font, const Ref<Font> &bold_italics_font, const Ref<Font> &italics_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale) {
scale = p_scale;
// Font colors
@@ -924,9 +924,9 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Te
theme->set_stylebox("normal", "RichTextLabel", make_empty_stylebox(0, 0, 0, 0));
theme->set_font("normal_font", "RichTextLabel", Ref<Font>());
- theme->set_font("bold_font", "RichTextLabel", Ref<Font>());
- theme->set_font("italics_font", "RichTextLabel", Ref<Font>());
- theme->set_font("bold_italics_font", "RichTextLabel", Ref<Font>());
+ theme->set_font("bold_font", "RichTextLabel", bold_font);
+ theme->set_font("italics_font", "RichTextLabel", italics_font);
+ theme->set_font("bold_italics_font", "RichTextLabel", bold_italics_font);
theme->set_font("mono_font", "RichTextLabel", Ref<Font>());
theme->set_font_size("normal_font_size", "RichTextLabel", -1);
@@ -1025,6 +1025,9 @@ void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPos
Ref<StyleBox> default_style;
Ref<Texture2D> default_icon;
Ref<Font> default_font;
+ Ref<Font> bold_font;
+ Ref<Font> bold_italics_font;
+ Ref<Font> italics_font;
float default_scale = CLAMP(p_scale, 0.5, 8.0);
if (p_font.is_valid()) {
@@ -1048,7 +1051,31 @@ void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPos
default_font = dynamic_font;
}
- fill_default_theme(t, default_font, default_icon, default_style, default_scale);
+ if (default_font.is_valid()) {
+ bold_font.instantiate();
+ for (int i = 0; i < default_font->get_data_count(); i++) {
+ Ref<FontData> data = default_font->get_data(i)->duplicate();
+ data->set_embolden(1.2);
+ bold_font->add_data(data);
+ }
+
+ bold_italics_font.instantiate();
+ for (int i = 0; i < default_font->get_data_count(); i++) {
+ Ref<FontData> data = default_font->get_data(i)->duplicate();
+ data->set_embolden(1.2);
+ data->set_transform(Transform2D(1.0, 0.4, 0.0, 1.0, 0.0, 0.0));
+ bold_italics_font->add_data(data);
+ }
+
+ italics_font.instantiate();
+ for (int i = 0; i < default_font->get_data_count(); i++) {
+ Ref<FontData> data = default_font->get_data(i)->duplicate();
+ data->set_transform(Transform2D(1.0, 0.4, 0.0, 1.0, 0.0, 0.0));
+ italics_font->add_data(data);
+ }
+ }
+
+ fill_default_theme(t, default_font, bold_font, bold_italics_font, italics_font, default_icon, default_style, default_scale);
Theme::set_default(t);
Theme::set_fallback_base_scale(default_scale);
diff --git a/scene/resources/default_theme/default_theme.h b/scene/resources/default_theme/default_theme.h
index 28afd5f5e1..a9e21dda3f 100644
--- a/scene/resources/default_theme/default_theme.h
+++ b/scene/resources/default_theme/default_theme.h
@@ -35,7 +35,7 @@
const int default_font_size = 16;
-void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale);
+void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &bold_font, const Ref<Font> &bold_italics_font, const Ref<Font> &italics_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale);
void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_subpixel, TextServer::Hinting p_hinting, bool p_aa);
void clear_default_theme();
diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp
index 5b57e93950..ce2a675854 100644
--- a/scene/resources/font.cpp
+++ b/scene/resources/font.cpp
@@ -61,6 +61,8 @@ _FORCE_INLINE_ void FontData::_ensure_rid(int p_cache_index) const {
TS->font_set_force_autohinter(cache[p_cache_index], force_autohinter);
TS->font_set_hinting(cache[p_cache_index], hinting);
TS->font_set_subpixel_positioning(cache[p_cache_index], subpixel_positioning);
+ TS->font_set_embolden(cache[p_cache_index], embolden);
+ TS->font_set_transform(cache[p_cache_index], transform);
TS->font_set_oversampling(cache[p_cache_index], oversampling);
}
}
@@ -105,6 +107,12 @@ void FontData::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_subpixel_positioning", "subpixel_positioning"), &FontData::set_subpixel_positioning);
ClassDB::bind_method(D_METHOD("get_subpixel_positioning"), &FontData::get_subpixel_positioning);
+ ClassDB::bind_method(D_METHOD("set_embolden", "strength"), &FontData::set_embolden);
+ ClassDB::bind_method(D_METHOD("get_embolden"), &FontData::get_embolden);
+
+ ClassDB::bind_method(D_METHOD("set_transform", "transform"), &FontData::set_transform);
+ ClassDB::bind_method(D_METHOD("get_transform"), &FontData::get_transform);
+
ClassDB::bind_method(D_METHOD("set_oversampling", "oversampling"), &FontData::set_oversampling);
ClassDB::bind_method(D_METHOD("get_oversampling"), &FontData::get_oversampling);
@@ -209,6 +217,8 @@ void FontData::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "style_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style_name", "get_font_style_name");
ADD_PROPERTY(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style", "get_font_style");
ADD_PROPERTY(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel", PROPERTY_USAGE_STORAGE), "set_subpixel_positioning", "get_subpixel_positioning");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "embolden", PROPERTY_HINT_RANGE, "-2,2,0.01", PROPERTY_USAGE_STORAGE), "set_embolden", "get_embolden");
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_transform", "get_transform");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_multichannel_signed_distance_field", "is_multichannel_signed_distance_field");
ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_msdf_pixel_range", "get_msdf_pixel_range");
ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_msdf_size", "get_msdf_size");
@@ -439,6 +449,8 @@ void FontData::reset_state() {
msdf_pixel_range = 14;
msdf_size = 128;
fixed_size = 0;
+ embolden = 0.f;
+ transform = Transform2D();
oversampling = 0.f;
}
@@ -1385,6 +1397,36 @@ TextServer::SubpixelPositioning FontData::get_subpixel_positioning() const {
return subpixel_positioning;
}
+void FontData::set_embolden(float p_strength) {
+ if (embolden != p_strength) {
+ embolden = p_strength;
+ for (int i = 0; i < cache.size(); i++) {
+ _ensure_rid(i);
+ TS->font_set_embolden(cache[i], embolden);
+ }
+ emit_changed();
+ }
+}
+
+float FontData::get_embolden() const {
+ return embolden;
+}
+
+void FontData::set_transform(Transform2D p_transform) {
+ if (transform != p_transform) {
+ transform = p_transform;
+ for (int i = 0; i < cache.size(); i++) {
+ _ensure_rid(i);
+ TS->font_set_transform(cache[i], transform);
+ }
+ emit_changed();
+ }
+}
+
+Transform2D FontData::get_transform() const {
+ return transform;
+}
+
void FontData::set_oversampling(real_t p_oversampling) {
if (oversampling != p_oversampling) {
oversampling = p_oversampling;
diff --git a/scene/resources/font.h b/scene/resources/font.h
index aaf0a7fe7b..0185b019f1 100644
--- a/scene/resources/font.h
+++ b/scene/resources/font.h
@@ -57,6 +57,8 @@ class FontData : public Resource {
TextServer::Hinting hinting = TextServer::HINTING_LIGHT;
TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
real_t oversampling = 0.f;
+ real_t embolden = 0.f;
+ Transform2D transform;
// Cache.
mutable Vector<RID> cache;
@@ -122,6 +124,12 @@ public:
virtual void set_subpixel_positioning(TextServer::SubpixelPositioning p_subpixel);
virtual TextServer::SubpixelPositioning get_subpixel_positioning() const;
+ virtual void set_embolden(float p_strength);
+ virtual float get_embolden() const;
+
+ virtual void set_transform(Transform2D p_transform);
+ virtual Transform2D get_transform() const;
+
virtual void set_oversampling(real_t p_oversampling);
virtual real_t get_oversampling() const;
diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp
index d9ac967699..fd6f018651 100644
--- a/scene/resources/resource_format_text.cpp
+++ b/scene/resources/resource_format_text.cpp
@@ -908,10 +908,9 @@ Error ResourceLoaderText::rename_dependencies(FileAccess *p_f, const String &p_p
return ERR_CANT_CREATE;
}
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
da->remove(p_path);
da->rename(p_path + ".depren", p_path);
- memdelete(da);
return OK;
}
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index d541284381..1930fa2682 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -482,24 +482,24 @@ void CompressedTexture2D::set_path(const String &p_path, bool p_take_over) {
}
void CompressedTexture2D::_requested_3d(void *p_ud) {
- CompressedTexture2D *st = (CompressedTexture2D *)p_ud;
- Ref<CompressedTexture2D> stex(st);
+ CompressedTexture2D *ct = (CompressedTexture2D *)p_ud;
+ Ref<CompressedTexture2D> ctex(ct);
ERR_FAIL_COND(!request_3d_callback);
- request_3d_callback(stex);
+ request_3d_callback(ctex);
}
void CompressedTexture2D::_requested_roughness(void *p_ud, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_roughness_channel) {
- CompressedTexture2D *st = (CompressedTexture2D *)p_ud;
- Ref<CompressedTexture2D> stex(st);
+ CompressedTexture2D *ct = (CompressedTexture2D *)p_ud;
+ Ref<CompressedTexture2D> ctex(ct);
ERR_FAIL_COND(!request_roughness_callback);
- request_roughness_callback(stex, p_normal_path, p_roughness_channel);
+ request_roughness_callback(ctex, p_normal_path, p_roughness_channel);
}
void CompressedTexture2D::_requested_normal(void *p_ud) {
- CompressedTexture2D *st = (CompressedTexture2D *)p_ud;
- Ref<CompressedTexture2D> stex(st);
+ CompressedTexture2D *ct = (CompressedTexture2D *)p_ud;
+ Ref<CompressedTexture2D> ctex(ct);
ERR_FAIL_COND(!request_normal_callback);
- request_normal_callback(stex);
+ request_normal_callback(ctex);
}
CompressedTexture2D::TextureFormatRequestCallback CompressedTexture2D::request_3d_callback = nullptr;
@@ -522,14 +522,14 @@ Error CompressedTexture2D::_load_data(const String &p_path, int &r_width, int &r
f->get_buffer(header, 4);
if (header[0] != 'G' || header[1] != 'S' || header[2] != 'T' || header[3] != '2') {
memdelete(f);
- ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is corrupt (Bad header).");
+ ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Compressed texture file is corrupt (Bad header).");
}
uint32_t version = f->get_32();
if (version > FORMAT_VERSION) {
memdelete(f);
- ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is too new.");
+ ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Compressed texture file is too new.");
}
r_width = f->get_32();
r_height = f->get_32();
@@ -973,11 +973,11 @@ Error CompressedTexture3D::_load_data(const String &p_path, Vector<Ref<Image>> &
f->get_buffer(header, 4);
ERR_FAIL_COND_V(header[0] != 'G' || header[1] != 'S' || header[2] != 'T' || header[3] != 'L', ERR_FILE_UNRECOGNIZED);
- //stored as stream textures (used for lossless and lossy compression)
+ //stored as compressed textures (used for lossless and lossy compression)
uint32_t version = f->get_32();
if (version > FORMAT_VERSION) {
- ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is too new.");
+ ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Compressed texture file is too new.");
}
r_depth = f->get_32(); //depth
@@ -1129,7 +1129,7 @@ RES ResourceFormatLoaderCompressedTexture3D::load(const String &p_path, const St
}
void ResourceFormatLoaderCompressedTexture3D::get_recognized_extensions(List<String> *p_extensions) const {
- p_extensions->push_back("stex3d");
+ p_extensions->push_back("ctex3d");
}
bool ResourceFormatLoaderCompressedTexture3D::handles_type(const String &p_type) const {
@@ -1137,7 +1137,7 @@ bool ResourceFormatLoaderCompressedTexture3D::handles_type(const String &p_type)
}
String ResourceFormatLoaderCompressedTexture3D::get_resource_type(const String &p_path) const {
- if (p_path.get_extension().to_lower() == "stex3d") {
+ if (p_path.get_extension().to_lower() == "ctex3d") {
return "CompressedTexture3D";
}
return "";
@@ -2792,13 +2792,13 @@ Error CompressedTextureLayered::_load_data(const String &p_path, Vector<Ref<Imag
uint8_t header[4];
f->get_buffer(header, 4);
if (header[0] != 'G' || header[1] != 'S' || header[2] != 'T' || header[3] != 'L') {
- ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture layered file is corrupt (Bad header).");
+ ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Compressed texture layered file is corrupt (Bad header).");
}
uint32_t version = f->get_32();
if (version > FORMAT_VERSION) {
- ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is too new.");
+ ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Compressed texture file is too new.");
}
uint32_t layer_count = f->get_32(); //layer count
@@ -2939,26 +2939,26 @@ CompressedTextureLayered::~CompressedTextureLayered() {
/////////////////////////////////////////////////
RES ResourceFormatLoaderCompressedTextureLayered::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
- Ref<CompressedTextureLayered> st;
- if (p_path.get_extension().to_lower() == "stexarray") {
- Ref<CompressedTexture2DArray> s;
- s.instantiate();
- st = s;
- } else if (p_path.get_extension().to_lower() == "scube") {
- Ref<CompressedCubemap> s;
- s.instantiate();
- st = s;
- } else if (p_path.get_extension().to_lower() == "scubearray") {
- Ref<CompressedCubemapArray> s;
- s.instantiate();
- st = s;
+ Ref<CompressedTextureLayered> ct;
+ if (p_path.get_extension().to_lower() == "ctexarray") {
+ Ref<CompressedTexture2DArray> c;
+ c.instantiate();
+ ct = c;
+ } else if (p_path.get_extension().to_lower() == "ccube") {
+ Ref<CompressedCubemap> c;
+ c.instantiate();
+ ct = c;
+ } else if (p_path.get_extension().to_lower() == "ccubearray") {
+ Ref<CompressedCubemapArray> c;
+ c.instantiate();
+ ct = c;
} else {
if (r_error) {
*r_error = ERR_FILE_UNRECOGNIZED;
}
return RES();
}
- Error err = st->load(p_path);
+ Error err = ct->load(p_path);
if (r_error) {
*r_error = err;
}
@@ -2966,13 +2966,13 @@ RES ResourceFormatLoaderCompressedTextureLayered::load(const String &p_path, con
return RES();
}
- return st;
+ return ct;
}
void ResourceFormatLoaderCompressedTextureLayered::get_recognized_extensions(List<String> *p_extensions) const {
- p_extensions->push_back("stexarray");
- p_extensions->push_back("scube");
- p_extensions->push_back("scubearray");
+ p_extensions->push_back("ctexarray");
+ p_extensions->push_back("ccube");
+ p_extensions->push_back("ccubearray");
}
bool ResourceFormatLoaderCompressedTextureLayered::handles_type(const String &p_type) const {
@@ -2980,13 +2980,13 @@ bool ResourceFormatLoaderCompressedTextureLayered::handles_type(const String &p_
}
String ResourceFormatLoaderCompressedTextureLayered::get_resource_type(const String &p_path) const {
- if (p_path.get_extension().to_lower() == "stexarray") {
+ if (p_path.get_extension().to_lower() == "ctexarray") {
return "CompressedTexture2DArray";
}
- if (p_path.get_extension().to_lower() == "scube") {
+ if (p_path.get_extension().to_lower() == "ccube") {
return "CompressedCubemap";
}
- if (p_path.get_extension().to_lower() == "scubearray") {
+ if (p_path.get_extension().to_lower() == "ccubearray") {
return "CompressedCubemapArray";
}
return "";
diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp
index 5792572dc1..1a10161a5b 100644
--- a/servers/text/text_server_extension.cpp
+++ b/servers/text/text_server_extension.cpp
@@ -88,6 +88,12 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(_font_set_subpixel_positioning, "font_rid", "subpixel_positioning");
GDVIRTUAL_BIND(_font_get_subpixel_positioning, "font_rid");
+ GDVIRTUAL_BIND(_font_set_embolden, "font_rid", "strength");
+ GDVIRTUAL_BIND(_font_get_embolden, "font_rid");
+
+ GDVIRTUAL_BIND(_font_set_transform, "font_rid", "transform");
+ GDVIRTUAL_BIND(_font_get_transform, "font_rid");
+
GDVIRTUAL_BIND(_font_set_variation_coordinates, "font_rid", "variation_coordinates");
GDVIRTUAL_BIND(_font_get_variation_coordinates, "font_rid");
@@ -527,6 +533,30 @@ TextServer::SubpixelPositioning TextServerExtension::font_get_subpixel_positioni
return TextServer::SubpixelPositioning::SUBPIXEL_POSITIONING_DISABLED;
}
+void TextServerExtension::font_set_embolden(RID p_font_rid, float p_strength) {
+ GDVIRTUAL_CALL(_font_set_embolden, p_font_rid, p_strength);
+}
+
+float TextServerExtension::font_get_embolden(RID p_font_rid) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_font_get_embolden, p_font_rid, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+void TextServerExtension::font_set_transform(RID p_font_rid, Transform2D p_transform) {
+ GDVIRTUAL_CALL(_font_set_transform, p_font_rid, p_transform);
+}
+
+Transform2D TextServerExtension::font_get_transform(RID p_font_rid) const {
+ Transform2D ret;
+ if (GDVIRTUAL_CALL(_font_get_transform, p_font_rid, ret)) {
+ return ret;
+ }
+ return Transform2D();
+}
+
void TextServerExtension::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) {
GDVIRTUAL_CALL(_font_set_variation_coordinates, p_font_rid, p_variation_coordinates);
}
diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h
index d185e44806..7d80467371 100644
--- a/servers/text/text_server_extension.h
+++ b/servers/text/text_server_extension.h
@@ -139,6 +139,16 @@ public:
GDVIRTUAL2(_font_set_subpixel_positioning, RID, SubpixelPositioning);
GDVIRTUAL1RC(SubpixelPositioning, _font_get_subpixel_positioning, RID);
+ virtual void font_set_embolden(RID p_font_rid, float p_strength) override;
+ virtual float font_get_embolden(RID p_font_rid) const override;
+ GDVIRTUAL2(_font_set_embolden, RID, float);
+ GDVIRTUAL1RC(float, _font_get_embolden, RID);
+
+ virtual void font_set_transform(RID p_font_rid, Transform2D p_transform) override;
+ virtual Transform2D font_get_transform(RID p_font_rid) const override;
+ GDVIRTUAL2(_font_set_transform, RID, Transform2D);
+ GDVIRTUAL1RC(Transform2D, _font_get_transform, RID);
+
virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override;
virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override;
GDVIRTUAL2(_font_set_variation_coordinates, RID, Dictionary);
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index e84c0f05cc..d188076607 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -241,6 +241,12 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_set_subpixel_positioning", "font_rid", "subpixel_positioning"), &TextServer::font_set_subpixel_positioning);
ClassDB::bind_method(D_METHOD("font_get_subpixel_positioning", "font_rid"), &TextServer::font_get_subpixel_positioning);
+ ClassDB::bind_method(D_METHOD("font_set_embolden", "font_rid", "strength"), &TextServer::font_set_embolden);
+ ClassDB::bind_method(D_METHOD("font_get_embolden", "font_rid"), &TextServer::font_get_embolden);
+
+ ClassDB::bind_method(D_METHOD("font_set_transform", "font_rid", "transform"), &TextServer::font_set_transform);
+ ClassDB::bind_method(D_METHOD("font_get_transform", "font_rid"), &TextServer::font_get_transform);
+
ClassDB::bind_method(D_METHOD("font_set_variation_coordinates", "font_rid", "variation_coordinates"), &TextServer::font_set_variation_coordinates);
ClassDB::bind_method(D_METHOD("font_get_variation_coordinates", "font_rid"), &TextServer::font_get_variation_coordinates);
diff --git a/servers/text_server.h b/servers/text_server.h
index 38ad496490..83dc3df56d 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -261,6 +261,12 @@ public:
virtual void font_set_subpixel_positioning(RID p_font_rid, SubpixelPositioning p_subpixel) = 0;
virtual SubpixelPositioning font_get_subpixel_positioning(RID p_font_rid) const = 0;
+ virtual void font_set_embolden(RID p_font_rid, float p_strength) = 0;
+ virtual float font_get_embolden(RID p_font_rid) const = 0;
+
+ virtual void font_set_transform(RID p_font_rid, Transform2D p_transform) = 0;
+ virtual Transform2D font_get_transform(RID p_font_rid) const = 0;
+
virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) = 0;
virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const = 0;