summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/core_bind.cpp17
-rw-r--r--core/core_bind.h3
-rw-r--r--core/os/os.cpp7
-rw-r--r--core/os/os.h3
-rw-r--r--doc/classes/Directory.xml2
-rw-r--r--doc/classes/OS.xml8
-rw-r--r--doc/classes/Theme.xml21
-rw-r--r--editor/code_editor.cpp6
-rw-r--r--editor/editor_spin_slider.cpp314
-rw-r--r--editor/editor_spin_slider.h1
-rw-r--r--editor/editor_themes.cpp20
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp15
-rw-r--r--editor/plugins/node_3d_editor_plugin.h2
-rw-r--r--editor/scene_tree_editor.cpp3
-rw-r--r--modules/gdscript/gdscript_cache.cpp2
-rw-r--r--platform/android/android_input_handler.cpp2
-rw-r--r--platform/android/export/export_plugin.cpp18
-rw-r--r--platform/android/export/export_plugin.h2
-rw-r--r--platform/android/export/gradle_export_util.cpp8
-rw-r--r--platform/android/export/gradle_export_util.h2
-rw-r--r--platform/android/java/app/AndroidManifest.xml1
-rw-r--r--platform/android/java/app/config.gradle8
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/Godot.java5
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotIO.java247
-rw-r--r--platform/android/java_godot_io_wrapper.cpp20
-rw-r--r--platform/android/java_godot_io_wrapper.h6
-rw-r--r--platform/android/os_android.cpp18
-rw-r--r--platform/android/os_android.h5
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp2
-rw-r--r--platform/linuxbsd/os_linuxbsd.h2
-rw-r--r--platform/osx/os_osx.h2
-rw-r--r--platform/osx/os_osx.mm2
-rw-r--r--platform/windows/os_windows.cpp2
-rw-r--r--platform/windows/os_windows.h2
-rw-r--r--scene/2d/physics_body_2d.cpp18
-rw-r--r--scene/gui/text_edit.cpp10
-rw-r--r--scene/main/window.cpp2
-rw-r--r--scene/resources/theme.cpp75
-rw-r--r--scene/resources/theme.h3
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h10
40 files changed, 393 insertions, 503 deletions
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index f3f51e57ee..7a2e6765b8 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -456,10 +456,6 @@ String _OS::get_user_data_dir() const {
return OS::get_singleton()->get_user_data_dir();
}
-String _OS::get_external_data_dir() const {
- return OS::get_singleton()->get_external_data_dir();
-}
-
String _OS::get_config_dir() const {
// Exposed as `get_config_dir()` instead of `get_config_path()` for consistency with other exposed OS methods.
return OS::get_singleton()->get_config_path();
@@ -483,8 +479,8 @@ bool _OS::is_debug_build() const {
#endif
}
-String _OS::get_system_dir(SystemDir p_dir) const {
- return OS::get_singleton()->get_system_dir(OS::SystemDir(p_dir));
+String _OS::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
+ return OS::get_singleton()->get_system_dir(OS::SystemDir(p_dir), p_shared_storage);
}
String _OS::get_keycode_string(uint32_t p_code) const {
@@ -567,8 +563,7 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_static_memory_peak_usage"), &_OS::get_static_memory_peak_usage);
ClassDB::bind_method(D_METHOD("get_user_data_dir"), &_OS::get_user_data_dir);
- ClassDB::bind_method(D_METHOD("get_external_data_dir"), &_OS::get_external_data_dir);
- ClassDB::bind_method(D_METHOD("get_system_dir", "dir"), &_OS::get_system_dir);
+ ClassDB::bind_method(D_METHOD("get_system_dir", "dir", "shared_storage"), &_OS::get_system_dir, DEFVAL(true));
ClassDB::bind_method(D_METHOD("get_config_dir"), &_OS::get_config_dir);
ClassDB::bind_method(D_METHOD("get_data_dir"), &_OS::get_data_dir);
ClassDB::bind_method(D_METHOD("get_cache_dir"), &_OS::get_cache_dir);
@@ -1560,15 +1555,17 @@ Error _Directory::copy(String p_from, String p_to) {
Error _Directory::rename(String p_from, String p_to) {
ERR_FAIL_COND_V_MSG(!is_open(), ERR_UNCONFIGURED, "Directory must be opened before use.");
+ ERR_FAIL_COND_V_MSG(p_from.is_empty() || p_from == "." || p_from == "..", ERR_INVALID_PARAMETER, "Invalid path to rename.");
+
if (!p_from.is_rel_path()) {
DirAccess *d = DirAccess::create_for_path(p_from);
- ERR_FAIL_COND_V_MSG(!d->file_exists(p_from), ERR_DOES_NOT_EXIST, "File does not exist.");
+ 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;
}
- ERR_FAIL_COND_V_MSG(!d->file_exists(p_from), ERR_DOES_NOT_EXIST, "File does not exist.");
+ 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.");
return d->rename(p_from, p_to);
}
diff --git a/core/core_bind.h b/core/core_bind.h
index 9060aff340..94e8ab2a34 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -229,10 +229,9 @@ public:
SYSTEM_DIR_RINGTONES,
};
- String get_system_dir(SystemDir p_dir) const;
+ String get_system_dir(SystemDir p_dir, bool p_shared_storage = true) const;
String get_user_data_dir() const;
- String get_external_data_dir() const;
String get_config_dir() const;
String get_data_dir() const;
String get_cache_dir() const;
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 76a6da51e1..63390919f4 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -277,18 +277,13 @@ String OS::get_user_data_dir() const {
return ".";
}
-// Android OS path to app's external data storage
-String OS::get_external_data_dir() const {
- return get_user_data_dir();
-};
-
// Absolute path to res://
String OS::get_resource_dir() const {
return ProjectSettings::get_singleton()->get_resource_path();
}
// Access system-specific dirs like Documents, Downloads, etc.
-String OS::get_system_dir(SystemDir p_dir) const {
+String OS::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
return ".";
}
diff --git a/core/os/os.h b/core/os/os.h
index 0466d94acd..55b21266fc 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -250,7 +250,6 @@ public:
virtual String get_bundle_resource_dir() const;
virtual String get_user_data_dir() const;
- virtual String get_external_data_dir() const;
virtual String get_resource_dir() const;
enum SystemDir {
@@ -264,7 +263,7 @@ public:
SYSTEM_DIR_RINGTONES,
};
- virtual String get_system_dir(SystemDir p_dir) const;
+ virtual String get_system_dir(SystemDir p_dir, bool p_shared_storage = true) const;
virtual Error move_to_trash(const String &p_path) { return FAILED; }
diff --git a/doc/classes/Directory.xml b/doc/classes/Directory.xml
index 919960cc9f..e8e5a286b4 100644
--- a/doc/classes/Directory.xml
+++ b/doc/classes/Directory.xml
@@ -187,7 +187,7 @@
<argument index="0" name="from" type="String" />
<argument index="1" name="to" type="String" />
<description>
- Renames (move) the [code]from[/code] file to the [code]to[/code] destination. Both arguments should be paths to files, either relative or absolute. If the destination file exists and is not access-protected, it will be overwritten.
+ Renames (move) the [code]from[/code] file or directory to the [code]to[/code] destination. Both arguments should be paths to files or directories, either relative or absolute. If the destination file or directory exists and is not access-protected, it will be overwritten.
Returns one of the [enum Error] code constants ([code]OK[/code] on success).
</description>
</method>
diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index e5d45189c7..757730f6c8 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -197,12 +197,6 @@
Returns the path to the current engine executable.
</description>
</method>
- <method name="get_external_data_dir" qualifiers="const">
- <return type="String" />
- <description>
- On Android, returns the absolute directory path where user data can be written to external storage if available. On all other platforms, this will return the same location as [method get_user_data_dir].
- </description>
- </method>
<method name="get_granted_permissions" qualifiers="const">
<return type="PackedStringArray" />
<description>
@@ -270,9 +264,11 @@
<method name="get_system_dir" qualifiers="const">
<return type="String" />
<argument index="0" name="dir" type="int" enum="OS.SystemDir" />
+ <argument index="1" name="shared_storage" type="bool" default="true" />
<description>
Returns the actual path to commonly used folders across different platforms. Available locations are specified in [enum SystemDir].
[b]Note:[/b] This method is implemented on Android, Linux, macOS and Windows.
+ [b]Note:[/b] Shared storage is implemented on Android and allows to differentiate between app specific and shared directories. Shared directories have additional restrictions on Android.
</description>
</method>
<method name="get_thread_caller_id" qualifiers="const">
diff --git a/doc/classes/Theme.xml b/doc/classes/Theme.xml
index 1124fb8084..edf5874432 100644
--- a/doc/classes/Theme.xml
+++ b/doc/classes/Theme.xml
@@ -81,19 +81,6 @@
Unmarks [code]theme_type[/code] as being a variation of any other type.
</description>
</method>
- <method name="copy_default_theme">
- <return type="void" />
- <description>
- Sets the theme's values to a copy of the default theme values.
- </description>
- </method>
- <method name="copy_theme">
- <return type="void" />
- <argument index="0" name="other" type="Theme" />
- <description>
- Sets the theme's values to a copy of a given theme.
- </description>
- </method>
<method name="get_color" qualifiers="const">
<return type="Color" />
<argument index="0" name="name" type="StringName" />
@@ -340,6 +327,14 @@
Returns [code]true[/code] if [code]theme_type[/code] is marked as a variation of [code]base_type[/code] in this theme.
</description>
</method>
+ <method name="merge_with">
+ <return type="void" />
+ <argument index="0" name="other" type="Theme" />
+ <description>
+ Adds missing and overrides existing definitions with values from the [code]other[/code] [Theme].
+ [b]Note:[/b] This modifies the current theme. If you want to merge two themes together without modifying either one, create a new empty theme and merge the other two into it one after another.
+ </description>
+ </method>
<method name="rename_color">
<return type="void" />
<argument index="0" name="old_name" type="StringName" />
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 48f2be450b..39095c42a4 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -1429,13 +1429,13 @@ void CodeTextEditor::toggle_inline_comment(const String &delimiter) {
void CodeTextEditor::goto_line(int p_line) {
text_editor->deselect();
text_editor->unfold_line(p_line);
- text_editor->call_deferred(SNAME("cursor_set_line"), p_line);
+ text_editor->call_deferred(SNAME("set_caret_line"), p_line);
}
void CodeTextEditor::goto_line_selection(int p_line, int p_begin, int p_end) {
text_editor->unfold_line(p_line);
- text_editor->call_deferred(SNAME("cursor_set_line"), p_line);
- text_editor->call_deferred(SNAME("cursor_set_column"), p_begin);
+ text_editor->call_deferred(SNAME("set_caret_line"), p_line);
+ text_editor->call_deferred(SNAME("set_caret_column"), p_begin);
text_editor->select(p_line, p_begin, p_line, p_end);
}
diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp
index a802afda0f..91f00deeaa 100644
--- a/editor/editor_spin_slider.cpp
+++ b/editor/editor_spin_slider.cpp
@@ -195,11 +195,11 @@ void EditorSpinSlider::_update_value_input_stylebox() {
if (!value_input) {
return;
}
+
// Add a left margin to the stylebox to make the number align with the Label
// when it's edited. The LineEdit "focus" stylebox uses the "normal" stylebox's
// default margins.
- Ref<StyleBoxFlat> stylebox =
- EditorNode::get_singleton()->get_theme_base()->get_theme_stylebox(SNAME("normal"), SNAME("LineEdit"))->duplicate();
+ Ref<StyleBox> stylebox = get_theme_stylebox(SNAME("normal"), SNAME("LineEdit"))->duplicate();
// EditorSpinSliders with a label have more space on the left, so add an
// higher margin to match the location where the text begins.
// The margin values below were determined by empirical testing.
@@ -210,188 +210,197 @@ void EditorSpinSlider::_update_value_input_stylebox() {
stylebox->set_default_margin(SIDE_LEFT, (get_label() != String() ? 23 : 16) * EDSCALE);
stylebox->set_default_margin(SIDE_RIGHT, 0);
}
+
value_input->add_theme_style_override("normal", stylebox);
}
-void EditorSpinSlider::_notification(int p_what) {
- if (p_what == NOTIFICATION_WM_WINDOW_FOCUS_OUT ||
- p_what == NOTIFICATION_WM_WINDOW_FOCUS_IN ||
- p_what == NOTIFICATION_EXIT_TREE) {
- if (grabbing_spinner) {
- grabber->hide();
- Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
- grabbing_spinner = false;
- grabbing_spinner_attempt = false;
- }
- }
- if (p_what == NOTIFICATION_READY || p_what == NOTIFICATION_THEME_CHANGED) {
- _update_value_input_stylebox();
- }
+void EditorSpinSlider::_draw_spin_slider() {
+ updown_offset = -1;
- if (p_what == NOTIFICATION_DRAW) {
- updown_offset = -1;
+ RID ci = get_canvas_item();
+ bool rtl = is_layout_rtl();
+ Vector2 size = get_size();
- RID ci = get_canvas_item();
- bool rtl = is_layout_rtl();
- Vector2 size = get_size();
+ Ref<StyleBox> sb = get_theme_stylebox(SNAME("normal"), SNAME("LineEdit"));
+ if (!flat) {
+ draw_style_box(sb, Rect2(Vector2(), size));
+ }
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("LineEdit"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("LineEdit"));
+ int sep_base = 4 * EDSCALE;
+ int sep = sep_base + sb->get_offset().x; //make it have the same margin on both sides, looks better
- Ref<StyleBox> sb = get_theme_stylebox(SNAME("normal"), SNAME("LineEdit"));
- if (!flat) {
- draw_style_box(sb, Rect2(Vector2(), size));
- }
- Ref<Font> font = get_theme_font(SNAME("font"), SNAME("LineEdit"));
- int font_size = get_theme_font_size(SNAME("font_size"), SNAME("LineEdit"));
- int sep_base = 4 * EDSCALE;
- int sep = sep_base + sb->get_offset().x; //make it have the same margin on both sides, looks better
+ int label_width = font->get_string_size(label, font_size).width;
+ int number_width = size.width - sb->get_minimum_size().width - label_width - sep;
- int label_width = font->get_string_size(label, font_size).width;
- int number_width = size.width - sb->get_minimum_size().width - label_width - sep;
+ Ref<Texture2D> updown = get_theme_icon(SNAME("updown"), SNAME("SpinBox"));
- Ref<Texture2D> updown = get_theme_icon(SNAME("updown"), SNAME("SpinBox"));
+ if (get_step() == 1) {
+ number_width -= updown->get_width();
+ }
- if (get_step() == 1) {
- number_width -= updown->get_width();
- }
+ String numstr = get_text_value();
- String numstr = get_text_value();
+ int vofs = (size.height - font->get_height(font_size)) / 2 + font->get_ascent(font_size);
- int vofs = (size.height - font->get_height(font_size)) / 2 + font->get_ascent(font_size);
+ Color fc = get_theme_color(SNAME("font_color"), SNAME("LineEdit"));
+ Color lc;
+ if (use_custom_label_color) {
+ lc = custom_label_color;
+ } else {
+ lc = fc;
+ }
- Color fc = get_theme_color(SNAME("font_color"), SNAME("LineEdit"));
- Color lc;
- if (use_custom_label_color) {
- lc = custom_label_color;
+ if (flat && label != String()) {
+ Color label_bg_color = get_theme_color(SNAME("dark_color_3"), SNAME("Editor"));
+ if (rtl) {
+ draw_rect(Rect2(Vector2(size.width - (sb->get_offset().x * 2 + label_width), 0), Vector2(sb->get_offset().x * 2 + label_width, size.height)), label_bg_color);
} else {
- lc = fc;
+ draw_rect(Rect2(Vector2(), Vector2(sb->get_offset().x * 2 + label_width, size.height)), label_bg_color);
}
+ }
- if (flat && label != String()) {
- Color label_bg_color = get_theme_color(SNAME("dark_color_3"), SNAME("Editor"));
- if (rtl) {
- draw_rect(Rect2(Vector2(size.width - (sb->get_offset().x * 2 + label_width), 0), Vector2(sb->get_offset().x * 2 + label_width, size.height)), label_bg_color);
- } else {
- draw_rect(Rect2(Vector2(), Vector2(sb->get_offset().x * 2 + label_width, size.height)), label_bg_color);
- }
- }
+ if (has_focus()) {
+ Ref<StyleBox> focus = get_theme_stylebox(SNAME("focus"), SNAME("LineEdit"));
+ draw_style_box(focus, Rect2(Vector2(), size));
+ }
+
+ if (rtl) {
+ draw_string(font, Vector2(Math::round(size.width - sb->get_offset().x - label_width), vofs), label, HALIGN_RIGHT, -1, font_size, lc * Color(1, 1, 1, 0.5));
+ } else {
+ draw_string(font, Vector2(Math::round(sb->get_offset().x), vofs), label, HALIGN_LEFT, -1, font_size, lc * Color(1, 1, 1, 0.5));
+ }
- if (has_focus()) {
- Ref<StyleBox> focus = get_theme_stylebox(SNAME("focus"), SNAME("LineEdit"));
- draw_style_box(focus, Rect2(Vector2(), size));
+ int suffix_start = numstr.length();
+ RID num_rid = TS->create_shaped_text();
+ TS->shaped_text_add_string(num_rid, numstr + U"\u2009" + suffix, font->get_rids(), font_size);
+
+ float text_start = rtl ? Math::round(sb->get_offset().x) : Math::round(sb->get_offset().x + label_width + sep);
+ Vector2 text_ofs = rtl ? Vector2(text_start + (number_width - TS->shaped_text_get_width(num_rid)), vofs) : Vector2(text_start, vofs);
+ const Vector<TextServer::Glyph> visual = TS->shaped_text_get_glyphs(num_rid);
+ int v_size = visual.size();
+ const TextServer::Glyph *glyphs = visual.ptr();
+ for (int i = 0; i < v_size; i++) {
+ for (int j = 0; j < glyphs[i].repeat; j++) {
+ if (text_ofs.x >= text_start && (text_ofs.x + glyphs[i].advance) <= (text_start + number_width)) {
+ Color color = fc;
+ if (glyphs[i].start >= suffix_start) {
+ color.a *= 0.4;
+ }
+ if (glyphs[i].font_rid != RID()) {
+ TS->font_draw_glyph(glyphs[i].font_rid, ci, glyphs[i].font_size, text_ofs + Vector2(glyphs[i].x_off, glyphs[i].y_off), glyphs[i].index, color);
+ } else if ((glyphs[i].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
+ TS->draw_hex_code_box(ci, glyphs[i].font_size, text_ofs + Vector2(glyphs[i].x_off, glyphs[i].y_off), glyphs[i].index, color);
+ }
+ }
+ text_ofs.x += glyphs[i].advance;
}
+ }
+ TS->free(num_rid);
+ if (get_step() == 1) {
+ Ref<Texture2D> updown2 = get_theme_icon(SNAME("updown"), SNAME("SpinBox"));
+ int updown_vofs = (size.height - updown2->get_height()) / 2;
if (rtl) {
- draw_string(font, Vector2(Math::round(size.width - sb->get_offset().x - label_width), vofs), label, HALIGN_RIGHT, -1, font_size, lc * Color(1, 1, 1, 0.5));
+ updown_offset = sb->get_margin(SIDE_LEFT);
} else {
- draw_string(font, Vector2(Math::round(sb->get_offset().x), vofs), label, HALIGN_LEFT, -1, font_size, lc * Color(1, 1, 1, 0.5));
+ updown_offset = size.width - sb->get_margin(SIDE_RIGHT) - updown2->get_width();
}
-
- int suffix_start = numstr.length();
- RID num_rid = TS->create_shaped_text();
- TS->shaped_text_add_string(num_rid, numstr + U"\u2009" + suffix, font->get_rids(), font_size);
-
- float text_start = rtl ? Math::round(sb->get_offset().x) : Math::round(sb->get_offset().x + label_width + sep);
- Vector2 text_ofs = rtl ? Vector2(text_start + (number_width - TS->shaped_text_get_width(num_rid)), vofs) : Vector2(text_start, vofs);
- const Vector<TextServer::Glyph> visual = TS->shaped_text_get_glyphs(num_rid);
- int v_size = visual.size();
- const TextServer::Glyph *glyphs = visual.ptr();
- for (int i = 0; i < v_size; i++) {
- for (int j = 0; j < glyphs[i].repeat; j++) {
- if (text_ofs.x >= text_start && (text_ofs.x + glyphs[i].advance) <= (text_start + number_width)) {
- Color color = fc;
- if (glyphs[i].start >= suffix_start) {
- color.a *= 0.4;
- }
- if (glyphs[i].font_rid != RID()) {
- TS->font_draw_glyph(glyphs[i].font_rid, ci, glyphs[i].font_size, text_ofs + Vector2(glyphs[i].x_off, glyphs[i].y_off), glyphs[i].index, color);
- } else if ((glyphs[i].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
- TS->draw_hex_code_box(ci, glyphs[i].font_size, text_ofs + Vector2(glyphs[i].x_off, glyphs[i].y_off), glyphs[i].index, color);
- }
- }
- text_ofs.x += glyphs[i].advance;
- }
+ Color c(1, 1, 1);
+ if (hover_updown) {
+ c *= Color(1.2, 1.2, 1.2);
}
- TS->free(num_rid);
-
- if (get_step() == 1) {
- Ref<Texture2D> updown2 = get_theme_icon(SNAME("updown"), SNAME("SpinBox"));
- int updown_vofs = (size.height - updown2->get_height()) / 2;
- if (rtl) {
- updown_offset = sb->get_margin(SIDE_LEFT);
+ draw_texture(updown2, Vector2(updown_offset, updown_vofs), c);
+ if (grabber->is_visible()) {
+ grabber->hide();
+ }
+ } else if (!hide_slider) {
+ int grabber_w = 4 * EDSCALE;
+ int width = size.width - sb->get_minimum_size().width - grabber_w;
+ int ofs = sb->get_offset().x;
+ int svofs = (size.height + vofs) / 2 - 1;
+ Color c = fc;
+ c.a = 0.2;
+
+ draw_rect(Rect2(ofs, svofs + 1, width, 2 * EDSCALE), c);
+ int gofs = get_as_ratio() * width;
+ c.a = 0.9;
+ Rect2 grabber_rect = Rect2(ofs + gofs, svofs + 1, grabber_w, 2 * EDSCALE);
+ draw_rect(grabber_rect, c);
+
+ grabbing_spinner_mouse_pos = get_global_position() + grabber_rect.position + grabber_rect.size * 0.5;
+
+ bool display_grabber = (mouse_over_spin || mouse_over_grabber) && !grabbing_spinner && !(value_input_popup && value_input_popup->is_visible());
+ if (grabber->is_visible() != display_grabber) {
+ if (display_grabber) {
+ grabber->show();
} else {
- updown_offset = size.width - sb->get_margin(SIDE_RIGHT) - updown2->get_width();
- }
- Color c(1, 1, 1);
- if (hover_updown) {
- c *= Color(1.2, 1.2, 1.2);
- }
- draw_texture(updown2, Vector2(updown_offset, updown_vofs), c);
- if (grabber->is_visible()) {
grabber->hide();
}
- } else if (!hide_slider) {
- int grabber_w = 4 * EDSCALE;
- int width = size.width - sb->get_minimum_size().width - grabber_w;
- int ofs = sb->get_offset().x;
- int svofs = (size.height + vofs) / 2 - 1;
- Color c = fc;
- c.a = 0.2;
-
- draw_rect(Rect2(ofs, svofs + 1, width, 2 * EDSCALE), c);
- int gofs = get_as_ratio() * width;
- c.a = 0.9;
- Rect2 grabber_rect = Rect2(ofs + gofs, svofs + 1, grabber_w, 2 * EDSCALE);
- draw_rect(grabber_rect, c);
-
- grabbing_spinner_mouse_pos = get_global_position() + grabber_rect.position + grabber_rect.size * 0.5;
-
- bool display_grabber = (mouse_over_spin || mouse_over_grabber) && !grabbing_spinner && !(value_input_popup && value_input_popup->is_visible());
- if (grabber->is_visible() != display_grabber) {
- if (display_grabber) {
- grabber->show();
- } else {
- grabber->hide();
- }
- }
-
- if (display_grabber) {
- Ref<Texture2D> grabber_tex;
- if (mouse_over_grabber) {
- grabber_tex = get_theme_icon(SNAME("grabber_highlight"), SNAME("HSlider"));
- } else {
- grabber_tex = get_theme_icon(SNAME("grabber"), SNAME("HSlider"));
- }
+ }
- if (grabber->get_texture() != grabber_tex) {
- grabber->set_texture(grabber_tex);
- }
+ if (display_grabber) {
+ Ref<Texture2D> grabber_tex;
+ if (mouse_over_grabber) {
+ grabber_tex = get_theme_icon(SNAME("grabber_highlight"), SNAME("HSlider"));
+ } else {
+ grabber_tex = get_theme_icon(SNAME("grabber"), SNAME("HSlider"));
+ }
- Vector2 scale = get_global_transform_with_canvas().get_scale();
- grabber->set_scale(scale);
- grabber->set_size(Size2(0, 0));
- grabber->set_position(get_global_position() + (grabber_rect.position + grabber_rect.size * 0.5 - grabber->get_size() * 0.5) * scale);
+ if (grabber->get_texture() != grabber_tex) {
+ grabber->set_texture(grabber_tex);
+ }
- if (mousewheel_over_grabber) {
- Input::get_singleton()->warp_mouse_position(grabber->get_position() + grabber_rect.size);
- }
+ Vector2 scale = get_global_transform_with_canvas().get_scale();
+ grabber->set_scale(scale);
+ grabber->set_size(Size2(0, 0));
+ grabber->set_position(get_global_position() + (grabber_rect.position + grabber_rect.size * 0.5 - grabber->get_size() * 0.5) * scale);
- grabber_range = width;
+ if (mousewheel_over_grabber) {
+ Input::get_singleton()->warp_mouse_position(grabber->get_position() + grabber_rect.size);
}
+
+ grabber_range = width;
}
}
+}
- if (p_what == NOTIFICATION_MOUSE_ENTER) {
- mouse_over_spin = true;
- update();
- }
- if (p_what == NOTIFICATION_MOUSE_EXIT) {
- mouse_over_spin = false;
- update();
- }
- if (p_what == NOTIFICATION_FOCUS_ENTER) {
- if ((Input::get_singleton()->is_action_pressed("ui_focus_next") || Input::get_singleton()->is_action_pressed("ui_focus_prev")) && !value_input_just_closed) {
- _focus_entered();
- }
- value_input_just_closed = false;
+void EditorSpinSlider::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED:
+ _update_value_input_stylebox();
+ break;
+
+ case NOTIFICATION_DRAW:
+ _draw_spin_slider();
+ break;
+
+ case NOTIFICATION_WM_WINDOW_FOCUS_IN:
+ case NOTIFICATION_WM_WINDOW_FOCUS_OUT:
+ case NOTIFICATION_EXIT_TREE:
+ if (grabbing_spinner) {
+ grabber->hide();
+ Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
+ grabbing_spinner = false;
+ grabbing_spinner_attempt = false;
+ }
+ break;
+
+ case NOTIFICATION_MOUSE_ENTER:
+ mouse_over_spin = true;
+ update();
+ break;
+ case NOTIFICATION_MOUSE_EXIT:
+ mouse_over_spin = false;
+ update();
+ break;
+ case NOTIFICATION_FOCUS_ENTER:
+ if ((Input::get_singleton()->is_action_pressed("ui_focus_next") || Input::get_singleton()->is_action_pressed("ui_focus_prev")) && !value_input_just_closed) {
+ _focus_entered();
+ }
+ value_input_just_closed = false;
+ break;
}
}
@@ -567,8 +576,10 @@ void EditorSpinSlider::_ensure_input_popup() {
if (value_input_popup) {
return;
}
+
value_input_popup = memnew(Popup);
add_child(value_input_popup);
+
value_input = memnew(LineEdit);
value_input_popup->add_child(value_input);
value_input_popup->set_wrap_controls(true);
@@ -576,6 +587,7 @@ void EditorSpinSlider::_ensure_input_popup() {
value_input_popup->connect("popup_hide", callable_mp(this, &EditorSpinSlider::_value_input_closed));
value_input->connect("text_submitted", callable_mp(this, &EditorSpinSlider::_value_input_submitted));
value_input->connect("focus_exited", callable_mp(this, &EditorSpinSlider::_value_focus_exited));
+
if (is_inside_tree()) {
_update_value_input_stylebox();
}
diff --git a/editor/editor_spin_slider.h b/editor/editor_spin_slider.h
index 5b99f88505..c09d084e88 100644
--- a/editor/editor_spin_slider.h
+++ b/editor/editor_spin_slider.h
@@ -81,6 +81,7 @@ class EditorSpinSlider : public Range {
void _update_value_input_stylebox();
void _ensure_input_popup();
+ void _draw_spin_slider();
protected:
void _notification(int p_what);
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 2c83fb2df6..7f8229e5e8 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -595,6 +595,11 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("panel", "PanelContainer", style_menu);
theme->set_stylebox("MenuPanel", "EditorStyles", style_menu);
+ // CanvasItem Editor
+ Ref<StyleBoxFlat> style_canvas_editor_info = make_flat_stylebox(Color(0.0, 0.0, 0.0, 0.2));
+ style_canvas_editor_info->set_expand_margin_size_all(4 * EDSCALE);
+ theme->set_stylebox("CanvasItemInfoOverlay", "EditorStyles", style_canvas_editor_info);
+
// Script Editor
theme->set_stylebox("ScriptEditorPanel", "EditorStyles", make_empty_stylebox(default_margin_size, 0, default_margin_size, default_margin_size));
theme->set_stylebox("ScriptEditor", "EditorStyles", make_empty_stylebox(0, 0, 0, 0));
@@ -1499,15 +1504,14 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
}
Ref<Theme> create_custom_theme(const Ref<Theme> p_theme) {
- Ref<Theme> theme;
-
- const String custom_theme = EditorSettings::get_singleton()->get("interface/theme/custom_theme");
- if (custom_theme != "") {
- theme = ResourceLoader::load(custom_theme);
- }
+ Ref<Theme> theme = create_editor_theme(p_theme);
- if (!theme.is_valid()) {
- theme = create_editor_theme(p_theme);
+ const String custom_theme_path = EditorSettings::get_singleton()->get("interface/theme/custom_theme");
+ if (custom_theme_path != "") {
+ Ref<Theme> custom_theme = ResourceLoader::load(custom_theme_path);
+ if (custom_theme.is_valid()) {
+ theme->merge_with(custom_theme);
+ }
}
return theme;
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 76c056ed33..477e066e87 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -3909,6 +3909,11 @@ void CanvasItemEditor::_notification(int p_what) {
anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignWide"), SNAME("EditorIcons")), TTR("Full Rect"), ANCHORS_PRESET_WIDE);
anchor_mode_button->set_icon(get_theme_icon(SNAME("Anchor"), SNAME("EditorIcons")));
+
+ info_overlay->get_theme()->set_stylebox("normal", "Label", get_theme_stylebox(SNAME("CanvasItemInfoOverlay"), SNAME("EditorStyles")));
+ warning_child_of_container->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), SNAME("Editor")));
+ warning_child_of_container->add_theme_font_override("font", get_theme_font(SNAME("main"), SNAME("EditorFonts")));
+ warning_child_of_container->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("main_size"), SNAME("EditorFonts")));
}
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
@@ -5280,21 +5285,13 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
info_overlay->add_theme_constant_override("separation", 10);
viewport_scrollable->add_child(info_overlay);
+ // Make sure all labels inside of the container are styled the same.
Theme *info_overlay_theme = memnew(Theme);
- info_overlay_theme->copy_default_theme();
info_overlay->set_theme(info_overlay_theme);
- StyleBoxFlat *info_overlay_label_stylebox = memnew(StyleBoxFlat);
- info_overlay_label_stylebox->set_bg_color(Color(0.0, 0.0, 0.0, 0.2));
- info_overlay_label_stylebox->set_expand_margin_size_all(4);
- info_overlay_theme->set_stylebox("normal", "Label", info_overlay_label_stylebox);
-
warning_child_of_container = memnew(Label);
warning_child_of_container->hide();
warning_child_of_container->set_text(TTR("Warning: Children of a container get their position and size determined only by their parent."));
- warning_child_of_container->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("warning_color"), SNAME("Editor")));
- warning_child_of_container->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("main"), SNAME("EditorFonts")));
- warning_child_of_container->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size(SNAME("main_size"), SNAME("EditorFonts")));
add_control_to_info_overlay(warning_child_of_container);
h_scroll = memnew(HScrollBar);
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index d29c1efabb..868b834993 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -532,7 +532,7 @@ private:
bool grid_enable[3]; //should be always visible if true
bool grid_enabled;
bool grid_init_draw = false;
- Camera3D::Projection grid_camera_last_update_perspective;
+ Camera3D::Projection grid_camera_last_update_perspective = Camera3D::PROJECTION_PERSPECTIVE;
Vector3 grid_camera_last_update_position = Vector3();
Ref<ArrayMesh> move_gizmo[3], move_plane_gizmo[3], rotate_gizmo[4], scale_gizmo[3], scale_plane_gizmo[3];
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index 83b0203f32..e7ba80677d 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -1206,11 +1206,10 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope
}
tree->connect("cell_selected", callable_mp(this, &SceneTreeEditor::_selected_changed));
- tree->connect("item_edited", callable_mp(this, &SceneTreeEditor::_renamed), varray(), CONNECT_DEFERRED);
+ tree->connect("item_edited", callable_mp(this, &SceneTreeEditor::_renamed));
tree->connect("multi_selected", callable_mp(this, &SceneTreeEditor::_cell_multi_selected));
tree->connect("button_pressed", callable_mp(this, &SceneTreeEditor::_cell_button_pressed));
tree->connect("nothing_selected", callable_mp(this, &SceneTreeEditor::_deselect_items));
- //tree->connect("item_edited", this,"_renamed",Vector<Variant>(),true);
error = memnew(AcceptDialog);
add_child(error);
diff --git a/modules/gdscript/gdscript_cache.cpp b/modules/gdscript/gdscript_cache.cpp
index 1a844bf241..07f50d14dc 100644
--- a/modules/gdscript/gdscript_cache.cpp
+++ b/modules/gdscript/gdscript_cache.cpp
@@ -200,7 +200,9 @@ Ref<GDScript> GDScriptCache::get_full_script(const String &p_path, Error &r_erro
if (singleton->full_gdscript_cache.has(p_path)) {
return singleton->full_gdscript_cache[p_path];
}
+
Ref<GDScript> script = get_shallow_script(p_path);
+ ERR_FAIL_COND_V(script.is_null(), Ref<GDScript>());
r_error = script->load_source_code(p_path);
diff --git a/platform/android/android_input_handler.cpp b/platform/android/android_input_handler.cpp
index b9004c4989..e03375e8d9 100644
--- a/platform/android/android_input_handler.cpp
+++ b/platform/android/android_input_handler.cpp
@@ -377,7 +377,7 @@ MouseButton AndroidInputHandler::_android_button_mask_to_godot_button_mask(int a
if (android_button_mask & AMOTION_EVENT_BUTTON_BACK) {
godot_button_mask |= MOUSE_BUTTON_MASK_XBUTTON1;
}
- if (android_button_mask & AMOTION_EVENT_BUTTON_SECONDARY) {
+ if (android_button_mask & AMOTION_EVENT_BUTTON_FORWARD) {
godot_button_mask |= MOUSE_BUTTON_MASK_XBUTTON2;
}
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index 17ee173855..8ed2d4e60a 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -717,6 +717,10 @@ Error EditorExportPlatformAndroid::copy_gradle_so(void *p_userdata, const Shared
return OK;
}
+bool EditorExportPlatformAndroid::_has_storage_permission(const Vector<String> &p_permissions) {
+ return p_permissions.find("android.permission.READ_EXTERNAL_STORAGE") != -1 || p_permissions.find("android.permission.WRITE_EXTERNAL_STORAGE") != -1;
+}
+
void EditorExportPlatformAndroid::_get_permissions(const Ref<EditorExportPreset> &p_preset, bool p_give_internet, Vector<String> &r_permissions) {
const char **aperms = android_perms;
while (*aperms) {
@@ -763,12 +767,17 @@ void EditorExportPlatformAndroid::_write_tmp_manifest(const Ref<EditorExportPres
Vector<String> perms;
_get_permissions(p_preset, p_give_internet, perms);
for (int i = 0; i < perms.size(); i++) {
- manifest_text += vformat(" <uses-permission android:name=\"%s\" />\n", perms.get(i));
+ String permission = perms.get(i);
+ if (permission == "android.permission.WRITE_EXTERNAL_STORAGE" || permission == "android.permission.READ_EXTERNAL_STORAGE") {
+ manifest_text += vformat(" <uses-permission android:name=\"%s\" android:maxSdkVersion=\"29\" />\n", permission);
+ } else {
+ manifest_text += vformat(" <uses-permission android:name=\"%s\" />\n", permission);
+ }
}
manifest_text += _get_xr_features_tag(p_preset);
manifest_text += _get_instrumentation_tag(p_preset);
- manifest_text += _get_application_tag(p_preset);
+ manifest_text += _get_application_tag(p_preset, _has_storage_permission(perms));
manifest_text += "</manifest>\n";
String manifest_path = vformat("res://android/build/src/%s/AndroidManifest.xml", (p_debug ? "debug" : "release"));
@@ -824,6 +833,7 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
Vector<String> perms;
// Write permissions into the perms variable.
_get_permissions(p_preset, p_give_internet, perms);
+ bool has_storage_permission = _has_storage_permission(perms);
while (ofs < (uint32_t)p_manifest.size()) {
uint32_t chunk = decode_uint32(&p_manifest[ofs]);
@@ -913,6 +923,10 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
}
}
+ if (tname == "application" && attrname == "requestLegacyExternalStorage") {
+ encode_uint32(has_storage_permission ? 0xFFFFFFFF : 0, &p_manifest.write[iofs + 16]);
+ }
+
if (tname == "application" && attrname == "allowBackup") {
encode_uint32(backup_allowed, &p_manifest.write[iofs + 16]);
}
diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h
index 909428c2fe..b061ee4e04 100644
--- a/platform/android/export/export_plugin.h
+++ b/platform/android/export/export_plugin.h
@@ -134,6 +134,8 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
static Error copy_gradle_so(void *p_userdata, const SharedObject &p_so);
+ bool _has_storage_permission(const Vector<String> &p_permissions);
+
void _get_permissions(const Ref<EditorExportPreset> &p_preset, bool p_give_internet, Vector<String> &r_permissions);
void _write_tmp_manifest(const Ref<EditorExportPreset> &p_preset, bool p_give_internet, bool p_debug);
diff --git a/platform/android/export/gradle_export_util.cpp b/platform/android/export/gradle_export_util.cpp
index 76512226bf..b9e28a7937 100644
--- a/platform/android/export/gradle_export_util.cpp
+++ b/platform/android/export/gradle_export_util.cpp
@@ -235,18 +235,20 @@ String _get_activity_tag(const Ref<EditorExportPreset> &p_preset) {
return manifest_activity_text;
}
-String _get_application_tag(const Ref<EditorExportPreset> &p_preset) {
+String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_storage_permission) {
String manifest_application_text = vformat(
" <application android:label=\"@string/godot_project_name_string\"\n"
" android:allowBackup=\"%s\"\n"
" android:icon=\"@mipmap/icon\"\n"
" android:isGame=\"%s\"\n"
" android:hasFragileUserData=\"%s\"\n"
- " tools:replace=\"android:allowBackup,android:isGame,android:hasFragileUserData\"\n"
+ " android:requestLegacyExternalStorage=\"%s\"\n"
+ " tools:replace=\"android:allowBackup,android:isGame,android:hasFragileUserData,android:requestLegacyExternalStorage\"\n"
" tools:ignore=\"GoogleAppIndexingWarning\">\n\n",
bool_to_string(p_preset->get("user_data_backup/allow")),
bool_to_string(p_preset->get("package/classify_as_game")),
- bool_to_string(p_preset->get("package/retain_data_on_uninstall")));
+ bool_to_string(p_preset->get("package/retain_data_on_uninstall")),
+ bool_to_string(p_has_storage_permission));
manifest_application_text += _get_activity_tag(p_preset);
manifest_application_text += " </application>\n";
diff --git a/platform/android/export/gradle_export_util.h b/platform/android/export/gradle_export_util.h
index 44e9a1727d..8a93c25d79 100644
--- a/platform/android/export/gradle_export_util.h
+++ b/platform/android/export/gradle_export_util.h
@@ -81,6 +81,6 @@ String _get_instrumentation_tag(const Ref<EditorExportPreset> &p_preset);
String _get_activity_tag(const Ref<EditorExportPreset> &p_preset);
-String _get_application_tag(const Ref<EditorExportPreset> &p_preset);
+String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_storage_permission);
#endif //GODOT_GRADLE_EXPORT_UTIL_H
diff --git a/platform/android/java/app/AndroidManifest.xml b/platform/android/java/app/AndroidManifest.xml
index 467a0dc3c0..00e01884cf 100644
--- a/platform/android/java/app/AndroidManifest.xml
+++ b/platform/android/java/app/AndroidManifest.xml
@@ -22,6 +22,7 @@
android:icon="@mipmap/icon"
android:isGame="true"
android:hasFragileUserData="false"
+ android:requestLegacyExternalStorage="false"
tools:ignore="GoogleAppIndexingWarning" >
<!-- Records the version of the Godot editor used for building -->
diff --git a/platform/android/java/app/config.gradle b/platform/android/java/app/config.gradle
index 81fc87b7ef..fad64c675f 100644
--- a/platform/android/java/app/config.gradle
+++ b/platform/android/java/app/config.gradle
@@ -1,8 +1,8 @@
ext.versions = [
- androidGradlePlugin: '4.2.1',
- compileSdk : 29,
- minSdk : 18,
- targetSdk : 29,
+ androidGradlePlugin: '4.2.2',
+ compileSdk : 30,
+ minSdk : 19,
+ targetSdk : 30,
buildTools : '30.0.3',
supportCoreUtils : '1.0.0',
kotlinVersion : '1.5.10',
diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
index 76751a886c..317175858b 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
@@ -49,7 +49,6 @@ import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.ComponentName;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
@@ -68,15 +67,12 @@ import android.os.Environment;
import android.os.Messenger;
import android.os.VibrationEffect;
import android.os.Vibrator;
-import android.provider.Settings.Secure;
import android.view.Display;
-import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
-import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
@@ -471,7 +467,6 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
final Activity activity = getActivity();
io = new GodotIO(activity);
- io.unique_id = Secure.getString(activity.getContentResolver(), Secure.ANDROID_ID);
GodotLib.io = io;
netUtils = new GodotNetUtils(activity);
mSensorManager = (SensorManager)activity.getSystemService(Context.SENSOR_SERVICE);
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
index 66882e8e72..d85d88ec6c 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
@@ -30,15 +30,19 @@
package org.godotengine.godot;
-import org.godotengine.godot.input.*;
+import org.godotengine.godot.input.GodotEditText;
import android.app.Activity;
-import android.content.*;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.AssetManager;
import android.graphics.Point;
import android.net.Uri;
-import android.os.*;
+import android.os.Build;
+import android.os.Environment;
+import android.provider.Settings;
+import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.SparseArray;
@@ -47,14 +51,16 @@ import android.view.DisplayCutout;
import android.view.WindowInsets;
import java.io.IOException;
-import java.io.InputStream;
import java.util.Locale;
// Wrapper for native library
public class GodotIO {
- AssetManager am;
- final Activity activity;
+ private static final String TAG = GodotIO.class.getSimpleName();
+
+ private final AssetManager am;
+ private final Activity activity;
+ private final String uniqueId;
GodotEditText edit;
final int SCREEN_LANDSCAPE = 0;
@@ -66,167 +72,6 @@ public class GodotIO {
final int SCREEN_SENSOR = 6;
/////////////////////////
- /// FILES
- /////////////////////////
-
- public int last_file_id = 1;
-
- static class AssetData {
- public boolean eof = false;
- public String path;
- public InputStream is;
- public int len;
- public int pos;
- }
-
- SparseArray<AssetData> streams;
-
- public int file_open(String path, boolean write) {
- //System.out.printf("file_open: Attempt to Open %s\n",path);
-
- //Log.v("MyApp", "TRYING TO OPEN FILE: " + path);
- if (write)
- return -1;
-
- AssetData ad = new AssetData();
-
- try {
- ad.is = am.open(path);
-
- } catch (Exception e) {
- //System.out.printf("Exception on file_open: %s\n",path);
- return -1;
- }
-
- try {
- ad.len = ad.is.available();
- } catch (Exception e) {
- System.out.printf("Exception availabling on file_open: %s\n", path);
- return -1;
- }
-
- ad.path = path;
- ad.pos = 0;
- ++last_file_id;
- streams.put(last_file_id, ad);
-
- return last_file_id;
- }
- public int file_get_size(int id) {
- if (streams.get(id) == null) {
- System.out.printf("file_get_size: Invalid file id: %d\n", id);
- return -1;
- }
-
- return streams.get(id).len;
- }
- public void file_seek(int id, int bytes) {
- if (streams.get(id) == null) {
- System.out.printf("file_get_size: Invalid file id: %d\n", id);
- return;
- }
- //seek sucks
- AssetData ad = streams.get(id);
- if (bytes > ad.len)
- bytes = ad.len;
- if (bytes < 0)
- bytes = 0;
-
- try {
- if (bytes > (int)ad.pos) {
- int todo = bytes - (int)ad.pos;
- while (todo > 0) {
- todo -= ad.is.skip(todo);
- }
- ad.pos = bytes;
- } else if (bytes < (int)ad.pos) {
- ad.is = am.open(ad.path);
-
- ad.pos = bytes;
- int todo = bytes;
- while (todo > 0) {
- todo -= ad.is.skip(todo);
- }
- }
-
- ad.eof = false;
- } catch (IOException e) {
- System.out.printf("Exception on file_seek: %s\n", e);
- return;
- }
- }
-
- public int file_tell(int id) {
- if (streams.get(id) == null) {
- System.out.printf("file_read: Can't tell eof for invalid file id: %d\n", id);
- return 0;
- }
-
- AssetData ad = streams.get(id);
- return ad.pos;
- }
- public boolean file_eof(int id) {
- if (streams.get(id) == null) {
- System.out.printf("file_read: Can't check eof for invalid file id: %d\n", id);
- return false;
- }
-
- AssetData ad = streams.get(id);
- return ad.eof;
- }
-
- public byte[] file_read(int id, int bytes) {
- if (streams.get(id) == null) {
- System.out.printf("file_read: Can't read invalid file id: %d\n", id);
- return new byte[0];
- }
-
- AssetData ad = streams.get(id);
-
- if (ad.pos + bytes > ad.len) {
- bytes = ad.len - ad.pos;
- ad.eof = true;
- }
-
- if (bytes == 0) {
- return new byte[0];
- }
-
- byte[] buf1 = new byte[bytes];
- int r = 0;
- try {
- r = ad.is.read(buf1);
- } catch (IOException e) {
- System.out.printf("Exception on file_read: %s\n", e);
- return new byte[bytes];
- }
-
- if (r == 0) {
- return new byte[0];
- }
-
- ad.pos += r;
-
- if (r < bytes) {
- byte[] buf2 = new byte[r];
- for (int i = 0; i < r; i++)
- buf2[i] = buf1[i];
- return buf2;
- } else {
- return buf1;
- }
- }
-
- public void file_close(int id) {
- if (streams.get(id) == null) {
- System.out.printf("file_close: Can't close invalid file id: %d\n", id);
- return;
- }
-
- streams.remove(id);
- }
-
- /////////////////////////
/// DIRECTORIES
/////////////////////////
@@ -236,9 +81,9 @@ public class GodotIO {
public String path;
}
- public int last_dir_id = 1;
+ private int last_dir_id = 1;
- SparseArray<AssetDir> dirs;
+ private final SparseArray<AssetDir> dirs;
public int dir_open(String path) {
AssetDir ad = new AssetDir();
@@ -257,7 +102,6 @@ public class GodotIO {
return -1;
}
- //System.out.printf("Opened dir: %s\n",path);
++last_dir_id;
dirs.put(last_dir_id, ad);
@@ -320,9 +164,14 @@ public class GodotIO {
GodotIO(Activity p_activity) {
am = p_activity.getAssets();
activity = p_activity;
- //streams = new HashMap<Integer, AssetData>();
- streams = new SparseArray<>();
dirs = new SparseArray<>();
+ String androidId = Settings.Secure.getString(activity.getContentResolver(),
+ Settings.Secure.ANDROID_ID);
+ if (androidId == null) {
+ androidId = "";
+ }
+
+ uniqueId = androidId;
}
/////////////////////////
@@ -331,7 +180,6 @@ public class GodotIO {
public int openURI(String p_uri) {
try {
- Log.v("MyApp", "TRYING TO OPEN URI: " + p_uri);
String path = p_uri;
String type = "";
if (path.startsWith("/")) {
@@ -357,12 +205,12 @@ public class GodotIO {
}
}
- public String getDataDir() {
- return activity.getFilesDir().getAbsolutePath();
+ public String getCacheDir() {
+ return activity.getCacheDir().getAbsolutePath();
}
- public String getExternalDataDir() {
- return activity.getExternalFilesDir(null).getAbsolutePath();
+ public String getDataDir() {
+ return activity.getFilesDir().getAbsolutePath();
}
public String getLocale() {
@@ -456,51 +304,58 @@ public class GodotIO {
public static final int SYSTEM_DIR_PICTURES = 6;
public static final int SYSTEM_DIR_RINGTONES = 7;
- public String getSystemDir(int idx) {
- String what = "";
+ public String getSystemDir(int idx, boolean shared_storage) {
+ String what;
switch (idx) {
- case SYSTEM_DIR_DESKTOP: {
- //what=Environment.DIRECTORY_DOCUMENTS;
- what = Environment.DIRECTORY_DOWNLOADS;
+ case SYSTEM_DIR_DESKTOP:
+ default: {
+ what = null; // This leads to the app specific external root directory.
} break;
+
case SYSTEM_DIR_DCIM: {
what = Environment.DIRECTORY_DCIM;
-
} break;
+
case SYSTEM_DIR_DOCUMENTS: {
- what = Environment.DIRECTORY_DOWNLOADS;
- //what=Environment.DIRECTORY_DOCUMENTS;
+ what = Environment.DIRECTORY_DOCUMENTS;
} break;
+
case SYSTEM_DIR_DOWNLOADS: {
what = Environment.DIRECTORY_DOWNLOADS;
-
} break;
+
case SYSTEM_DIR_MOVIES: {
what = Environment.DIRECTORY_MOVIES;
-
} break;
+
case SYSTEM_DIR_MUSIC: {
what = Environment.DIRECTORY_MUSIC;
} break;
+
case SYSTEM_DIR_PICTURES: {
what = Environment.DIRECTORY_PICTURES;
} break;
+
case SYSTEM_DIR_RINGTONES: {
what = Environment.DIRECTORY_RINGTONES;
-
} break;
}
- if (what.equals(""))
- return "";
- return Environment.getExternalStoragePublicDirectory(what).getAbsolutePath();
+ if (shared_storage) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ Log.w(TAG, "Shared storage access is limited on Android 10 and higher.");
+ }
+ if (TextUtils.isEmpty(what)) {
+ return Environment.getExternalStorageDirectory().getAbsolutePath();
+ } else {
+ return Environment.getExternalStoragePublicDirectory(what).getAbsolutePath();
+ }
+ } else {
+ return activity.getExternalFilesDir(what).getAbsolutePath();
+ }
}
- protected static final String PREFS_FILE = "device_id.xml";
- protected static final String PREFS_DEVICE_ID = "device_id";
-
- public static String unique_id = "";
public String getUniqueID() {
- return unique_id;
+ return uniqueId;
}
}
diff --git a/platform/android/java_godot_io_wrapper.cpp b/platform/android/java_godot_io_wrapper.cpp
index 5e99135498..5cd2c382d2 100644
--- a/platform/android/java_godot_io_wrapper.cpp
+++ b/platform/android/java_godot_io_wrapper.cpp
@@ -48,8 +48,8 @@ GodotIOJavaWrapper::GodotIOJavaWrapper(JNIEnv *p_env, jobject p_godot_io_instanc
}
_open_URI = p_env->GetMethodID(cls, "openURI", "(Ljava/lang/String;)I");
+ _get_cache_dir = p_env->GetMethodID(cls, "getCacheDir", "()Ljava/lang/String;");
_get_data_dir = p_env->GetMethodID(cls, "getDataDir", "()Ljava/lang/String;");
- _get_external_data_dir = p_env->GetMethodID(cls, "getExternalDataDir", "()Ljava/lang/String;");
_get_locale = p_env->GetMethodID(cls, "getLocale", "()Ljava/lang/String;");
_get_model = p_env->GetMethodID(cls, "getModel", "()Ljava/lang/String;");
_get_screen_DPI = p_env->GetMethodID(cls, "getScreenDPI", "()I");
@@ -59,7 +59,7 @@ GodotIOJavaWrapper::GodotIOJavaWrapper(JNIEnv *p_env, jobject p_godot_io_instanc
_hide_keyboard = p_env->GetMethodID(cls, "hideKeyboard", "()V");
_set_screen_orientation = p_env->GetMethodID(cls, "setScreenOrientation", "(I)V");
_get_screen_orientation = p_env->GetMethodID(cls, "getScreenOrientation", "()I");
- _get_system_dir = p_env->GetMethodID(cls, "getSystemDir", "(I)Ljava/lang/String;");
+ _get_system_dir = p_env->GetMethodID(cls, "getSystemDir", "(IZ)Ljava/lang/String;");
}
}
@@ -82,22 +82,22 @@ Error GodotIOJavaWrapper::open_uri(const String &p_uri) {
}
}
-String GodotIOJavaWrapper::get_user_data_dir() {
- if (_get_data_dir) {
+String GodotIOJavaWrapper::get_cache_dir() {
+ if (_get_cache_dir) {
JNIEnv *env = get_jni_env();
ERR_FAIL_COND_V(env == nullptr, String());
- jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_data_dir);
+ jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_cache_dir);
return jstring_to_string(s, env);
} else {
return String();
}
}
-String GodotIOJavaWrapper::get_external_data_dir() {
- if (_get_external_data_dir) {
+String GodotIOJavaWrapper::get_user_data_dir() {
+ if (_get_data_dir) {
JNIEnv *env = get_jni_env();
ERR_FAIL_COND_V(env == nullptr, String());
- jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_external_data_dir);
+ jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_data_dir);
return jstring_to_string(s, env);
} else {
return String();
@@ -200,11 +200,11 @@ int GodotIOJavaWrapper::get_screen_orientation() {
}
}
-String GodotIOJavaWrapper::get_system_dir(int p_dir) {
+String GodotIOJavaWrapper::get_system_dir(int p_dir, bool p_shared_storage) {
if (_get_system_dir) {
JNIEnv *env = get_jni_env();
ERR_FAIL_COND_V(env == nullptr, String("."));
- jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_system_dir, p_dir);
+ jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_system_dir, p_dir, p_shared_storage);
return jstring_to_string(s, env);
} else {
return String(".");
diff --git a/platform/android/java_godot_io_wrapper.h b/platform/android/java_godot_io_wrapper.h
index e4c0a4b2c7..8f6d7f813f 100644
--- a/platform/android/java_godot_io_wrapper.h
+++ b/platform/android/java_godot_io_wrapper.h
@@ -46,8 +46,8 @@ private:
jclass cls;
jmethodID _open_URI = 0;
+ jmethodID _get_cache_dir = 0;
jmethodID _get_data_dir = 0;
- jmethodID _get_external_data_dir = 0;
jmethodID _get_locale = 0;
jmethodID _get_model = 0;
jmethodID _get_screen_DPI = 0;
@@ -66,8 +66,8 @@ public:
jobject get_instance();
Error open_uri(const String &p_uri);
+ String get_cache_dir();
String get_user_data_dir();
- String get_external_data_dir();
String get_locale();
String get_model();
int get_screen_dpi();
@@ -80,7 +80,7 @@ public:
void set_vk_height(int p_height);
void set_screen_orientation(int p_orient);
int get_screen_orientation();
- String get_system_dir(int p_dir);
+ String get_system_dir(int p_dir, bool p_shared_storage);
};
#endif /* !JAVA_GODOT_IO_WRAPPER_H */
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index c2e12442b3..21fb31d991 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -213,6 +213,10 @@ String OS_Android::get_model_name() const {
return OS_Unix::get_model_name();
}
+String OS_Android::get_data_path() const {
+ return get_user_data_dir();
+}
+
String OS_Android::get_user_data_dir() const {
if (data_dir_cache != String())
return data_dir_cache;
@@ -225,11 +229,11 @@ String OS_Android::get_user_data_dir() const {
return ".";
}
-String OS_Android::get_external_data_dir() const {
- String data_dir = godot_io_java->get_external_data_dir();
- if (data_dir != "") {
- data_dir = _remove_symlink(data_dir);
- return data_dir;
+String OS_Android::get_cache_path() const {
+ String cache_dir = godot_io_java->get_cache_dir();
+ if (cache_dir != "") {
+ cache_dir = _remove_symlink(cache_dir);
+ return cache_dir;
}
return ".";
}
@@ -242,8 +246,8 @@ String OS_Android::get_unique_id() const {
return OS::get_unique_id();
}
-String OS_Android::get_system_dir(SystemDir p_dir) const {
- return godot_io_java->get_system_dir(p_dir);
+String OS_Android::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
+ return godot_io_java->get_system_dir(p_dir, p_shared_storage);
}
void OS_Android::set_display_size(const Size2i &p_size) {
diff --git a/platform/android/os_android.h b/platform/android/os_android.h
index a5b995a775..c938297821 100644
--- a/platform/android/os_android.h
+++ b/platform/android/os_android.h
@@ -110,14 +110,15 @@ public:
virtual Error shell_open(String p_uri) override;
virtual String get_user_data_dir() const override;
- virtual String get_external_data_dir() const override;
+ virtual String get_data_path() const override;
+ virtual String get_cache_path() const override;
virtual String get_resource_dir() const override;
virtual String get_locale() const override;
virtual String get_model_name() const override;
virtual String get_unique_id() const override;
- virtual String get_system_dir(SystemDir p_dir) const override;
+ virtual String get_system_dir(SystemDir p_dir, bool p_shared_storage = true) const override;
void vibrate_handheld(int p_duration_ms) override;
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index 08630be8b0..2c9801f512 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -273,7 +273,7 @@ String OS_LinuxBSD::get_cache_path() const {
}
}
-String OS_LinuxBSD::get_system_dir(SystemDir p_dir) const {
+String OS_LinuxBSD::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
String xdgparam;
switch (p_dir) {
diff --git a/platform/linuxbsd/os_linuxbsd.h b/platform/linuxbsd/os_linuxbsd.h
index 1e06587322..35c80e3f9b 100644
--- a/platform/linuxbsd/os_linuxbsd.h
+++ b/platform/linuxbsd/os_linuxbsd.h
@@ -84,7 +84,7 @@ public:
virtual String get_data_path() const override;
virtual String get_cache_path() const override;
- virtual String get_system_dir(SystemDir p_dir) const override;
+ virtual String get_system_dir(SystemDir p_dir, bool p_shared_storage = true) const override;
virtual Error shell_open(String p_uri) override;
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index 37d30add78..df41ccd892 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -84,7 +84,7 @@ public:
virtual String get_bundle_resource_dir() const override;
virtual String get_godot_dir_name() const override;
- virtual String get_system_dir(SystemDir p_dir) const override;
+ virtual String get_system_dir(SystemDir p_dir, bool p_shared_storage = true) const override;
Error shell_open(String p_uri) override;
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index c458a0264a..c6e35fee83 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -395,7 +395,7 @@ String OS_OSX::get_godot_dir_name() const {
return String(VERSION_SHORT_NAME).capitalize();
}
-String OS_OSX::get_system_dir(SystemDir p_dir) const {
+String OS_OSX::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
NSSearchPathDirectory id;
bool found = true;
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 2c8afaf7de..2a0a509d43 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -681,7 +681,7 @@ String OS_Windows::get_godot_dir_name() const {
return String(VERSION_SHORT_NAME).capitalize();
}
-String OS_Windows::get_system_dir(SystemDir p_dir) const {
+String OS_Windows::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
KNOWNFOLDERID id;
switch (p_dir) {
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index ea0c263b78..c4a2eda8f4 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -150,7 +150,7 @@ public:
virtual String get_cache_path() const override;
virtual String get_godot_dir_name() const override;
- virtual String get_system_dir(SystemDir p_dir) const override;
+ virtual String get_system_dir(SystemDir p_dir, bool p_shared_storage = true) const override;
virtual String get_user_data_dir() const override;
virtual String get_unique_id() const override;
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 00da94c3b0..dd1a4671d9 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -1104,14 +1104,12 @@ bool CharacterBody2D::move_and_slide() {
for (int iteration = 0; iteration < max_slides; ++iteration) {
PhysicsServer2D::MotionResult result;
- bool found_collision = false;
Vector2 prev_position = get_global_transform().elements[2];
bool collided = move_and_collide(motion, result, margin, false, !sliding_enabled);
if (collided) {
- found_collision = true;
motion_results.push_back(result);
_set_collision_direction(result);
@@ -1136,7 +1134,7 @@ bool CharacterBody2D::move_and_slide() {
// Move on floor only checks.
if (floor_block_on_wall && on_wall && motion_slide_up.dot(result.collision_normal) <= 0) {
// Avoid to move forward on a wall if floor_block_on_wall is true.
- if (was_on_floor && !is_on_floor_only() && !vel_dir_facing_up) {
+ if (was_on_floor && !on_floor && !vel_dir_facing_up) {
// If the movement is large the body can be prevented from reaching the walls.
if (result.travel.length() <= margin) {
// Cancels the motion.
@@ -1155,7 +1153,7 @@ bool CharacterBody2D::move_and_slide() {
break;
}
// Prevents the body from being able to climb a slope when it moves forward against the wall.
- else if (!is_on_floor_only()) {
+ else if (!on_floor) {
motion = up_direction * up_direction.dot(result.remainder);
motion = motion.slide(result.collision_normal);
} else {
@@ -1166,9 +1164,7 @@ bool CharacterBody2D::move_and_slide() {
else if (floor_constant_speed && is_on_floor_only() && can_apply_constant_speed && was_on_floor && motion.dot(result.collision_normal) < 0) {
can_apply_constant_speed = false;
Vector2 motion_slide_norm = result.remainder.slide(result.collision_normal).normalized();
- if (!motion_slide_norm.is_equal_approx(Vector2())) {
- motion = motion_slide_norm * (motion_slide_up.length() - result.travel.slide(up_direction).length() - last_travel.slide(up_direction).length());
- }
+ motion = motion_slide_norm * (motion_slide_up.length() - result.travel.slide(up_direction).length() - last_travel.slide(up_direction).length());
}
// Regular sliding, the last part of the test handle the case when you don't want to slide on the ceiling.
else if ((sliding_enabled || !on_floor) && (!on_ceiling || slide_on_ceiling || !vel_dir_facing_up)) {
@@ -1209,17 +1205,15 @@ bool CharacterBody2D::move_and_slide() {
set_global_transform(gt);
Vector2 motion_slide_norm = motion.slide(prev_floor_normal).normalized();
- if (!motion_slide_norm.is_equal_approx(Vector2())) {
- motion = motion_slide_norm * (motion_slide_up.length());
- found_collision = true;
- }
+ motion = motion_slide_norm * (motion_slide_up.length());
+ collided = true;
}
can_apply_constant_speed = !can_apply_constant_speed && !sliding_enabled;
sliding_enabled = true;
first_slide = false;
- if (!found_collision || motion.is_equal_approx(Vector2())) {
+ if (!collided || motion.is_equal_approx(Vector2())) {
break;
}
}
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index a2c5769947..12f0c9e89a 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -4906,6 +4906,11 @@ void TextEdit::_backspace() {
return;
}
+ if (has_selection()) {
+ delete_selection();
+ return;
+ }
+
int cc = get_caret_column();
int cl = get_caret_line();
@@ -4913,11 +4918,6 @@ void TextEdit::_backspace() {
return;
}
- if (has_selection()) {
- delete_selection();
- return;
- }
-
int prev_line = cc ? cl : cl - 1;
int prev_column = cc ? (cc - 1) : (text[cl - 1].length());
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index 6995c77b8e..73eec73d75 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -300,7 +300,7 @@ void Window::_propagate_window_notification(Node *p_node, int p_notification) {
Node *child = p_node->get_child(i);
Window *window = Object::cast_to<Window>(child);
if (window) {
- break;
+ continue;
}
_propagate_window_notification(child, p_notification);
}
diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp
index e4a731c7f7..e49d883ba4 100644
--- a/scene/resources/theme.cpp
+++ b/scene/resources/theme.cpp
@@ -1350,40 +1350,36 @@ void Theme::clear() {
_emit_theme_changed();
}
-void Theme::copy_default_theme() {
- Ref<Theme> default_theme2 = get_default();
- copy_theme(default_theme2);
-}
-
-void Theme::copy_theme(const Ref<Theme> &p_other) {
+void Theme::merge_with(const Ref<Theme> &p_other) {
if (p_other.is_null()) {
- clear();
return;
}
_freeze_change_propagation();
- // These items need reconnecting, so add them normally.
+ // Colors.
{
const StringName *K = nullptr;
- while ((K = p_other->icon_map.next(K))) {
+ while ((K = p_other->color_map.next(K))) {
const StringName *L = nullptr;
- while ((L = p_other->icon_map[*K].next(L))) {
- set_icon(*L, *K, p_other->icon_map[*K][*L]);
+ while ((L = p_other->color_map[*K].next(L))) {
+ set_color(*L, *K, p_other->color_map[*K][*L]);
}
}
}
+ // Constants.
{
const StringName *K = nullptr;
- while ((K = p_other->style_map.next(K))) {
+ while ((K = p_other->constant_map.next(K))) {
const StringName *L = nullptr;
- while ((L = p_other->style_map[*K].next(L))) {
- set_stylebox(*L, *K, p_other->style_map[*K][*L]);
+ while ((L = p_other->constant_map[*K].next(L))) {
+ set_constant(*L, *K, p_other->constant_map[*K][*L]);
}
}
}
+ // Fonts.
{
const StringName *K = nullptr;
while ((K = p_other->font_map.next(K))) {
@@ -1394,13 +1390,46 @@ void Theme::copy_theme(const Ref<Theme> &p_other) {
}
}
- // These items can be simply copied.
- font_size_map = p_other->font_size_map;
- color_map = p_other->color_map;
- constant_map = p_other->constant_map;
+ // Font sizes.
+ {
+ const StringName *K = nullptr;
+ while ((K = p_other->font_size_map.next(K))) {
+ const StringName *L = nullptr;
+ while ((L = p_other->font_size_map[*K].next(L))) {
+ set_font_size(*L, *K, p_other->font_size_map[*K][*L]);
+ }
+ }
+ }
- variation_map = p_other->variation_map;
- variation_base_map = p_other->variation_base_map;
+ // Icons.
+ {
+ const StringName *K = nullptr;
+ while ((K = p_other->icon_map.next(K))) {
+ const StringName *L = nullptr;
+ while ((L = p_other->icon_map[*K].next(L))) {
+ set_icon(*L, *K, p_other->icon_map[*K][*L]);
+ }
+ }
+ }
+
+ // Styleboxes.
+ {
+ const StringName *K = nullptr;
+ while ((K = p_other->style_map.next(K))) {
+ const StringName *L = nullptr;
+ while ((L = p_other->style_map[*K].next(L))) {
+ set_stylebox(*L, *K, p_other->style_map[*K][*L]);
+ }
+ }
+ }
+
+ // Type variations.
+ {
+ const StringName *K = nullptr;
+ while ((K = p_other->variation_map.next(K))) {
+ set_type_variation(*K, p_other->variation_map[*K]);
+ }
+ }
_unfreeze_and_propagate_changes();
}
@@ -1534,8 +1563,6 @@ void Theme::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_constant_list", "theme_type"), &Theme::_get_constant_list);
ClassDB::bind_method(D_METHOD("get_constant_type_list"), &Theme::_get_constant_type_list);
- ClassDB::bind_method(D_METHOD("clear"), &Theme::clear);
-
ClassDB::bind_method(D_METHOD("set_default_font", "font"), &Theme::set_default_theme_font);
ClassDB::bind_method(D_METHOD("get_default_font"), &Theme::get_default_theme_font);
@@ -1558,8 +1585,8 @@ void Theme::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_type_list"), &Theme::_get_type_list);
- ClassDB::bind_method("copy_default_theme", &Theme::copy_default_theme);
- ClassDB::bind_method(D_METHOD("copy_theme", "other"), &Theme::copy_theme);
+ ClassDB::bind_method(D_METHOD("merge_with", "other"), &Theme::merge_with);
+ ClassDB::bind_method(D_METHOD("clear"), &Theme::clear);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "default_font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_default_font", "get_default_font");
ADD_PROPERTY(PropertyInfo(Variant::INT, "default_font_size"), "set_default_font_size", "get_default_font_size");
diff --git a/scene/resources/theme.h b/scene/resources/theme.h
index 8a8fc28be1..15f21b91b8 100644
--- a/scene/resources/theme.h
+++ b/scene/resources/theme.h
@@ -210,8 +210,7 @@ public:
void get_type_list(List<StringName> *p_list) const;
void get_type_dependencies(const StringName &p_base_type, const StringName &p_type_variant, List<StringName> *p_list);
- void copy_default_theme();
- void copy_theme(const Ref<Theme> &p_other);
+ void merge_with(const Ref<Theme> &p_other);
void clear();
Theme();
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h
index c048be5dc8..b7adef6c60 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.h
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.h
@@ -668,14 +668,14 @@ private:
};
uint32_t emitting;
- double system_phase;
- double prev_system_phase;
+ float system_phase;
+ float prev_system_phase;
uint32_t cycle;
real_t explosiveness;
real_t randomness;
- double time;
- double delta;
+ float time;
+ float delta;
uint32_t frame;
uint32_t pad0;
@@ -812,7 +812,7 @@ private:
struct ParticlesShader {
struct PushConstant {
- double lifetime;
+ float lifetime;
uint32_t clear;
uint32_t total_particles;
uint32_t trail_size;