diff options
108 files changed, 749 insertions, 212 deletions
diff --git a/SConstruct b/SConstruct index 0536cab14b..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", "") @@ -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/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..454b9c1c32 100644 --- a/doc/classes/AnimatedTexture.xml +++ b/doc/classes/AnimatedTexture.xml @@ -46,7 +46,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/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/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/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/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index dcc4248682..3177780a26 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -2334,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/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/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/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 9eabc31621..c27417f037 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -6623,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); @@ -6632,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)); @@ -6735,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/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/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/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/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/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/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/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 09a257d995..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,6 +185,9 @@ def configure(env: "Environment"): ## Dependencies + if env["use_sowrap"]: + env.Append(CPPDEFINES=["SOWRAP_ENABLED"]) + if env["touch"]: env.Append(CPPDEFINES=["TOUCH_ENABLED"]) @@ -278,26 +282,83 @@ def configure(env: "Environment"): 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 @@ -305,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=[ @@ -316,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/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/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 45218773fe..b861d7af01 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -139,11 +139,14 @@ bool Label::_shape() { can_process_lines = true; lines_dirty = false; } else { - // With autowrap on, 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. - - can_process_lines = get_size().width == stable_width || autowrap_mode == TextServer::AUTOWRAP_OFF; + // 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) { @@ -171,14 +174,13 @@ bool Label::_shape() { } } - if (autowrap_mode == TextServer::AUTOWRAP_OFF) { + 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; } } - // With autowrap off, by now we already know the width the label will take. width = (minsize.width - style->get_minimum_size().width); } diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index e5dcdd2afd..1c7d42ad36 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -515,12 +515,13 @@ void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, cons ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); 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() || p_dash <= 0.0) { 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..085becb033 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -2704,6 +2704,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/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 6e63f2ed9b..3d0443b494 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -2856,8 +2856,8 @@ RenderingServer::RenderingServer() { } void RenderingServer::init() { - GLOBAL_DEF_RST_BASIC("rendering/textures/vram_compression/import_s3tc_bptc", OS::get_singleton()->get_preferred_texture_format() == OS::PREFERRED_TEXTURE_FORMAT_S3TC_BPTC); - GLOBAL_DEF_RST_BASIC("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); |