summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/core_bind.cpp17
-rw-r--r--core/core_bind.h3
-rw-r--r--core/object/undo_redo.cpp4
-rw-r--r--core/object/undo_redo.h4
-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/TextEdit.xml12
-rw-r--r--doc/classes/Theme.xml21
-rw-r--r--doc/classes/UndoRedo.xml4
-rw-r--r--drivers/vulkan/vulkan_context.cpp54
-rw-r--r--editor/code_editor.cpp6
-rw-r--r--editor/editor_node.cpp17
-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/plugins/script_text_editor.cpp12
-rw-r--r--editor/plugins/script_text_editor.h1
-rw-r--r--editor/plugins/text_editor.cpp12
-rw-r--r--editor/plugins/text_editor.h1
-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/3d/physics_body_3d.cpp10
-rw-r--r--scene/gui/line_edit.cpp16
-rw-r--r--scene/gui/line_edit.h2
-rw-r--r--scene/gui/text_edit.cpp19
-rw-r--r--scene/gui/text_edit.h2
-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
53 files changed, 512 insertions, 542 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/object/undo_redo.cpp b/core/object/undo_redo.cpp
index adf068eb2f..b7d2bac96d 100644
--- a/core/object/undo_redo.cpp
+++ b/core/object/undo_redo.cpp
@@ -405,11 +405,11 @@ String UndoRedo::get_current_action_name() const {
return actions[current_action].name;
}
-bool UndoRedo::has_undo() {
+bool UndoRedo::has_undo() const {
return current_action >= 0;
}
-bool UndoRedo::has_redo() {
+bool UndoRedo::has_redo() const {
return (current_action + 1) < actions.size();
}
diff --git a/core/object/undo_redo.h b/core/object/undo_redo.h
index 8f009830e3..d1ce252d86 100644
--- a/core/object/undo_redo.h
+++ b/core/object/undo_redo.h
@@ -121,8 +121,8 @@ public:
String get_action_name(int p_id);
void clear_history(bool p_increase_version = true);
- bool has_undo();
- bool has_redo();
+ bool has_undo() const;
+ bool has_redo() const;
uint64_t get_version() 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/TextEdit.xml b/doc/classes/TextEdit.xml
index 68d20e41d0..7aa627b7d0 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -464,12 +464,24 @@
Returns if the user has IME text.
</description>
</method>
+ <method name="has_redo" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if a "redo" action is available.
+ </description>
+ </method>
<method name="has_selection" qualifiers="const">
<return type="bool" />
<description>
Returns [code]true[/code] if the user has selected text.
</description>
</method>
+ <method name="has_undo" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if an "undo" action is available.
+ </description>
+ </method>
<method name="insert_line_at">
<return type="void" />
<argument index="0" name="line" type="int" />
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/doc/classes/UndoRedo.xml b/doc/classes/UndoRedo.xml
index 4417447891..def6fe5d1f 100644
--- a/doc/classes/UndoRedo.xml
+++ b/doc/classes/UndoRedo.xml
@@ -166,13 +166,13 @@
This is useful mostly to check if something changed from a saved version.
</description>
</method>
- <method name="has_redo">
+ <method name="has_redo" qualifiers="const">
<return type="bool" />
<description>
Returns [code]true[/code] if a "redo" action is available.
</description>
</method>
- <method name="has_undo">
+ <method name="has_undo" qualifiers="const">
<return type="bool" />
<description>
Returns [code]true[/code] if an "undo" action is available.
diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp
index 87749450c4..625c222b67 100644
--- a/drivers/vulkan/vulkan_context.cpp
+++ b/drivers/vulkan/vulkan_context.cpp
@@ -976,37 +976,35 @@ Error VulkanContext::_create_device() {
sdevice.queueCreateInfoCount = 2;
}
-#ifdef VK_VERSION_1_2
VkPhysicalDeviceVulkan11Features vulkan11features;
-
- vulkan11features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
- vulkan11features.pNext = nullptr;
- // !BAS! Need to figure out which ones of these we want enabled...
- vulkan11features.storageBuffer16BitAccess = 0;
- vulkan11features.uniformAndStorageBuffer16BitAccess = 0;
- vulkan11features.storagePushConstant16 = 0;
- vulkan11features.storageInputOutput16 = 0;
- vulkan11features.multiview = multiview_capabilities.is_supported;
- vulkan11features.multiviewGeometryShader = multiview_capabilities.geometry_shader_is_supported;
- vulkan11features.multiviewTessellationShader = multiview_capabilities.tessellation_shader_is_supported;
- vulkan11features.variablePointersStorageBuffer = 0;
- vulkan11features.variablePointers = 0;
- vulkan11features.protectedMemory = 0;
- vulkan11features.samplerYcbcrConversion = 0;
- vulkan11features.shaderDrawParameters = 0;
-
- sdevice.pNext = &vulkan11features;
-#elif VK_VERSION_1_1
VkPhysicalDeviceMultiviewFeatures multiview_features;
+ if (vulkan_major > 1 || vulkan_minor >= 2) {
+ vulkan11features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
+ vulkan11features.pNext = nullptr;
+ // !BAS! Need to figure out which ones of these we want enabled...
+ vulkan11features.storageBuffer16BitAccess = 0;
+ vulkan11features.uniformAndStorageBuffer16BitAccess = 0;
+ vulkan11features.storagePushConstant16 = 0;
+ vulkan11features.storageInputOutput16 = 0;
+ vulkan11features.multiview = multiview_capabilities.is_supported;
+ vulkan11features.multiviewGeometryShader = multiview_capabilities.geometry_shader_is_supported;
+ vulkan11features.multiviewTessellationShader = multiview_capabilities.tessellation_shader_is_supported;
+ vulkan11features.variablePointersStorageBuffer = 0;
+ vulkan11features.variablePointers = 0;
+ vulkan11features.protectedMemory = 0;
+ vulkan11features.samplerYcbcrConversion = 0;
+ vulkan11features.shaderDrawParameters = 0;
+
+ sdevice.pNext = &vulkan11features;
+ } else if (vulkan_major == 1 && vulkan_minor == 1) {
+ multiview_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES;
+ multiview_features.pNext = nullptr;
+ multiview_features.multiview = multiview_capabilities.is_supported;
+ multiview_features.multiviewGeometryShader = multiview_capabilities.geometry_shader_is_supported;
+ multiview_features.multiviewTessellationShader = multiview_capabilities.tessellation_shader_is_supported;
- multiview_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES;
- multiview_features.pNext = nullptr;
- multiview_features.multiview = multiview_capabilities.is_supported;
- multiview_features.multiviewGeometryShader = multiview_capabilities.geometry_shader_is_supported;
- multiview_features.multiviewTessellationShader = multiview_capabilities.tessellation_shader_is_supported;
-
- sdevice.pNext = &multiview_features;
-#endif
+ sdevice.pNext = &multiview_features;
+ }
err = vkCreateDevice(gpu, &sdevice, nullptr, &device);
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
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_node.cpp b/editor/editor_node.cpp
index 4cd2e8bdd0..3adb7688b0 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -2592,26 +2592,26 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
case EDIT_UNDO: {
if (Input::get_singleton()->get_mouse_button_mask() & 0x7) {
- log->add_message("Can't undo while mouse buttons are pressed.", EditorLog::MSG_TYPE_EDITOR);
+ log->add_message(TTR("Can't undo while mouse buttons are pressed."), EditorLog::MSG_TYPE_EDITOR);
} else {
String action = editor_data.get_undo_redo().get_current_action_name();
if (!editor_data.get_undo_redo().undo()) {
- log->add_message("Nothing to undo.", EditorLog::MSG_TYPE_EDITOR);
+ log->add_message(TTR("Nothing to undo."), EditorLog::MSG_TYPE_EDITOR);
} else if (action != "") {
- log->add_message("Undo: " + action, EditorLog::MSG_TYPE_EDITOR);
+ log->add_message(vformat(TTR("Undo: %s"), action), EditorLog::MSG_TYPE_EDITOR);
}
}
} break;
case EDIT_REDO: {
if (Input::get_singleton()->get_mouse_button_mask() & 0x7) {
- log->add_message("Can't redo while mouse buttons are pressed.", EditorLog::MSG_TYPE_EDITOR);
+ log->add_message(TTR("Can't redo while mouse buttons are pressed."), EditorLog::MSG_TYPE_EDITOR);
} else {
if (!editor_data.get_undo_redo().redo()) {
- log->add_message("Nothing to redo.", EditorLog::MSG_TYPE_EDITOR);
+ log->add_message(TTR("Nothing to redo."), EditorLog::MSG_TYPE_EDITOR);
} else {
String action = editor_data.get_undo_redo().get_current_action_name();
- log->add_message("Redo: " + action, EditorLog::MSG_TYPE_EDITOR);
+ log->add_message(vformat(TTR("Redo: %s"), action), EditorLog::MSG_TYPE_EDITOR);
}
}
} break;
@@ -3014,8 +3014,13 @@ void EditorNode::_update_file_menu_opened() {
close_scene_sc->set_name(TTR("Close Scene"));
Ref<Shortcut> reopen_closed_scene_sc = ED_GET_SHORTCUT("editor/reopen_closed_scene");
reopen_closed_scene_sc->set_name(TTR("Reopen Closed Scene"));
+
PopupMenu *pop = file_menu->get_popup();
pop->set_item_disabled(pop->get_item_index(FILE_OPEN_PREV), previous_scenes.is_empty());
+
+ const UndoRedo &undo_redo = editor_data.get_undo_redo();
+ pop->set_item_disabled(pop->get_item_index(EDIT_UNDO), !undo_redo.has_undo());
+ pop->set_item_disabled(pop->get_item_index(EDIT_REDO), !undo_redo.has_redo());
}
void EditorNode::_update_file_menu_closed() {
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/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index d3f07ab39a..7f2908eada 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -1630,6 +1630,13 @@ void ScriptTextEditor::_color_changed(const Color &p_color) {
code_editor->get_text_editor()->update();
}
+void ScriptTextEditor::_prepare_edit_menu() {
+ const CodeEdit *tx = code_editor->get_text_editor();
+ PopupMenu *popup = edit_menu->get_popup();
+ popup->set_item_disabled(popup->get_item_index(EDIT_UNDO), !tx->has_undo());
+ popup->set_item_disabled(popup->get_item_index(EDIT_REDO), !tx->has_redo());
+}
+
void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p_foldable, bool p_open_docs, bool p_goto_definition, Vector2 p_pos) {
context_menu->clear();
context_menu->add_shortcut(ED_GET_SHORTCUT("ui_undo"), EDIT_UNDO);
@@ -1669,6 +1676,10 @@ void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p
}
}
+ const CodeEdit *tx = code_editor->get_text_editor();
+ context_menu->set_item_disabled(context_menu->get_item_index(EDIT_UNDO), !tx->has_undo());
+ context_menu->set_item_disabled(context_menu->get_item_index(EDIT_REDO), !tx->has_redo());
+
context_menu->set_position(get_global_transform().xform(p_pos));
context_menu->set_size(Vector2(1, 1));
context_menu->popup();
@@ -1754,6 +1765,7 @@ void ScriptTextEditor::_enable_code_editor() {
search_menu->get_popup()->connect("id_pressed", callable_mp(this, &ScriptTextEditor::_edit_option));
edit_hb->add_child(edit_menu);
+ edit_menu->connect("about_to_popup", callable_mp(this, &ScriptTextEditor::_prepare_edit_menu));
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_undo"), EDIT_UNDO);
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_redo"), EDIT_REDO);
edit_menu->get_popup()->add_separator();
diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h
index e4a13951e4..1ca6f56ea1 100644
--- a/editor/plugins/script_text_editor.h
+++ b/editor/plugins/script_text_editor.h
@@ -178,6 +178,7 @@ protected:
void _make_context_menu(bool p_selection, bool p_color, bool p_foldable, bool p_open_docs, bool p_goto_definition, Vector2 p_pos);
void _text_edit_gui_input(const Ref<InputEvent> &ev);
void _color_changed(const Color &p_color);
+ void _prepare_edit_menu();
void _goto_line(int p_line) { goto_line(p_line); }
void _lookup_symbol(const String &p_symbol, int p_row, int p_column);
diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp
index 481eb84081..32bcc1a4e6 100644
--- a/editor/plugins/text_editor.cpp
+++ b/editor/plugins/text_editor.cpp
@@ -471,6 +471,13 @@ void TextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
}
}
+void TextEditor::_prepare_edit_menu() {
+ const CodeEdit *tx = code_editor->get_text_editor();
+ PopupMenu *popup = edit_menu->get_popup();
+ popup->set_item_disabled(popup->get_item_index(EDIT_UNDO), !tx->has_undo());
+ popup->set_item_disabled(popup->get_item_index(EDIT_REDO), !tx->has_redo());
+}
+
void TextEditor::_make_context_menu(bool p_selection, bool p_can_fold, bool p_is_folded, Vector2 p_position) {
context_menu->clear();
if (p_selection) {
@@ -497,6 +504,10 @@ void TextEditor::_make_context_menu(bool p_selection, bool p_can_fold, bool p_is
context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_fold_line"), EDIT_TOGGLE_FOLD_LINE);
}
+ const CodeEdit *tx = code_editor->get_text_editor();
+ context_menu->set_item_disabled(context_menu->get_item_index(EDIT_UNDO), !tx->has_undo());
+ context_menu->set_item_disabled(context_menu->get_item_index(EDIT_REDO), !tx->has_redo());
+
context_menu->set_position(get_global_transform().xform(p_position));
context_menu->set_size(Vector2(1, 1));
context_menu->popup();
@@ -542,6 +553,7 @@ TextEditor::TextEditor() {
edit_hb->add_child(edit_menu);
edit_menu->set_text(TTR("Edit"));
edit_menu->set_switch_on_hover(true);
+ edit_menu->connect("about_to_popup", callable_mp(this, &TextEditor::_prepare_edit_menu));
edit_menu->get_popup()->connect("id_pressed", callable_mp(this, &TextEditor::_edit_option));
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_undo"), EDIT_UNDO);
diff --git a/editor/plugins/text_editor.h b/editor/plugins/text_editor.h
index 86a4910ac0..839e1c5f7a 100644
--- a/editor/plugins/text_editor.h
+++ b/editor/plugins/text_editor.h
@@ -92,6 +92,7 @@ protected:
void _edit_option(int p_op);
void _make_context_menu(bool p_selection, bool p_can_fold, bool p_is_folded, Vector2 p_position);
void _text_edit_gui_input(const Ref<InputEvent> &ev);
+ void _prepare_edit_menu();
Map<String, Ref<EditorSyntaxHighlighter>> highlighters;
void _change_syntax_highlighter(int p_idx);
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/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index 610974ff90..092efc55d7 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -1176,11 +1176,6 @@ bool CharacterBody3D::move_and_slide() {
}
}
- if (!on_floor && !on_wall) {
- // Add last platform velocity when just left a moving platform.
- linear_velocity += current_floor_velocity;
- }
-
if (was_on_floor && snap != Vector3()) {
// Apply snap.
Transform3D gt = get_global_transform();
@@ -1213,6 +1208,11 @@ bool CharacterBody3D::move_and_slide() {
}
}
+ if (!on_floor && !on_wall) {
+ // Add last platform velocity when just left a moving platform.
+ linear_velocity += current_floor_velocity;
+ }
+
return motion_results.size() > 0;
}
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 2b3be1d5c2..11e08b231e 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -946,6 +946,17 @@ void LineEdit::paste_text() {
}
}
+bool LineEdit::has_undo() const {
+ if (undo_stack_pos == nullptr) {
+ return undo_stack.size() > 1;
+ }
+ return undo_stack_pos != undo_stack.front();
+}
+
+bool LineEdit::has_redo() const {
+ return undo_stack_pos != nullptr && undo_stack_pos != undo_stack.back();
+}
+
void LineEdit::undo() {
if (!editable) {
return;
@@ -2277,6 +2288,11 @@ void LineEdit::_ensure_menu() {
menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_AUTO), text_direction == TEXT_DIRECTION_AUTO);
menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_LTR), text_direction == TEXT_DIRECTION_LTR);
menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_RTL), text_direction == TEXT_DIRECTION_RTL);
+
+ if (editable) {
+ menu->set_item_disabled(menu->get_item_index(MENU_UNDO), !has_undo());
+ menu->set_item_disabled(menu->get_item_index(MENU_REDO), !has_redo());
+ }
}
LineEdit::LineEdit() {
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index c5c92d60aa..0e9c032e88 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -285,6 +285,8 @@ public:
void copy_text();
void cut_text();
void paste_text();
+ bool has_undo() const;
+ bool has_redo() const;
void undo();
void redo();
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 12f0c9e89a..87f06445ac 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -2963,6 +2963,18 @@ void TextEdit::end_complex_operation() {
undo_stack.back()->get().chain_backward = true;
}
+bool TextEdit::has_undo() const {
+ if (undo_stack_pos == nullptr) {
+ int pending = current_op.type == TextOperation::TYPE_NONE ? 0 : 1;
+ return undo_stack.size() + pending > 0;
+ }
+ return undo_stack_pos != undo_stack.front();
+}
+
+bool TextEdit::has_redo() const {
+ return undo_stack_pos != nullptr;
+}
+
void TextEdit::undo() {
if (!editable) {
return;
@@ -4482,6 +4494,8 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("begin_complex_operation"), &TextEdit::begin_complex_operation);
ClassDB::bind_method(D_METHOD("end_complex_operation"), &TextEdit::end_complex_operation);
+ ClassDB::bind_method(D_METHOD("has_undo"), &TextEdit::has_undo);
+ ClassDB::bind_method(D_METHOD("has_redo"), &TextEdit::has_redo);
ClassDB::bind_method(D_METHOD("undo"), &TextEdit::undo);
ClassDB::bind_method(D_METHOD("redo"), &TextEdit::redo);
ClassDB::bind_method(D_METHOD("clear_undo_history"), &TextEdit::clear_undo_history);
@@ -5070,6 +5084,11 @@ void TextEdit::_generate_context_menu() {
menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_AUTO), text_direction == TEXT_DIRECTION_AUTO);
menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_LTR), text_direction == TEXT_DIRECTION_LTR);
menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_RTL), text_direction == TEXT_DIRECTION_RTL);
+
+ if (editable) {
+ menu->set_item_disabled(menu->get_item_index(MENU_UNDO), !has_undo());
+ menu->set_item_disabled(menu->get_item_index(MENU_REDO), !has_redo());
+ }
}
int TextEdit::_get_menu_action_accelerator(const String &p_action) {
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index da322a7bcd..69468978ab 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -659,6 +659,8 @@ public:
void begin_complex_operation();
void end_complex_operation();
+ bool has_undo() const;
+ bool has_redo() const;
void undo();
void redo();
void clear_undo_history();
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;