summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/core_bind.cpp11
-rw-r--r--core/core_bind.h3
-rw-r--r--core/object/object.cpp15
-rw-r--r--core/object/object.h1
-rw-r--r--core/os/os.cpp7
-rw-r--r--core/os/os.h3
-rw-r--r--doc/classes/OS.xml8
-rw-r--r--doc/classes/Theme.xml21
-rw-r--r--editor/code_editor.cpp79
-rw-r--r--editor/editor_settings.cpp193
-rw-r--r--editor/editor_spin_slider.cpp314
-rw-r--r--editor/editor_spin_slider.h1
-rw-r--r--editor/editor_themes.cpp134
-rw-r--r--editor/inspector_dock.cpp7
-rw-r--r--editor/inspector_dock.h1
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp15
-rw-r--r--editor/plugins/editor_preview_plugins.cpp12
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp90
-rw-r--r--editor/plugins/script_editor_plugin.cpp60
-rw-r--r--editor/plugins/script_text_editor.cpp10
-rw-r--r--editor/plugins/shader_editor_plugin.cpp24
-rw-r--r--editor/plugins/text_editor.cpp2
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp36
-rw-r--r--editor/settings_config_dialog.cpp2
-rw-r--r--modules/gdscript/editor/gdscript_highlighter.cpp44
-rw-r--r--modules/gdscript/gdscript_editor.cpp4
-rw-r--r--modules/gdscript/gdscript_parser.cpp2
-rw-r--r--modules/gdscript/gdscript_tokenizer.cpp2
-rw-r--r--modules/gdscript/tests/test_gdscript.cpp2
-rw-r--r--modules/mono/csharp_script.cpp195
-rw-r--r--modules/mono/csharp_script.h17
-rw-r--r--modules/mono/glue/base_object_glue.cpp10
-rw-r--r--modules/mono/mono_gd/gd_mono_internals.cpp7
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp19
-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/joypad_osx.cpp16
-rw-r--r--platform/osx/joypad_osx.h1
-rw-r--r--platform/osx/os_osx.h2
-rw-r--r--platform/osx/os_osx.mm2
-rw-r--r--platform/windows/os_windows.cpp2
-rw-r--r--platform/windows/os_windows.h2
-rw-r--r--scene/2d/physics_body_2d.cpp18
-rw-r--r--scene/gui/line_edit.cpp8
-rw-r--r--scene/gui/text_edit.cpp10
-rw-r--r--scene/main/window.cpp2
-rw-r--r--scene/resources/theme.cpp75
-rw-r--r--scene/resources/theme.h3
-rw-r--r--servers/physics_3d/body_3d_sw.cpp2
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp67
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h35
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl83
65 files changed, 1032 insertions, 993 deletions
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index f3f51e57ee..e1d595e98c 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);
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/object.cpp b/core/object/object.cpp
index c191109a8f..2bb4b981b9 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -1811,6 +1811,21 @@ void *Object::get_instance_binding(void *p_token, const GDNativeInstanceBindingC
return binding;
}
+bool Object::has_instance_binding(void *p_token) {
+ bool found = false;
+ _instance_binding_mutex.lock();
+ for (uint32_t i = 0; i < _instance_binding_count; i++) {
+ if (_instance_bindings[i].token == p_token) {
+ found = true;
+ break;
+ }
+ }
+
+ _instance_binding_mutex.unlock();
+
+ return found;
+}
+
void Object::_construct_object(bool p_reference) {
type_is_reference = p_reference;
_instance_id = ObjectDB::add_instance(this);
diff --git a/core/object/object.h b/core/object/object.h
index 1f5e17c99f..6523105820 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -809,6 +809,7 @@ public:
void *get_instance_binding(void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks);
// Used on creation by binding only.
void set_instance_binding(void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks);
+ bool has_instance_binding(void *p_token);
void clear_internal_resource_paths();
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/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 a5943c952b..48f2be450b 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -926,38 +926,55 @@ bool CodeTextEditor::_add_font_size(int p_delta) {
}
void CodeTextEditor::update_editor_settings() {
- completion_font_color = EDITOR_GET("text_editor/highlighting/completion_font_color");
- completion_string_color = EDITOR_GET("text_editor/highlighting/string_color");
- completion_comment_color = EDITOR_GET("text_editor/highlighting/comment_color");
-
- text_editor->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_all_occurrences"));
- text_editor->set_highlight_current_line(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_current_line"));
- text_editor->set_indent_using_spaces(EditorSettings::get_singleton()->get("text_editor/indent/type"));
- text_editor->set_indent_size(EditorSettings::get_singleton()->get("text_editor/indent/size"));
- text_editor->set_auto_indent_enabled(EditorSettings::get_singleton()->get("text_editor/indent/auto_indent"));
- text_editor->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/indent/draw_tabs"));
- text_editor->set_draw_spaces(EditorSettings::get_singleton()->get("text_editor/indent/draw_spaces"));
- text_editor->set_smooth_scroll_enabled(EditorSettings::get_singleton()->get("text_editor/navigation/smooth_scrolling"));
- text_editor->set_v_scroll_speed(EditorSettings::get_singleton()->get("text_editor/navigation/v_scroll_speed"));
- text_editor->set_draw_minimap(EditorSettings::get_singleton()->get("text_editor/navigation/show_minimap"));
- text_editor->set_minimap_width((int)EditorSettings::get_singleton()->get("text_editor/navigation/minimap_width") * EDSCALE);
- text_editor->set_draw_line_numbers(EditorSettings::get_singleton()->get("text_editor/appearance/show_line_numbers"));
- text_editor->set_line_numbers_zero_padded(EditorSettings::get_singleton()->get("text_editor/appearance/line_numbers_zero_padded"));
- text_editor->set_draw_bookmarks_gutter(EditorSettings::get_singleton()->get("text_editor/appearance/show_bookmark_gutter"));
- text_editor->set_line_folding_enabled(EditorSettings::get_singleton()->get("text_editor/appearance/code_folding"));
- text_editor->set_draw_fold_gutter(EditorSettings::get_singleton()->get("text_editor/appearance/code_folding"));
- text_editor->set_line_wrapping_mode((TextEdit::LineWrappingMode)EditorSettings::get_singleton()->get("text_editor/appearance/word_wrap").operator int());
- text_editor->set_scroll_past_end_of_file_enabled(EditorSettings::get_singleton()->get("text_editor/cursor/scroll_past_end_of_file"));
- text_editor->set_caret_type((TextEdit::CaretType)EditorSettings::get_singleton()->get("text_editor/cursor/type").operator int());
- text_editor->set_caret_blink_enabled(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink"));
- text_editor->set_caret_blink_speed(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink_speed"));
+ // Theme: Highlighting
+ completion_font_color = EDITOR_GET("text_editor/theme/highlighting/completion_font_color");
+ completion_string_color = EDITOR_GET("text_editor/theme/highlighting/string_color");
+ completion_comment_color = EDITOR_GET("text_editor/theme/highlighting/comment_color");
+
+ // Appearance: Caret
+ text_editor->set_caret_type((TextEdit::CaretType)EditorSettings::get_singleton()->get("text_editor/appearance/caret/type").operator int());
+ text_editor->set_caret_blink_enabled(EditorSettings::get_singleton()->get("text_editor/appearance/caret/caret_blink"));
+ text_editor->set_caret_blink_speed(EditorSettings::get_singleton()->get("text_editor/appearance/caret/caret_blink_speed"));
+ text_editor->set_highlight_current_line(EditorSettings::get_singleton()->get("text_editor/appearance/caret/highlight_current_line"));
+ text_editor->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/appearance/caret/highlight_all_occurrences"));
+
+ // Appearance: Gutters
+ text_editor->set_draw_line_numbers(EditorSettings::get_singleton()->get("text_editor/appearance/gutters/show_line_numbers"));
+ text_editor->set_line_numbers_zero_padded(EditorSettings::get_singleton()->get("text_editor/appearance/gutters/line_numbers_zero_padded"));
+ text_editor->set_draw_bookmarks_gutter(EditorSettings::get_singleton()->get("text_editor/appearance/gutters/show_bookmark_gutter"));
+
+ // Appearance: Minimap
+ text_editor->set_draw_minimap(EditorSettings::get_singleton()->get("text_editor/appearance/minimap/show_minimap"));
+ text_editor->set_minimap_width((int)EditorSettings::get_singleton()->get("text_editor/appearance/minimap/minimap_width") * EDSCALE);
+
+ // Appearance: Lines
+ text_editor->set_line_folding_enabled(EditorSettings::get_singleton()->get("text_editor/appearance/lines/code_folding"));
+ text_editor->set_draw_fold_gutter(EditorSettings::get_singleton()->get("text_editor/appearance/lines/code_folding"));
+ text_editor->set_line_wrapping_mode((TextEdit::LineWrappingMode)EditorSettings::get_singleton()->get("text_editor/appearance/lines/word_wrap").operator int());
+
+ // Appearance: Whitespace
+ text_editor->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/appearance/whitespace/draw_tabs"));
+ text_editor->set_draw_spaces(EditorSettings::get_singleton()->get("text_editor/appearance/whitespace/draw_spaces"));
+
+ // Behavior: Navigation
+ text_editor->set_scroll_past_end_of_file_enabled(EditorSettings::get_singleton()->get("text_editor/behavior/navigation/scroll_past_end_of_file"));
+ text_editor->set_smooth_scroll_enabled(EditorSettings::get_singleton()->get("text_editor/behavior/navigation/smooth_scrolling"));
+ text_editor->set_v_scroll_speed(EditorSettings::get_singleton()->get("text_editor/behavior/navigation/v_scroll_speed"));
+
+ // Behavior: indent
+ text_editor->set_indent_using_spaces(EditorSettings::get_singleton()->get("text_editor/behavior/indent/type"));
+ text_editor->set_indent_size(EditorSettings::get_singleton()->get("text_editor/behavior/indent/size"));
+ text_editor->set_auto_indent_enabled(EditorSettings::get_singleton()->get("text_editor/behavior/indent/auto_indent"));
+
+ // Completion
text_editor->set_auto_brace_completion_enabled(EditorSettings::get_singleton()->get("text_editor/completion/auto_brace_complete"));
- if (EditorSettings::get_singleton()->get("text_editor/appearance/show_line_length_guidelines")) {
+ // Appearance: Guidelines
+ if (EditorSettings::get_singleton()->get("text_editor/appearance/guidelines/show_line_length_guidelines")) {
TypedArray<int> guideline_cols;
- guideline_cols.append(EditorSettings::get_singleton()->get("text_editor/appearance/line_length_guideline_hard_column"));
- if (EditorSettings::get_singleton()->get("text_editor/appearance/line_length_guideline_soft_column") != guideline_cols[0]) {
- guideline_cols.append(EditorSettings::get_singleton()->get("text_editor/appearance/line_length_guideline_soft_column"));
+ guideline_cols.append(EditorSettings::get_singleton()->get("text_editor/appearance/guidelines/line_length_guideline_hard_column"));
+ if (EditorSettings::get_singleton()->get("text_editor/appearance/guidelines/line_length_guideline_soft_column") != guideline_cols[0]) {
+ guideline_cols.append(EditorSettings::get_singleton()->get("text_editor/appearance/guidelines/line_length_guideline_soft_column"));
}
text_editor->set_line_length_guidelines(guideline_cols);
}
@@ -1028,7 +1045,7 @@ void CodeTextEditor::insert_final_newline() {
}
void CodeTextEditor::convert_indent_to_spaces() {
- int indent_size = EditorSettings::get_singleton()->get("text_editor/indent/size");
+ int indent_size = EditorSettings::get_singleton()->get("text_editor/behavior/indent/size");
String indent = "";
for (int i = 0; i < indent_size; i++) {
@@ -1072,7 +1089,7 @@ void CodeTextEditor::convert_indent_to_spaces() {
}
void CodeTextEditor::convert_indent_to_tabs() {
- int indent_size = EditorSettings::get_singleton()->get("text_editor/indent/size");
+ int indent_size = EditorSettings::get_singleton()->get("text_editor/behavior/indent/size");
indent_size -= 1;
int cursor_line = text_editor->get_caret_line();
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 009a83994c..3fc010c701 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -492,68 +492,73 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
// Theme
_initial_set("text_editor/theme/color_theme", "Default");
hints["text_editor/theme/color_theme"] = PropertyInfo(Variant::STRING, "text_editor/theme/color_theme", PROPERTY_HINT_ENUM, "Default,Godot 2,Custom");
- _initial_set("text_editor/theme/line_spacing", 6);
- hints["text_editor/theme/line_spacing"] = PropertyInfo(Variant::INT, "text_editor/theme/line_spacing", PROPERTY_HINT_RANGE, "0,50,1");
+ // Theme: Highlighting
_load_godot2_text_editor_theme();
- // Highlighting
- _initial_set("text_editor/highlighting/highlight_all_occurrences", true);
- _initial_set("text_editor/highlighting/highlight_current_line", true);
- _initial_set("text_editor/highlighting/highlight_type_safe_lines", true);
-
- // Indent
- _initial_set("text_editor/indent/type", 0);
- hints["text_editor/indent/type"] = PropertyInfo(Variant::INT, "text_editor/indent/type", PROPERTY_HINT_ENUM, "Tabs,Spaces");
- _initial_set("text_editor/indent/size", 4);
- hints["text_editor/indent/size"] = PropertyInfo(Variant::INT, "text_editor/indent/size", PROPERTY_HINT_RANGE, "1, 64, 1"); // size of 0 crashes.
- _initial_set("text_editor/indent/auto_indent", true);
- _initial_set("text_editor/indent/convert_indent_on_save", true);
- _initial_set("text_editor/indent/draw_tabs", true);
- _initial_set("text_editor/indent/draw_spaces", false);
-
- // Navigation
- _initial_set("text_editor/navigation/smooth_scrolling", true);
- _initial_set("text_editor/navigation/v_scroll_speed", 80);
- _initial_set("text_editor/navigation/show_minimap", true);
- _initial_set("text_editor/navigation/minimap_width", 80);
- hints["text_editor/navigation/minimap_width"] = PropertyInfo(Variant::INT, "text_editor/navigation/minimap_width", PROPERTY_HINT_RANGE, "50,250,1");
-
// Appearance
- _initial_set("text_editor/appearance/show_line_numbers", true);
- _initial_set("text_editor/appearance/line_numbers_zero_padded", false);
- _initial_set("text_editor/appearance/show_bookmark_gutter", true);
- _initial_set("text_editor/appearance/show_info_gutter", true);
- _initial_set("text_editor/appearance/code_folding", true);
- _initial_set("text_editor/appearance/word_wrap", 0);
- hints["text_editor/appearance/word_wrap"] = PropertyInfo(Variant::INT, "text_editor/appearance/word_wrap", PROPERTY_HINT_ENUM, "None,Boundary");
-
- _initial_set("text_editor/appearance/show_line_length_guidelines", true);
- _initial_set("text_editor/appearance/line_length_guideline_soft_column", 80);
- hints["text_editor/appearance/line_length_guideline_soft_column"] = PropertyInfo(Variant::INT, "text_editor/appearance/line_length_guideline_soft_column", PROPERTY_HINT_RANGE, "20, 160, 1");
- _initial_set("text_editor/appearance/line_length_guideline_hard_column", 100);
- hints["text_editor/appearance/line_length_guideline_hard_column"] = PropertyInfo(Variant::INT, "text_editor/appearance/line_length_guideline_hard_column", PROPERTY_HINT_RANGE, "20, 160, 1");
+ // Appearance: Caret
+ _initial_set("text_editor/appearance/caret/type", 0);
+ hints["text_editor/appearance/caret/type"] = PropertyInfo(Variant::INT, "text_editor/appearance/caret/type", PROPERTY_HINT_ENUM, "Line,Block");
+ _initial_set("text_editor/appearance/caret/caret_blink", true);
+ _initial_set("text_editor/appearance/caret/caret_blink_speed", 0.5);
+ hints["text_editor/appearance/caret/caret_blink_speed"] = PropertyInfo(Variant::FLOAT, "text_editor/appearance/caret/caret_blink_speed", PROPERTY_HINT_RANGE, "0.1, 10, 0.01");
+ _initial_set("text_editor/appearance/caret/highlight_current_line", true);
+ _initial_set("text_editor/appearance/caret/highlight_all_occurrences", true);
+
+ // Appearance: Guidelines
+ _initial_set("text_editor/appearance/guidelines/show_line_length_guidelines", true);
+ _initial_set("text_editor/appearance/guidelines/line_length_guideline_soft_column", 80);
+ hints["text_editor/appearance/guidelines/line_length_guideline_soft_column"] = PropertyInfo(Variant::INT, "text_editor/appearance/guidelines/line_length_guideline_soft_column", PROPERTY_HINT_RANGE, "20, 160, 1");
+ _initial_set("text_editor/appearance/guidelines/line_length_guideline_hard_column", 100);
+ hints["text_editor/appearance/guidelines/line_length_guideline_hard_column"] = PropertyInfo(Variant::INT, "text_editor/appearance/guidelines/line_length_guideline_hard_column", PROPERTY_HINT_RANGE, "20, 160, 1");
+
+ // Appearance: Gutters
+ _initial_set("text_editor/appearance/gutters/show_line_numbers", true);
+ _initial_set("text_editor/appearance/gutters/line_numbers_zero_padded", false);
+ _initial_set("text_editor/appearance/gutters/highlight_type_safe_lines", true);
+ _initial_set("text_editor/appearance/gutters/show_bookmark_gutter", true);
+ _initial_set("text_editor/appearance/gutters/show_info_gutter", true);
+
+ // Appearance: Minimap
+ _initial_set("text_editor/appearance/minimap/show_minimap", true);
+ _initial_set("text_editor/appearance/minimap/minimap_width", 80);
+ hints["text_editor/appearance/minimap/minimap_width"] = PropertyInfo(Variant::INT, "text_editor/appearance/minimap/minimap_width", PROPERTY_HINT_RANGE, "50,250,1");
+
+ // Appearance: Lines
+ _initial_set("text_editor/appearance/lines/code_folding", true);
+ _initial_set("text_editor/appearance/lines/word_wrap", 0);
+ hints["text_editor/appearance/lines/word_wrap"] = PropertyInfo(Variant::INT, "text_editor/appearance/lines/word_wrap", PROPERTY_HINT_ENUM, "None,Boundary");
+
+ // Appearance: Whitespace
+ _initial_set("text_editor/appearance/whitespace/draw_tabs", true);
+ _initial_set("text_editor/appearance/whitespace/draw_spaces", false);
+ _initial_set("text_editor/appearance/whitespace/line_spacing", 6);
+ hints["text_editor/appearance/whitespace/line_spacing"] = PropertyInfo(Variant::INT, "text_editor/appearance/whitespace/line_spacing", PROPERTY_HINT_RANGE, "0,50,1");
+
+ // Behavior
+ // Behavior: Navigation
+ _initial_set("text_editor/behavior/navigation/move_caret_on_right_click", true);
+ _initial_set("text_editor/behavior/navigation/scroll_past_end_of_file", false);
+ _initial_set("text_editor/behavior/navigation/smooth_scrolling", true);
+ _initial_set("text_editor/behavior/navigation/v_scroll_speed", 80);
+
+ // Behavior: Indent
+ _initial_set("text_editor/behavior/indent/type", 0);
+ hints["text_editor/behavior/indent/type"] = PropertyInfo(Variant::INT, "text_editor/behavior/indent/type", PROPERTY_HINT_ENUM, "Tabs,Spaces");
+ _initial_set("text_editor/behavior/indent/size", 4);
+ hints["text_editor/behavior/indent/size"] = PropertyInfo(Variant::INT, "text_editor/behavior/indent/size", PROPERTY_HINT_RANGE, "1, 64, 1"); // size of 0 crashes.
+ _initial_set("text_editor/behavior/indent/auto_indent", true);
+
+ // Behavior: Files
+ _initial_set("text_editor/behavior/files/trim_trailing_whitespace_on_save", false);
+ _initial_set("text_editor/behavior/files/autosave_interval_secs", 0);
+ _initial_set("text_editor/behavior/files/restore_scripts_on_load", true);
+ _initial_set("text_editor/behavior/files/convert_indent_on_save", true);
// Script list
_initial_set("text_editor/script_list/show_members_overview", true);
-
- // Files
- _initial_set("text_editor/files/trim_trailing_whitespace_on_save", false);
- _initial_set("text_editor/files/autosave_interval_secs", 0);
- _initial_set("text_editor/files/restore_scripts_on_load", true);
-
- // Tools
- _initial_set("text_editor/tools/create_signal_callbacks", true);
- _initial_set("text_editor/tools/sort_members_outline_alphabetically", false);
-
- // Cursor
- _initial_set("text_editor/cursor/scroll_past_end_of_file", false);
- _initial_set("text_editor/cursor/type", 0);
- hints["text_editor/cursor/type"] = PropertyInfo(Variant::INT, "text_editor/cursor/type", PROPERTY_HINT_ENUM, "Line,Block");
- _initial_set("text_editor/cursor/caret_blink", true);
- _initial_set("text_editor/cursor/caret_blink_speed", 0.5);
- hints["text_editor/cursor/caret_blink_speed"] = PropertyInfo(Variant::FLOAT, "text_editor/cursor/caret_blink_speed", PROPERTY_HINT_RANGE, "0.1, 10, 0.01");
- _initial_set("text_editor/cursor/right_click_moves_caret", true);
+ _initial_set("text_editor/script_list/sort_members_outline_alphabetically", false);
// Completion
_initial_set("text_editor/completion/idle_parse_delay", 2.0);
@@ -777,41 +782,41 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
void EditorSettings::_load_godot2_text_editor_theme() {
// Godot 2 is only a dark theme; it doesn't have a light theme counterpart.
- _initial_set("text_editor/highlighting/symbol_color", Color(0.73, 0.87, 1.0));
- _initial_set("text_editor/highlighting/keyword_color", Color(1.0, 1.0, 0.7));
- _initial_set("text_editor/highlighting/control_flow_keyword_color", Color(1.0, 0.85, 0.7));
- _initial_set("text_editor/highlighting/base_type_color", Color(0.64, 1.0, 0.83));
- _initial_set("text_editor/highlighting/engine_type_color", Color(0.51, 0.83, 1.0));
- _initial_set("text_editor/highlighting/user_type_color", Color(0.42, 0.67, 0.93));
- _initial_set("text_editor/highlighting/comment_color", Color(0.4, 0.4, 0.4));
- _initial_set("text_editor/highlighting/string_color", Color(0.94, 0.43, 0.75));
- _initial_set("text_editor/highlighting/background_color", Color(0.13, 0.12, 0.15));
- _initial_set("text_editor/highlighting/completion_background_color", Color(0.17, 0.16, 0.2));
- _initial_set("text_editor/highlighting/completion_selected_color", Color(0.26, 0.26, 0.27));
- _initial_set("text_editor/highlighting/completion_existing_color", Color(0.13, 0.87, 0.87, 0.87));
- _initial_set("text_editor/highlighting/completion_scroll_color", Color(1, 1, 1));
- _initial_set("text_editor/highlighting/completion_font_color", Color(0.67, 0.67, 0.67));
- _initial_set("text_editor/highlighting/text_color", Color(0.67, 0.67, 0.67));
- _initial_set("text_editor/highlighting/line_number_color", Color(0.67, 0.67, 0.67, 0.4));
- _initial_set("text_editor/highlighting/safe_line_number_color", Color(0.67, 0.78, 0.67, 0.6));
- _initial_set("text_editor/highlighting/caret_color", Color(0.67, 0.67, 0.67));
- _initial_set("text_editor/highlighting/caret_background_color", Color(0, 0, 0));
- _initial_set("text_editor/highlighting/text_selected_color", Color(0, 0, 0));
- _initial_set("text_editor/highlighting/selection_color", Color(0.41, 0.61, 0.91, 0.35));
- _initial_set("text_editor/highlighting/brace_mismatch_color", Color(1, 0.2, 0.2));
- _initial_set("text_editor/highlighting/current_line_color", Color(0.3, 0.5, 0.8, 0.15));
- _initial_set("text_editor/highlighting/line_length_guideline_color", Color(0.3, 0.5, 0.8, 0.1));
- _initial_set("text_editor/highlighting/word_highlighted_color", Color(0.8, 0.9, 0.9, 0.15));
- _initial_set("text_editor/highlighting/number_color", Color(0.92, 0.58, 0.2));
- _initial_set("text_editor/highlighting/function_color", Color(0.4, 0.64, 0.81));
- _initial_set("text_editor/highlighting/member_variable_color", Color(0.9, 0.31, 0.35));
- _initial_set("text_editor/highlighting/mark_color", Color(1.0, 0.4, 0.4, 0.4));
- _initial_set("text_editor/highlighting/bookmark_color", Color(0.08, 0.49, 0.98));
- _initial_set("text_editor/highlighting/breakpoint_color", Color(0.9, 0.29, 0.3));
- _initial_set("text_editor/highlighting/executing_line_color", Color(0.98, 0.89, 0.27));
- _initial_set("text_editor/highlighting/code_folding_color", Color(0.8, 0.8, 0.8, 0.8));
- _initial_set("text_editor/highlighting/search_result_color", Color(0.05, 0.25, 0.05, 1));
- _initial_set("text_editor/highlighting/search_result_border_color", Color(0.41, 0.61, 0.91, 0.38));
+ _initial_set("text_editor/theme/highlighting/symbol_color", Color(0.73, 0.87, 1.0));
+ _initial_set("text_editor/theme/highlighting/keyword_color", Color(1.0, 1.0, 0.7));
+ _initial_set("text_editor/theme/highlighting/control_flow_keyword_color", Color(1.0, 0.85, 0.7));
+ _initial_set("text_editor/theme/highlighting/base_type_color", Color(0.64, 1.0, 0.83));
+ _initial_set("text_editor/theme/highlighting/engine_type_color", Color(0.51, 0.83, 1.0));
+ _initial_set("text_editor/theme/highlighting/user_type_color", Color(0.42, 0.67, 0.93));
+ _initial_set("text_editor/theme/highlighting/comment_color", Color(0.4, 0.4, 0.4));
+ _initial_set("text_editor/theme/highlighting/string_color", Color(0.94, 0.43, 0.75));
+ _initial_set("text_editor/theme/highlighting/background_color", Color(0.13, 0.12, 0.15));
+ _initial_set("text_editor/theme/highlighting/completion_background_color", Color(0.17, 0.16, 0.2));
+ _initial_set("text_editor/theme/highlighting/completion_selected_color", Color(0.26, 0.26, 0.27));
+ _initial_set("text_editor/theme/highlighting/completion_existing_color", Color(0.13, 0.87, 0.87, 0.87));
+ _initial_set("text_editor/theme/highlighting/completion_scroll_color", Color(1, 1, 1));
+ _initial_set("text_editor/theme/highlighting/completion_font_color", Color(0.67, 0.67, 0.67));
+ _initial_set("text_editor/theme/highlighting/text_color", Color(0.67, 0.67, 0.67));
+ _initial_set("text_editor/theme/highlighting/line_number_color", Color(0.67, 0.67, 0.67, 0.4));
+ _initial_set("text_editor/theme/highlighting/safe_line_number_color", Color(0.67, 0.78, 0.67, 0.6));
+ _initial_set("text_editor/theme/highlighting/caret_color", Color(0.67, 0.67, 0.67));
+ _initial_set("text_editor/theme/highlighting/caret_background_color", Color(0, 0, 0));
+ _initial_set("text_editor/theme/highlighting/text_selected_color", Color(0, 0, 0));
+ _initial_set("text_editor/theme/highlighting/selection_color", Color(0.41, 0.61, 0.91, 0.35));
+ _initial_set("text_editor/theme/highlighting/brace_mismatch_color", Color(1, 0.2, 0.2));
+ _initial_set("text_editor/theme/highlighting/current_line_color", Color(0.3, 0.5, 0.8, 0.15));
+ _initial_set("text_editor/theme/highlighting/line_length_guideline_color", Color(0.3, 0.5, 0.8, 0.1));
+ _initial_set("text_editor/theme/highlighting/word_highlighted_color", Color(0.8, 0.9, 0.9, 0.15));
+ _initial_set("text_editor/theme/highlighting/number_color", Color(0.92, 0.58, 0.2));
+ _initial_set("text_editor/theme/highlighting/function_color", Color(0.4, 0.64, 0.81));
+ _initial_set("text_editor/theme/highlighting/member_variable_color", Color(0.9, 0.31, 0.35));
+ _initial_set("text_editor/theme/highlighting/mark_color", Color(1.0, 0.4, 0.4, 0.4));
+ _initial_set("text_editor/theme/highlighting/bookmark_color", Color(0.08, 0.49, 0.98));
+ _initial_set("text_editor/theme/highlighting/breakpoint_color", Color(0.9, 0.29, 0.3));
+ _initial_set("text_editor/theme/highlighting/executing_line_color", Color(0.98, 0.89, 0.27));
+ _initial_set("text_editor/theme/highlighting/code_folding_color", Color(0.8, 0.8, 0.8, 0.8));
+ _initial_set("text_editor/theme/highlighting/search_result_color", Color(0.05, 0.25, 0.05, 1));
+ _initial_set("text_editor/theme/highlighting/search_result_border_color", Color(0.41, 0.61, 0.91, 0.38));
}
bool EditorSettings::_save_text_editor_theme(String p_file) {
@@ -823,8 +828,8 @@ bool EditorSettings::_save_text_editor_theme(String p_file) {
keys.sort();
for (const String &key : keys) {
- if (key.begins_with("text_editor/highlighting/") && key.find("color") >= 0) {
- cf->set_value(theme_section, key.replace("text_editor/highlighting/", ""), ((Color)props[key].variant).to_html());
+ if (key.begins_with("text_editor/theme/highlighting/") && key.find("color") >= 0) {
+ cf->set_value(theme_section, key.replace("text_editor/theme/highlighting/", ""), ((Color)props[key].variant).to_html());
}
}
@@ -1340,10 +1345,10 @@ void EditorSettings::load_text_editor_theme() {
String val = cf->get_value("color_theme", key);
// don't load if it's not already there!
- if (has_setting("text_editor/highlighting/" + key)) {
+ if (has_setting("text_editor/theme/highlighting/" + key)) {
// make sure it is actually a color
if (val.is_valid_html_color() && key.find("color") >= 0) {
- props["text_editor/highlighting/" + key].variant = Color::html(val); // change manually to prevent "Settings changed" console spam
+ props["text_editor/theme/highlighting/" + key].variant = Color::html(val); // change manually to prevent "Settings changed" console spam
}
}
}
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 e93c8a1a05..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));
@@ -1061,7 +1066,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_icon("folded", "CodeEdit", theme->get_icon("GuiTreeArrowRight", "EditorIcons"));
theme->set_icon("can_fold", "CodeEdit", theme->get_icon("GuiTreeArrowDown", "EditorIcons"));
theme->set_icon("executing_line", "CodeEdit", theme->get_icon("MainPlay", "EditorIcons"));
- theme->set_constant("line_spacing", "CodeEdit", EDITOR_DEF("text_editor/theme/line_spacing", 6));
+ theme->set_constant("line_spacing", "CodeEdit", EDITOR_DEF("text_editor/appearance/whitespace/line_spacing", 6));
// H/VSplitContainer
theme->set_stylebox("bg", "VSplitContainer", make_stylebox(theme->get_icon("GuiVsplitBg", "EditorIcons"), 1, 1, 1, 1));
@@ -1433,81 +1438,80 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
EditorSettings *setting = EditorSettings::get_singleton();
String text_editor_color_theme = setting->get("text_editor/theme/color_theme");
if (text_editor_color_theme == "Default") {
- setting->set_initial_value("text_editor/highlighting/symbol_color", symbol_color, true);
- setting->set_initial_value("text_editor/highlighting/keyword_color", keyword_color, true);
- setting->set_initial_value("text_editor/highlighting/control_flow_keyword_color", control_flow_keyword_color, true);
- setting->set_initial_value("text_editor/highlighting/base_type_color", basetype_color, true);
- setting->set_initial_value("text_editor/highlighting/engine_type_color", type_color, true);
- setting->set_initial_value("text_editor/highlighting/user_type_color", usertype_color, true);
- setting->set_initial_value("text_editor/highlighting/comment_color", comment_color, true);
- setting->set_initial_value("text_editor/highlighting/string_color", string_color, true);
- setting->set_initial_value("text_editor/highlighting/background_color", te_background_color, true);
- setting->set_initial_value("text_editor/highlighting/completion_background_color", completion_background_color, true);
- setting->set_initial_value("text_editor/highlighting/completion_selected_color", completion_selected_color, true);
- setting->set_initial_value("text_editor/highlighting/completion_existing_color", completion_existing_color, true);
- setting->set_initial_value("text_editor/highlighting/completion_scroll_color", completion_scroll_color, true);
- setting->set_initial_value("text_editor/highlighting/completion_font_color", completion_font_color, true);
- setting->set_initial_value("text_editor/highlighting/text_color", text_color, true);
- setting->set_initial_value("text_editor/highlighting/line_number_color", line_number_color, true);
- setting->set_initial_value("text_editor/highlighting/safe_line_number_color", safe_line_number_color, true);
- setting->set_initial_value("text_editor/highlighting/caret_color", caret_color, true);
- setting->set_initial_value("text_editor/highlighting/caret_background_color", caret_background_color, true);
- setting->set_initial_value("text_editor/highlighting/text_selected_color", text_selected_color, true);
- setting->set_initial_value("text_editor/highlighting/selection_color", selection_color, true);
- setting->set_initial_value("text_editor/highlighting/brace_mismatch_color", brace_mismatch_color, true);
- setting->set_initial_value("text_editor/highlighting/current_line_color", current_line_color, true);
- setting->set_initial_value("text_editor/highlighting/line_length_guideline_color", line_length_guideline_color, true);
- setting->set_initial_value("text_editor/highlighting/word_highlighted_color", word_highlighted_color, true);
- setting->set_initial_value("text_editor/highlighting/number_color", number_color, true);
- setting->set_initial_value("text_editor/highlighting/function_color", function_color, true);
- setting->set_initial_value("text_editor/highlighting/member_variable_color", member_variable_color, true);
- setting->set_initial_value("text_editor/highlighting/mark_color", mark_color, true);
- setting->set_initial_value("text_editor/highlighting/bookmark_color", bookmark_color, true);
- setting->set_initial_value("text_editor/highlighting/breakpoint_color", breakpoint_color, true);
- setting->set_initial_value("text_editor/highlighting/executing_line_color", executing_line_color, true);
- setting->set_initial_value("text_editor/highlighting/code_folding_color", code_folding_color, true);
- setting->set_initial_value("text_editor/highlighting/search_result_color", search_result_color, true);
- setting->set_initial_value("text_editor/highlighting/search_result_border_color", search_result_border_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/symbol_color", symbol_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/keyword_color", keyword_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/control_flow_keyword_color", control_flow_keyword_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/base_type_color", basetype_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/engine_type_color", type_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/user_type_color", usertype_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/comment_color", comment_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/string_color", string_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/background_color", te_background_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/completion_background_color", completion_background_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/completion_selected_color", completion_selected_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/completion_existing_color", completion_existing_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/completion_scroll_color", completion_scroll_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/completion_font_color", completion_font_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/text_color", text_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/line_number_color", line_number_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/safe_line_number_color", safe_line_number_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/caret_color", caret_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/caret_background_color", caret_background_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/text_selected_color", text_selected_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/selection_color", selection_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/brace_mismatch_color", brace_mismatch_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/current_line_color", current_line_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/line_length_guideline_color", line_length_guideline_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/word_highlighted_color", word_highlighted_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/number_color", number_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/function_color", function_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/member_variable_color", member_variable_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/mark_color", mark_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/bookmark_color", bookmark_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/breakpoint_color", breakpoint_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/executing_line_color", executing_line_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/code_folding_color", code_folding_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/search_result_color", search_result_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/search_result_border_color", search_result_border_color, true);
} else if (text_editor_color_theme == "Godot 2") {
setting->load_text_editor_theme();
}
// Now theme is loaded, apply it to CodeEdit.
- theme->set_color("background_color", "CodeEdit", EDITOR_GET("text_editor/highlighting/background_color"));
- theme->set_color("completion_background_color", "CodeEdit", EDITOR_GET("text_editor/highlighting/completion_background_color"));
- theme->set_color("completion_selected_color", "CodeEdit", EDITOR_GET("text_editor/highlighting/completion_selected_color"));
- theme->set_color("completion_existing_color", "CodeEdit", EDITOR_GET("text_editor/highlighting/completion_existing_color"));
- theme->set_color("completion_scroll_color", "CodeEdit", EDITOR_GET("text_editor/highlighting/completion_scroll_color"));
- theme->set_color("completion_font_color", "CodeEdit", EDITOR_GET("text_editor/highlighting/completion_font_color"));
- theme->set_color("font_color", "CodeEdit", EDITOR_GET("text_editor/highlighting/text_color"));
- theme->set_color("line_number_color", "CodeEdit", EDITOR_GET("text_editor/highlighting/line_number_color"));
- theme->set_color("caret_color", "CodeEdit", EDITOR_GET("text_editor/highlighting/caret_color"));
- theme->set_color("font_selected_color", "CodeEdit", EDITOR_GET("text_editor/highlighting/text_selected_color"));
- theme->set_color("selection_color", "CodeEdit", EDITOR_GET("text_editor/highlighting/selection_color"));
- theme->set_color("brace_mismatch_color", "CodeEdit", EDITOR_GET("text_editor/highlighting/brace_mismatch_color"));
- theme->set_color("current_line_color", "CodeEdit", EDITOR_GET("text_editor/highlighting/current_line_color"));
- theme->set_color("line_length_guideline_color", "CodeEdit", EDITOR_GET("text_editor/highlighting/line_length_guideline_color"));
- theme->set_color("word_highlighted_color", "CodeEdit", EDITOR_GET("text_editor/highlighting/word_highlighted_color"));
- theme->set_color("bookmark_color", "CodeEdit", EDITOR_GET("text_editor/highlighting/bookmark_color"));
- theme->set_color("breakpoint_color", "CodeEdit", EDITOR_GET("text_editor/highlighting/breakpoint_color"));
- theme->set_color("executing_line_color", "CodeEdit", EDITOR_GET("text_editor/highlighting/executing_line_color"));
- theme->set_color("code_folding_color", "CodeEdit", EDITOR_GET("text_editor/highlighting/code_folding_color"));
- theme->set_color("search_result_color", "CodeEdit", EDITOR_GET("text_editor/highlighting/search_result_color"));
- theme->set_color("search_result_border_color", "CodeEdit", EDITOR_GET("text_editor/highlighting/search_result_border_color"));
+ theme->set_color("background_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/background_color"));
+ theme->set_color("completion_background_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_background_color"));
+ theme->set_color("completion_selected_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_selected_color"));
+ theme->set_color("completion_existing_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_existing_color"));
+ theme->set_color("completion_scroll_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_scroll_color"));
+ theme->set_color("completion_font_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_font_color"));
+ theme->set_color("font_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/text_color"));
+ theme->set_color("line_number_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/line_number_color"));
+ theme->set_color("caret_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/caret_color"));
+ theme->set_color("font_selected_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/text_selected_color"));
+ theme->set_color("selection_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/selection_color"));
+ theme->set_color("brace_mismatch_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/brace_mismatch_color"));
+ theme->set_color("current_line_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/current_line_color"));
+ theme->set_color("line_length_guideline_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/line_length_guideline_color"));
+ theme->set_color("word_highlighted_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/word_highlighted_color"));
+ theme->set_color("bookmark_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/bookmark_color"));
+ theme->set_color("breakpoint_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/breakpoint_color"));
+ theme->set_color("executing_line_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/executing_line_color"));
+ theme->set_color("code_folding_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/code_folding_color"));
+ theme->set_color("search_result_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/search_result_color"));
+ theme->set_color("search_result_border_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/search_result_border_color"));
return 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/inspector_dock.cpp b/editor/inspector_dock.cpp
index 952bec4d87..778046f45c 100644
--- a/editor/inspector_dock.cpp
+++ b/editor/inspector_dock.cpp
@@ -209,6 +209,12 @@ void InspectorDock::_paste_resource() {
}
}
+void InspectorDock::_prepare_resource_extra_popup() {
+ RES r = EditorSettings::get_singleton()->get_resource_clipboard();
+ PopupMenu *popup = resource_extra_button->get_popup();
+ popup->set_item_disabled(popup->get_item_index(RESOURCE_EDIT_CLIPBOARD), r.is_null());
+}
+
void InspectorDock::_prepare_history() {
EditorHistory *editor_history = EditorNode::get_singleton()->get_editor_history();
@@ -525,6 +531,7 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) {
resource_extra_button->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
resource_extra_button->set_tooltip(TTR("Extra resource options."));
general_options_hb->add_child(resource_extra_button);
+ resource_extra_button->connect("about_to_popup", callable_mp(this, &InspectorDock::_prepare_resource_extra_popup));
resource_extra_button->get_popup()->add_icon_shortcut(get_theme_icon(SNAME("ActionPaste"), SNAME("EditorIcons")), ED_SHORTCUT("property_editor/paste_resource", TTR("Edit Resource from Clipboard")), RESOURCE_EDIT_CLIPBOARD);
resource_extra_button->get_popup()->add_icon_shortcut(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")), ED_SHORTCUT("property_editor/copy_resource", TTR("Copy Resource")), RESOURCE_COPY);
resource_extra_button->get_popup()->set_item_disabled(1, true);
diff --git a/editor/inspector_dock.h b/editor/inspector_dock.h
index d50785d95c..6615845b66 100644
--- a/editor/inspector_dock.h
+++ b/editor/inspector_dock.h
@@ -102,6 +102,7 @@ class InspectorDock : public VBoxContainer {
void _unref_resource();
void _copy_resource();
void _paste_resource();
+ void _prepare_resource_extra_popup();
void _warning_pressed();
void _resource_created();
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/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp
index d47bd2d410..95f68d5f7f 100644
--- a/editor/plugins/editor_preview_plugins.cpp
+++ b/editor/plugins/editor_preview_plugins.cpp
@@ -505,12 +505,12 @@ Ref<Texture2D> EditorScriptPreviewPlugin::generate(const RES &p_from, const Size
int thumbnail_size = MAX(p_size.x, p_size.y);
img->create(thumbnail_size, thumbnail_size, false, Image::FORMAT_RGBA8);
- Color bg_color = EditorSettings::get_singleton()->get("text_editor/highlighting/background_color");
- Color keyword_color = EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color");
- Color control_flow_keyword_color = EditorSettings::get_singleton()->get("text_editor/highlighting/control_flow_keyword_color");
- Color text_color = EditorSettings::get_singleton()->get("text_editor/highlighting/text_color");
- Color symbol_color = EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color");
- Color comment_color = EditorSettings::get_singleton()->get("text_editor/highlighting/comment_color");
+ Color bg_color = EditorSettings::get_singleton()->get("text_editor/theme/highlighting/background_color");
+ Color keyword_color = EditorSettings::get_singleton()->get("text_editor/theme/highlighting/keyword_color");
+ Color control_flow_keyword_color = EditorSettings::get_singleton()->get("text_editor/theme/highlighting/control_flow_keyword_color");
+ Color text_color = EditorSettings::get_singleton()->get("text_editor/theme/highlighting/text_color");
+ Color symbol_color = EditorSettings::get_singleton()->get("text_editor/theme/highlighting/symbol_color");
+ Color comment_color = EditorSettings::get_singleton()->get("text_editor/theme/highlighting/comment_color");
if (bg_color.a == 0) {
bg_color = Color(0, 0, 0, 0);
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index a48b6a090b..4300a56ef0 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -690,53 +690,55 @@ void Node3DEditorViewport::_select_region() {
Node3D *single_selected = spatial_editor->get_single_selected_node();
Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(single_selected);
- Ref<EditorNode3DGizmo> old_gizmo;
- if (!clicked_wants_append) {
- se->subgizmos.clear();
- old_gizmo = se->gizmo;
- se->gizmo.unref();
- }
-
- bool found_subgizmos = false;
- Vector<Ref<Node3DGizmo>> gizmos = single_selected->get_gizmos();
- for (int j = 0; j < gizmos.size(); j++) {
- Ref<EditorNode3DGizmo> seg = gizmos[j];
- if (!seg.is_valid()) {
- continue;
+ if (se) {
+ Ref<EditorNode3DGizmo> old_gizmo;
+ if (!clicked_wants_append) {
+ se->subgizmos.clear();
+ old_gizmo = se->gizmo;
+ se->gizmo.unref();
}
- if (se->gizmo.is_valid() && se->gizmo != seg) {
- continue;
- }
+ bool found_subgizmos = false;
+ Vector<Ref<Node3DGizmo>> gizmos = single_selected->get_gizmos();
+ for (int j = 0; j < gizmos.size(); j++) {
+ Ref<EditorNode3DGizmo> seg = gizmos[j];
+ if (!seg.is_valid()) {
+ continue;
+ }
+
+ if (se->gizmo.is_valid() && se->gizmo != seg) {
+ continue;
+ }
- Vector<int> subgizmos = seg->subgizmos_intersect_frustum(camera, frustum);
- if (!subgizmos.is_empty()) {
- se->gizmo = seg;
- for (int i = 0; i < subgizmos.size(); i++) {
- int subgizmo_id = subgizmos[i];
- if (!se->subgizmos.has(subgizmo_id)) {
- se->subgizmos.insert(subgizmo_id, se->gizmo->get_subgizmo_transform(subgizmo_id));
+ Vector<int> subgizmos = seg->subgizmos_intersect_frustum(camera, frustum);
+ if (!subgizmos.is_empty()) {
+ se->gizmo = seg;
+ for (int i = 0; i < subgizmos.size(); i++) {
+ int subgizmo_id = subgizmos[i];
+ if (!se->subgizmos.has(subgizmo_id)) {
+ se->subgizmos.insert(subgizmo_id, se->gizmo->get_subgizmo_transform(subgizmo_id));
+ }
}
+ found_subgizmos = true;
+ break;
}
- found_subgizmos = true;
- break;
}
- }
- if (!clicked_wants_append || found_subgizmos) {
- if (se->gizmo.is_valid()) {
- se->gizmo->redraw();
- }
+ if (!clicked_wants_append || found_subgizmos) {
+ if (se->gizmo.is_valid()) {
+ se->gizmo->redraw();
+ }
- if (old_gizmo != se->gizmo && old_gizmo.is_valid()) {
- old_gizmo->redraw();
- }
+ if (old_gizmo != se->gizmo && old_gizmo.is_valid()) {
+ old_gizmo->redraw();
+ }
- spatial_editor->update_transform_gizmo();
- }
+ spatial_editor->update_transform_gizmo();
+ }
- if (found_subgizmos) {
- return;
+ if (found_subgizmos) {
+ return;
+ }
}
}
@@ -4824,13 +4826,13 @@ void _update_all_gizmos(Node *p_node) {
}
void Node3DEditor::update_all_gizmos(Node *p_node) {
+ if (!p_node && get_tree()) {
+ p_node = get_tree()->get_edited_scene_root();
+ }
+
if (!p_node) {
- if (SceneTree::get_singleton()) {
- p_node = SceneTree::get_singleton()->get_root();
- } else {
- // No scene tree, so nothing to update.
- return;
- }
+ // No edited scene, so nothing to update.
+ return;
}
_update_all_gizmos(p_node);
}
@@ -6639,6 +6641,7 @@ void Node3DEditor::_notification(int p_what) {
_register_all_gizmos();
_update_gizmos_menu();
_init_indicators();
+ update_all_gizmos();
} break;
case NOTIFICATION_EXIT_TREE: {
_finish_indicators();
@@ -7772,7 +7775,6 @@ void Node3DEditor::add_gizmo_plugin(Ref<EditorNode3DGizmoPlugin> p_plugin) {
gizmo_plugins_by_name.sort_custom<_GizmoPluginNameComparator>();
_update_gizmos_menu();
- Node3DEditor::get_singleton()->update_all_gizmos();
}
void Node3DEditor::remove_gizmo_plugin(Ref<EditorNode3DGizmoPlugin> p_plugin) {
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index e6762826dd..226a54b966 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -94,13 +94,13 @@ void EditorStandardSyntaxHighlighter::_update_cache() {
highlighter->clear_member_keyword_colors();
highlighter->clear_color_regions();
- highlighter->set_symbol_color(EDITOR_GET("text_editor/highlighting/symbol_color"));
- highlighter->set_function_color(EDITOR_GET("text_editor/highlighting/function_color"));
- highlighter->set_number_color(EDITOR_GET("text_editor/highlighting/number_color"));
- highlighter->set_member_variable_color(EDITOR_GET("text_editor/highlighting/member_variable_color"));
+ highlighter->set_symbol_color(EDITOR_GET("text_editor/theme/highlighting/symbol_color"));
+ highlighter->set_function_color(EDITOR_GET("text_editor/theme/highlighting/function_color"));
+ highlighter->set_number_color(EDITOR_GET("text_editor/theme/highlighting/number_color"));
+ highlighter->set_member_variable_color(EDITOR_GET("text_editor/theme/highlighting/member_variable_color"));
/* Engine types. */
- const Color type_color = EDITOR_GET("text_editor/highlighting/engine_type_color");
+ const Color type_color = EDITOR_GET("text_editor/theme/highlighting/engine_type_color");
List<StringName> types;
ClassDB::get_class_list(&types);
for (const StringName &E : types) {
@@ -112,7 +112,7 @@ void EditorStandardSyntaxHighlighter::_update_cache() {
}
/* User types. */
- const Color usertype_color = EDITOR_GET("text_editor/highlighting/user_type_color");
+ const Color usertype_color = EDITOR_GET("text_editor/theme/highlighting/user_type_color");
List<StringName> global_classes;
ScriptServer::get_global_class_list(&global_classes);
for (const StringName &E : global_classes) {
@@ -131,7 +131,7 @@ void EditorStandardSyntaxHighlighter::_update_cache() {
const Ref<Script> script = _get_edited_resource();
if (script.is_valid()) {
/* Core types. */
- const Color basetype_color = EDITOR_GET("text_editor/highlighting/base_type_color");
+ const Color basetype_color = EDITOR_GET("text_editor/theme/highlighting/base_type_color");
List<String> core_types;
script->get_language()->get_core_type_words(&core_types);
for (const String &E : core_types) {
@@ -139,8 +139,8 @@ void EditorStandardSyntaxHighlighter::_update_cache() {
}
/* Reserved words. */
- const Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color");
- const Color control_flow_keyword_color = EDITOR_GET("text_editor/highlighting/control_flow_keyword_color");
+ const Color keyword_color = EDITOR_GET("text_editor/theme/highlighting/keyword_color");
+ const Color control_flow_keyword_color = EDITOR_GET("text_editor/theme/highlighting/control_flow_keyword_color");
List<String> keywords;
script->get_language()->get_reserved_words(&keywords);
for (const String &E : keywords) {
@@ -152,7 +152,7 @@ void EditorStandardSyntaxHighlighter::_update_cache() {
}
/* Member types. */
- const Color member_variable_color = EDITOR_GET("text_editor/highlighting/member_variable_color");
+ const Color member_variable_color = EDITOR_GET("text_editor/theme/highlighting/member_variable_color");
StringName instance_base = script->get_instance_base_type();
if (instance_base != StringName()) {
List<PropertyInfo> plist;
@@ -176,7 +176,7 @@ void EditorStandardSyntaxHighlighter::_update_cache() {
}
/* Comments */
- const Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color");
+ const Color comment_color = EDITOR_GET("text_editor/theme/highlighting/comment_color");
List<String> comments;
script->get_language()->get_comment_delimiters(&comments);
for (const String &comment : comments) {
@@ -186,7 +186,7 @@ void EditorStandardSyntaxHighlighter::_update_cache() {
}
/* Strings */
- const Color string_color = EDITOR_GET("text_editor/highlighting/string_color");
+ const Color string_color = EDITOR_GET("text_editor/theme/highlighting/string_color");
List<String> strings;
script->get_language()->get_string_delimiters(&strings);
for (const String &string : strings) {
@@ -961,7 +961,7 @@ bool ScriptEditor::_test_script_times_on_disk(RES p_for_script) {
bool need_ask = false;
bool need_reload = false;
- bool use_autoreload = bool(EDITOR_DEF("text_editor/files/auto_reload_scripts_on_external_change", false));
+ bool use_autoreload = bool(EDITOR_DEF("text_editor/behavior/files/auto_reload_scripts_on_external_change", false));
for (int i = 0; i < tab_container->get_child_count(); i++) {
ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_child(i));
@@ -1712,7 +1712,7 @@ void ScriptEditor::_update_members_overview_visibility() {
}
void ScriptEditor::_toggle_members_overview_alpha_sort(bool p_alphabetic_sort) {
- EditorSettings::get_singleton()->set("text_editor/tools/sort_members_outline_alphabetically", p_alphabetic_sort);
+ EditorSettings::get_singleton()->set("text_editor/script_list/sort_members_outline_alphabetically", p_alphabetic_sort);
_update_members_overview();
}
@@ -1725,7 +1725,7 @@ void ScriptEditor::_update_members_overview() {
}
Vector<String> functions = se->get_functions();
- if (EditorSettings::get_singleton()->get("text_editor/tools/sort_members_outline_alphabetically")) {
+ if (EditorSettings::get_singleton()->get("text_editor/script_list/sort_members_outline_alphabetically")) {
functions.sort();
}
@@ -2104,7 +2104,7 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra
const bool use_external_editor =
EditorSettings::get_singleton()->get("text_editor/external/use_external_editor") ||
(script.is_valid() && script->get_language()->overrides_external_editor());
- const bool open_dominant = EditorSettings::get_singleton()->get("text_editor/files/open_dominant_script_on_scene_change");
+ const bool open_dominant = EditorSettings::get_singleton()->get("text_editor/behavior/files/open_dominant_script_on_scene_change");
const bool should_open = (open_dominant && !use_external_editor) || !EditorNode::get_singleton()->is_changing_scene();
@@ -2469,9 +2469,9 @@ void ScriptEditor::_save_layout() {
}
void ScriptEditor::_editor_settings_changed() {
- trim_trailing_whitespace_on_save = EditorSettings::get_singleton()->get("text_editor/files/trim_trailing_whitespace_on_save");
- convert_indent_on_save = EditorSettings::get_singleton()->get("text_editor/indent/convert_indent_on_save");
- use_space_indentation = EditorSettings::get_singleton()->get("text_editor/indent/type");
+ trim_trailing_whitespace_on_save = EditorSettings::get_singleton()->get("text_editor/behavior/files/trim_trailing_whitespace_on_save");
+ convert_indent_on_save = EditorSettings::get_singleton()->get("text_editor/behavior/files/convert_indent_on_save");
+ use_space_indentation = EditorSettings::get_singleton()->get("text_editor/behavior/indent/type");
members_overview_enabled = EditorSettings::get_singleton()->get("text_editor/script_list/show_members_overview");
help_overview_enabled = EditorSettings::get_singleton()->get("text_editor/help/show_help_index");
@@ -2498,7 +2498,7 @@ void ScriptEditor::_editor_settings_changed() {
_update_script_colors();
_update_script_names();
- ScriptServer::set_reload_scripts_on_save(EDITOR_DEF("text_editor/files/auto_reload_and_parse_scripts_on_save", true));
+ ScriptServer::set_reload_scripts_on_save(EDITOR_DEF("text_editor/behavior/files/auto_reload_and_parse_scripts_on_save", true));
}
void ScriptEditor::_filesystem_changed() {
@@ -2537,7 +2537,7 @@ void ScriptEditor::_update_autosave_timer() {
return;
}
- float autosave_time = EditorSettings::get_singleton()->get("text_editor/files/autosave_interval_secs");
+ float autosave_time = EditorSettings::get_singleton()->get("text_editor/behavior/files/autosave_interval_secs");
if (autosave_time > 0) {
autosave_timer->set_wait_time(autosave_time);
autosave_timer->start();
@@ -2827,7 +2827,7 @@ void ScriptEditor::_make_script_list_context_menu() {
}
void ScriptEditor::set_window_layout(Ref<ConfigFile> p_layout) {
- if (!bool(EDITOR_DEF("text_editor/files/restore_scripts_on_load", true))) {
+ if (!bool(EDITOR_DEF("text_editor/behavior/files/restore_scripts_on_load", true))) {
return;
}
@@ -3120,7 +3120,7 @@ void ScriptEditor::set_scene_root_script(Ref<Script> p_script) {
const bool use_external_editor =
EditorSettings::get_singleton()->get("text_editor/external/use_external_editor") ||
(p_script.is_valid() && p_script->get_language()->overrides_external_editor());
- const bool open_dominant = EditorSettings::get_singleton()->get("text_editor/files/open_dominant_script_on_scene_change");
+ const bool open_dominant = EditorSettings::get_singleton()->get("text_editor/behavior/files/open_dominant_script_on_scene_change");
if (open_dominant && !use_external_editor && p_script.is_valid()) {
edit(p_script);
@@ -3367,7 +3367,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
members_overview_alphabeta_sort_button->set_flat(true);
members_overview_alphabeta_sort_button->set_tooltip(TTR("Toggle alphabetical sorting of the method list."));
members_overview_alphabeta_sort_button->set_toggle_mode(true);
- members_overview_alphabeta_sort_button->set_pressed(EditorSettings::get_singleton()->get("text_editor/tools/sort_members_outline_alphabetically"));
+ members_overview_alphabeta_sort_button->set_pressed(EditorSettings::get_singleton()->get("text_editor/script_list/sort_members_outline_alphabetically"));
members_overview_alphabeta_sort_button->connect("toggled", callable_mp(this, &ScriptEditor::_toggle_members_overview_alpha_sort));
buttons_hbox->add_child(members_overview_alphabeta_sort_button);
@@ -3604,9 +3604,9 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
history_pos = -1;
edit_pass = 0;
- trim_trailing_whitespace_on_save = EditorSettings::get_singleton()->get("text_editor/files/trim_trailing_whitespace_on_save");
- convert_indent_on_save = EditorSettings::get_singleton()->get("text_editor/indent/convert_indent_on_save");
- use_space_indentation = EditorSettings::get_singleton()->get("text_editor/indent/type");
+ trim_trailing_whitespace_on_save = EditorSettings::get_singleton()->get("text_editor/behavior/files/trim_trailing_whitespace_on_save");
+ convert_indent_on_save = EditorSettings::get_singleton()->get("text_editor/behavior/files/convert_indent_on_save");
+ use_space_indentation = EditorSettings::get_singleton()->get("text_editor/behavior/indent/type");
ScriptServer::edit_request_func = _open_script_request;
@@ -3703,9 +3703,9 @@ ScriptEditorPlugin::ScriptEditorPlugin(EditorNode *p_node) {
script_editor->hide();
- EDITOR_DEF("text_editor/files/auto_reload_scripts_on_external_change", true);
- ScriptServer::set_reload_scripts_on_save(EDITOR_DEF("text_editor/files/auto_reload_and_parse_scripts_on_save", true));
- EDITOR_DEF("text_editor/files/open_dominant_script_on_scene_change", true);
+ EDITOR_DEF("text_editor/behavior/files/auto_reload_scripts_on_external_change", true);
+ ScriptServer::set_reload_scripts_on_save(EDITOR_DEF("text_editor/behavior/files/auto_reload_and_parse_scripts_on_save", true));
+ EDITOR_DEF("text_editor/behavior/files/open_dominant_script_on_scene_change", true);
EDITOR_DEF("text_editor/external/use_external_editor", false);
EDITOR_DEF("text_editor/external/exec_path", "");
EDITOR_DEF("text_editor/script_list/script_temperature_enabled", true);
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index 1d7592d2c3..4491c13b4c 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -166,8 +166,8 @@ void ScriptTextEditor::enable_editor() {
void ScriptTextEditor::_load_theme_settings() {
CodeEdit *text_edit = code_editor->get_text_editor();
- Color updated_marked_line_color = EDITOR_GET("text_editor/highlighting/mark_color");
- Color updated_safe_line_number_color = EDITOR_GET("text_editor/highlighting/safe_line_number_color");
+ Color updated_marked_line_color = EDITOR_GET("text_editor/theme/highlighting/mark_color");
+ Color updated_safe_line_number_color = EDITOR_GET("text_editor/theme/highlighting/safe_line_number_color");
bool safe_line_number_color_updated = updated_safe_line_number_color != safe_line_number_color;
bool marked_line_color_updated = updated_marked_line_color != marked_line_color;
@@ -294,7 +294,7 @@ bool ScriptTextEditor::show_members_overview() {
}
void ScriptTextEditor::update_settings() {
- code_editor->get_text_editor()->set_gutter_draw(connection_gutter, EditorSettings::get_singleton()->get("text_editor/appearance/show_info_gutter"));
+ code_editor->get_text_editor()->set_gutter_draw(connection_gutter, EditorSettings::get_singleton()->get("text_editor/appearance/gutters/show_info_gutter"));
code_editor->update_editor_settings();
}
@@ -506,7 +506,7 @@ void ScriptTextEditor::_validate_script() {
}
errors_panel->pop(); // Table
- bool highlight_safe = EDITOR_DEF("text_editor/highlighting/highlight_type_safe_lines", true);
+ bool highlight_safe = EDITOR_DEF("text_editor/appearance/gutters/highlight_type_safe_lines", true);
bool last_is_safe = false;
for (int i = 0; i < te->get_line_count(); i++) {
if (errors.is_empty()) {
@@ -1527,7 +1527,7 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
int row = pos.y;
int col = pos.x;
- tx->set_move_caret_on_right_click_enabled(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret"));
+ tx->set_move_caret_on_right_click_enabled(EditorSettings::get_singleton()->get("text_editor/behavior/navigation/move_caret_on_right_click"));
if (tx->is_move_caret_on_right_click_enabled()) {
if (tx->has_selection()) {
int from_line = tx->get_selection_from_line();
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 29436e32b2..22ca5592bd 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -96,7 +96,7 @@ void ShaderTextEditor::set_warnings_panel(RichTextLabel *p_warnings_panel) {
void ShaderTextEditor::_load_theme_settings() {
CodeEdit *text_editor = get_text_editor();
- Color updated_marked_line_color = EDITOR_GET("text_editor/highlighting/mark_color");
+ Color updated_marked_line_color = EDITOR_GET("text_editor/theme/highlighting/mark_color");
if (updated_marked_line_color != marked_line_color) {
for (int i = 0; i < text_editor->get_line_count(); i++) {
if (text_editor->get_line_background_color(i) == marked_line_color) {
@@ -106,17 +106,17 @@ void ShaderTextEditor::_load_theme_settings() {
marked_line_color = updated_marked_line_color;
}
- syntax_highlighter->set_number_color(EDITOR_GET("text_editor/highlighting/number_color"));
- syntax_highlighter->set_symbol_color(EDITOR_GET("text_editor/highlighting/symbol_color"));
- syntax_highlighter->set_function_color(EDITOR_GET("text_editor/highlighting/function_color"));
- syntax_highlighter->set_member_variable_color(EDITOR_GET("text_editor/highlighting/member_variable_color"));
+ syntax_highlighter->set_number_color(EDITOR_GET("text_editor/theme/highlighting/number_color"));
+ syntax_highlighter->set_symbol_color(EDITOR_GET("text_editor/theme/highlighting/symbol_color"));
+ syntax_highlighter->set_function_color(EDITOR_GET("text_editor/theme/highlighting/function_color"));
+ syntax_highlighter->set_member_variable_color(EDITOR_GET("text_editor/theme/highlighting/member_variable_color"));
syntax_highlighter->clear_keyword_colors();
List<String> keywords;
ShaderLanguage::get_keyword_list(&keywords);
- const Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color");
- const Color control_flow_keyword_color = EDITOR_GET("text_editor/highlighting/control_flow_keyword_color");
+ const Color keyword_color = EDITOR_GET("text_editor/theme/highlighting/keyword_color");
+ const Color control_flow_keyword_color = EDITOR_GET("text_editor/theme/highlighting/control_flow_keyword_color");
for (const String &E : keywords) {
if (ShaderLanguage::is_control_flow_keyword(E)) {
@@ -142,14 +142,14 @@ void ShaderTextEditor::_load_theme_settings() {
}
}
- const Color member_variable_color = EDITOR_GET("text_editor/highlighting/member_variable_color");
+ const Color member_variable_color = EDITOR_GET("text_editor/theme/highlighting/member_variable_color");
for (const String &E : built_ins) {
syntax_highlighter->add_keyword_color(E, member_variable_color);
}
// Colorize comments.
- const Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color");
+ const Color comment_color = EDITOR_GET("text_editor/theme/highlighting/comment_color");
syntax_highlighter->clear_color_regions();
syntax_highlighter->add_color_region("/*", "*/", comment_color, false);
syntax_highlighter->add_color_region("//", "", comment_color, true);
@@ -397,7 +397,7 @@ void ShaderEditor::_notification(int p_what) {
void ShaderEditor::_editor_settings_changed() {
shader_editor->update_editor_settings();
- shader_editor->get_text_editor()->add_theme_constant_override("line_spacing", EditorSettings::get_singleton()->get("text_editor/theme/line_spacing"));
+ shader_editor->get_text_editor()->add_theme_constant_override("line_spacing", EditorSettings::get_singleton()->get("text_editor/appearance/whitespace/line_spacing"));
shader_editor->get_text_editor()->set_draw_breakpoints_gutter(false);
shader_editor->get_text_editor()->set_draw_executing_lines_gutter(false);
}
@@ -483,7 +483,7 @@ void ShaderEditor::_check_for_external_edit() {
return;
}
- bool use_autoreload = bool(EDITOR_DEF("text_editor/files/auto_reload_scripts_on_external_change", false));
+ bool use_autoreload = bool(EDITOR_DEF("text_editor/behavior/files/auto_reload_scripts_on_external_change", false));
if (shader->get_last_modified_time() != FileAccess::get_modified_time(shader->get_path())) {
if (use_autoreload) {
_reload_shader_from_disk();
@@ -555,7 +555,7 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
Point2i pos = tx->get_line_column_at_pos(mb->get_global_position() - tx->get_global_position());
int row = pos.y;
int col = pos.x;
- tx->set_move_caret_on_right_click_enabled(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret"));
+ tx->set_move_caret_on_right_click_enabled(EditorSettings::get_singleton()->get("text_editor/behavior/navigation/move_caret_on_right_click"));
if (tx->is_move_caret_on_right_click_enabled()) {
if (tx->has_selection()) {
diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp
index cfccf90499..481eb84081 100644
--- a/editor/plugins/text_editor.cpp
+++ b/editor/plugins/text_editor.cpp
@@ -433,7 +433,7 @@ void TextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
int row = pos.y;
int col = pos.x;
- tx->set_move_caret_on_right_click_enabled(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret"));
+ tx->set_move_caret_on_right_click_enabled(EditorSettings::get_singleton()->get("text_editor/behavior/navigation/move_caret_on_right_click"));
bool can_fold = tx->can_fold_line(row);
bool is_folded = tx->is_line_folded(row);
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 1fbf5eb0e6..2dd8270ee3 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -859,15 +859,15 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
node->add_child(expression_box);
register_expression_edit(p_id, expression_box);
- Color background_color = EDITOR_GET("text_editor/highlighting/background_color");
- Color text_color = EDITOR_GET("text_editor/highlighting/text_color");
- Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color");
- Color control_flow_keyword_color = EDITOR_GET("text_editor/highlighting/control_flow_keyword_color");
- Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color");
- Color symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color");
- Color function_color = EDITOR_GET("text_editor/highlighting/function_color");
- Color number_color = EDITOR_GET("text_editor/highlighting/number_color");
- Color members_color = EDITOR_GET("text_editor/highlighting/member_variable_color");
+ Color background_color = EDITOR_GET("text_editor/theme/highlighting/background_color");
+ Color text_color = EDITOR_GET("text_editor/theme/highlighting/text_color");
+ Color keyword_color = EDITOR_GET("text_editor/theme/highlighting/keyword_color");
+ Color control_flow_keyword_color = EDITOR_GET("text_editor/theme/highlighting/control_flow_keyword_color");
+ Color comment_color = EDITOR_GET("text_editor/theme/highlighting/comment_color");
+ Color symbol_color = EDITOR_GET("text_editor/theme/highlighting/symbol_color");
+ Color function_color = EDITOR_GET("text_editor/theme/highlighting/function_color");
+ Color number_color = EDITOR_GET("text_editor/theme/highlighting/number_color");
+ Color members_color = EDITOR_GET("text_editor/theme/highlighting/member_variable_color");
expression_box->set_syntax_highlighter(expression_syntax_highlighter);
expression_box->add_theme_color_override("background_color", background_color);
@@ -3112,15 +3112,15 @@ void VisualShaderEditor::_notification(int p_what) {
preview_shader->set_icon(Control::get_theme_icon(SNAME("Shader"), SNAME("EditorIcons")));
{
- Color background_color = EDITOR_GET("text_editor/highlighting/background_color");
- Color text_color = EDITOR_GET("text_editor/highlighting/text_color");
+ Color background_color = EDITOR_GET("text_editor/theme/highlighting/background_color");
+ Color text_color = EDITOR_GET("text_editor/theme/highlighting/text_color");
Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color");
- Color control_flow_keyword_color = EDITOR_GET("text_editor/highlighting/control_flow_keyword_color");
- Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color");
- Color symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color");
- Color function_color = EDITOR_GET("text_editor/highlighting/function_color");
- Color number_color = EDITOR_GET("text_editor/highlighting/number_color");
- Color members_color = EDITOR_GET("text_editor/highlighting/member_variable_color");
+ Color control_flow_keyword_color = EDITOR_GET("text_editor/theme/highlighting/control_flow_keyword_color");
+ Color comment_color = EDITOR_GET("text_editor/theme/highlighting/comment_color");
+ Color symbol_color = EDITOR_GET("text_editor/theme/highlighting/symbol_color");
+ Color function_color = EDITOR_GET("text_editor/theme/highlighting/function_color");
+ Color number_color = EDITOR_GET("text_editor/theme/highlighting/number_color");
+ Color members_color = EDITOR_GET("text_editor/theme/highlighting/member_variable_color");
preview_text->add_theme_color_override("background_color", background_color);
@@ -3786,7 +3786,7 @@ void VisualShaderEditor::_update_preview() {
preview_text->set_line_background_color(i, Color(0, 0, 0, 0));
}
if (err != OK) {
- Color error_line_color = EDITOR_GET("text_editor/highlighting/mark_color");
+ Color error_line_color = EDITOR_GET("text_editor/theme/highlighting/mark_color");
preview_text->set_line_background_color(sl.get_error_line() - 1, error_line_color);
error_panel->show();
diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp
index 5c77c9f124..ee100ca938 100644
--- a/editor/settings_config_dialog.cpp
+++ b/editor/settings_config_dialog.cpp
@@ -59,7 +59,7 @@ void EditorSettingsDialog::_settings_property_edited(const String &p_name) {
if (full_name == "interface/theme/accent_color" || full_name == "interface/theme/base_color" || full_name == "interface/theme/contrast") {
EditorSettings::get_singleton()->set_manually("interface/theme/preset", "Custom"); // set preset to Custom
- } else if (full_name.begins_with("text_editor/highlighting")) {
+ } else if (full_name.begins_with("text_editor/theme/highlighting")) {
EditorSettings::get_singleton()->set_manually("text_editor/theme/color_theme", "Custom");
}
}
diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp
index ed8b0a4690..3441233811 100644
--- a/modules/gdscript/editor/gdscript_highlighter.cpp
+++ b/modules/gdscript/editor/gdscript_highlighter.cpp
@@ -449,13 +449,13 @@ void GDScriptSyntaxHighlighter::_update_cache() {
color_region_cache.clear();
font_color = text_edit->get_theme_color(SNAME("font_color"));
- symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color");
- function_color = EDITOR_GET("text_editor/highlighting/function_color");
- number_color = EDITOR_GET("text_editor/highlighting/number_color");
- member_color = EDITOR_GET("text_editor/highlighting/member_variable_color");
+ symbol_color = EDITOR_GET("text_editor/theme/highlighting/symbol_color");
+ function_color = EDITOR_GET("text_editor/theme/highlighting/function_color");
+ number_color = EDITOR_GET("text_editor/theme/highlighting/number_color");
+ member_color = EDITOR_GET("text_editor/theme/highlighting/member_variable_color");
/* Engine types. */
- const Color types_color = EDITOR_GET("text_editor/highlighting/engine_type_color");
+ const Color types_color = EDITOR_GET("text_editor/theme/highlighting/engine_type_color");
List<StringName> types;
ClassDB::get_class_list(&types);
for (const StringName &E : types) {
@@ -467,7 +467,7 @@ void GDScriptSyntaxHighlighter::_update_cache() {
}
/* User types. */
- const Color usertype_color = EDITOR_GET("text_editor/highlighting/user_type_color");
+ const Color usertype_color = EDITOR_GET("text_editor/theme/highlighting/user_type_color");
List<StringName> global_classes;
ScriptServer::get_global_class_list(&global_classes);
for (const StringName &E : global_classes) {
@@ -486,7 +486,7 @@ void GDScriptSyntaxHighlighter::_update_cache() {
const GDScriptLanguage *gdscript = GDScriptLanguage::get_singleton();
/* Core types. */
- const Color basetype_color = EDITOR_GET("text_editor/highlighting/base_type_color");
+ const Color basetype_color = EDITOR_GET("text_editor/theme/highlighting/base_type_color");
List<String> core_types;
gdscript->get_core_type_words(&core_types);
for (const String &E : core_types) {
@@ -494,8 +494,8 @@ void GDScriptSyntaxHighlighter::_update_cache() {
}
/* Reserved words. */
- const Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color");
- const Color control_flow_keyword_color = EDITOR_GET("text_editor/highlighting/control_flow_keyword_color");
+ const Color keyword_color = EDITOR_GET("text_editor/theme/highlighting/keyword_color");
+ const Color control_flow_keyword_color = EDITOR_GET("text_editor/theme/highlighting/control_flow_keyword_color");
List<String> keyword_list;
gdscript->get_reserved_words(&keyword_list);
for (const String &E : keyword_list) {
@@ -507,7 +507,7 @@ void GDScriptSyntaxHighlighter::_update_cache() {
}
/* Comments */
- const Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color");
+ const Color comment_color = EDITOR_GET("text_editor/theme/highlighting/comment_color");
List<String> comments;
gdscript->get_comment_delimiters(&comments);
for (const String &comment : comments) {
@@ -517,7 +517,7 @@ void GDScriptSyntaxHighlighter::_update_cache() {
}
/* Strings */
- const Color string_color = EDITOR_GET("text_editor/highlighting/string_color");
+ const Color string_color = EDITOR_GET("text_editor/theme/highlighting/string_color");
List<String> strings;
gdscript->get_string_delimiters(&strings);
for (const String &string : strings) {
@@ -529,7 +529,7 @@ void GDScriptSyntaxHighlighter::_update_cache() {
const Ref<Script> script = _get_edited_resource();
if (script.is_valid()) {
/* Member types. */
- const Color member_variable_color = EDITOR_GET("text_editor/highlighting/member_variable_color");
+ const Color member_variable_color = EDITOR_GET("text_editor/theme/highlighting/member_variable_color");
StringName instance_base = script->get_instance_base_type();
if (instance_base != StringName()) {
List<PropertyInfo> plist;
@@ -566,28 +566,28 @@ void GDScriptSyntaxHighlighter::_update_cache() {
annotation_color = Color(0.8, 0.5, 0.25);
}
- EDITOR_DEF("text_editor/highlighting/gdscript/function_definition_color", function_definition_color);
- EDITOR_DEF("text_editor/highlighting/gdscript/node_path_color", node_path_color);
- EDITOR_DEF("text_editor/highlighting/gdscript/annotation_color", annotation_color);
+ EDITOR_DEF("text_editor/theme/highlighting/gdscript/function_definition_color", function_definition_color);
+ EDITOR_DEF("text_editor/theme/highlighting/gdscript/node_path_color", node_path_color);
+ EDITOR_DEF("text_editor/theme/highlighting/gdscript/annotation_color", annotation_color);
if (text_edit_color_theme == "Default" || godot_2_theme) {
EditorSettings::get_singleton()->set_initial_value(
- "text_editor/highlighting/gdscript/function_definition_color",
+ "text_editor/theme/highlighting/gdscript/function_definition_color",
function_definition_color,
true);
EditorSettings::get_singleton()->set_initial_value(
- "text_editor/highlighting/gdscript/node_path_color",
+ "text_editor/theme/highlighting/gdscript/node_path_color",
node_path_color,
true);
EditorSettings::get_singleton()->set_initial_value(
- "text_editor/highlighting/gdscript/annotation_color",
+ "text_editor/theme/highlighting/gdscript/annotation_color",
annotation_color,
true);
}
- function_definition_color = EDITOR_GET("text_editor/highlighting/gdscript/function_definition_color");
- node_path_color = EDITOR_GET("text_editor/highlighting/gdscript/node_path_color");
- annotation_color = EDITOR_GET("text_editor/highlighting/gdscript/annotation_color");
- type_color = EDITOR_GET("text_editor/highlighting/base_type_color");
+ function_definition_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/function_definition_color");
+ node_path_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/node_path_color");
+ annotation_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/annotation_color");
+ type_color = EDITOR_GET("text_editor/theme/highlighting/base_type_color");
}
void GDScriptSyntaxHighlighter::add_color_region(const String &p_start_key, const String &p_end_key, const Color &p_color, bool p_line_only) {
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index 1c6f23f454..73661855b4 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -2703,10 +2703,10 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
String GDScriptLanguage::_get_indentation() const {
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
- bool use_space_indentation = EDITOR_DEF("text_editor/indent/type", false);
+ bool use_space_indentation = EDITOR_DEF("text_editor/behavior/indent/type", false);
if (use_space_indentation) {
- int indent_size = EDITOR_DEF("text_editor/indent/size", 4);
+ int indent_size = EDITOR_DEF("text_editor/behavior/indent/size", 4);
String space_indent = "";
for (int i = 0; i < indent_size; i++) {
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index a21167ad95..8c3bb1ea57 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -337,7 +337,7 @@ Error GDScriptParser::parse(const String &p_source_code, const String &p_script_
int tab_size = 4;
#ifdef TOOLS_ENABLED
if (EditorSettings::get_singleton()) {
- tab_size = EditorSettings::get_singleton()->get_setting("text_editor/indent/size");
+ tab_size = EditorSettings::get_singleton()->get_setting("text_editor/behavior/indent/size");
}
#endif // TOOLS_ENABLED
diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp
index 3f14156dfa..d4a098811a 100644
--- a/modules/gdscript/gdscript_tokenizer.cpp
+++ b/modules/gdscript/gdscript_tokenizer.cpp
@@ -1440,7 +1440,7 @@ GDScriptTokenizer::Token GDScriptTokenizer::scan() {
GDScriptTokenizer::GDScriptTokenizer() {
#ifdef TOOLS_ENABLED
if (EditorSettings::get_singleton()) {
- tab_size = EditorSettings::get_singleton()->get_setting("text_editor/indent/size");
+ tab_size = EditorSettings::get_singleton()->get_setting("text_editor/behavior/indent/size");
}
#endif // TOOLS_ENABLED
}
diff --git a/modules/gdscript/tests/test_gdscript.cpp b/modules/gdscript/tests/test_gdscript.cpp
index 52e9d92223..e54f055f2b 100644
--- a/modules/gdscript/tests/test_gdscript.cpp
+++ b/modules/gdscript/tests/test_gdscript.cpp
@@ -56,7 +56,7 @@ static void test_tokenizer(const String &p_code, const Vector<String> &p_lines)
int tab_size = 4;
#ifdef TOOLS_ENABLED
if (EditorSettings::get_singleton()) {
- tab_size = EditorSettings::get_singleton()->get_setting("text_editor/indent/size");
+ tab_size = EditorSettings::get_singleton()->get_setting("text_editor/behavior/indent/size");
}
#endif // TOOLS_ENABLED
String tab = String(" ").repeat(tab_size);
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 520262c0eb..1f7f1390ea 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -82,6 +82,12 @@ static bool _create_project_solution_if_needed() {
CSharpLanguage *CSharpLanguage::singleton = nullptr;
+GDNativeInstanceBindingCallbacks CSharpLanguage::_instance_binding_callbacks = {
+ &_instance_binding_create_callback,
+ &_instance_binding_free_callback,
+ &_instance_binding_reference_callback
+};
+
String CSharpLanguage::get_name() const {
return "C#";
}
@@ -542,10 +548,10 @@ String CSharpLanguage::make_function(const String &, const String &, const Packe
String CSharpLanguage::_get_indentation() const {
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
- bool use_space_indentation = EDITOR_DEF("text_editor/indent/type", 0);
+ bool use_space_indentation = EDITOR_DEF("text_editor/behavior/indent/type", 0);
if (use_space_indentation) {
- int indent_size = EDITOR_DEF("text_editor/indent/size", 4);
+ int indent_size = EDITOR_DEF("text_editor/behavior/indent/size", 4);
String space_indent = "";
for (int i = 0; i < indent_size; i++) {
@@ -1444,46 +1450,46 @@ bool CSharpLanguage::setup_csharp_script_binding(CSharpScriptBinding &r_script_b
return true;
}
-void *CSharpLanguage::alloc_instance_binding_data(Object *p_object) {
- MutexLock lock(language_bind_mutex);
+Map<Object *, CSharpScriptBinding>::Element *CSharpLanguage::insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding) {
+ return script_bindings.insert(p_object, p_script_binding);
+}
+
+void *CSharpLanguage::_instance_binding_create_callback(void *, void *p_instance) {
+ CSharpLanguage *csharp_lang = CSharpLanguage::get_singleton();
- Map<Object *, CSharpScriptBinding>::Element *match = script_bindings.find(p_object);
+ MutexLock lock(csharp_lang->language_bind_mutex);
+
+ Map<Object *, CSharpScriptBinding>::Element *match = csharp_lang->script_bindings.find((Object *)p_instance);
if (match) {
return (void *)match;
}
CSharpScriptBinding script_binding;
- if (!setup_csharp_script_binding(script_binding, p_object)) {
- return nullptr;
- }
-
- return (void *)insert_script_binding(p_object, script_binding);
+ return (void *)csharp_lang->insert_script_binding((Object *)p_instance, script_binding);
}
-Map<Object *, CSharpScriptBinding>::Element *CSharpLanguage::insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding) {
- return script_bindings.insert(p_object, p_script_binding);
-}
+void CSharpLanguage::_instance_binding_free_callback(void *, void *, void *p_binding) {
+ CSharpLanguage *csharp_lang = CSharpLanguage::get_singleton();
-void CSharpLanguage::free_instance_binding_data(void *p_data) {
if (GDMono::get_singleton() == nullptr) {
#ifdef DEBUG_ENABLED
- CRASH_COND(!script_bindings.is_empty());
+ CRASH_COND(!csharp_lang->script_bindings.is_empty());
#endif
// Mono runtime finalized, all the gchandle bindings were already released
return;
}
- if (finalizing) {
+ if (csharp_lang->finalizing) {
return; // inside CSharpLanguage::finish(), all the gchandle bindings are released there
}
GD_MONO_ASSERT_THREAD_ATTACHED;
{
- MutexLock lock(language_bind_mutex);
+ MutexLock lock(csharp_lang->language_bind_mutex);
- Map<Object *, CSharpScriptBinding>::Element *data = (Map<Object *, CSharpScriptBinding>::Element *)p_data;
+ Map<Object *, CSharpScriptBinding>::Element *data = (Map<Object *, CSharpScriptBinding>::Element *)p_binding;
CSharpScriptBinding &script_binding = data->value();
@@ -1497,92 +1503,110 @@ void CSharpLanguage::free_instance_binding_data(void *p_data) {
script_binding.gchandle.release();
}
- script_bindings.erase(data);
+ csharp_lang->script_bindings.erase(data);
}
}
-void CSharpLanguage::refcount_incremented_instance_binding(Object *p_object) {
-#if 0
- RefCounted *rc_owner = Object::cast_to<RefCounted>(p_object);
+GDNativeBool CSharpLanguage::_instance_binding_reference_callback(void *p_token, void *p_binding, GDNativeBool p_reference) {
+ CRASH_COND(!p_binding);
+
+ CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)p_binding)->get();
+
+ RefCounted *rc_owner = Object::cast_to<RefCounted>(script_binding.owner);
#ifdef DEBUG_ENABLED
CRASH_COND(!rc_owner);
- CRASH_COND(!p_object->has_script_instance_binding(get_language_index()));
#endif
- void *data = p_object->get_script_instance_binding(get_language_index());
- CRASH_COND(!data);
-
- CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
MonoGCHandleData &gchandle = script_binding.gchandle;
+ int refcount = rc_owner->reference_get_count();
+
if (!script_binding.inited) {
- return;
+ return refcount == 0;
}
- if (rc_owner->reference_get_count() > 1 && gchandle.is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
- GD_MONO_SCOPE_THREAD_ATTACH;
+ if (p_reference) {
+ // Refcount incremented
+ if (refcount > 1 && gchandle.is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
+ GD_MONO_SCOPE_THREAD_ATTACH;
- // The reference count was increased after the managed side was the only one referencing our owner.
- // This means the owner is being referenced again by the unmanaged side,
- // so the owner must hold the managed side alive again to avoid it from being GCed.
+ // The reference count was increased after the managed side was the only one referencing our owner.
+ // This means the owner is being referenced again by the unmanaged side,
+ // so the owner must hold the managed side alive again to avoid it from being GCed.
+
+ MonoObject *target = gchandle.get_target();
+ if (!target) {
+ return false; // Called after the managed side was collected, so nothing to do here
+ }
- MonoObject *target = gchandle.get_target();
- if (!target) {
- return; // Called after the managed side was collected, so nothing to do here
+ // Release the current weak handle and replace it with a strong handle.
+ MonoGCHandleData strong_gchandle = MonoGCHandleData::new_strong_handle(target);
+ gchandle.release();
+ gchandle = strong_gchandle;
}
- // Release the current weak handle and replace it with a strong handle.
- MonoGCHandleData strong_gchandle = MonoGCHandleData::new_strong_handle(target);
- gchandle.release();
- gchandle = strong_gchandle;
- }
-#endif
-}
+ return false;
+ } else {
+ // Refcount decremented
+ if (refcount == 1 && !gchandle.is_released() && !gchandle.is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
+ GD_MONO_SCOPE_THREAD_ATTACH;
-bool CSharpLanguage::refcount_decremented_instance_binding(Object *p_object) {
-#if 0
- RefCounted *rc_owner = Object::cast_to<RefCounted>(p_object);
+ // If owner owner is no longer referenced by the unmanaged side,
+ // the managed instance takes responsibility of deleting the owner when GCed.
-#ifdef DEBUG_ENABLED
- CRASH_COND(!rc_owner);
- CRASH_COND(!p_object->has_script_instance_binding(get_language_index()));
-#endif
+ MonoObject *target = gchandle.get_target();
+ if (!target) {
+ return refcount == 0; // Called after the managed side was collected, so nothing to do here
+ }
- void *data = p_object->get_script_instance_binding(get_language_index());
- CRASH_COND(!data);
+ // Release the current strong handle and replace it with a weak handle.
+ MonoGCHandleData weak_gchandle = MonoGCHandleData::new_weak_handle(target);
+ gchandle.release();
+ gchandle = weak_gchandle;
- CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
- MonoGCHandleData &gchandle = script_binding.gchandle;
-
- int refcount = rc_owner->reference_get_count();
+ return false;
+ }
- if (!script_binding.inited) {
return refcount == 0;
}
+}
- if (refcount == 1 && !gchandle.is_released() && !gchandle.is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
- GD_MONO_SCOPE_THREAD_ATTACH;
+void *CSharpLanguage::get_instance_binding(Object *p_object) {
+ void *binding = p_object->get_instance_binding(get_singleton(), &_instance_binding_callbacks);
- // If owner owner is no longer referenced by the unmanaged side,
- // the managed instance takes responsibility of deleting the owner when GCed.
+ // Initially this was in `_instance_binding_create_callback`. However, after the new instance
+ // binding re-write it was resulting in a deadlock in `_instance_binding_reference`, as
+ // `setup_csharp_script_binding` may call `reference()`. It was moved here outside to fix that.
- MonoObject *target = gchandle.get_target();
- if (!target) {
- return refcount == 0; // Called after the managed side was collected, so nothing to do here
- }
+ if (binding) {
+ CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)binding)->value();
- // Release the current strong handle and replace it with a weak handle.
- MonoGCHandleData weak_gchandle = MonoGCHandleData::new_weak_handle(target);
- gchandle.release();
- gchandle = weak_gchandle;
+ if (!script_binding.inited) {
+ MutexLock lock(CSharpLanguage::get_singleton()->get_language_bind_mutex());
- return false;
+ if (!script_binding.inited) { // Another thread may have set it up
+ CSharpLanguage::get_singleton()->setup_csharp_script_binding(script_binding, p_object);
+ }
+ }
}
- return refcount == 0;
+ return binding;
+}
+
+void *CSharpLanguage::get_existing_instance_binding(Object *p_object) {
+#ifdef DEBUG_ENABLED
+ CRASH_COND(p_object->has_instance_binding(p_object));
#endif
- return false;
+ return p_object->get_instance_binding(get_singleton(), &_instance_binding_callbacks);
+}
+
+void CSharpLanguage::set_instance_binding(Object *p_object, void *p_binding) {
+ p_object->set_instance_binding(get_singleton(), p_binding, &_instance_binding_callbacks);
+}
+
+bool CSharpLanguage::has_instance_binding(Object *p_object) {
+ return p_object->has_instance_binding(get_singleton());
}
CSharpInstance *CSharpInstance::create_for_managed_type(Object *p_owner, CSharpScript *p_script, const MonoGCHandleData &p_gchandle) {
@@ -2260,29 +2284,16 @@ CSharpInstance::~CSharpInstance() {
// Otherwise, the unsafe reference debug checks will incorrectly detect a bug.
bool die = _unreference_owner_unsafe();
CRASH_COND(die); // `owner_keep_alive` holds a reference, so it can't die
-#if 0
- void *data = owner->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());
-
+ void *data = CSharpLanguage::get_instance_binding(owner);
CRASH_COND(data == nullptr);
-
CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
-
- if (!script_binding.inited) {
- MutexLock lock(CSharpLanguage::get_singleton()->get_language_bind_mutex());
-
- if (!script_binding.inited) { // Other thread may have set it up
- // Already had a binding that needs to be setup
- CSharpLanguage::get_singleton()->setup_csharp_script_binding(script_binding, owner);
- CRASH_COND(!script_binding.inited);
- }
- }
+ CRASH_COND(!script_binding.inited);
#ifdef DEBUG_ENABLED
// The "instance binding" holds a reference so the refcount should be at least 2 before `scope_keep_owner_alive` goes out of scope
CRASH_COND(rc_owner->reference_get_count() <= 1);
#endif
-#endif
}
if (script.is_valid() && owner) {
@@ -3100,10 +3111,10 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg
// Hold it alive. Important if we have to dispose a script instance binding before creating the CSharpInstance.
ref = Ref<RefCounted>(static_cast<RefCounted *>(p_owner));
}
-#if 0
+
// If the object had a script instance binding, dispose it before adding the CSharpInstance
- if (p_owner->has_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index())) {
- void *data = p_owner->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());
+ if (CSharpLanguage::has_instance_binding(p_owner)) {
+ void *data = CSharpLanguage::get_existing_instance_binding(p_owner);
CRASH_COND(data == nullptr);
CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
@@ -3122,7 +3133,7 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg
script_binding.inited = false;
}
}
-#endif
+
CSharpInstance *instance = memnew(CSharpInstance(Ref<CSharpScript>(this)));
instance->base_ref_counted = p_is_ref_counted;
instance->owner = p_owner;
@@ -3192,7 +3203,7 @@ Variant CSharpScript::_new(const Variant **p_args, int p_argcount, Callable::Cal
CSharpInstance *instance = _create_instance(p_args, p_argcount, owner, r != nullptr, r_error);
if (!instance) {
if (ref.is_null()) {
- memdelete(owner); //no owner, sorry
+ memdelete(owner); // no owner, sorry
}
return Variant();
}
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index da6b60aee2..4552f376d0 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -401,7 +401,18 @@ class CSharpLanguage : public ScriptLanguage {
static void _editor_init_callback();
#endif
+ static void *_instance_binding_create_callback(void *p_token, void *p_instance);
+ static void _instance_binding_free_callback(void *p_token, void *p_instance, void *p_binding);
+ static GDNativeBool _instance_binding_reference_callback(void *p_token, void *p_binding, GDNativeBool p_reference);
+
+ static GDNativeInstanceBindingCallbacks _instance_binding_callbacks;
+
public:
+ static void *get_instance_binding(Object *p_object);
+ static void *get_existing_instance_binding(Object *p_object);
+ static void set_instance_binding(Object *p_object, void *p_binding);
+ static bool has_instance_binding(Object *p_object);
+
StringNameCache string_names;
const Mutex &get_language_bind_mutex() { return language_bind_mutex; }
@@ -507,12 +518,6 @@ public:
void thread_enter() override;
void thread_exit() override;
- // Don't use these. I'm watching you
- void *alloc_instance_binding_data(Object *p_object) override;
- void free_instance_binding_data(void *p_data) override;
- void refcount_incremented_instance_binding(Object *p_object) override;
- bool refcount_decremented_instance_binding(Object *p_object) override;
-
Map<Object *, CSharpScriptBinding>::Element *insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding);
bool setup_csharp_script_binding(CSharpScriptBinding &r_script_binding, Object *p_object);
diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp
index a99dff8432..6c5503a3bd 100644
--- a/modules/mono/glue/base_object_glue.cpp
+++ b/modules/mono/glue/base_object_glue.cpp
@@ -64,8 +64,8 @@ void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr) {
return;
}
}
-#if 0
- void *data = p_ptr->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());
+
+ void *data = CSharpLanguage::get_existing_instance_binding(p_ptr);
if (data) {
CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
@@ -76,7 +76,6 @@ void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr) {
}
}
}
-#endif
}
void godot_icall_RefCounted_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolean p_is_finalizer) {
@@ -85,7 +84,7 @@ void godot_icall_RefCounted_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoole
// This is only called with RefCounted derived classes
CRASH_COND(!Object::cast_to<RefCounted>(p_ptr));
#endif
-#if 0
+
RefCounted *rc = static_cast<RefCounted *>(p_ptr);
if (rc->get_script_instance()) {
@@ -113,7 +112,7 @@ void godot_icall_RefCounted_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoole
if (rc->unreference()) {
memdelete(rc);
} else {
- void *data = rc->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());
+ void *data = CSharpLanguage::get_existing_instance_binding(rc);
if (data) {
CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
@@ -125,7 +124,6 @@ void godot_icall_RefCounted_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoole
}
}
}
-#endif
}
void godot_icall_Object_ConnectEventSignals(Object *p_ptr) {
diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp
index d6545d50ec..60047545c4 100644
--- a/modules/mono/mono_gd/gd_mono_internals.cpp
+++ b/modules/mono/mono_gd/gd_mono_internals.cpp
@@ -45,7 +45,7 @@
namespace GDMonoInternals {
void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
// This method should not fail
-#if 0
+
CRASH_COND(!unmanaged);
// All mono objects created from the managed world (e.g.: 'new Player()')
@@ -89,12 +89,12 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
}
// The object was just created, no script instance binding should have been attached
- CRASH_COND(unmanaged->has_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index()));
+ CRASH_COND(CSharpLanguage::has_instance_binding(unmanaged));
void *data = (void *)CSharpLanguage::get_singleton()->insert_script_binding(unmanaged, script_binding);
// Should be thread safe because the object was just created and nothing else should be referencing it
- unmanaged->set_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index(), data);
+ CSharpLanguage::set_instance_binding(unmanaged, data);
return;
}
@@ -108,7 +108,6 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
CSharpInstance *csharp_instance = CSharpInstance::create_for_managed_type(unmanaged, script.ptr(), gchandle);
unmanaged->set_script_and_instance(script, csharp_instance);
-#endif
}
void unhandled_exception(MonoException *p_exc) {
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index 080398c997..13939bd014 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -54,7 +54,6 @@
namespace GDMonoUtils {
MonoObject *unmanaged_get_managed(Object *unmanaged) {
-#if 0
if (!unmanaged) {
return nullptr;
}
@@ -69,22 +68,10 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) {
// If the owner does not have a CSharpInstance...
- void *data = unmanaged->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());
-
+ void *data = CSharpLanguage::get_instance_binding(unmanaged);
ERR_FAIL_NULL_V(data, nullptr);
-
CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->value();
-
- if (!script_binding.inited) {
- MutexLock lock(CSharpLanguage::get_singleton()->get_language_bind_mutex());
-
- if (!script_binding.inited) { // Other thread may have set it up
- // Already had a binding that needs to be setup
- CSharpLanguage::get_singleton()->setup_csharp_script_binding(script_binding, unmanaged);
-
- ERR_FAIL_COND_V(!script_binding.inited, nullptr);
- }
- }
+ ERR_FAIL_COND_V(!script_binding.inited, nullptr);
MonoGCHandleData &gchandle = script_binding.gchandle;
@@ -121,8 +108,6 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) {
}
return mono_object;
-#endif
- return nullptr;
}
void set_main_thread(MonoThread *p_thread) {
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/joypad_osx.cpp b/platform/osx/joypad_osx.cpp
index d778271350..e67d2b0e91 100644
--- a/platform/osx/joypad_osx.cpp
+++ b/platform/osx/joypad_osx.cpp
@@ -143,6 +143,8 @@ void joypad::add_hid_element(IOHIDElementRef p_element) {
switch (usage) {
case kHIDUsage_Sim_Rudder:
case kHIDUsage_Sim_Throttle:
+ case kHIDUsage_Sim_Accelerator:
+ case kHIDUsage_Sim_Brake:
if (!has_element(cookie, &axis_elements)) {
list = &axis_elements;
}
@@ -332,6 +334,13 @@ bool JoypadOSX::configure_joypad(IOHIDDeviceRef p_device_ref, joypad *p_joy) {
p_joy->add_hid_elements(array);
CFRelease(array);
}
+ // Xbox controller hat values start at 1 rather than 0.
+ p_joy->offset_hat = vendor == 0x45e &&
+ (product_id == 0x0b05 ||
+ product_id == 0x02e0 ||
+ product_id == 0x02fd ||
+ product_id == 0x0b13);
+
return true;
}
@@ -388,13 +397,16 @@ bool joypad::check_ff_features() {
return false;
}
-static int process_hat_value(int p_min, int p_max, int p_value) {
+static int process_hat_value(int p_min, int p_max, int p_value, bool p_offset_hat) {
int range = (p_max - p_min + 1);
int value = p_value - p_min;
int hat_value = HatMask::HAT_MASK_CENTER;
if (range == 4) {
value *= 2;
}
+ if (p_offset_hat) {
+ value -= 1;
+ }
switch (value) {
case 0:
@@ -468,7 +480,7 @@ void JoypadOSX::process_joypads() {
for (int j = 0; j < joy.hat_elements.size(); j++) {
rec_element &elem = joy.hat_elements.write[j];
int value = joy.get_hid_element_state(&elem);
- int hat_value = process_hat_value(elem.min, elem.max, value);
+ int hat_value = process_hat_value(elem.min, elem.max, value, joy.offset_hat);
input->joy_hat(joy.id, (HatMask)hat_value);
}
diff --git a/platform/osx/joypad_osx.h b/platform/osx/joypad_osx.h
index bf7e8949df..c060c3d523 100644
--- a/platform/osx/joypad_osx.h
+++ b/platform/osx/joypad_osx.h
@@ -64,6 +64,7 @@ struct joypad {
Vector<rec_element> hat_elements;
int id = 0;
+ bool offset_hat = false;
io_service_t ffservice = 0; /* Interface for force feedback, 0 = no ff */
FFCONSTANTFORCE ff_constant_force;
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/line_edit.cpp b/scene/gui/line_edit.cpp
index 68e9171c15..2b3be1d5c2 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -577,8 +577,8 @@ void LineEdit::_notification(int p_what) {
#ifdef TOOLS_ENABLED
case NOTIFICATION_ENTER_TREE: {
if (Engine::get_singleton()->is_editor_hint() && !get_tree()->is_node_being_edited(this)) {
- set_caret_blink_enabled(EDITOR_DEF("text_editor/cursor/caret_blink", false));
- set_caret_blink_speed(EDITOR_DEF("text_editor/cursor/caret_blink_speed", 0.65));
+ set_caret_blink_enabled(EDITOR_DEF("text_editor/appearance/caret/caret_blink", false));
+ set_caret_blink_speed(EDITOR_DEF("text_editor/appearance/caret/caret_blink_speed", 0.65));
if (!EditorSettings::get_singleton()->is_connected("settings_changed", callable_mp(this, &LineEdit::_editor_settings_changed))) {
EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &LineEdit::_editor_settings_changed));
@@ -1824,8 +1824,8 @@ PopupMenu *LineEdit::get_menu() const {
void LineEdit::_editor_settings_changed() {
#ifdef TOOLS_ENABLED
- set_caret_blink_enabled(EDITOR_DEF("text_editor/cursor/caret_blink", false));
- set_caret_blink_speed(EDITOR_DEF("text_editor/cursor/caret_blink_speed", 0.65));
+ set_caret_blink_enabled(EDITOR_DEF("text_editor/appearance/caret/caret_blink", false));
+ set_caret_blink_speed(EDITOR_DEF("text_editor/appearance/caret/caret_blink_speed", 0.65));
#endif
}
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/physics_3d/body_3d_sw.cpp b/servers/physics_3d/body_3d_sw.cpp
index ea6064cb4c..0c4079332d 100644
--- a/servers/physics_3d/body_3d_sw.cpp
+++ b/servers/physics_3d/body_3d_sw.cpp
@@ -578,7 +578,7 @@ void Body3DSW::integrate_velocities(real_t p_step) {
real_t ang_vel = total_angular_velocity.length();
Transform3D transform = get_transform();
- if (ang_vel != 0.0) {
+ if (!Math::is_zero_approx(ang_vel)) {
Vector3 ang_vel_axis = total_angular_velocity / ang_vel;
Basis rot(ang_vel_axis, ang_vel * p_step);
Basis identity3(1, 0, 0, 0, 1, 0, 0, 0, 1);
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index ddd2a26d71..96b3cdadd4 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -665,6 +665,23 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
_pre_opaque_render(p_render_data, false, false, RID(), RID());
+ uint32_t spec_constant_base_flags = 0;
+
+ {
+ //figure out spec constants
+
+ if (p_render_data->directional_light_count > 0) {
+ if (p_render_data->directional_light_soft_shadows) {
+ spec_constant_base_flags |= 1 << SPEC_CONSTANT_USING_DIRECTIONAL_SOFT_SHADOWS;
+ }
+ } else {
+ spec_constant_base_flags |= 1 << SPEC_CONSTANT_DISABLE_DIRECTIONAL_LIGHTS;
+ }
+
+ if (!is_environment(p_render_data->environment) || environment_is_fog_enabled(p_render_data->environment)) {
+ spec_constant_base_flags |= 1 << SPEC_CONSTANT_DISABLE_FOG;
+ }
+ }
{
if (render_buffer) {
RD::get_singleton()->draw_command_begin_label("Render 3D Pass");
@@ -707,7 +724,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
}
RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
render_list_params.framebuffer_format = fb_format;
if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) {
// secondary command buffers need more testing at this time
@@ -771,7 +788,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (using_subpass_transparent) {
RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
- RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
render_list_params.framebuffer_format = fb_format;
if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) {
// secondary command buffers need more testing at this time
@@ -808,7 +825,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
// _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
- RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
render_list_params.framebuffer_format = fb_format;
if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) {
// secondary command buffers need more testing at this time
@@ -935,7 +952,7 @@ void RenderForwardMobile::_render_shadow_end(uint32_t p_barrier) {
for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) {
SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i];
- RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
+ RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, shadow_pass.rp_uniform_set, 0, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
_render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector<Color>(), 1.0, 0, shadow_pass.rect);
}
@@ -975,7 +992,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c
RENDER_TIMESTAMP("Render Material");
{
- RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, rp_uniform_set);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, rp_uniform_set, 0);
//regular forward for now
Vector<Color> clear;
clear.push_back(Color(0, 0, 0, 0));
@@ -1016,7 +1033,7 @@ void RenderForwardMobile::_render_uv2(const PagedArray<GeometryInstance *> &p_in
RENDER_TIMESTAMP("Render Material");
{
- RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, rp_uniform_set, true);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, rp_uniform_set, true, 0);
//regular forward for now
Vector<Color> clear;
clear.push_back(Color(0, 0, 0, 0));
@@ -1090,7 +1107,7 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const
{
//regular forward for now
- RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, rp_uniform_set);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, rp_uniform_set, 0);
_render_list_with_threads(&render_list_params, p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ);
}
RD::get_singleton()->draw_command_end_label();
@@ -1733,7 +1750,7 @@ void RenderForwardMobile::_render_list_with_threads(RenderListParameters *p_para
}
}
-void RenderForwardMobile::_fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, const GeometryInstanceForwardMobile *p_instance) {
+void RenderForwardMobile::_fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance) {
// first zero out our indices
p_push_constant->omni_lights[0] = 0xFFFF;
@@ -1748,6 +1765,19 @@ void RenderForwardMobile::_fill_push_constant_instance_indices(GeometryInstanceF
p_push_constant->reflection_probes[0] = 0xFFFF;
p_push_constant->reflection_probes[1] = 0xFFFF;
+ if (p_instance->omni_light_count == 0) {
+ spec_constants |= 1 << SPEC_CONSTANT_DISABLE_OMNI_LIGHTS;
+ }
+ if (p_instance->spot_light_count == 0) {
+ spec_constants |= 1 << SPEC_CONSTANT_DISABLE_SPOT_LIGHTS;
+ }
+ if (p_instance->reflection_probe_count == 0) {
+ spec_constants |= 1 << SPEC_CONSTANT_DISABLE_REFLECTION_PROBES;
+ }
+ if (p_instance->decals_count == 0) {
+ spec_constants |= 1 << SPEC_CONSTANT_DISABLE_DECALS;
+ }
+
for (uint32_t i = 0; i < MAX_RDL_CULL; i++) {
uint32_t ofs = i < 4 ? 0 : 1;
uint32_t shift = (i & 0x3) << 3;
@@ -1795,6 +1825,8 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
const RenderElementInfo &element_info = p_params->element_info[i];
const GeometryInstanceForwardMobile *inst = surf->owner;
+ uint32_t base_spec_constants = p_params->spec_constant_base_flags;
+
// GeometryInstanceForwardMobile::PushConstant push_constant = inst->push_constant;
GeometryInstanceForwardMobile::PushConstant push_constant;
@@ -1830,7 +1862,13 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
mesh_surface = surf->surface_shadow;
} else {
- _fill_push_constant_instance_indices(&push_constant, inst);
+ if (inst->use_projector) {
+ base_spec_constants |= 1 << SPEC_CONSTANT_USING_PROJECTOR;
+ }
+ if (inst->use_soft_shadow) {
+ base_spec_constants |= 1 << SPEC_CONSTANT_USING_SOFT_SHADOWS;
+ }
+ _fill_push_constant_instance_indices(&push_constant, base_spec_constants, inst);
#ifdef DEBUG_ENABLED
if (unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_LIGHTING)) {
@@ -1922,7 +1960,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
prev_index_array_rd = index_array_rd;
}
- RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format, p_params->force_wireframe, p_params->subpass);
+ RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format, p_params->force_wireframe, p_params->subpass, base_spec_constants);
if (pipeline_rd != prev_pipeline_rd) {
// checking with prev shader does not make so much sense, as
@@ -2181,6 +2219,11 @@ void RenderForwardMobile::geometry_instance_pair_voxel_gi_instances(GeometryInst
}
void RenderForwardMobile::geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) {
+ GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+
+ ginstance->use_projector = p_projector;
+ ginstance->use_soft_shadow = p_softshadow;
}
void RenderForwardMobile::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) {
@@ -2559,12 +2602,12 @@ void RenderForwardMobile::_update_shader_quality_settings() {
spec_constants.push_back(sc);
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
- sc.constant_id = SPEC_CONSTANT_DECAL_FILTER;
+ sc.constant_id = SPEC_CONSTANT_DECAL_USE_MIPMAPS;
sc.bool_value = decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
spec_constants.push_back(sc);
- sc.constant_id = SPEC_CONSTANT_PROJECTOR_FILTER;
+ sc.constant_id = SPEC_CONSTANT_PROJECTOR_USE_MIPMAPS;
sc.bool_value = light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
spec_constants.push_back(sc);
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
index b981592840..764d8e80df 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -65,12 +65,27 @@ protected:
};
enum {
- SPEC_CONSTANT_SOFT_SHADOW_SAMPLES = 6,
- SPEC_CONSTANT_PENUMBRA_SHADOW_SAMPLES = 7,
- SPEC_CONSTANT_DIRECTIONAL_SOFT_SHADOW_SAMPLES = 8,
- SPEC_CONSTANT_DIRECTIONAL_PENUMBRA_SHADOW_SAMPLES = 9,
- SPEC_CONSTANT_DECAL_FILTER = 10,
- SPEC_CONSTANT_PROJECTOR_FILTER = 11,
+
+ SPEC_CONSTANT_USING_PROJECTOR = 0,
+ SPEC_CONSTANT_USING_SOFT_SHADOWS = 1,
+ SPEC_CONSTANT_USING_DIRECTIONAL_SOFT_SHADOWS = 2,
+
+ SPEC_CONSTANT_SOFT_SHADOW_SAMPLES = 3,
+ SPEC_CONSTANT_PENUMBRA_SHADOW_SAMPLES = 4,
+ SPEC_CONSTANT_DIRECTIONAL_SOFT_SHADOW_SAMPLES = 5,
+ SPEC_CONSTANT_DIRECTIONAL_PENUMBRA_SHADOW_SAMPLES = 6,
+
+ SPEC_CONSTANT_DECAL_USE_MIPMAPS = 7,
+ SPEC_CONSTANT_PROJECTOR_USE_MIPMAPS = 8,
+
+ SPEC_CONSTANT_DISABLE_OMNI_LIGHTS = 9,
+ SPEC_CONSTANT_DISABLE_SPOT_LIGHTS = 10,
+ SPEC_CONSTANT_DISABLE_REFLECTION_PROBES = 11,
+ SPEC_CONSTANT_DISABLE_DIRECTIONAL_LIGHTS = 12,
+
+ SPEC_CONSTANT_DISABLE_DECALS = 13,
+ SPEC_CONSTANT_DISABLE_FOG = 14,
+
};
enum {
@@ -159,6 +174,7 @@ protected:
bool force_wireframe = false;
Vector2 uv_offset;
Plane lod_plane;
+ uint32_t spec_constant_base_flags = 0;
float lod_distance_multiplier = 0.0;
float screen_lod_threshold = 0.0;
RD::FramebufferFormatID framebuffer_format = 0;
@@ -166,7 +182,7 @@ protected:
uint32_t barrier = RD::BARRIER_MASK_ALL;
uint32_t subpass = 0;
- RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
+ RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, uint32_t p_spec_constant_base_flags = 0, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
elements = p_elements;
element_info = p_element_info;
element_count = p_element_count;
@@ -182,6 +198,7 @@ protected:
screen_lod_threshold = p_screen_lod_threshold;
element_offset = p_element_offset;
barrier = p_barrier;
+ spec_constant_base_flags = p_spec_constant_base_flags;
}
};
@@ -526,6 +543,8 @@ protected:
RID transforms_uniform_set;
float depth = 0;
bool mirror = false;
+ bool use_projector = false;
+ bool use_soft_shadow = false;
Transform3D transform;
bool store_transform_cache = true; // if true we copy our transform into our PushConstant, if false we use our transforms UBO and clear our PushConstants transform
bool non_uniform_scale = false;
@@ -584,7 +603,7 @@ protected:
dirty_list_element(this) {}
};
- _FORCE_INLINE_ void _fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, const GeometryInstanceForwardMobile *p_instance);
+ _FORCE_INLINE_ void _fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance);
void _update_shader_quality_settings() override;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
index 2babe92c1c..663100a0b3 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
@@ -373,26 +373,38 @@ void main() {
//use medium precision for floats on mobile.
precision mediump float;
+precision highp int;
/* Specialization Constants */
-/* Specialization Constants (Toggles) */
+#if !defined(MODE_RENDER_DEPTH)
+
+#if !defined(MODE_UNSHADED)
+
+layout(constant_id = 0) const bool sc_use_light_projector = false;
+layout(constant_id = 1) const bool sc_use_light_soft_shadows = false;
+layout(constant_id = 2) const bool sc_use_directional_soft_shadows = false;
-layout(constant_id = 0) const bool sc_use_forward_gi = false;
-layout(constant_id = 1) const bool sc_use_light_projector = false;
-layout(constant_id = 2) const bool sc_use_light_soft_shadows = false;
-layout(constant_id = 3) const bool sc_use_directional_soft_shadows = false;
+layout(constant_id = 3) const uint sc_soft_shadow_samples = 4;
+layout(constant_id = 4) const uint sc_penumbra_shadow_samples = 4;
-/* Specialization Constants (Values) */
+layout(constant_id = 5) const uint sc_directional_soft_shadow_samples = 4;
+layout(constant_id = 6) const uint sc_directional_penumbra_shadow_samples = 4;
-layout(constant_id = 6) const uint sc_soft_shadow_samples = 4;
-layout(constant_id = 7) const uint sc_penumbra_shadow_samples = 4;
+layout(constant_id = 8) const bool sc_projector_use_mipmaps = true;
-layout(constant_id = 8) const uint sc_directional_soft_shadow_samples = 4;
-layout(constant_id = 9) const uint sc_directional_penumbra_shadow_samples = 4;
+layout(constant_id = 9) const bool sc_disable_omni_lights = false;
+layout(constant_id = 10) const bool sc_disable_spot_lights = false;
+layout(constant_id = 11) const bool sc_disable_reflection_probes = false;
+layout(constant_id = 12) const bool sc_disable_directional_lights = false;
-layout(constant_id = 10) const bool sc_decal_use_mipmaps = true;
-layout(constant_id = 11) const bool sc_projector_use_mipmaps = true;
+#endif //!MODE_UNSHADED
+
+layout(constant_id = 7) const bool sc_decal_use_mipmaps = true;
+layout(constant_id = 13) const bool sc_disable_decals = false;
+layout(constant_id = 14) const bool sc_disable_fog = false;
+
+#endif //!MODE_RENDER_DEPTH
/* Include our forward mobile UBOs definitions etc. */
#include "scene_forward_mobile_inc.glsl"
@@ -735,7 +747,7 @@ void main() {
// to maximize VGPR usage
// Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky.
- if (scene_data.fog_enabled) {
+ if (!sc_disable_fog && scene_data.fog_enabled) {
fog = fog_process(vertex);
}
@@ -753,7 +765,7 @@ void main() {
vec3 vertex_ddx = dFdx(vertex);
vec3 vertex_ddy = dFdy(vertex);
- { //Decals
+ if (!sc_disable_decals) { //Decals
// must implement
uint decal_indices = draw_call.decals.x;
@@ -774,25 +786,35 @@ void main() {
continue; //out of decal
}
- //we need ddx/ddy for mipmaps, so simulate them
- vec2 ddx = (decals.data[decal_index].xform * vec4(vertex_ddx, 0.0)).xz;
- vec2 ddy = (decals.data[decal_index].xform * vec4(vertex_ddy, 0.0)).xz;
-
float fade = pow(1.0 - (uv_local.y > 0.0 ? uv_local.y : -uv_local.y), uv_local.y > 0.0 ? decals.data[decal_index].upper_fade : decals.data[decal_index].lower_fade);
if (decals.data[decal_index].normal_fade > 0.0) {
fade *= smoothstep(decals.data[decal_index].normal_fade, 1.0, dot(normal_interp, decals.data[decal_index].normal) * 0.5 + 0.5);
}
+ //we need ddx/ddy for mipmaps, so simulate them
+ vec2 ddx = (decals.data[decal_index].xform * vec4(vertex_ddx, 0.0)).xz;
+ vec2 ddy = (decals.data[decal_index].xform * vec4(vertex_ddy, 0.0)).xz;
+
if (decals.data[decal_index].albedo_rect != vec4(0.0)) {
//has albedo
- vec4 decal_albedo = textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, ddx * decals.data[decal_index].albedo_rect.zw, ddy * decals.data[decal_index].albedo_rect.zw);
+ vec4 decal_albedo;
+ if (sc_decal_use_mipmaps) {
+ decal_albedo = textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, ddx * decals.data[decal_index].albedo_rect.zw, ddy * decals.data[decal_index].albedo_rect.zw);
+ } else {
+ decal_albedo = textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, 0.0);
+ }
decal_albedo *= decals.data[decal_index].modulate;
decal_albedo.a *= fade;
albedo = mix(albedo, decal_albedo.rgb, decal_albedo.a * decals.data[decal_index].albedo_mix);
if (decals.data[decal_index].normal_rect != vec4(0.0)) {
- vec3 decal_normal = textureGrad(sampler2D(decal_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, ddx * decals.data[decal_index].normal_rect.zw, ddy * decals.data[decal_index].normal_rect.zw).xyz;
+ vec3 decal_normal;
+ if (sc_decal_use_mipmaps) {
+ decal_normal = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, ddx * decals.data[decal_index].normal_rect.zw, ddy * decals.data[decal_index].normal_rect.zw).xyz;
+ } else {
+ decal_normal = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, 0.0).xyz;
+ }
decal_normal.xy = decal_normal.xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); //users prefer flipped y normal maps in most authoring software
decal_normal.z = sqrt(max(0.0, 1.0 - dot(decal_normal.xy, decal_normal.xy)));
//convert to view space, use xzy because y is up
@@ -802,7 +824,12 @@ void main() {
}
if (decals.data[decal_index].orm_rect != vec4(0.0)) {
- vec3 decal_orm = textureGrad(sampler2D(decal_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, ddx * decals.data[decal_index].orm_rect.zw, ddy * decals.data[decal_index].orm_rect.zw).xyz;
+ vec3 decal_orm;
+ if (sc_decal_use_mipmaps) {
+ decal_orm = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, ddx * decals.data[decal_index].orm_rect.zw, ddy * decals.data[decal_index].orm_rect.zw).xyz;
+ } else {
+ decal_orm = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, 0.0).xyz;
+ }
ao = mix(ao, decal_orm.r, decal_albedo.a);
roughness = mix(roughness, decal_orm.g, decal_albedo.a);
metallic = mix(metallic, decal_orm.b, decal_albedo.a);
@@ -811,7 +838,11 @@ void main() {
if (decals.data[decal_index].emission_rect != vec4(0.0)) {
//emission is additive, so its independent from albedo
- emission += textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade;
+ if (sc_decal_use_mipmaps) {
+ emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade;
+ } else {
+ emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].emission_energy * fade;
+ }
}
}
} //Decals
@@ -951,7 +982,7 @@ void main() {
// skipping ssao, do we remove ssao totally?
- { //Reflection probes
+ if (!sc_disable_reflection_probes) { //Reflection probes
vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0);
vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0);
@@ -1017,7 +1048,7 @@ void main() {
// LIGHTING
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
- { //directional light
+ if (!sc_disable_directional_lights) { //directional light
// Do shadow and lighting in two passes to reduce register pressure
uint shadow0 = 0;
@@ -1347,7 +1378,7 @@ void main() {
}
} //directional light
- { //omni lights
+ if (!sc_disable_omni_lights) { //omni lights
uint light_indices = draw_call.omni_lights.x;
for (uint i = 0; i < 8; i++) {
uint light_index = light_indices & 0xFF;
@@ -1394,7 +1425,7 @@ void main() {
}
} //omni lights
- { //spot lights
+ if (!sc_disable_spot_lights) { //spot lights
uint light_indices = draw_call.spot_lights.x;
for (uint i = 0; i < 8; i++) {