summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore9
-rw-r--r--SConstruct7
-rw-r--r--core/input/input_map.cpp2
-rw-r--r--core/io/file_access.cpp2
-rw-r--r--core/io/file_access.h2
-rw-r--r--core/io/file_access_compressed.cpp4
-rw-r--r--core/io/file_access_compressed.h2
-rw-r--r--core/io/file_access_encrypted.cpp4
-rw-r--r--core/io/file_access_encrypted.h2
-rw-r--r--core/io/file_access_memory.h2
-rw-r--r--core/io/file_access_network.cpp9
-rw-r--r--core/io/file_access_network.h2
-rw-r--r--core/io/file_access_pack.cpp4
-rw-r--r--core/io/file_access_pack.h2
-rw-r--r--core/io/file_access_zip.cpp4
-rw-r--r--core/io/file_access_zip.h2
-rw-r--r--core/object/script_language_extension.cpp1
-rw-r--r--core/templates/paged_array.h20
-rw-r--r--doc/classes/@GlobalScope.xml2
-rw-r--r--doc/classes/AnimatedTexture.xml5
-rw-r--r--doc/classes/Decal.xml2
-rw-r--r--doc/classes/DisplayServer.xml9
-rw-r--r--doc/classes/FileAccess.xml9
-rw-r--r--doc/classes/NavigationAgent2D.xml2
-rw-r--r--doc/classes/NavigationAgent3D.xml8
-rw-r--r--doc/classes/NavigationLink2D.xml26
-rw-r--r--doc/classes/NavigationLink3D.xml26
-rw-r--r--doc/classes/NavigationServer2D.xml13
-rw-r--r--doc/classes/NavigationServer3D.xml13
-rw-r--r--doc/classes/Node3D.xml2
-rw-r--r--doc/classes/OmniLight3D.xml3
-rw-r--r--doc/classes/PopupMenu.xml16
-rw-r--r--doc/classes/ProjectSettings.xml9
-rw-r--r--doc/classes/ScriptExtension.xml5
-rw-r--r--doc/classes/SpotLight3D.xml5
-rw-r--r--doc/classes/String.xml2
-rw-r--r--doc/classes/StringName.xml2
-rw-r--r--doc/classes/TextureRect.xml3
-rw-r--r--doc/classes/VisibleOnScreenEnabler2D.xml2
-rw-r--r--doc/classes/XRInterface.xml2
-rw-r--r--drivers/alsa/SCsub3
-rw-r--r--drivers/alsa/audio_driver_alsa.cpp5
-rw-r--r--drivers/alsa/audio_driver_alsa.h4
-rw-r--r--drivers/alsamidi/midi_driver_alsamidi.h5
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp7
-rw-r--r--drivers/gles3/shaders/stdlib_inc.glsl6
-rw-r--r--drivers/pulseaudio/SCsub3
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.cpp7
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.h4
-rw-r--r--drivers/unix/file_access_unix.cpp4
-rw-r--r--drivers/unix/file_access_unix.h2
-rw-r--r--drivers/windows/file_access_windows.cpp5
-rw-r--r--drivers/windows/file_access_windows.h2
-rw-r--r--editor/animation_track_editor.cpp12
-rw-r--r--editor/code_editor.cpp5
-rw-r--r--editor/debugger/editor_profiler.cpp2
-rw-r--r--editor/editor_audio_buses.cpp2
-rw-r--r--editor/editor_file_dialog.cpp18
-rw-r--r--editor/editor_inspector.cpp2
-rw-r--r--editor/editor_properties.cpp15
-rw-r--r--editor/editor_themes.cpp40
-rw-r--r--editor/export/editor_export_platform.cpp3
-rw-r--r--editor/import/resource_importer_scene.cpp1
-rw-r--r--editor/import/scene_import_settings.cpp16
-rw-r--r--editor/import/scene_import_settings.h2
-rw-r--r--editor/input_event_configuration_dialog.cpp3
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp1
-rw-r--r--editor/plugins/cast_2d_editor_plugin.cpp2
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/script_editor_plugin.cpp2
-rw-r--r--editor/plugins/theme_editor_plugin.cpp7
-rw-r--r--editor/plugins/tiles/tile_map_editor.cpp31
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.cpp71
-rw-r--r--editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp11
-rw-r--r--editor/project_settings_editor.cpp2
-rw-r--r--main/main.cpp1
-rw-r--r--methods.py4
-rw-r--r--misc/dist/ios_xcode/godot_ios/vulkan/icd.d/MoltenVK_icd.json7
-rw-r--r--modules/basis_universal/SCsub3
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp1
-rw-r--r--modules/gdscript/gdscript_compiler.cpp2
-rw-r--r--modules/gdscript/gdscript_vm.cpp33
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.gd7
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.out6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.gd10
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.out6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/getter_return_type.gd9
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/getter_return_type.out2
-rw-r--r--modules/gridmap/editor/grid_map_editor_plugin.cpp1
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs3
-rw-r--r--modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs4
-rw-r--r--modules/navigation/SCsub2
-rw-r--r--modules/ogg/ogg_packet_sequence.h5
-rw-r--r--modules/text_server_adv/SCsub5
-rw-r--r--modules/vorbis/audio_stream_ogg_vorbis.cpp3
-rw-r--r--modules/vorbis/audio_stream_ogg_vorbis.h3
-rw-r--r--modules/vorbis/resource_importer_ogg_vorbis.cpp5
-rw-r--r--platform/android/export/export_plugin.cpp12
-rw-r--r--platform/android/file_access_android.cpp4
-rw-r--r--platform/android/file_access_android.h2
-rw-r--r--platform/android/file_access_filesystem_jandroid.cpp6
-rw-r--r--platform/android/file_access_filesystem_jandroid.h2
-rw-r--r--platform/ios/SCsub1
-rw-r--r--platform/ios/godot_view.h5
-rw-r--r--platform/ios/godot_view.mm82
-rw-r--r--platform/ios/godot_view_gesture_recognizer.h46
-rw-r--r--platform/ios/godot_view_gesture_recognizer.mm186
-rw-r--r--platform/ios/joypad_ios.mm19
-rw-r--r--platform/linuxbsd/SCsub17
-rw-r--r--platform/linuxbsd/detect.py143
-rw-r--r--platform/linuxbsd/freedesktop_portal_desktop.cpp8
-rw-r--r--platform/linuxbsd/freedesktop_screensaver.cpp8
-rw-r--r--platform/linuxbsd/joypad_linux.cpp6
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp4
-rw-r--r--platform/linuxbsd/os_linuxbsd.h4
-rw-r--r--platform/linuxbsd/tts_linux.cpp10
-rw-r--r--platform/linuxbsd/tts_linux.h4
-rw-r--r--platform/linuxbsd/x11/SCsub20
-rw-r--r--platform/linuxbsd/x11/detect_prime_x11.cpp6
-rw-r--r--platform/linuxbsd/x11/display_server_x11.cpp26
-rw-r--r--platform/linuxbsd/x11/display_server_x11.h26
-rw-r--r--platform/linuxbsd/x11/gl_manager_x11.h15
-rw-r--r--scene/2d/audio_stream_player_2d.cpp2
-rw-r--r--scene/2d/navigation_agent_2d.cpp32
-rw-r--r--scene/2d/navigation_link_2d.cpp38
-rw-r--r--scene/2d/navigation_link_2d.h6
-rw-r--r--scene/2d/touch_screen_button.cpp4
-rw-r--r--scene/3d/audio_stream_player_3d.cpp2
-rw-r--r--scene/3d/navigation_agent_3d.cpp34
-rw-r--r--scene/3d/navigation_agent_3d.h6
-rw-r--r--scene/3d/navigation_link_3d.cpp38
-rw-r--r--scene/3d/navigation_link_3d.h6
-rw-r--r--scene/3d/voxelizer.cpp32
-rw-r--r--scene/audio/audio_stream_player.cpp2
-rw-r--r--scene/gui/aspect_ratio_container.cpp12
-rw-r--r--scene/gui/color_picker.cpp113
-rw-r--r--scene/gui/color_picker.h12
-rw-r--r--scene/gui/file_dialog.cpp9
-rw-r--r--scene/gui/label.cpp259
-rw-r--r--scene/gui/label.h4
-rw-r--r--scene/gui/rich_text_label.cpp6
-rw-r--r--scene/main/canvas_item.cpp6
-rw-r--r--scene/main/viewport.cpp4
-rw-r--r--scene/main/window.cpp28
-rw-r--r--scene/main/window.h2
-rw-r--r--scene/resources/texture.cpp68
-rw-r--r--scene/resources/texture.h23
-rw-r--r--scene/resources/tile_set.cpp48
-rw-r--r--servers/audio/effects/audio_effect_pitch_shift.cpp2
-rw-r--r--servers/navigation_server_2d.cpp6
-rw-r--r--servers/navigation_server_2d.h2
-rw-r--r--servers/navigation_server_3d.cpp37
-rw-r--r--servers/navigation_server_3d.h9
-rw-r--r--servers/navigation_server_3d_dummy.h2
-rw-r--r--servers/physics_3d/godot_shape_3d.cpp2
-rw-r--r--servers/rendering/renderer_rd/effects/ss_effects.cpp32
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl15
-rw-r--r--servers/rendering/shader_language.cpp2
-rw-r--r--servers/rendering_server.cpp4
-rw-r--r--tests/core/templates/test_paged_array.h51
-rw-r--r--thirdparty/basis_universal/encoder/basisu_comp.cpp2
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_transcoder.cpp2
163 files changed, 1397 insertions, 906 deletions
diff --git a/.gitignore b/.gitignore
index e9beb26e7e..17c9a6c95a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -243,9 +243,6 @@ xcuserdata/
x64/
x86/
-# Do not ignore x86 folders anywhere under thirdparty libraries
-!thirdparty/**/x86/
-
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
@@ -255,6 +252,12 @@ bld/
[Ll]og/
[Ll]ogs/
+# Do not ignore arch-specific folders anywhere under thirdparty libraries
+!thirdparty/**/x64/
+!thirdparty/**/x86/
+!thirdparty/**/arm/
+!thirdparty/**/arm64/
+
# Visual Studio 2015/2017 cache/options directory
.vs/
diff --git a/SConstruct b/SConstruct
index 845b9be4a6..2763f3f578 100644
--- a/SConstruct
+++ b/SConstruct
@@ -200,6 +200,7 @@ opts.Add(EnumVariable("warnings", "Level of compilation warnings", "all", ("extr
opts.Add(BoolVariable("werror", "Treat compiler warnings as errors", False))
opts.Add("extra_suffix", "Custom extra suffix added to the base filename of all generated binary files", "")
opts.Add(BoolVariable("vsproj", "Generate a Visual Studio solution", False))
+opts.Add("vsproj_name", "Name of the Visual Studio solution", "godot")
opts.Add(BoolVariable("disable_3d", "Disable 3D nodes for a smaller executable", False))
opts.Add(BoolVariable("disable_advanced_gui", "Disable advanced GUI nodes and behaviors", False))
opts.Add("build_profile", "Path to a file containing a feature build profile", "")
@@ -217,7 +218,7 @@ opts.Add(BoolVariable("builtin_msdfgen", "Use the built-in MSDFgen library", Tru
opts.Add(BoolVariable("builtin_glslang", "Use the built-in glslang library", True))
opts.Add(BoolVariable("builtin_graphite", "Use the built-in Graphite library", True))
opts.Add(BoolVariable("builtin_harfbuzz", "Use the built-in HarfBuzz library", True))
-opts.Add(BoolVariable("builtin_icu", "Use the built-in ICU library", True))
+opts.Add(BoolVariable("builtin_icu4c", "Use the built-in ICU library", True))
opts.Add(BoolVariable("builtin_libogg", "Use the built-in libogg library", True))
opts.Add(BoolVariable("builtin_libpng", "Use the built-in libpng library", True))
opts.Add(BoolVariable("builtin_libtheora", "Use the built-in libtheora library", True))
@@ -228,7 +229,7 @@ opts.Add(BoolVariable("builtin_mbedtls", "Use the built-in mbedTLS library", Tru
opts.Add(BoolVariable("builtin_miniupnpc", "Use the built-in miniupnpc library", True))
opts.Add(BoolVariable("builtin_pcre2", "Use the built-in PCRE2 library", True))
opts.Add(BoolVariable("builtin_pcre2_with_jit", "Use JIT compiler for the built-in PCRE2 library", True))
-opts.Add(BoolVariable("builtin_recast", "Use the built-in Recast library", True))
+opts.Add(BoolVariable("builtin_recastnavigation", "Use the built-in Recast navigation library", True))
opts.Add(BoolVariable("builtin_rvo2", "Use the built-in RVO2 library", True))
opts.Add(BoolVariable("builtin_squish", "Use the built-in squish library", True))
opts.Add(BoolVariable("builtin_xatlas", "Use the built-in xatlas library", True))
@@ -923,7 +924,7 @@ if selected_platform in platform_list:
print("Error: The `vsproj` option is only usable on Windows with Visual Studio.")
Exit(255)
env["CPPPATH"] = [Dir(path) for path in env["CPPPATH"]]
- methods.generate_vs_project(env, GetOption("num_jobs"))
+ methods.generate_vs_project(env, GetOption("num_jobs"), env["vsproj_name"])
methods.generate_cpp_hint_file("cpp.hint")
# Check for the existence of headers
diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp
index 5a07d44197..b2e6b57eb6 100644
--- a/core/input/input_map.cpp
+++ b/core/input/input_map.cpp
@@ -344,7 +344,7 @@ static const _BuiltinActionDisplayName _builtin_action_display_names[] = {
{ "ui_text_add_selection_for_next_occurrence", TTRC("Add Selection for Next Occurrence") },
{ "ui_text_clear_carets_and_selection", TTRC("Clear Carets and Selection") },
{ "ui_text_toggle_insert_mode", TTRC("Toggle Insert Mode") },
- { "ui_text_submit", TTRC("Text Submitted") },
+ { "ui_text_submit", TTRC("Submit Text") },
{ "ui_graph_duplicate", TTRC("Duplicate Nodes") },
{ "ui_graph_delete", TTRC("Delete Nodes") },
{ "ui_filedialog_up_one_level", TTRC("Go Up One Level") },
diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp
index cacbcb28a4..0e9084de84 100644
--- a/core/io/file_access.cpp
+++ b/core/io/file_access.cpp
@@ -856,6 +856,8 @@ void FileAccess::_bind_methods() {
ClassDB::bind_method(D_METHOD("store_pascal_string", "string"), &FileAccess::store_pascal_string);
ClassDB::bind_method(D_METHOD("get_pascal_string"), &FileAccess::get_pascal_string);
+ ClassDB::bind_method(D_METHOD("close"), &FileAccess::close);
+
ClassDB::bind_static_method("FileAccess", D_METHOD("file_exists", "path"), &FileAccess::exists);
ClassDB::bind_static_method("FileAccess", D_METHOD("get_modified_time", "file"), &FileAccess::get_modified_time);
diff --git a/core/io/file_access.h b/core/io/file_access.h
index 3e51ba11ed..47770cad87 100644
--- a/core/io/file_access.h
+++ b/core/io/file_access.h
@@ -166,6 +166,8 @@ public:
void store_var(const Variant &p_var, bool p_full_objects = false);
+ virtual void close() = 0;
+
virtual bool file_exists(const String &p_name) = 0; ///< return true if a file exists
virtual Error reopen(const String &p_path, int p_mode_flags); ///< does not change the AccessType
diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp
index c256668af0..da59ae8c59 100644
--- a/core/io/file_access_compressed.cpp
+++ b/core/io/file_access_compressed.cpp
@@ -385,6 +385,10 @@ Error FileAccessCompressed::_set_unix_permissions(const String &p_file, uint32_t
return FAILED;
}
+void FileAccessCompressed::close() {
+ _close();
+}
+
FileAccessCompressed::~FileAccessCompressed() {
_close();
}
diff --git a/core/io/file_access_compressed.h b/core/io/file_access_compressed.h
index 136fcede06..601b74a9c1 100644
--- a/core/io/file_access_compressed.h
+++ b/core/io/file_access_compressed.h
@@ -97,6 +97,8 @@ public:
virtual uint32_t _get_unix_permissions(const String &p_file) override;
virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override;
+ virtual void close() override;
+
FileAccessCompressed() {}
virtual ~FileAccessCompressed();
};
diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp
index 8282f2515c..c39d19d52b 100644
--- a/core/io/file_access_encrypted.cpp
+++ b/core/io/file_access_encrypted.cpp
@@ -294,6 +294,10 @@ Error FileAccessEncrypted::_set_unix_permissions(const String &p_file, uint32_t
return ERR_UNAVAILABLE;
}
+void FileAccessEncrypted::close() {
+ _close();
+}
+
FileAccessEncrypted::~FileAccessEncrypted() {
_close();
}
diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h
index d8cd0df6d1..9702b5a517 100644
--- a/core/io/file_access_encrypted.h
+++ b/core/io/file_access_encrypted.h
@@ -88,6 +88,8 @@ public:
virtual uint32_t _get_unix_permissions(const String &p_file) override;
virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override;
+ virtual void close() override;
+
FileAccessEncrypted() {}
~FileAccessEncrypted();
};
diff --git a/core/io/file_access_memory.h b/core/io/file_access_memory.h
index adc29f74be..43fe6ab658 100644
--- a/core/io/file_access_memory.h
+++ b/core/io/file_access_memory.h
@@ -71,6 +71,8 @@ public:
virtual uint32_t _get_unix_permissions(const String &p_file) override { return 0; }
virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override { return FAILED; }
+ virtual void close() override {}
+
FileAccessMemory() {}
};
diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp
index e765eb2d42..7fabff26ac 100644
--- a/core/io/file_access_network.cpp
+++ b/core/io/file_access_network.cpp
@@ -469,6 +469,15 @@ void FileAccessNetwork::configure() {
GLOBAL_DEF(PropertyInfo(Variant::INT, "network/remote_fs/page_read_ahead", PROPERTY_HINT_RANGE, "0,8,1,or_greater"), 4);
}
+void FileAccessNetwork::close() {
+ _close();
+
+ FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
+ nc->lock_mutex();
+ nc->accesses.erase(id);
+ nc->unlock_mutex();
+}
+
FileAccessNetwork::FileAccessNetwork() {
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
nc->lock_mutex();
diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h
index 16e8920114..78c19347ce 100644
--- a/core/io/file_access_network.h
+++ b/core/io/file_access_network.h
@@ -156,6 +156,8 @@ public:
virtual uint32_t _get_unix_permissions(const String &p_file) override;
virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override;
+ virtual void close() override;
+
static void configure();
FileAccessNetwork();
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index 7c392c005a..9553f35b19 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -366,6 +366,10 @@ bool FileAccessPack::file_exists(const String &p_name) {
return false;
}
+void FileAccessPack::close() {
+ f = Ref<FileAccess>();
+}
+
FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file) :
pf(p_file),
f(FileAccess::open(pf.pack, FileAccess::READ)) {
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index baa62e4516..8bfabc9529 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -178,6 +178,8 @@ public:
virtual bool file_exists(const String &p_name) override;
+ virtual void close() override;
+
FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file);
};
diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp
index b71dd5e9bd..064353476f 100644
--- a/core/io/file_access_zip.cpp
+++ b/core/io/file_access_zip.cpp
@@ -336,6 +336,10 @@ bool FileAccessZip::file_exists(const String &p_name) {
return false;
}
+void FileAccessZip::close() {
+ _close();
+}
+
FileAccessZip::FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file) {
open_internal(p_path, FileAccess::READ);
}
diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h
index 63f1012f99..f8b640946c 100644
--- a/core/io/file_access_zip.h
+++ b/core/io/file_access_zip.h
@@ -109,6 +109,8 @@ public:
virtual uint32_t _get_unix_permissions(const String &p_file) override { return 0; }
virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override { return FAILED; }
+ virtual void close() override;
+
FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file);
~FileAccessZip();
};
diff --git a/core/object/script_language_extension.cpp b/core/object/script_language_extension.cpp
index 19c6fc3383..c7eb32c020 100644
--- a/core/object/script_language_extension.cpp
+++ b/core/object/script_language_extension.cpp
@@ -36,6 +36,7 @@ void ScriptExtension::_bind_methods() {
GDVIRTUAL_BIND(_can_instantiate);
GDVIRTUAL_BIND(_get_base_script);
+ GDVIRTUAL_BIND(_get_global_name);
GDVIRTUAL_BIND(_inherits_script, "script");
GDVIRTUAL_BIND(_get_instance_base_type);
diff --git a/core/templates/paged_array.h b/core/templates/paged_array.h
index c447b5af64..45b90869b9 100644
--- a/core/templates/paged_array.h
+++ b/core/templates/paged_array.h
@@ -278,10 +278,10 @@ public:
count -= remainder;
- uint32_t src_pages = p_array._get_pages_in_use();
+ uint32_t src_page_index = 0;
uint32_t page_size = page_size_mask + 1;
- for (uint32_t i = 0; i < src_pages; i++) {
+ while (p_array.count > 0) {
uint32_t page_count = _get_pages_in_use();
uint32_t new_page_count = page_count + 1;
@@ -289,16 +289,14 @@ public:
_grow_page_array(); //keep out of inline
}
- page_data[page_count] = p_array.page_data[i];
- page_ids[page_count] = p_array.page_ids[i];
- if (i == src_pages - 1) {
- //last page, only increment with remainder
- count += p_array.count & page_size_mask;
- } else {
- count += page_size;
- }
+ page_data[page_count] = p_array.page_data[src_page_index];
+ page_ids[page_count] = p_array.page_ids[src_page_index];
+
+ uint32_t take = MIN(p_array.count, page_size); //pages to take away
+ p_array.count -= take;
+ count += take;
+ src_page_index++;
}
- p_array.count = 0; //take away the other array pages
//handle the remainder page if exists
if (remainder_page) {
diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml
index d5280cb548..ed7bdc07fc 100644
--- a/doc/classes/@GlobalScope.xml
+++ b/doc/classes/@GlobalScope.xml
@@ -1140,7 +1140,7 @@
<return type="float" />
<param index="0" name="x" type="float" />
<description>
- Returns [code]-1.0[/code] if [param x] is negative, [code]1.0[/code] if [param x] is positive, and [code]0.0[/code] if if [param x] is zero.
+ Returns [code]-1.0[/code] if [param x] is negative, [code]1.0[/code] if [param x] is positive, and [code]0.0[/code] if [param x] is zero.
[codeblock]
sign(-6.5) # Returns -1.0
sign(0.0) # Returns 0.0
diff --git a/doc/classes/AnimatedTexture.xml b/doc/classes/AnimatedTexture.xml
index 57a7f86901..052c55dfb6 100644
--- a/doc/classes/AnimatedTexture.xml
+++ b/doc/classes/AnimatedTexture.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AnimatedTexture" inherits="Texture2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="AnimatedTexture" inherits="Texture2D" is_deprecated="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Proxy texture for simple frame-based animations.
</brief_description>
@@ -8,6 +8,7 @@
The playback of the animation is controlled by the [member speed_scale] property, as well as each frame's duration (see [method set_frame_duration]). The animation loops, i.e. it will restart at frame 0 automatically after playing the last frame.
[AnimatedTexture] currently requires all frame textures to have the same size, otherwise the bigger ones will be cropped to match the smallest one.
[b]Note:[/b] AnimatedTexture doesn't support using [AtlasTexture]s. Each frame needs to be a separate [Texture2D].
+ [b]Warning:[/b] AnimatedTexture is deprecated, and might be removed in a future release. Its current implementation is not efficient for the modern renderers.
</description>
<tutorials>
</tutorials>
@@ -46,7 +47,7 @@
</methods>
<members>
<member name="current_frame" type="int" setter="set_current_frame" getter="get_current_frame">
- Sets the currently visible frame of the texture.
+ Sets the currently visible frame of the texture. Setting this frame while playing resets the current frame time, so the newly selected frame plays for its whole configured frame duration.
</member>
<member name="frames" type="int" setter="set_frames" getter="get_frames" default="1">
Number of frames to use in the animation. While you can create the frames independently with [method set_frame_texture], you need to set this value for the animation to take new frames into account. The maximum number of frames is [constant MAX_FRAMES].
diff --git a/doc/classes/Decal.xml b/doc/classes/Decal.xml
index ddfa64891d..824416e4d4 100644
--- a/doc/classes/Decal.xml
+++ b/doc/classes/Decal.xml
@@ -96,7 +96,7 @@
[b]Note:[/b] Unlike [BaseMaterial3D] whose filter mode can be adjusted on a per-material basis, the filter mode for [Decal] textures is set globally with [member ProjectSettings.rendering/textures/decals/filter].
</member>
<member name="texture_emission" type="Texture2D" setter="set_texture" getter="get_texture">
- [Texture2D] with the emission [Color] of the Decal. Either this or the [member texture_emission] must be set for the Decal to be visible. Use the alpha channel like a mask to smoothly blend the edges of the decal with the underlying object.
+ [Texture2D] with the emission [Color] of the Decal. Either this or the [member texture_albedo] must be set for the Decal to be visible. Use the alpha channel like a mask to smoothly blend the edges of the decal with the underlying object.
[b]Note:[/b] Unlike [BaseMaterial3D] whose filter mode can be adjusted on a per-material basis, the filter mode for [Decal] textures is set globally with [member ProjectSettings.rendering/textures/decals/filter].
</member>
<member name="texture_normal" type="Texture2D" setter="set_texture" getter="get_texture">
diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml
index fc5de1b771..122db7e668 100644
--- a/doc/classes/DisplayServer.xml
+++ b/doc/classes/DisplayServer.xml
@@ -190,6 +190,7 @@
<description>
Adds a new checkable item with text [param label] to the global menu with ID [param menu_root].
Returns index of the inserted item, it's not guaranteed to be the same as [param index] value.
+ An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using boolean OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
[b]Note:[/b] The [param callback] and [param key_callback] Callables need to accept exactly one Variant parameter, the parameter passed to the Callables will be the value passed to [param tag].
[b]Note:[/b] This method is implemented on macOS.
[b]Supported system menu IDs:[/b]
@@ -212,6 +213,7 @@
<description>
Adds a new checkable item with text [param label] and icon [param icon] to the global menu with ID [param menu_root].
Returns index of the inserted item, it's not guaranteed to be the same as [param index] value.
+ An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using boolean OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
[b]Note:[/b] The [param callback] and [param key_callback] Callables need to accept exactly one Variant parameter, the parameter passed to the Callables will be the value passed to [param tag].
[b]Note:[/b] This method is implemented on macOS.
[b]Supported system menu IDs:[/b]
@@ -234,6 +236,7 @@
<description>
Adds a new item with text [param label] and icon [param icon] to the global menu with ID [param menu_root].
Returns index of the inserted item, it's not guaranteed to be the same as [param index] value.
+ An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using boolean OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
[b]Note:[/b] The [param callback] and [param key_callback] Callables need to accept exactly one Variant parameter, the parameter passed to the Callables will be the value passed to [param tag].
[b]Note:[/b] This method is implemented on macOS.
[b]Supported system menu IDs:[/b]
@@ -256,6 +259,7 @@
<description>
Adds a new radio-checkable item with text [param label] and icon [param icon] to the global menu with ID [param menu_root].
Returns index of the inserted item, it's not guaranteed to be the same as [param index] value.
+ An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using boolean OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
[b]Note:[/b] Radio-checkable items just display a checkmark, but don't have any built-in checking behavior and must be checked/unchecked manually. See [method global_menu_set_item_checked] for more info on how to control it.
[b]Note:[/b] The [param callback] and [param key_callback] Callables need to accept exactly one Variant parameter, the parameter passed to the Callables will be the value passed to [param tag].
[b]Note:[/b] This method is implemented on macOS.
@@ -278,6 +282,7 @@
<description>
Adds a new item with text [param label] to the global menu with ID [param menu_root].
Returns index of the inserted item, it's not guaranteed to be the same as [param index] value.
+ An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using boolean OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
[b]Note:[/b] The [param callback] and [param key_callback] Callables need to accept exactly one Variant parameter, the parameter passed to the Callables will be the value passed to [param tag].
[b]Note:[/b] This method is implemented on macOS.
[b]Supported system menu IDs:[/b]
@@ -302,6 +307,7 @@
Adds a new item with text [param label] to the global menu with ID [param menu_root].
Contrarily to normal binary items, multistate items can have more than two states, as defined by [param max_states]. Each press or activate of the item will increase the state by one. The default value is defined by [param default_state].
Returns index of the inserted item, it's not guaranteed to be the same as [param index] value.
+ An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using boolean OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
[b]Note:[/b] By default, there's no indication of the current item state, it should be changed manually.
[b]Note:[/b] The [param callback] and [param key_callback] Callables need to accept exactly one Variant parameter, the parameter passed to the Callables will be the value passed to [param tag].
[b]Note:[/b] This method is implemented on macOS.
@@ -324,6 +330,7 @@
<description>
Adds a new radio-checkable item with text [param label] to the global menu with ID [param menu_root].
Returns index of the inserted item, it's not guaranteed to be the same as [param index] value.
+ An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using boolean OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
[b]Note:[/b] Radio-checkable items just display a checkmark, but don't have any built-in checking behavior and must be checked/unchecked manually. See [method global_menu_set_item_checked] for more info on how to control it.
[b]Note:[/b] The [param callback] and [param key_callback] Callables need to accept exactly one Variant parameter, the parameter passed to the Callables will be the value passed to [param tag].
[b]Note:[/b] This method is implemented on macOS.
@@ -558,7 +565,7 @@
<param index="1" name="idx" type="int" />
<param index="2" name="keycode" type="int" enum="Key" />
<description>
- Sets the accelerator of the item at index [param idx].
+ Sets the accelerator of the item at index [param idx]. [param keycode] can be a single [enum Key], or a combination of [enum KeyModifierMask]s and [enum Key]s using boolean OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
[b]Note:[/b] This method is implemented on macOS.
</description>
</method>
diff --git a/doc/classes/FileAccess.xml b/doc/classes/FileAccess.xml
index eda06d57da..526f7c22e6 100644
--- a/doc/classes/FileAccess.xml
+++ b/doc/classes/FileAccess.xml
@@ -33,7 +33,7 @@
[/csharp]
[/codeblocks]
In the example above, the file will be saved in the user data folder as specified in the [url=$DOCS_URL/tutorials/io/data_paths.html]Data paths[/url] documentation.
- There is no method to close a file in order to free it from use. Instead, [FileAccess] will close when it's freed, which happens when it goes out of scope or when it gets assigned with [code]null[/code]. In C# the reference must be disposed after we are done using it, this can be done with the [code]using[/code] statement or calling the [code]Dispose[/code] method directly.
+ [FileAccess] will close when it's freed, which happens when it goes out of scope or when it gets assigned with [code]null[/code]. In C# the reference must be disposed after we are done using it, this can be done with the [code]using[/code] statement or calling the [code]Dispose[/code] method directly.
[codeblocks]
[gdscript]
var file = FileAccess.open("res://something") # File is opened and locked for use.
@@ -52,6 +52,13 @@
<link title="3D Voxel Demo">https://godotengine.org/asset-library/asset/676</link>
</tutorials>
<methods>
+ <method name="close">
+ <return type="void" />
+ <description>
+ Closes the currently opened file and prevents subsequent read/write operations. Use flush to persist the data to disk without closing the file.
+ [b]Note:[/b] [FileAccess] will automatically close when it's freed, which happens when it goes out of scope or when it gets assigned with [code]null[/code]. In C# the reference must be disposed after we are done using it, this can be done with the [code]using[/code] statement or calling the [code]Dispose[/code] method directly.
+ </description>
+ </method>
<method name="eof_reached" qualifiers="const">
<return type="bool" />
<description>
diff --git a/doc/classes/NavigationAgent2D.xml b/doc/classes/NavigationAgent2D.xml
index 92fd8bcc6a..c6d03fb6d8 100644
--- a/doc/classes/NavigationAgent2D.xml
+++ b/doc/classes/NavigationAgent2D.xml
@@ -171,6 +171,8 @@
- [code]type[/code]: Always [constant NavigationPathQueryResult2D.PATH_SEGMENT_TYPE_LINK].
- [code]rid[/code]: The [RID] of the link.
- [code]owner[/code]: The object which manages the link (usually [NavigationLink2D]).
+ - [code]link_entry_position[/code]: If [code]owner[/code] is available and the owner is a [NavigationLink2D], it will contain the global position of the link's point the agent is entering.
+ - [code]link_exit_position[/code]: If [code]owner[/code] is available and the owner is a [NavigationLink2D], it will contain the global position of the link's point which the agent is exiting.
</description>
</signal>
<signal name="navigation_finished">
diff --git a/doc/classes/NavigationAgent3D.xml b/doc/classes/NavigationAgent3D.xml
index 0ed11bc477..d2151773da 100644
--- a/doc/classes/NavigationAgent3D.xml
+++ b/doc/classes/NavigationAgent3D.xml
@@ -144,13 +144,13 @@
<member name="path_desired_distance" type="float" setter="set_path_desired_distance" getter="get_path_desired_distance" default="1.0">
The distance threshold before a path point is considered to be reached. This will allow an agent to not have to hit a path point on the path exactly, but in the area. If this value is set to high the NavigationAgent will skip points on the path which can lead to leaving the navigation mesh. If this value is set to low the NavigationAgent will be stuck in a repath loop cause it will constantly overshoot or undershoot the distance to the next point on each physics frame update.
</member>
- <member name="path_max_distance" type="float" setter="set_path_max_distance" getter="get_path_max_distance" default="3.0">
+ <member name="path_max_distance" type="float" setter="set_path_max_distance" getter="get_path_max_distance" default="5.0">
The maximum distance the agent is allowed away from the ideal path to the final position. This can happen due to trying to avoid collisions. When the maximum distance is exceeded, it recalculates the ideal path.
</member>
<member name="path_metadata_flags" type="int" setter="set_path_metadata_flags" getter="get_path_metadata_flags" enum="NavigationPathQueryParameters3D.PathMetadataFlags" default="7">
Additional information to return with the navigation path.
</member>
- <member name="radius" type="float" setter="set_radius" getter="get_radius" default="1.0">
+ <member name="radius" type="float" setter="set_radius" getter="get_radius" default="0.5">
The radius of the avoidance agent. This is the "body" of the avoidance agent and not the avoidance maneuver starting radius (which is controlled by [member neighbor_distance]).
Does not affect normal pathfinding. To change an actor's pathfinding radius bake [NavigationMesh] resources with a different [member NavigationMesh.agent_radius] property and use different navigation maps for each actor size.
</member>
@@ -160,7 +160,7 @@
<member name="target_position" type="Vector3" setter="set_target_position" getter="get_target_position" default="Vector3(0, 0, 0)">
The user-defined target position. Setting this property will clear the current navigation path.
</member>
- <member name="time_horizon" type="float" setter="set_time_horizon" getter="get_time_horizon" default="5.0">
+ <member name="time_horizon" type="float" setter="set_time_horizon" getter="get_time_horizon" default="1.0">
The minimal amount of time for which this agent's velocities, that are computed with the collision avoidance algorithm, are safe with respect to other agents. The larger the number, the sooner the agent will respond to other agents, but less freedom in choosing its velocities. Must be positive.
</member>
</members>
@@ -174,6 +174,8 @@
- [code]type[/code]: Always [constant NavigationPathQueryResult3D.PATH_SEGMENT_TYPE_LINK].
- [code]rid[/code]: The [RID] of the link.
- [code]owner[/code]: The object which manages the link (usually [NavigationLink3D]).
+ - [code]link_entry_position[/code]: If [code]owner[/code] is available and the owner is a [NavigationLink2D], it will contain the global position of the link's point the agent is entering.
+ - [code]link_exit_position[/code]: If [code]owner[/code] is available and the owner is a [NavigationLink2D], it will contain the global position of the link's point which the agent is exiting.
</description>
</signal>
<signal name="navigation_finished">
diff --git a/doc/classes/NavigationLink2D.xml b/doc/classes/NavigationLink2D.xml
index b3f4367675..3f5b1fb184 100644
--- a/doc/classes/NavigationLink2D.xml
+++ b/doc/classes/NavigationLink2D.xml
@@ -10,6 +10,18 @@
<link title="Using NavigationLinks">$DOCS_URL/tutorials/navigation/navigation_using_navigationlinks.html</link>
</tutorials>
<methods>
+ <method name="get_global_end_position" qualifiers="const">
+ <return type="Vector2" />
+ <description>
+ Returns the [member end_position] that is relative to the link as a global position.
+ </description>
+ </method>
+ <method name="get_global_start_position" qualifiers="const">
+ <return type="Vector2" />
+ <description>
+ Returns the [member start_position] that is relative to the link as a global position.
+ </description>
+ </method>
<method name="get_navigation_layer_value" qualifiers="const">
<return type="bool" />
<param index="0" name="layer_number" type="int" />
@@ -17,6 +29,20 @@
Returns whether or not the specified layer of the [member navigation_layers] bitmask is enabled, given a [code]layer_number[/code] between 1 and 32.
</description>
</method>
+ <method name="set_global_end_position">
+ <return type="void" />
+ <param index="0" name="position" type="Vector2" />
+ <description>
+ Sets the [member end_position] that is relative to the link from a global [param position].
+ </description>
+ </method>
+ <method name="set_global_start_position">
+ <return type="void" />
+ <param index="0" name="position" type="Vector2" />
+ <description>
+ Sets the [member start_position] that is relative to the link from a global [param position].
+ </description>
+ </method>
<method name="set_navigation_layer_value">
<return type="void" />
<param index="0" name="layer_number" type="int" />
diff --git a/doc/classes/NavigationLink3D.xml b/doc/classes/NavigationLink3D.xml
index 4dff226042..4081426dcd 100644
--- a/doc/classes/NavigationLink3D.xml
+++ b/doc/classes/NavigationLink3D.xml
@@ -10,6 +10,18 @@
<link title="Using NavigationLinks">$DOCS_URL/tutorials/navigation/navigation_using_navigationlinks.html</link>
</tutorials>
<methods>
+ <method name="get_global_end_position" qualifiers="const">
+ <return type="Vector3" />
+ <description>
+ Returns the [member end_position] that is relative to the link as a global position.
+ </description>
+ </method>
+ <method name="get_global_start_position" qualifiers="const">
+ <return type="Vector3" />
+ <description>
+ Returns the [member start_position] that is relative to the link as a global position.
+ </description>
+ </method>
<method name="get_navigation_layer_value" qualifiers="const">
<return type="bool" />
<param index="0" name="layer_number" type="int" />
@@ -17,6 +29,20 @@
Returns whether or not the specified layer of the [member navigation_layers] bitmask is enabled, given a [code]layer_number[/code] between 1 and 32.
</description>
</method>
+ <method name="set_global_end_position">
+ <return type="void" />
+ <param index="0" name="position" type="Vector3" />
+ <description>
+ Sets the [member end_position] that is relative to the link from a global [param position].
+ </description>
+ </method>
+ <method name="set_global_start_position">
+ <return type="void" />
+ <param index="0" name="position" type="Vector3" />
+ <description>
+ Sets the [member start_position] that is relative to the link from a global [param position].
+ </description>
+ </method>
<method name="set_navigation_layer_value">
<return type="void" />
<param index="0" name="layer_number" type="int" />
diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml
index e7a2b99172..103de8eddb 100644
--- a/doc/classes/NavigationServer2D.xml
+++ b/doc/classes/NavigationServer2D.xml
@@ -126,6 +126,12 @@
Destroys the given RID.
</description>
</method>
+ <method name="get_debug_enabled" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] when the NavigationServer has debug enabled.
+ </description>
+ </method>
<method name="get_maps" qualifiers="const">
<return type="RID[]" />
<description>
@@ -520,6 +526,13 @@
Sets the [param travel_cost] for this [param region].
</description>
</method>
+ <method name="set_debug_enabled">
+ <return type="void" />
+ <param index="0" name="enabled" type="bool" />
+ <description>
+ If [code]true[/code] enables debug mode on the NavigationServer.
+ </description>
+ </method>
</methods>
<signals>
<signal name="map_changed">
diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml
index 1feb363999..0d8cb78ff9 100644
--- a/doc/classes/NavigationServer3D.xml
+++ b/doc/classes/NavigationServer3D.xml
@@ -126,6 +126,12 @@
Destroys the given RID.
</description>
</method>
+ <method name="get_debug_enabled" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] when the NavigationServer has debug enabled.
+ </description>
+ </method>
<method name="get_maps" qualifiers="const">
<return type="RID[]" />
<description>
@@ -575,6 +581,13 @@
Control activation of this server.
</description>
</method>
+ <method name="set_debug_enabled">
+ <return type="void" />
+ <param index="0" name="enabled" type="bool" />
+ <description>
+ If [code]true[/code] enables debug mode on the NavigationServer.
+ </description>
+ </method>
</methods>
<signals>
<signal name="map_changed">
diff --git a/doc/classes/Node3D.xml b/doc/classes/Node3D.xml
index 1aa71113e9..c199c1aae6 100644
--- a/doc/classes/Node3D.xml
+++ b/doc/classes/Node3D.xml
@@ -4,7 +4,7 @@
Most basic 3D game object, parent of all 3D-related nodes.
</brief_description>
<description>
- Most basic 3D game object, with a 3D [Transform3D] and visibility settings. All other 3D game objects inherit from Node3D. Use [Node3D] as a parent node to move, scale, rotate and show/hide children in a 3D project.
+ Most basic 3D game object, with a [Transform3D] and visibility settings. All other 3D game objects inherit from Node3D. Use [Node3D] as a parent node to move, scale, rotate and show/hide children in a 3D project.
Affine operations (rotate, scale, translate) happen in parent's local coordinate system, unless the [Node3D] object is set as top-level. Affine operations in this coordinate system correspond to direct affine operations on the [Node3D]'s transform. The word local below refers to this coordinate system. The coordinate system that is attached to the [Node3D] object itself is referred to as object-local coordinate system.
[b]Note:[/b] Unless otherwise specified, all methods that have angle parameters must have angles specified as [i]radians[/i]. To convert degrees to radians, use [method @GlobalScope.deg_to_rad].
</description>
diff --git a/doc/classes/OmniLight3D.xml b/doc/classes/OmniLight3D.xml
index 1df8c255dd..7c5b9aff46 100644
--- a/doc/classes/OmniLight3D.xml
+++ b/doc/classes/OmniLight3D.xml
@@ -13,7 +13,8 @@
</tutorials>
<members>
<member name="omni_attenuation" type="float" setter="set_param" getter="get_param" default="1.0">
- The light's attenuation (drop-off) curve. A number of presets are available in the [b]Inspector[/b] by right-clicking the curve.
+ The light's attenuation (drop-off) curve. A number of presets are available in the [b]Inspector[/b] by right-clicking the curve. Zero and negative values are allowed but can produce unusual effects.
+ [b]Note:[/b] Very high [member omni_attenuation] values (typically above 10) can impact performance negatively if the light is made to use a larger [member omni_range] to compensate. This is because culling opportunities will become less common and shading costs will be increased (as the light will cover more pixels on screen while resulting in the same amount of brightness). To improve performance, use the lowest [member omni_attenuation] value possible for the visuals you're trying to achieve.
</member>
<member name="omni_range" type="float" setter="set_param" getter="get_param" default="5.0">
The light's radius. Note that the effectively lit area may appear to be smaller depending on the [member omni_attenuation] in use. No matter the [member omni_attenuation] in use, the light will never reach anything outside this radius.
diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml
index 8dec4eaf86..97cc05d1a1 100644
--- a/doc/classes/PopupMenu.xml
+++ b/doc/classes/PopupMenu.xml
@@ -20,7 +20,7 @@
<param index="2" name="accel" type="int" enum="Key" default="0" />
<description>
Adds a new checkable item with text [param label].
- An [param id] can optionally be provided, as well as an accelerator ([param accel]). If no [param id] is provided, one will be created from the index. If no [param accel] is provided then the default [code]0[/code] will be assigned to it. See [method get_item_accelerator] for more info on accelerators.
+ An [param id] can optionally be provided, as well as an accelerator ([param accel]). If no [param id] is provided, one will be created from the index. If no [param accel] is provided, then the default value of 0 (corresponding to [constant @GlobalScope.KEY_NONE]) will be assigned to the item (which means it won't have any accelerator). See [method get_item_accelerator] for more info on accelerators.
[b]Note:[/b] Checkable items just display a checkmark, but don't have any built-in checking behavior and must be checked/unchecked manually. See [method set_item_checked] for more info on how to control it.
</description>
</method>
@@ -43,7 +43,7 @@
<param index="3" name="accel" type="int" enum="Key" default="0" />
<description>
Adds a new checkable item with text [param label] and icon [param texture].
- An [param id] can optionally be provided, as well as an accelerator ([param accel]). If no [param id] is provided, one will be created from the index. If no [param accel] is provided then the default [code]0[/code] will be assigned to it. See [method get_item_accelerator] for more info on accelerators.
+ An [param id] can optionally be provided, as well as an accelerator ([param accel]). If no [param id] is provided, one will be created from the index. If no [param accel] is provided, then the default value of 0 (corresponding to [constant @GlobalScope.KEY_NONE]) will be assigned to the item (which means it won't have any accelerator). See [method get_item_accelerator] for more info on accelerators.
[b]Note:[/b] Checkable items just display a checkmark, but don't have any built-in checking behavior and must be checked/unchecked manually. See [method set_item_checked] for more info on how to control it.
</description>
</method>
@@ -67,7 +67,7 @@
<param index="3" name="accel" type="int" enum="Key" default="0" />
<description>
Adds a new item with text [param label] and icon [param texture].
- An [param id] can optionally be provided, as well as an accelerator ([param accel]). If no [param id] is provided, one will be created from the index. If no [param accel] is provided then the default [code]0[/code] will be assigned to it. See [method get_item_accelerator] for more info on accelerators.
+ An [param id] can optionally be provided, as well as an accelerator ([param accel]). If no [param id] is provided, one will be created from the index. If no [param accel] is provided, then the default value of 0 (corresponding to [constant @GlobalScope.KEY_NONE]) will be assigned to the item (which means it won't have any accelerator). See [method get_item_accelerator] for more info on accelerators.
</description>
</method>
<method name="add_icon_radio_check_item">
@@ -108,7 +108,7 @@
<param index="2" name="accel" type="int" enum="Key" default="0" />
<description>
Adds a new item with text [param label].
- An [param id] can optionally be provided, as well as an accelerator ([param accel]). If no [param id] is provided, one will be created from the index. If no [param accel] is provided then the default [code]0[/code] will be assigned to it. See [method get_item_accelerator] for more info on accelerators.
+ An [param id] can optionally be provided, as well as an accelerator ([param accel]). If no [param id] is provided, one will be created from the index. If no [param accel] is provided, then the default value of 0 (corresponding to [constant @GlobalScope.KEY_NONE]) will be assigned to the item (which means it won't have any accelerator). See [method get_item_accelerator] for more info on accelerators.
[b]Note:[/b] The provided [param id] is used only in [signal id_pressed] and [signal id_focused] signals. It's not related to the [code]index[/code] arguments in e.g. [method set_item_checked].
</description>
</method>
@@ -122,7 +122,7 @@
<description>
Adds a new multistate item with text [param label].
Contrarily to normal binary items, multistate items can have more than two states, as defined by [param max_states]. Each press or activate of the item will increase the state by one. The default value is defined by [param default_state].
- An [param id] can optionally be provided, as well as an accelerator ([param accel]). If no [param id] is provided, one will be created from the index. If no [param accel] is provided then the default [code]0[/code] will be assigned to it. See [method get_item_accelerator] for more info on accelerators.
+ An [param id] can optionally be provided, as well as an accelerator ([param accel]). If no [param id] is provided, one will be created from the index. If no [param accel] is provided, then the default value of 0 (corresponding to [constant @GlobalScope.KEY_NONE]) will be assigned to the item (which means it won't have any accelerator). See [method get_item_accelerator] for more info on accelerators.
</description>
</method>
<method name="add_radio_check_item">
@@ -132,7 +132,7 @@
<param index="2" name="accel" type="int" enum="Key" default="0" />
<description>
Adds a new radio check button with text [param label].
- An [param id] can optionally be provided, as well as an accelerator ([param accel]). If no [param id] is provided, one will be created from the index. If no [param accel] is provided then the default [code]0[/code] will be assigned to it. See [method get_item_accelerator] for more info on accelerators.
+ An [param id] can optionally be provided, as well as an accelerator ([param accel]). If no [param id] is provided, one will be created from the index. If no [param accel] is provided, then the default value of 0 (corresponding to [constant @GlobalScope.KEY_NONE]) will be assigned to the item (which means it won't have any accelerator). See [method get_item_accelerator] for more info on accelerators.
[b]Note:[/b] Checkable items just display a checkmark, but don't have any built-in checking behavior and must be checked/unchecked manually. See [method set_item_checked] for more info on how to control it.
</description>
</method>
@@ -192,7 +192,7 @@
<return type="int" enum="Key" />
<param index="0" name="index" type="int" />
<description>
- Returns the accelerator of the item at the given [param index]. Accelerators are special combinations of keys that activate the item, no matter which control is focused.
+ Returns the accelerator of the item at the given [param index]. An accelerator is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The return value is an integer which is generally a combination of [enum KeyModifierMask]s and [enum Key]s using boolean OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]). If no accelerator is defined for the specified [param index], [method get_item_accelerator] returns [code]0[/code] (corresponding to [constant @GlobalScope.KEY_NONE]).
</description>
</method>
<method name="get_item_icon" qualifiers="const">
@@ -345,7 +345,7 @@
<param index="0" name="index" type="int" />
<param index="1" name="accel" type="int" enum="Key" />
<description>
- Sets the accelerator of the item at the given [param index]. Accelerators are special combinations of keys that activate the item, no matter which control is focused.
+ Sets the accelerator of the item at the given [param index]. An accelerator is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. [param accel] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using boolean OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
</description>
</method>
<method name="set_item_as_checkable">
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 986810edf2..3177780a26 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -667,7 +667,7 @@
Main window initial position.
[code]0[/code] - "Absolute", [member display/window/size/initial_position] is used to set window position.
[code]1[/code] - "Primary Screen Center".
- [code]2[/code] - "Other Screen Center", [member display/window/size/initial_screen] is used to set window position.
+ [code]2[/code] - "Other Screen Center", [member display/window/size/initial_screen] is used to set the screen.
</member>
<member name="display/window/size/initial_screen" type="int" setter="" getter="" default="0">
Main window initial screen, this settings is used only if [member display/window/size/initial_position_type] is set to "Other Screen Center" ([code]2[/code]).
@@ -1147,9 +1147,6 @@
<member name="input_devices/pointing/emulate_touch_from_mouse" type="bool" setter="" getter="" default="false">
If [code]true[/code], sends touch input events when clicking or dragging the mouse.
</member>
- <member name="input_devices/pointing/ios/touch_delay" type="float" setter="" getter="" default="0.15">
- Default delay for touch events. This only affects iOS devices.
- </member>
<member name="internationalization/locale/fallback" type="String" setter="" getter="" default="&quot;en&quot;">
The locale to fall back to if a translation isn't available in a given language. If left empty, [code]en[/code] (English) will be used.
</member>
@@ -2337,11 +2334,11 @@
<member name="rendering/textures/lossless_compression/force_png" type="bool" setter="" getter="" default="false">
If [code]true[/code], the texture importer will import lossless textures using the PNG format. Otherwise, it will default to using WebP.
</member>
- <member name="rendering/textures/vram_compression/import_etc2_astc" type="bool" setter="" getter="" default="false">
+ <member name="rendering/textures/vram_compression/import_etc2_astc" type="bool" setter="" getter="">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the Ericsson Texture Compression 2 algorithm for lower quality textures and normalmaps and Adaptable Scalable Texture Compression algorithm for high quality textures (in 4x4 block size).
[b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]).
</member>
- <member name="rendering/textures/vram_compression/import_s3tc_bptc" type="bool" setter="" getter="" default="true">
+ <member name="rendering/textures/vram_compression/import_s3tc_bptc" type="bool" setter="" getter="">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the S3 Texture Compression algorithm (DXT1-5) for lower quality textures and the the BPTC algorithm (BC6H and BC7) for high quality textures. This algorithm is only supported on PC desktop platforms and consoles.
[b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]).
</member>
diff --git a/doc/classes/ScriptExtension.xml b/doc/classes/ScriptExtension.xml
index 045eadda41..61034f8e4a 100644
--- a/doc/classes/ScriptExtension.xml
+++ b/doc/classes/ScriptExtension.xml
@@ -32,6 +32,11 @@
<description>
</description>
</method>
+ <method name="_get_global_name" qualifiers="virtual const">
+ <return type="StringName" />
+ <description>
+ </description>
+ </method>
<method name="_get_instance_base_type" qualifiers="virtual const">
<return type="StringName" />
<description>
diff --git a/doc/classes/SpotLight3D.xml b/doc/classes/SpotLight3D.xml
index 6bb4ae548c..3b32923872 100644
--- a/doc/classes/SpotLight3D.xml
+++ b/doc/classes/SpotLight3D.xml
@@ -20,10 +20,11 @@
[b]Note:[/b] [member spot_angle] is not affected by [member Node3D.scale] (the light's scale or its parent's scale).
</member>
<member name="spot_angle_attenuation" type="float" setter="set_param" getter="get_param" default="1.0">
- The spotlight's angular attenuation curve.
+ The spotlight's [i]angular[/i] attenuation curve. See also [member spot_attenuation].
</member>
<member name="spot_attenuation" type="float" setter="set_param" getter="get_param" default="1.0">
- The spotlight's light energy attenuation curve.
+ The spotlight's light energy (drop-off) attenuation curve. A number of presets are available in the [b]Inspector[/b] by right-clicking the curve. Zero and negative values are allowed but can produce unusual effects. See also [member spot_angle_attenuation].
+ [b]Note:[/b] Very high [member spot_attenuation] values (typically above 10) can impact performance negatively if the light is made to use a larger [member spot_range] to compensate. This is because culling opportunities will become less common and shading costs will be increased (as the light will cover more pixels on screen while resulting in the same amount of brightness). To improve performance, use the lowest [member spot_attenuation] value possible for the visuals you're trying to achieve.
</member>
<member name="spot_range" type="float" setter="set_param" getter="get_param" default="5.0">
The maximal range that can be reached by the spotlight. Note that the effectively lit area may appear to be smaller depending on the [member spot_attenuation] in use. No matter the [member spot_attenuation] in use, the light will never reach anything outside this range.
diff --git a/doc/classes/String.xml b/doc/classes/String.xml
index 8535dacda7..53b34332d7 100644
--- a/doc/classes/String.xml
+++ b/doc/classes/String.xml
@@ -1052,7 +1052,7 @@
[codeblock]
print("I caught %d fishes!" % 2) # Prints "I caught 2 fishes!"
- var my_message = "Travelling to %s, at %2.2f per second."
+ var my_message = "Travelling to %s, at %2.2f km/h."
var location = "Deep Valley"
var speed = 40.3485
print(my_message % [location, speed]) # Prints "Travelling to Deep Valley, at 40.35 km/h."
diff --git a/doc/classes/StringName.xml b/doc/classes/StringName.xml
index 96b958a5b9..4ccb93dab3 100644
--- a/doc/classes/StringName.xml
+++ b/doc/classes/StringName.xml
@@ -505,7 +505,7 @@
<return type="bool" />
<param index="0" name="expr" type="String" />
<description>
- Does a simple expression match, where [code]*[/code] matches zero or more arbitrary characters and [code]?[/code] matches any single character except a period ([code].[/code]). An empty string or empty expression always evaluates to [code]false[/code].
+ Does a simple expression match (also called "glob" or "globbing"), where [code]*[/code] matches zero or more arbitrary characters and [code]?[/code] matches any single character except a period ([code].[/code]). An empty string or empty expression always evaluates to [code]false[/code].
</description>
</method>
<method name="matchn" qualifiers="const">
diff --git a/doc/classes/TextureRect.xml b/doc/classes/TextureRect.xml
index 460ffbbb80..3500a0ddf5 100644
--- a/doc/classes/TextureRect.xml
+++ b/doc/classes/TextureRect.xml
@@ -10,8 +10,9 @@
<link title="3D Voxel Demo">https://godotengine.org/asset-library/asset/676</link>
</tutorials>
<members>
- <member name="expand_mode" type="int" setter="set_expand_mode" getter="get_expand_mode" enum="TextureRect.ExpandMode" default="0">
+ <member name="expand_mode" type="int" setter="set_expand_mode" getter="get_expand_mode" enum="TextureRect.ExpandMode" default="0" is_experimental="true">
Defines how minimum size is determined based on the texture's size. See [enum ExpandMode] for options.
+ [b]Note:[/b] Using [constant EXPAND_FIT_WIDTH], [constant EXPAND_FIT_WIDTH_PROPORTIONAL], [constant EXPAND_FIT_HEIGHT] or [constant EXPAND_FIT_HEIGHT_PROPORTIONAL] may result in unstable behavior in some containers. This functionality is being re-evaluated and will change in the future.
</member>
<member name="flip_h" type="bool" setter="set_flip_h" getter="is_flipped_h" default="false">
If [code]true[/code], texture is flipped horizontally.
diff --git a/doc/classes/VisibleOnScreenEnabler2D.xml b/doc/classes/VisibleOnScreenEnabler2D.xml
index 8590e9cc9f..68e510a6dc 100644
--- a/doc/classes/VisibleOnScreenEnabler2D.xml
+++ b/doc/classes/VisibleOnScreenEnabler2D.xml
@@ -24,7 +24,7 @@
Corresponds to [constant Node.PROCESS_MODE_ALWAYS].
</constant>
<constant name="ENABLE_MODE_WHEN_PAUSED" value="2" enum="EnableMode">
- Corresponds to [constant Node.PROCESS_MODE_WHEN_PAUSED.
+ Corresponds to [constant Node.PROCESS_MODE_WHEN_PAUSED].
</constant>
</constants>
</class>
diff --git a/doc/classes/XRInterface.xml b/doc/classes/XRInterface.xml
index db65ce62f2..cdada35970 100644
--- a/doc/classes/XRInterface.xml
+++ b/doc/classes/XRInterface.xml
@@ -210,7 +210,7 @@
This interface supports quad rendering (not yet supported by Godot).
</constant>
<constant name="XR_VR" value="8" enum="Capabilities">
- this interface supports VR.
+ This interface supports VR.
</constant>
<constant name="XR_AR" value="16" enum="Capabilities">
This interface supports AR (video background and real world tracking).
diff --git a/drivers/alsa/SCsub b/drivers/alsa/SCsub
index 1d76bb18c4..f17acb0f91 100644
--- a/drivers/alsa/SCsub
+++ b/drivers/alsa/SCsub
@@ -3,6 +3,7 @@
Import("env")
if "alsa" in env and env["alsa"]:
- env.add_source_files(env.drivers_sources, "asound-so_wrap.c")
+ if env["use_sowrap"]:
+ env.add_source_files(env.drivers_sources, "asound-so_wrap.c")
env.add_source_files(env.drivers_sources, "*.cpp")
diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp
index 20cd8dd26c..689f76389b 100644
--- a/drivers/alsa/audio_driver_alsa.cpp
+++ b/drivers/alsa/audio_driver_alsa.cpp
@@ -37,7 +37,7 @@
#include <errno.h>
-#ifdef PULSEAUDIO_ENABLED
+#if defined(PULSEAUDIO_ENABLED) && defined(SOWRAP_ENABLED)
extern "C" {
extern int initialize_pulse(int verbose);
}
@@ -153,6 +153,7 @@ Error AudioDriverALSA::init_output_device() {
}
Error AudioDriverALSA::init() {
+#ifdef SOWRAP_ENABLED
#ifdef DEBUG_ENABLED
int dylibloader_verbose = 1;
#else
@@ -167,7 +168,7 @@ Error AudioDriverALSA::init() {
if (initialize_asound(dylibloader_verbose)) {
return ERR_CANT_OPEN;
}
-
+#endif
active.clear();
exit_thread.clear();
diff --git a/drivers/alsa/audio_driver_alsa.h b/drivers/alsa/audio_driver_alsa.h
index 821ba1d145..b62d7188dd 100644
--- a/drivers/alsa/audio_driver_alsa.h
+++ b/drivers/alsa/audio_driver_alsa.h
@@ -38,7 +38,11 @@
#include "core/templates/safe_refcount.h"
#include "servers/audio_server.h"
+#ifdef SOWRAP_ENABLED
#include "asound-so_wrap.h"
+#else
+#include <alsa/asoundlib.h>
+#endif
class AudioDriverALSA : public AudioDriver {
Thread thread;
diff --git a/drivers/alsamidi/midi_driver_alsamidi.h b/drivers/alsamidi/midi_driver_alsamidi.h
index 3c6300411c..80cc96310f 100644
--- a/drivers/alsamidi/midi_driver_alsamidi.h
+++ b/drivers/alsamidi/midi_driver_alsamidi.h
@@ -39,7 +39,12 @@
#include "core/templates/safe_refcount.h"
#include "core/templates/vector.h"
+#ifdef SOWRAP_ENABLED
#include "../alsa/asound-so_wrap.h"
+#else
+#include <alsa/asoundlib.h>
+#endif
+
#include <stdio.h>
class MIDIDriverALSAMidi : public MIDIDriver {
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 1a18f35e64..6cc6b8224c 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -1895,6 +1895,10 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
glViewport(0, 0, rb->width, rb->height);
+ glCullFace(GL_BACK);
+ glEnable(GL_CULL_FACE);
+ scene_state.cull_mode = GLES3::SceneShaderData::CULL_BACK;
+
// Do depth prepass if it's explicitly enabled
bool use_depth_prepass = config->use_depth_prepass;
@@ -1910,9 +1914,6 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDisable(GL_SCISSOR_TEST);
- glCullFace(GL_BACK);
- glEnable(GL_CULL_FACE);
- scene_state.cull_mode = GLES3::SceneShaderData::CULL_BACK;
glColorMask(0, 0, 0, 0);
glClearDepth(1.0f);
diff --git a/drivers/gles3/shaders/stdlib_inc.glsl b/drivers/gles3/shaders/stdlib_inc.glsl
index 0b76c4334a..92bf2d87e4 100644
--- a/drivers/gles3/shaders/stdlib_inc.glsl
+++ b/drivers/gles3/shaders/stdlib_inc.glsl
@@ -14,11 +14,7 @@ uint float2half(uint f) {
uint half2float(uint h) {
uint h_e = h & uint(0x7c00);
- if (h_e == uint(0x0000)) {
- return uint(0);
- } else {
- return ((h & uint(0x8000)) << uint(16)) | ((h_e + uint(0x1c000)) << uint(13)) | ((h & uint(0x03ff)) << uint(13));
- }
+ return ((h & uint(0x8000)) << uint(16)) | uint((h_e >> uint(10)) != uint(0)) * (((h_e + uint(0x1c000)) << uint(13)) | ((h & uint(0x03ff)) << uint(13)));
}
uint packHalf2x16(vec2 v) {
diff --git a/drivers/pulseaudio/SCsub b/drivers/pulseaudio/SCsub
index 467d1448dc..f48489d787 100644
--- a/drivers/pulseaudio/SCsub
+++ b/drivers/pulseaudio/SCsub
@@ -3,6 +3,7 @@
Import("env")
if "pulseaudio" in env and env["pulseaudio"]:
- env.add_source_files(env.drivers_sources, "pulse-so_wrap.c")
+ if env["use_sowrap"]:
+ env.add_source_files(env.drivers_sources, "pulse-so_wrap.c")
env.add_source_files(env.drivers_sources, "*.cpp")
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
index 0246af4fea..797ffd67fe 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
@@ -37,7 +37,11 @@
#include "core/version.h"
#ifdef ALSAMIDI_ENABLED
+#ifdef SOWRAP_ENABLED
#include "drivers/alsa/asound-so_wrap.h"
+#else
+#include <alsa/asoundlib.h>
+#endif
#endif
void AudioDriverPulseAudio::pa_state_cb(pa_context *c, void *userdata) {
@@ -272,6 +276,7 @@ Error AudioDriverPulseAudio::init_output_device() {
}
Error AudioDriverPulseAudio::init() {
+#ifdef SOWRAP_ENABLED
#ifdef DEBUG_ENABLED
int dylibloader_verbose = 1;
#else
@@ -284,7 +289,7 @@ Error AudioDriverPulseAudio::init() {
if (initialize_pulse(dylibloader_verbose)) {
return ERR_CANT_OPEN;
}
-
+#endif
active.clear();
exit_thread.clear();
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.h b/drivers/pulseaudio/audio_driver_pulseaudio.h
index f4ff44d361..585e882059 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.h
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.h
@@ -38,7 +38,11 @@
#include "core/templates/safe_refcount.h"
#include "servers/audio_server.h"
+#ifdef SOWRAP_ENABLED
#include "pulse-so_wrap.h"
+#else
+#include <pulse/pulseaudio.h>
+#endif
class AudioDriverPulseAudio : public AudioDriver {
Thread thread;
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index 43d3f53904..ee3cb876cf 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -318,6 +318,10 @@ Error FileAccessUnix::_set_unix_permissions(const String &p_file, uint32_t p_per
return FAILED;
}
+void FileAccessUnix::close() {
+ _close();
+}
+
CloseNotificationFunc FileAccessUnix::close_notification_func = nullptr;
FileAccessUnix::~FileAccessUnix() {
diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h
index 884fb9567f..79c4e73636 100644
--- a/drivers/unix/file_access_unix.h
+++ b/drivers/unix/file_access_unix.h
@@ -82,6 +82,8 @@ public:
virtual uint32_t _get_unix_permissions(const String &p_file) override;
virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override;
+ virtual void close() override;
+
FileAccessUnix() {}
virtual ~FileAccessUnix();
};
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index ea40622afc..0e51586b5a 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -375,6 +375,10 @@ Error FileAccessWindows::_set_unix_permissions(const String &p_file, uint32_t p_
return ERR_UNAVAILABLE;
}
+void FileAccessWindows::close() {
+ _close();
+}
+
FileAccessWindows::~FileAccessWindows() {
_close();
}
@@ -391,6 +395,7 @@ void FileAccessWindows::initialize() {
reserved_file_index++;
}
}
+
void FileAccessWindows::finalize() {
invalid_files.clear();
}
diff --git a/drivers/windows/file_access_windows.h b/drivers/windows/file_access_windows.h
index 2b9960d494..453f8d3b5f 100644
--- a/drivers/windows/file_access_windows.h
+++ b/drivers/windows/file_access_windows.h
@@ -82,6 +82,8 @@ public:
virtual uint32_t _get_unix_permissions(const String &p_file) override;
virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override;
+ virtual void close() override;
+
static void initialize();
static void finalize();
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 9f3893a5db..c27417f037 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -1522,6 +1522,8 @@ void AnimationTimelineEdit::set_animation(const Ref<Animation> &p_animation, boo
animation = p_animation;
read_only = p_read_only;
+ length->set_read_only(read_only);
+
if (animation.is_valid()) {
len_hb->show();
if (read_only) {
@@ -6621,7 +6623,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
optimize_dialog = memnew(ConfirmationDialog);
add_child(optimize_dialog);
- optimize_dialog->set_title(TTR("Anim. Optimizer"));
+ optimize_dialog->set_title(TTR("Animation Optimizer"));
VBoxContainer *optimize_vb = memnew(VBoxContainer);
optimize_dialog->add_child(optimize_vb);
@@ -6630,19 +6632,19 @@ AnimationTrackEditor::AnimationTrackEditor() {
optimize_velocity_error->set_min(0.001);
optimize_velocity_error->set_step(0.001);
optimize_velocity_error->set_value(0.01);
- optimize_vb->add_margin_child(TTR("Max. Velocity Error:"), optimize_velocity_error);
+ optimize_vb->add_margin_child(TTR("Max Velocity Error:"), optimize_velocity_error);
optimize_angular_error = memnew(SpinBox);
optimize_angular_error->set_max(1.0);
optimize_angular_error->set_min(0.001);
optimize_angular_error->set_step(0.001);
optimize_angular_error->set_value(0.01);
- optimize_vb->add_margin_child(TTR("Max. Angular Error:"), optimize_angular_error);
+ optimize_vb->add_margin_child(TTR("Max Angular Error:"), optimize_angular_error);
optimize_precision_error = memnew(SpinBox);
optimize_precision_error->set_max(6);
optimize_precision_error->set_min(1);
optimize_precision_error->set_step(1);
optimize_precision_error->set_value(3);
- optimize_vb->add_margin_child(TTR("Max. Precision Error:"), optimize_precision_error);
+ optimize_vb->add_margin_child(TTR("Max Precision Error:"), optimize_precision_error);
optimize_dialog->set_ok_button_text(TTR("Optimize"));
optimize_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_OPTIMIZE_ANIMATION_CONFIRM));
@@ -6733,7 +6735,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
//
bake_dialog = memnew(ConfirmationDialog);
- bake_dialog->set_title(TTR("Anim. Baker"));
+ bake_dialog->set_title(TTR("Animation Baker"));
bake_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_BAKE_ANIMATION_CONFIRM));
add_child(bake_dialog);
GridContainer *bake_grid = memnew(GridContainer);
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 97a73d89e7..9a8a1097cd 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -1629,14 +1629,15 @@ void CodeTextEditor::toggle_inline_comment(const String &delimiter) {
int selection_i = 0;
int offset = (is_commented ? -1 : 1) * delimiter.length();
for (const int &c2 : caret_edit_order) {
+ bool is_line_selection = text_editor->has_selection(c2) && text_editor->get_selection_from_line(c2) < text_editor->get_selection_to_line(c2);
if (text_editor->get_caret_line(c2) >= from && text_editor->get_caret_line(c2) <= to) {
int caret_col = caret_cols[caret_i++];
- caret_col += (caret_col == 0) ? 0 : offset;
+ caret_col += (is_line_selection && caret_col == 0) ? 0 : offset;
text_editor->set_caret_column(caret_col, c2 == 0, c2);
}
if (text_editor->has_selection(c2) && text_editor->get_selection_to_line(c2) >= from && text_editor->get_selection_to_line(c2) <= to) {
int from_col = text_editor->get_selection_from_column(c2);
- from_col += (from_col == 0) ? 0 : offset;
+ from_col += (is_line_selection && from_col == 0) ? 0 : offset;
int to_col = selection_to_cols[selection_i++];
to_col += (to_col == 0) ? 0 : offset;
text_editor->select(
diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp
index e4730faf38..b0d6135d52 100644
--- a/editor/debugger/editor_profiler.cpp
+++ b/editor/debugger/editor_profiler.cpp
@@ -624,7 +624,9 @@ EditorProfiler::EditorProfiler() {
hb->add_child(memnew(Label(TTR("Time:"))));
display_time = memnew(OptionButton);
+ // TRANSLATORS: This is an option in the profiler to display the time spent in a function, including the time spent in other functions called by that function.
display_time->add_item(TTR("Inclusive"));
+ // TRANSLATORS: This is an option in the profiler to display the time spent in a function, exincluding the time spent in other functions called by that function.
display_time->add_item(TTR("Self"));
display_time->set_tooltip_text(TTR("Inclusive: Includes time from other functions called by this function.\nUse this to spot bottlenecks.\n\nSelf: Only count the time spent in the function itself, not in other functions called by that function.\nUse this to find individual functions to optimize."));
display_time->connect("item_selected", callable_mp(this, &EditorProfiler::_combo_changed));
diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp
index f4cefc606b..ed7638414c 100644
--- a/editor/editor_audio_buses.cpp
+++ b/editor/editor_audio_buses.cpp
@@ -1336,6 +1336,8 @@ EditorAudioBuses::EditorAudioBuses() {
add_child(file_dialog);
file_dialog->connect("file_selected", callable_mp(this, &EditorAudioBuses::_file_dialog_callback));
+ AudioServer::get_singleton()->connect("bus_layout_changed", callable_mp(this, &EditorAudioBuses::_update_buses));
+
set_process(true);
}
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index 4a1f0b4c09..80d1e9dcd7 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -472,6 +472,14 @@ void EditorFileDialog::_action_pressed() {
}
}
+ // First check we're not having an empty name.
+ String file_name = file_text.strip_edges().get_file();
+ if (file_name.is_empty()) {
+ error_dialog->set_text(TTR("Cannot save file with an empty filename."));
+ error_dialog->popup_centered(Size2(250, 80) * EDSCALE);
+ return;
+ }
+
// Add first extension of filter if no valid extension is found.
if (!valid) {
int idx = filter->get_selected();
@@ -480,9 +488,15 @@ void EditorFileDialog::_action_pressed() {
f += "." + ext;
}
+ if (file_name.begins_with(".")) { // Could still happen if typed manually.
+ error_dialog->set_text(TTR("Cannot save file with a name starting with a dot."));
+ error_dialog->popup_centered(Size2(250, 80) * EDSCALE);
+ return;
+ }
+
if (dir_access->file_exists(f) && !disable_overwrite_warning) {
- confirm_save->set_text(TTR("File exists, overwrite?"));
- confirm_save->popup_centered(Size2(200, 80));
+ confirm_save->set_text(vformat(TTR("File \"%s\" already exists.\nDo you want to overwrite it?"), f));
+ confirm_save->popup_centered(Size2(250, 80) * EDSCALE);
} else {
_save_to_recent();
hide();
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index 01d3428c9e..36462f6805 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -705,7 +705,7 @@ void EditorProperty::gui_input(const Ref<InputEvent> &p_event) {
bool is_valid_revert = false;
Variant revert_value = EditorPropertyRevert::get_property_revert_value(object, property, &is_valid_revert);
ERR_FAIL_COND(!is_valid_revert);
- emit_changed(property, revert_value);
+ emit_changed(_get_revert_property(), revert_value);
update_property();
}
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index 3bd18736f8..801f1ca5b6 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -4181,9 +4181,12 @@ struct EditorPropertyRangeHint {
bool radians = false;
};
-static EditorPropertyRangeHint _parse_range_hint(PropertyHint p_hint, const String &p_hint_text, double p_default_step) {
+static EditorPropertyRangeHint _parse_range_hint(PropertyHint p_hint, const String &p_hint_text, double p_default_step, bool is_int = false) {
EditorPropertyRangeHint hint;
hint.step = p_default_step;
+ if (is_int) {
+ hint.hide_slider = false; // Always show slider for ints, unless specified in hint range.
+ }
Vector<String> slices = p_hint_text.split(",");
if (p_hint == PROPERTY_HINT_RANGE) {
ERR_FAIL_COND_V_MSG(slices.size() < 2, hint,
@@ -4301,7 +4304,7 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
} else {
EditorPropertyInteger *editor = memnew(EditorPropertyInteger);
- EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1);
+ EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1, true);
editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.or_greater, hint.or_less, hint.suffix);
return editor;
@@ -4390,7 +4393,7 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
} break;
case Variant::VECTOR2I: {
EditorPropertyVector2i *editor = memnew(EditorPropertyVector2i(p_wide));
- EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1);
+ EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1, true);
editor->setup(hint.min, hint.max, p_hint == PROPERTY_HINT_LINK, hint.suffix);
return editor;
@@ -4403,7 +4406,7 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
} break;
case Variant::RECT2I: {
EditorPropertyRect2i *editor = memnew(EditorPropertyRect2i(p_wide));
- EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1);
+ EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1, true);
editor->setup(hint.min, hint.max, hint.suffix);
return editor;
@@ -4417,7 +4420,7 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
} break;
case Variant::VECTOR3I: {
EditorPropertyVector3i *editor = memnew(EditorPropertyVector3i(p_wide));
- EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1);
+ EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1, true);
editor->setup(hint.min, hint.max, p_hint == PROPERTY_HINT_LINK, hint.suffix);
return editor;
@@ -4431,7 +4434,7 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
} break;
case Variant::VECTOR4I: {
EditorPropertyVector4i *editor = memnew(EditorPropertyVector4i);
- EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1);
+ EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1, true);
editor->setup(hint.min, hint.max, hint.suffix);
return editor;
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 6410821dcf..304a7acff1 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -509,6 +509,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
const Color font_disabled_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.35);
const Color font_readonly_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.65);
const Color font_placeholder_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.6);
+ const Color font_outline_color = Color(0, 0, 0, 0);
const Color selection_color = accent_color * Color(1, 1, 1, 0.4);
const Color disabled_color = mono_color.inverted().lerp(base_color, 0.7);
const Color disabled_bg_color = mono_color.inverted().lerp(base_color, 0.9);
@@ -816,6 +817,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
style_write_movie_button->set_expand_margin(SIDE_RIGHT, 2 * EDSCALE);
theme->set_stylebox("MovieWriterButtonPressed", "EditorStyles", style_write_movie_button);
+ // MenuButton
theme->set_stylebox("normal", "MenuButton", style_menu);
theme->set_stylebox("hover", "MenuButton", style_widget_hover);
theme->set_stylebox("pressed", "MenuButton", style_menu);
@@ -826,6 +828,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("font_hover_color", "MenuButton", font_hover_color);
theme->set_color("font_hover_pressed_color", "MenuButton", font_hover_pressed_color);
theme->set_color("font_focus_color", "MenuButton", font_focus_color);
+ theme->set_color("font_outline_color", "MenuButton", font_outline_color);
+
+ theme->set_constant("outline_size", "MenuButton", 0 * EDSCALE);
theme->set_stylebox("MenuHover", "EditorStyles", style_widget_hover);
@@ -842,6 +847,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("font_focus_color", "Button", font_focus_color);
theme->set_color("font_pressed_color", "Button", accent_color);
theme->set_color("font_disabled_color", "Button", font_disabled_color);
+ theme->set_color("font_outline_color", "Button", font_outline_color);
theme->set_color("icon_normal_color", "Button", icon_normal_color);
theme->set_color("icon_hover_color", "Button", icon_hover_color);
@@ -849,6 +855,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("icon_pressed_color", "Button", icon_pressed_color);
theme->set_color("icon_disabled_color", "Button", icon_disabled_color);
+ theme->set_constant("outline_size", "Button", 0 * EDSCALE);
+
const float ACTION_BUTTON_EXTRA_MARGIN = 32 * EDSCALE;
theme->set_type_variation("InspectorActionButton", "Button");
@@ -895,6 +903,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("font_focus_color", "MenuBar", font_focus_color);
theme->set_color("font_pressed_color", "MenuBar", accent_color);
theme->set_color("font_disabled_color", "MenuBar", font_disabled_color);
+ theme->set_color("font_outline_color", "MenuBar", font_outline_color);
theme->set_color("icon_normal_color", "MenuBar", icon_normal_color);
theme->set_color("icon_hover_color", "MenuBar", icon_hover_color);
@@ -902,6 +911,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("icon_pressed_color", "MenuBar", icon_pressed_color);
theme->set_color("icon_disabled_color", "MenuBar", icon_disabled_color);
+ theme->set_constant("outline_size", "MenuBar", 0 * EDSCALE);
+
// OptionButton
Ref<StyleBoxFlat> style_option_button_focus = style_widget_focus->duplicate();
Ref<StyleBoxFlat> style_option_button_normal = style_widget->duplicate();
@@ -932,6 +943,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("font_focus_color", "OptionButton", font_focus_color);
theme->set_color("font_pressed_color", "OptionButton", accent_color);
theme->set_color("font_disabled_color", "OptionButton", font_disabled_color);
+ theme->set_color("font_outline_color", "OptionButton", font_outline_color);
theme->set_color("icon_normal_color", "OptionButton", icon_normal_color);
theme->set_color("icon_hover_color", "OptionButton", icon_hover_color);
@@ -943,6 +955,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_constant("arrow_margin", "OptionButton", widget_default_margin.x - 2 * EDSCALE);
theme->set_constant("modulate_arrow", "OptionButton", true);
theme->set_constant("h_separation", "OptionButton", 4 * EDSCALE);
+ theme->set_constant("outline_size", "OptionButton", 0 * EDSCALE);
// CheckButton
theme->set_stylebox("normal", "CheckButton", style_menu);
@@ -967,6 +980,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("font_focus_color", "CheckButton", font_focus_color);
theme->set_color("font_pressed_color", "CheckButton", accent_color);
theme->set_color("font_disabled_color", "CheckButton", font_disabled_color);
+ theme->set_color("font_outline_color", "CheckButton", font_outline_color);
theme->set_color("icon_normal_color", "CheckButton", icon_normal_color);
theme->set_color("icon_hover_color", "CheckButton", icon_hover_color);
@@ -976,6 +990,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_constant("h_separation", "CheckButton", 8 * EDSCALE);
theme->set_constant("check_v_offset", "CheckButton", 0 * EDSCALE);
+ theme->set_constant("outline_size", "CheckButton", 0 * EDSCALE);
// Checkbox
Ref<StyleBoxFlat> sb_checkbox = style_menu->duplicate();
@@ -1001,6 +1016,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("font_focus_color", "CheckBox", font_focus_color);
theme->set_color("font_pressed_color", "CheckBox", accent_color);
theme->set_color("font_disabled_color", "CheckBox", font_disabled_color);
+ theme->set_color("font_outline_color", "CheckBox", font_outline_color);
theme->set_color("icon_normal_color", "CheckBox", icon_normal_color);
theme->set_color("icon_hover_color", "CheckBox", icon_hover_color);
@@ -1010,6 +1026,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_constant("h_separation", "CheckBox", 8 * EDSCALE);
theme->set_constant("check_v_offset", "CheckBox", 0 * EDSCALE);
+ theme->set_constant("outline_size", "CheckBox", 0 * EDSCALE);
// PopupDialog
theme->set_stylebox("panel", "PopupDialog", style_popup);
@@ -1043,6 +1060,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("font_accelerator_color", "PopupMenu", font_disabled_color);
theme->set_color("font_disabled_color", "PopupMenu", font_disabled_color);
theme->set_color("font_separator_color", "PopupMenu", font_disabled_color);
+ theme->set_color("font_outline_color", "PopupMenu", font_outline_color);
theme->set_icon("checked", "PopupMenu", theme->get_icon(SNAME("GuiChecked"), SNAME("EditorIcons")));
theme->set_icon("unchecked", "PopupMenu", theme->get_icon(SNAME("GuiUnchecked"), SNAME("EditorIcons")));
theme->set_icon("radio_checked", "PopupMenu", theme->get_icon(SNAME("GuiRadioChecked"), SNAME("EditorIcons")));
@@ -1063,6 +1081,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
const int vsep_base = extra_spacing + default_margin_size + 6;
const int force_even_vsep = vsep_base + (vsep_base % 2);
theme->set_constant("v_separation", "PopupMenu", force_even_vsep * EDSCALE);
+ theme->set_constant("outline_size", "PopupMenu", 0 * EDSCALE);
theme->set_constant("item_start_padding", "PopupMenu", default_margin_size * 1.5 * EDSCALE);
theme->set_constant("item_end_padding", "PopupMenu", default_margin_size * 1.5 * EDSCALE);
@@ -1171,6 +1190,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("custom_button_font_highlight", "Tree", font_hover_color);
theme->set_color("font_color", "Tree", font_color);
theme->set_color("font_selected_color", "Tree", mono_color);
+ theme->set_color("font_outline_color", "Tree", font_outline_color);
theme->set_color("title_button_color", "Tree", font_color);
theme->set_color("drop_position_color", "Tree", accent_color);
theme->set_constant("v_separation", "Tree", widget_default_margin.y - EDSCALE);
@@ -1180,6 +1200,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_constant("button_margin", "Tree", default_margin_size * EDSCALE);
theme->set_constant("scroll_border", "Tree", 40 * EDSCALE);
theme->set_constant("scroll_speed", "Tree", 12);
+ theme->set_constant("outline_size", "Tree", 0 * EDSCALE);
const Color guide_color = mono_color * Color(1, 1, 1, 0.05);
Color relationship_line_color = mono_color * Color(1, 1, 1, relationship_line_opacity);
@@ -1269,11 +1290,13 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("selected", "ItemList", style_tree_selected);
theme->set_color("font_color", "ItemList", font_color);
theme->set_color("font_selected_color", "ItemList", mono_color);
+ theme->set_color("font_outline_color", "ItemList", font_outline_color);
theme->set_color("guide_color", "ItemList", guide_color);
theme->set_constant("v_separation", "ItemList", force_even_vsep * 0.5 * EDSCALE);
theme->set_constant("h_separation", "ItemList", 6 * EDSCALE);
theme->set_constant("icon_margin", "ItemList", 6 * EDSCALE);
theme->set_constant("line_separation", "ItemList", 3 * EDSCALE);
+ theme->set_constant("outline_size", "ItemList", 0 * EDSCALE);
// TabBar & TabContainer
Ref<StyleBoxFlat> style_tabbar_background = make_flat_stylebox(dark_color_1, 0, 0, 0, 0, corner_radius * EDSCALE);
@@ -1291,8 +1314,10 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("button_highlight", "TabBar", style_menu);
theme->set_color("font_selected_color", "TabContainer", font_color);
theme->set_color("font_unselected_color", "TabContainer", font_disabled_color);
+ theme->set_color("font_outline_color", "TabContainer", font_outline_color);
theme->set_color("font_selected_color", "TabBar", font_color);
theme->set_color("font_unselected_color", "TabBar", font_disabled_color);
+ theme->set_color("font_outline_color", "TabBar", font_outline_color);
theme->set_color("drop_mark_color", "TabContainer", tab_highlight);
theme->set_color("drop_mark_color", "TabBar", tab_highlight);
theme->set_icon("menu", "TabContainer", theme->get_icon(SNAME("GuiTabMenu"), SNAME("EditorIcons")));
@@ -1309,7 +1334,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_icon("drop_mark", "TabContainer", theme->get_icon(SNAME("GuiTabDropMark"), SNAME("EditorIcons")));
theme->set_icon("drop_mark", "TabBar", theme->get_icon(SNAME("GuiTabDropMark"), SNAME("EditorIcons")));
theme->set_constant("side_margin", "TabContainer", 0);
+ theme->set_constant("outline_size", "TabContainer", 0 * EDSCALE);
theme->set_constant("h_separation", "TabBar", 4 * EDSCALE);
+ theme->set_constant("outline_size", "TabBar", 0 * EDSCALE);
// Content of each tab.
Ref<StyleBoxFlat> style_content_panel = style_default->duplicate();
@@ -1400,10 +1427,12 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("font_selected_color", "LineEdit", mono_color);
theme->set_color("font_uneditable_color", "LineEdit", font_readonly_color);
theme->set_color("font_placeholder_color", "LineEdit", font_placeholder_color);
+ theme->set_color("font_outline_color", "LineEdit", font_outline_color);
theme->set_color("caret_color", "LineEdit", font_color);
theme->set_color("selection_color", "LineEdit", selection_color);
theme->set_color("clear_button_color", "LineEdit", font_color);
theme->set_color("clear_button_color_pressed", "LineEdit", accent_color);
+ theme->set_constant("outline_size", "LineEdit", 0 * EDSCALE);
// TextEdit
theme->set_stylebox("normal", "TextEdit", style_line_edit);
@@ -1414,9 +1443,11 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("font_color", "TextEdit", font_color);
theme->set_color("font_readonly_color", "TextEdit", font_readonly_color);
theme->set_color("font_placeholder_color", "TextEdit", font_placeholder_color);
+ theme->set_color("font_outline_color", "TextEdit", font_outline_color);
theme->set_color("caret_color", "TextEdit", font_color);
theme->set_color("selection_color", "TextEdit", selection_color);
theme->set_constant("line_spacing", "TextEdit", 4 * EDSCALE);
+ theme->set_constant("outline_size", "TextEdit", 0 * EDSCALE);
theme->set_icon("h_grabber", "SplitContainer", theme->get_icon(SNAME("GuiHsplitter"), SNAME("EditorIcons")));
theme->set_icon("v_grabber", "SplitContainer", theme->get_icon(SNAME("GuiVsplitter"), SNAME("EditorIcons")));
@@ -1549,9 +1580,11 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// RichTextLabel
theme->set_color("default_color", "RichTextLabel", font_color);
theme->set_color("font_shadow_color", "RichTextLabel", Color(0, 0, 0, 0));
+ theme->set_color("font_outline_color", "RichTextLabel", font_outline_color);
theme->set_constant("shadow_offset_x", "RichTextLabel", 1 * EDSCALE);
theme->set_constant("shadow_offset_y", "RichTextLabel", 1 * EDSCALE);
theme->set_constant("shadow_outline_size", "RichTextLabel", 1 * EDSCALE);
+ theme->set_constant("outline_size", "RichTextLabel", 0 * EDSCALE);
theme->set_stylebox("focus", "RichTextLabel", make_empty_stylebox());
theme->set_stylebox("normal", "RichTextLabel", style_tree_bg);
@@ -1590,10 +1623,12 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("normal", "Label", style_empty);
theme->set_color("font_color", "Label", font_color);
theme->set_color("font_shadow_color", "Label", Color(0, 0, 0, 0));
+ theme->set_color("font_outline_color", "Label", font_outline_color);
theme->set_constant("shadow_offset_x", "Label", 1 * EDSCALE);
theme->set_constant("shadow_offset_y", "Label", 1 * EDSCALE);
theme->set_constant("shadow_outline_size", "Label", 1 * EDSCALE);
theme->set_constant("line_spacing", "Label", 3 * EDSCALE);
+ theme->set_constant("outline_size", "Label", 0 * EDSCALE);
// LinkButton
theme->set_stylebox("focus", "LinkButton", style_empty);
@@ -1603,6 +1638,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("font_focus_color", "LinkButton", font_focus_color);
theme->set_color("font_pressed_color", "LinkButton", accent_color);
theme->set_color("font_disabled_color", "LinkButton", font_disabled_color);
+ theme->set_color("font_outline_color", "LinkButton", font_outline_color);
+
+ theme->set_constant("outline_size", "LinkButton", 0 * EDSCALE);
// TooltipPanel + TooltipLabel
// TooltipPanel is also used for custom tooltips, while TooltipLabel
@@ -1638,6 +1676,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("background", "ProgressBar", make_stylebox(theme->get_icon(SNAME("GuiProgressBar"), SNAME("EditorIcons")), 4, 4, 4, 4, 0, 0, 0, 0));
theme->set_stylebox("fill", "ProgressBar", make_stylebox(theme->get_icon(SNAME("GuiProgressFill"), SNAME("EditorIcons")), 6, 6, 6, 6, 2, 1, 2, 1));
theme->set_color("font_color", "ProgressBar", font_color);
+ theme->set_color("font_outline_color", "ProgressBar", font_outline_color);
+ theme->set_constant("outline_size", "ProgressBar", 0 * EDSCALE);
// GraphEdit
theme->set_stylebox("bg", "GraphEdit", style_tree_bg);
diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp
index 96a8cc8b91..fe3c2333ed 100644
--- a/editor/export/editor_export_platform.cpp
+++ b/editor/export/editor_export_platform.cpp
@@ -247,7 +247,8 @@ Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_pa
pd->file_ofs.push_back(sd);
- if (pd->ep->step(TTR("Storing File:") + " " + p_path, 2 + p_file * 100 / p_total, false)) {
+ // TRANSLATORS: This is an editor progress label describing the storing of a file.
+ if (pd->ep->step(vformat(TTR("Storing File: %s"), p_path), 2 + p_file * 100 / p_total, false)) {
return ERR_SKIP;
}
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index d0f04cb46f..32c16255dd 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -2267,6 +2267,7 @@ Node *ResourceImporterScene::pre_import(const String &p_source_file, const HashM
Ref<EditorSceneFormatImporter> importer;
String ext = p_source_file.get_extension().to_lower();
+ // TRANSLATORS: This is an editor progress label.
EditorProgress progress("pre-import", TTR("Pre-Import Scene"), 0);
progress.step(TTR("Importing Scene..."), 0);
diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp
index 6eebb84216..348aad1162 100644
--- a/editor/import/scene_import_settings.cpp
+++ b/editor/import/scene_import_settings.cpp
@@ -142,24 +142,23 @@ void SceneImportSettings::_fill_material(Tree *p_tree, const Ref<Material> &p_ma
String import_id;
bool has_import_id = false;
- bool created = false;
- if (!material_set.has(p_material)) {
- material_set.insert(p_material);
- created = true;
- }
-
if (p_material->has_meta("import_id")) {
import_id = p_material->get_meta("import_id");
has_import_id = true;
} else if (!p_material->get_name().is_empty()) {
import_id = p_material->get_name();
has_import_id = true;
+ } else if (unnamed_material_name_map.has(p_material)) {
+ import_id = unnamed_material_name_map[p_material];
} else {
- import_id = "@MATERIAL:" + itos(material_set.size() - 1);
+ import_id = "@MATERIAL:" + itos(material_map.size());
+ unnamed_material_name_map[p_material] = import_id;
}
+ bool created = false;
if (!material_map.has(import_id)) {
MaterialData md;
+ created = true;
md.has_import_id = has_import_id;
md.material = p_material;
@@ -169,6 +168,7 @@ void SceneImportSettings::_fill_material(Tree *p_tree, const Ref<Material> &p_ma
}
MaterialData &material_data = material_map[import_id];
+ ERR_FAIL_COND(p_material != material_data.material);
Ref<Texture2D> icon = get_theme_icon(SNAME("StandardMaterial3D"), SNAME("EditorIcons"));
@@ -564,10 +564,10 @@ void SceneImportSettings::open_settings(const String &p_path, bool p_for_animati
base_path = p_path;
- material_set.clear();
mesh_set.clear();
animation_map.clear();
material_map.clear();
+ unnamed_material_name_map.clear();
mesh_map.clear();
node_map.clear();
defaults.clear();
diff --git a/editor/import/scene_import_settings.h b/editor/import/scene_import_settings.h
index 69bf58b627..d65bb1404a 100644
--- a/editor/import/scene_import_settings.h
+++ b/editor/import/scene_import_settings.h
@@ -107,6 +107,7 @@ class SceneImportSettings : public ConfirmationDialog {
HashMap<StringName, Variant> settings;
};
HashMap<String, MaterialData> material_map;
+ HashMap<Ref<Material>, String> unnamed_material_name_map;
struct MeshData {
bool has_import_id;
@@ -141,7 +142,6 @@ class SceneImportSettings : public ConfirmationDialog {
void _fill_scene(Node *p_node, TreeItem *p_parent_item);
HashSet<Ref<Mesh>> mesh_set;
- HashSet<Ref<Material>> material_set;
String selected_type;
String selected_id;
diff --git a/editor/input_event_configuration_dialog.cpp b/editor/input_event_configuration_dialog.cpp
index fb450a41d3..c620858439 100644
--- a/editor/input_event_configuration_dialog.cpp
+++ b/editor/input_event_configuration_dialog.cpp
@@ -538,6 +538,8 @@ void InputEventConfigurationDialog::_notification(int p_what) {
icon_cache.joypad_button = get_theme_icon(SNAME("JoyButton"), SNAME("EditorIcons"));
icon_cache.joypad_axis = get_theme_icon(SNAME("JoyAxis"), SNAME("EditorIcons"));
+ event_as_text->add_theme_font_override("font", get_theme_font(SNAME("bold"), SNAME("EditorFonts")));
+
_update_input_list();
} break;
}
@@ -591,7 +593,6 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
event_as_text = memnew(Label);
event_as_text->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
event_as_text->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
- event_as_text->add_theme_font_override("font", get_theme_font(SNAME("bold"), SNAME("EditorFonts")));
event_as_text->add_theme_font_size_override("font_size", 18 * EDSCALE);
main_vbox->add_child(event_as_text);
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index b33ad67f23..c5bfd968d7 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -1134,6 +1134,7 @@ void AnimationPlayerEditor::_animation_duplicate() {
name_dialog_op = TOOL_DUPLICATE_ANIM;
name_dialog->set_title(TTR("Duplicate Animation"));
+ // TRANSLATORS: This is a label for the new name field in the "Duplicate Animation" dialog.
name_title->set_text(TTR("Duplicated Animation Name:"));
name->set_text(new_name);
name_dialog->popup_centered(Size2(300, 90));
diff --git a/editor/plugins/cast_2d_editor_plugin.cpp b/editor/plugins/cast_2d_editor_plugin.cpp
index 723082c293..331b4749cc 100644
--- a/editor/plugins/cast_2d_editor_plugin.cpp
+++ b/editor/plugins/cast_2d_editor_plugin.cpp
@@ -78,7 +78,7 @@ bool Cast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
}
} else if (pressed) {
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Set target_position"));
+ undo_redo->create_action(TTR("Set Target Position"));
undo_redo->add_do_property(node, "target_position", target_position);
undo_redo->add_do_method(canvas_item_editor, "update_viewport");
undo_redo->add_undo_property(node, "target_position", original_target_position);
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index fc1d8936d5..96f5aeedf0 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -1666,6 +1666,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
} break;
case TRANSFORM_Z_AXIS: {
_edit.plane = TRANSFORM_VIEW;
+ // TRANSLATORS: This refers to the transform of the view plane.
set_message(TTR("View Plane Transform."), 2);
} break;
@@ -4956,6 +4957,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p
view_menu->get_popup()->add_separator();
view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_lock_rotation", TTR("Lock View Rotation")), VIEW_LOCK_ROTATION);
view_menu->get_popup()->add_separator();
+ // TRANSLATORS: "Normal" as in "normal life", not "normal vector".
view_menu->get_popup()->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_normal", TTR("Display Normal")), VIEW_DISPLAY_NORMAL);
view_menu->get_popup()->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_wireframe", TTR("Display Wireframe")), VIEW_DISPLAY_WIREFRAME);
view_menu->get_popup()->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_overdraw", TTR("Display Overdraw")), VIEW_DISPLAY_OVERDRAW);
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 6d747ba6a8..ccbc7c3d74 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -2518,7 +2518,7 @@ void ScriptEditor::save_all_scripts() {
} else {
// For built-in scripts, save their scenes instead.
const String scene_path = edited_res->get_path().get_slice("::", 0);
- if (!scenes_to_save.has(scene_path)) {
+ if (!scene_path.is_empty() && !scenes_to_save.has(scene_path)) {
scenes_to_save.push_back(scene_path);
}
}
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index 073adb467a..2519928ea3 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -3223,6 +3223,7 @@ void ThemeTypeEditor::_update_stylebox_from_leading() {
if (!leading_stylebox.pinned || leading_stylebox.stylebox.is_null()) {
return;
}
+ ERR_FAIL_COND_MSG(edited_theme.is_null(), "Leading stylebox does not have an edited theme to update");
// Prevent changes from immediately being reported while the operation is still ongoing.
edited_theme->_freeze_change_propagation();
@@ -3706,7 +3707,11 @@ void ThemeEditorPlugin::edit(Object *p_node) {
if (Object::cast_to<Theme>(p_node)) {
theme_editor->edit(Object::cast_to<Theme>(p_node));
} else {
- theme_editor->edit(Ref<Theme>());
+ // We intentionally keep a reference to the last used theme to work around
+ // the the editor being hidden while base resources are edited. Uncomment
+ // the following line again and remove this comment once that bug has been
+ // fixed (scheduled for Godot 4.1 in PR 73098):
+ // theme_editor->edit(Ref<Theme>());
}
}
diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp
index 04a09a97e7..4d9e2db682 100644
--- a/editor/plugins/tiles/tile_map_editor.cpp
+++ b/editor/plugins/tiles/tile_map_editor.cpp
@@ -2055,7 +2055,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
select_tool_button->set_flat(true);
select_tool_button->set_toggle_mode(true);
select_tool_button->set_button_group(tool_buttons_group);
- select_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/selection_tool", "Selection", Key::S));
+ select_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/selection_tool", TTR("Selection"), Key::S));
select_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar));
tilemap_tiles_tools_buttons->add_child(select_tool_button);
@@ -2063,7 +2063,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
paint_tool_button->set_flat(true);
paint_tool_button->set_toggle_mode(true);
paint_tool_button->set_button_group(tool_buttons_group);
- paint_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/paint_tool", "Paint", Key::D));
+ paint_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/paint_tool", TTR("Paint"), Key::D));
paint_tool_button->set_tooltip_text(TTR("Shift: Draw line.") + "\n" + TTR("Shift+Ctrl: Draw rectangle."));
paint_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar));
tilemap_tiles_tools_buttons->add_child(paint_tool_button);
@@ -2072,7 +2072,8 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
line_tool_button->set_flat(true);
line_tool_button->set_toggle_mode(true);
line_tool_button->set_button_group(tool_buttons_group);
- line_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/line_tool", "Line", Key::L));
+ // TRANSLATORS: This refers to the line tool in the tilemap editor.
+ line_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/line_tool", TTR("Line", "Tool"), Key::L));
line_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar));
tilemap_tiles_tools_buttons->add_child(line_tool_button);
@@ -2080,7 +2081,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
rect_tool_button->set_flat(true);
rect_tool_button->set_toggle_mode(true);
rect_tool_button->set_button_group(tool_buttons_group);
- rect_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/rect_tool", "Rect", Key::R));
+ rect_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/rect_tool", TTR("Rect"), Key::R));
rect_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar));
tilemap_tiles_tools_buttons->add_child(rect_tool_button);
@@ -2088,7 +2089,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
bucket_tool_button->set_flat(true);
bucket_tool_button->set_toggle_mode(true);
bucket_tool_button->set_button_group(tool_buttons_group);
- bucket_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/bucket_tool", "Bucket", Key::B));
+ bucket_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/bucket_tool", TTR("Bucket"), Key::B));
bucket_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar));
tilemap_tiles_tools_buttons->add_child(bucket_tool_button);
toolbar->add_child(tilemap_tiles_tools_buttons);
@@ -2104,7 +2105,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
picker_button = memnew(Button);
picker_button->set_flat(true);
picker_button->set_toggle_mode(true);
- picker_button->set_shortcut(ED_SHORTCUT("tiles_editor/picker", "Picker", Key::P));
+ picker_button->set_shortcut(ED_SHORTCUT("tiles_editor/picker", TTR("Picker"), Key::P));
picker_button->set_tooltip_text(TTR("Alternatively hold Ctrl with other tools to pick tile."));
picker_button->connect("pressed", callable_mp(CanvasItemEditor::get_singleton(), &CanvasItemEditor::update_viewport));
tools_settings->add_child(picker_button);
@@ -2113,7 +2114,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
erase_button = memnew(Button);
erase_button->set_flat(true);
erase_button->set_toggle_mode(true);
- erase_button->set_shortcut(ED_SHORTCUT("tiles_editor/eraser", "Eraser", Key::E));
+ erase_button->set_shortcut(ED_SHORTCUT("tiles_editor/eraser", TTR("Eraser"), Key::E));
erase_button->set_tooltip_text(TTR("Alternatively use RMB to erase tiles."));
erase_button->connect("pressed", callable_mp(CanvasItemEditor::get_singleton(), &CanvasItemEditor::update_viewport));
tools_settings->add_child(erase_button);
@@ -3180,7 +3181,7 @@ void TileMapEditorTerrainsPlugin::_update_terrains_tree() {
terrain_set_tree_item->set_icon(0, main_vbox_container->get_theme_icon(SNAME("TerrainMatchSides"), SNAME("EditorIcons")));
matches = String(TTR("Matches Sides Only"));
}
- terrain_set_tree_item->set_text(0, vformat("Terrain Set %d (%s)", terrain_set_index, matches));
+ terrain_set_tree_item->set_text(0, vformat(TTR("Terrain Set %d (%s)"), terrain_set_index, matches));
terrain_set_tree_item->set_selectable(0, false);
for (int terrain_index = 0; terrain_index < tile_set->get_terrains_count(terrain_set_index); terrain_index++) {
@@ -3329,7 +3330,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() {
main_vbox_container = memnew(VBoxContainer);
main_vbox_container->connect("tree_entered", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_theme));
main_vbox_container->connect("theme_changed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_theme));
- main_vbox_container->set_name("Terrains");
+ main_vbox_container->set_name(TTR("Terrains"));
HSplitContainer *tilemap_tab_terrains = memnew(HSplitContainer);
tilemap_tab_terrains->set_h_size_flags(Control::SIZE_EXPAND_FILL);
@@ -3365,7 +3366,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() {
paint_tool_button->set_toggle_mode(true);
paint_tool_button->set_button_group(tool_buttons_group);
paint_tool_button->set_pressed(true);
- paint_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/paint_tool", "Paint", Key::D));
+ paint_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/paint_tool", TTR("Paint"), Key::D));
paint_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_toolbar));
tilemap_tiles_tools_buttons->add_child(paint_tool_button);
@@ -3373,7 +3374,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() {
line_tool_button->set_flat(true);
line_tool_button->set_toggle_mode(true);
line_tool_button->set_button_group(tool_buttons_group);
- line_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/line_tool", "Line", Key::L));
+ line_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/line_tool", TTR("Line"), Key::L));
line_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_toolbar));
tilemap_tiles_tools_buttons->add_child(line_tool_button);
@@ -3381,7 +3382,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() {
rect_tool_button->set_flat(true);
rect_tool_button->set_toggle_mode(true);
rect_tool_button->set_button_group(tool_buttons_group);
- rect_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/rect_tool", "Rect", Key::R));
+ rect_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/rect_tool", TTR("Rect"), Key::R));
rect_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_toolbar));
tilemap_tiles_tools_buttons->add_child(rect_tool_button);
@@ -3389,7 +3390,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() {
bucket_tool_button->set_flat(true);
bucket_tool_button->set_toggle_mode(true);
bucket_tool_button->set_button_group(tool_buttons_group);
- bucket_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/bucket_tool", "Bucket", Key::B));
+ bucket_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/bucket_tool", TTR("Bucket"), Key::B));
bucket_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_toolbar));
tilemap_tiles_tools_buttons->add_child(bucket_tool_button);
@@ -3406,7 +3407,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() {
picker_button = memnew(Button);
picker_button->set_flat(true);
picker_button->set_toggle_mode(true);
- picker_button->set_shortcut(ED_SHORTCUT("tiles_editor/picker", "Picker", Key::P));
+ picker_button->set_shortcut(ED_SHORTCUT("tiles_editor/picker", TTR("Picker"), Key::P));
picker_button->connect("pressed", callable_mp(CanvasItemEditor::get_singleton(), &CanvasItemEditor::update_viewport));
tools_settings->add_child(picker_button);
@@ -3414,7 +3415,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() {
erase_button = memnew(Button);
erase_button->set_flat(true);
erase_button->set_toggle_mode(true);
- erase_button->set_shortcut(ED_SHORTCUT("tiles_editor/eraser", "Eraser", Key::E));
+ erase_button->set_shortcut(ED_SHORTCUT("tiles_editor/eraser", TTR("Eraser"), Key::E));
erase_button->connect("pressed", callable_mp(CanvasItemEditor::get_singleton(), &CanvasItemEditor::update_viewport));
tools_settings->add_child(erase_button);
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
index e56541b50d..fcefbb7d06 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
@@ -34,6 +34,7 @@
#include "editor/editor_inspector.h"
#include "editor/editor_node.h"
+#include "editor/editor_property_name_processor.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
@@ -106,13 +107,13 @@ bool TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_get(const StringN
void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::NIL, TTR("Atlas"), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY));
- p_list->push_back(PropertyInfo(Variant::INT, "id", PROPERTY_HINT_RANGE, "0," + itos(INT_MAX) + ",1"));
- p_list->push_back(PropertyInfo(Variant::STRING, "name", PROPERTY_HINT_NONE, ""));
- p_list->push_back(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"));
- p_list->push_back(PropertyInfo(Variant::VECTOR2I, "margins", PROPERTY_HINT_NONE, "suffix:px"));
- p_list->push_back(PropertyInfo(Variant::VECTOR2I, "separation", PROPERTY_HINT_NONE));
- p_list->push_back(PropertyInfo(Variant::VECTOR2I, "texture_region_size", PROPERTY_HINT_NONE, "suffix:px"));
- p_list->push_back(PropertyInfo(Variant::BOOL, "use_texture_padding", PROPERTY_HINT_NONE, ""));
+ p_list->push_back(PropertyInfo(Variant::INT, PNAME("id"), PROPERTY_HINT_RANGE, "0," + itos(INT_MAX) + ",1"));
+ p_list->push_back(PropertyInfo(Variant::STRING, PNAME("name")));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, PNAME("texture"), PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2I, PNAME("margins"), PROPERTY_HINT_NONE, "suffix:px"));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2I, PNAME("separation")));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2I, PNAME("texture_region_size"), PROPERTY_HINT_NONE, "suffix:px"));
+ p_list->push_back(PropertyInfo(Variant::BOOL, PNAME("use_texture_padding")));
}
void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_bind_methods() {
@@ -392,11 +393,11 @@ void TileSetAtlasSourceEditor::AtlasTileProxyObject::_get_property_list(List<Pro
if (tiles.size() == 1) {
if (tiles.front()->get().alternative == 0) {
p_list->push_back(PropertyInfo(Variant::NIL, TTR("Base Tile"), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY));
- p_list->push_back(PropertyInfo(Variant::VECTOR2I, "atlas_coords"));
- p_list->push_back(PropertyInfo(Variant::VECTOR2I, "size_in_atlas"));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2I, PNAME("atlas_coords")));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2I, PNAME("size_in_atlas")));
} else {
p_list->push_back(PropertyInfo(Variant::NIL, TTR("Alternative Tile"), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY));
- p_list->push_back(PropertyInfo(Variant::INT, "alternative_id"));
+ p_list->push_back(PropertyInfo(Variant::INT, PNAME("alternative_id")));
}
} else {
p_list->push_back(PropertyInfo(Variant::NIL, TTR("Tiles"), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY));
@@ -413,17 +414,17 @@ void TileSetAtlasSourceEditor::AtlasTileProxyObject::_get_property_list(List<Pro
}
if (all_alternatve_id_zero) {
- p_list->push_back(PropertyInfo(Variant::NIL, "Animation", PROPERTY_HINT_NONE, "animation_", PROPERTY_USAGE_GROUP));
- p_list->push_back(PropertyInfo(Variant::INT, "animation_columns", PROPERTY_HINT_NONE, ""));
- p_list->push_back(PropertyInfo(Variant::VECTOR2I, "animation_separation", PROPERTY_HINT_NONE, ""));
- p_list->push_back(PropertyInfo(Variant::FLOAT, "animation_speed", PROPERTY_HINT_NONE, ""));
- p_list->push_back(PropertyInfo(Variant::INT, "animation_frames_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ARRAY, "Frames,animation_frame_"));
+ p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Animation", "animation_"), PROPERTY_HINT_NONE, "animation_", PROPERTY_USAGE_GROUP));
+ p_list->push_back(PropertyInfo(Variant::INT, PNAME("animation_columns")));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2I, PNAME("animation_separation")));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("animation_speed")));
+ p_list->push_back(PropertyInfo(Variant::INT, PNAME("animation_frames_count"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ARRAY, "Frames,animation_frame_"));
// Not optimal, but returns value for the first tile. This is similar to what MultiNodeEdit does.
if (tile_set_atlas_source->get_tile_animation_frames_count(tiles.front()->get().tile) == 1) {
p_list->push_back(PropertyInfo(Variant::FLOAT, "animation_frame_0/duration", PROPERTY_HINT_NONE, "suffix:s", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY));
} else {
for (int i = 0; i < tile_set_atlas_source->get_tile_animation_frames_count(tiles.front()->get().tile); i++) {
- p_list->push_back(PropertyInfo(Variant::FLOAT, vformat("animation_frame_%d/duration", i), PROPERTY_HINT_NONE, "suffix:s"));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, vformat("animation_frame_%d/%s", i, PNAME("duration")), PROPERTY_HINT_NONE, "suffix:s"));
}
}
}
@@ -641,9 +642,9 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() {
// List of editors.
// --- Rendering ---
- ADD_TILE_DATA_EDITOR_GROUP("Rendering");
+ ADD_TILE_DATA_EDITOR_GROUP(TTR("Rendering"));
- ADD_TILE_DATA_EDITOR(group, "Texture Origin", "texture_origin");
+ ADD_TILE_DATA_EDITOR(group, TTR("Texture Origin"), "texture_origin");
if (!tile_data_editors.has("texture_origin")) {
TileDataTextureOriginEditor *tile_data_texture_origin_editor = memnew(TileDataTextureOriginEditor);
tile_data_texture_origin_editor->hide();
@@ -653,7 +654,7 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() {
tile_data_editors["texture_origin"] = tile_data_texture_origin_editor;
}
- ADD_TILE_DATA_EDITOR(group, "Modulate", "modulate");
+ ADD_TILE_DATA_EDITOR(group, TTR("Modulate"), "modulate");
if (!tile_data_editors.has("modulate")) {
TileDataDefaultEditor *tile_data_modulate_editor = memnew(TileDataDefaultEditor());
tile_data_modulate_editor->hide();
@@ -663,7 +664,7 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() {
tile_data_editors["modulate"] = tile_data_modulate_editor;
}
- ADD_TILE_DATA_EDITOR(group, "Z Index", "z_index");
+ ADD_TILE_DATA_EDITOR(group, TTR("Z Index"), "z_index");
if (!tile_data_editors.has("z_index")) {
TileDataDefaultEditor *tile_data_z_index_editor = memnew(TileDataDefaultEditor());
tile_data_z_index_editor->hide();
@@ -673,7 +674,7 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() {
tile_data_editors["z_index"] = tile_data_z_index_editor;
}
- ADD_TILE_DATA_EDITOR(group, "Y Sort Origin", "y_sort_origin");
+ ADD_TILE_DATA_EDITOR(group, TTR("Y Sort Origin"), "y_sort_origin");
if (!tile_data_editors.has("y_sort_origin")) {
TileDataYSortEditor *tile_data_y_sort_editor = memnew(TileDataYSortEditor);
tile_data_y_sort_editor->hide();
@@ -684,7 +685,7 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() {
}
for (int i = 0; i < tile_set->get_occlusion_layers_count(); i++) {
- ADD_TILE_DATA_EDITOR(group, vformat("Occlusion Layer %d", i), vformat("occlusion_layer_%d", i));
+ ADD_TILE_DATA_EDITOR(group, vformat(TTR("Occlusion Layer %d"), i), vformat("occlusion_layer_%d", i));
if (!tile_data_editors.has(vformat("occlusion_layer_%d", i))) {
TileDataOcclusionShapeEditor *tile_data_occlusion_shape_editor = memnew(TileDataOcclusionShapeEditor());
tile_data_occlusion_shape_editor->hide();
@@ -700,7 +701,7 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() {
}
// --- Rendering ---
- ADD_TILE_DATA_EDITOR(root, "Terrains", "terrain_set");
+ ADD_TILE_DATA_EDITOR(root, TTR("Terrains"), "terrain_set");
if (!tile_data_editors.has("terrain_set")) {
TileDataTerrainsEditor *tile_data_terrains_editor = memnew(TileDataTerrainsEditor);
tile_data_terrains_editor->hide();
@@ -710,7 +711,7 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() {
}
// --- Miscellaneous ---
- ADD_TILE_DATA_EDITOR(root, "Probability", "probability");
+ ADD_TILE_DATA_EDITOR(root, TTR("Probability"), "probability");
if (!tile_data_editors.has("probability")) {
TileDataDefaultEditor *tile_data_probability_editor = memnew(TileDataDefaultEditor());
tile_data_probability_editor->hide();
@@ -721,9 +722,9 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() {
}
// --- Physics ---
- ADD_TILE_DATA_EDITOR_GROUP("Physics");
+ ADD_TILE_DATA_EDITOR_GROUP(TTR("Physics"));
for (int i = 0; i < tile_set->get_physics_layers_count(); i++) {
- ADD_TILE_DATA_EDITOR(group, vformat("Physics Layer %d", i), vformat("physics_layer_%d", i));
+ ADD_TILE_DATA_EDITOR(group, vformat(TTR("Physics Layer %d"), i), vformat("physics_layer_%d", i));
if (!tile_data_editors.has(vformat("physics_layer_%d", i))) {
TileDataCollisionEditor *tile_data_collision_editor = memnew(TileDataCollisionEditor());
tile_data_collision_editor->hide();
@@ -739,9 +740,9 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() {
}
// --- Navigation ---
- ADD_TILE_DATA_EDITOR_GROUP("Navigation");
+ ADD_TILE_DATA_EDITOR_GROUP(TTR("Navigation"));
for (int i = 0; i < tile_set->get_navigation_layers_count(); i++) {
- ADD_TILE_DATA_EDITOR(group, vformat("Navigation Layer %d", i), vformat("navigation_layer_%d", i));
+ ADD_TILE_DATA_EDITOR(group, vformat(TTR("Navigation Layer %d"), i), vformat("navigation_layer_%d", i));
if (!tile_data_editors.has(vformat("navigation_layer_%d", i))) {
TileDataNavigationEditor *tile_data_navigation_editor = memnew(TileDataNavigationEditor());
tile_data_navigation_editor->hide();
@@ -757,14 +758,14 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() {
}
// --- Custom Data ---
- ADD_TILE_DATA_EDITOR_GROUP("Custom Data");
+ ADD_TILE_DATA_EDITOR_GROUP(TTR("Custom Data"));
for (int i = 0; i < tile_set->get_custom_data_layers_count(); i++) {
String editor_name = vformat("custom_data_%d", i);
String prop_name = tile_set->get_custom_data_layer_name(i);
Variant::Type prop_type = tile_set->get_custom_data_layer_type(i);
if (prop_name.is_empty()) {
- ADD_TILE_DATA_EDITOR(group, vformat("Custom Data %d", i), editor_name);
+ ADD_TILE_DATA_EDITOR(group, vformat(TTR("Custom Data %d"), i), editor_name);
} else {
ADD_TILE_DATA_EDITOR(group, prop_name, editor_name);
}
@@ -2414,6 +2415,14 @@ void TileSetAtlasSourceEditor::_notification(int p_what) {
}
}
} break;
+
+ case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
+ if (EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/localize_settings")) {
+ EditorPropertyNameProcessor::Style style = EditorPropertyNameProcessor::get_singleton()->get_settings_style();
+ atlas_source_inspector->set_property_name_style(style);
+ tile_inspector->set_property_name_style(style);
+ }
+ } break;
}
}
@@ -2483,6 +2492,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
tile_inspector->edit(tile_proxy_object);
tile_inspector->set_use_folding(true);
tile_inspector->connect("property_selected", callable_mp(this, &TileSetAtlasSourceEditor::_inspector_property_selected));
+ tile_inspector->set_property_name_style(EditorPropertyNameProcessor::get_singleton()->get_settings_style());
middle_vbox_container->add_child(tile_inspector);
tile_inspector_no_tile_selected_label = memnew(Label);
@@ -2534,6 +2544,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
atlas_source_inspector->set_v_size_flags(SIZE_EXPAND_FILL);
atlas_source_inspector->set_show_categories(true);
atlas_source_inspector->edit(atlas_source_proxy_object);
+ atlas_source_inspector->set_property_name_style(EditorPropertyNameProcessor::get_singleton()->get_settings_style());
middle_vbox_container->add_child(atlas_source_inspector);
// -- Right side --
diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
index cc276597fa..101ec5f66c 100644
--- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
@@ -32,6 +32,7 @@
#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
+#include "editor/editor_property_name_processor.h"
#include "editor/editor_resource_preview.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
@@ -362,6 +363,14 @@ void TileSetScenesCollectionSourceEditor::_notification(int p_what) {
_update_scenes_list();
_update_action_buttons();
} break;
+
+ case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
+ if (EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/localize_settings")) {
+ EditorPropertyNameProcessor::Style style = EditorPropertyNameProcessor::get_singleton()->get_settings_style();
+ scenes_collection_source_inspector->set_property_name_style(style);
+ tile_inspector->set_property_name_style(style);
+ }
+ } break;
}
}
@@ -503,6 +512,7 @@ TileSetScenesCollectionSourceEditor::TileSetScenesCollectionSourceEditor() {
scenes_collection_source_inspector = memnew(EditorInspector);
scenes_collection_source_inspector->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
scenes_collection_source_inspector->edit(scenes_collection_source_proxy_object);
+ scenes_collection_source_inspector->set_property_name_style(EditorPropertyNameProcessor::get_singleton()->get_settings_style());
middle_vbox_container->add_child(scenes_collection_source_inspector);
// Tile inspector.
@@ -519,6 +529,7 @@ TileSetScenesCollectionSourceEditor::TileSetScenesCollectionSourceEditor() {
tile_inspector->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
tile_inspector->edit(tile_proxy_object);
tile_inspector->set_use_folding(true);
+ tile_inspector->set_property_name_style(EditorPropertyNameProcessor::get_singleton()->get_settings_style());
middle_vbox_container->add_child(tile_inspector);
// Scenes list.
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index a43745b70f..374ce98d63 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -412,7 +412,7 @@ void ProjectSettingsEditor::_action_renamed(const String &p_old_name, const Stri
Dictionary action = GLOBAL_GET(old_property_name);
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Rename Input Action Event"));
+ undo_redo->create_action(TTR("Rename Input Action"));
// Do: clear old, set new
undo_redo->add_do_method(ProjectSettings::get_singleton(), "clear", old_property_name);
undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", new_property_name, action);
diff --git a/main/main.cpp b/main/main.cpp
index 81f2c101a1..ae3a6d2a94 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -1843,7 +1843,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
GLOBAL_DEF("display/window/ios/hide_home_indicator", true);
GLOBAL_DEF("display/window/ios/hide_status_bar", true);
GLOBAL_DEF("display/window/ios/suppress_ui_gesture", true);
- GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "input_devices/pointing/ios/touch_delay", PROPERTY_HINT_RANGE, "0,1,0.001"), 0.15);
// XR project settings.
GLOBAL_DEF_RST_BASIC("xr/openxr/enabled", false);
diff --git a/methods.py b/methods.py
index 7ede2592ff..dddac9bd86 100644
--- a/methods.py
+++ b/methods.py
@@ -732,7 +732,7 @@ def add_to_vs_project(env, sources):
env.vs_srcs += [basename + ".cpp"]
-def generate_vs_project(env, num_jobs):
+def generate_vs_project(env, num_jobs, project_name="godot"):
batch_file = find_visual_c_batch_file(env)
if batch_file:
@@ -873,7 +873,7 @@ def generate_vs_project(env, num_jobs):
env["MSVS"]["PROJECTSUFFIX"] = ".vcxproj"
env["MSVS"]["SOLUTIONSUFFIX"] = ".sln"
env.MSVSProject(
- target=["#godot" + env["MSVSPROJECTSUFFIX"]],
+ target=["#" + project_name + env["MSVSPROJECTSUFFIX"]],
incs=env.vs_incs,
srcs=env.vs_srcs,
auto_build_solution=1,
diff --git a/misc/dist/ios_xcode/godot_ios/vulkan/icd.d/MoltenVK_icd.json b/misc/dist/ios_xcode/godot_ios/vulkan/icd.d/MoltenVK_icd.json
deleted file mode 100644
index 7501cb548c..0000000000
--- a/misc/dist/ios_xcode/godot_ios/vulkan/icd.d/MoltenVK_icd.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "file_format_version" : "1.0.0",
- "ICD": {
- "library_path": "./../../Frameworks/MoltenVK.framework/MoltenVK",
- "api_version" : "1.0.0"
- }
-}
diff --git a/modules/basis_universal/SCsub b/modules/basis_universal/SCsub
index 161b0f3814..14669847bc 100644
--- a/modules/basis_universal/SCsub
+++ b/modules/basis_universal/SCsub
@@ -40,6 +40,9 @@ if not env.msvc:
else:
env_basisu.Prepend(CPPPATH=[thirdparty_dir])
+if env["builtin_zstd"]:
+ env_basisu.Prepend(CPPPATH=["#thirdparty/zstd"])
+
if env.dev_build:
env_basisu.Append(CPPDEFINES=[("BASISU_DEVEL_MESSAGES", 1), ("BASISD_ENABLE_DEBUG_FLAGS", 1)])
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index 8d09249125..d0525be853 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -1742,6 +1742,7 @@ void GDScriptAnalyzer::resolve_assignable(GDScriptParser::AssignableNode *p_assi
}
type.is_constant = is_constant;
+ type.is_read_only = false;
p_assignable->set_datatype(type);
}
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 46cd4b0d55..b34be11169 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -254,7 +254,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
if (codegen.script->member_indices.has(identifier)) {
if (codegen.script->member_indices[identifier].getter != StringName() && codegen.script->member_indices[identifier].getter != codegen.function_name) {
// Perform getter.
- GDScriptCodeGenerator::Address temp = codegen.add_temporary();
+ GDScriptCodeGenerator::Address temp = codegen.add_temporary(codegen.script->member_indices[identifier].data_type);
Vector<GDScriptCodeGenerator::Address> args; // No argument needed.
gen->write_call_self(temp, codegen.script->member_indices[identifier].getter, args);
return temp;
diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp
index 7a11ea52f0..4db41c4dfa 100644
--- a/modules/gdscript/gdscript_vm.cpp
+++ b/modules/gdscript/gdscript_vm.cpp
@@ -1244,7 +1244,17 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
"' to a variable of type '" + nc->get_name() + "'.";
OPCODE_BREAK;
}
- Object *src_obj = src->operator Object *();
+
+ bool was_freed = false;
+ Object *src_obj = src->get_validated_object_with_check(was_freed);
+ if (!src_obj) {
+ if (was_freed) {
+ err_text = "Trying to assign invalid previously freed instance.";
+ } else {
+ err_text = "Trying to assign invalid null variable.";
+ }
+ OPCODE_BREAK;
+ }
if (src_obj && !ClassDB::is_parent_class(src_obj->get_class_name(), nc->get_name())) {
err_text = "Trying to assign value of type '" + src_obj->get_class_name() +
@@ -1274,15 +1284,26 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE_BREAK;
}
- if (src->get_type() != Variant::NIL && src->operator Object *() != nullptr) {
- ScriptInstance *scr_inst = src->operator Object *()->get_script_instance();
+ if (src->get_type() != Variant::NIL) {
+ bool was_freed = false;
+ Object *val_obj = src->get_validated_object_with_check(was_freed);
+ if (!val_obj) {
+ if (was_freed) {
+ err_text = "Trying to assign invalid previously freed instance.";
+ } else {
+ err_text = "Trying to assign invalid null variable.";
+ }
+ OPCODE_BREAK;
+ }
+
+ ScriptInstance *scr_inst = val_obj->get_script_instance();
if (!scr_inst) {
- err_text = "Trying to assign value of type '" + src->operator Object *()->get_class_name() +
+ err_text = "Trying to assign value of type '" + val_obj->get_class_name() +
"' to a variable of type '" + base_type->get_path().get_file() + "'.";
OPCODE_BREAK;
}
- Script *src_type = src->operator Object *()->get_script_instance()->get_script().ptr();
+ Script *src_type = val_obj->get_script_instance()->get_script().ptr();
bool valid = false;
while (src_type) {
@@ -1294,7 +1315,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
if (!valid) {
- err_text = "Trying to assign value of type '" + src->operator Object *()->get_script_instance()->get_script()->get_path().get_file() +
+ err_text = "Trying to assign value of type '" + val_obj->get_script_instance()->get_script()->get_path().get_file() +
"' to a variable of type '" + base_type->get_path().get_file() + "'.";
OPCODE_BREAK;
}
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.gd b/modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.gd
new file mode 100644
index 0000000000..dd2708b21d
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.gd
@@ -0,0 +1,7 @@
+func test():
+ var x = Node.new()
+
+ x.free()
+
+ var ok = x
+ var bad : Node = x
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.out b/modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.out
new file mode 100644
index 0000000000..679e51ed81
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> analyzer/errors/native_freed_instance.gd
+>> 7
+>> Trying to assign invalid previously freed instance.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.gd b/modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.gd
new file mode 100644
index 0000000000..758fbaccc9
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.gd
@@ -0,0 +1,10 @@
+class A extends Node:
+ pass
+
+func test():
+ var x = A.new()
+
+ x.free()
+
+ var ok = x
+ var bad : A = x
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.out b/modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.out
new file mode 100644
index 0000000000..dec7090322
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> analyzer/errors/script_freed_instance.gd
+>> 10
+>> Trying to assign invalid previously freed instance.
diff --git a/modules/gdscript/tests/scripts/analyzer/features/getter_return_type.gd b/modules/gdscript/tests/scripts/analyzer/features/getter_return_type.gd
new file mode 100644
index 0000000000..38bb7f6e9c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/getter_return_type.gd
@@ -0,0 +1,9 @@
+var Value:int = 8 :
+ get:
+ return Value
+ set(v):
+ Value = v
+
+func test():
+ var f:float = Value
+ print(int(f))
diff --git a/modules/gdscript/tests/scripts/analyzer/features/getter_return_type.out b/modules/gdscript/tests/scripts/analyzer/features/getter_return_type.out
new file mode 100644
index 0000000000..b0cb63ef59
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/getter_return_type.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+8
diff --git a/modules/gridmap/editor/grid_map_editor_plugin.cpp b/modules/gridmap/editor/grid_map_editor_plugin.cpp
index 183190460e..9a7b37df21 100644
--- a/modules/gridmap/editor/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/editor/grid_map_editor_plugin.cpp
@@ -1197,6 +1197,7 @@ GridMapEditor::GridMapEditor() {
options->get_popup()->add_item(TTR("Cursor Back Rotate Z"), MENU_OPTION_CURSOR_BACK_ROTATE_Z, KeyModifierMask::SHIFT + Key::D);
options->get_popup()->add_item(TTR("Cursor Clear Rotation"), MENU_OPTION_CURSOR_CLEAR_ROTATION, Key::W);
options->get_popup()->add_separator();
+ // TRANSLATORS: This is a toggle to select after pasting the new content.
options->get_popup()->add_check_item(TTR("Paste Selects"), MENU_OPTION_PASTE_SELECTS);
options->get_popup()->add_separator();
options->get_popup()->add_item(TTR("Duplicate Selection"), MENU_OPTION_SELECTION_DUPLICATE, KeyModifierMask::CTRL + Key::C);
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs
index ed3a4c6e26..6c5c61acb9 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs
@@ -302,7 +302,7 @@ namespace GodotTools.Build
public static bool CleanProjectBlocking(
[DisallowNull] string configuration,
[AllowNull] string platform = null
- ) => CleanProjectBlocking(CreateBuildInfo(configuration, platform, rebuild: false));
+ ) => CleanProjectBlocking(CreateBuildInfo(configuration, platform, rebuild: false, onlyClean: true));
public static bool PublishProjectBlocking(
[DisallowNull] string configuration,
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
index 43ead4af69..060c01b3f9 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
@@ -272,8 +272,7 @@ namespace GodotTools
}
}
- string resourcePath = ProjectSettings.GlobalizePath("res://");
- args.Add(resourcePath);
+ args.Add(Path.GetDirectoryName(GodotSharpDirs.ProjectSlnPath));
string scriptPath = ProjectSettings.GlobalizePath(script.ResourcePath);
diff --git a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs
index 3226ca79e5..6b000cc89b 100644
--- a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs
+++ b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs
@@ -168,7 +168,9 @@ using Godot.NativeInterop;
{
var parameter = callback.Parameters[i];
- source.Append(parameter.ToDisplayString());
+ AppendRefKind(source, parameter.RefKind);
+ source.Append(' ');
+ source.Append(parameter.Type.FullQualifiedNameIncludeGlobal());
source.Append(' ');
source.Append(parameter.Name);
diff --git a/modules/navigation/SCsub b/modules/navigation/SCsub
index 0b0822db2d..a9277657f4 100644
--- a/modules/navigation/SCsub
+++ b/modules/navigation/SCsub
@@ -10,7 +10,7 @@ env_navigation = env_modules.Clone()
thirdparty_obj = []
# Recast Thirdparty source files
-if env["builtin_recast"]:
+if env["builtin_recastnavigation"]:
thirdparty_dir = "#thirdparty/recastnavigation/Recast/"
thirdparty_sources = [
"Source/Recast.cpp",
diff --git a/modules/ogg/ogg_packet_sequence.h b/modules/ogg/ogg_packet_sequence.h
index 4aa5ffa254..7085504500 100644
--- a/modules/ogg/ogg_packet_sequence.h
+++ b/modules/ogg/ogg_packet_sequence.h
@@ -32,11 +32,10 @@
#define OGG_PACKET_SEQUENCE_H
#include "core/io/resource.h"
-#include "core/object/gdvirtual.gen.inc"
-#include "core/variant/native_ptr.h"
#include "core/variant/typed_array.h"
#include "core/variant/variant.h"
-#include "thirdparty/libogg/ogg/ogg.h"
+
+#include <ogg/ogg.h>
class OggPacketSequencePlayback;
diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub
index 4a9c7b3567..b7b7dccdb0 100644
--- a/modules/text_server_adv/SCsub
+++ b/modules/text_server_adv/SCsub
@@ -7,7 +7,6 @@ env_text_server_adv = env_modules.Clone()
def make_icu_data(target, source, env):
-
dst = target[0].srcnode().abspath
g = open(dst, "w", encoding="utf-8")
@@ -126,7 +125,7 @@ if env["builtin_harfbuzz"]:
env_harfbuzz.Prepend(CPPPATH=["#thirdparty/harfbuzz/src"])
env_harfbuzz.Append(CCFLAGS=["-DHAVE_ICU"])
- if env["builtin_icu"]:
+ if env["builtin_icu4c"]:
env_harfbuzz.Prepend(CPPPATH=["#thirdparty/icu4c/common/", "#thirdparty/icu4c/i18n/"])
env_harfbuzz.Append(CCFLAGS=["-DU_HAVE_LIB_SUFFIX=1", "-DU_LIB_SUFFIX_C_NAME=_godot", "-DHAVE_ICU_BUILTIN"])
@@ -240,7 +239,7 @@ if env["builtin_graphite"] and freetype_enabled and env["graphite"]:
env.Append(LIBS=[lib])
-if env["builtin_icu"]:
+if env["builtin_icu4c"]:
env_icu = env_modules.Clone()
env_icu.disable_warnings()
diff --git a/modules/vorbis/audio_stream_ogg_vorbis.cpp b/modules/vorbis/audio_stream_ogg_vorbis.cpp
index f3ae35ce42..fcd717cfec 100644
--- a/modules/vorbis/audio_stream_ogg_vorbis.cpp
+++ b/modules/vorbis/audio_stream_ogg_vorbis.cpp
@@ -32,7 +32,8 @@
#include "core/io/file_access.h"
#include "core/variant/typed_array.h"
-#include "thirdparty/libogg/ogg/ogg.h"
+
+#include <ogg/ogg.h>
int AudioStreamPlaybackOggVorbis::_mix_internal(AudioFrame *p_buffer, int p_frames) {
ERR_FAIL_COND_V(!ready, 0);
diff --git a/modules/vorbis/audio_stream_ogg_vorbis.h b/modules/vorbis/audio_stream_ogg_vorbis.h
index ad6746eae2..c76df7f84d 100644
--- a/modules/vorbis/audio_stream_ogg_vorbis.h
+++ b/modules/vorbis/audio_stream_ogg_vorbis.h
@@ -34,7 +34,8 @@
#include "core/variant/variant.h"
#include "modules/ogg/ogg_packet_sequence.h"
#include "servers/audio/audio_stream.h"
-#include "thirdparty/libvorbis/vorbis/codec.h"
+
+#include <vorbis/codec.h>
class AudioStreamOggVorbis;
diff --git a/modules/vorbis/resource_importer_ogg_vorbis.cpp b/modules/vorbis/resource_importer_ogg_vorbis.cpp
index b712d63030..9e280de0ca 100644
--- a/modules/vorbis/resource_importer_ogg_vorbis.cpp
+++ b/modules/vorbis/resource_importer_ogg_vorbis.cpp
@@ -33,8 +33,9 @@
#include "core/io/file_access.h"
#include "core/io/resource_saver.h"
#include "scene/resources/texture.h"
-#include "thirdparty/libogg/ogg/ogg.h"
-#include "thirdparty/libvorbis/vorbis/codec.h"
+
+#include <ogg/ogg.h>
+#include <vorbis/codec.h>
#ifdef TOOLS_ENABLED
#include "editor/import/audio_stream_import_settings.h"
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index fdd2fed836..641258a26c 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -251,7 +251,7 @@ static const int EXPORT_FORMAT_AAB = 1;
static const char *APK_ASSETS_DIRECTORY = "res://android/build/assets";
static const char *AAB_ASSETS_DIRECTORY = "res://android/build/assetPacks/installTime/src/main/assets";
-static const int DEFAULT_MIN_SDK_VERSION = 21; // Should match the value in 'platform/android/java/app/config.gradle#minSdk'
+static const int OPENGL_MIN_SDK_VERSION = 21; // Should match the value in 'platform/android/java/app/config.gradle#minSdk'
static const int VULKAN_MIN_SDK_VERSION = 24;
static const int DEFAULT_TARGET_SDK_VERSION = 32; // Should match the value in 'platform/android/java/app/config.gradle#targetSdk'
@@ -1706,7 +1706,7 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "gradle_build/export_format", PROPERTY_HINT_ENUM, "Export APK,Export AAB"), EXPORT_FORMAT_APK));
// Using String instead of int to default to an empty string (no override) with placeholder for instructions (see GH-62465).
// This implies doing validation that the string is a proper int.
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "gradle_build/min_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", DEFAULT_MIN_SDK_VERSION)), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "gradle_build/min_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", VULKAN_MIN_SDK_VERSION)), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "gradle_build/target_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", DEFAULT_TARGET_SDK_VERSION)), ""));
Vector<PluginConfigAndroid> plugins_configs = get_plugins();
@@ -2337,7 +2337,7 @@ bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref<Edit
// Check the min sdk version.
String min_sdk_str = p_preset->get("gradle_build/min_sdk");
- int min_sdk_int = DEFAULT_MIN_SDK_VERSION;
+ int min_sdk_int = VULKAN_MIN_SDK_VERSION;
if (!min_sdk_str.is_empty()) { // Empty means no override, nothing to do.
if (!gradle_build_enabled) {
valid = false;
@@ -2350,9 +2350,9 @@ bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref<Edit
err += "\n";
} else {
min_sdk_int = min_sdk_str.to_int();
- if (min_sdk_int < DEFAULT_MIN_SDK_VERSION) {
+ if (min_sdk_int < OPENGL_MIN_SDK_VERSION) {
valid = false;
- err += vformat(TTR("\"Min SDK\" cannot be lower than %d, which is the version needed by the Godot library."), DEFAULT_MIN_SDK_VERSION);
+ err += vformat(TTR("\"Min SDK\" cannot be lower than %d, which is the version needed by the Godot library."), OPENGL_MIN_SDK_VERSION);
err += "\n";
}
}
@@ -2808,7 +2808,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
String version_name = p_preset->get("version/name");
String min_sdk_version = p_preset->get("gradle_build/min_sdk");
if (!min_sdk_version.is_valid_int()) {
- min_sdk_version = itos(DEFAULT_MIN_SDK_VERSION);
+ min_sdk_version = itos(VULKAN_MIN_SDK_VERSION);
}
String target_sdk_version = p_preset->get("gradle_build/target_sdk");
if (!target_sdk_version.is_valid_int()) {
diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp
index 5df05580a5..1249f2219f 100644
--- a/platform/android/file_access_android.cpp
+++ b/platform/android/file_access_android.cpp
@@ -169,6 +169,10 @@ bool FileAccessAndroid::file_exists(const String &p_path) {
return true;
}
+void FileAccessAndroid::close() {
+ _close();
+}
+
FileAccessAndroid::~FileAccessAndroid() {
_close();
}
diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h
index 1d25a28d90..b8f45628e5 100644
--- a/platform/android/file_access_android.h
+++ b/platform/android/file_access_android.h
@@ -78,6 +78,8 @@ public:
virtual uint32_t _get_unix_permissions(const String &p_file) override { return 0; }
virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override { return FAILED; }
+ virtual void close() override;
+
~FileAccessAndroid();
};
diff --git a/platform/android/file_access_filesystem_jandroid.cpp b/platform/android/file_access_filesystem_jandroid.cpp
index 7174d57344..ea8459d1ed 100644
--- a/platform/android/file_access_filesystem_jandroid.cpp
+++ b/platform/android/file_access_filesystem_jandroid.cpp
@@ -333,6 +333,12 @@ void FileAccessFilesystemJAndroid::setup(jobject p_file_access_handler) {
_file_last_modified = env->GetMethodID(cls, "fileLastModified", "(Ljava/lang/String;)J");
}
+void FileAccessFilesystemJAndroid::close() {
+ if (is_open()) {
+ _close();
+ }
+}
+
FileAccessFilesystemJAndroid::FileAccessFilesystemJAndroid() {
id = 0;
}
diff --git a/platform/android/file_access_filesystem_jandroid.h b/platform/android/file_access_filesystem_jandroid.h
index 7829ab7cf9..5e74d9de24 100644
--- a/platform/android/file_access_filesystem_jandroid.h
+++ b/platform/android/file_access_filesystem_jandroid.h
@@ -93,6 +93,8 @@ public:
virtual uint32_t _get_unix_permissions(const String &p_file) override { return 0; }
virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override { return FAILED; }
+ virtual void close() override;
+
FileAccessFilesystemJAndroid();
~FileAccessFilesystemJAndroid();
};
diff --git a/platform/ios/SCsub b/platform/ios/SCsub
index f3925c146f..18ba6617af 100644
--- a/platform/ios/SCsub
+++ b/platform/ios/SCsub
@@ -17,7 +17,6 @@ ios_lib = [
"display_layer.mm",
"godot_app_delegate.m",
"godot_view_renderer.mm",
- "godot_view_gesture_recognizer.mm",
"device_metrics.m",
"keyboard_input_view.mm",
"key_mapping_ios.mm",
diff --git a/platform/ios/godot_view.h b/platform/ios/godot_view.h
index 077584baa6..b00ca37ebe 100644
--- a/platform/ios/godot_view.h
+++ b/platform/ios/godot_view.h
@@ -59,9 +59,4 @@ class String;
- (void)stopRendering;
- (void)startRendering;
-- (void)godotTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
-- (void)godotTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
-- (void)godotTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
-- (void)godotTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
-
@end
diff --git a/platform/ios/godot_view.mm b/platform/ios/godot_view.mm
index 4b10f95ab8..fafec79bf6 100644
--- a/platform/ios/godot_view.mm
+++ b/platform/ios/godot_view.mm
@@ -35,7 +35,6 @@
#include "core/string/ustring.h"
#import "display_layer.h"
#include "display_server_ios.h"
-#import "godot_view_gesture_recognizer.h"
#import "godot_view_renderer.h"
#import <CoreMotion/CoreMotion.h>
@@ -60,8 +59,6 @@ static const float earth_gravity = 9.80665;
@property(strong, nonatomic) CMMotionManager *motionManager;
-@property(strong, nonatomic) GodotViewGestureRecognizer *delayGestureRecognizer;
-
@end
@implementation GodotView
@@ -148,10 +145,6 @@ static const float earth_gravity = 9.80665;
[self.animationTimer invalidate];
self.animationTimer = nil;
}
-
- if (self.delayGestureRecognizer) {
- self.delayGestureRecognizer = nil;
- }
}
- (void)godot_commonInit {
@@ -171,11 +164,6 @@ static const float earth_gravity = 9.80665;
self.motionManager = nil;
}
}
-
- // Initialize delay gesture recognizer
- GodotViewGestureRecognizer *gestureRecognizer = [[GodotViewGestureRecognizer alloc] init];
- self.delayGestureRecognizer = gestureRecognizer;
- [self addGestureRecognizer:self.delayGestureRecognizer];
}
- (void)stopRendering {
@@ -347,58 +335,42 @@ static const float earth_gravity = 9.80665;
}
}
-- (void)godotTouchesBegan:(NSSet *)touchesSet withEvent:(UIEvent *)event {
- NSArray *tlist = [event.allTouches allObjects];
- for (unsigned int i = 0; i < [tlist count]; i++) {
- if ([touchesSet containsObject:[tlist objectAtIndex:i]]) {
- UITouch *touch = [tlist objectAtIndex:i];
- int tid = [self getTouchIDForTouch:touch];
- ERR_FAIL_COND(tid == -1);
- CGPoint touchPoint = [touch locationInView:self];
- DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, true, touch.tapCount > 1);
- }
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
+ for (UITouch *touch in touches) {
+ int tid = [self getTouchIDForTouch:touch];
+ ERR_FAIL_COND(tid == -1);
+ CGPoint touchPoint = [touch locationInView:self];
+ DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, true, touch.tapCount > 1);
}
}
-- (void)godotTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
- NSArray *tlist = [event.allTouches allObjects];
- for (unsigned int i = 0; i < [tlist count]; i++) {
- if ([touches containsObject:[tlist objectAtIndex:i]]) {
- UITouch *touch = [tlist objectAtIndex:i];
- int tid = [self getTouchIDForTouch:touch];
- ERR_FAIL_COND(tid == -1);
- CGPoint touchPoint = [touch locationInView:self];
- CGPoint prev_point = [touch previousLocationInView:self];
- CGFloat alt = [touch altitudeAngle];
- CGVector azim = [touch azimuthUnitVectorInView:self];
- DisplayServerIOS::get_singleton()->touch_drag(tid, prev_point.x * self.contentScaleFactor, prev_point.y * self.contentScaleFactor, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, [touch force] / [touch maximumPossibleForce], Vector2(azim.dx, azim.dy) * Math::cos(alt));
- }
+- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
+ for (UITouch *touch in touches) {
+ int tid = [self getTouchIDForTouch:touch];
+ ERR_FAIL_COND(tid == -1);
+ CGPoint touchPoint = [touch locationInView:self];
+ CGPoint prev_point = [touch previousLocationInView:self];
+ CGFloat alt = [touch altitudeAngle];
+ CGVector azim = [touch azimuthUnitVectorInView:self];
+ DisplayServerIOS::get_singleton()->touch_drag(tid, prev_point.x * self.contentScaleFactor, prev_point.y * self.contentScaleFactor, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, [touch force] / [touch maximumPossibleForce], Vector2(azim.dx, azim.dy) * Math::cos(alt));
}
}
-- (void)godotTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
- NSArray *tlist = [event.allTouches allObjects];
- for (unsigned int i = 0; i < [tlist count]; i++) {
- if ([touches containsObject:[tlist objectAtIndex:i]]) {
- UITouch *touch = [tlist objectAtIndex:i];
- int tid = [self getTouchIDForTouch:touch];
- ERR_FAIL_COND(tid == -1);
- [self removeTouch:touch];
- CGPoint touchPoint = [touch locationInView:self];
- DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, false, false);
- }
+- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
+ for (UITouch *touch in touches) {
+ int tid = [self getTouchIDForTouch:touch];
+ ERR_FAIL_COND(tid == -1);
+ [self removeTouch:touch];
+ CGPoint touchPoint = [touch locationInView:self];
+ DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, false, false);
}
}
-- (void)godotTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
- NSArray *tlist = [event.allTouches allObjects];
- for (unsigned int i = 0; i < [tlist count]; i++) {
- if ([touches containsObject:[tlist objectAtIndex:i]]) {
- UITouch *touch = [tlist objectAtIndex:i];
- int tid = [self getTouchIDForTouch:touch];
- ERR_FAIL_COND(tid == -1);
- DisplayServerIOS::get_singleton()->touches_canceled(tid);
- }
+- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
+ for (UITouch *touch in touches) {
+ int tid = [self getTouchIDForTouch:touch];
+ ERR_FAIL_COND(tid == -1);
+ DisplayServerIOS::get_singleton()->touches_canceled(tid);
}
[self clearTouches];
}
diff --git a/platform/ios/godot_view_gesture_recognizer.h b/platform/ios/godot_view_gesture_recognizer.h
deleted file mode 100644
index 57bfc75568..0000000000
--- a/platform/ios/godot_view_gesture_recognizer.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/**************************************************************************/
-/* godot_view_gesture_recognizer.h */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-// GLViewGestureRecognizer allows iOS gestures to work correctly by
-// emulating UIScrollView's UIScrollViewDelayedTouchesBeganGestureRecognizer.
-// It catches all gestures incoming to UIView and delays them for 150ms
-// (the same value used by UIScrollViewDelayedTouchesBeganGestureRecognizer)
-// If touch cancellation or end message is fired it fires delayed
-// begin touch immediately as well as last touch signal
-
-#import <UIKit/UIKit.h>
-
-@interface GodotViewGestureRecognizer : UIGestureRecognizer
-
-@property(nonatomic, readonly, assign) NSTimeInterval delayTimeInterval;
-
-- (instancetype)init;
-
-@end
diff --git a/platform/ios/godot_view_gesture_recognizer.mm b/platform/ios/godot_view_gesture_recognizer.mm
deleted file mode 100644
index 9b71228864..0000000000
--- a/platform/ios/godot_view_gesture_recognizer.mm
+++ /dev/null
@@ -1,186 +0,0 @@
-/**************************************************************************/
-/* godot_view_gesture_recognizer.mm */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#import "godot_view_gesture_recognizer.h"
-
-#import "godot_view.h"
-
-#include "core/config/project_settings.h"
-
-// Minimum distance for touches to move to fire
-// a delay timer before scheduled time.
-// Should be the low enough to not cause issues with dragging
-// but big enough to allow click to work.
-const CGFloat kGLGestureMovementDistance = 0.5;
-
-@interface GodotViewGestureRecognizer ()
-
-@property(nonatomic, readwrite, assign) NSTimeInterval delayTimeInterval;
-
-@end
-
-@interface GodotViewGestureRecognizer ()
-
-// Timer used to delay begin touch message.
-// Should work as simple emulation of UIDelayedAction
-@property(strong, nonatomic) NSTimer *delayTimer;
-
-// Delayed touch parameters
-@property(strong, nonatomic) NSSet *delayedTouches;
-@property(strong, nonatomic) UIEvent *delayedEvent;
-
-@end
-
-@implementation GodotViewGestureRecognizer
-
-- (GodotView *)godotView {
- return (GodotView *)self.view;
-}
-
-- (instancetype)init {
- self = [super init];
-
- self.cancelsTouchesInView = YES;
- self.delaysTouchesBegan = YES;
- self.delaysTouchesEnded = YES;
- self.requiresExclusiveTouchType = NO;
-
- self.delayTimeInterval = GLOBAL_GET("input_devices/pointing/ios/touch_delay");
-
- return self;
-}
-
-- (void)dealloc {
- if (self.delayTimer) {
- [self.delayTimer invalidate];
- self.delayTimer = nil;
- }
-
- if (self.delayedTouches) {
- self.delayedTouches = nil;
- }
-
- if (self.delayedEvent) {
- self.delayedEvent = nil;
- }
-}
-
-- (void)delayTouches:(NSSet *)touches andEvent:(UIEvent *)event {
- [self.delayTimer fire];
-
- self.delayedTouches = touches;
- self.delayedEvent = event;
-
- self.delayTimer = [NSTimer
- scheduledTimerWithTimeInterval:self.delayTimeInterval
- target:self
- selector:@selector(fireDelayedTouches:)
- userInfo:nil
- repeats:NO];
-}
-
-- (void)fireDelayedTouches:(id)timer {
- [self.delayTimer invalidate];
- self.delayTimer = nil;
-
- if (self.delayedTouches) {
- [self.godotView godotTouchesBegan:self.delayedTouches withEvent:self.delayedEvent];
- }
-
- self.delayedTouches = nil;
- self.delayedEvent = nil;
-}
-
-- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
- NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseBegan];
- [self delayTouches:cleared andEvent:event];
-
- [super touchesBegan:touches withEvent:event];
-}
-
-- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
- NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseMoved];
-
- if (self.delayTimer) {
- // We should check if movement was significant enough to fire an event
- // for dragging to work correctly.
- for (UITouch *touch in cleared) {
- CGPoint from = [touch locationInView:self.godotView];
- CGPoint to = [touch previousLocationInView:self.godotView];
- CGFloat xDistance = from.x - to.x;
- CGFloat yDistance = from.y - to.y;
-
- CGFloat distance = sqrt(xDistance * xDistance + yDistance * yDistance);
-
- // Early exit, since one of touches has moved enough to fire a drag event.
- if (distance > kGLGestureMovementDistance) {
- [self.delayTimer fire];
- [self.godotView godotTouchesMoved:cleared withEvent:event];
- return;
- }
- }
-
- return;
- }
-
- [self.godotView godotTouchesMoved:cleared withEvent:event];
-
- [super touchesMoved:touches withEvent:event];
-}
-
-- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
- [self.delayTimer fire];
-
- NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseEnded];
- [self.godotView godotTouchesEnded:cleared withEvent:event];
-
- [super touchesEnded:touches withEvent:event];
-}
-
-- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
- [self.delayTimer fire];
- [self.godotView godotTouchesCancelled:touches withEvent:event];
-
- [super touchesCancelled:touches withEvent:event];
-}
-
-- (NSSet *)copyClearedTouches:(NSSet *)touches phase:(UITouchPhase)phaseToSave {
- NSMutableSet *cleared = [touches mutableCopy];
-
- for (UITouch *touch in touches) {
- if (touch.view != self.view || touch.phase != phaseToSave) {
- [cleared removeObject:touch];
- }
- }
-
- return cleared;
-}
-
-@end
diff --git a/platform/ios/joypad_ios.mm b/platform/ios/joypad_ios.mm
index 057f439b81..9194b09ef6 100644
--- a/platform/ios/joypad_ios.mm
+++ b/platform/ios/joypad_ios.mm
@@ -305,6 +305,25 @@ void JoypadIOS::start_processing() {
float value = gamepad.rightTrigger.value;
Input::get_singleton()->joy_axis(joy_id, JoyAxis::TRIGGER_RIGHT, value);
}
+
+ if (@available(iOS 13, *)) {
+ // iOS uses 'buttonOptions' and 'buttonMenu' names for BACK and START joy buttons.
+ if (element == gamepad.buttonOptions) {
+ Input::get_singleton()->joy_button(joy_id, JoyButton::BACK,
+ gamepad.buttonOptions.isPressed);
+ } else if (element == gamepad.buttonMenu) {
+ Input::get_singleton()->joy_button(joy_id, JoyButton::START,
+ gamepad.buttonMenu.isPressed);
+ }
+ }
+
+ if (@available(iOS 14, *)) {
+ // iOS uses 'buttonHome' for the GUIDE joy button.
+ if (element == gamepad.buttonHome) {
+ Input::get_singleton()->joy_button(joy_id, JoyButton::GUIDE,
+ gamepad.buttonHome.isPressed);
+ }
+ }
};
} else if (controller.microGamepad != nil) {
// micro gamepads were added in OS 9 and feature just 2 buttons and a d-pad
diff --git a/platform/linuxbsd/SCsub b/platform/linuxbsd/SCsub
index 3c5dc78c60..4dd74ff9d0 100644
--- a/platform/linuxbsd/SCsub
+++ b/platform/linuxbsd/SCsub
@@ -11,23 +11,30 @@ common_linuxbsd = [
"joypad_linux.cpp",
"freedesktop_portal_desktop.cpp",
"freedesktop_screensaver.cpp",
- "xkbcommon-so_wrap.c",
]
+if env["use_sowrap"]:
+ common_linuxbsd.append("xkbcommon-so_wrap.c")
+
if env["x11"]:
common_linuxbsd += SConscript("x11/SCsub")
if env["speechd"]:
- common_linuxbsd.append(["speechd-so_wrap.c", "tts_linux.cpp"])
+ common_linuxbsd.append("tts_linux.cpp")
+ if env["use_sowrap"]:
+ common_linuxbsd.append("speechd-so_wrap.c")
if env["fontconfig"]:
- common_linuxbsd.append("fontconfig-so_wrap.c")
+ if env["use_sowrap"]:
+ common_linuxbsd.append("fontconfig-so_wrap.c")
if env["udev"]:
- common_linuxbsd.append("libudev-so_wrap.c")
+ if env["use_sowrap"]:
+ common_linuxbsd.append("libudev-so_wrap.c")
if env["dbus"]:
- common_linuxbsd.append("dbus-so_wrap.c")
+ if env["use_sowrap"]:
+ common_linuxbsd.append("dbus-so_wrap.c")
prog = env.add_program("#bin/godot", ["godot_linuxbsd.cpp"] + common_linuxbsd)
diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py
index bae5a98aee..3f713d2db3 100644
--- a/platform/linuxbsd/detect.py
+++ b/platform/linuxbsd/detect.py
@@ -43,6 +43,7 @@ def get_opts():
BoolVariable("use_lsan", "Use LLVM/GCC compiler leak sanitizer (LSAN)", False),
BoolVariable("use_tsan", "Use LLVM/GCC compiler thread sanitizer (TSAN)", False),
BoolVariable("use_msan", "Use LLVM compiler memory sanitizer (MSAN)", False),
+ BoolVariable("use_sowrap", "Dynamically load system libraries", True),
BoolVariable("alsa", "Use ALSA", True),
BoolVariable("pulseaudio", "Use PulseAudio", True),
BoolVariable("dbus", "Use D-Bus to handle screensaver and portal desktop settings", True),
@@ -184,25 +185,30 @@ def configure(env: "Environment"):
## Dependencies
+ if env["use_sowrap"]:
+ env.Append(CPPDEFINES=["SOWRAP_ENABLED"])
+
if env["touch"]:
env.Append(CPPDEFINES=["TOUCH_ENABLED"])
# FIXME: Check for existence of the libs before parsing their flags with pkg-config
# freetype depends on libpng and zlib, so bundling one of them while keeping others
- # as shared libraries leads to weird issues
- if (
- env["builtin_freetype"]
- or env["builtin_libpng"]
- or env["builtin_zlib"]
- or env["builtin_graphite"]
- or env["builtin_harfbuzz"]
- ):
- env["builtin_freetype"] = True
- env["builtin_libpng"] = True
- env["builtin_zlib"] = True
- env["builtin_graphite"] = True
- env["builtin_harfbuzz"] = True
+ # as shared libraries leads to weird issues. And graphite and harfbuzz need freetype.
+ ft_linked_deps = [
+ env["builtin_freetype"],
+ env["builtin_libpng"],
+ env["builtin_zlib"],
+ env["builtin_graphite"],
+ env["builtin_harfbuzz"],
+ ]
+ if (not all(ft_linked_deps)) and any(ft_linked_deps): # All or nothing.
+ print(
+ "These libraries should be either all builtin, or all system provided:\n"
+ "freetype, libpng, zlib, graphite, harfbuzz.\n"
+ "Please specify `builtin_<name>=no` for all of them, or none."
+ )
+ sys.exit()
if not env["builtin_freetype"]:
env.ParseConfig("pkg-config freetype2 --cflags --libs")
@@ -210,8 +216,8 @@ def configure(env: "Environment"):
if not env["builtin_graphite"]:
env.ParseConfig("pkg-config graphite2 --cflags --libs")
- if not env["builtin_icu"]:
- env.ParseConfig("pkg-config icu-uc --cflags --libs")
+ if not env["builtin_icu4c"]:
+ env.ParseConfig("pkg-config icu-i18n icu-uc --cflags --libs")
if not env["builtin_harfbuzz"]:
env.ParseConfig("pkg-config harfbuzz harfbuzz-icu --cflags --libs")
@@ -266,31 +272,93 @@ def configure(env: "Environment"):
if not env["builtin_pcre2"]:
env.ParseConfig("pkg-config libpcre2-32 --cflags --libs")
+ if not env["builtin_recastnavigation"]:
+ # No pkgconfig file so far, hardcode default paths.
+ env.Prepend(CPPPATH=["/usr/include/recastnavigation"])
+ env.Append(LIBS=["Recast"])
+
if not env["builtin_embree"]:
# No pkgconfig file so far, hardcode expected lib name.
env.Append(LIBS=["embree3"])
## Flags
-
if env["fontconfig"]:
- env.Append(CPPDEFINES=["FONTCONFIG_ENABLED"])
+ if not env["use_sowrap"]:
+ if os.system("pkg-config --exists fontconfig") == 0: # 0 means found
+ env.ParseConfig("pkg-config fontconfig --cflags --libs")
+ env.Append(CPPDEFINES=["FONTCONFIG_ENABLED"])
+ else:
+ print("Warning: fontconfig development libraries not found. Disabling the system fonts support.")
+ env["fontconfig"] = False
+ else:
+ env.Append(CPPDEFINES=["FONTCONFIG_ENABLED"])
if env["alsa"]:
- env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"])
+ if not env["use_sowrap"]:
+ if os.system("pkg-config --exists alsa") == 0: # 0 means found
+ env.ParseConfig("pkg-config alsa --cflags --libs")
+ env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"])
+ else:
+ print("Warning: ALSA development libraries not found. Disabling the ALSA audio driver.")
+ env["alsa"] = False
+ else:
+ env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"])
if env["pulseaudio"]:
+ if not env["use_sowrap"]:
+ if os.system("pkg-config --exists libpulse") == 0: # 0 means found
+ env.ParseConfig("pkg-config libpulse --cflags --libs")
+ env.Append(CPPDEFINES=["PULSEAUDIO_ENABLED", "_REENTRANT"])
+ else:
+ print("Warning: PulseAudio development libraries not found. Disabling the PulseAudio audio driver.")
+ env["pulseaudio"] = False
env.Append(CPPDEFINES=["PULSEAUDIO_ENABLED", "_REENTRANT"])
if env["dbus"]:
- env.Append(CPPDEFINES=["DBUS_ENABLED"])
+ if not env["use_sowrap"]:
+ if os.system("pkg-config --exists dbus-1") == 0: # 0 means found
+ env.ParseConfig("pkg-config dbus-1 --cflags --libs")
+ env.Append(CPPDEFINES=["DBUS_ENABLED"])
+ else:
+ print("Warning: D-Bus development libraries not found. Disabling screensaver prevention.")
+ env["dbus"] = False
+ else:
+ env.Append(CPPDEFINES=["DBUS_ENABLED"])
if env["speechd"]:
- env.Append(CPPDEFINES=["SPEECHD_ENABLED"])
+ if not env["use_sowrap"]:
+ if os.system("pkg-config --exists speech-dispatcher") == 0: # 0 means found
+ env.ParseConfig("pkg-config speech-dispatcher --cflags --libs")
+ env.Append(CPPDEFINES=["SPEECHD_ENABLED"])
+ else:
+ print("Warning: speech-dispatcher development libraries not found. Disabling text to speech support.")
+ env["speechd"] = False
+ else:
+ env.Append(CPPDEFINES=["SPEECHD_ENABLED"])
+
+ if not env["use_sowrap"]:
+ if os.system("pkg-config --exists xkbcommon") == 0: # 0 means found
+ env.ParseConfig("pkg-config xkbcommon --cflags --libs")
+ env.Append(CPPDEFINES=["XKB_ENABLED"])
+ else:
+ print(
+ "Warning: libxkbcommon development libraries not found. Disabling dead key composition and key label support."
+ )
+ else:
+ env.Append(CPPDEFINES=["XKB_ENABLED"])
if platform.system() == "Linux":
env.Append(CPPDEFINES=["JOYDEV_ENABLED"])
if env["udev"]:
- env.Append(CPPDEFINES=["UDEV_ENABLED"])
+ if not env["use_sowrap"]:
+ if os.system("pkg-config --exists libudev") == 0: # 0 means found
+ env.ParseConfig("pkg-config libudev --cflags --libs")
+ env.Append(CPPDEFINES=["UDEV_ENABLED"])
+ else:
+ print("Warning: libudev development libraries not found. Disabling controller hotplugging support.")
+ env["udev"] = False
+ else:
+ env.Append(CPPDEFINES=["UDEV_ENABLED"])
else:
env["udev"] = False # Linux specific
@@ -298,7 +366,9 @@ def configure(env: "Environment"):
if not env["builtin_zlib"]:
env.ParseConfig("pkg-config zlib --cflags --libs")
- env.Prepend(CPPPATH=["#platform/linuxbsd", "#thirdparty/linuxbsd_headers"])
+ env.Prepend(CPPPATH=["#platform/linuxbsd"])
+ if env["use_sowrap"]:
+ env.Prepend(CPPPATH=["#thirdparty/linuxbsd_headers"])
env.Append(
CPPDEFINES=[
@@ -309,6 +379,35 @@ def configure(env: "Environment"):
)
if env["x11"]:
+ if not env["use_sowrap"]:
+ if os.system("pkg-config --exists x11"):
+ print("Error: X11 libraries not found. Aborting.")
+ sys.exit(255)
+ env.ParseConfig("pkg-config x11 --cflags --libs")
+ if os.system("pkg-config --exists xcursor"):
+ print("Error: Xcursor library not found. Aborting.")
+ sys.exit(255)
+ env.ParseConfig("pkg-config xcursor --cflags --libs")
+ if os.system("pkg-config --exists xinerama"):
+ print("Error: Xinerama library not found. Aborting.")
+ sys.exit(255)
+ env.ParseConfig("pkg-config xinerama --cflags --libs")
+ if os.system("pkg-config --exists xext"):
+ print("Error: Xext library not found. Aborting.")
+ sys.exit(255)
+ env.ParseConfig("pkg-config xext --cflags --libs")
+ if os.system("pkg-config --exists xrandr"):
+ print("Error: XrandR library not found. Aborting.")
+ sys.exit(255)
+ env.ParseConfig("pkg-config xrandr --cflags --libs")
+ if os.system("pkg-config --exists xrender"):
+ print("Error: XRender library not found. Aborting.")
+ sys.exit(255)
+ env.ParseConfig("pkg-config xrender --cflags --libs")
+ if os.system("pkg-config --exists xi"):
+ print("Error: Xi library not found. Aborting.")
+ sys.exit(255)
+ env.ParseConfig("pkg-config xi --cflags --libs")
env.Append(CPPDEFINES=["X11_ENABLED"])
if env["vulkan"]:
diff --git a/platform/linuxbsd/freedesktop_portal_desktop.cpp b/platform/linuxbsd/freedesktop_portal_desktop.cpp
index 72d4e3772f..ec1fcf6698 100644
--- a/platform/linuxbsd/freedesktop_portal_desktop.cpp
+++ b/platform/linuxbsd/freedesktop_portal_desktop.cpp
@@ -36,7 +36,11 @@
#include "core/os/os.h"
#include "core/string/ustring.h"
+#ifdef SOWRAP_ENABLED
#include "dbus-so_wrap.h"
+#else
+#include <dbus/dbus.h>
+#endif
#include "core/variant/variant.h"
@@ -124,12 +128,16 @@ uint32_t FreeDesktopPortalDesktop::get_appearance_color_scheme() {
}
FreeDesktopPortalDesktop::FreeDesktopPortalDesktop() {
+#ifdef SOWRAP_ENABLED
#ifdef DEBUG_ENABLED
int dylibloader_verbose = 1;
#else
int dylibloader_verbose = 0;
#endif
unsupported = (initialize_dbus(dylibloader_verbose) != 0);
+#else
+ unsupported = false;
+#endif
}
#endif // DBUS_ENABLED
diff --git a/platform/linuxbsd/freedesktop_screensaver.cpp b/platform/linuxbsd/freedesktop_screensaver.cpp
index 159fd0df61..d07e781a5f 100644
--- a/platform/linuxbsd/freedesktop_screensaver.cpp
+++ b/platform/linuxbsd/freedesktop_screensaver.cpp
@@ -34,7 +34,11 @@
#include "core/config/project_settings.h"
+#ifdef SOWRAP_ENABLED
#include "dbus-so_wrap.h"
+#else
+#include <dbus/dbus.h>
+#endif
#define BUS_OBJECT_NAME "org.freedesktop.ScreenSaver"
#define BUS_OBJECT_PATH "/org/freedesktop/ScreenSaver"
@@ -127,12 +131,16 @@ void FreeDesktopScreenSaver::uninhibit() {
}
FreeDesktopScreenSaver::FreeDesktopScreenSaver() {
+#ifdef SOWRAP_ENABLED
#ifdef DEBUG_ENABLED
int dylibloader_verbose = 1;
#else
int dylibloader_verbose = 0;
#endif
unsupported = (initialize_dbus(dylibloader_verbose) != 0);
+#else
+ unsupported = false;
+#endif
}
#endif // DBUS_ENABLED
diff --git a/platform/linuxbsd/joypad_linux.cpp b/platform/linuxbsd/joypad_linux.cpp
index b77f989677..0256af0a59 100644
--- a/platform/linuxbsd/joypad_linux.cpp
+++ b/platform/linuxbsd/joypad_linux.cpp
@@ -39,7 +39,11 @@
#include <unistd.h>
#ifdef UDEV_ENABLED
+#ifdef SOWRAP_ENABLED
#include "libudev-so_wrap.h"
+#else
+#include <libudev.h>
+#endif
#endif
#define LONG_BITS (sizeof(long) * 8)
@@ -70,6 +74,7 @@ void JoypadLinux::Joypad::reset() {
JoypadLinux::JoypadLinux(Input *in) {
#ifdef UDEV_ENABLED
+#ifdef SOWRAP_ENABLED
#ifdef DEBUG_ENABLED
int dylibloader_verbose = 1;
#else
@@ -81,6 +86,7 @@ JoypadLinux::JoypadLinux(Input *in) {
} else {
print_verbose("JoypadLinux: udev enabled, but couldn't be loaded. Falling back to /dev/input to detect joypads.");
}
+#endif
#else
print_verbose("JoypadLinux: udev disabled, parsing /dev/input to detect joypads.");
#endif
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index 41d1f1d050..54bb34ef73 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -1083,12 +1083,16 @@ OS_LinuxBSD::OS_LinuxBSD() {
#endif
#ifdef FONTCONFIG_ENABLED
+#ifdef SOWRAP_ENABLED
#ifdef DEBUG_ENABLED
int dylibloader_verbose = 1;
#else
int dylibloader_verbose = 0;
#endif
font_config_initialized = (initialize_fontconfig(dylibloader_verbose) == 0);
+#else
+ font_config_initialized = true;
+#endif
if (font_config_initialized) {
config = FcInitLoadConfigAndFonts();
if (!config) {
diff --git a/platform/linuxbsd/os_linuxbsd.h b/platform/linuxbsd/os_linuxbsd.h
index 045d3d95ba..9423514944 100644
--- a/platform/linuxbsd/os_linuxbsd.h
+++ b/platform/linuxbsd/os_linuxbsd.h
@@ -41,7 +41,11 @@
#include "servers/audio_server.h"
#ifdef FONTCONFIG_ENABLED
+#ifdef SOWRAP_ENABLED
#include "fontconfig-so_wrap.h"
+#else
+#include <fontconfig/fontconfig.h>
+#endif
#endif
class OS_LinuxBSD : public OS_Unix {
diff --git a/platform/linuxbsd/tts_linux.cpp b/platform/linuxbsd/tts_linux.cpp
index 4662aaf02d..04d7c5444f 100644
--- a/platform/linuxbsd/tts_linux.cpp
+++ b/platform/linuxbsd/tts_linux.cpp
@@ -39,12 +39,18 @@ void TTS_Linux::speech_init_thread_func(void *p_userdata) {
TTS_Linux *tts = (TTS_Linux *)p_userdata;
if (tts) {
MutexLock thread_safe_method(tts->_thread_safe_);
+#ifdef SOWRAP_ENABLED
#ifdef DEBUG_ENABLED
int dylibloader_verbose = 1;
#else
int dylibloader_verbose = 0;
#endif
- if (initialize_speechd(dylibloader_verbose) == 0) {
+ if (initialize_speechd(dylibloader_verbose) != 0) {
+ print_verbose("Text-to-Speech: Cannot load Speech Dispatcher library!");
+ } else {
+#else
+ {
+#endif
CharString class_str;
String config_name = GLOBAL_GET("application/config/name");
if (config_name.length() == 0) {
@@ -64,8 +70,6 @@ void TTS_Linux::speech_init_thread_func(void *p_userdata) {
} else {
print_verbose("Text-to-Speech: Cannot initialize Speech Dispatcher synthesizer!");
}
- } else {
- print_verbose("Text-to-Speech: Cannot load Speech Dispatcher library!");
}
}
}
diff --git a/platform/linuxbsd/tts_linux.h b/platform/linuxbsd/tts_linux.h
index 425654d975..3fe7b659d0 100644
--- a/platform/linuxbsd/tts_linux.h
+++ b/platform/linuxbsd/tts_linux.h
@@ -39,7 +39,11 @@
#include "core/variant/array.h"
#include "servers/display_server.h"
+#ifdef SOWRAP_ENABLED
#include "speechd-so_wrap.h"
+#else
+#include <libspeechd.h>
+#endif
class TTS_Linux {
_THREAD_SAFE_CLASS_
diff --git a/platform/linuxbsd/x11/SCsub b/platform/linuxbsd/x11/SCsub
index 8b2e2aabe4..a4890391ce 100644
--- a/platform/linuxbsd/x11/SCsub
+++ b/platform/linuxbsd/x11/SCsub
@@ -5,15 +5,21 @@ Import("env")
source_files = [
"display_server_x11.cpp",
"key_mapping_x11.cpp",
- "dynwrappers/xlib-so_wrap.c",
- "dynwrappers/xcursor-so_wrap.c",
- "dynwrappers/xinerama-so_wrap.c",
- "dynwrappers/xinput2-so_wrap.c",
- "dynwrappers/xrandr-so_wrap.c",
- "dynwrappers/xrender-so_wrap.c",
- "dynwrappers/xext-so_wrap.c",
]
+if env["use_sowrap"]:
+ source_files.append(
+ [
+ "dynwrappers/xlib-so_wrap.c",
+ "dynwrappers/xcursor-so_wrap.c",
+ "dynwrappers/xinerama-so_wrap.c",
+ "dynwrappers/xinput2-so_wrap.c",
+ "dynwrappers/xrandr-so_wrap.c",
+ "dynwrappers/xrender-so_wrap.c",
+ "dynwrappers/xext-so_wrap.c",
+ ]
+ )
+
if env["vulkan"]:
source_files.append("vulkan_context_x11.cpp")
diff --git a/platform/linuxbsd/x11/detect_prime_x11.cpp b/platform/linuxbsd/x11/detect_prime_x11.cpp
index 8d586599e6..3d07be1c76 100644
--- a/platform/linuxbsd/x11/detect_prime_x11.cpp
+++ b/platform/linuxbsd/x11/detect_prime_x11.cpp
@@ -41,7 +41,13 @@
#include "thirdparty/glad/glad/gl.h"
#include "thirdparty/glad/glad/glx.h"
+#ifdef SOWRAP_ENABLED
#include "dynwrappers/xlib-so_wrap.h"
+#else
+#include <X11/XKBlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#endif
#include <cstring>
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index 5d70af56bd..896b7b95eb 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -1329,12 +1329,14 @@ void DisplayServerX11::delete_sub_window(WindowID p_id) {
wd.xic = nullptr;
}
XDestroyWindow(x11_display, wd.x11_xim_window);
+#ifdef XKB_ENABLED
if (xkb_loaded) {
if (wd.xkb_state) {
xkb_compose_state_unref(wd.xkb_state);
wd.xkb_state = nullptr;
}
}
+#endif
XUnmapWindow(x11_display, wd.x11_window);
XDestroyWindow(x11_display, wd.x11_window);
@@ -2942,11 +2944,13 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
XLookupString(&xkeyevent_no_mod, nullptr, 0, &keysym_keycode, nullptr);
String keysym;
+#ifdef XKB_ENABLED
if (xkb_loaded) {
KeySym keysym_unicode_nm = 0; // keysym used to find unicode
XLookupString(&xkeyevent_no_mod, nullptr, 0, &keysym_unicode_nm, nullptr);
keysym = String::chr(xkb_keysym_to_utf32(xkb_keysym_to_upper(keysym_unicode_nm)));
}
+#endif
// Meanwhile, XLookupString returns keysyms useful for unicode.
@@ -3035,6 +3039,7 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
}
} while (status == XBufferOverflow);
#endif
+#ifdef XKB_ENABLED
} else if (xkeyevent->type == KeyPress && wd.xkb_state && xkb_loaded) {
xkb_compose_feed_result res = xkb_compose_state_feed(wd.xkb_state, keysym_unicode);
if (res == XKB_COMPOSE_FEED_ACCEPTED) {
@@ -3093,6 +3098,7 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
return;
}
}
+#endif
}
/* Phase 2, obtain a Godot keycode from the keysym */
@@ -4948,11 +4954,11 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
window_attributes_ime.event_mask = KeyPressMask | KeyReleaseMask | StructureNotifyMask | ExposureMask;
wd.x11_xim_window = XCreateWindow(x11_display, wd.x11_window, 0, 0, 1, 1, 0, CopyFromParent, InputOnly, CopyFromParent, CWEventMask, &window_attributes_ime);
-
+#ifdef XKB_ENABLED
if (dead_tbl && xkb_loaded) {
wd.xkb_state = xkb_compose_state_new(dead_tbl, XKB_COMPOSE_STATE_NO_FLAGS);
}
-
+#endif
// Enable receiving notification when the window is initialized (MapNotify)
// so the focus can be set at the right time.
if (!wd.no_focus && !wd.is_popup) {
@@ -5217,6 +5223,7 @@ static ::XIMStyle _get_best_xim_style(const ::XIMStyle &p_style_a, const ::XIMSt
DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) {
KeyMappingX11::initialize();
+#ifdef SOWRAP_ENABLED
#ifdef DEBUG_ENABLED
int dylibloader_verbose = 1;
#else
@@ -5231,9 +5238,9 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
r_error = ERR_UNAVAILABLE;
ERR_FAIL_MSG("Can't load XCursor dynamically.");
}
-
+#ifdef XKB_ENABLED
xkb_loaded = (initialize_xkbcommon(dylibloader_verbose) == 0);
-
+#endif
if (initialize_xext(dylibloader_verbose) != 0) {
r_error = ERR_UNAVAILABLE;
ERR_FAIL_MSG("Can't load Xext dynamically.");
@@ -5258,7 +5265,13 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
r_error = ERR_UNAVAILABLE;
ERR_FAIL_MSG("Can't load Xinput2 dynamically.");
}
+#else
+#ifdef XKB_ENABLED
+ xkb_loaded = true;
+#endif
+#endif
+#ifdef XKB_ENABLED
if (xkb_loaded) {
xkb_ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (xkb_ctx) {
@@ -5275,6 +5288,7 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
dead_tbl = xkb_compose_table_new_from_locale(xkb_ctx, locale, XKB_COMPOSE_COMPILE_NO_FLAGS);
}
}
+#endif
Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events);
@@ -5717,16 +5731,19 @@ DisplayServerX11::~DisplayServerX11() {
wd.xic = nullptr;
}
XDestroyWindow(x11_display, wd.x11_xim_window);
+#ifdef XKB_ENABLED
if (xkb_loaded) {
if (wd.xkb_state) {
xkb_compose_state_unref(wd.xkb_state);
wd.xkb_state = nullptr;
}
}
+#endif
XUnmapWindow(x11_display, wd.x11_window);
XDestroyWindow(x11_display, wd.x11_window);
}
+#ifdef XKB_ENABLED
if (xkb_loaded) {
if (dead_tbl) {
xkb_compose_table_unref(dead_tbl);
@@ -5735,6 +5752,7 @@ DisplayServerX11::~DisplayServerX11() {
xkb_context_unref(xkb_ctx);
}
}
+#endif
//destroy drivers
#if defined(VULKAN_ENABLED)
diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h
index ea54b42262..dbe8a0ce2b 100644
--- a/platform/linuxbsd/x11/display_server_x11.h
+++ b/platform/linuxbsd/x11/display_server_x11.h
@@ -36,6 +36,8 @@
#include "servers/display_server.h"
#include "core/input/input.h"
+#include "core/os/mutex.h"
+#include "core/os/thread.h"
#include "core/templates/local_vector.h"
#include "drivers/alsa/audio_driver_alsa.h"
#include "drivers/alsamidi/midi_driver_alsamidi.h"
@@ -69,6 +71,7 @@
#include <X11/Xutil.h>
#include <X11/keysym.h>
+#ifdef SOWRAP_ENABLED
#include "dynwrappers/xlib-so_wrap.h"
#include "dynwrappers/xcursor-so_wrap.h"
@@ -79,6 +82,25 @@
#include "dynwrappers/xrender-so_wrap.h"
#include "../xkbcommon-so_wrap.h"
+#else
+#include <X11/XKBlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include <X11/Xcursor/Xcursor.h>
+#include <X11/extensions/XInput2.h>
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/Xinerama.h>
+#include <X11/extensions/Xrandr.h>
+#include <X11/extensions/Xrender.h>
+#include <X11/extensions/shape.h>
+
+#ifdef XKB_ENABLED
+#include <xkbcommon/xkbcommon-compose.h>
+#include <xkbcommon/xkbcommon-keysyms.h>
+#include <xkbcommon/xkbcommon.h>
+#endif
+#endif
typedef struct _xrr_monitor_info {
Atom name;
@@ -142,7 +164,9 @@ class DisplayServerX11 : public DisplayServer {
bool ime_active = false;
bool ime_in_progress = false;
bool ime_suppress_next_keyup = false;
+#ifdef XKB_ENABLED
xkb_compose_state *xkb_state = nullptr;
+#endif
Size2i min_size;
Size2i max_size;
@@ -186,9 +210,11 @@ class DisplayServerX11 : public DisplayServer {
Point2i im_selection;
String im_text;
+#ifdef XKB_ENABLED
bool xkb_loaded = false;
xkb_context *xkb_ctx = nullptr;
xkb_compose_table *dead_tbl = nullptr;
+#endif
HashMap<WindowID, WindowData> windows;
diff --git a/platform/linuxbsd/x11/gl_manager_x11.h b/platform/linuxbsd/x11/gl_manager_x11.h
index 713b13376c..0eb8ab64f4 100644
--- a/platform/linuxbsd/x11/gl_manager_x11.h
+++ b/platform/linuxbsd/x11/gl_manager_x11.h
@@ -37,9 +37,22 @@
#include "core/os/os.h"
#include "core/templates/local_vector.h"
-#include "dynwrappers/xext-so_wrap.h"
+
+#ifdef SOWRAP_ENABLED
#include "dynwrappers/xlib-so_wrap.h"
+
+#include "dynwrappers/xext-so_wrap.h"
#include "dynwrappers/xrender-so_wrap.h"
+#else
+#include <X11/XKBlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/Xrender.h>
+#include <X11/extensions/shape.h>
+#endif
+
#include "servers/display_server.h"
struct GLManager_X11_Private;
diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp
index 902fba38bf..c175edb6cb 100644
--- a/scene/2d/audio_stream_player_2d.cpp
+++ b/scene/2d/audio_stream_player_2d.cpp
@@ -234,7 +234,7 @@ float AudioStreamPlayer2D::get_volume_db() const {
}
void AudioStreamPlayer2D::set_pitch_scale(float p_pitch_scale) {
- ERR_FAIL_COND(p_pitch_scale <= 0.0);
+ ERR_FAIL_COND(!(p_pitch_scale > 0.0));
pitch_scale = p_pitch_scale;
for (Ref<AudioStreamPlayback> &playback : stream_playbacks) {
AudioServer::get_singleton()->set_playback_pitch_scale(playback, p_pitch_scale);
diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp
index 52a1213a49..bfe2f6252e 100644
--- a/scene/2d/navigation_agent_2d.cpp
+++ b/scene/2d/navigation_agent_2d.cpp
@@ -31,6 +31,7 @@
#include "navigation_agent_2d.h"
#include "core/math/geometry_2d.h"
+#include "scene/2d/navigation_link_2d.h"
#include "scene/resources/world_2d.h"
#include "servers/navigation_server_2d.h"
@@ -94,19 +95,19 @@ void NavigationAgent2D::_bind_methods() {
ADD_GROUP("Pathfinding", "");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "target_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_target_position", "get_target_position");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_desired_distance", PROPERTY_HINT_RANGE, "0.1,1000,0.01,suffix:px"), "set_path_desired_distance", "get_path_desired_distance");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_desired_distance", PROPERTY_HINT_RANGE, "0.1,1000,0.01,suffix:px"), "set_target_desired_distance", "get_target_desired_distance");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "10,1000,1,suffix:px"), "set_path_max_distance", "get_path_max_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_desired_distance", PROPERTY_HINT_RANGE, "0.1,1000,0.01,or_greater,suffix:px"), "set_path_desired_distance", "get_path_desired_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_desired_distance", PROPERTY_HINT_RANGE, "0.1,1000,0.01,or_greater,suffix:px"), "set_target_desired_distance", "get_target_desired_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "10,1000,1,or_greater,suffix:px"), "set_path_max_distance", "get_path_max_distance");
ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
ADD_PROPERTY(PropertyInfo(Variant::INT, "path_metadata_flags", PROPERTY_HINT_FLAGS, "Include Types,Include RIDs,Include Owners"), "set_path_metadata_flags", "get_path_metadata_flags");
ADD_GROUP("Avoidance", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.1,500,0.01,suffix:px"), "set_radius", "get_radius");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "neighbor_distance", PROPERTY_HINT_RANGE, "0.1,100000,0.01,suffix:px"), "set_neighbor_distance", "get_neighbor_distance");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "max_neighbors", PROPERTY_HINT_RANGE, "1,10000,1"), "set_max_neighbors", "get_max_neighbors");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon", PROPERTY_HINT_RANGE, "0.1,10,0.01,suffix:s"), "set_time_horizon", "get_time_horizon");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,10000,0.01,suffix:px/s"), "set_max_speed", "get_max_speed");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.1,500,0.01,or_greater,suffix:px"), "set_radius", "get_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "neighbor_distance", PROPERTY_HINT_RANGE, "0.1,100000,0.01,or_greater,suffix:px"), "set_neighbor_distance", "get_neighbor_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_neighbors", PROPERTY_HINT_RANGE, "1,10000,or_greater,1"), "set_max_neighbors", "get_max_neighbors");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon", PROPERTY_HINT_RANGE, "0.1,10,0.01,or_greater,suffix:s"), "set_time_horizon", "get_time_horizon");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,10000,0.01,or_greater,suffix:px/s"), "set_max_speed", "get_max_speed");
ClassDB::bind_method(D_METHOD("set_debug_enabled", "enabled"), &NavigationAgent2D::set_debug_enabled);
ClassDB::bind_method(D_METHOD("get_debug_enabled"), &NavigationAgent2D::get_debug_enabled);
@@ -623,6 +624,21 @@ void NavigationAgent2D::update_navigation() {
}
details[SNAME("owner")] = owner;
+
+ if (waypoint_type == NavigationPathQueryResult2D::PATH_SEGMENT_TYPE_LINK) {
+ const NavigationLink2D *navlink = Object::cast_to<NavigationLink2D>(owner);
+ if (navlink) {
+ Vector2 link_global_start_position = navlink->get_global_start_position();
+ Vector2 link_global_end_position = navlink->get_global_end_position();
+ if (waypoint.distance_to(link_global_start_position) < waypoint.distance_to(link_global_end_position)) {
+ details[SNAME("link_entry_position")] = link_global_start_position;
+ details[SNAME("link_exit_position")] = link_global_end_position;
+ } else {
+ details[SNAME("link_entry_position")] = link_global_end_position;
+ details[SNAME("link_exit_position")] = link_global_start_position;
+ }
+ }
+ }
}
// Emit a signal for the waypoint
diff --git a/scene/2d/navigation_link_2d.cpp b/scene/2d/navigation_link_2d.cpp
index 26dca40176..8adb7c6305 100644
--- a/scene/2d/navigation_link_2d.cpp
+++ b/scene/2d/navigation_link_2d.cpp
@@ -54,6 +54,12 @@ void NavigationLink2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_end_position", "position"), &NavigationLink2D::set_end_position);
ClassDB::bind_method(D_METHOD("get_end_position"), &NavigationLink2D::get_end_position);
+ ClassDB::bind_method(D_METHOD("set_global_start_position", "position"), &NavigationLink2D::set_global_start_position);
+ ClassDB::bind_method(D_METHOD("get_global_start_position"), &NavigationLink2D::get_global_start_position);
+
+ ClassDB::bind_method(D_METHOD("set_global_end_position", "position"), &NavigationLink2D::set_global_end_position);
+ ClassDB::bind_method(D_METHOD("get_global_end_position"), &NavigationLink2D::get_global_end_position);
+
ClassDB::bind_method(D_METHOD("set_enter_cost", "enter_cost"), &NavigationLink2D::set_enter_cost);
ClassDB::bind_method(D_METHOD("get_enter_cost"), &NavigationLink2D::get_enter_cost);
@@ -271,6 +277,38 @@ void NavigationLink2D::set_end_position(Vector2 p_position) {
#endif // DEBUG_ENABLED
}
+void NavigationLink2D::set_global_start_position(Vector2 p_position) {
+ if (is_inside_tree()) {
+ set_start_position(to_local(p_position));
+ } else {
+ set_start_position(p_position);
+ }
+}
+
+Vector2 NavigationLink2D::get_global_start_position() const {
+ if (is_inside_tree()) {
+ return to_global(start_position);
+ } else {
+ return start_position;
+ }
+}
+
+void NavigationLink2D::set_global_end_position(Vector2 p_position) {
+ if (is_inside_tree()) {
+ set_end_position(to_local(p_position));
+ } else {
+ set_end_position(p_position);
+ }
+}
+
+Vector2 NavigationLink2D::get_global_end_position() const {
+ if (is_inside_tree()) {
+ return to_global(end_position);
+ } else {
+ return end_position;
+ }
+}
+
void NavigationLink2D::set_enter_cost(real_t p_enter_cost) {
ERR_FAIL_COND_MSG(p_enter_cost < 0.0, "The enter_cost must be positive.");
if (Math::is_equal_approx(enter_cost, p_enter_cost)) {
diff --git a/scene/2d/navigation_link_2d.h b/scene/2d/navigation_link_2d.h
index 5bf2a72358..8a24d611c9 100644
--- a/scene/2d/navigation_link_2d.h
+++ b/scene/2d/navigation_link_2d.h
@@ -78,6 +78,12 @@ public:
void set_end_position(Vector2 p_position);
Vector2 get_end_position() const { return end_position; }
+ void set_global_start_position(Vector2 p_position);
+ Vector2 get_global_start_position() const;
+
+ void set_global_end_position(Vector2 p_position);
+ Vector2 get_global_end_position() const;
+
void set_enter_cost(real_t p_enter_cost);
real_t get_enter_cost() const { return enter_cost; }
diff --git a/scene/2d/touch_screen_button.cpp b/scene/2d/touch_screen_button.cpp
index 54ed96f585..1c2903fe22 100644
--- a/scene/2d/touch_screen_button.cpp
+++ b/scene/2d/touch_screen_button.cpp
@@ -194,10 +194,6 @@ void TouchScreenButton::input(const Ref<InputEvent> &p_event) {
return;
}
- if (p_event->get_device() != 0) {
- return;
- }
-
const InputEventScreenTouch *st = Object::cast_to<InputEventScreenTouch>(*p_event);
if (passby_press) {
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index 77bf15125e..ac626d0d2a 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -559,7 +559,7 @@ float AudioStreamPlayer3D::get_max_db() const {
}
void AudioStreamPlayer3D::set_pitch_scale(float p_pitch_scale) {
- ERR_FAIL_COND(p_pitch_scale <= 0.0);
+ ERR_FAIL_COND(!(p_pitch_scale > 0.0));
pitch_scale = p_pitch_scale;
}
diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp
index 16f357194e..396e4b72af 100644
--- a/scene/3d/navigation_agent_3d.cpp
+++ b/scene/3d/navigation_agent_3d.cpp
@@ -30,6 +30,7 @@
#include "navigation_agent_3d.h"
+#include "scene/3d/navigation_link_3d.h"
#include "servers/navigation_server_3d.h"
void NavigationAgent3D::_bind_methods() {
@@ -98,20 +99,20 @@ void NavigationAgent3D::_bind_methods() {
ADD_GROUP("Pathfinding", "");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "target_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_target_position", "get_target_position");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01,suffix:m"), "set_path_desired_distance", "get_path_desired_distance");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01,suffix:m"), "set_target_desired_distance", "get_target_desired_distance");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_height_offset", PROPERTY_HINT_RANGE, "-100.0,100,0.01,suffix:m"), "set_agent_height_offset", "get_agent_height_offset");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "0.01,100,0.1,suffix:m"), "set_path_max_distance", "get_path_max_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01,or_greater,suffix:m"), "set_path_desired_distance", "get_path_desired_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01,or_greater,suffix:m"), "set_target_desired_distance", "get_target_desired_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_height_offset", PROPERTY_HINT_RANGE, "-100.0,100,0.01,or_greater,suffix:m"), "set_agent_height_offset", "get_agent_height_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "0.01,100,0.1,or_greater,suffix:m"), "set_path_max_distance", "get_path_max_distance");
ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
ADD_PROPERTY(PropertyInfo(Variant::INT, "path_metadata_flags", PROPERTY_HINT_FLAGS, "Include Types,Include RIDs,Include Owners"), "set_path_metadata_flags", "get_path_metadata_flags");
ADD_GROUP("Avoidance", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.1,100,0.01,suffix:m"), "set_radius", "get_radius");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "neighbor_distance", PROPERTY_HINT_RANGE, "0.1,10000,0.01,suffix:m"), "set_neighbor_distance", "get_neighbor_distance");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "max_neighbors", PROPERTY_HINT_RANGE, "1,10000,1"), "set_max_neighbors", "get_max_neighbors");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon", PROPERTY_HINT_RANGE, "0.01,100,0.01,suffix:s"), "set_time_horizon", "get_time_horizon");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,10000,0.01,suffix:m/s"), "set_max_speed", "get_max_speed");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.1,100,0.01,or_greater,suffix:m"), "set_radius", "get_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "neighbor_distance", PROPERTY_HINT_RANGE, "0.1,10000,0.01,or_greater,suffix:m"), "set_neighbor_distance", "get_neighbor_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_neighbors", PROPERTY_HINT_RANGE, "1,10000,1,or_greater"), "set_max_neighbors", "get_max_neighbors");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon", PROPERTY_HINT_RANGE, "0.01,10,0.01,or_greater,suffix:s"), "set_time_horizon", "get_time_horizon");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,1000,0.01,or_greater,suffix:m/s"), "set_max_speed", "get_max_speed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_y"), "set_ignore_y", "get_ignore_y");
ADD_SIGNAL(MethodInfo("path_changed"));
@@ -649,6 +650,21 @@ void NavigationAgent3D::update_navigation() {
}
details[SNAME("owner")] = owner;
+
+ if (waypoint_type == NavigationPathQueryResult3D::PATH_SEGMENT_TYPE_LINK) {
+ const NavigationLink3D *navlink = Object::cast_to<NavigationLink3D>(owner);
+ if (navlink) {
+ Vector3 link_global_start_position = navlink->get_global_start_position();
+ Vector3 link_global_end_position = navlink->get_global_end_position();
+ if (waypoint.distance_to(link_global_start_position) < waypoint.distance_to(link_global_end_position)) {
+ details[SNAME("link_entry_position")] = link_global_start_position;
+ details[SNAME("link_exit_position")] = link_global_end_position;
+ } else {
+ details[SNAME("link_entry_position")] = link_global_end_position;
+ details[SNAME("link_exit_position")] = link_global_start_position;
+ }
+ }
+ }
}
// Emit a signal for the waypoint
diff --git a/scene/3d/navigation_agent_3d.h b/scene/3d/navigation_agent_3d.h
index 072ca1d3e8..cde826ed5c 100644
--- a/scene/3d/navigation_agent_3d.h
+++ b/scene/3d/navigation_agent_3d.h
@@ -52,14 +52,14 @@ class NavigationAgent3D : public Node {
real_t path_desired_distance = 1.0;
real_t target_desired_distance = 1.0;
- real_t radius = 1.0;
+ real_t radius = 0.5;
real_t navigation_height_offset = 0.0;
bool ignore_y = true;
real_t neighbor_distance = 50.0;
int max_neighbors = 10;
- real_t time_horizon = 5.0;
+ real_t time_horizon = 1.0;
real_t max_speed = 10.0;
- real_t path_max_distance = 3.0;
+ real_t path_max_distance = 5.0;
Vector3 target_position;
bool target_position_submitted = false;
diff --git a/scene/3d/navigation_link_3d.cpp b/scene/3d/navigation_link_3d.cpp
index f47fcfaf51..9c4b8e7905 100644
--- a/scene/3d/navigation_link_3d.cpp
+++ b/scene/3d/navigation_link_3d.cpp
@@ -163,6 +163,12 @@ void NavigationLink3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_end_position", "position"), &NavigationLink3D::set_end_position);
ClassDB::bind_method(D_METHOD("get_end_position"), &NavigationLink3D::get_end_position);
+ ClassDB::bind_method(D_METHOD("set_global_start_position", "position"), &NavigationLink3D::set_global_start_position);
+ ClassDB::bind_method(D_METHOD("get_global_start_position"), &NavigationLink3D::get_global_start_position);
+
+ ClassDB::bind_method(D_METHOD("set_global_end_position", "position"), &NavigationLink3D::set_global_end_position);
+ ClassDB::bind_method(D_METHOD("get_global_end_position"), &NavigationLink3D::get_global_end_position);
+
ClassDB::bind_method(D_METHOD("set_enter_cost", "enter_cost"), &NavigationLink3D::set_enter_cost);
ClassDB::bind_method(D_METHOD("get_enter_cost"), &NavigationLink3D::get_enter_cost);
@@ -386,6 +392,38 @@ void NavigationLink3D::set_end_position(Vector3 p_position) {
update_configuration_warnings();
}
+void NavigationLink3D::set_global_start_position(Vector3 p_position) {
+ if (is_inside_tree()) {
+ set_start_position(to_local(p_position));
+ } else {
+ set_start_position(p_position);
+ }
+}
+
+Vector3 NavigationLink3D::get_global_start_position() const {
+ if (is_inside_tree()) {
+ return to_global(start_position);
+ } else {
+ return start_position;
+ }
+}
+
+void NavigationLink3D::set_global_end_position(Vector3 p_position) {
+ if (is_inside_tree()) {
+ set_end_position(to_local(p_position));
+ } else {
+ set_end_position(p_position);
+ }
+}
+
+Vector3 NavigationLink3D::get_global_end_position() const {
+ if (is_inside_tree()) {
+ return to_global(end_position);
+ } else {
+ return end_position;
+ }
+}
+
void NavigationLink3D::set_enter_cost(real_t p_enter_cost) {
ERR_FAIL_COND_MSG(p_enter_cost < 0.0, "The enter_cost must be positive.");
if (Math::is_equal_approx(enter_cost, p_enter_cost)) {
diff --git a/scene/3d/navigation_link_3d.h b/scene/3d/navigation_link_3d.h
index 5c9ec36189..991f45c85d 100644
--- a/scene/3d/navigation_link_3d.h
+++ b/scene/3d/navigation_link_3d.h
@@ -83,6 +83,12 @@ public:
void set_end_position(Vector3 p_position);
Vector3 get_end_position() const { return end_position; }
+ void set_global_start_position(Vector3 p_position);
+ Vector3 get_global_start_position() const;
+
+ void set_global_end_position(Vector3 p_position);
+ Vector3 get_global_end_position() const;
+
void set_enter_cost(real_t p_enter_cost);
real_t get_enter_cost() const { return enter_cost; }
diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp
index d169999de4..42b0748698 100644
--- a/scene/3d/voxelizer.cpp
+++ b/scene/3d/voxelizer.cpp
@@ -346,25 +346,29 @@ Voxelizer::MaterialCache Voxelizer::_get_material_cache(Ref<Material> p_material
} else {
mc.albedo = _get_bake_texture(img_albedo, Color(1, 1, 1), mat->get_albedo()); // no albedo texture, color is additive
}
+ if (mat->get_feature(BaseMaterial3D::FEATURE_EMISSION)) {
+ Ref<Texture2D> emission_tex = mat->get_texture(BaseMaterial3D::TEXTURE_EMISSION);
- Ref<Texture2D> emission_tex = mat->get_texture(BaseMaterial3D::TEXTURE_EMISSION);
-
- Color emission_col = mat->get_emission();
- float emission_energy = mat->get_emission_energy_multiplier() * exposure_normalization;
- if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
- emission_energy *= mat->get_emission_intensity();
- }
+ Color emission_col = mat->get_emission();
+ float emission_energy = mat->get_emission_energy_multiplier() * exposure_normalization;
+ if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
+ emission_energy *= mat->get_emission_intensity();
+ }
- Ref<Image> img_emission;
+ Ref<Image> img_emission;
- if (emission_tex.is_valid()) {
- img_emission = emission_tex->get_image();
- }
+ if (emission_tex.is_valid()) {
+ img_emission = emission_tex->get_image();
+ }
- if (mat->get_emission_operator() == BaseMaterial3D::EMISSION_OP_ADD) {
- mc.emission = _get_bake_texture(img_emission, Color(1, 1, 1) * emission_energy, emission_col * emission_energy);
+ if (mat->get_emission_operator() == BaseMaterial3D::EMISSION_OP_ADD) {
+ mc.emission = _get_bake_texture(img_emission, Color(1, 1, 1) * emission_energy, emission_col * emission_energy);
+ } else {
+ mc.emission = _get_bake_texture(img_emission, emission_col * emission_energy, Color(0, 0, 0));
+ }
} else {
- mc.emission = _get_bake_texture(img_emission, emission_col * emission_energy, Color(0, 0, 0));
+ Ref<Image> empty;
+ mc.emission = _get_bake_texture(empty, Color(0, 0, 0), Color(0, 0, 0));
}
} else {
diff --git a/scene/audio/audio_stream_player.cpp b/scene/audio/audio_stream_player.cpp
index 7533a56b59..6c37d6f81d 100644
--- a/scene/audio/audio_stream_player.cpp
+++ b/scene/audio/audio_stream_player.cpp
@@ -111,7 +111,7 @@ float AudioStreamPlayer::get_volume_db() const {
}
void AudioStreamPlayer::set_pitch_scale(float p_pitch_scale) {
- ERR_FAIL_COND(p_pitch_scale <= 0.0);
+ ERR_FAIL_COND(!(p_pitch_scale > 0.0));
pitch_scale = p_pitch_scale;
for (Ref<AudioStreamPlayback> &playback : stream_playbacks) {
diff --git a/scene/gui/aspect_ratio_container.cpp b/scene/gui/aspect_ratio_container.cpp
index 802189c374..94240ccead 100644
--- a/scene/gui/aspect_ratio_container.cpp
+++ b/scene/gui/aspect_ratio_container.cpp
@@ -30,6 +30,8 @@
#include "aspect_ratio_container.h"
+#include "scene/gui/texture_rect.h"
+
Size2 AspectRatioContainer::get_minimum_size() const {
Size2 ms;
for (int i = 0; i < get_child_count(); i++) {
@@ -113,6 +115,16 @@ void AspectRatioContainer::_notification(int p_what) {
if (c->is_set_as_top_level()) {
continue;
}
+
+ // Temporary fix for editor crash.
+ TextureRect *trect = Object::cast_to<TextureRect>(c);
+ if (trect) {
+ if (trect->get_expand_mode() == TextureRect::EXPAND_FIT_WIDTH_PROPORTIONAL || trect->get_expand_mode() == TextureRect::EXPAND_FIT_HEIGHT_PROPORTIONAL) {
+ WARN_PRINT_ONCE("Proportional TextureRect is currently not supported inside AspectRatioContainer");
+ continue;
+ }
+ }
+
Size2 child_minsize = c->get_combined_minimum_size();
Size2 child_size = Size2(ratio, 1.0);
float scale_factor = 1.0;
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 0b0698188c..48e3759981 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -31,10 +31,12 @@
#include "color_picker.h"
#include "core/input/input.h"
+#include "core/io/image.h"
#include "core/math/color.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "scene/gui/color_mode.h"
+#include "servers/display_server.h"
#include "thirdparty/misc/ok_color.h"
#include "thirdparty/misc/ok_color_shader.h"
@@ -90,8 +92,8 @@ void ColorPicker::_notification(int p_what) {
} break;
case NOTIFICATION_WM_CLOSE_REQUEST: {
- if (screen != nullptr && screen->is_visible()) {
- screen->hide();
+ if (picker_window != nullptr && picker_window->is_visible()) {
+ picker_window->hide();
}
} break;
}
@@ -1372,30 +1374,26 @@ void ColorPicker::_recent_preset_pressed(const bool p_pressed, ColorPresetButton
emit_signal(SNAME("color_changed"), p_preset->get_preset_color());
}
-void ColorPicker::_screen_input(const Ref<InputEvent> &p_event) {
+void ColorPicker::_picker_texture_input(const Ref<InputEvent> &p_event) {
if (!is_inside_tree()) {
return;
}
Ref<InputEventMouseButton> bev = p_event;
if (bev.is_valid() && bev->get_button_index() == MouseButton::LEFT && !bev->is_pressed()) {
+ set_pick_color(picker_color);
emit_signal(SNAME("color_changed"), color);
- screen->hide();
+ picker_window->hide();
}
Ref<InputEventMouseMotion> mev = p_event;
if (mev.is_valid()) {
- Viewport *r = get_tree()->get_root();
- if (!r->get_visible_rect().has_point(mev->get_global_position())) {
- return;
- }
-
- Ref<Image> img = r->get_texture()->get_image();
+ Ref<Image> img = picker_texture_rect->get_texture()->get_image();
if (img.is_valid() && !img->is_empty()) {
- Vector2 ofs = mev->get_global_position();
- Color c = img->get_pixel(ofs.x, ofs.y);
-
- set_pick_color(c);
+ Vector2 ofs = mev->get_position();
+ picker_color = img->get_pixel(ofs.x, ofs.y);
+ picker_preview_style_box->set_bg_color(picker_color);
+ picker_preview_label->set_self_modulate(picker_color.get_luminance() < 0.5 ? Color(1.0f, 1.0f, 1.0f) : Color(0.0f, 0.0f, 0.0f));
}
}
}
@@ -1409,27 +1407,79 @@ void ColorPicker::_add_preset_pressed() {
emit_signal(SNAME("preset_added"), color);
}
-void ColorPicker::_screen_pick_pressed() {
+void ColorPicker::_pick_button_pressed() {
if (!is_inside_tree()) {
return;
}
- Viewport *r = get_tree()->get_root();
- if (!screen) {
- screen = memnew(Control);
- r->add_child(screen);
- screen->set_as_top_level(true);
- screen->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
- screen->set_default_cursor_shape(CURSOR_POINTING_HAND);
- screen->connect("gui_input", callable_mp(this, &ColorPicker::_screen_input));
- // It immediately toggles off in the first press otherwise.
- screen->call_deferred(SNAME("connect"), "hidden", Callable(btn_pick, "set_pressed").bind(false));
+ if (!picker_window) {
+ picker_window = memnew(Popup);
+ picker_window->hide();
+ picker_window->set_transient(true);
+ add_child(picker_window);
+
+ picker_texture_rect = memnew(TextureRect);
+ picker_texture_rect->set_anchors_preset(Control::PRESET_FULL_RECT);
+ picker_window->add_child(picker_texture_rect);
+ picker_texture_rect->set_default_cursor_shape(CURSOR_POINTING_HAND);
+ picker_texture_rect->connect(SNAME("gui_input"), callable_mp(this, &ColorPicker::_picker_texture_input));
+
+ picker_preview = memnew(Panel);
+ picker_preview->set_anchors_preset(Control::PRESET_CENTER_TOP);
+ picker_preview->set_mouse_filter(MOUSE_FILTER_IGNORE);
+ picker_window->add_child(picker_preview);
+
+ picker_preview_label = memnew(Label);
+ picker_preview->set_anchors_preset(Control::PRESET_CENTER_TOP);
+ picker_preview_label->set_text("Color Picking active");
+ picker_preview->add_child(picker_preview_label);
+
+ picker_preview_style_box = (Ref<StyleBoxFlat>)memnew(StyleBoxFlat);
+ picker_preview_style_box->set_bg_color(Color(1.0, 1.0, 1.0));
+ picker_preview->add_theme_style_override("panel", picker_preview_style_box);
+ }
+
+ Rect2i screen_rect;
+ if (picker_window->is_embedded()) {
+ screen_rect = picker_window->get_embedder()->get_visible_rect();
+ picker_window->set_position(Point2i());
+ picker_texture_rect->set_texture(ImageTexture::create_from_image(picker_window->get_embedder()->get_texture()->get_image()));
} else {
- screen->show();
+ screen_rect = picker_window->get_parent_rect();
+ picker_window->set_position(screen_rect.position);
+
+ Ref<Image> target_image = Image::create_empty(screen_rect.size.x, screen_rect.size.y, false, Image::FORMAT_RGB8);
+ DisplayServer *ds = DisplayServer::get_singleton();
+
+ // Add the Texture of each Window to the Image.
+ Vector<DisplayServer::WindowID> wl = ds->get_window_list();
+ // FIXME: sort windows by visibility.
+ for (int index = 0; index < wl.size(); index++) {
+ DisplayServer::WindowID wid = wl[index];
+ if (wid == DisplayServer::INVALID_WINDOW_ID) {
+ continue;
+ }
+
+ ObjectID woid = DisplayServer::get_singleton()->window_get_attached_instance_id(wid);
+ if (woid == ObjectID()) {
+ continue;
+ }
+
+ Window *w = Object::cast_to<Window>(ObjectDB::get_instance(woid));
+ Ref<Image> img = w->get_texture()->get_image();
+ if (!img.is_valid() || img->is_empty()) {
+ continue;
+ }
+ img->convert(Image::FORMAT_RGB8);
+ target_image->blit_rect(img, Rect2i(Point2i(0, 0), img->get_size()), w->get_position());
+ }
+
+ picker_texture_rect->set_texture(ImageTexture::create_from_image(target_image));
}
- screen->move_to_front();
- // TODO: show modal no longer works, needs to be converted to a popup.
- //screen->show_modal();
+
+ picker_window->set_size(screen_rect.size);
+ picker_preview->set_size(screen_rect.size / 10.0); // 10% of size in each axis.
+ picker_window->popup();
}
void ColorPicker::_html_focus_exit() {
@@ -1595,9 +1645,8 @@ ColorPicker::ColorPicker() {
btn_pick = memnew(Button);
sample_hbc->add_child(btn_pick);
- btn_pick->set_toggle_mode(true);
- btn_pick->set_tooltip_text(RTR("Pick a color from the editor window."));
- btn_pick->connect("pressed", callable_mp(this, &ColorPicker::_screen_pick_pressed));
+ btn_pick->set_tooltip_text(RTR("Pick a color from the application window."));
+ btn_pick->connect(SNAME("pressed"), callable_mp(this, &ColorPicker::_pick_button_pressed));
sample = memnew(TextureRect);
sample_hbc->add_child(sample);
diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h
index f7578612cd..d02c3278e6 100644
--- a/scene/gui/color_picker.h
+++ b/scene/gui/color_picker.h
@@ -40,6 +40,7 @@
#include "scene/gui/line_edit.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/option_button.h"
+#include "scene/gui/panel.h"
#include "scene/gui/popup.h"
#include "scene/gui/separator.h"
#include "scene/gui/slider.h"
@@ -111,7 +112,12 @@ private:
Vector<ColorMode *> modes;
- Control *screen = nullptr;
+ Popup *picker_window = nullptr;
+ TextureRect *picker_texture_rect = nullptr;
+ Panel *picker_preview = nullptr;
+ Label *picker_preview_label = nullptr;
+ Ref<StyleBoxFlat> picker_preview_style_box;
+ Color picker_color;
Control *uv_edit = nullptr;
Control *w_edit = nullptr;
AspectRatioContainer *wheel_edit = nullptr;
@@ -211,10 +217,10 @@ private:
void _line_edit_input(const Ref<InputEvent> &p_event);
void _preset_input(const Ref<InputEvent> &p_event, const Color &p_color);
void _recent_preset_pressed(const bool pressed, ColorPresetButton *p_preset);
- void _screen_input(const Ref<InputEvent> &p_event);
+ void _picker_texture_input(const Ref<InputEvent> &p_event);
void _text_changed(const String &p_new_text);
void _add_preset_pressed();
- void _screen_pick_pressed();
+ void _pick_button_pressed();
void _html_focus_exit();
inline int _get_preset_size();
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 5dd8cde342..ee065cccbf 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -347,14 +347,15 @@ void FileDialog::_action_pressed() {
}
}
- if (!valid) {
+ String file_name = file_text.strip_edges().get_file();
+ if (!valid || file_name.is_empty()) {
exterr->popup_centered(Size2(250, 80));
return;
}
if (dir_access->file_exists(f)) {
- confirm_save->set_text(RTR("File exists, overwrite?"));
- confirm_save->popup_centered(Size2(200, 80));
+ confirm_save->set_text(vformat(RTR("File \"%s\" already exists.\nDo you want to overwrite it?"), f));
+ confirm_save->popup_centered(Size2(250, 80));
} else {
emit_signal(SNAME("file_selected"), f);
hide();
@@ -1136,7 +1137,7 @@ FileDialog::FileDialog() {
add_child(mkdirerr, false, INTERNAL_MODE_FRONT);
exterr = memnew(AcceptDialog);
- exterr->set_text(RTR("Must use a valid extension."));
+ exterr->set_text(RTR("Invalid extension, or empty filename."));
add_child(exterr, false, INTERNAL_MODE_FRONT);
update_filters();
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index c0ef71ee4f..b861d7af01 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -86,9 +86,7 @@ int Label::get_line_height(int p_line) const {
}
}
-void Label::_shape() {
- bool font_was_dirty = font_dirty;
-
+bool Label::_shape() {
Ref<StyleBox> style = theme_cache.normal_style;
int width = (get_size().width - style->get_minimum_size().width);
@@ -103,7 +101,7 @@ void Label::_shape() {
}
const Ref<Font> &font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : theme_cache.font;
int font_size = settings.is_valid() ? settings->get_font_size() : theme_cache.font_size;
- ERR_FAIL_COND(font.is_null());
+ ERR_FAIL_COND_V(font.is_null(), true);
String txt = (uppercase) ? TS->string_to_upper(xl_text, language) : xl_text;
if (visible_chars >= 0 && visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) {
txt = txt.substr(0, visible_chars);
@@ -123,6 +121,7 @@ void Label::_shape() {
dirty = false;
font_dirty = false;
lines_dirty = true;
+ // Note for future maintainers: forgetting stable width here (e.g., setting it to -1) may fix still undiscovered bugs.
}
if (lines_dirty) {
@@ -135,129 +134,138 @@ void Label::_shape() {
Size2i prev_minsize = minsize;
minsize = Size2();
+ bool can_process_lines = false;
if (xl_text.length() == 0) {
+ can_process_lines = true;
lines_dirty = false;
- return;
- }
-
- // Don't compute minimum size until width is stable (two shape requests in a row with the same width.)
- // This avoids situations in which the initial width is very narrow and the label would break text
- // into many very short lines, causing a very tall label that can leave a deformed container.
- bool width_stabilized = get_size().width == stable_width;
- stable_width = get_size().width;
+ } else {
+ // With autowrap on or off with trimming enabled, we won't compute the minimum size until width is stable
+ // (two shape requests in a row with the same width.) This avoids situations in which the initial width is
+ // very narrow and the label would break text into many very short lines, causing a very tall label that can
+ // leave a deformed container. In the remaining case (namely, autowrap off and no trimming), the label is
+ // free to dictate its own width, something that will be taken advtantage of.
+ bool can_dictate_width = autowrap_mode == TextServer::AUTOWRAP_OFF && overrun_behavior == TextServer::OVERRUN_NO_TRIMMING;
+ bool is_width_stable = get_size().width == stable_width;
+ can_process_lines = can_dictate_width || is_width_stable;
+ stable_width = get_size().width;
+
+ if (can_process_lines) {
+ if (lines_dirty) {
+ BitField<TextServer::LineBreakFlag> autowrap_flags = TextServer::BREAK_MANDATORY;
+ switch (autowrap_mode) {
+ case TextServer::AUTOWRAP_WORD_SMART:
+ autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_ADAPTIVE | TextServer::BREAK_MANDATORY;
+ break;
+ case TextServer::AUTOWRAP_WORD:
+ autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_MANDATORY;
+ break;
+ case TextServer::AUTOWRAP_ARBITRARY:
+ autowrap_flags = TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_MANDATORY;
+ break;
+ case TextServer::AUTOWRAP_OFF:
+ break;
+ }
+ autowrap_flags = autowrap_flags | TextServer::BREAK_TRIM_EDGE_SPACES;
- // With autowrap off, there's still a point in shaping before width is stable: to contribute a min width.
- if (lines_dirty && (width_stabilized || autowrap_mode == TextServer::AUTOWRAP_OFF)) {
- BitField<TextServer::LineBreakFlag> autowrap_flags = TextServer::BREAK_MANDATORY;
- switch (autowrap_mode) {
- case TextServer::AUTOWRAP_WORD_SMART:
- autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_ADAPTIVE | TextServer::BREAK_MANDATORY;
- break;
- case TextServer::AUTOWRAP_WORD:
- autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_MANDATORY;
- break;
- case TextServer::AUTOWRAP_ARBITRARY:
- autowrap_flags = TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_MANDATORY;
- break;
- case TextServer::AUTOWRAP_OFF:
- break;
- }
- autowrap_flags = autowrap_flags | TextServer::BREAK_TRIM_EDGE_SPACES;
+ PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags);
+ for (int i = 0; i < line_breaks.size(); i = i + 2) {
+ RID line = TS->shaped_text_substr(text_rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]);
+ lines_rid.push_back(line);
+ }
+ }
- PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags);
- for (int i = 0; i < line_breaks.size(); i = i + 2) {
- RID line = TS->shaped_text_substr(text_rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]);
- lines_rid.push_back(line);
- }
- }
+ if (can_dictate_width) {
+ for (int i = 0; i < lines_rid.size(); i++) {
+ if (minsize.width < TS->shaped_text_get_size(lines_rid[i]).x) {
+ minsize.width = TS->shaped_text_get_size(lines_rid[i]).x;
+ }
+ }
- if (autowrap_mode == TextServer::AUTOWRAP_OFF) {
- for (int i = 0; i < lines_rid.size(); i++) {
- if (minsize.width < TS->shaped_text_get_size(lines_rid[i]).x) {
- minsize.width = TS->shaped_text_get_size(lines_rid[i]).x;
+ width = (minsize.width - style->get_minimum_size().width);
}
- }
- // With autowrap off, by now we already know the width the label will take.
- width = (minsize.width - style->get_minimum_size().width);
- width_stabilized = true;
- }
-
- if (lines_dirty && width_stabilized) {
- BitField<TextServer::TextOverrunFlag> overrun_flags = TextServer::OVERRUN_NO_TRIM;
- switch (overrun_behavior) {
- case TextServer::OVERRUN_TRIM_WORD_ELLIPSIS:
- overrun_flags.set_flag(TextServer::OVERRUN_TRIM);
- overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY);
- overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS);
- break;
- case TextServer::OVERRUN_TRIM_ELLIPSIS:
- overrun_flags.set_flag(TextServer::OVERRUN_TRIM);
- overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS);
- break;
- case TextServer::OVERRUN_TRIM_WORD:
- overrun_flags.set_flag(TextServer::OVERRUN_TRIM);
- overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY);
- break;
- case TextServer::OVERRUN_TRIM_CHAR:
- overrun_flags.set_flag(TextServer::OVERRUN_TRIM);
- break;
- case TextServer::OVERRUN_NO_TRIMMING:
- break;
- }
+ if (lines_dirty) {
+ BitField<TextServer::TextOverrunFlag> overrun_flags = TextServer::OVERRUN_NO_TRIM;
+ switch (overrun_behavior) {
+ case TextServer::OVERRUN_TRIM_WORD_ELLIPSIS:
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM);
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY);
+ overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS);
+ break;
+ case TextServer::OVERRUN_TRIM_ELLIPSIS:
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM);
+ overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS);
+ break;
+ case TextServer::OVERRUN_TRIM_WORD:
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM);
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY);
+ break;
+ case TextServer::OVERRUN_TRIM_CHAR:
+ overrun_flags.set_flag(TextServer::OVERRUN_TRIM);
+ break;
+ case TextServer::OVERRUN_NO_TRIMMING:
+ break;
+ }
- // Fill after min_size calculation.
+ // Fill after min_size calculation.
- int visible_lines = lines_rid.size();
- if (max_lines_visible >= 0 && visible_lines > max_lines_visible) {
- visible_lines = max_lines_visible;
- }
- if (autowrap_mode != TextServer::AUTOWRAP_OFF) {
- bool lines_hidden = visible_lines > 0 && visible_lines < lines_rid.size();
- if (lines_hidden) {
- overrun_flags.set_flag(TextServer::OVERRUN_ENFORCE_ELLIPSIS);
- }
- if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) {
- for (int i = 0; i < lines_rid.size(); i++) {
- if (i < visible_lines - 1 || lines_rid.size() == 1) {
- TS->shaped_text_fit_to_width(lines_rid[i], width);
- } else if (i == (visible_lines - 1)) {
+ int visible_lines = lines_rid.size();
+ if (max_lines_visible >= 0 && visible_lines > max_lines_visible) {
+ visible_lines = max_lines_visible;
+ }
+ if (autowrap_mode != TextServer::AUTOWRAP_OFF) {
+ bool lines_hidden = visible_lines > 0 && visible_lines < lines_rid.size();
+ if (lines_hidden) {
+ overrun_flags.set_flag(TextServer::OVERRUN_ENFORCE_ELLIPSIS);
+ }
+ if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) {
+ for (int i = 0; i < lines_rid.size(); i++) {
+ if (i < visible_lines - 1 || lines_rid.size() == 1) {
+ TS->shaped_text_fit_to_width(lines_rid[i], width);
+ } else if (i == (visible_lines - 1)) {
+ TS->shaped_text_overrun_trim_to_width(lines_rid[visible_lines - 1], width, overrun_flags);
+ }
+ }
+ } else if (lines_hidden) {
TS->shaped_text_overrun_trim_to_width(lines_rid[visible_lines - 1], width, overrun_flags);
}
- }
- } else if (lines_hidden) {
- TS->shaped_text_overrun_trim_to_width(lines_rid[visible_lines - 1], width, overrun_flags);
- }
- } else {
- // Autowrap disabled.
- for (int i = 0; i < lines_rid.size(); i++) {
- if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) {
- TS->shaped_text_fit_to_width(lines_rid[i], width);
- overrun_flags.set_flag(TextServer::OVERRUN_JUSTIFICATION_AWARE);
- TS->shaped_text_overrun_trim_to_width(lines_rid[i], width, overrun_flags);
- TS->shaped_text_fit_to_width(lines_rid[i], width, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS);
} else {
- TS->shaped_text_overrun_trim_to_width(lines_rid[i], width, overrun_flags);
+ // Autowrap disabled.
+ for (int i = 0; i < lines_rid.size(); i++) {
+ if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) {
+ TS->shaped_text_fit_to_width(lines_rid[i], width);
+ overrun_flags.set_flag(TextServer::OVERRUN_JUSTIFICATION_AWARE);
+ TS->shaped_text_overrun_trim_to_width(lines_rid[i], width, overrun_flags);
+ TS->shaped_text_fit_to_width(lines_rid[i], width, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS);
+ } else {
+ TS->shaped_text_overrun_trim_to_width(lines_rid[i], width, overrun_flags);
+ }
+ }
+ }
+
+ int last_line = MIN(lines_rid.size(), visible_lines + lines_skipped);
+ int line_spacing = settings.is_valid() ? settings->get_line_spacing() : theme_cache.line_spacing;
+ for (int64_t i = lines_skipped; i < last_line; i++) {
+ minsize.height += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing;
}
- }
- }
- int last_line = MIN(lines_rid.size(), visible_lines + lines_skipped);
- int line_spacing = settings.is_valid() ? settings->get_line_spacing() : theme_cache.line_spacing;
- for (int64_t i = lines_skipped; i < last_line; i++) {
- minsize.height += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing;
+ lines_dirty = false;
+ }
+ } else {
+ callable_mp(this, &Label::_shape).call_deferred();
}
+ }
- lines_dirty = false;
+ if (draw_pending) {
+ queue_redraw();
+ draw_pending = false;
}
- if (minsize != prev_minsize || font_was_dirty) {
+ if (minsize != prev_minsize) {
update_minimum_size();
}
- if (!width_stabilized) {
- callable_mp(this, &Label::_shape).call_deferred();
- }
+ return can_process_lines;
}
inline void draw_glyph(const Glyph &p_gl, const RID &p_canvas, const Color &p_font_color, const Vector2 &p_ofs) {
@@ -367,10 +375,9 @@ void Label::_notification(int p_what) {
}
if (dirty || font_dirty || lines_dirty) {
- _shape();
- if (lines_dirty) {
+ if (!_shape()) {
// There will be another pass.
- queue_redraw();
+ draw_pending = true;
break;
}
}
@@ -396,7 +403,7 @@ void Label::_notification(int p_what) {
style->draw(ci, Rect2(Point2(0, 0), get_size()));
float total_h = 0.0;
- int visible_lines = 0;
+ int lines_visible = 0;
// Get number of lines to fit to the height.
for (int64_t i = lines_skipped; i < lines_rid.size(); i++) {
@@ -404,14 +411,14 @@ void Label::_notification(int p_what) {
if (total_h > (get_size().height - style->get_minimum_size().height + line_spacing)) {
break;
}
- visible_lines++;
+ lines_visible++;
}
- if (max_lines_visible >= 0 && visible_lines > max_lines_visible) {
- visible_lines = max_lines_visible;
+ if (max_lines_visible >= 0 && lines_visible > max_lines_visible) {
+ lines_visible = max_lines_visible;
}
- int last_line = MIN(lines_rid.size(), visible_lines + lines_skipped);
+ int last_line = MIN(lines_rid.size(), lines_visible + lines_skipped);
bool trim_chars = (visible_chars >= 0) && (visible_chars_behavior == TextServer::VC_CHARS_AFTER_SHAPING);
bool trim_glyphs_ltr = (visible_chars >= 0) && ((visible_chars_behavior == TextServer::VC_GLYPHS_LTR) || ((visible_chars_behavior == TextServer::VC_GLYPHS_AUTO) && !rtl_layout));
bool trim_glyphs_rtl = (visible_chars >= 0) && ((visible_chars_behavior == TextServer::VC_GLYPHS_RTL) || ((visible_chars_behavior == TextServer::VC_GLYPHS_AUTO) && rtl_layout));
@@ -428,7 +435,7 @@ void Label::_notification(int p_what) {
total_h += style->get_margin(SIDE_TOP) + style->get_margin(SIDE_BOTTOM);
int vbegin = 0, vsep = 0;
- if (visible_lines > 0) {
+ if (lines_visible > 0) {
switch (vertical_alignment) {
case VERTICAL_ALIGNMENT_TOP: {
// Nothing.
@@ -445,8 +452,8 @@ void Label::_notification(int p_what) {
} break;
case VERTICAL_ALIGNMENT_FILL: {
vbegin = 0;
- if (visible_lines > 1) {
- vsep = (size.y - (total_h - line_spacing)) / (visible_lines - 1);
+ if (lines_visible > 1) {
+ vsep = (size.y - (total_h - line_spacing)) / (lines_visible - 1);
} else {
vsep = 0;
}
@@ -615,6 +622,8 @@ void Label::_notification(int p_what) {
}
ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + vsep + line_spacing;
}
+
+ draw_pending = false;
} break;
case NOTIFICATION_THEME_CHANGED: {
@@ -666,25 +675,25 @@ int Label::get_line_count() const {
int Label::get_visible_line_count() const {
Ref<StyleBox> style = theme_cache.normal_style;
int line_spacing = settings.is_valid() ? settings->get_line_spacing() : theme_cache.line_spacing;
- int visible_lines = 0;
+ int lines_visible = 0;
float total_h = 0.0;
for (int64_t i = lines_skipped; i < lines_rid.size(); i++) {
total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing;
if (total_h > (get_size().height - style->get_minimum_size().height + line_spacing)) {
break;
}
- visible_lines++;
+ lines_visible++;
}
- if (visible_lines > lines_rid.size()) {
- visible_lines = lines_rid.size();
+ if (lines_visible > lines_rid.size()) {
+ lines_visible = lines_rid.size();
}
- if (max_lines_visible >= 0 && visible_lines > max_lines_visible) {
- visible_lines = max_lines_visible;
+ if (max_lines_visible >= 0 && lines_visible > max_lines_visible) {
+ lines_visible = max_lines_visible;
}
- return visible_lines;
+ return lines_visible;
}
void Label::set_horizontal_alignment(HorizontalAlignment p_alignment) {
@@ -969,7 +978,7 @@ void Label::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_visible_ratio"), &Label::get_visible_ratio);
ClassDB::bind_method(D_METHOD("set_lines_skipped", "lines_skipped"), &Label::set_lines_skipped);
ClassDB::bind_method(D_METHOD("get_lines_skipped"), &Label::get_lines_skipped);
- ClassDB::bind_method(D_METHOD("set_max_lines_visible", "visible_lines"), &Label::set_max_lines_visible);
+ ClassDB::bind_method(D_METHOD("set_max_lines_visible", "lines_visible"), &Label::set_max_lines_visible);
ClassDB::bind_method(D_METHOD("get_max_lines_visible"), &Label::get_max_lines_visible);
ClassDB::bind_method(D_METHOD("set_structured_text_bidi_override", "parser"), &Label::set_structured_text_bidi_override);
ClassDB::bind_method(D_METHOD("get_structured_text_bidi_override"), &Label::get_structured_text_bidi_override);
diff --git a/scene/gui/label.h b/scene/gui/label.h
index 448cb245eb..36b85f7af8 100644
--- a/scene/gui/label.h
+++ b/scene/gui/label.h
@@ -50,7 +50,6 @@ private:
bool uppercase = false;
bool lines_dirty = true;
-
bool dirty = true;
bool font_dirty = true;
RID text_rid;
@@ -66,6 +65,7 @@ private:
float visible_ratio = 1.0;
int lines_skipped = 0;
int max_lines_visible = -1;
+ bool draw_pending = false;
Ref<LabelSettings> settings;
@@ -83,7 +83,7 @@ private:
int font_shadow_outline_size;
} theme_cache;
- void _shape();
+ bool _shape();
void _invalidate();
protected:
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 2c1c44322a..973b02b3a3 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -1179,7 +1179,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
dot_ul_started = false;
float y_off = TS->shaped_text_get_underline_position(rid);
float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale;
- draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, underline_width * 2);
+ draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, MAX(2.0, underline_width * 2));
}
if (_find_strikethrough(it)) {
if (!st_started) {
@@ -1341,7 +1341,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
dot_ul_started = false;
float y_off = TS->shaped_text_get_underline_position(rid);
float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale;
- draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, underline_width * 2);
+ draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, MAX(2.0, underline_width * 2));
}
if (st_started) {
st_started = false;
@@ -1363,7 +1363,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
dot_ul_started = false;
float y_off = TS->shaped_text_get_underline_position(rid);
float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale;
- draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, underline_width * 2);
+ draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, MAX(2.0, underline_width * 2));
}
if (st_started) {
st_started = false;
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index e5dcdd2afd..b36353158b 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -513,14 +513,16 @@ bool CanvasItem::is_y_sort_enabled() const {
void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, real_t p_dash, bool p_aligned) {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
+ ERR_FAIL_COND(p_dash <= 0.0);
float length = (p_to - p_from).length();
- if (length < p_dash) {
+ Vector2 step = p_dash * (p_to - p_from).normalized();
+
+ if (length < p_dash || step == Vector2()) {
RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width);
return;
}
- Vector2 step = p_dash * (p_to - p_from).normalized();
int steps = (p_aligned) ? Math::ceil(length / p_dash) : Math::floor(length / p_dash);
if (steps % 2 == 0) {
steps--;
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 126b1d54fc..244e0d5b93 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -1330,7 +1330,7 @@ void Viewport::_gui_show_tooltip() {
Window *window = gui.tooltip_popup->get_parent_visible_window();
Rect2i vr;
if (gui.tooltip_popup->is_embedded()) {
- vr = gui.tooltip_popup->_get_embedder()->get_visible_rect();
+ vr = gui.tooltip_popup->get_embedder()->get_visible_rect();
} else {
vr = window->get_usable_parent_rect();
}
@@ -1851,7 +1851,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Window *w = Object::cast_to<Window>(this);
if (w) {
if (w->is_embedded()) {
- embedder = w->_get_embedder();
+ embedder = w->get_embedder();
viewport_pos = get_final_transform().xform(mpos) + w->get_position(); // To parent coords.
}
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index b79a9ba444..59e3d307c6 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -485,7 +485,7 @@ void Window::set_ime_position(const Point2i &p_pos) {
bool Window::is_embedded() const {
ERR_FAIL_COND_V(!is_inside_tree(), false);
- return _get_embedder() != nullptr;
+ return get_embedder() != nullptr;
}
bool Window::is_in_edited_scene_root() const {
@@ -710,7 +710,7 @@ void Window::set_visible(bool p_visible) {
// Stop any queued resizing, as the window will be resized right now.
updating_child_controls = false;
- Viewport *embedder_vp = _get_embedder();
+ Viewport *embedder_vp = get_embedder();
if (!embedder_vp) {
if (!p_visible && window_id != DisplayServer::INVALID_WINDOW_ID) {
@@ -1053,7 +1053,7 @@ void Window::_update_window_callbacks() {
DisplayServer::get_singleton()->window_set_drop_files_callback(callable_mp(this, &Window::_window_drop_files), window_id);
}
-Viewport *Window::_get_embedder() const {
+Viewport *Window::get_embedder() const {
Viewport *vp = get_parent_viewport();
while (vp) {
@@ -1088,7 +1088,7 @@ void Window::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
bool embedded = false;
{
- embedder = _get_embedder();
+ embedder = get_embedder();
if (embedder) {
embedded = true;
if (!visible) {
@@ -1431,7 +1431,7 @@ void Window::popup_centered_clamped(const Size2i &p_size, float p_fallback_ratio
Rect2 parent_rect;
if (is_embedded()) {
- parent_rect = _get_embedder()->get_visible_rect();
+ parent_rect = get_embedder()->get_visible_rect();
} else {
DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id();
int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id);
@@ -1462,7 +1462,7 @@ void Window::popup_centered(const Size2i &p_minsize) {
Rect2 parent_rect;
if (is_embedded()) {
- parent_rect = _get_embedder()->get_visible_rect();
+ parent_rect = get_embedder()->get_visible_rect();
} else {
DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id();
int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id);
@@ -1488,7 +1488,7 @@ void Window::popup_centered_ratio(float p_ratio) {
Rect2 parent_rect;
if (is_embedded()) {
- parent_rect = _get_embedder()->get_visible_rect();
+ parent_rect = get_embedder()->get_visible_rect();
} else {
DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id();
int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id);
@@ -1509,7 +1509,7 @@ void Window::popup_centered_ratio(float p_ratio) {
void Window::popup(const Rect2i &p_screen_rect) {
emit_signal(SNAME("about_to_popup"));
- if (!_get_embedder() && get_flag(FLAG_POPUP)) {
+ if (!get_embedder() && get_flag(FLAG_POPUP)) {
// Send a focus-out notification when opening a Window Manager Popup.
SceneTree *scene_tree = get_tree();
if (scene_tree) {
@@ -1545,7 +1545,7 @@ void Window::popup(const Rect2i &p_screen_rect) {
Rect2i parent_rect;
if (is_embedded()) {
- parent_rect = _get_embedder()->get_visible_rect();
+ parent_rect = get_embedder()->get_visible_rect();
} else {
int screen_id = DisplayServer::get_singleton()->window_get_current_screen(get_window_id());
parent_rect = DisplayServer::get_singleton()->screen_get_usable_rect(screen_id);
@@ -1587,7 +1587,7 @@ Rect2i Window::get_usable_parent_rect() const {
ERR_FAIL_COND_V(!is_inside_tree(), Rect2());
Rect2i parent_rect;
if (is_embedded()) {
- parent_rect = _get_embedder()->get_visible_rect();
+ parent_rect = get_embedder()->get_visible_rect();
} else {
const Window *w = is_visible() ? this : get_parent_visible_window();
//find a parent that can contain us
@@ -2154,9 +2154,9 @@ Transform2D Window::get_final_transform() const {
Transform2D Window::get_screen_transform_internal(bool p_absolute_position) const {
Transform2D embedder_transform;
- if (_get_embedder()) {
+ if (get_embedder()) {
embedder_transform.translate_local(get_position());
- embedder_transform = _get_embedder()->get_screen_transform_internal(p_absolute_position) * embedder_transform;
+ embedder_transform = get_embedder()->get_screen_transform_internal(p_absolute_position) * embedder_transform;
} else if (p_absolute_position) {
embedder_transform.translate_local(get_position());
}
@@ -2170,8 +2170,8 @@ Transform2D Window::get_popup_base_transform() const {
Transform2D popup_base_transform;
popup_base_transform.set_origin(get_position());
popup_base_transform *= get_final_transform();
- if (_get_embedder()) {
- return _get_embedder()->get_popup_base_transform() * popup_base_transform;
+ if (get_embedder()) {
+ return get_embedder()->get_popup_base_transform() * popup_base_transform;
}
return popup_base_transform;
}
diff --git a/scene/main/window.h b/scene/main/window.h
index 5359c37e9a..40b629ed11 100644
--- a/scene/main/window.h
+++ b/scene/main/window.h
@@ -192,7 +192,6 @@ private:
Ref<Shortcut> debugger_stop_shortcut;
protected:
- Viewport *_get_embedder() const;
virtual Rect2i _popup_adjust_rect() const { return Rect2i(); }
virtual void _update_theme_item_cache();
@@ -278,6 +277,7 @@ public:
void set_ime_position(const Point2i &p_pos);
bool is_embedded() const;
+ Viewport *get_embedder() const;
void set_content_scale_size(const Size2i &p_size);
Size2i get_content_scale_size() const;
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index 7e3156d2ff..05be40c446 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -2566,73 +2566,6 @@ void GradientTexture2D::_bind_methods() {
//////////////////////////////////////
-void ProxyTexture::set_base(const Ref<Texture2D> &p_texture) {
- ERR_FAIL_COND(p_texture == this);
-
- base = p_texture;
- if (base.is_valid()) {
- ERR_FAIL_NULL(RenderingServer::get_singleton());
- if (proxy_ph.is_valid()) {
- RS::get_singleton()->texture_proxy_update(proxy, base->get_rid());
- RS::get_singleton()->free(proxy_ph);
- proxy_ph = RID();
- } else if (proxy.is_valid()) {
- RS::get_singleton()->texture_proxy_update(proxy, base->get_rid());
- } else {
- proxy = RS::get_singleton()->texture_proxy_create(base->get_rid());
- }
- }
-}
-
-Ref<Texture2D> ProxyTexture::get_base() const {
- return base;
-}
-
-int ProxyTexture::get_width() const {
- if (base.is_valid()) {
- return base->get_width();
- }
- return 1;
-}
-
-int ProxyTexture::get_height() const {
- if (base.is_valid()) {
- return base->get_height();
- }
- return 1;
-}
-
-RID ProxyTexture::get_rid() const {
- if (proxy.is_null()) {
- proxy_ph = RS::get_singleton()->texture_2d_placeholder_create();
- proxy = RS::get_singleton()->texture_proxy_create(proxy_ph);
- }
- return proxy;
-}
-
-bool ProxyTexture::has_alpha() const {
- if (base.is_valid()) {
- return base->has_alpha();
- }
- return false;
-}
-
-ProxyTexture::ProxyTexture() {
- //proxy = RS::get_singleton()->texture_create();
-}
-
-ProxyTexture::~ProxyTexture() {
- ERR_FAIL_NULL(RenderingServer::get_singleton());
- if (proxy_ph.is_valid()) {
- RS::get_singleton()->free(proxy_ph);
- }
- if (proxy.is_valid()) {
- RS::get_singleton()->free(proxy);
- }
-}
-
-//////////////////////////////////////////////
-
void AnimatedTexture::_update_proxy() {
RWLockRead r(rw_lock);
@@ -2704,6 +2637,7 @@ void AnimatedTexture::set_current_frame(int p_frame) {
RWLockWrite r(rw_lock);
current_frame = p_frame;
+ time = 0;
}
int AnimatedTexture::get_current_frame() const {
diff --git a/scene/resources/texture.h b/scene/resources/texture.h
index 7f74ae6941..7c4d479da8 100644
--- a/scene/resources/texture.h
+++ b/scene/resources/texture.h
@@ -892,29 +892,6 @@ public:
VARIANT_ENUM_CAST(GradientTexture2D::Fill);
VARIANT_ENUM_CAST(GradientTexture2D::Repeat);
-class ProxyTexture : public Texture2D {
-private:
- mutable RID proxy_ph;
- mutable RID proxy;
- Ref<Texture2D> base;
-
-protected:
- static void _bind_methods();
-
-public:
- void set_base(const Ref<Texture2D> &p_texture);
- Ref<Texture2D> get_base() const;
-
- virtual int get_width() const override;
- virtual int get_height() const override;
- virtual RID get_rid() const override;
-
- virtual bool has_alpha() const override;
-
- ProxyTexture();
- ~ProxyTexture();
-};
-
class AnimatedTexture : public Texture2D {
GDCLASS(AnimatedTexture, Texture2D);
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index fee0a4a910..d4b2be355e 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -3308,7 +3308,7 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const {
void TileSet::_get_property_list(List<PropertyInfo> *p_list) const {
PropertyInfo property_info;
// Rendering.
- p_list->push_back(PropertyInfo(Variant::NIL, "Rendering", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
+ p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Rendering", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
for (int i = 0; i < occlusion_layers.size(); i++) {
p_list->push_back(PropertyInfo(Variant::INT, vformat("occlusion_layer_%d/light_mask", i), PROPERTY_HINT_LAYERS_2D_RENDER));
@@ -3321,7 +3321,7 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const {
}
// Physics.
- p_list->push_back(PropertyInfo(Variant::NIL, "Physics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
+ p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Physics", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
for (int i = 0; i < physics_layers.size(); i++) {
p_list->push_back(PropertyInfo(Variant::INT, vformat("physics_layer_%d/collision_layer", i), PROPERTY_HINT_LAYERS_2D_PHYSICS));
@@ -3341,7 +3341,7 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const {
}
// Terrains.
- p_list->push_back(PropertyInfo(Variant::NIL, "Terrains", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
+ p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Terrains", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
for (int terrain_set_index = 0; terrain_set_index < terrain_sets.size(); terrain_set_index++) {
p_list->push_back(PropertyInfo(Variant::INT, vformat("terrain_set_%d/mode", terrain_set_index), PROPERTY_HINT_ENUM, "Match Corners and Sides,Match Corners,Match Sides"));
p_list->push_back(PropertyInfo(Variant::NIL, vformat("terrain_set_%d/terrains", terrain_set_index), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ARRAY, vformat("terrain_set_%d/terrain_", terrain_set_index)));
@@ -3352,7 +3352,7 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const {
}
// Navigation.
- p_list->push_back(PropertyInfo(Variant::NIL, "Navigation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
+ p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Navigation", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
for (int i = 0; i < navigation_layers.size(); i++) {
p_list->push_back(PropertyInfo(Variant::INT, vformat("navigation_layer_%d/layers", i), PROPERTY_HINT_LAYERS_2D_NAVIGATION));
}
@@ -3362,7 +3362,7 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const {
for (int i = 1; i < Variant::VARIANT_MAX; i++) {
argt += "," + Variant::get_type_name(Variant::Type(i));
}
- p_list->push_back(PropertyInfo(Variant::NIL, "Custom data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
+ p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Custom Data", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
for (int i = 0; i < custom_data_layers.size(); i++) {
p_list->push_back(PropertyInfo(Variant::STRING, vformat("custom_data_layer_%d/name", i)));
p_list->push_back(PropertyInfo(Variant::INT, vformat("custom_data_layer_%d/type", i), PROPERTY_HINT_ENUM, argt));
@@ -3376,10 +3376,10 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const {
// Tile Proxies.
// Note: proxies need to be set after sources are set.
- p_list->push_back(PropertyInfo(Variant::NIL, "Tile Proxies", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
- p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/source_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
- p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/coords_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
- p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/alternative_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
+ p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Tile Proxies", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
+ p_list->push_back(PropertyInfo(Variant::ARRAY, PNAME("tile_proxies/source_level"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
+ p_list->push_back(PropertyInfo(Variant::ARRAY, PNAME("tile_proxies/coords_level"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
+ p_list->push_back(PropertyInfo(Variant::ARRAY, PNAME("tile_proxies/alternative_level"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
// Patterns.
for (unsigned int pattern_index = 0; pattern_index < patterns.size(); pattern_index++) {
@@ -4887,9 +4887,9 @@ bool TileSetScenesCollectionSource::_get(const StringName &p_name, Variant &r_re
void TileSetScenesCollectionSource::_get_property_list(List<PropertyInfo> *p_list) const {
for (int i = 0; i < scenes_ids.size(); i++) {
- p_list->push_back(PropertyInfo(Variant::OBJECT, vformat("scenes/%d/scene", scenes_ids[i]), PROPERTY_HINT_RESOURCE_TYPE, "TileSetScenesCollectionSource"));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, vformat("%s/%d/%s", PNAME("scenes"), scenes_ids[i], PNAME("scene")), PROPERTY_HINT_RESOURCE_TYPE, "TileSetScenesCollectionSource"));
- PropertyInfo property_info = PropertyInfo(Variant::BOOL, vformat("scenes/%d/display_placeholder", scenes_ids[i]));
+ PropertyInfo property_info = PropertyInfo(Variant::BOOL, vformat("%s/%d/%s", PNAME("scenes"), scenes_ids[i], PNAME("display_placeholder")));
if (scenes[scenes_ids[i]].display_placeholder == false) {
property_info.usage ^= PROPERTY_USAGE_STORAGE;
}
@@ -5692,10 +5692,10 @@ void TileData::_get_property_list(List<PropertyInfo> *p_list) const {
// Add the groups manually.
if (tile_set) {
// Occlusion layers.
- p_list->push_back(PropertyInfo(Variant::NIL, "Rendering", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
+ p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Rendering", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
for (int i = 0; i < occluders.size(); i++) {
// occlusion_layer_%d/polygon
- property_info = PropertyInfo(Variant::OBJECT, vformat("occlusion_layer_%d/polygon", i), PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D", PROPERTY_USAGE_DEFAULT);
+ property_info = PropertyInfo(Variant::OBJECT, vformat("occlusion_layer_%d/%s", i, PNAME("polygon")), PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D", PROPERTY_USAGE_DEFAULT);
if (!occluders[i].is_valid()) {
property_info.usage ^= PROPERTY_USAGE_STORAGE;
}
@@ -5703,29 +5703,29 @@ void TileData::_get_property_list(List<PropertyInfo> *p_list) const {
}
// Physics layers.
- p_list->push_back(PropertyInfo(Variant::NIL, "Physics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
+ p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Physics", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
for (int i = 0; i < physics.size(); i++) {
- p_list->push_back(PropertyInfo(Variant::VECTOR2, vformat("physics_layer_%d/linear_velocity", i), PROPERTY_HINT_NONE));
- p_list->push_back(PropertyInfo(Variant::FLOAT, vformat("physics_layer_%d/angular_velocity", i), PROPERTY_HINT_NONE));
- p_list->push_back(PropertyInfo(Variant::INT, vformat("physics_layer_%d/polygons_count", i), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2, vformat("physics_layer_%d/%s", i, PNAME("linear_velocity")), PROPERTY_HINT_NONE));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, vformat("physics_layer_%d/%s", i, PNAME("angular_velocity")), PROPERTY_HINT_NONE));
+ p_list->push_back(PropertyInfo(Variant::INT, vformat("physics_layer_%d/%s", i, PNAME("polygons_count")), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
for (int j = 0; j < physics[i].polygons.size(); j++) {
// physics_layer_%d/points
- property_info = PropertyInfo(Variant::ARRAY, vformat("physics_layer_%d/polygon_%d/points", i, j), PROPERTY_HINT_ARRAY_TYPE, "Vector2", PROPERTY_USAGE_DEFAULT);
+ property_info = PropertyInfo(Variant::ARRAY, vformat("physics_layer_%d/polygon_%d/%s", i, j, PNAME("points")), PROPERTY_HINT_ARRAY_TYPE, "Vector2", PROPERTY_USAGE_DEFAULT);
if (physics[i].polygons[j].polygon.is_empty()) {
property_info.usage ^= PROPERTY_USAGE_STORAGE;
}
p_list->push_back(property_info);
// physics_layer_%d/polygon_%d/one_way
- property_info = PropertyInfo(Variant::BOOL, vformat("physics_layer_%d/polygon_%d/one_way", i, j));
+ property_info = PropertyInfo(Variant::BOOL, vformat("physics_layer_%d/polygon_%d/%s", i, j, PNAME("one_way")));
if (physics[i].polygons[j].one_way == false) {
property_info.usage ^= PROPERTY_USAGE_STORAGE;
}
p_list->push_back(property_info);
// physics_layer_%d/polygon_%d/one_way_margin
- property_info = PropertyInfo(Variant::FLOAT, vformat("physics_layer_%d/polygon_%d/one_way_margin", i, j));
+ property_info = PropertyInfo(Variant::FLOAT, vformat("physics_layer_%d/polygon_%d/%s", i, j, PNAME("one_way_margin")));
if (physics[i].polygons[j].one_way_margin == 1.0) {
property_info.usage ^= PROPERTY_USAGE_STORAGE;
}
@@ -5735,7 +5735,7 @@ void TileData::_get_property_list(List<PropertyInfo> *p_list) const {
// Terrain data
if (terrain_set >= 0) {
- p_list->push_back(PropertyInfo(Variant::NIL, "Terrains", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
+ p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Terrains", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
if (is_valid_terrain_peering_bit(bit)) {
@@ -5749,9 +5749,9 @@ void TileData::_get_property_list(List<PropertyInfo> *p_list) const {
}
// Navigation layers.
- p_list->push_back(PropertyInfo(Variant::NIL, "Navigation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
+ p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Navigation", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
for (int i = 0; i < navigation.size(); i++) {
- property_info = PropertyInfo(Variant::OBJECT, vformat("navigation_layer_%d/polygon", i), PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon", PROPERTY_USAGE_DEFAULT);
+ property_info = PropertyInfo(Variant::OBJECT, vformat("navigation_layer_%d/%s", i, PNAME("polygon")), PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon", PROPERTY_USAGE_DEFAULT);
if (!navigation[i].is_valid()) {
property_info.usage ^= PROPERTY_USAGE_STORAGE;
}
@@ -5759,7 +5759,7 @@ void TileData::_get_property_list(List<PropertyInfo> *p_list) const {
}
// Custom data layers.
- p_list->push_back(PropertyInfo(Variant::NIL, "Custom data", PROPERTY_HINT_NONE, "custom_data_", PROPERTY_USAGE_GROUP));
+ p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Custom Data", "custom_data_"), PROPERTY_HINT_NONE, "custom_data_", PROPERTY_USAGE_GROUP));
for (int i = 0; i < custom_data.size(); i++) {
Variant default_val;
Callable::CallError error;
diff --git a/servers/audio/effects/audio_effect_pitch_shift.cpp b/servers/audio/effects/audio_effect_pitch_shift.cpp
index 2693b2a56a..11c1d44472 100644
--- a/servers/audio/effects/audio_effect_pitch_shift.cpp
+++ b/servers/audio/effects/audio_effect_pitch_shift.cpp
@@ -309,7 +309,7 @@ Ref<AudioEffectInstance> AudioEffectPitchShift::instantiate() {
}
void AudioEffectPitchShift::set_pitch_scale(float p_pitch_scale) {
- ERR_FAIL_COND(p_pitch_scale <= 0.0);
+ ERR_FAIL_COND(!(p_pitch_scale > 0.0));
pitch_scale = p_pitch_scale;
}
diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp
index 668b1dffc3..273bb9ceda 100644
--- a/servers/navigation_server_2d.cpp
+++ b/servers/navigation_server_2d.cpp
@@ -152,14 +152,15 @@ void NavigationServer2D::_emit_map_changed(RID p_map) {
emit_signal(SNAME("map_changed"), p_map);
}
-#ifdef DEBUG_ENABLED
void NavigationServer2D::set_debug_enabled(bool p_enabled) {
NavigationServer3D::get_singleton()->set_debug_enabled(p_enabled);
}
+
bool NavigationServer2D::get_debug_enabled() const {
return NavigationServer3D::get_singleton()->get_debug_enabled();
}
+#ifdef DEBUG_ENABLED
void NavigationServer2D::set_debug_navigation_edge_connection_color(const Color &p_color) {
NavigationServer3D::get_singleton()->set_debug_navigation_edge_connection_color(p_color);
}
@@ -341,6 +342,9 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer2D::free);
+ ClassDB::bind_method(D_METHOD("set_debug_enabled", "enabled"), &NavigationServer2D::set_debug_enabled);
+ ClassDB::bind_method(D_METHOD("get_debug_enabled"), &NavigationServer2D::get_debug_enabled);
+
ADD_SIGNAL(MethodInfo("map_changed", PropertyInfo(Variant::RID, "map")));
ADD_SIGNAL(MethodInfo("navigation_debug_changed"));
diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h
index 153e60272c..ed2e39e53c 100644
--- a/servers/navigation_server_2d.h
+++ b/servers/navigation_server_2d.h
@@ -234,10 +234,10 @@ public:
NavigationServer2D();
virtual ~NavigationServer2D();
-#ifdef DEBUG_ENABLED
void set_debug_enabled(bool p_enabled);
bool get_debug_enabled() const;
+#ifdef DEBUG_ENABLED
void set_debug_navigation_edge_connection_color(const Color &p_color);
Color get_debug_navigation_edge_connection_color() const;
diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp
index fbe97b9acb..e5cc426708 100644
--- a/servers/navigation_server_3d.cpp
+++ b/servers/navigation_server_3d.cpp
@@ -116,6 +116,9 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_active", "active"), &NavigationServer3D::set_active);
+ ClassDB::bind_method(D_METHOD("set_debug_enabled", "enabled"), &NavigationServer3D::set_debug_enabled);
+ ClassDB::bind_method(D_METHOD("get_debug_enabled"), &NavigationServer3D::get_debug_enabled);
+
ADD_SIGNAL(MethodInfo("map_changed", PropertyInfo(Variant::RID, "map")));
ADD_SIGNAL(MethodInfo("navigation_debug_changed"));
@@ -184,6 +187,24 @@ NavigationServer3D::~NavigationServer3D() {
singleton = nullptr;
}
+void NavigationServer3D::set_debug_enabled(bool p_enabled) {
+#ifdef DEBUG_ENABLED
+ if (debug_enabled != p_enabled) {
+ debug_dirty = true;
+ }
+
+ debug_enabled = p_enabled;
+
+ if (debug_dirty) {
+ call_deferred("_emit_navigation_debug_changed_signal");
+ }
+#endif // DEBUG_ENABLED
+}
+
+bool NavigationServer3D::get_debug_enabled() const {
+ return debug_enabled;
+}
+
#ifdef DEBUG_ENABLED
void NavigationServer3D::_emit_navigation_debug_changed_signal() {
if (debug_dirty) {
@@ -533,22 +554,6 @@ bool NavigationServer3D::get_debug_navigation_enable_link_connections_xray() con
return debug_navigation_enable_link_connections_xray;
}
-void NavigationServer3D::set_debug_enabled(bool p_enabled) {
- if (debug_enabled != p_enabled) {
- debug_dirty = true;
- }
-
- debug_enabled = p_enabled;
-
- if (debug_dirty) {
- call_deferred("_emit_navigation_debug_changed_signal");
- }
-}
-
-bool NavigationServer3D::get_debug_enabled() const {
- return debug_enabled;
-}
-
void NavigationServer3D::set_debug_navigation_enable_agent_paths(const bool p_value) {
if (debug_navigation_enable_agent_paths != p_value) {
debug_dirty = true;
diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h
index 79729c55be..05df5ca0fe 100644
--- a/servers/navigation_server_3d.h
+++ b/servers/navigation_server_3d.h
@@ -274,9 +274,13 @@ public:
virtual int get_process_info(ProcessInfo p_info) const = 0;
-#ifdef DEBUG_ENABLED
+ void set_debug_enabled(bool p_enabled);
+ bool get_debug_enabled() const;
+
private:
bool debug_enabled = false;
+
+#ifdef DEBUG_ENABLED
bool debug_dirty = true;
void _emit_navigation_debug_changed_signal();
@@ -313,9 +317,6 @@ private:
Ref<StandardMaterial3D> debug_navigation_agent_path_point_material;
public:
- void set_debug_enabled(bool p_enabled);
- bool get_debug_enabled() const;
-
void set_debug_navigation_edge_connection_color(const Color &p_color);
Color get_debug_navigation_edge_connection_color() const;
diff --git a/servers/navigation_server_3d_dummy.h b/servers/navigation_server_3d_dummy.h
index d2f8fe6048..fd9226e59e 100644
--- a/servers/navigation_server_3d_dummy.h
+++ b/servers/navigation_server_3d_dummy.h
@@ -112,6 +112,8 @@ public:
void process(real_t delta_time) override {}
NavigationUtilities::PathQueryResult _query_path(const NavigationUtilities::PathQueryParameters &p_parameters) const override { return NavigationUtilities::PathQueryResult(); }
int get_process_info(ProcessInfo p_info) const override { return 0; }
+ void set_debug_enabled(bool p_enabled) {}
+ bool get_debug_enabled() const { return false; }
};
#endif // NAVIGATION_SERVER_3D_DUMMY_H
diff --git a/servers/physics_3d/godot_shape_3d.cpp b/servers/physics_3d/godot_shape_3d.cpp
index 300dca4e08..d566d612ce 100644
--- a/servers/physics_3d/godot_shape_3d.cpp
+++ b/servers/physics_3d/godot_shape_3d.cpp
@@ -1092,6 +1092,8 @@ void GodotConvexPolygonShape3D::_setup(const Vector<Vector3> &p_vertices) {
if (err != OK) {
ERR_PRINT("Failed to build convex hull");
}
+ extreme_vertices.resize(0);
+ vertex_neighbors.resize(0);
AABB _aabb;
diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp
index e031e33041..9389f8149e 100644
--- a/servers/rendering/renderer_rd/effects/ss_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp
@@ -484,7 +484,7 @@ void SSEffects::downsample_depth(Ref<RenderSceneBuffersRD> p_render_buffers, uin
downsample_uniform_set = uniform_set_cache->get_cache_vec(shader, 2, u_depths);
}
- float depth_linearize_mul = -p_projection.columns[3][2];
+ float depth_linearize_mul = -p_projection.columns[3][2] * 0.5;
float depth_linearize_add = p_projection.columns[2][2];
if (depth_linearize_mul * depth_linearize_add < 0) {
depth_linearize_add = -depth_linearize_add;
@@ -668,8 +668,14 @@ void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_rende
ssil.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
ssil.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
- ssil.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;
- ssil.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;
+ ssil.gather_push_constant.half_screen_pixel_size[0] = 2.0 / p_settings.full_screen_size.x;
+ ssil.gather_push_constant.half_screen_pixel_size[1] = 2.0 / p_settings.full_screen_size.y;
+ if (ssil_half_size) {
+ ssil.gather_push_constant.half_screen_pixel_size[0] *= 2.0;
+ ssil.gather_push_constant.half_screen_pixel_size[1] *= 2.0;
+ }
+ ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.75;
+ ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.75;
float tan_half_fov_x = 1.0 / p_projection.columns[0][0];
float tan_half_fov_y = 1.0 / p_projection.columns[1][1];
ssil.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
@@ -680,9 +686,6 @@ void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_rende
ssil.gather_push_constant.z_far = p_projection.get_z_far();
ssil.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();
- ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.25;
- ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.25;
-
ssil.gather_push_constant.radius = p_settings.radius;
float radius_near_limit = (p_settings.radius * 1.2f);
if (ssil_quality <= RS::ENV_SSIL_QUALITY_LOW) {
@@ -733,7 +736,7 @@ void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_rende
RD::Uniform u_depth_texture_view;
u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
u_depth_texture_view.binding = 0;
- u_depth_texture_view.append_id(default_sampler);
+ u_depth_texture_view.append_id(ss_effects.mirror_sampler);
u_depth_texture_view.append_id(depth_texture_view);
RD::Uniform u_normal_buffer;
@@ -1056,8 +1059,14 @@ void SSEffects::generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORe
ssao.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
- ssao.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width;
- ssao.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height;
+ ssao.gather_push_constant.half_screen_pixel_size[0] = 2.0 / p_settings.full_screen_size.x;
+ ssao.gather_push_constant.half_screen_pixel_size[1] = 2.0 / p_settings.full_screen_size.y;
+ if (ssao_half_size) {
+ ssao.gather_push_constant.half_screen_pixel_size[0] *= 2.0;
+ ssao.gather_push_constant.half_screen_pixel_size[1] *= 2.0;
+ }
+ ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.75;
+ ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.75;
float tan_half_fov_x = 1.0 / p_projection.columns[0][0];
float tan_half_fov_y = 1.0 / p_projection.columns[1][1];
ssao.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
@@ -1066,9 +1075,6 @@ void SSEffects::generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORe
ssao.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;
ssao.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();
- ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.25;
- ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.25;
-
ssao.gather_push_constant.radius = p_settings.radius;
float radius_near_limit = (p_settings.radius * 1.2f);
if (ssao_quality <= RS::ENV_SSAO_QUALITY_LOW) {
@@ -1105,7 +1111,7 @@ void SSEffects::generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORe
RD::Uniform u_depth_texture_view;
u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
u_depth_texture_view.binding = 0;
- u_depth_texture_view.append_id(default_sampler);
+ u_depth_texture_view.append_id(ss_effects.mirror_sampler);
u_depth_texture_view.append_id(depth_texture_view);
RD::Uniform u_normal_buffer;
diff --git a/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl
index b1ff46dd3b..4f81e36c58 100644
--- a/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl
@@ -161,17 +161,11 @@ void prepare_depths_and_mips(vec4 p_samples, uvec2 p_output_coord, uvec2 p_gtid)
still_alive = p_gtid.x % 16 == depth_array_offset.x && depth_array_offset.y % 16 == depth_array_offset.y;
p_output_coord /= 2;
- groupMemoryBarrier();
- barrier();
if (still_alive) {
+ // Use the previous average, not ideal, but still not bad.
float sample_00 = depth_buffer[depth_array_index][buffer_coord.x + 0][buffer_coord.y + 0];
- float sample_01 = depth_buffer[depth_array_index][buffer_coord.x + 0][buffer_coord.y + 8];
- float sample_10 = depth_buffer[depth_array_index][buffer_coord.x + 8][buffer_coord.y + 0];
- float sample_11 = depth_buffer[depth_array_index][buffer_coord.x + 8][buffer_coord.y + 8];
-
- float avg = mip_smart_average(vec4(sample_00, sample_01, sample_10, sample_11));
- imageStore(dest_image4, ivec3(p_output_coord.x, p_output_coord.y, depth_array_index), vec4(avg));
+ imageStore(dest_image4, ivec3(p_output_coord.x, p_output_coord.y, depth_array_index), vec4(sample_00));
}
#endif
}
@@ -190,6 +184,7 @@ void prepare_depths(vec4 p_samples, uvec2 p_tid) {
void main() {
#ifdef USE_HALF_BUFFERS
+// Half buffers means that we divide depth into two half res buffers (we only capture 1/4 of pixels).
#ifdef USE_HALF_SIZE
float sample_00 = texelFetch(source_depth, ivec2(4 * gl_GlobalInvocationID.x + 0, 4 * gl_GlobalInvocationID.y + 0), 0).x;
float sample_11 = texelFetch(source_depth, ivec2(4 * gl_GlobalInvocationID.x + 2, 4 * gl_GlobalInvocationID.y + 2), 0).x;
@@ -219,11 +214,11 @@ void main() {
vec2 uv = (vec2(depth_buffer_coord) + 0.5f) * params.pixel_size;
vec4 samples = textureGather(source_depth, uv);
-#endif
+#endif //USE_HALF_SIZE
#ifdef GENERATE_MIPS
prepare_depths_and_mips(samples, output_coord, gl_LocalInvocationID.xy);
#else
prepare_depths(samples, gl_GlobalInvocationID.xy);
#endif
-#endif
+#endif //USE_HALF_BUFFERS
}
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index a727e83513..940363a7e8 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -8780,7 +8780,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
--texture_uniforms;
--texture_binding;
if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") {
- _set_error(RTR("'hint_normal_roughness_texture is not supported in gl_compatibility shaders."));
+ _set_error(RTR("'hint_normal_roughness_texture' is not supported in gl_compatibility shaders."));
return ERR_PARSE_ERROR;
}
} break;
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index 05b1a8f87a..3d0443b494 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -2856,8 +2856,8 @@ RenderingServer::RenderingServer() {
}
void RenderingServer::init() {
- GLOBAL_DEF_RST("rendering/textures/vram_compression/import_s3tc_bptc", OS::get_singleton()->get_preferred_texture_format() == OS::PREFERRED_TEXTURE_FORMAT_S3TC_BPTC);
- GLOBAL_DEF_RST("rendering/textures/vram_compression/import_etc2_astc", OS::get_singleton()->get_preferred_texture_format() == OS::PREFERRED_TEXTURE_FORMAT_ETC2_ASTC);
+ GLOBAL_DEF_RST_NOVAL_BASIC("rendering/textures/vram_compression/import_s3tc_bptc", OS::get_singleton()->get_preferred_texture_format() == OS::PREFERRED_TEXTURE_FORMAT_S3TC_BPTC);
+ GLOBAL_DEF_RST_NOVAL_BASIC("rendering/textures/vram_compression/import_etc2_astc", OS::get_singleton()->get_preferred_texture_format() == OS::PREFERRED_TEXTURE_FORMAT_ETC2_ASTC);
GLOBAL_DEF("rendering/textures/lossless_compression/force_png", false);
diff --git a/tests/core/templates/test_paged_array.h b/tests/core/templates/test_paged_array.h
index 37be3080e8..10dc4473ca 100644
--- a/tests/core/templates/test_paged_array.h
+++ b/tests/core/templates/test_paged_array.h
@@ -148,6 +148,57 @@ TEST_CASE("[PagedArray] Shared pool fill, including merging") {
array2.reset(); //reset so pagepool can be reset
pool.reset();
}
+
+TEST_CASE("[PagedArray] Extensive merge_unordered() test") {
+ for (int page_size = 1; page_size <= 128; page_size *= 2) {
+ PagedArrayPool<uint32_t> pool(page_size);
+ PagedArray<uint32_t> array1;
+ PagedArray<uint32_t> array2;
+ array1.set_page_pool(&pool);
+ array2.set_page_pool(&pool);
+
+ const int max_count = 123;
+ // Test merging arrays of lengths 0+123, 1+122, 2+121, ..., 123+0
+ for (uint32_t j = 0; j < max_count; j++) {
+ CHECK(array1.size() == 0);
+ CHECK(array2.size() == 0);
+
+ uint32_t sum = 12345;
+ for (uint32_t i = 0; i < j; i++) {
+ // Hashing the addend makes it extremely unlikely for any values
+ // other than the original inputs to produce a matching sum
+ uint32_t addend = hash_murmur3_one_32(i) + i;
+ array1.push_back(addend);
+ sum += addend;
+ }
+ for (uint32_t i = j; i < max_count; i++) {
+ // See above
+ uint32_t addend = hash_murmur3_one_32(i) + i;
+ array2.push_back(addend);
+ sum += addend;
+ }
+
+ CHECK(array1.size() == j);
+ CHECK(array2.size() == max_count - j);
+
+ array1.merge_unordered(array2);
+ CHECK_MESSAGE(array1.size() == max_count, "merge_unordered() added/dropped elements while merging");
+
+ // If any elements were altered during merging, the sum will not match up.
+ for (uint32_t i = 0; i < array1.size(); i++) {
+ sum -= array1[i];
+ }
+ CHECK_MESSAGE(sum == 12345, "merge_unordered() altered elements while merging");
+
+ array1.clear();
+ }
+
+ array1.reset();
+ array2.reset();
+ pool.reset();
+ }
+}
+
} // namespace TestPagedArray
#endif // TEST_PAGED_ARRAY_H
diff --git a/thirdparty/basis_universal/encoder/basisu_comp.cpp b/thirdparty/basis_universal/encoder/basisu_comp.cpp
index 41eae2b78a..4e69e9e2ee 100644
--- a/thirdparty/basis_universal/encoder/basisu_comp.cpp
+++ b/thirdparty/basis_universal/encoder/basisu_comp.cpp
@@ -28,7 +28,7 @@
#endif
#if BASISD_SUPPORT_KTX2_ZSTD
-#include "../zstd/zstd.h"
+#include <zstd.h>
#endif
// Set to 1 to disable the mipPadding alignment workaround (which only seems to be needed when no key-values are written at all)
diff --git a/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp b/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp
index 3aeba0ee7a..c698861f3b 100644
--- a/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp
+++ b/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp
@@ -155,7 +155,7 @@
// If BASISD_SUPPORT_KTX2_ZSTD is 0, UASTC files compressed with Zstd cannot be loaded.
#if BASISD_SUPPORT_KTX2_ZSTD
// We only use two Zstd API's: ZSTD_decompress() and ZSTD_isError()
- #include "../zstd/zstd.h"
+ #include <zstd.h>
#endif
#endif