diff options
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; |