diff options
171 files changed, 1492 insertions, 1106 deletions
diff --git a/SConstruct b/SConstruct index 845b9be4a6..2763f3f578 100644 --- a/SConstruct +++ b/SConstruct @@ -200,6 +200,7 @@ opts.Add(EnumVariable("warnings", "Level of compilation warnings", "all", ("extr opts.Add(BoolVariable("werror", "Treat compiler warnings as errors", False)) opts.Add("extra_suffix", "Custom extra suffix added to the base filename of all generated binary files", "") opts.Add(BoolVariable("vsproj", "Generate a Visual Studio solution", False)) +opts.Add("vsproj_name", "Name of the Visual Studio solution", "godot") opts.Add(BoolVariable("disable_3d", "Disable 3D nodes for a smaller executable", False)) opts.Add(BoolVariable("disable_advanced_gui", "Disable advanced GUI nodes and behaviors", False)) opts.Add("build_profile", "Path to a file containing a feature build profile", "") @@ -217,7 +218,7 @@ opts.Add(BoolVariable("builtin_msdfgen", "Use the built-in MSDFgen library", Tru opts.Add(BoolVariable("builtin_glslang", "Use the built-in glslang library", True)) opts.Add(BoolVariable("builtin_graphite", "Use the built-in Graphite library", True)) opts.Add(BoolVariable("builtin_harfbuzz", "Use the built-in HarfBuzz library", True)) -opts.Add(BoolVariable("builtin_icu", "Use the built-in ICU library", True)) +opts.Add(BoolVariable("builtin_icu4c", "Use the built-in ICU library", True)) opts.Add(BoolVariable("builtin_libogg", "Use the built-in libogg library", True)) opts.Add(BoolVariable("builtin_libpng", "Use the built-in libpng library", True)) opts.Add(BoolVariable("builtin_libtheora", "Use the built-in libtheora library", True)) @@ -228,7 +229,7 @@ opts.Add(BoolVariable("builtin_mbedtls", "Use the built-in mbedTLS library", Tru opts.Add(BoolVariable("builtin_miniupnpc", "Use the built-in miniupnpc library", True)) opts.Add(BoolVariable("builtin_pcre2", "Use the built-in PCRE2 library", True)) opts.Add(BoolVariable("builtin_pcre2_with_jit", "Use JIT compiler for the built-in PCRE2 library", True)) -opts.Add(BoolVariable("builtin_recast", "Use the built-in Recast library", True)) +opts.Add(BoolVariable("builtin_recastnavigation", "Use the built-in Recast navigation library", True)) opts.Add(BoolVariable("builtin_rvo2", "Use the built-in RVO2 library", True)) opts.Add(BoolVariable("builtin_squish", "Use the built-in squish library", True)) opts.Add(BoolVariable("builtin_xatlas", "Use the built-in xatlas library", True)) @@ -923,7 +924,7 @@ if selected_platform in platform_list: print("Error: The `vsproj` option is only usable on Windows with Visual Studio.") Exit(255) env["CPPPATH"] = [Dir(path) for path in env["CPPPATH"]] - methods.generate_vs_project(env, GetOption("num_jobs")) + methods.generate_vs_project(env, GetOption("num_jobs"), env["vsproj_name"]) methods.generate_cpp_hint_file("cpp.hint") # Check for the existence of headers diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp index 5a07d44197..b2e6b57eb6 100644 --- a/core/input/input_map.cpp +++ b/core/input/input_map.cpp @@ -344,7 +344,7 @@ static const _BuiltinActionDisplayName _builtin_action_display_names[] = { { "ui_text_add_selection_for_next_occurrence", TTRC("Add Selection for Next Occurrence") }, { "ui_text_clear_carets_and_selection", TTRC("Clear Carets and Selection") }, { "ui_text_toggle_insert_mode", TTRC("Toggle Insert Mode") }, - { "ui_text_submit", TTRC("Text Submitted") }, + { "ui_text_submit", TTRC("Submit Text") }, { "ui_graph_duplicate", TTRC("Duplicate Nodes") }, { "ui_graph_delete", TTRC("Delete Nodes") }, { "ui_filedialog_up_one_level", TTRC("Go Up One Level") }, diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp index cacbcb28a4..0e9084de84 100644 --- a/core/io/file_access.cpp +++ b/core/io/file_access.cpp @@ -856,6 +856,8 @@ void FileAccess::_bind_methods() { ClassDB::bind_method(D_METHOD("store_pascal_string", "string"), &FileAccess::store_pascal_string); ClassDB::bind_method(D_METHOD("get_pascal_string"), &FileAccess::get_pascal_string); + ClassDB::bind_method(D_METHOD("close"), &FileAccess::close); + ClassDB::bind_static_method("FileAccess", D_METHOD("file_exists", "path"), &FileAccess::exists); ClassDB::bind_static_method("FileAccess", D_METHOD("get_modified_time", "file"), &FileAccess::get_modified_time); diff --git a/core/io/file_access.h b/core/io/file_access.h index 3e51ba11ed..47770cad87 100644 --- a/core/io/file_access.h +++ b/core/io/file_access.h @@ -166,6 +166,8 @@ public: void store_var(const Variant &p_var, bool p_full_objects = false); + virtual void close() = 0; + virtual bool file_exists(const String &p_name) = 0; ///< return true if a file exists virtual Error reopen(const String &p_path, int p_mode_flags); ///< does not change the AccessType diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp index c256668af0..da59ae8c59 100644 --- a/core/io/file_access_compressed.cpp +++ b/core/io/file_access_compressed.cpp @@ -385,6 +385,10 @@ Error FileAccessCompressed::_set_unix_permissions(const String &p_file, uint32_t return FAILED; } +void FileAccessCompressed::close() { + _close(); +} + FileAccessCompressed::~FileAccessCompressed() { _close(); } diff --git a/core/io/file_access_compressed.h b/core/io/file_access_compressed.h index 136fcede06..601b74a9c1 100644 --- a/core/io/file_access_compressed.h +++ b/core/io/file_access_compressed.h @@ -97,6 +97,8 @@ public: virtual uint32_t _get_unix_permissions(const String &p_file) override; virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override; + virtual void close() override; + FileAccessCompressed() {} virtual ~FileAccessCompressed(); }; diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp index 8282f2515c..c39d19d52b 100644 --- a/core/io/file_access_encrypted.cpp +++ b/core/io/file_access_encrypted.cpp @@ -294,6 +294,10 @@ Error FileAccessEncrypted::_set_unix_permissions(const String &p_file, uint32_t return ERR_UNAVAILABLE; } +void FileAccessEncrypted::close() { + _close(); +} + FileAccessEncrypted::~FileAccessEncrypted() { _close(); } diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h index d8cd0df6d1..9702b5a517 100644 --- a/core/io/file_access_encrypted.h +++ b/core/io/file_access_encrypted.h @@ -88,6 +88,8 @@ public: virtual uint32_t _get_unix_permissions(const String &p_file) override; virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override; + virtual void close() override; + FileAccessEncrypted() {} ~FileAccessEncrypted(); }; diff --git a/core/io/file_access_memory.h b/core/io/file_access_memory.h index adc29f74be..43fe6ab658 100644 --- a/core/io/file_access_memory.h +++ b/core/io/file_access_memory.h @@ -71,6 +71,8 @@ public: virtual uint32_t _get_unix_permissions(const String &p_file) override { return 0; } virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override { return FAILED; } + virtual void close() override {} + FileAccessMemory() {} }; diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp index e765eb2d42..7fabff26ac 100644 --- a/core/io/file_access_network.cpp +++ b/core/io/file_access_network.cpp @@ -469,6 +469,15 @@ void FileAccessNetwork::configure() { GLOBAL_DEF(PropertyInfo(Variant::INT, "network/remote_fs/page_read_ahead", PROPERTY_HINT_RANGE, "0,8,1,or_greater"), 4); } +void FileAccessNetwork::close() { + _close(); + + FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton; + nc->lock_mutex(); + nc->accesses.erase(id); + nc->unlock_mutex(); +} + FileAccessNetwork::FileAccessNetwork() { FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton; nc->lock_mutex(); diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h index 16e8920114..78c19347ce 100644 --- a/core/io/file_access_network.h +++ b/core/io/file_access_network.h @@ -156,6 +156,8 @@ public: virtual uint32_t _get_unix_permissions(const String &p_file) override; virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override; + virtual void close() override; + static void configure(); FileAccessNetwork(); diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index 7c392c005a..9553f35b19 100644 --- a/core/io/file_access_pack.cpp +++ b/core/io/file_access_pack.cpp @@ -366,6 +366,10 @@ bool FileAccessPack::file_exists(const String &p_name) { return false; } +void FileAccessPack::close() { + f = Ref<FileAccess>(); +} + FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file) : pf(p_file), f(FileAccess::open(pf.pack, FileAccess::READ)) { diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h index baa62e4516..8bfabc9529 100644 --- a/core/io/file_access_pack.h +++ b/core/io/file_access_pack.h @@ -178,6 +178,8 @@ public: virtual bool file_exists(const String &p_name) override; + virtual void close() override; + FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file); }; diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp index b71dd5e9bd..064353476f 100644 --- a/core/io/file_access_zip.cpp +++ b/core/io/file_access_zip.cpp @@ -336,6 +336,10 @@ bool FileAccessZip::file_exists(const String &p_name) { return false; } +void FileAccessZip::close() { + _close(); +} + FileAccessZip::FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file) { open_internal(p_path, FileAccess::READ); } diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h index 63f1012f99..f8b640946c 100644 --- a/core/io/file_access_zip.h +++ b/core/io/file_access_zip.h @@ -109,6 +109,8 @@ public: virtual uint32_t _get_unix_permissions(const String &p_file) override { return 0; } virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override { return FAILED; } + virtual void close() override; + FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file); ~FileAccessZip(); }; diff --git a/core/object/script_language_extension.cpp b/core/object/script_language_extension.cpp index 19c6fc3383..c7eb32c020 100644 --- a/core/object/script_language_extension.cpp +++ b/core/object/script_language_extension.cpp @@ -36,6 +36,7 @@ void ScriptExtension::_bind_methods() { GDVIRTUAL_BIND(_can_instantiate); GDVIRTUAL_BIND(_get_base_script); + GDVIRTUAL_BIND(_get_global_name); GDVIRTUAL_BIND(_inherits_script, "script"); GDVIRTUAL_BIND(_get_instance_base_type); diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index a8860721d6..ed7bdc07fc 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -803,7 +803,8 @@ Returns the result of [param base] raised to the power of [param exp]. In GDScript, this is the equivalent of the [code]**[/code] operator. [codeblock] - pow(2, 5) # Returns 32 + pow(2, 5) # Returns 32.0 + pow(4, 1.5) # Returns 8.0 [/codeblock] </description> </method> @@ -1139,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 @@ -1287,14 +1288,14 @@ Converts a formatted [param string] that was returned by [method var_to_str] to the original [Variant]. [codeblocks] [gdscript] - var a = '{ "a": 1, "b": 2 }' # a is a String - var b = str_to_var(a) # b is a Dictionary - print(b["a"]) # Prints 1 + var data = '{ "a": 1, "b": 2 }' # data is a String + var dict = str_to_var(data) # dict is a Dictionary + print(dict["a"]) # Prints 1 [/gdscript] [csharp] - string a = "{ \"a\": 1, \"b\": 2 }"; // a is a string - var b = GD.StrToVar(a).AsGodotDictionary(); // b is a Dictionary - GD.Print(b["a"]); // Prints 1 + string data = "{ \"a\": 1, \"b\": 2 }"; // data is a string + var dict = GD.StrToVar(data).AsGodotDictionary(); // dict is a Dictionary + GD.Print(dict["a"]); // Prints 1 [/csharp] [/codeblocks] </description> @@ -2272,7 +2273,7 @@ Command (on macOS) or Meta/Windows key mask. </constant> <constant name="KEY_MASK_CTRL" value="268435456" enum="KeyModifierMask" is_bitfield="true"> - Ctrl key mask. + Control key mask. </constant> <constant name="KEY_MASK_KPAD" value="536870912" enum="KeyModifierMask" is_bitfield="true"> Keypad key mask. @@ -2293,10 +2294,10 @@ Middle mouse button. </constant> <constant name="MOUSE_BUTTON_WHEEL_UP" value="4" enum="MouseButton"> - Mouse wheel up. + Mouse wheel scrolling up. </constant> <constant name="MOUSE_BUTTON_WHEEL_DOWN" value="5" enum="MouseButton"> - Mouse wheel down. + Mouse wheel scrolling down. </constant> <constant name="MOUSE_BUTTON_WHEEL_LEFT" value="6" enum="MouseButton"> Mouse wheel left button (only present on some mice). @@ -2760,6 +2761,7 @@ Hints that a string property is a password, and every character is replaced with the secret character. </constant> <constant name="PROPERTY_HINT_MAX" value="37" enum="PropertyHint"> + Represents the size of the [enum PropertyHint] enum. </constant> <constant name="PROPERTY_USAGE_NONE" value="0" enum="PropertyUsageFlags" is_bitfield="true"> The property is not stored, and does not display in the editor. This is the default for non-exported properties. diff --git a/doc/classes/AnimatedTexture.xml b/doc/classes/AnimatedTexture.xml index 57a7f86901..052c55dfb6 100644 --- a/doc/classes/AnimatedTexture.xml +++ b/doc/classes/AnimatedTexture.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AnimatedTexture" inherits="Texture2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="AnimatedTexture" inherits="Texture2D" is_deprecated="true" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> Proxy texture for simple frame-based animations. </brief_description> @@ -8,6 +8,7 @@ The playback of the animation is controlled by the [member speed_scale] property, as well as each frame's duration (see [method set_frame_duration]). The animation loops, i.e. it will restart at frame 0 automatically after playing the last frame. [AnimatedTexture] currently requires all frame textures to have the same size, otherwise the bigger ones will be cropped to match the smallest one. [b]Note:[/b] AnimatedTexture doesn't support using [AtlasTexture]s. Each frame needs to be a separate [Texture2D]. + [b]Warning:[/b] AnimatedTexture is deprecated, and might be removed in a future release. Its current implementation is not efficient for the modern renderers. </description> <tutorials> </tutorials> @@ -46,7 +47,7 @@ </methods> <members> <member name="current_frame" type="int" setter="set_current_frame" getter="get_current_frame"> - Sets the currently visible frame of the texture. + Sets the currently visible frame of the texture. Setting this frame while playing resets the current frame time, so the newly selected frame plays for its whole configured frame duration. </member> <member name="frames" type="int" setter="set_frames" getter="get_frames" default="1"> Number of frames to use in the animation. While you can create the frames independently with [method set_frame_texture], you need to set this value for the animation to take new frames into account. The maximum number of frames is [constant MAX_FRAMES]. diff --git a/doc/classes/Decal.xml b/doc/classes/Decal.xml index ddfa64891d..824416e4d4 100644 --- a/doc/classes/Decal.xml +++ b/doc/classes/Decal.xml @@ -96,7 +96,7 @@ [b]Note:[/b] Unlike [BaseMaterial3D] whose filter mode can be adjusted on a per-material basis, the filter mode for [Decal] textures is set globally with [member ProjectSettings.rendering/textures/decals/filter]. </member> <member name="texture_emission" type="Texture2D" setter="set_texture" getter="get_texture"> - [Texture2D] with the emission [Color] of the Decal. Either this or the [member texture_emission] must be set for the Decal to be visible. Use the alpha channel like a mask to smoothly blend the edges of the decal with the underlying object. + [Texture2D] with the emission [Color] of the Decal. Either this or the [member texture_albedo] must be set for the Decal to be visible. Use the alpha channel like a mask to smoothly blend the edges of the decal with the underlying object. [b]Note:[/b] Unlike [BaseMaterial3D] whose filter mode can be adjusted on a per-material basis, the filter mode for [Decal] textures is set globally with [member ProjectSettings.rendering/textures/decals/filter]. </member> <member name="texture_normal" type="Texture2D" setter="set_texture" getter="get_texture"> diff --git a/doc/classes/FileAccess.xml b/doc/classes/FileAccess.xml index eda06d57da..526f7c22e6 100644 --- a/doc/classes/FileAccess.xml +++ b/doc/classes/FileAccess.xml @@ -33,7 +33,7 @@ [/csharp] [/codeblocks] In the example above, the file will be saved in the user data folder as specified in the [url=$DOCS_URL/tutorials/io/data_paths.html]Data paths[/url] documentation. - There is no method to close a file in order to free it from use. Instead, [FileAccess] will close when it's freed, which happens when it goes out of scope or when it gets assigned with [code]null[/code]. In C# the reference must be disposed after we are done using it, this can be done with the [code]using[/code] statement or calling the [code]Dispose[/code] method directly. + [FileAccess] will close when it's freed, which happens when it goes out of scope or when it gets assigned with [code]null[/code]. In C# the reference must be disposed after we are done using it, this can be done with the [code]using[/code] statement or calling the [code]Dispose[/code] method directly. [codeblocks] [gdscript] var file = FileAccess.open("res://something") # File is opened and locked for use. @@ -52,6 +52,13 @@ <link title="3D Voxel Demo">https://godotengine.org/asset-library/asset/676</link> </tutorials> <methods> + <method name="close"> + <return type="void" /> + <description> + Closes the currently opened file and prevents subsequent read/write operations. Use flush to persist the data to disk without closing the file. + [b]Note:[/b] [FileAccess] will automatically close when it's freed, which happens when it goes out of scope or when it gets assigned with [code]null[/code]. In C# the reference must be disposed after we are done using it, this can be done with the [code]using[/code] statement or calling the [code]Dispose[/code] method directly. + </description> + </method> <method name="eof_reached" qualifiers="const"> <return type="bool" /> <description> diff --git a/doc/classes/NavigationAgent2D.xml b/doc/classes/NavigationAgent2D.xml index 92fd8bcc6a..c6d03fb6d8 100644 --- a/doc/classes/NavigationAgent2D.xml +++ b/doc/classes/NavigationAgent2D.xml @@ -171,6 +171,8 @@ - [code]type[/code]: Always [constant NavigationPathQueryResult2D.PATH_SEGMENT_TYPE_LINK]. - [code]rid[/code]: The [RID] of the link. - [code]owner[/code]: The object which manages the link (usually [NavigationLink2D]). + - [code]link_entry_position[/code]: If [code]owner[/code] is available and the owner is a [NavigationLink2D], it will contain the global position of the link's point the agent is entering. + - [code]link_exit_position[/code]: If [code]owner[/code] is available and the owner is a [NavigationLink2D], it will contain the global position of the link's point which the agent is exiting. </description> </signal> <signal name="navigation_finished"> diff --git a/doc/classes/NavigationAgent3D.xml b/doc/classes/NavigationAgent3D.xml index 0ed11bc477..d2151773da 100644 --- a/doc/classes/NavigationAgent3D.xml +++ b/doc/classes/NavigationAgent3D.xml @@ -144,13 +144,13 @@ <member name="path_desired_distance" type="float" setter="set_path_desired_distance" getter="get_path_desired_distance" default="1.0"> The distance threshold before a path point is considered to be reached. This will allow an agent to not have to hit a path point on the path exactly, but in the area. If this value is set to high the NavigationAgent will skip points on the path which can lead to leaving the navigation mesh. If this value is set to low the NavigationAgent will be stuck in a repath loop cause it will constantly overshoot or undershoot the distance to the next point on each physics frame update. </member> - <member name="path_max_distance" type="float" setter="set_path_max_distance" getter="get_path_max_distance" default="3.0"> + <member name="path_max_distance" type="float" setter="set_path_max_distance" getter="get_path_max_distance" default="5.0"> The maximum distance the agent is allowed away from the ideal path to the final position. This can happen due to trying to avoid collisions. When the maximum distance is exceeded, it recalculates the ideal path. </member> <member name="path_metadata_flags" type="int" setter="set_path_metadata_flags" getter="get_path_metadata_flags" enum="NavigationPathQueryParameters3D.PathMetadataFlags" default="7"> Additional information to return with the navigation path. </member> - <member name="radius" type="float" setter="set_radius" getter="get_radius" default="1.0"> + <member name="radius" type="float" setter="set_radius" getter="get_radius" default="0.5"> The radius of the avoidance agent. This is the "body" of the avoidance agent and not the avoidance maneuver starting radius (which is controlled by [member neighbor_distance]). Does not affect normal pathfinding. To change an actor's pathfinding radius bake [NavigationMesh] resources with a different [member NavigationMesh.agent_radius] property and use different navigation maps for each actor size. </member> @@ -160,7 +160,7 @@ <member name="target_position" type="Vector3" setter="set_target_position" getter="get_target_position" default="Vector3(0, 0, 0)"> The user-defined target position. Setting this property will clear the current navigation path. </member> - <member name="time_horizon" type="float" setter="set_time_horizon" getter="get_time_horizon" default="5.0"> + <member name="time_horizon" type="float" setter="set_time_horizon" getter="get_time_horizon" default="1.0"> The minimal amount of time for which this agent's velocities, that are computed with the collision avoidance algorithm, are safe with respect to other agents. The larger the number, the sooner the agent will respond to other agents, but less freedom in choosing its velocities. Must be positive. </member> </members> @@ -174,6 +174,8 @@ - [code]type[/code]: Always [constant NavigationPathQueryResult3D.PATH_SEGMENT_TYPE_LINK]. - [code]rid[/code]: The [RID] of the link. - [code]owner[/code]: The object which manages the link (usually [NavigationLink3D]). + - [code]link_entry_position[/code]: If [code]owner[/code] is available and the owner is a [NavigationLink2D], it will contain the global position of the link's point the agent is entering. + - [code]link_exit_position[/code]: If [code]owner[/code] is available and the owner is a [NavigationLink2D], it will contain the global position of the link's point which the agent is exiting. </description> </signal> <signal name="navigation_finished"> diff --git a/doc/classes/NavigationLink2D.xml b/doc/classes/NavigationLink2D.xml index b3f4367675..3f5b1fb184 100644 --- a/doc/classes/NavigationLink2D.xml +++ b/doc/classes/NavigationLink2D.xml @@ -10,6 +10,18 @@ <link title="Using NavigationLinks">$DOCS_URL/tutorials/navigation/navigation_using_navigationlinks.html</link> </tutorials> <methods> + <method name="get_global_end_position" qualifiers="const"> + <return type="Vector2" /> + <description> + Returns the [member end_position] that is relative to the link as a global position. + </description> + </method> + <method name="get_global_start_position" qualifiers="const"> + <return type="Vector2" /> + <description> + Returns the [member start_position] that is relative to the link as a global position. + </description> + </method> <method name="get_navigation_layer_value" qualifiers="const"> <return type="bool" /> <param index="0" name="layer_number" type="int" /> @@ -17,6 +29,20 @@ Returns whether or not the specified layer of the [member navigation_layers] bitmask is enabled, given a [code]layer_number[/code] between 1 and 32. </description> </method> + <method name="set_global_end_position"> + <return type="void" /> + <param index="0" name="position" type="Vector2" /> + <description> + Sets the [member end_position] that is relative to the link from a global [param position]. + </description> + </method> + <method name="set_global_start_position"> + <return type="void" /> + <param index="0" name="position" type="Vector2" /> + <description> + Sets the [member start_position] that is relative to the link from a global [param position]. + </description> + </method> <method name="set_navigation_layer_value"> <return type="void" /> <param index="0" name="layer_number" type="int" /> diff --git a/doc/classes/NavigationLink3D.xml b/doc/classes/NavigationLink3D.xml index 4dff226042..4081426dcd 100644 --- a/doc/classes/NavigationLink3D.xml +++ b/doc/classes/NavigationLink3D.xml @@ -10,6 +10,18 @@ <link title="Using NavigationLinks">$DOCS_URL/tutorials/navigation/navigation_using_navigationlinks.html</link> </tutorials> <methods> + <method name="get_global_end_position" qualifiers="const"> + <return type="Vector3" /> + <description> + Returns the [member end_position] that is relative to the link as a global position. + </description> + </method> + <method name="get_global_start_position" qualifiers="const"> + <return type="Vector3" /> + <description> + Returns the [member start_position] that is relative to the link as a global position. + </description> + </method> <method name="get_navigation_layer_value" qualifiers="const"> <return type="bool" /> <param index="0" name="layer_number" type="int" /> @@ -17,6 +29,20 @@ Returns whether or not the specified layer of the [member navigation_layers] bitmask is enabled, given a [code]layer_number[/code] between 1 and 32. </description> </method> + <method name="set_global_end_position"> + <return type="void" /> + <param index="0" name="position" type="Vector3" /> + <description> + Sets the [member end_position] that is relative to the link from a global [param position]. + </description> + </method> + <method name="set_global_start_position"> + <return type="void" /> + <param index="0" name="position" type="Vector3" /> + <description> + Sets the [member start_position] that is relative to the link from a global [param position]. + </description> + </method> <method name="set_navigation_layer_value"> <return type="void" /> <param index="0" name="layer_number" type="int" /> diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml index e7a2b99172..103de8eddb 100644 --- a/doc/classes/NavigationServer2D.xml +++ b/doc/classes/NavigationServer2D.xml @@ -126,6 +126,12 @@ Destroys the given RID. </description> </method> + <method name="get_debug_enabled" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] when the NavigationServer has debug enabled. + </description> + </method> <method name="get_maps" qualifiers="const"> <return type="RID[]" /> <description> @@ -520,6 +526,13 @@ Sets the [param travel_cost] for this [param region]. </description> </method> + <method name="set_debug_enabled"> + <return type="void" /> + <param index="0" name="enabled" type="bool" /> + <description> + If [code]true[/code] enables debug mode on the NavigationServer. + </description> + </method> </methods> <signals> <signal name="map_changed"> diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml index 16b850866a..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> @@ -422,15 +428,6 @@ Sets the map up direction. </description> </method> - <method name="process"> - <return type="void" /> - <param index="0" name="delta_time" type="float" /> - <description> - Process the collision avoidance agents. - The result of this process is needed by the physics server, so this must be called in the main thread. - [b]Note:[/b] This function is not thread safe. - </description> - </method> <method name="query_path" qualifiers="const"> <return type="void" /> <param index="0" name="parameters" type="NavigationPathQueryParameters3D" /> @@ -584,6 +581,13 @@ Control activation of this server. </description> </method> + <method name="set_debug_enabled"> + <return type="void" /> + <param index="0" name="enabled" type="bool" /> + <description> + If [code]true[/code] enables debug mode on the NavigationServer. + </description> + </method> </methods> <signals> <signal name="map_changed"> diff --git a/doc/classes/Node3D.xml b/doc/classes/Node3D.xml index 1aa71113e9..c199c1aae6 100644 --- a/doc/classes/Node3D.xml +++ b/doc/classes/Node3D.xml @@ -4,7 +4,7 @@ Most basic 3D game object, parent of all 3D-related nodes. </brief_description> <description> - Most basic 3D game object, with a 3D [Transform3D] and visibility settings. All other 3D game objects inherit from Node3D. Use [Node3D] as a parent node to move, scale, rotate and show/hide children in a 3D project. + Most basic 3D game object, with a [Transform3D] and visibility settings. All other 3D game objects inherit from Node3D. Use [Node3D] as a parent node to move, scale, rotate and show/hide children in a 3D project. Affine operations (rotate, scale, translate) happen in parent's local coordinate system, unless the [Node3D] object is set as top-level. Affine operations in this coordinate system correspond to direct affine operations on the [Node3D]'s transform. The word local below refers to this coordinate system. The coordinate system that is attached to the [Node3D] object itself is referred to as object-local coordinate system. [b]Note:[/b] Unless otherwise specified, all methods that have angle parameters must have angles specified as [i]radians[/i]. To convert degrees to radians, use [method @GlobalScope.deg_to_rad]. </description> diff --git a/doc/classes/OmniLight3D.xml b/doc/classes/OmniLight3D.xml index 1df8c255dd..7c5b9aff46 100644 --- a/doc/classes/OmniLight3D.xml +++ b/doc/classes/OmniLight3D.xml @@ -13,7 +13,8 @@ </tutorials> <members> <member name="omni_attenuation" type="float" setter="set_param" getter="get_param" default="1.0"> - The light's attenuation (drop-off) curve. A number of presets are available in the [b]Inspector[/b] by right-clicking the curve. + The light's attenuation (drop-off) curve. A number of presets are available in the [b]Inspector[/b] by right-clicking the curve. Zero and negative values are allowed but can produce unusual effects. + [b]Note:[/b] Very high [member omni_attenuation] values (typically above 10) can impact performance negatively if the light is made to use a larger [member omni_range] to compensate. This is because culling opportunities will become less common and shading costs will be increased (as the light will cover more pixels on screen while resulting in the same amount of brightness). To improve performance, use the lowest [member omni_attenuation] value possible for the visuals you're trying to achieve. </member> <member name="omni_range" type="float" setter="set_param" getter="get_param" default="5.0"> The light's radius. Note that the effectively lit area may appear to be smaller depending on the [member omni_attenuation] in use. No matter the [member omni_attenuation] in use, the light will never reach anything outside this radius. diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 986810edf2..3177780a26 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -667,7 +667,7 @@ Main window initial position. [code]0[/code] - "Absolute", [member display/window/size/initial_position] is used to set window position. [code]1[/code] - "Primary Screen Center". - [code]2[/code] - "Other Screen Center", [member display/window/size/initial_screen] is used to set window position. + [code]2[/code] - "Other Screen Center", [member display/window/size/initial_screen] is used to set the screen. </member> <member name="display/window/size/initial_screen" type="int" setter="" getter="" default="0"> Main window initial screen, this settings is used only if [member display/window/size/initial_position_type] is set to "Other Screen Center" ([code]2[/code]). @@ -1147,9 +1147,6 @@ <member name="input_devices/pointing/emulate_touch_from_mouse" type="bool" setter="" getter="" default="false"> If [code]true[/code], sends touch input events when clicking or dragging the mouse. </member> - <member name="input_devices/pointing/ios/touch_delay" type="float" setter="" getter="" default="0.15"> - Default delay for touch events. This only affects iOS devices. - </member> <member name="internationalization/locale/fallback" type="String" setter="" getter="" default=""en""> The locale to fall back to if a translation isn't available in a given language. If left empty, [code]en[/code] (English) will be used. </member> @@ -2337,11 +2334,11 @@ <member name="rendering/textures/lossless_compression/force_png" type="bool" setter="" getter="" default="false"> If [code]true[/code], the texture importer will import lossless textures using the PNG format. Otherwise, it will default to using WebP. </member> - <member name="rendering/textures/vram_compression/import_etc2_astc" type="bool" setter="" getter="" default="false"> + <member name="rendering/textures/vram_compression/import_etc2_astc" type="bool" setter="" getter=""> If [code]true[/code], the texture importer will import VRAM-compressed textures using the Ericsson Texture Compression 2 algorithm for lower quality textures and normalmaps and Adaptable Scalable Texture Compression algorithm for high quality textures (in 4x4 block size). [b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]). </member> - <member name="rendering/textures/vram_compression/import_s3tc_bptc" type="bool" setter="" getter="" default="true"> + <member name="rendering/textures/vram_compression/import_s3tc_bptc" type="bool" setter="" getter=""> If [code]true[/code], the texture importer will import VRAM-compressed textures using the S3 Texture Compression algorithm (DXT1-5) for lower quality textures and the the BPTC algorithm (BC6H and BC7) for high quality textures. This algorithm is only supported on PC desktop platforms and consoles. [b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]). </member> diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml index 49bb65b64d..5985af53fc 100644 --- a/doc/classes/RichTextLabel.xml +++ b/doc/classes/RichTextLabel.xml @@ -373,7 +373,7 @@ <return type="void" /> <param index="0" name="data" type="Variant" /> <description> - Adds a [code][meta][/code] tag to the tag stack. Similar to the BBCode [code][url=something]{text}[/url][/code], but supports non-[String] metadata types. + Adds a meta tag to the tag stack. Similar to the BBCode [code][url=something]{text}[/url][/code], but supports non-[String] metadata types. </description> </method> <method name="push_mono"> @@ -625,60 +625,6 @@ <constant name="LIST_DOTS" value="3" enum="ListType"> Each list item has a filled circle marker. </constant> - <constant name="ITEM_FRAME" value="0" enum="ItemType"> - </constant> - <constant name="ITEM_TEXT" value="1" enum="ItemType"> - </constant> - <constant name="ITEM_IMAGE" value="2" enum="ItemType"> - </constant> - <constant name="ITEM_NEWLINE" value="3" enum="ItemType"> - </constant> - <constant name="ITEM_FONT" value="4" enum="ItemType"> - </constant> - <constant name="ITEM_FONT_SIZE" value="5" enum="ItemType"> - </constant> - <constant name="ITEM_FONT_FEATURES" value="6" enum="ItemType"> - </constant> - <constant name="ITEM_COLOR" value="7" enum="ItemType"> - </constant> - <constant name="ITEM_OUTLINE_SIZE" value="8" enum="ItemType"> - </constant> - <constant name="ITEM_OUTLINE_COLOR" value="9" enum="ItemType"> - </constant> - <constant name="ITEM_UNDERLINE" value="10" enum="ItemType"> - </constant> - <constant name="ITEM_STRIKETHROUGH" value="11" enum="ItemType"> - </constant> - <constant name="ITEM_PARAGRAPH" value="12" enum="ItemType"> - </constant> - <constant name="ITEM_INDENT" value="13" enum="ItemType"> - </constant> - <constant name="ITEM_LIST" value="14" enum="ItemType"> - </constant> - <constant name="ITEM_TABLE" value="15" enum="ItemType"> - </constant> - <constant name="ITEM_FADE" value="16" enum="ItemType"> - </constant> - <constant name="ITEM_SHAKE" value="17" enum="ItemType"> - </constant> - <constant name="ITEM_WAVE" value="18" enum="ItemType"> - </constant> - <constant name="ITEM_TORNADO" value="19" enum="ItemType"> - </constant> - <constant name="ITEM_RAINBOW" value="20" enum="ItemType"> - </constant> - <constant name="ITEM_BGCOLOR" value="21" enum="ItemType"> - </constant> - <constant name="ITEM_FGCOLOR" value="22" enum="ItemType"> - </constant> - <constant name="ITEM_META" value="23" enum="ItemType"> - </constant> - <constant name="ITEM_HINT" value="24" enum="ItemType"> - </constant> - <constant name="ITEM_DROPCAP" value="25" enum="ItemType"> - </constant> - <constant name="ITEM_CUSTOMFX" value="26" enum="ItemType"> - </constant> <constant name="MENU_COPY" value="0" enum="MenuItems"> Copies the selected text. </constant> diff --git a/doc/classes/ScriptExtension.xml b/doc/classes/ScriptExtension.xml index 045eadda41..61034f8e4a 100644 --- a/doc/classes/ScriptExtension.xml +++ b/doc/classes/ScriptExtension.xml @@ -32,6 +32,11 @@ <description> </description> </method> + <method name="_get_global_name" qualifiers="virtual const"> + <return type="StringName" /> + <description> + </description> + </method> <method name="_get_instance_base_type" qualifiers="virtual const"> <return type="StringName" /> <description> diff --git a/doc/classes/SpotLight3D.xml b/doc/classes/SpotLight3D.xml index 6bb4ae548c..3b32923872 100644 --- a/doc/classes/SpotLight3D.xml +++ b/doc/classes/SpotLight3D.xml @@ -20,10 +20,11 @@ [b]Note:[/b] [member spot_angle] is not affected by [member Node3D.scale] (the light's scale or its parent's scale). </member> <member name="spot_angle_attenuation" type="float" setter="set_param" getter="get_param" default="1.0"> - The spotlight's angular attenuation curve. + The spotlight's [i]angular[/i] attenuation curve. See also [member spot_attenuation]. </member> <member name="spot_attenuation" type="float" setter="set_param" getter="get_param" default="1.0"> - The spotlight's light energy attenuation curve. + The spotlight's light energy (drop-off) attenuation curve. A number of presets are available in the [b]Inspector[/b] by right-clicking the curve. Zero and negative values are allowed but can produce unusual effects. See also [member spot_angle_attenuation]. + [b]Note:[/b] Very high [member spot_attenuation] values (typically above 10) can impact performance negatively if the light is made to use a larger [member spot_range] to compensate. This is because culling opportunities will become less common and shading costs will be increased (as the light will cover more pixels on screen while resulting in the same amount of brightness). To improve performance, use the lowest [member spot_attenuation] value possible for the visuals you're trying to achieve. </member> <member name="spot_range" type="float" setter="set_param" getter="get_param" default="5.0"> The maximal range that can be reached by the spotlight. Note that the effectively lit area may appear to be smaller depending on the [member spot_attenuation] in use. No matter the [member spot_attenuation] in use, the light will never reach anything outside this range. diff --git a/doc/classes/String.xml b/doc/classes/String.xml index 792cd38741..53b34332d7 100644 --- a/doc/classes/String.xml +++ b/doc/classes/String.xml @@ -193,8 +193,8 @@ GD.Print("Team".Find("I")); // Prints -1 GD.Print("Potato".Find("t")); // Prints 2 - GD.print("Potato".Find("t", 3)); // Prints 4 - GD.print("Potato".Find("t", 5)); // Prints -1 + GD.Print("Potato".Find("t", 3)); // Prints 4 + GD.Print("Potato".Find("t", 5)); // Prints -1 [/csharp] [/codeblocks] [b]Note:[/b] If you just want to know whether the string contains [param what], use [method contains]. In GDScript, you may also use the [code]in[/code] operator. @@ -230,6 +230,7 @@ print("User {id} is {name}.".format([["id", 42], ["name", "Godot"]])) [/codeblock] See also the [url=$DOCS_URL/tutorials/scripting/gdscript/gdscript_format_string.html]GDScript format string[/url] tutorial. + [b]Note:[/b] In C#, it's recommended to [url=https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated]interpolate strings with "$"[/url], instead. </description> </method> <method name="get_base_dir" qualifiers="const"> @@ -480,7 +481,7 @@ var fruits = new string[] {"Apple", "Orange", "Pear", "Kiwi"}; // In C#, this method is static. - GD.Print(string.Join(", ", fruits); // Prints "Apple, Orange, Pear, Kiwi" + GD.Print(string.Join(", ", fruits)); // Prints "Apple, Orange, Pear, Kiwi" GD.Print(string.Join("---", fruits)); // Prints "Apple---Orange---Pear---Kiwi" [/csharp] [/codeblocks] @@ -1047,18 +1048,17 @@ <return type="String" /> <param index="0" name="right" type="Variant" /> <description> - Formats the [String], replacing the placeholders with one or more parameters. - To pass multiple parameters, [param right] needs to be an [Array]. + Formats the [String], replacing the placeholders with one or more parameters. To pass multiple parameters, [param right] needs to be an [Array]. [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." [/codeblock] - In C#, there is no direct equivalent to this operator. Use the [method format] method, instead. For more information, see the [url=$DOCS_URL/tutorials/scripting/gdscript/gdscript_format_string.html]GDScript format strings[/url] tutorial. + [b]Note:[/b] In C#, this operator is not available. Instead, see [url=https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated]how to interpolate strings with "$"[/url]. </description> </operator> <operator name="operator +"> @@ -1072,6 +1072,7 @@ <return type="String" /> <param index="0" name="right" type="StringName" /> <description> + Appends [param right] at the end of this [String], returning a [String]. This is also known as a string concatenation. </description> </operator> <operator name="operator <"> diff --git a/doc/classes/StringName.xml b/doc/classes/StringName.xml index c103fb2287..4ccb93dab3 100644 --- a/doc/classes/StringName.xml +++ b/doc/classes/StringName.xml @@ -5,7 +5,7 @@ </brief_description> <description> [StringName]s are immutable strings designed for general-purpose representation of unique names (also called "string interning"). [StringName] ensures that only one instance of a given name exists (so two [StringName]s with the same value are the same object). Comparing them is much faster than with regular [String]s, because only the pointers are compared, not the whole strings. - You will usually just pass a [String] to methods expecting a [StringName] and it will be automatically converted, but you may occasionally want to construct a [StringName] ahead of time with [StringName] or, in GDScript, the literal syntax [code]&"example"[/code]. + You will usually just pass a [String] to methods expecting a [StringName] and it will be automatically converted, but you may occasionally want to construct a [StringName] ahead of time with the [StringName] constructor or, in GDScript, the literal syntax [code]&"example"[/code]. See also [NodePath], which is a similar concept specifically designed to store pre-parsed node paths. Some string methods have corresponding variations. Variations suffixed with [code]n[/code] ([method countn], [method findn], [method replacen], etc.) are [b]case-insensitive[/b] (they make no distinction between uppercase and lowercase letters). Method variations prefixed with [code]r[/code] ([method rfind], [method rsplit], etc.) are reversed, and start from the end of the string, instead of the beginning. [b]Note:[/b] In a boolean context, a [StringName] will evaluate to [code]false[/code] if it is empty ([code]StringName("")[/code]). Otherwise, a [StringName] will always evaluate to [code]true[/code]. @@ -176,8 +176,8 @@ GD.Print("Team".Find("I")); // Prints -1 GD.Print("Potato".Find("t")); // Prints 2 - GD.print("Potato".Find("t", 3)); // Prints 4 - GD.print("Potato".Find("t", 5)); // Prints -1 + GD.Print("Potato".Find("t", 3)); // Prints 4 + GD.Print("Potato".Find("t", 5)); // Prints -1 [/csharp] [/codeblocks] [b]Note:[/b] If you just want to know whether the string contains [param what], use [method contains]. In GDScript, you may also use the [code]in[/code] operator. @@ -213,6 +213,7 @@ print("User {id} is {name}.".format([["id", 42], ["name", "Godot"]])) [/codeblock] See also the [url=$DOCS_URL/tutorials/scripting/gdscript/gdscript_format_string.html]GDScript format string[/url] tutorial. + [b]Note:[/b] In C#, it's recommended to [url=https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated]interpolate strings with "$"[/url], instead. </description> </method> <method name="get_base_dir" qualifiers="const"> @@ -455,7 +456,7 @@ var fruits = new string[] {"Apple", "Orange", "Pear", "Kiwi"}; // In C#, this method is static. - GD.Print(string.Join(", ", fruits); // Prints "Apple, Orange, Pear, Kiwi" + GD.Print(string.Join(", ", fruits)); // Prints "Apple, Orange, Pear, Kiwi" GD.Print(string.Join("---", fruits)); // Prints "Apple---Orange---Pear---Kiwi" [/csharp] [/codeblocks] @@ -504,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"> @@ -954,18 +955,23 @@ <return type="String" /> <param index="0" name="right" type="Variant" /> <description> + Formats the [StringName], replacing the placeholders with one or more parameters, returning a [String]. To pass multiple parameters, [param right] needs to be an [Array]. + For more information, see the [url=$DOCS_URL/tutorials/scripting/gdscript/gdscript_format_string.html]GDScript format strings[/url] tutorial. + [b]Note:[/b] In C#, this operator is not available. Instead, see [url=https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated]how to interpolate strings with "$"[/url]. </description> </operator> <operator name="operator +"> <return type="String" /> <param index="0" name="right" type="String" /> <description> + Appends [param right] at the end of this [StringName], returning a [String]. This is also known as a string concatenation. </description> </operator> <operator name="operator +"> <return type="String" /> <param index="0" name="right" type="StringName" /> <description> + Appends [param right] at the end of this [StringName], returning a [String]. This is also known as a string concatenation. </description> </operator> <operator name="operator <"> diff --git a/doc/classes/TextureRect.xml b/doc/classes/TextureRect.xml index 460ffbbb80..3500a0ddf5 100644 --- a/doc/classes/TextureRect.xml +++ b/doc/classes/TextureRect.xml @@ -10,8 +10,9 @@ <link title="3D Voxel Demo">https://godotengine.org/asset-library/asset/676</link> </tutorials> <members> - <member name="expand_mode" type="int" setter="set_expand_mode" getter="get_expand_mode" enum="TextureRect.ExpandMode" default="0"> + <member name="expand_mode" type="int" setter="set_expand_mode" getter="get_expand_mode" enum="TextureRect.ExpandMode" default="0" is_experimental="true"> Defines how minimum size is determined based on the texture's size. See [enum ExpandMode] for options. + [b]Note:[/b] Using [constant EXPAND_FIT_WIDTH], [constant EXPAND_FIT_WIDTH_PROPORTIONAL], [constant EXPAND_FIT_HEIGHT] or [constant EXPAND_FIT_HEIGHT_PROPORTIONAL] may result in unstable behavior in some containers. This functionality is being re-evaluated and will change in the future. </member> <member name="flip_h" type="bool" setter="set_flip_h" getter="is_flipped_h" default="false"> If [code]true[/code], texture is flipped horizontally. diff --git a/doc/classes/VisibleOnScreenEnabler2D.xml b/doc/classes/VisibleOnScreenEnabler2D.xml index 8590e9cc9f..68e510a6dc 100644 --- a/doc/classes/VisibleOnScreenEnabler2D.xml +++ b/doc/classes/VisibleOnScreenEnabler2D.xml @@ -24,7 +24,7 @@ Corresponds to [constant Node.PROCESS_MODE_ALWAYS]. </constant> <constant name="ENABLE_MODE_WHEN_PAUSED" value="2" enum="EnableMode"> - Corresponds to [constant Node.PROCESS_MODE_WHEN_PAUSED. + Corresponds to [constant Node.PROCESS_MODE_WHEN_PAUSED]. </constant> </constants> </class> diff --git a/doc/classes/XRInterface.xml b/doc/classes/XRInterface.xml index db65ce62f2..cdada35970 100644 --- a/doc/classes/XRInterface.xml +++ b/doc/classes/XRInterface.xml @@ -210,7 +210,7 @@ This interface supports quad rendering (not yet supported by Godot). </constant> <constant name="XR_VR" value="8" enum="Capabilities"> - this interface supports VR. + This interface supports VR. </constant> <constant name="XR_AR" value="16" enum="Capabilities"> This interface supports AR (video background and real world tracking). diff --git a/drivers/alsa/SCsub b/drivers/alsa/SCsub index 1d76bb18c4..f17acb0f91 100644 --- a/drivers/alsa/SCsub +++ b/drivers/alsa/SCsub @@ -3,6 +3,7 @@ Import("env") if "alsa" in env and env["alsa"]: - env.add_source_files(env.drivers_sources, "asound-so_wrap.c") + if env["use_sowrap"]: + env.add_source_files(env.drivers_sources, "asound-so_wrap.c") env.add_source_files(env.drivers_sources, "*.cpp") diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp index 20cd8dd26c..689f76389b 100644 --- a/drivers/alsa/audio_driver_alsa.cpp +++ b/drivers/alsa/audio_driver_alsa.cpp @@ -37,7 +37,7 @@ #include <errno.h> -#ifdef PULSEAUDIO_ENABLED +#if defined(PULSEAUDIO_ENABLED) && defined(SOWRAP_ENABLED) extern "C" { extern int initialize_pulse(int verbose); } @@ -153,6 +153,7 @@ Error AudioDriverALSA::init_output_device() { } Error AudioDriverALSA::init() { +#ifdef SOWRAP_ENABLED #ifdef DEBUG_ENABLED int dylibloader_verbose = 1; #else @@ -167,7 +168,7 @@ Error AudioDriverALSA::init() { if (initialize_asound(dylibloader_verbose)) { return ERR_CANT_OPEN; } - +#endif active.clear(); exit_thread.clear(); diff --git a/drivers/alsa/audio_driver_alsa.h b/drivers/alsa/audio_driver_alsa.h index 821ba1d145..b62d7188dd 100644 --- a/drivers/alsa/audio_driver_alsa.h +++ b/drivers/alsa/audio_driver_alsa.h @@ -38,7 +38,11 @@ #include "core/templates/safe_refcount.h" #include "servers/audio_server.h" +#ifdef SOWRAP_ENABLED #include "asound-so_wrap.h" +#else +#include <alsa/asoundlib.h> +#endif class AudioDriverALSA : public AudioDriver { Thread thread; diff --git a/drivers/alsamidi/midi_driver_alsamidi.h b/drivers/alsamidi/midi_driver_alsamidi.h index 3c6300411c..80cc96310f 100644 --- a/drivers/alsamidi/midi_driver_alsamidi.h +++ b/drivers/alsamidi/midi_driver_alsamidi.h @@ -39,7 +39,12 @@ #include "core/templates/safe_refcount.h" #include "core/templates/vector.h" +#ifdef SOWRAP_ENABLED #include "../alsa/asound-so_wrap.h" +#else +#include <alsa/asoundlib.h> +#endif + #include <stdio.h> class MIDIDriverALSAMidi : public MIDIDriver { diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index 2e3e6263ed..600aa908cc 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -306,6 +306,15 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display glReadBuffer(GL_COLOR_ATTACHMENT0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, GLES3::TextureStorage::system_fbo); + + if (p_screen_rect.position != Vector2()) { + // Viewport doesn't cover entire window so clear window to black before blitting. + Size2i win_size = DisplayServer::get_singleton()->window_get_size(); + glViewport(0, 0, win_size.width, win_size.height); + glClearColor(0.0, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + } + Vector2i screen_rect_end = p_screen_rect.get_end(); glBlitFramebuffer(0, 0, rt->size.x, rt->size.y, p_screen_rect.position.x, flip_y ? screen_rect_end.y : p_screen_rect.position.y, screen_rect_end.x, flip_y ? p_screen_rect.position.y : screen_rect_end.y, diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 1a18f35e64..6cc6b8224c 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1895,6 +1895,10 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_ glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo); glViewport(0, 0, rb->width, rb->height); + glCullFace(GL_BACK); + glEnable(GL_CULL_FACE); + scene_state.cull_mode = GLES3::SceneShaderData::CULL_BACK; + // Do depth prepass if it's explicitly enabled bool use_depth_prepass = config->use_depth_prepass; @@ -1910,9 +1914,6 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_ glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glDisable(GL_SCISSOR_TEST); - glCullFace(GL_BACK); - glEnable(GL_CULL_FACE); - scene_state.cull_mode = GLES3::SceneShaderData::CULL_BACK; glColorMask(0, 0, 0, 0); glClearDepth(1.0f); diff --git a/drivers/gles3/shaders/stdlib_inc.glsl b/drivers/gles3/shaders/stdlib_inc.glsl index 0b76c4334a..92bf2d87e4 100644 --- a/drivers/gles3/shaders/stdlib_inc.glsl +++ b/drivers/gles3/shaders/stdlib_inc.glsl @@ -14,11 +14,7 @@ uint float2half(uint f) { uint half2float(uint h) { uint h_e = h & uint(0x7c00); - if (h_e == uint(0x0000)) { - return uint(0); - } else { - return ((h & uint(0x8000)) << uint(16)) | ((h_e + uint(0x1c000)) << uint(13)) | ((h & uint(0x03ff)) << uint(13)); - } + return ((h & uint(0x8000)) << uint(16)) | uint((h_e >> uint(10)) != uint(0)) * (((h_e + uint(0x1c000)) << uint(13)) | ((h & uint(0x03ff)) << uint(13))); } uint packHalf2x16(vec2 v) { diff --git a/drivers/pulseaudio/SCsub b/drivers/pulseaudio/SCsub index 467d1448dc..f48489d787 100644 --- a/drivers/pulseaudio/SCsub +++ b/drivers/pulseaudio/SCsub @@ -3,6 +3,7 @@ Import("env") if "pulseaudio" in env and env["pulseaudio"]: - env.add_source_files(env.drivers_sources, "pulse-so_wrap.c") + if env["use_sowrap"]: + env.add_source_files(env.drivers_sources, "pulse-so_wrap.c") env.add_source_files(env.drivers_sources, "*.cpp") diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp index 0246af4fea..797ffd67fe 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp +++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp @@ -37,7 +37,11 @@ #include "core/version.h" #ifdef ALSAMIDI_ENABLED +#ifdef SOWRAP_ENABLED #include "drivers/alsa/asound-so_wrap.h" +#else +#include <alsa/asoundlib.h> +#endif #endif void AudioDriverPulseAudio::pa_state_cb(pa_context *c, void *userdata) { @@ -272,6 +276,7 @@ Error AudioDriverPulseAudio::init_output_device() { } Error AudioDriverPulseAudio::init() { +#ifdef SOWRAP_ENABLED #ifdef DEBUG_ENABLED int dylibloader_verbose = 1; #else @@ -284,7 +289,7 @@ Error AudioDriverPulseAudio::init() { if (initialize_pulse(dylibloader_verbose)) { return ERR_CANT_OPEN; } - +#endif active.clear(); exit_thread.clear(); diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.h b/drivers/pulseaudio/audio_driver_pulseaudio.h index f4ff44d361..585e882059 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.h +++ b/drivers/pulseaudio/audio_driver_pulseaudio.h @@ -38,7 +38,11 @@ #include "core/templates/safe_refcount.h" #include "servers/audio_server.h" +#ifdef SOWRAP_ENABLED #include "pulse-so_wrap.h" +#else +#include <pulse/pulseaudio.h> +#endif class AudioDriverPulseAudio : public AudioDriver { Thread thread; diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp index 43d3f53904..ee3cb876cf 100644 --- a/drivers/unix/file_access_unix.cpp +++ b/drivers/unix/file_access_unix.cpp @@ -318,6 +318,10 @@ Error FileAccessUnix::_set_unix_permissions(const String &p_file, uint32_t p_per return FAILED; } +void FileAccessUnix::close() { + _close(); +} + CloseNotificationFunc FileAccessUnix::close_notification_func = nullptr; FileAccessUnix::~FileAccessUnix() { diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h index 884fb9567f..79c4e73636 100644 --- a/drivers/unix/file_access_unix.h +++ b/drivers/unix/file_access_unix.h @@ -82,6 +82,8 @@ public: virtual uint32_t _get_unix_permissions(const String &p_file) override; virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override; + virtual void close() override; + FileAccessUnix() {} virtual ~FileAccessUnix(); }; diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index ea40622afc..0e51586b5a 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -375,6 +375,10 @@ Error FileAccessWindows::_set_unix_permissions(const String &p_file, uint32_t p_ return ERR_UNAVAILABLE; } +void FileAccessWindows::close() { + _close(); +} + FileAccessWindows::~FileAccessWindows() { _close(); } @@ -391,6 +395,7 @@ void FileAccessWindows::initialize() { reserved_file_index++; } } + void FileAccessWindows::finalize() { invalid_files.clear(); } diff --git a/drivers/windows/file_access_windows.h b/drivers/windows/file_access_windows.h index 2b9960d494..453f8d3b5f 100644 --- a/drivers/windows/file_access_windows.h +++ b/drivers/windows/file_access_windows.h @@ -82,6 +82,8 @@ public: virtual uint32_t _get_unix_permissions(const String &p_file) override; virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override; + virtual void close() override; + static void initialize(); static void finalize(); diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 9f3893a5db..c27417f037 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -1522,6 +1522,8 @@ void AnimationTimelineEdit::set_animation(const Ref<Animation> &p_animation, boo animation = p_animation; read_only = p_read_only; + length->set_read_only(read_only); + if (animation.is_valid()) { len_hb->show(); if (read_only) { @@ -6621,7 +6623,7 @@ AnimationTrackEditor::AnimationTrackEditor() { optimize_dialog = memnew(ConfirmationDialog); add_child(optimize_dialog); - optimize_dialog->set_title(TTR("Anim. Optimizer")); + optimize_dialog->set_title(TTR("Animation Optimizer")); VBoxContainer *optimize_vb = memnew(VBoxContainer); optimize_dialog->add_child(optimize_vb); @@ -6630,19 +6632,19 @@ AnimationTrackEditor::AnimationTrackEditor() { optimize_velocity_error->set_min(0.001); optimize_velocity_error->set_step(0.001); optimize_velocity_error->set_value(0.01); - optimize_vb->add_margin_child(TTR("Max. Velocity Error:"), optimize_velocity_error); + optimize_vb->add_margin_child(TTR("Max Velocity Error:"), optimize_velocity_error); optimize_angular_error = memnew(SpinBox); optimize_angular_error->set_max(1.0); optimize_angular_error->set_min(0.001); optimize_angular_error->set_step(0.001); optimize_angular_error->set_value(0.01); - optimize_vb->add_margin_child(TTR("Max. Angular Error:"), optimize_angular_error); + optimize_vb->add_margin_child(TTR("Max Angular Error:"), optimize_angular_error); optimize_precision_error = memnew(SpinBox); optimize_precision_error->set_max(6); optimize_precision_error->set_min(1); optimize_precision_error->set_step(1); optimize_precision_error->set_value(3); - optimize_vb->add_margin_child(TTR("Max. Precision Error:"), optimize_precision_error); + optimize_vb->add_margin_child(TTR("Max Precision Error:"), optimize_precision_error); optimize_dialog->set_ok_button_text(TTR("Optimize")); optimize_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_OPTIMIZE_ANIMATION_CONFIRM)); @@ -6733,7 +6735,7 @@ AnimationTrackEditor::AnimationTrackEditor() { // bake_dialog = memnew(ConfirmationDialog); - bake_dialog->set_title(TTR("Anim. Baker")); + bake_dialog->set_title(TTR("Animation Baker")); bake_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_BAKE_ANIMATION_CONFIRM)); add_child(bake_dialog); GridContainer *bake_grid = memnew(GridContainer); diff --git a/editor/animation_track_editor_plugins.cpp b/editor/animation_track_editor_plugins.cpp index 2895aa9710..be4a070213 100644 --- a/editor/animation_track_editor_plugins.cpp +++ b/editor/animation_track_editor_plugins.cpp @@ -847,9 +847,14 @@ bool AnimationTrackEditTypeAudio::is_key_selectable_by_distance() const { void AnimationTrackEditTypeAudio::draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right) { Ref<AudioStream> stream = get_animation()->audio_track_get_key_stream(get_track(), p_index); - if (!stream.is_valid()) { - AnimationTrackEdit::draw_key(p_index, p_pixels_sec, p_x, p_selected, p_clip_left, p_clip_right); + AnimationTrackEdit::draw_key(p_index, p_pixels_sec, p_x, p_selected, p_clip_left, p_clip_right); // Draw diamond. + return; + } + + float len = stream->get_length(); + if (len == 0) { + AnimationTrackEdit::draw_key(p_index, p_pixels_sec, p_x, p_selected, p_clip_left, p_clip_right); // Draw diamond. return; } @@ -871,16 +876,10 @@ void AnimationTrackEditTypeAudio::draw_key(int p_index, float p_pixels_sec, int int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label")); float fh = int(font->get_height(font_size) * 1.5); - float len = stream->get_length(); - Ref<AudioStreamPreview> preview = AudioStreamPreviewGenerator::get_singleton()->generate_preview(stream); float preview_len = preview->get_length(); - if (len == 0) { - len = preview_len; - } - int pixel_total_len = len * p_pixels_sec; len -= end_ofs; @@ -1044,16 +1043,13 @@ void AnimationTrackEditTypeAudio::gui_input(const Ref<InputEvent> &p_event) { continue; } - float start_ofs = get_animation()->audio_track_get_key_start_offset(get_track(), i); - float end_ofs = get_animation()->audio_track_get_key_end_offset(get_track(), i); float len = stream->get_length(); - if (len == 0) { - Ref<AudioStreamPreview> preview = AudioStreamPreviewGenerator::get_singleton()->generate_preview(stream); - float preview_len = preview->get_length(); - len = preview_len; + continue; } + float start_ofs = get_animation()->audio_track_get_key_start_offset(get_track(), i); + float end_ofs = get_animation()->audio_track_get_key_end_offset(get_track(), i); len -= end_ofs; len -= start_ofs; diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 97a73d89e7..9a8a1097cd 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -1629,14 +1629,15 @@ void CodeTextEditor::toggle_inline_comment(const String &delimiter) { int selection_i = 0; int offset = (is_commented ? -1 : 1) * delimiter.length(); for (const int &c2 : caret_edit_order) { + bool is_line_selection = text_editor->has_selection(c2) && text_editor->get_selection_from_line(c2) < text_editor->get_selection_to_line(c2); if (text_editor->get_caret_line(c2) >= from && text_editor->get_caret_line(c2) <= to) { int caret_col = caret_cols[caret_i++]; - caret_col += (caret_col == 0) ? 0 : offset; + caret_col += (is_line_selection && caret_col == 0) ? 0 : offset; text_editor->set_caret_column(caret_col, c2 == 0, c2); } if (text_editor->has_selection(c2) && text_editor->get_selection_to_line(c2) >= from && text_editor->get_selection_to_line(c2) <= to) { int from_col = text_editor->get_selection_from_column(c2); - from_col += (from_col == 0) ? 0 : offset; + from_col += (is_line_selection && from_col == 0) ? 0 : offset; int to_col = selection_to_cols[selection_i++]; to_col += (to_col == 0) ? 0 : offset; text_editor->select( diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp index e4730faf38..b0d6135d52 100644 --- a/editor/debugger/editor_profiler.cpp +++ b/editor/debugger/editor_profiler.cpp @@ -624,7 +624,9 @@ EditorProfiler::EditorProfiler() { hb->add_child(memnew(Label(TTR("Time:")))); display_time = memnew(OptionButton); + // TRANSLATORS: This is an option in the profiler to display the time spent in a function, including the time spent in other functions called by that function. display_time->add_item(TTR("Inclusive")); + // TRANSLATORS: This is an option in the profiler to display the time spent in a function, exincluding the time spent in other functions called by that function. display_time->add_item(TTR("Self")); display_time->set_tooltip_text(TTR("Inclusive: Includes time from other functions called by this function.\nUse this to spot bottlenecks.\n\nSelf: Only count the time spent in the function itself, not in other functions called by that function.\nUse this to find individual functions to optimize.")); display_time->connect("item_selected", callable_mp(this, &EditorProfiler::_combo_changed)); diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index f4cefc606b..ed7638414c 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -1336,6 +1336,8 @@ EditorAudioBuses::EditorAudioBuses() { add_child(file_dialog); file_dialog->connect("file_selected", callable_mp(this, &EditorAudioBuses::_file_dialog_callback)); + AudioServer::get_singleton()->connect("bus_layout_changed", callable_mp(this, &EditorAudioBuses::_update_buses)); + set_process(true); } diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index 4a1f0b4c09..80d1e9dcd7 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -472,6 +472,14 @@ void EditorFileDialog::_action_pressed() { } } + // First check we're not having an empty name. + String file_name = file_text.strip_edges().get_file(); + if (file_name.is_empty()) { + error_dialog->set_text(TTR("Cannot save file with an empty filename.")); + error_dialog->popup_centered(Size2(250, 80) * EDSCALE); + return; + } + // Add first extension of filter if no valid extension is found. if (!valid) { int idx = filter->get_selected(); @@ -480,9 +488,15 @@ void EditorFileDialog::_action_pressed() { f += "." + ext; } + if (file_name.begins_with(".")) { // Could still happen if typed manually. + error_dialog->set_text(TTR("Cannot save file with a name starting with a dot.")); + error_dialog->popup_centered(Size2(250, 80) * EDSCALE); + return; + } + if (dir_access->file_exists(f) && !disable_overwrite_warning) { - confirm_save->set_text(TTR("File exists, overwrite?")); - confirm_save->popup_centered(Size2(200, 80)); + confirm_save->set_text(vformat(TTR("File \"%s\" already exists.\nDo you want to overwrite it?"), f)); + confirm_save->popup_centered(Size2(250, 80) * EDSCALE); } else { _save_to_recent(); hide(); diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index dd912eac42..4533bcc51c 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -693,7 +693,7 @@ void EditorProperty::gui_input(const Ref<InputEvent> &p_event) { bool is_valid_revert = false; Variant revert_value = EditorPropertyRevert::get_property_revert_value(object, property, &is_valid_revert); ERR_FAIL_COND(!is_valid_revert); - emit_changed(property, revert_value); + emit_changed(_get_revert_property(), revert_value); update_property(); } diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 33bba90c70..30c7d2b85f 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -4174,9 +4174,12 @@ struct EditorPropertyRangeHint { bool radians = false; }; -static EditorPropertyRangeHint _parse_range_hint(PropertyHint p_hint, const String &p_hint_text, double p_default_step) { +static EditorPropertyRangeHint _parse_range_hint(PropertyHint p_hint, const String &p_hint_text, double p_default_step, bool is_int = false) { EditorPropertyRangeHint hint; hint.step = p_default_step; + if (is_int) { + hint.hide_slider = false; // Always show slider for ints, unless specified in hint range. + } Vector<String> slices = p_hint_text.split(","); if (p_hint == PROPERTY_HINT_RANGE) { ERR_FAIL_COND_V_MSG(slices.size() < 2, hint, @@ -4294,7 +4297,7 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ } else { EditorPropertyInteger *editor = memnew(EditorPropertyInteger); - EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1); + EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1, true); editor->setup(hint.min, hint.max, hint.step, hint.hide_slider, hint.or_greater, hint.or_less, hint.suffix); return editor; @@ -4383,7 +4386,7 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ } break; case Variant::VECTOR2I: { EditorPropertyVector2i *editor = memnew(EditorPropertyVector2i(p_wide)); - EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1); + EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1, true); editor->setup(hint.min, hint.max, p_hint == PROPERTY_HINT_LINK, hint.suffix); return editor; @@ -4396,7 +4399,7 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ } break; case Variant::RECT2I: { EditorPropertyRect2i *editor = memnew(EditorPropertyRect2i(p_wide)); - EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1); + EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1, true); editor->setup(hint.min, hint.max, hint.suffix); return editor; @@ -4410,7 +4413,7 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ } break; case Variant::VECTOR3I: { EditorPropertyVector3i *editor = memnew(EditorPropertyVector3i(p_wide)); - EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1); + EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1, true); editor->setup(hint.min, hint.max, p_hint == PROPERTY_HINT_LINK, hint.suffix); return editor; @@ -4424,7 +4427,7 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ } break; case Variant::VECTOR4I: { EditorPropertyVector4i *editor = memnew(EditorPropertyVector4i); - EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1); + EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1, true); editor->setup(hint.min, hint.max, hint.suffix); return editor; diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index dd84f3b9e1..23e32dcbd8 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -384,9 +384,6 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { if (score > 0 && score >= best_score) { best = locale; best_score = score; - if (score == 10) { - break; // Exact match, skip the rest. - } } } if (best_score == 0) { diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp index a46484bb0e..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; } @@ -1513,7 +1514,7 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b f = FileAccess::open(p_path, FileAccess::WRITE); if (f.is_null()) { DirAccess::remove_file_or_error(tmppath); - add_message(EXPORT_MESSAGE_ERROR, TTR("Save PCK"), vformat(TTR("Can't open file to read from path \"%s\"."), tmppath)); + add_message(EXPORT_MESSAGE_ERROR, TTR("Save PCK"), vformat(TTR("Can't open file for writing at path \"%s\"."), p_path)); return ERR_CANT_CREATE; } } else { @@ -1521,7 +1522,7 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b f = FileAccess::open(p_path, FileAccess::READ_WRITE); if (f.is_null()) { DirAccess::remove_file_or_error(tmppath); - add_message(EXPORT_MESSAGE_ERROR, TTR("Save PCK"), vformat(TTR("Can't open executable file from path \"%s\"."), tmppath)); + add_message(EXPORT_MESSAGE_ERROR, TTR("Save PCK"), vformat(TTR("Can't open file for reading-writing at path \"%s\"."), p_path)); return ERR_FILE_CANT_OPEN; } diff --git a/editor/export/editor_export_platform_pc.cpp b/editor/export/editor_export_platform_pc.cpp index bbfd73be5e..7f934bc45b 100644 --- a/editor/export/editor_export_platform_pc.cpp +++ b/editor/export/editor_export_platform_pc.cpp @@ -33,6 +33,9 @@ #include "core/config/project_settings.h" void EditorExportPlatformPC::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const { + if (p_preset->get("texture_format/bptc")) { + r_features->push_back("bptc"); + } if (p_preset->get("texture_format/s3tc")) { r_features->push_back("s3tc"); } 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 b001b4f766..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; @@ -3392,7 +3393,6 @@ void Node3DEditorViewport::_menu_option(int p_option) { VIEW_DISPLAY_SHADELESS, VIEW_DISPLAY_LIGHTING, VIEW_DISPLAY_NORMAL_BUFFER, - VIEW_DISPLAY_WIREFRAME, VIEW_DISPLAY_DEBUG_SHADOW_ATLAS, VIEW_DISPLAY_DEBUG_DIRECTIONAL_SHADOW_ATLAS, VIEW_DISPLAY_DEBUG_VOXEL_GI_ALBEDO, @@ -3422,7 +3422,6 @@ void Node3DEditorViewport::_menu_option(int p_option) { Viewport::DEBUG_DRAW_UNSHADED, Viewport::DEBUG_DRAW_LIGHTING, Viewport::DEBUG_DRAW_NORMAL_BUFFER, - Viewport::DEBUG_DRAW_WIREFRAME, Viewport::DEBUG_DRAW_SHADOW_ATLAS, Viewport::DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS, Viewport::DEBUG_DRAW_VOXEL_GI_ALBEDO, @@ -3445,9 +3444,7 @@ void Node3DEditorViewport::_menu_option(int p_option) { Viewport::DEBUG_DRAW_MOTION_VECTORS, }; - int idx = 0; - - while (display_options[idx] != VIEW_MAX) { + for (int idx = 0; display_options[idx] != VIEW_MAX; idx++) { int id = display_options[idx]; int item_idx = view_menu->get_popup()->get_item_index(id); if (item_idx != -1) { @@ -3461,7 +3458,6 @@ void Node3DEditorViewport::_menu_option(int p_option) { if (id == p_option) { viewport->set_debug_draw(debug_draw_modes[idx]); } - idx++; } } break; } @@ -4961,6 +4957,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p view_menu->get_popup()->add_separator(); view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_lock_rotation", TTR("Lock View Rotation")), VIEW_LOCK_ROTATION); view_menu->get_popup()->add_separator(); + // TRANSLATORS: "Normal" as in "normal life", not "normal vector". view_menu->get_popup()->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_normal", TTR("Display Normal")), VIEW_DISPLAY_NORMAL); view_menu->get_popup()->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_wireframe", TTR("Display Wireframe")), VIEW_DISPLAY_WIREFRAME); view_menu->get_popup()->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_overdraw", TTR("Display Overdraw")), VIEW_DISPLAY_OVERDRAW); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 6d747ba6a8..ccbc7c3d74 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -2518,7 +2518,7 @@ void ScriptEditor::save_all_scripts() { } else { // For built-in scripts, save their scenes instead. const String scene_path = edited_res->get_path().get_slice("::", 0); - if (!scenes_to_save.has(scene_path)) { + if (!scene_path.is_empty() && !scenes_to_save.has(scene_path)) { scenes_to_save.push_back(scene_path); } } diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index 073adb467a..2519928ea3 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -3223,6 +3223,7 @@ void ThemeTypeEditor::_update_stylebox_from_leading() { if (!leading_stylebox.pinned || leading_stylebox.stylebox.is_null()) { return; } + ERR_FAIL_COND_MSG(edited_theme.is_null(), "Leading stylebox does not have an edited theme to update"); // Prevent changes from immediately being reported while the operation is still ongoing. edited_theme->_freeze_change_propagation(); @@ -3706,7 +3707,11 @@ void ThemeEditorPlugin::edit(Object *p_node) { if (Object::cast_to<Theme>(p_node)) { theme_editor->edit(Object::cast_to<Theme>(p_node)); } else { - theme_editor->edit(Ref<Theme>()); + // We intentionally keep a reference to the last used theme to work around + // the the editor being hidden while base resources are edited. Uncomment + // the following line again and remove this comment once that bug has been + // fixed (scheduled for Godot 4.1 in PR 73098): + // theme_editor->edit(Ref<Theme>()); } } diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp index 04a09a97e7..4d9e2db682 100644 --- a/editor/plugins/tiles/tile_map_editor.cpp +++ b/editor/plugins/tiles/tile_map_editor.cpp @@ -2055,7 +2055,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { select_tool_button->set_flat(true); select_tool_button->set_toggle_mode(true); select_tool_button->set_button_group(tool_buttons_group); - select_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/selection_tool", "Selection", Key::S)); + select_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/selection_tool", TTR("Selection"), Key::S)); select_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar)); tilemap_tiles_tools_buttons->add_child(select_tool_button); @@ -2063,7 +2063,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { paint_tool_button->set_flat(true); paint_tool_button->set_toggle_mode(true); paint_tool_button->set_button_group(tool_buttons_group); - paint_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/paint_tool", "Paint", Key::D)); + paint_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/paint_tool", TTR("Paint"), Key::D)); paint_tool_button->set_tooltip_text(TTR("Shift: Draw line.") + "\n" + TTR("Shift+Ctrl: Draw rectangle.")); paint_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar)); tilemap_tiles_tools_buttons->add_child(paint_tool_button); @@ -2072,7 +2072,8 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { line_tool_button->set_flat(true); line_tool_button->set_toggle_mode(true); line_tool_button->set_button_group(tool_buttons_group); - line_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/line_tool", "Line", Key::L)); + // TRANSLATORS: This refers to the line tool in the tilemap editor. + line_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/line_tool", TTR("Line", "Tool"), Key::L)); line_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar)); tilemap_tiles_tools_buttons->add_child(line_tool_button); @@ -2080,7 +2081,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { rect_tool_button->set_flat(true); rect_tool_button->set_toggle_mode(true); rect_tool_button->set_button_group(tool_buttons_group); - rect_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/rect_tool", "Rect", Key::R)); + rect_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/rect_tool", TTR("Rect"), Key::R)); rect_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar)); tilemap_tiles_tools_buttons->add_child(rect_tool_button); @@ -2088,7 +2089,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { bucket_tool_button->set_flat(true); bucket_tool_button->set_toggle_mode(true); bucket_tool_button->set_button_group(tool_buttons_group); - bucket_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/bucket_tool", "Bucket", Key::B)); + bucket_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/bucket_tool", TTR("Bucket"), Key::B)); bucket_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar)); tilemap_tiles_tools_buttons->add_child(bucket_tool_button); toolbar->add_child(tilemap_tiles_tools_buttons); @@ -2104,7 +2105,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { picker_button = memnew(Button); picker_button->set_flat(true); picker_button->set_toggle_mode(true); - picker_button->set_shortcut(ED_SHORTCUT("tiles_editor/picker", "Picker", Key::P)); + picker_button->set_shortcut(ED_SHORTCUT("tiles_editor/picker", TTR("Picker"), Key::P)); picker_button->set_tooltip_text(TTR("Alternatively hold Ctrl with other tools to pick tile.")); picker_button->connect("pressed", callable_mp(CanvasItemEditor::get_singleton(), &CanvasItemEditor::update_viewport)); tools_settings->add_child(picker_button); @@ -2113,7 +2114,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { erase_button = memnew(Button); erase_button->set_flat(true); erase_button->set_toggle_mode(true); - erase_button->set_shortcut(ED_SHORTCUT("tiles_editor/eraser", "Eraser", Key::E)); + erase_button->set_shortcut(ED_SHORTCUT("tiles_editor/eraser", TTR("Eraser"), Key::E)); erase_button->set_tooltip_text(TTR("Alternatively use RMB to erase tiles.")); erase_button->connect("pressed", callable_mp(CanvasItemEditor::get_singleton(), &CanvasItemEditor::update_viewport)); tools_settings->add_child(erase_button); @@ -3180,7 +3181,7 @@ void TileMapEditorTerrainsPlugin::_update_terrains_tree() { terrain_set_tree_item->set_icon(0, main_vbox_container->get_theme_icon(SNAME("TerrainMatchSides"), SNAME("EditorIcons"))); matches = String(TTR("Matches Sides Only")); } - terrain_set_tree_item->set_text(0, vformat("Terrain Set %d (%s)", terrain_set_index, matches)); + terrain_set_tree_item->set_text(0, vformat(TTR("Terrain Set %d (%s)"), terrain_set_index, matches)); terrain_set_tree_item->set_selectable(0, false); for (int terrain_index = 0; terrain_index < tile_set->get_terrains_count(terrain_set_index); terrain_index++) { @@ -3329,7 +3330,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() { main_vbox_container = memnew(VBoxContainer); main_vbox_container->connect("tree_entered", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_theme)); main_vbox_container->connect("theme_changed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_theme)); - main_vbox_container->set_name("Terrains"); + main_vbox_container->set_name(TTR("Terrains")); HSplitContainer *tilemap_tab_terrains = memnew(HSplitContainer); tilemap_tab_terrains->set_h_size_flags(Control::SIZE_EXPAND_FILL); @@ -3365,7 +3366,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() { paint_tool_button->set_toggle_mode(true); paint_tool_button->set_button_group(tool_buttons_group); paint_tool_button->set_pressed(true); - paint_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/paint_tool", "Paint", Key::D)); + paint_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/paint_tool", TTR("Paint"), Key::D)); paint_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_toolbar)); tilemap_tiles_tools_buttons->add_child(paint_tool_button); @@ -3373,7 +3374,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() { line_tool_button->set_flat(true); line_tool_button->set_toggle_mode(true); line_tool_button->set_button_group(tool_buttons_group); - line_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/line_tool", "Line", Key::L)); + line_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/line_tool", TTR("Line"), Key::L)); line_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_toolbar)); tilemap_tiles_tools_buttons->add_child(line_tool_button); @@ -3381,7 +3382,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() { rect_tool_button->set_flat(true); rect_tool_button->set_toggle_mode(true); rect_tool_button->set_button_group(tool_buttons_group); - rect_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/rect_tool", "Rect", Key::R)); + rect_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/rect_tool", TTR("Rect"), Key::R)); rect_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_toolbar)); tilemap_tiles_tools_buttons->add_child(rect_tool_button); @@ -3389,7 +3390,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() { bucket_tool_button->set_flat(true); bucket_tool_button->set_toggle_mode(true); bucket_tool_button->set_button_group(tool_buttons_group); - bucket_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/bucket_tool", "Bucket", Key::B)); + bucket_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/bucket_tool", TTR("Bucket"), Key::B)); bucket_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_toolbar)); tilemap_tiles_tools_buttons->add_child(bucket_tool_button); @@ -3406,7 +3407,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() { picker_button = memnew(Button); picker_button->set_flat(true); picker_button->set_toggle_mode(true); - picker_button->set_shortcut(ED_SHORTCUT("tiles_editor/picker", "Picker", Key::P)); + picker_button->set_shortcut(ED_SHORTCUT("tiles_editor/picker", TTR("Picker"), Key::P)); picker_button->connect("pressed", callable_mp(CanvasItemEditor::get_singleton(), &CanvasItemEditor::update_viewport)); tools_settings->add_child(picker_button); @@ -3414,7 +3415,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() { erase_button = memnew(Button); erase_button->set_flat(true); erase_button->set_toggle_mode(true); - erase_button->set_shortcut(ED_SHORTCUT("tiles_editor/eraser", "Eraser", Key::E)); + erase_button->set_shortcut(ED_SHORTCUT("tiles_editor/eraser", TTR("Eraser"), Key::E)); erase_button->connect("pressed", callable_mp(CanvasItemEditor::get_singleton(), &CanvasItemEditor::update_viewport)); tools_settings->add_child(erase_button); diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp index e56541b50d..fcefbb7d06 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp @@ -34,6 +34,7 @@ #include "editor/editor_inspector.h" #include "editor/editor_node.h" +#include "editor/editor_property_name_processor.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" @@ -106,13 +107,13 @@ bool TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_get(const StringN void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::NIL, TTR("Atlas"), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY)); - p_list->push_back(PropertyInfo(Variant::INT, "id", PROPERTY_HINT_RANGE, "0," + itos(INT_MAX) + ",1")); - p_list->push_back(PropertyInfo(Variant::STRING, "name", PROPERTY_HINT_NONE, "")); - p_list->push_back(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D")); - p_list->push_back(PropertyInfo(Variant::VECTOR2I, "margins", PROPERTY_HINT_NONE, "suffix:px")); - p_list->push_back(PropertyInfo(Variant::VECTOR2I, "separation", PROPERTY_HINT_NONE)); - p_list->push_back(PropertyInfo(Variant::VECTOR2I, "texture_region_size", PROPERTY_HINT_NONE, "suffix:px")); - p_list->push_back(PropertyInfo(Variant::BOOL, "use_texture_padding", PROPERTY_HINT_NONE, "")); + p_list->push_back(PropertyInfo(Variant::INT, PNAME("id"), PROPERTY_HINT_RANGE, "0," + itos(INT_MAX) + ",1")); + p_list->push_back(PropertyInfo(Variant::STRING, PNAME("name"))); + p_list->push_back(PropertyInfo(Variant::OBJECT, PNAME("texture"), PROPERTY_HINT_RESOURCE_TYPE, "Texture2D")); + p_list->push_back(PropertyInfo(Variant::VECTOR2I, PNAME("margins"), PROPERTY_HINT_NONE, "suffix:px")); + p_list->push_back(PropertyInfo(Variant::VECTOR2I, PNAME("separation"))); + p_list->push_back(PropertyInfo(Variant::VECTOR2I, PNAME("texture_region_size"), PROPERTY_HINT_NONE, "suffix:px")); + p_list->push_back(PropertyInfo(Variant::BOOL, PNAME("use_texture_padding"))); } void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_bind_methods() { @@ -392,11 +393,11 @@ void TileSetAtlasSourceEditor::AtlasTileProxyObject::_get_property_list(List<Pro if (tiles.size() == 1) { if (tiles.front()->get().alternative == 0) { p_list->push_back(PropertyInfo(Variant::NIL, TTR("Base Tile"), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY)); - p_list->push_back(PropertyInfo(Variant::VECTOR2I, "atlas_coords")); - p_list->push_back(PropertyInfo(Variant::VECTOR2I, "size_in_atlas")); + p_list->push_back(PropertyInfo(Variant::VECTOR2I, PNAME("atlas_coords"))); + p_list->push_back(PropertyInfo(Variant::VECTOR2I, PNAME("size_in_atlas"))); } else { p_list->push_back(PropertyInfo(Variant::NIL, TTR("Alternative Tile"), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY)); - p_list->push_back(PropertyInfo(Variant::INT, "alternative_id")); + p_list->push_back(PropertyInfo(Variant::INT, PNAME("alternative_id"))); } } else { p_list->push_back(PropertyInfo(Variant::NIL, TTR("Tiles"), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY)); @@ -413,17 +414,17 @@ void TileSetAtlasSourceEditor::AtlasTileProxyObject::_get_property_list(List<Pro } if (all_alternatve_id_zero) { - p_list->push_back(PropertyInfo(Variant::NIL, "Animation", PROPERTY_HINT_NONE, "animation_", PROPERTY_USAGE_GROUP)); - p_list->push_back(PropertyInfo(Variant::INT, "animation_columns", PROPERTY_HINT_NONE, "")); - p_list->push_back(PropertyInfo(Variant::VECTOR2I, "animation_separation", PROPERTY_HINT_NONE, "")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "animation_speed", PROPERTY_HINT_NONE, "")); - p_list->push_back(PropertyInfo(Variant::INT, "animation_frames_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ARRAY, "Frames,animation_frame_")); + p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Animation", "animation_"), PROPERTY_HINT_NONE, "animation_", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::INT, PNAME("animation_columns"))); + p_list->push_back(PropertyInfo(Variant::VECTOR2I, PNAME("animation_separation"))); + p_list->push_back(PropertyInfo(Variant::FLOAT, PNAME("animation_speed"))); + p_list->push_back(PropertyInfo(Variant::INT, PNAME("animation_frames_count"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ARRAY, "Frames,animation_frame_")); // Not optimal, but returns value for the first tile. This is similar to what MultiNodeEdit does. if (tile_set_atlas_source->get_tile_animation_frames_count(tiles.front()->get().tile) == 1) { p_list->push_back(PropertyInfo(Variant::FLOAT, "animation_frame_0/duration", PROPERTY_HINT_NONE, "suffix:s", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY)); } else { for (int i = 0; i < tile_set_atlas_source->get_tile_animation_frames_count(tiles.front()->get().tile); i++) { - p_list->push_back(PropertyInfo(Variant::FLOAT, vformat("animation_frame_%d/duration", i), PROPERTY_HINT_NONE, "suffix:s")); + p_list->push_back(PropertyInfo(Variant::FLOAT, vformat("animation_frame_%d/%s", i, PNAME("duration")), PROPERTY_HINT_NONE, "suffix:s")); } } } @@ -641,9 +642,9 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() { // List of editors. // --- Rendering --- - ADD_TILE_DATA_EDITOR_GROUP("Rendering"); + ADD_TILE_DATA_EDITOR_GROUP(TTR("Rendering")); - ADD_TILE_DATA_EDITOR(group, "Texture Origin", "texture_origin"); + ADD_TILE_DATA_EDITOR(group, TTR("Texture Origin"), "texture_origin"); if (!tile_data_editors.has("texture_origin")) { TileDataTextureOriginEditor *tile_data_texture_origin_editor = memnew(TileDataTextureOriginEditor); tile_data_texture_origin_editor->hide(); @@ -653,7 +654,7 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() { tile_data_editors["texture_origin"] = tile_data_texture_origin_editor; } - ADD_TILE_DATA_EDITOR(group, "Modulate", "modulate"); + ADD_TILE_DATA_EDITOR(group, TTR("Modulate"), "modulate"); if (!tile_data_editors.has("modulate")) { TileDataDefaultEditor *tile_data_modulate_editor = memnew(TileDataDefaultEditor()); tile_data_modulate_editor->hide(); @@ -663,7 +664,7 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() { tile_data_editors["modulate"] = tile_data_modulate_editor; } - ADD_TILE_DATA_EDITOR(group, "Z Index", "z_index"); + ADD_TILE_DATA_EDITOR(group, TTR("Z Index"), "z_index"); if (!tile_data_editors.has("z_index")) { TileDataDefaultEditor *tile_data_z_index_editor = memnew(TileDataDefaultEditor()); tile_data_z_index_editor->hide(); @@ -673,7 +674,7 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() { tile_data_editors["z_index"] = tile_data_z_index_editor; } - ADD_TILE_DATA_EDITOR(group, "Y Sort Origin", "y_sort_origin"); + ADD_TILE_DATA_EDITOR(group, TTR("Y Sort Origin"), "y_sort_origin"); if (!tile_data_editors.has("y_sort_origin")) { TileDataYSortEditor *tile_data_y_sort_editor = memnew(TileDataYSortEditor); tile_data_y_sort_editor->hide(); @@ -684,7 +685,7 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() { } for (int i = 0; i < tile_set->get_occlusion_layers_count(); i++) { - ADD_TILE_DATA_EDITOR(group, vformat("Occlusion Layer %d", i), vformat("occlusion_layer_%d", i)); + ADD_TILE_DATA_EDITOR(group, vformat(TTR("Occlusion Layer %d"), i), vformat("occlusion_layer_%d", i)); if (!tile_data_editors.has(vformat("occlusion_layer_%d", i))) { TileDataOcclusionShapeEditor *tile_data_occlusion_shape_editor = memnew(TileDataOcclusionShapeEditor()); tile_data_occlusion_shape_editor->hide(); @@ -700,7 +701,7 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() { } // --- Rendering --- - ADD_TILE_DATA_EDITOR(root, "Terrains", "terrain_set"); + ADD_TILE_DATA_EDITOR(root, TTR("Terrains"), "terrain_set"); if (!tile_data_editors.has("terrain_set")) { TileDataTerrainsEditor *tile_data_terrains_editor = memnew(TileDataTerrainsEditor); tile_data_terrains_editor->hide(); @@ -710,7 +711,7 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() { } // --- Miscellaneous --- - ADD_TILE_DATA_EDITOR(root, "Probability", "probability"); + ADD_TILE_DATA_EDITOR(root, TTR("Probability"), "probability"); if (!tile_data_editors.has("probability")) { TileDataDefaultEditor *tile_data_probability_editor = memnew(TileDataDefaultEditor()); tile_data_probability_editor->hide(); @@ -721,9 +722,9 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() { } // --- Physics --- - ADD_TILE_DATA_EDITOR_GROUP("Physics"); + ADD_TILE_DATA_EDITOR_GROUP(TTR("Physics")); for (int i = 0; i < tile_set->get_physics_layers_count(); i++) { - ADD_TILE_DATA_EDITOR(group, vformat("Physics Layer %d", i), vformat("physics_layer_%d", i)); + ADD_TILE_DATA_EDITOR(group, vformat(TTR("Physics Layer %d"), i), vformat("physics_layer_%d", i)); if (!tile_data_editors.has(vformat("physics_layer_%d", i))) { TileDataCollisionEditor *tile_data_collision_editor = memnew(TileDataCollisionEditor()); tile_data_collision_editor->hide(); @@ -739,9 +740,9 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() { } // --- Navigation --- - ADD_TILE_DATA_EDITOR_GROUP("Navigation"); + ADD_TILE_DATA_EDITOR_GROUP(TTR("Navigation")); for (int i = 0; i < tile_set->get_navigation_layers_count(); i++) { - ADD_TILE_DATA_EDITOR(group, vformat("Navigation Layer %d", i), vformat("navigation_layer_%d", i)); + ADD_TILE_DATA_EDITOR(group, vformat(TTR("Navigation Layer %d"), i), vformat("navigation_layer_%d", i)); if (!tile_data_editors.has(vformat("navigation_layer_%d", i))) { TileDataNavigationEditor *tile_data_navigation_editor = memnew(TileDataNavigationEditor()); tile_data_navigation_editor->hide(); @@ -757,14 +758,14 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() { } // --- Custom Data --- - ADD_TILE_DATA_EDITOR_GROUP("Custom Data"); + ADD_TILE_DATA_EDITOR_GROUP(TTR("Custom Data")); for (int i = 0; i < tile_set->get_custom_data_layers_count(); i++) { String editor_name = vformat("custom_data_%d", i); String prop_name = tile_set->get_custom_data_layer_name(i); Variant::Type prop_type = tile_set->get_custom_data_layer_type(i); if (prop_name.is_empty()) { - ADD_TILE_DATA_EDITOR(group, vformat("Custom Data %d", i), editor_name); + ADD_TILE_DATA_EDITOR(group, vformat(TTR("Custom Data %d"), i), editor_name); } else { ADD_TILE_DATA_EDITOR(group, prop_name, editor_name); } @@ -2414,6 +2415,14 @@ void TileSetAtlasSourceEditor::_notification(int p_what) { } } } break; + + case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { + if (EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/localize_settings")) { + EditorPropertyNameProcessor::Style style = EditorPropertyNameProcessor::get_singleton()->get_settings_style(); + atlas_source_inspector->set_property_name_style(style); + tile_inspector->set_property_name_style(style); + } + } break; } } @@ -2483,6 +2492,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() { tile_inspector->edit(tile_proxy_object); tile_inspector->set_use_folding(true); tile_inspector->connect("property_selected", callable_mp(this, &TileSetAtlasSourceEditor::_inspector_property_selected)); + tile_inspector->set_property_name_style(EditorPropertyNameProcessor::get_singleton()->get_settings_style()); middle_vbox_container->add_child(tile_inspector); tile_inspector_no_tile_selected_label = memnew(Label); @@ -2534,6 +2544,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() { atlas_source_inspector->set_v_size_flags(SIZE_EXPAND_FILL); atlas_source_inspector->set_show_categories(true); atlas_source_inspector->edit(atlas_source_proxy_object); + atlas_source_inspector->set_property_name_style(EditorPropertyNameProcessor::get_singleton()->get_settings_style()); middle_vbox_container->add_child(atlas_source_inspector); // -- Right side -- diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp index cc276597fa..101ec5f66c 100644 --- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp @@ -32,6 +32,7 @@ #include "editor/editor_file_system.h" #include "editor/editor_node.h" +#include "editor/editor_property_name_processor.h" #include "editor/editor_resource_preview.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" @@ -362,6 +363,14 @@ void TileSetScenesCollectionSourceEditor::_notification(int p_what) { _update_scenes_list(); _update_action_buttons(); } break; + + case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { + if (EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/localize_settings")) { + EditorPropertyNameProcessor::Style style = EditorPropertyNameProcessor::get_singleton()->get_settings_style(); + scenes_collection_source_inspector->set_property_name_style(style); + tile_inspector->set_property_name_style(style); + } + } break; } } @@ -503,6 +512,7 @@ TileSetScenesCollectionSourceEditor::TileSetScenesCollectionSourceEditor() { scenes_collection_source_inspector = memnew(EditorInspector); scenes_collection_source_inspector->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED); scenes_collection_source_inspector->edit(scenes_collection_source_proxy_object); + scenes_collection_source_inspector->set_property_name_style(EditorPropertyNameProcessor::get_singleton()->get_settings_style()); middle_vbox_container->add_child(scenes_collection_source_inspector); // Tile inspector. @@ -519,6 +529,7 @@ TileSetScenesCollectionSourceEditor::TileSetScenesCollectionSourceEditor() { tile_inspector->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED); tile_inspector->edit(tile_proxy_object); tile_inspector->set_use_folding(true); + tile_inspector->set_property_name_style(EditorPropertyNameProcessor::get_singleton()->get_settings_style()); middle_vbox_container->add_child(tile_inspector); // Scenes list. diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index a43745b70f..374ce98d63 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -412,7 +412,7 @@ void ProjectSettingsEditor::_action_renamed(const String &p_old_name, const Stri Dictionary action = GLOBAL_GET(old_property_name); EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); - undo_redo->create_action(TTR("Rename Input Action Event")); + undo_redo->create_action(TTR("Rename Input Action")); // Do: clear old, set new undo_redo->add_do_method(ProjectSettings::get_singleton(), "clear", old_property_name); undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", new_property_name, action); diff --git a/main/main.cpp b/main/main.cpp index 81f2c101a1..ae3a6d2a94 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1843,7 +1843,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph GLOBAL_DEF("display/window/ios/hide_home_indicator", true); GLOBAL_DEF("display/window/ios/hide_status_bar", true); GLOBAL_DEF("display/window/ios/suppress_ui_gesture", true); - GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "input_devices/pointing/ios/touch_delay", PROPERTY_HINT_RANGE, "0,1,0.001"), 0.15); // XR project settings. GLOBAL_DEF_RST_BASIC("xr/openxr/enabled", false); diff --git a/methods.py b/methods.py index 7ede2592ff..dddac9bd86 100644 --- a/methods.py +++ b/methods.py @@ -732,7 +732,7 @@ def add_to_vs_project(env, sources): env.vs_srcs += [basename + ".cpp"] -def generate_vs_project(env, num_jobs): +def generate_vs_project(env, num_jobs, project_name="godot"): batch_file = find_visual_c_batch_file(env) if batch_file: @@ -873,7 +873,7 @@ def generate_vs_project(env, num_jobs): env["MSVS"]["PROJECTSUFFIX"] = ".vcxproj" env["MSVS"]["SOLUTIONSUFFIX"] = ".sln" env.MSVSProject( - target=["#godot" + env["MSVSPROJECTSUFFIX"]], + target=["#" + project_name + env["MSVSPROJECTSUFFIX"]], incs=env.vs_incs, srcs=env.vs_srcs, auto_build_solution=1, diff --git a/modules/basis_universal/SCsub b/modules/basis_universal/SCsub index 161b0f3814..14669847bc 100644 --- a/modules/basis_universal/SCsub +++ b/modules/basis_universal/SCsub @@ -40,6 +40,9 @@ if not env.msvc: else: env_basisu.Prepend(CPPPATH=[thirdparty_dir]) +if env["builtin_zstd"]: + env_basisu.Prepend(CPPPATH=["#thirdparty/zstd"]) + if env.dev_build: env_basisu.Append(CPPDEFINES=[("BASISU_DEVEL_MESSAGES", 1), ("BASISD_ENABLE_DEBUG_FLAGS", 1)]) diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index 923b2fe30d..0b7e4e50e6 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -4,7 +4,7 @@ Built-in GDScript functions. </brief_description> <description> - A list of GDScript-specific utility functions accessed in any script. + A list of GDScript-specific utility functions and annotations accessible from any script. For the list of the global functions and constants see [@GlobalScope]. </description> <tutorials> @@ -20,7 +20,7 @@ <description> Returns a [Color] constructed from red ([param r8]), green ([param g8]), blue ([param b8]), and optionally alpha ([param a8]) integer channels, each divided by [code]255.0[/code] for their final value. [codeblock] - var red = Color8(255, 0, 0) # Same as Color(1, 0, 0) + var red = Color8(255, 0, 0) # Same as Color(1, 0, 0). var dark_blue = Color8(0, 0, 51) # Same as Color(0, 0, 0.2). var my_color = Color8(306, 255, 0, 102) # Same as Color(1.2, 1, 0, 0.4). [/codeblock] @@ -37,10 +37,10 @@ [codeblock] # Imagine we always want speed to be between 0 and 20. var speed = -10 - assert(speed < 20) # True, the program will continue - assert(speed >= 0) # False, the program will stop - assert(speed >= 0 and speed < 20) # You can also combine the two conditional statements in one check - assert(speed < 20, "the speed limit is 20") # Show a message + assert(speed < 20) # True, the program will continue. + assert(speed >= 0) # False, the program will stop. + assert(speed >= 0 and speed < 20) # You can also combine the two conditional statements in one check. + assert(speed < 20, "the speed limit is 20") # Show a message. [/codeblock] </description> </method> @@ -140,7 +140,7 @@ <param index="0" name="path" type="String" /> <description> Returns a [Resource] from the filesystem located at the absolute [param path]. Unless it's already referenced elsewhere (such as in another script or in the scene), the resource is loaded from disk on function call, which might cause a slight delay, especially when loading large scenes. To avoid unnecessary delays when loading something multiple times, either store the resource in a variable or use [method preload]. - [b]Note:[/b] Resource paths can be obtained by right-clicking on a resource in the FileSystem dock and choosing "Copy Path" or by dragging the file from the FileSystem dock into the script. + [b]Note:[/b] Resource paths can be obtained by right-clicking on a resource in the FileSystem dock and choosing "Copy Path", or by dragging the file from the FileSystem dock into the current script. [codeblock] # Load a scene called "main" located in the root of the project directory and cache it in a variable. var main = load("res://main.tscn") # main will contain a PackedScene resource. @@ -155,7 +155,7 @@ <param index="0" name="path" type="String" /> <description> Returns a [Resource] from the filesystem located at [param path]. During run-time, the resource is loaded when the script is being parsed. This function effectively acts as a reference to that resource. Note that this function requires [param path] to be a constant [String]. If you want to load a resource from a dynamic/variable path, use [method load]. - [b]Note:[/b] Resource paths can be obtained by right clicking on a resource in the Assets Panel and choosing "Copy Path" or by dragging the file from the FileSystem dock into the script. + [b]Note:[/b] Resource paths can be obtained by right-clicking on a resource in the Assets Panel and choosing "Copy Path", or by dragging the file from the FileSystem dock into the current script. [codeblock] # Create instance of a scene. var diamond = preload("res://diamond.tscn").instantiate() @@ -259,10 +259,12 @@ <annotation name="@export"> <return type="void" /> <description> - Mark the following property as exported (editable in the Inspector dock and saved to disk). To control the type of the exported property use the type hint notation. + Mark the following property as exported (editable in the Inspector dock and saved to disk). To control the type of the exported property, use the type hint notation. [codeblock] + @export var string = "" @export var int_number = 5 @export var float_number: float = 5 + @export var image : Image [/codeblock] </description> </annotation> @@ -273,20 +275,20 @@ Define a new category for the following exported properties. This helps to organize properties in the Inspector dock. See also [constant PROPERTY_USAGE_CATEGORY]. [codeblock] - @export_category("My Properties") - @export var number = 3 - @export var string = "" + @export_category("Statistics") + @export var hp = 30 + @export var speed = 1.25 [/codeblock] - [b]Note:[/b] Categories in the property list are supposed to indicate different base types, so the use of this annotation is not encouraged. See [annotation @export_group] and [annotation @export_subgroup] instead. + [b]Note:[/b] Categories in the Inspector dock's list usually divide properties coming from different classes (Node, Node2D, Sprite, etc.). For better clarity, it's recommended to use [annotation @export_group] and [annotation @export_subgroup], instead. </description> </annotation> <annotation name="@export_color_no_alpha"> <return type="void" /> <description> - Export a [Color] property without transparency (its alpha fixed as [code]1.0[/code]). + Export a [Color] property without allowing its transparency ([member Color.a]) to be edited. See also [constant PROPERTY_HINT_COLOR_NO_ALPHA]. [codeblock] - @export_color_no_alpha var modulate_color: Color + @export_color_no_alpha var dye_color : Color [/codeblock] </description> </annotation> @@ -296,7 +298,7 @@ Export a [String] property as a path to a directory. The path will be limited to the project folder and its subfolders. See [annotation @export_global_dir] to allow picking from the entire filesystem. See also [constant PROPERTY_HINT_DIR]. [codeblock] - @export_dir var sprite_folder: String + @export_dir var sprite_folder_path: String [/codeblock] </description> </annotation> @@ -343,8 +345,8 @@ If [param filter] is provided, only matching files will be available for picking. See also [constant PROPERTY_HINT_FILE]. [codeblock] - @export_file var sound_effect_file: String - @export_file("*.txt") var notes_file: String + @export_file var sound_effect_path: String + @export_file("*.txt") var notes_path: String [/codeblock] </description> </annotation> @@ -436,10 +438,10 @@ <annotation name="@export_global_dir"> <return type="void" /> <description> - Export a [String] property as a path to a directory. The path can be picked from the entire filesystem. See [annotation @export_dir] to limit it to the project folder and its subfolders. + Export a [String] property as an absolute path to a directory. The path can be picked from the entire filesystem. See [annotation @export_dir] to limit it to the project folder and its subfolders. See also [constant PROPERTY_HINT_GLOBAL_DIR]. [codeblock] - @export_global_dir var sprite_folder: String + @export_global_dir var sprite_folder_path: String [/codeblock] </description> </annotation> @@ -447,12 +449,12 @@ <return type="void" /> <param index="0" name="filter" type="String" default="""" /> <description> - Export a [String] property as a path to a file. The path can be picked from the entire filesystem. See [annotation @export_file] to limit it to the project folder and its subfolders. + Export a [String] property as an absolute path to a file. The path can be picked from the entire filesystem. See [annotation @export_file] to limit it to the project folder and its subfolders. If [param filter] is provided, only matching files will be available for picking. See also [constant PROPERTY_HINT_GLOBAL_FILE]. [codeblock] - @export_global_file var sound_effect_file: String - @export_global_file("*.txt") var notes_file: String + @export_global_file var sound_effect_path: String + @export_global_file("*.txt") var notes_path: String [/codeblock] </description> </annotation> @@ -466,13 +468,13 @@ Groups cannot be nested, use [annotation @export_subgroup] to add subgroups within groups. See also [constant PROPERTY_USAGE_GROUP]. [codeblock] - @export_group("My Properties") - @export var number = 3 - @export var string = "" + @export_group("Racer Properties") + @export var nickname = "Nick" + @export var age = 26 - @export_group("Prefixed Properties", "prefix_") - @export var prefix_number = 3 - @export var prefix_string = "" + @export_group("Car Properties", "car_") + @export var car_label = "Speedy" + @export var car_number = 3 @export_group("", "") @export var ungrouped_number = 3 @@ -544,13 +546,13 @@ Define a new subgroup for the following exported properties. This helps to organize properties in the Inspector dock. Subgroups work exactly like groups, except they need a parent group to exist. See [annotation @export_group]. See also [constant PROPERTY_USAGE_SUBGROUP]. [codeblock] - @export_group("My Properties") - @export var number = 3 - @export var string = "" + @export_group("Racer Properties") + @export var nickname = "Nick" + @export var age = 26 - @export_subgroup("My Prefixed Properties", "prefix_") - @export var prefix_number = 3 - @export var prefix_string = "" + @export_subgroup("Car Properties", "car_") + @export var car_label = "Speedy" + @export var car_number = 3 [/codeblock] [b]Note:[/b] Subgroups cannot be nested, they only provide one extra level of depth. Just like the next group ends the previous group, so do the subsequent subgroups. </description> @@ -571,7 +573,7 @@ <annotation name="@onready"> <return type="void" /> <description> - Mark the following property as assigned on [Node]'s ready state change. Values for these properties are not assigned immediately upon the node's creation, and instead are computed and stored right before [method Node._ready]. + Mark the following property as assigned when the [Node] is ready. Values for these properties are not assigned immediately when the node is initialized ([method Object._init]), and instead are computed and stored right before [method Node._ready]. [codeblock] @onready var character_name: Label = $Label [/codeblock] diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index de0dacece3..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); } @@ -4278,11 +4279,15 @@ Variant GDScriptAnalyzer::make_variable_default_value(GDScriptParser::VariableNo } } else { GDScriptParser::DataType datatype = p_variable->get_datatype(); - if (datatype.is_hard_type() && datatype.kind == GDScriptParser::DataType::BUILTIN && datatype.builtin_type != Variant::OBJECT) { - if (datatype.builtin_type == Variant::ARRAY && datatype.has_container_element_type()) { - result = make_array_from_element_datatype(datatype.get_container_element_type()); - } else { - VariantInternal::initialize(&result, datatype.builtin_type); + if (datatype.is_hard_type()) { + if (datatype.kind == GDScriptParser::DataType::BUILTIN && datatype.builtin_type != Variant::OBJECT) { + if (datatype.builtin_type == Variant::ARRAY && datatype.has_container_element_type()) { + result = make_array_from_element_datatype(datatype.get_container_element_type()); + } else { + VariantInternal::initialize(&result, datatype.builtin_type); + } + } else if (datatype.kind == GDScriptParser::DataType::ENUM) { + result = 0; } } } 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/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp index 520f33261a..7dcdc8e7cf 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.cpp +++ b/modules/gltf/editor/editor_scene_importer_blend.cpp @@ -214,7 +214,14 @@ Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_ } return nullptr; } + +#ifndef DISABLE_DEPRECATED + bool trimming = p_options.has("animation/trimming") ? (bool)p_options["animation/trimming"] : false; + bool remove_immutable = p_options.has("animation/remove_immutable_tracks") ? (bool)p_options["animation/remove_immutable_tracks"] : true; + return gltf->generate_scene(state, (float)p_options["animation/fps"], trimming, remove_immutable); +#else return gltf->generate_scene(state, (float)p_options["animation/fps"], (bool)p_options["animation/trimming"], (bool)p_options["animation/remove_immutable_tracks"]); +#endif } Variant EditorSceneFormatImporterBlend::get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, diff --git a/modules/gltf/editor/editor_scene_importer_fbx.cpp b/modules/gltf/editor/editor_scene_importer_fbx.cpp index d829630032..f8f458fcc7 100644 --- a/modules/gltf/editor/editor_scene_importer_fbx.cpp +++ b/modules/gltf/editor/editor_scene_importer_fbx.cpp @@ -100,7 +100,14 @@ Node *EditorSceneFormatImporterFBX::import_scene(const String &p_path, uint32_t } return nullptr; } + +#ifndef DISABLE_DEPRECATED + bool trimming = p_options.has("animation/trimming") ? (bool)p_options["animation/trimming"] : false; + bool remove_immutable = p_options.has("animation/remove_immutable_tracks") ? (bool)p_options["animation/remove_immutable_tracks"] : true; + return gltf->generate_scene(state, (float)p_options["animation/fps"], trimming, remove_immutable); +#else return gltf->generate_scene(state, (float)p_options["animation/fps"], (bool)p_options["animation/trimming"], (bool)p_options["animation/remove_immutable_tracks"]); +#endif } Variant EditorSceneFormatImporterFBX::get_option_visibility(const String &p_path, bool p_for_animation, diff --git a/modules/gltf/editor/editor_scene_importer_gltf.cpp b/modules/gltf/editor/editor_scene_importer_gltf.cpp index 012a144d52..5339275439 100644 --- a/modules/gltf/editor/editor_scene_importer_gltf.cpp +++ b/modules/gltf/editor/editor_scene_importer_gltf.cpp @@ -47,15 +47,15 @@ void EditorSceneFormatImporterGLTF::get_extensions(List<String> *r_extensions) c Node *EditorSceneFormatImporterGLTF::import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, List<String> *r_missing_deps, Error *r_err) { - Ref<GLTFDocument> doc; - doc.instantiate(); + Ref<GLTFDocument> gltf; + gltf.instantiate(); Ref<GLTFState> state; state.instantiate(); if (p_options.has("gltf/embedded_image_handling")) { int32_t enum_option = p_options["gltf/embedded_image_handling"]; state->set_handle_binary_image(enum_option); } - Error err = doc->append_from_file(p_path, state, p_flags); + Error err = gltf->append_from_file(p_path, state, p_flags); if (err != OK) { if (r_err) { *r_err = err; @@ -67,21 +67,11 @@ Node *EditorSceneFormatImporterGLTF::import_scene(const String &p_path, uint32_t } #ifndef DISABLE_DEPRECATED - if (p_options.has("animation/trimming")) { - if (p_options.has("animation/remove_immutable_tracks")) { - return doc->generate_scene(state, (float)p_options["animation/fps"], (bool)p_options["animation/trimming"], (bool)p_options["animation/remove_immutable_tracks"]); - } else { - return doc->generate_scene(state, (float)p_options["animation/fps"], (bool)p_options["animation/trimming"], true); - } - } else { - if (p_options.has("animation/remove_immutable_tracks")) { - return doc->generate_scene(state, (float)p_options["animation/fps"], false, (bool)p_options["animation/remove_immutable_tracks"]); - } else { - return doc->generate_scene(state, (float)p_options["animation/fps"], false, true); - } - } + bool trimming = p_options.has("animation/trimming") ? (bool)p_options["animation/trimming"] : false; + bool remove_immutable = p_options.has("animation/remove_immutable_tracks") ? (bool)p_options["animation/remove_immutable_tracks"] : true; + return gltf->generate_scene(state, (float)p_options["animation/fps"], trimming, remove_immutable); #else - return doc->generate_scene(state, (float)p_options["animation/fps"], (bool)p_options["animation/trimming"], (bool)p_options["animation/remove_immutable_tracks"]); + return gltf->generate_scene(state, (float)p_options["animation/fps"], (bool)p_options["animation/trimming"], (bool)p_options["animation/remove_immutable_tracks"]); #endif } diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 028028a103..e3ba290eb2 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -3285,7 +3285,6 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> p_state, const String &p_base_p tex.instantiate(); tex->set_name(img->get_name()); tex->set_keep_compressed_buffer(true); - p_state->source_images.push_back(img); tex->create_from_image(img, PortableCompressedTexture2D::COMPRESSION_MODE_BASIS_UNIVERSAL); p_state->images.push_back(tex); p_state->source_images.push_back(img); diff --git a/modules/gridmap/editor/grid_map_editor_plugin.cpp b/modules/gridmap/editor/grid_map_editor_plugin.cpp index 183190460e..9a7b37df21 100644 --- a/modules/gridmap/editor/grid_map_editor_plugin.cpp +++ b/modules/gridmap/editor/grid_map_editor_plugin.cpp @@ -1197,6 +1197,7 @@ GridMapEditor::GridMapEditor() { options->get_popup()->add_item(TTR("Cursor Back Rotate Z"), MENU_OPTION_CURSOR_BACK_ROTATE_Z, KeyModifierMask::SHIFT + Key::D); options->get_popup()->add_item(TTR("Cursor Clear Rotation"), MENU_OPTION_CURSOR_CLEAR_ROTATION, Key::W); options->get_popup()->add_separator(); + // TRANSLATORS: This is a toggle to select after pasting the new content. options->get_popup()->add_check_item(TTR("Paste Selects"), MENU_OPTION_PASTE_SELECTS); options->get_popup()->add_separator(); options->get_popup()->add_item(TTR("Duplicate Selection"), MENU_OPTION_SELECTION_DUPLICATE, KeyModifierMask::CTRL + Key::C); diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs index ed3a4c6e26..6c5c61acb9 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs @@ -302,7 +302,7 @@ namespace GodotTools.Build public static bool CleanProjectBlocking( [DisallowNull] string configuration, [AllowNull] string platform = null - ) => CleanProjectBlocking(CreateBuildInfo(configuration, platform, rebuild: false)); + ) => CleanProjectBlocking(CreateBuildInfo(configuration, platform, rebuild: false, onlyClean: true)); public static bool PublishProjectBlocking( [DisallowNull] string configuration, diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs index 43ead4af69..060c01b3f9 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs +++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs @@ -272,8 +272,7 @@ namespace GodotTools } } - string resourcePath = ProjectSettings.GlobalizePath("res://"); - args.Add(resourcePath); + args.Add(Path.GetDirectoryName(GodotSharpDirs.ProjectSlnPath)); string scriptPath = ProjectSettings.GlobalizePath(script.ResourcePath); diff --git a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs index 3226ca79e5..6b000cc89b 100644 --- a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs +++ b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs @@ -168,7 +168,9 @@ using Godot.NativeInterop; { var parameter = callback.Parameters[i]; - source.Append(parameter.ToDisplayString()); + AppendRefKind(source, parameter.RefKind); + source.Append(' '); + source.Append(parameter.Type.FullQualifiedNameIncludeGlobal()); source.Append(' '); source.Append(parameter.Name); diff --git a/modules/multiplayer/scene_replication_interface.cpp b/modules/multiplayer/scene_replication_interface.cpp index 3466cb10df..68b6bc4a24 100644 --- a/modules/multiplayer/scene_replication_interface.cpp +++ b/modules/multiplayer/scene_replication_interface.cpp @@ -742,6 +742,7 @@ Error SceneReplicationInterface::on_sync_receive(int p_from, const uint8_t *p_bu ofs += 4; uint32_t size = decode_uint32(&p_buffer[ofs]); ofs += 4; + ERR_FAIL_COND_V(size > uint32_t(p_buffer_len - ofs), ERR_INVALID_DATA); MultiplayerSynchronizer *sync = nullptr; if (net_id & 0x80000000) { sync = Object::cast_to<MultiplayerSynchronizer>(multiplayer->get_path_cache()->get_cached_object(p_from, net_id & 0x7FFFFFFF)); @@ -756,14 +757,15 @@ Error SceneReplicationInterface::on_sync_receive(int p_from, const uint8_t *p_bu } Node *node = sync->get_root_node(); if (sync->get_multiplayer_authority() != p_from || !node) { - ERR_CONTINUE(true); + // Not valid for me. + ofs += size; + ERR_CONTINUE_MSG(true, "Ignoring sync data from non-authority or for missing node."); } if (!sync->update_inbound_sync_time(time)) { // State is too old. ofs += size; continue; } - ERR_FAIL_COND_V(size > uint32_t(p_buffer_len - ofs), ERR_BUG); const List<NodePath> props = sync->get_replication_config()->get_sync_properties(); Vector<Variant> vars; vars.resize(props.size()); diff --git a/modules/navigation/SCsub b/modules/navigation/SCsub index 0b0822db2d..a9277657f4 100644 --- a/modules/navigation/SCsub +++ b/modules/navigation/SCsub @@ -10,7 +10,7 @@ env_navigation = env_modules.Clone() thirdparty_obj = [] # Recast Thirdparty source files -if env["builtin_recast"]: +if env["builtin_recastnavigation"]: thirdparty_dir = "#thirdparty/recastnavigation/Recast/" thirdparty_sources = [ "Source/Recast.cpp", diff --git a/modules/ogg/ogg_packet_sequence.h b/modules/ogg/ogg_packet_sequence.h index 4aa5ffa254..7085504500 100644 --- a/modules/ogg/ogg_packet_sequence.h +++ b/modules/ogg/ogg_packet_sequence.h @@ -32,11 +32,10 @@ #define OGG_PACKET_SEQUENCE_H #include "core/io/resource.h" -#include "core/object/gdvirtual.gen.inc" -#include "core/variant/native_ptr.h" #include "core/variant/typed_array.h" #include "core/variant/variant.h" -#include "thirdparty/libogg/ogg/ogg.h" + +#include <ogg/ogg.h> class OggPacketSequencePlayback; diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub index 4a9c7b3567..b7b7dccdb0 100644 --- a/modules/text_server_adv/SCsub +++ b/modules/text_server_adv/SCsub @@ -7,7 +7,6 @@ env_text_server_adv = env_modules.Clone() def make_icu_data(target, source, env): - dst = target[0].srcnode().abspath g = open(dst, "w", encoding="utf-8") @@ -126,7 +125,7 @@ if env["builtin_harfbuzz"]: env_harfbuzz.Prepend(CPPPATH=["#thirdparty/harfbuzz/src"]) env_harfbuzz.Append(CCFLAGS=["-DHAVE_ICU"]) - if env["builtin_icu"]: + if env["builtin_icu4c"]: env_harfbuzz.Prepend(CPPPATH=["#thirdparty/icu4c/common/", "#thirdparty/icu4c/i18n/"]) env_harfbuzz.Append(CCFLAGS=["-DU_HAVE_LIB_SUFFIX=1", "-DU_LIB_SUFFIX_C_NAME=_godot", "-DHAVE_ICU_BUILTIN"]) @@ -240,7 +239,7 @@ if env["builtin_graphite"] and freetype_enabled and env["graphite"]: env.Append(LIBS=[lib]) -if env["builtin_icu"]: +if env["builtin_icu4c"]: env_icu = env_modules.Clone() env_icu.disable_warnings() diff --git a/modules/vorbis/audio_stream_ogg_vorbis.cpp b/modules/vorbis/audio_stream_ogg_vorbis.cpp index f3ae35ce42..fcd717cfec 100644 --- a/modules/vorbis/audio_stream_ogg_vorbis.cpp +++ b/modules/vorbis/audio_stream_ogg_vorbis.cpp @@ -32,7 +32,8 @@ #include "core/io/file_access.h" #include "core/variant/typed_array.h" -#include "thirdparty/libogg/ogg/ogg.h" + +#include <ogg/ogg.h> int AudioStreamPlaybackOggVorbis::_mix_internal(AudioFrame *p_buffer, int p_frames) { ERR_FAIL_COND_V(!ready, 0); diff --git a/modules/vorbis/audio_stream_ogg_vorbis.h b/modules/vorbis/audio_stream_ogg_vorbis.h index ad6746eae2..c76df7f84d 100644 --- a/modules/vorbis/audio_stream_ogg_vorbis.h +++ b/modules/vorbis/audio_stream_ogg_vorbis.h @@ -34,7 +34,8 @@ #include "core/variant/variant.h" #include "modules/ogg/ogg_packet_sequence.h" #include "servers/audio/audio_stream.h" -#include "thirdparty/libvorbis/vorbis/codec.h" + +#include <vorbis/codec.h> class AudioStreamOggVorbis; diff --git a/modules/vorbis/resource_importer_ogg_vorbis.cpp b/modules/vorbis/resource_importer_ogg_vorbis.cpp index b712d63030..9e280de0ca 100644 --- a/modules/vorbis/resource_importer_ogg_vorbis.cpp +++ b/modules/vorbis/resource_importer_ogg_vorbis.cpp @@ -33,8 +33,9 @@ #include "core/io/file_access.h" #include "core/io/resource_saver.h" #include "scene/resources/texture.h" -#include "thirdparty/libogg/ogg/ogg.h" -#include "thirdparty/libvorbis/vorbis/codec.h" + +#include <ogg/ogg.h> +#include <vorbis/codec.h> #ifdef TOOLS_ENABLED #include "editor/import/audio_stream_import_settings.h" diff --git a/platform/android/android_input_handler.cpp b/platform/android/android_input_handler.cpp index 6d34e28182..63045237e9 100644 --- a/platform/android/android_input_handler.cpp +++ b/platform/android/android_input_handler.cpp @@ -49,11 +49,19 @@ void AndroidInputHandler::process_joy_event(AndroidInputHandler::JoypadEvent p_e } } -void AndroidInputHandler::_set_key_modifier_state(Ref<InputEventWithModifiers> ev) { - ev->set_shift_pressed(shift_mem); - ev->set_alt_pressed(alt_mem); - ev->set_meta_pressed(meta_mem); - ev->set_ctrl_pressed(control_mem); +void AndroidInputHandler::_set_key_modifier_state(Ref<InputEventWithModifiers> ev, Key p_keycode) { + if (p_keycode != Key::SHIFT) { + ev->set_shift_pressed(shift_mem); + } + if (p_keycode != Key::ALT) { + ev->set_alt_pressed(alt_mem); + } + if (p_keycode != Key::META) { + ev->set_meta_pressed(meta_mem); + } + if (p_keycode != Key::CTRL) { + ev->set_ctrl_pressed(control_mem); + } } void AndroidInputHandler::process_key_event(int p_physical_keycode, int p_unicode, int p_key_label, bool p_pressed) { @@ -118,7 +126,7 @@ void AndroidInputHandler::process_key_event(int p_physical_keycode, int p_unicod ev->set_unicode(fix_unicode(unicode)); ev->set_pressed(p_pressed); - _set_key_modifier_state(ev); + _set_key_modifier_state(ev, keycode); if (p_physical_keycode == AKEYCODE_BACK) { if (DisplayServerAndroid *dsa = Object::cast_to<DisplayServerAndroid>(DisplayServer::get_singleton())) { @@ -260,7 +268,7 @@ void AndroidInputHandler::_parse_mouse_event_info(BitField<MouseButtonMask> even Ref<InputEventMouseButton> ev; ev.instantiate(); - _set_key_modifier_state(ev); + _set_key_modifier_state(ev, Key::NONE); if (p_source_mouse_relative) { ev->set_position(hover_prev_pos); ev->set_global_position(hover_prev_pos); @@ -294,7 +302,7 @@ void AndroidInputHandler::process_mouse_event(int p_event_action, int p_event_an // https://developer.android.com/reference/android/view/MotionEvent.html#ACTION_HOVER_ENTER Ref<InputEventMouseMotion> ev; ev.instantiate(); - _set_key_modifier_state(ev); + _set_key_modifier_state(ev, Key::NONE); ev->set_position(p_event_pos); ev->set_global_position(p_event_pos); ev->set_relative(p_event_pos - hover_prev_pos); @@ -329,7 +337,7 @@ void AndroidInputHandler::process_mouse_event(int p_event_action, int p_event_an Ref<InputEventMouseMotion> ev; ev.instantiate(); - _set_key_modifier_state(ev); + _set_key_modifier_state(ev, Key::NONE); if (p_source_mouse_relative) { ev->set_position(hover_prev_pos); ev->set_global_position(hover_prev_pos); @@ -348,7 +356,7 @@ void AndroidInputHandler::process_mouse_event(int p_event_action, int p_event_an case AMOTION_EVENT_ACTION_SCROLL: { Ref<InputEventMouseButton> ev; ev.instantiate(); - _set_key_modifier_state(ev); + _set_key_modifier_state(ev, Key::NONE); if (p_source_mouse_relative) { ev->set_position(hover_prev_pos); ev->set_global_position(hover_prev_pos); @@ -375,7 +383,7 @@ void AndroidInputHandler::process_mouse_event(int p_event_action, int p_event_an void AndroidInputHandler::_wheel_button_click(BitField<MouseButtonMask> event_buttons_mask, const Ref<InputEventMouseButton> &ev, MouseButton wheel_button, float factor) { Ref<InputEventMouseButton> evd = ev->duplicate(); - _set_key_modifier_state(evd); + _set_key_modifier_state(evd, Key::NONE); evd->set_button_index(wheel_button); evd->set_button_mask(BitField<MouseButtonMask>(event_buttons_mask.operator int64_t() ^ int64_t(mouse_button_to_mask(wheel_button)))); evd->set_factor(factor); @@ -389,7 +397,7 @@ void AndroidInputHandler::_wheel_button_click(BitField<MouseButtonMask> event_bu void AndroidInputHandler::process_magnify(Point2 p_pos, float p_factor) { Ref<InputEventMagnifyGesture> magnify_event; magnify_event.instantiate(); - _set_key_modifier_state(magnify_event); + _set_key_modifier_state(magnify_event, Key::NONE); magnify_event->set_position(p_pos); magnify_event->set_factor(p_factor); Input::get_singleton()->parse_input_event(magnify_event); @@ -398,7 +406,7 @@ void AndroidInputHandler::process_magnify(Point2 p_pos, float p_factor) { void AndroidInputHandler::process_pan(Point2 p_pos, Vector2 p_delta) { Ref<InputEventPanGesture> pan_event; pan_event.instantiate(); - _set_key_modifier_state(pan_event); + _set_key_modifier_state(pan_event, Key::NONE); pan_event->set_position(p_pos); pan_event->set_delta(p_delta); Input::get_singleton()->parse_input_event(pan_event); diff --git a/platform/android/android_input_handler.h b/platform/android/android_input_handler.h index a56b6aa6c4..2badd32636 100644 --- a/platform/android/android_input_handler.h +++ b/platform/android/android_input_handler.h @@ -76,7 +76,7 @@ private: MouseEventInfo mouse_event_info; Point2 hover_prev_pos; // needed to calculate the relative position on hover events - void _set_key_modifier_state(Ref<InputEventWithModifiers> ev); + void _set_key_modifier_state(Ref<InputEventWithModifiers> ev, Key p_keycode); static MouseButton _button_index_from_mask(BitField<MouseButtonMask> button_mask); static BitField<MouseButtonMask> _android_button_mask_to_godot_button_mask(int android_button_mask); diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index fdd2fed836..641258a26c 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -251,7 +251,7 @@ static const int EXPORT_FORMAT_AAB = 1; static const char *APK_ASSETS_DIRECTORY = "res://android/build/assets"; static const char *AAB_ASSETS_DIRECTORY = "res://android/build/assetPacks/installTime/src/main/assets"; -static const int DEFAULT_MIN_SDK_VERSION = 21; // Should match the value in 'platform/android/java/app/config.gradle#minSdk' +static const int OPENGL_MIN_SDK_VERSION = 21; // Should match the value in 'platform/android/java/app/config.gradle#minSdk' static const int VULKAN_MIN_SDK_VERSION = 24; static const int DEFAULT_TARGET_SDK_VERSION = 32; // Should match the value in 'platform/android/java/app/config.gradle#targetSdk' @@ -1706,7 +1706,7 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "gradle_build/export_format", PROPERTY_HINT_ENUM, "Export APK,Export AAB"), EXPORT_FORMAT_APK)); // Using String instead of int to default to an empty string (no override) with placeholder for instructions (see GH-62465). // This implies doing validation that the string is a proper int. - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "gradle_build/min_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", DEFAULT_MIN_SDK_VERSION)), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "gradle_build/min_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", VULKAN_MIN_SDK_VERSION)), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "gradle_build/target_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", DEFAULT_TARGET_SDK_VERSION)), "")); Vector<PluginConfigAndroid> plugins_configs = get_plugins(); @@ -2337,7 +2337,7 @@ bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref<Edit // Check the min sdk version. String min_sdk_str = p_preset->get("gradle_build/min_sdk"); - int min_sdk_int = DEFAULT_MIN_SDK_VERSION; + int min_sdk_int = VULKAN_MIN_SDK_VERSION; if (!min_sdk_str.is_empty()) { // Empty means no override, nothing to do. if (!gradle_build_enabled) { valid = false; @@ -2350,9 +2350,9 @@ bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref<Edit err += "\n"; } else { min_sdk_int = min_sdk_str.to_int(); - if (min_sdk_int < DEFAULT_MIN_SDK_VERSION) { + if (min_sdk_int < OPENGL_MIN_SDK_VERSION) { valid = false; - err += vformat(TTR("\"Min SDK\" cannot be lower than %d, which is the version needed by the Godot library."), DEFAULT_MIN_SDK_VERSION); + err += vformat(TTR("\"Min SDK\" cannot be lower than %d, which is the version needed by the Godot library."), OPENGL_MIN_SDK_VERSION); err += "\n"; } } @@ -2808,7 +2808,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP String version_name = p_preset->get("version/name"); String min_sdk_version = p_preset->get("gradle_build/min_sdk"); if (!min_sdk_version.is_valid_int()) { - min_sdk_version = itos(DEFAULT_MIN_SDK_VERSION); + min_sdk_version = itos(VULKAN_MIN_SDK_VERSION); } String target_sdk_version = p_preset->get("gradle_build/target_sdk"); if (!target_sdk_version.is_valid_int()) { diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp index 5df05580a5..1249f2219f 100644 --- a/platform/android/file_access_android.cpp +++ b/platform/android/file_access_android.cpp @@ -169,6 +169,10 @@ bool FileAccessAndroid::file_exists(const String &p_path) { return true; } +void FileAccessAndroid::close() { + _close(); +} + FileAccessAndroid::~FileAccessAndroid() { _close(); } diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h index 1d25a28d90..b8f45628e5 100644 --- a/platform/android/file_access_android.h +++ b/platform/android/file_access_android.h @@ -78,6 +78,8 @@ public: virtual uint32_t _get_unix_permissions(const String &p_file) override { return 0; } virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override { return FAILED; } + virtual void close() override; + ~FileAccessAndroid(); }; diff --git a/platform/android/file_access_filesystem_jandroid.cpp b/platform/android/file_access_filesystem_jandroid.cpp index 7174d57344..ea8459d1ed 100644 --- a/platform/android/file_access_filesystem_jandroid.cpp +++ b/platform/android/file_access_filesystem_jandroid.cpp @@ -333,6 +333,12 @@ void FileAccessFilesystemJAndroid::setup(jobject p_file_access_handler) { _file_last_modified = env->GetMethodID(cls, "fileLastModified", "(Ljava/lang/String;)J"); } +void FileAccessFilesystemJAndroid::close() { + if (is_open()) { + _close(); + } +} + FileAccessFilesystemJAndroid::FileAccessFilesystemJAndroid() { id = 0; } diff --git a/platform/android/file_access_filesystem_jandroid.h b/platform/android/file_access_filesystem_jandroid.h index 7829ab7cf9..5e74d9de24 100644 --- a/platform/android/file_access_filesystem_jandroid.h +++ b/platform/android/file_access_filesystem_jandroid.h @@ -93,6 +93,8 @@ public: virtual uint32_t _get_unix_permissions(const String &p_file) override { return 0; } virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override { return FAILED; } + virtual void close() override; + FileAccessFilesystemJAndroid(); ~FileAccessFilesystemJAndroid(); }; diff --git a/platform/ios/SCsub b/platform/ios/SCsub index f3925c146f..18ba6617af 100644 --- a/platform/ios/SCsub +++ b/platform/ios/SCsub @@ -17,7 +17,6 @@ ios_lib = [ "display_layer.mm", "godot_app_delegate.m", "godot_view_renderer.mm", - "godot_view_gesture_recognizer.mm", "device_metrics.m", "keyboard_input_view.mm", "key_mapping_ios.mm", diff --git a/platform/ios/godot_view.h b/platform/ios/godot_view.h index 077584baa6..b00ca37ebe 100644 --- a/platform/ios/godot_view.h +++ b/platform/ios/godot_view.h @@ -59,9 +59,4 @@ class String; - (void)stopRendering; - (void)startRendering; -- (void)godotTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; -- (void)godotTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; -- (void)godotTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; -- (void)godotTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event; - @end diff --git a/platform/ios/godot_view.mm b/platform/ios/godot_view.mm index 4b10f95ab8..fafec79bf6 100644 --- a/platform/ios/godot_view.mm +++ b/platform/ios/godot_view.mm @@ -35,7 +35,6 @@ #include "core/string/ustring.h" #import "display_layer.h" #include "display_server_ios.h" -#import "godot_view_gesture_recognizer.h" #import "godot_view_renderer.h" #import <CoreMotion/CoreMotion.h> @@ -60,8 +59,6 @@ static const float earth_gravity = 9.80665; @property(strong, nonatomic) CMMotionManager *motionManager; -@property(strong, nonatomic) GodotViewGestureRecognizer *delayGestureRecognizer; - @end @implementation GodotView @@ -148,10 +145,6 @@ static const float earth_gravity = 9.80665; [self.animationTimer invalidate]; self.animationTimer = nil; } - - if (self.delayGestureRecognizer) { - self.delayGestureRecognizer = nil; - } } - (void)godot_commonInit { @@ -171,11 +164,6 @@ static const float earth_gravity = 9.80665; self.motionManager = nil; } } - - // Initialize delay gesture recognizer - GodotViewGestureRecognizer *gestureRecognizer = [[GodotViewGestureRecognizer alloc] init]; - self.delayGestureRecognizer = gestureRecognizer; - [self addGestureRecognizer:self.delayGestureRecognizer]; } - (void)stopRendering { @@ -347,58 +335,42 @@ static const float earth_gravity = 9.80665; } } -- (void)godotTouchesBegan:(NSSet *)touchesSet withEvent:(UIEvent *)event { - NSArray *tlist = [event.allTouches allObjects]; - for (unsigned int i = 0; i < [tlist count]; i++) { - if ([touchesSet containsObject:[tlist objectAtIndex:i]]) { - UITouch *touch = [tlist objectAtIndex:i]; - int tid = [self getTouchIDForTouch:touch]; - ERR_FAIL_COND(tid == -1); - CGPoint touchPoint = [touch locationInView:self]; - DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, true, touch.tapCount > 1); - } +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { + for (UITouch *touch in touches) { + int tid = [self getTouchIDForTouch:touch]; + ERR_FAIL_COND(tid == -1); + CGPoint touchPoint = [touch locationInView:self]; + DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, true, touch.tapCount > 1); } } -- (void)godotTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { - NSArray *tlist = [event.allTouches allObjects]; - for (unsigned int i = 0; i < [tlist count]; i++) { - if ([touches containsObject:[tlist objectAtIndex:i]]) { - UITouch *touch = [tlist objectAtIndex:i]; - int tid = [self getTouchIDForTouch:touch]; - ERR_FAIL_COND(tid == -1); - CGPoint touchPoint = [touch locationInView:self]; - CGPoint prev_point = [touch previousLocationInView:self]; - CGFloat alt = [touch altitudeAngle]; - CGVector azim = [touch azimuthUnitVectorInView:self]; - DisplayServerIOS::get_singleton()->touch_drag(tid, prev_point.x * self.contentScaleFactor, prev_point.y * self.contentScaleFactor, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, [touch force] / [touch maximumPossibleForce], Vector2(azim.dx, azim.dy) * Math::cos(alt)); - } +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { + for (UITouch *touch in touches) { + int tid = [self getTouchIDForTouch:touch]; + ERR_FAIL_COND(tid == -1); + CGPoint touchPoint = [touch locationInView:self]; + CGPoint prev_point = [touch previousLocationInView:self]; + CGFloat alt = [touch altitudeAngle]; + CGVector azim = [touch azimuthUnitVectorInView:self]; + DisplayServerIOS::get_singleton()->touch_drag(tid, prev_point.x * self.contentScaleFactor, prev_point.y * self.contentScaleFactor, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, [touch force] / [touch maximumPossibleForce], Vector2(azim.dx, azim.dy) * Math::cos(alt)); } } -- (void)godotTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { - NSArray *tlist = [event.allTouches allObjects]; - for (unsigned int i = 0; i < [tlist count]; i++) { - if ([touches containsObject:[tlist objectAtIndex:i]]) { - UITouch *touch = [tlist objectAtIndex:i]; - int tid = [self getTouchIDForTouch:touch]; - ERR_FAIL_COND(tid == -1); - [self removeTouch:touch]; - CGPoint touchPoint = [touch locationInView:self]; - DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, false, false); - } +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { + for (UITouch *touch in touches) { + int tid = [self getTouchIDForTouch:touch]; + ERR_FAIL_COND(tid == -1); + [self removeTouch:touch]; + CGPoint touchPoint = [touch locationInView:self]; + DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, false, false); } } -- (void)godotTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { - NSArray *tlist = [event.allTouches allObjects]; - for (unsigned int i = 0; i < [tlist count]; i++) { - if ([touches containsObject:[tlist objectAtIndex:i]]) { - UITouch *touch = [tlist objectAtIndex:i]; - int tid = [self getTouchIDForTouch:touch]; - ERR_FAIL_COND(tid == -1); - DisplayServerIOS::get_singleton()->touches_canceled(tid); - } +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { + for (UITouch *touch in touches) { + int tid = [self getTouchIDForTouch:touch]; + ERR_FAIL_COND(tid == -1); + DisplayServerIOS::get_singleton()->touches_canceled(tid); } [self clearTouches]; } diff --git a/platform/ios/godot_view_gesture_recognizer.h b/platform/ios/godot_view_gesture_recognizer.h deleted file mode 100644 index 57bfc75568..0000000000 --- a/platform/ios/godot_view_gesture_recognizer.h +++ /dev/null @@ -1,46 +0,0 @@ -/**************************************************************************/ -/* godot_view_gesture_recognizer.h */ -/**************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/**************************************************************************/ -/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/**************************************************************************/ - -// GLViewGestureRecognizer allows iOS gestures to work correctly by -// emulating UIScrollView's UIScrollViewDelayedTouchesBeganGestureRecognizer. -// It catches all gestures incoming to UIView and delays them for 150ms -// (the same value used by UIScrollViewDelayedTouchesBeganGestureRecognizer) -// If touch cancellation or end message is fired it fires delayed -// begin touch immediately as well as last touch signal - -#import <UIKit/UIKit.h> - -@interface GodotViewGestureRecognizer : UIGestureRecognizer - -@property(nonatomic, readonly, assign) NSTimeInterval delayTimeInterval; - -- (instancetype)init; - -@end diff --git a/platform/ios/godot_view_gesture_recognizer.mm b/platform/ios/godot_view_gesture_recognizer.mm deleted file mode 100644 index 9b71228864..0000000000 --- a/platform/ios/godot_view_gesture_recognizer.mm +++ /dev/null @@ -1,186 +0,0 @@ -/**************************************************************************/ -/* godot_view_gesture_recognizer.mm */ -/**************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/**************************************************************************/ -/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/**************************************************************************/ - -#import "godot_view_gesture_recognizer.h" - -#import "godot_view.h" - -#include "core/config/project_settings.h" - -// Minimum distance for touches to move to fire -// a delay timer before scheduled time. -// Should be the low enough to not cause issues with dragging -// but big enough to allow click to work. -const CGFloat kGLGestureMovementDistance = 0.5; - -@interface GodotViewGestureRecognizer () - -@property(nonatomic, readwrite, assign) NSTimeInterval delayTimeInterval; - -@end - -@interface GodotViewGestureRecognizer () - -// Timer used to delay begin touch message. -// Should work as simple emulation of UIDelayedAction -@property(strong, nonatomic) NSTimer *delayTimer; - -// Delayed touch parameters -@property(strong, nonatomic) NSSet *delayedTouches; -@property(strong, nonatomic) UIEvent *delayedEvent; - -@end - -@implementation GodotViewGestureRecognizer - -- (GodotView *)godotView { - return (GodotView *)self.view; -} - -- (instancetype)init { - self = [super init]; - - self.cancelsTouchesInView = YES; - self.delaysTouchesBegan = YES; - self.delaysTouchesEnded = YES; - self.requiresExclusiveTouchType = NO; - - self.delayTimeInterval = GLOBAL_GET("input_devices/pointing/ios/touch_delay"); - - return self; -} - -- (void)dealloc { - if (self.delayTimer) { - [self.delayTimer invalidate]; - self.delayTimer = nil; - } - - if (self.delayedTouches) { - self.delayedTouches = nil; - } - - if (self.delayedEvent) { - self.delayedEvent = nil; - } -} - -- (void)delayTouches:(NSSet *)touches andEvent:(UIEvent *)event { - [self.delayTimer fire]; - - self.delayedTouches = touches; - self.delayedEvent = event; - - self.delayTimer = [NSTimer - scheduledTimerWithTimeInterval:self.delayTimeInterval - target:self - selector:@selector(fireDelayedTouches:) - userInfo:nil - repeats:NO]; -} - -- (void)fireDelayedTouches:(id)timer { - [self.delayTimer invalidate]; - self.delayTimer = nil; - - if (self.delayedTouches) { - [self.godotView godotTouchesBegan:self.delayedTouches withEvent:self.delayedEvent]; - } - - self.delayedTouches = nil; - self.delayedEvent = nil; -} - -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { - NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseBegan]; - [self delayTouches:cleared andEvent:event]; - - [super touchesBegan:touches withEvent:event]; -} - -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { - NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseMoved]; - - if (self.delayTimer) { - // We should check if movement was significant enough to fire an event - // for dragging to work correctly. - for (UITouch *touch in cleared) { - CGPoint from = [touch locationInView:self.godotView]; - CGPoint to = [touch previousLocationInView:self.godotView]; - CGFloat xDistance = from.x - to.x; - CGFloat yDistance = from.y - to.y; - - CGFloat distance = sqrt(xDistance * xDistance + yDistance * yDistance); - - // Early exit, since one of touches has moved enough to fire a drag event. - if (distance > kGLGestureMovementDistance) { - [self.delayTimer fire]; - [self.godotView godotTouchesMoved:cleared withEvent:event]; - return; - } - } - - return; - } - - [self.godotView godotTouchesMoved:cleared withEvent:event]; - - [super touchesMoved:touches withEvent:event]; -} - -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { - [self.delayTimer fire]; - - NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseEnded]; - [self.godotView godotTouchesEnded:cleared withEvent:event]; - - [super touchesEnded:touches withEvent:event]; -} - -- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { - [self.delayTimer fire]; - [self.godotView godotTouchesCancelled:touches withEvent:event]; - - [super touchesCancelled:touches withEvent:event]; -} - -- (NSSet *)copyClearedTouches:(NSSet *)touches phase:(UITouchPhase)phaseToSave { - NSMutableSet *cleared = [touches mutableCopy]; - - for (UITouch *touch in touches) { - if (touch.view != self.view || touch.phase != phaseToSave) { - [cleared removeObject:touch]; - } - } - - return cleared; -} - -@end diff --git a/platform/ios/joypad_ios.mm b/platform/ios/joypad_ios.mm index 057f439b81..9194b09ef6 100644 --- a/platform/ios/joypad_ios.mm +++ b/platform/ios/joypad_ios.mm @@ -305,6 +305,25 @@ void JoypadIOS::start_processing() { float value = gamepad.rightTrigger.value; Input::get_singleton()->joy_axis(joy_id, JoyAxis::TRIGGER_RIGHT, value); } + + if (@available(iOS 13, *)) { + // iOS uses 'buttonOptions' and 'buttonMenu' names for BACK and START joy buttons. + if (element == gamepad.buttonOptions) { + Input::get_singleton()->joy_button(joy_id, JoyButton::BACK, + gamepad.buttonOptions.isPressed); + } else if (element == gamepad.buttonMenu) { + Input::get_singleton()->joy_button(joy_id, JoyButton::START, + gamepad.buttonMenu.isPressed); + } + } + + if (@available(iOS 14, *)) { + // iOS uses 'buttonHome' for the GUIDE joy button. + if (element == gamepad.buttonHome) { + Input::get_singleton()->joy_button(joy_id, JoyButton::GUIDE, + gamepad.buttonHome.isPressed); + } + } }; } else if (controller.microGamepad != nil) { // micro gamepads were added in OS 9 and feature just 2 buttons and a d-pad diff --git a/platform/linuxbsd/SCsub b/platform/linuxbsd/SCsub index 3c5dc78c60..4dd74ff9d0 100644 --- a/platform/linuxbsd/SCsub +++ b/platform/linuxbsd/SCsub @@ -11,23 +11,30 @@ common_linuxbsd = [ "joypad_linux.cpp", "freedesktop_portal_desktop.cpp", "freedesktop_screensaver.cpp", - "xkbcommon-so_wrap.c", ] +if env["use_sowrap"]: + common_linuxbsd.append("xkbcommon-so_wrap.c") + if env["x11"]: common_linuxbsd += SConscript("x11/SCsub") if env["speechd"]: - common_linuxbsd.append(["speechd-so_wrap.c", "tts_linux.cpp"]) + common_linuxbsd.append("tts_linux.cpp") + if env["use_sowrap"]: + common_linuxbsd.append("speechd-so_wrap.c") if env["fontconfig"]: - common_linuxbsd.append("fontconfig-so_wrap.c") + if env["use_sowrap"]: + common_linuxbsd.append("fontconfig-so_wrap.c") if env["udev"]: - common_linuxbsd.append("libudev-so_wrap.c") + if env["use_sowrap"]: + common_linuxbsd.append("libudev-so_wrap.c") if env["dbus"]: - common_linuxbsd.append("dbus-so_wrap.c") + if env["use_sowrap"]: + common_linuxbsd.append("dbus-so_wrap.c") prog = env.add_program("#bin/godot", ["godot_linuxbsd.cpp"] + common_linuxbsd) diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py index bae5a98aee..3f713d2db3 100644 --- a/platform/linuxbsd/detect.py +++ b/platform/linuxbsd/detect.py @@ -43,6 +43,7 @@ def get_opts(): BoolVariable("use_lsan", "Use LLVM/GCC compiler leak sanitizer (LSAN)", False), BoolVariable("use_tsan", "Use LLVM/GCC compiler thread sanitizer (TSAN)", False), BoolVariable("use_msan", "Use LLVM compiler memory sanitizer (MSAN)", False), + BoolVariable("use_sowrap", "Dynamically load system libraries", True), BoolVariable("alsa", "Use ALSA", True), BoolVariable("pulseaudio", "Use PulseAudio", True), BoolVariable("dbus", "Use D-Bus to handle screensaver and portal desktop settings", True), @@ -184,25 +185,30 @@ def configure(env: "Environment"): ## Dependencies + if env["use_sowrap"]: + env.Append(CPPDEFINES=["SOWRAP_ENABLED"]) + if env["touch"]: env.Append(CPPDEFINES=["TOUCH_ENABLED"]) # FIXME: Check for existence of the libs before parsing their flags with pkg-config # freetype depends on libpng and zlib, so bundling one of them while keeping others - # as shared libraries leads to weird issues - if ( - env["builtin_freetype"] - or env["builtin_libpng"] - or env["builtin_zlib"] - or env["builtin_graphite"] - or env["builtin_harfbuzz"] - ): - env["builtin_freetype"] = True - env["builtin_libpng"] = True - env["builtin_zlib"] = True - env["builtin_graphite"] = True - env["builtin_harfbuzz"] = True + # as shared libraries leads to weird issues. And graphite and harfbuzz need freetype. + ft_linked_deps = [ + env["builtin_freetype"], + env["builtin_libpng"], + env["builtin_zlib"], + env["builtin_graphite"], + env["builtin_harfbuzz"], + ] + if (not all(ft_linked_deps)) and any(ft_linked_deps): # All or nothing. + print( + "These libraries should be either all builtin, or all system provided:\n" + "freetype, libpng, zlib, graphite, harfbuzz.\n" + "Please specify `builtin_<name>=no` for all of them, or none." + ) + sys.exit() if not env["builtin_freetype"]: env.ParseConfig("pkg-config freetype2 --cflags --libs") @@ -210,8 +216,8 @@ def configure(env: "Environment"): if not env["builtin_graphite"]: env.ParseConfig("pkg-config graphite2 --cflags --libs") - if not env["builtin_icu"]: - env.ParseConfig("pkg-config icu-uc --cflags --libs") + if not env["builtin_icu4c"]: + env.ParseConfig("pkg-config icu-i18n icu-uc --cflags --libs") if not env["builtin_harfbuzz"]: env.ParseConfig("pkg-config harfbuzz harfbuzz-icu --cflags --libs") @@ -266,31 +272,93 @@ def configure(env: "Environment"): if not env["builtin_pcre2"]: env.ParseConfig("pkg-config libpcre2-32 --cflags --libs") + if not env["builtin_recastnavigation"]: + # No pkgconfig file so far, hardcode default paths. + env.Prepend(CPPPATH=["/usr/include/recastnavigation"]) + env.Append(LIBS=["Recast"]) + if not env["builtin_embree"]: # No pkgconfig file so far, hardcode expected lib name. env.Append(LIBS=["embree3"]) ## Flags - if env["fontconfig"]: - env.Append(CPPDEFINES=["FONTCONFIG_ENABLED"]) + if not env["use_sowrap"]: + if os.system("pkg-config --exists fontconfig") == 0: # 0 means found + env.ParseConfig("pkg-config fontconfig --cflags --libs") + env.Append(CPPDEFINES=["FONTCONFIG_ENABLED"]) + else: + print("Warning: fontconfig development libraries not found. Disabling the system fonts support.") + env["fontconfig"] = False + else: + env.Append(CPPDEFINES=["FONTCONFIG_ENABLED"]) if env["alsa"]: - env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"]) + if not env["use_sowrap"]: + if os.system("pkg-config --exists alsa") == 0: # 0 means found + env.ParseConfig("pkg-config alsa --cflags --libs") + env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"]) + else: + print("Warning: ALSA development libraries not found. Disabling the ALSA audio driver.") + env["alsa"] = False + else: + env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"]) if env["pulseaudio"]: + if not env["use_sowrap"]: + if os.system("pkg-config --exists libpulse") == 0: # 0 means found + env.ParseConfig("pkg-config libpulse --cflags --libs") + env.Append(CPPDEFINES=["PULSEAUDIO_ENABLED", "_REENTRANT"]) + else: + print("Warning: PulseAudio development libraries not found. Disabling the PulseAudio audio driver.") + env["pulseaudio"] = False env.Append(CPPDEFINES=["PULSEAUDIO_ENABLED", "_REENTRANT"]) if env["dbus"]: - env.Append(CPPDEFINES=["DBUS_ENABLED"]) + if not env["use_sowrap"]: + if os.system("pkg-config --exists dbus-1") == 0: # 0 means found + env.ParseConfig("pkg-config dbus-1 --cflags --libs") + env.Append(CPPDEFINES=["DBUS_ENABLED"]) + else: + print("Warning: D-Bus development libraries not found. Disabling screensaver prevention.") + env["dbus"] = False + else: + env.Append(CPPDEFINES=["DBUS_ENABLED"]) if env["speechd"]: - env.Append(CPPDEFINES=["SPEECHD_ENABLED"]) + if not env["use_sowrap"]: + if os.system("pkg-config --exists speech-dispatcher") == 0: # 0 means found + env.ParseConfig("pkg-config speech-dispatcher --cflags --libs") + env.Append(CPPDEFINES=["SPEECHD_ENABLED"]) + else: + print("Warning: speech-dispatcher development libraries not found. Disabling text to speech support.") + env["speechd"] = False + else: + env.Append(CPPDEFINES=["SPEECHD_ENABLED"]) + + if not env["use_sowrap"]: + if os.system("pkg-config --exists xkbcommon") == 0: # 0 means found + env.ParseConfig("pkg-config xkbcommon --cflags --libs") + env.Append(CPPDEFINES=["XKB_ENABLED"]) + else: + print( + "Warning: libxkbcommon development libraries not found. Disabling dead key composition and key label support." + ) + else: + env.Append(CPPDEFINES=["XKB_ENABLED"]) if platform.system() == "Linux": env.Append(CPPDEFINES=["JOYDEV_ENABLED"]) if env["udev"]: - env.Append(CPPDEFINES=["UDEV_ENABLED"]) + if not env["use_sowrap"]: + if os.system("pkg-config --exists libudev") == 0: # 0 means found + env.ParseConfig("pkg-config libudev --cflags --libs") + env.Append(CPPDEFINES=["UDEV_ENABLED"]) + else: + print("Warning: libudev development libraries not found. Disabling controller hotplugging support.") + env["udev"] = False + else: + env.Append(CPPDEFINES=["UDEV_ENABLED"]) else: env["udev"] = False # Linux specific @@ -298,7 +366,9 @@ def configure(env: "Environment"): if not env["builtin_zlib"]: env.ParseConfig("pkg-config zlib --cflags --libs") - env.Prepend(CPPPATH=["#platform/linuxbsd", "#thirdparty/linuxbsd_headers"]) + env.Prepend(CPPPATH=["#platform/linuxbsd"]) + if env["use_sowrap"]: + env.Prepend(CPPPATH=["#thirdparty/linuxbsd_headers"]) env.Append( CPPDEFINES=[ @@ -309,6 +379,35 @@ def configure(env: "Environment"): ) if env["x11"]: + if not env["use_sowrap"]: + if os.system("pkg-config --exists x11"): + print("Error: X11 libraries not found. Aborting.") + sys.exit(255) + env.ParseConfig("pkg-config x11 --cflags --libs") + if os.system("pkg-config --exists xcursor"): + print("Error: Xcursor library not found. Aborting.") + sys.exit(255) + env.ParseConfig("pkg-config xcursor --cflags --libs") + if os.system("pkg-config --exists xinerama"): + print("Error: Xinerama library not found. Aborting.") + sys.exit(255) + env.ParseConfig("pkg-config xinerama --cflags --libs") + if os.system("pkg-config --exists xext"): + print("Error: Xext library not found. Aborting.") + sys.exit(255) + env.ParseConfig("pkg-config xext --cflags --libs") + if os.system("pkg-config --exists xrandr"): + print("Error: XrandR library not found. Aborting.") + sys.exit(255) + env.ParseConfig("pkg-config xrandr --cflags --libs") + if os.system("pkg-config --exists xrender"): + print("Error: XRender library not found. Aborting.") + sys.exit(255) + env.ParseConfig("pkg-config xrender --cflags --libs") + if os.system("pkg-config --exists xi"): + print("Error: Xi library not found. Aborting.") + sys.exit(255) + env.ParseConfig("pkg-config xi --cflags --libs") env.Append(CPPDEFINES=["X11_ENABLED"]) if env["vulkan"]: diff --git a/platform/linuxbsd/freedesktop_portal_desktop.cpp b/platform/linuxbsd/freedesktop_portal_desktop.cpp index 72d4e3772f..ec1fcf6698 100644 --- a/platform/linuxbsd/freedesktop_portal_desktop.cpp +++ b/platform/linuxbsd/freedesktop_portal_desktop.cpp @@ -36,7 +36,11 @@ #include "core/os/os.h" #include "core/string/ustring.h" +#ifdef SOWRAP_ENABLED #include "dbus-so_wrap.h" +#else +#include <dbus/dbus.h> +#endif #include "core/variant/variant.h" @@ -124,12 +128,16 @@ uint32_t FreeDesktopPortalDesktop::get_appearance_color_scheme() { } FreeDesktopPortalDesktop::FreeDesktopPortalDesktop() { +#ifdef SOWRAP_ENABLED #ifdef DEBUG_ENABLED int dylibloader_verbose = 1; #else int dylibloader_verbose = 0; #endif unsupported = (initialize_dbus(dylibloader_verbose) != 0); +#else + unsupported = false; +#endif } #endif // DBUS_ENABLED diff --git a/platform/linuxbsd/freedesktop_screensaver.cpp b/platform/linuxbsd/freedesktop_screensaver.cpp index 159fd0df61..d07e781a5f 100644 --- a/platform/linuxbsd/freedesktop_screensaver.cpp +++ b/platform/linuxbsd/freedesktop_screensaver.cpp @@ -34,7 +34,11 @@ #include "core/config/project_settings.h" +#ifdef SOWRAP_ENABLED #include "dbus-so_wrap.h" +#else +#include <dbus/dbus.h> +#endif #define BUS_OBJECT_NAME "org.freedesktop.ScreenSaver" #define BUS_OBJECT_PATH "/org/freedesktop/ScreenSaver" @@ -127,12 +131,16 @@ void FreeDesktopScreenSaver::uninhibit() { } FreeDesktopScreenSaver::FreeDesktopScreenSaver() { +#ifdef SOWRAP_ENABLED #ifdef DEBUG_ENABLED int dylibloader_verbose = 1; #else int dylibloader_verbose = 0; #endif unsupported = (initialize_dbus(dylibloader_verbose) != 0); +#else + unsupported = false; +#endif } #endif // DBUS_ENABLED diff --git a/platform/linuxbsd/joypad_linux.cpp b/platform/linuxbsd/joypad_linux.cpp index b77f989677..0256af0a59 100644 --- a/platform/linuxbsd/joypad_linux.cpp +++ b/platform/linuxbsd/joypad_linux.cpp @@ -39,7 +39,11 @@ #include <unistd.h> #ifdef UDEV_ENABLED +#ifdef SOWRAP_ENABLED #include "libudev-so_wrap.h" +#else +#include <libudev.h> +#endif #endif #define LONG_BITS (sizeof(long) * 8) @@ -70,6 +74,7 @@ void JoypadLinux::Joypad::reset() { JoypadLinux::JoypadLinux(Input *in) { #ifdef UDEV_ENABLED +#ifdef SOWRAP_ENABLED #ifdef DEBUG_ENABLED int dylibloader_verbose = 1; #else @@ -81,6 +86,7 @@ JoypadLinux::JoypadLinux(Input *in) { } else { print_verbose("JoypadLinux: udev enabled, but couldn't be loaded. Falling back to /dev/input to detect joypads."); } +#endif #else print_verbose("JoypadLinux: udev disabled, parsing /dev/input to detect joypads."); #endif diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp index 41d1f1d050..54bb34ef73 100644 --- a/platform/linuxbsd/os_linuxbsd.cpp +++ b/platform/linuxbsd/os_linuxbsd.cpp @@ -1083,12 +1083,16 @@ OS_LinuxBSD::OS_LinuxBSD() { #endif #ifdef FONTCONFIG_ENABLED +#ifdef SOWRAP_ENABLED #ifdef DEBUG_ENABLED int dylibloader_verbose = 1; #else int dylibloader_verbose = 0; #endif font_config_initialized = (initialize_fontconfig(dylibloader_verbose) == 0); +#else + font_config_initialized = true; +#endif if (font_config_initialized) { config = FcInitLoadConfigAndFonts(); if (!config) { diff --git a/platform/linuxbsd/os_linuxbsd.h b/platform/linuxbsd/os_linuxbsd.h index 045d3d95ba..9423514944 100644 --- a/platform/linuxbsd/os_linuxbsd.h +++ b/platform/linuxbsd/os_linuxbsd.h @@ -41,7 +41,11 @@ #include "servers/audio_server.h" #ifdef FONTCONFIG_ENABLED +#ifdef SOWRAP_ENABLED #include "fontconfig-so_wrap.h" +#else +#include <fontconfig/fontconfig.h> +#endif #endif class OS_LinuxBSD : public OS_Unix { diff --git a/platform/linuxbsd/tts_linux.cpp b/platform/linuxbsd/tts_linux.cpp index 4662aaf02d..04d7c5444f 100644 --- a/platform/linuxbsd/tts_linux.cpp +++ b/platform/linuxbsd/tts_linux.cpp @@ -39,12 +39,18 @@ void TTS_Linux::speech_init_thread_func(void *p_userdata) { TTS_Linux *tts = (TTS_Linux *)p_userdata; if (tts) { MutexLock thread_safe_method(tts->_thread_safe_); +#ifdef SOWRAP_ENABLED #ifdef DEBUG_ENABLED int dylibloader_verbose = 1; #else int dylibloader_verbose = 0; #endif - if (initialize_speechd(dylibloader_verbose) == 0) { + if (initialize_speechd(dylibloader_verbose) != 0) { + print_verbose("Text-to-Speech: Cannot load Speech Dispatcher library!"); + } else { +#else + { +#endif CharString class_str; String config_name = GLOBAL_GET("application/config/name"); if (config_name.length() == 0) { @@ -64,8 +70,6 @@ void TTS_Linux::speech_init_thread_func(void *p_userdata) { } else { print_verbose("Text-to-Speech: Cannot initialize Speech Dispatcher synthesizer!"); } - } else { - print_verbose("Text-to-Speech: Cannot load Speech Dispatcher library!"); } } } diff --git a/platform/linuxbsd/tts_linux.h b/platform/linuxbsd/tts_linux.h index 425654d975..3fe7b659d0 100644 --- a/platform/linuxbsd/tts_linux.h +++ b/platform/linuxbsd/tts_linux.h @@ -39,7 +39,11 @@ #include "core/variant/array.h" #include "servers/display_server.h" +#ifdef SOWRAP_ENABLED #include "speechd-so_wrap.h" +#else +#include <libspeechd.h> +#endif class TTS_Linux { _THREAD_SAFE_CLASS_ diff --git a/platform/linuxbsd/x11/SCsub b/platform/linuxbsd/x11/SCsub index 8b2e2aabe4..a4890391ce 100644 --- a/platform/linuxbsd/x11/SCsub +++ b/platform/linuxbsd/x11/SCsub @@ -5,15 +5,21 @@ Import("env") source_files = [ "display_server_x11.cpp", "key_mapping_x11.cpp", - "dynwrappers/xlib-so_wrap.c", - "dynwrappers/xcursor-so_wrap.c", - "dynwrappers/xinerama-so_wrap.c", - "dynwrappers/xinput2-so_wrap.c", - "dynwrappers/xrandr-so_wrap.c", - "dynwrappers/xrender-so_wrap.c", - "dynwrappers/xext-so_wrap.c", ] +if env["use_sowrap"]: + source_files.append( + [ + "dynwrappers/xlib-so_wrap.c", + "dynwrappers/xcursor-so_wrap.c", + "dynwrappers/xinerama-so_wrap.c", + "dynwrappers/xinput2-so_wrap.c", + "dynwrappers/xrandr-so_wrap.c", + "dynwrappers/xrender-so_wrap.c", + "dynwrappers/xext-so_wrap.c", + ] + ) + if env["vulkan"]: source_files.append("vulkan_context_x11.cpp") diff --git a/platform/linuxbsd/x11/detect_prime_x11.cpp b/platform/linuxbsd/x11/detect_prime_x11.cpp index 8d586599e6..3d07be1c76 100644 --- a/platform/linuxbsd/x11/detect_prime_x11.cpp +++ b/platform/linuxbsd/x11/detect_prime_x11.cpp @@ -41,7 +41,13 @@ #include "thirdparty/glad/glad/gl.h" #include "thirdparty/glad/glad/glx.h" +#ifdef SOWRAP_ENABLED #include "dynwrappers/xlib-so_wrap.h" +#else +#include <X11/XKBlib.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#endif #include <cstring> diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index 525c62fbf2..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 */ @@ -4936,6 +4942,11 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V win_rect.position = wpos; } + // Position and size hints are set from these values before they are updated to the actual + // window size, so we need to initialize them here. + wd.position = win_rect.position; + wd.size = win_rect.size; + { wd.x11_window = XCreateWindow(x11_display, RootWindow(x11_display, visualInfo.screen), win_rect.position.x, win_rect.position.y, win_rect.size.width > 0 ? win_rect.size.width : 1, win_rect.size.height > 0 ? win_rect.size.height : 1, 0, visualInfo.depth, InputOutput, visualInfo.visual, valuemask, &windowAttributes); @@ -4943,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) { @@ -5212,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 @@ -5226,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."); @@ -5253,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) { @@ -5270,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); @@ -5712,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); @@ -5730,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/platform/web/display_server_web.cpp b/platform/web/display_server_web.cpp index d71fd60543..e89a79834b 100644 --- a/platform/web/display_server_web.cpp +++ b/platform/web/display_server_web.cpp @@ -108,11 +108,19 @@ void DisplayServerWeb::request_quit_callback() { // Keys -void DisplayServerWeb::dom2godot_mod(Ref<InputEventWithModifiers> ev, int p_mod) { - ev->set_shift_pressed(p_mod & 1); - ev->set_alt_pressed(p_mod & 2); - ev->set_ctrl_pressed(p_mod & 4); - ev->set_meta_pressed(p_mod & 8); +void DisplayServerWeb::dom2godot_mod(Ref<InputEventWithModifiers> ev, int p_mod, Key p_keycode) { + if (p_keycode != Key::SHIFT) { + ev->set_shift_pressed(p_mod & 1); + } + if (p_keycode != Key::ALT) { + ev->set_alt_pressed(p_mod & 2); + } + if (p_keycode != Key::CTRL) { + ev->set_ctrl_pressed(p_mod & 4); + } + if (p_keycode != Key::META) { + ev->set_meta_pressed(p_mod & 8); + } } void DisplayServerWeb::key_callback(int p_pressed, int p_repeat, int p_modifiers) { @@ -138,7 +146,7 @@ void DisplayServerWeb::key_callback(int p_pressed, int p_repeat, int p_modifiers ev->set_key_label(fix_key_label(c, keycode)); ev->set_unicode(fix_unicode(c)); ev->set_pressed(p_pressed); - dom2godot_mod(ev, p_modifiers); + dom2godot_mod(ev, p_modifiers, fix_keycode(c, keycode)); Input::get_singleton()->parse_input_event(ev); @@ -157,7 +165,7 @@ int DisplayServerWeb::mouse_button_callback(int p_pressed, int p_button, double ev->set_position(pos); ev->set_global_position(pos); ev->set_pressed(p_pressed); - dom2godot_mod(ev, p_modifiers); + dom2godot_mod(ev, p_modifiers, Key::NONE); switch (p_button) { case DOM_BUTTON_LEFT: @@ -235,7 +243,7 @@ void DisplayServerWeb::mouse_move_callback(double p_x, double p_y, double p_rel_ Point2 pos(p_x, p_y); Ref<InputEventMouseMotion> ev; ev.instantiate(); - dom2godot_mod(ev, p_modifiers); + dom2godot_mod(ev, p_modifiers, Key::NONE); ev->set_button_mask(input_mask); ev->set_position(pos); diff --git a/platform/web/display_server_web.h b/platform/web/display_server_web.h index 6d76af4e56..2e50a6bbc8 100644 --- a/platform/web/display_server_web.h +++ b/platform/web/display_server_web.h @@ -81,7 +81,7 @@ private: bool swap_cancel_ok = false; // utilities - static void dom2godot_mod(Ref<InputEventWithModifiers> ev, int p_mod); + static void dom2godot_mod(Ref<InputEventWithModifiers> ev, int p_mod, Key p_keycode); static const char *godot2dom_cursor(DisplayServer::CursorShape p_shape); // events diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index fe7d91dc18..1cfc9c9f47 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -3668,10 +3668,18 @@ void DisplayServerWindows::_process_key_events() { } k->set_window_id(ke.window_id); - k->set_shift_pressed(ke.shift); - k->set_alt_pressed(ke.alt); - k->set_ctrl_pressed(ke.control); - k->set_meta_pressed(ke.meta); + if (keycode != Key::SHIFT) { + k->set_shift_pressed(ke.shift); + } + if (keycode != Key::ALT) { + k->set_alt_pressed(ke.alt); + } + if (keycode != Key::CTRL) { + k->set_ctrl_pressed(ke.control); + } + if (keycode != Key::META) { + k->set_meta_pressed(ke.meta); + } k->set_pressed(true); k->set_keycode(keycode); k->set_physical_keycode(physical_keycode); @@ -3693,11 +3701,6 @@ void DisplayServerWindows::_process_key_events() { k.instantiate(); k->set_window_id(ke.window_id); - k->set_shift_pressed(ke.shift); - k->set_alt_pressed(ke.alt); - k->set_ctrl_pressed(ke.control); - k->set_meta_pressed(ke.meta); - k->set_pressed(ke.uMsg == WM_KEYDOWN); Key keycode = KeyMappingWindows::get_keysym(ke.wParam); @@ -3719,6 +3722,18 @@ void DisplayServerWindows::_process_key_events() { } } + if (keycode != Key::SHIFT) { + k->set_shift_pressed(ke.shift); + } + if (keycode != Key::ALT) { + k->set_alt_pressed(ke.alt); + } + if (keycode != Key::CTRL) { + k->set_ctrl_pressed(ke.control); + } + if (keycode != Key::META) { + k->set_meta_pressed(ke.meta); + } k->set_keycode(keycode); k->set_physical_keycode(physical_keycode); k->set_key_label(key_label); diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp index 52a1213a49..bfe2f6252e 100644 --- a/scene/2d/navigation_agent_2d.cpp +++ b/scene/2d/navigation_agent_2d.cpp @@ -31,6 +31,7 @@ #include "navigation_agent_2d.h" #include "core/math/geometry_2d.h" +#include "scene/2d/navigation_link_2d.h" #include "scene/resources/world_2d.h" #include "servers/navigation_server_2d.h" @@ -94,19 +95,19 @@ void NavigationAgent2D::_bind_methods() { ADD_GROUP("Pathfinding", ""); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "target_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_target_position", "get_target_position"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_desired_distance", PROPERTY_HINT_RANGE, "0.1,1000,0.01,suffix:px"), "set_path_desired_distance", "get_path_desired_distance"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_desired_distance", PROPERTY_HINT_RANGE, "0.1,1000,0.01,suffix:px"), "set_target_desired_distance", "get_target_desired_distance"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "10,1000,1,suffix:px"), "set_path_max_distance", "get_path_max_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_desired_distance", PROPERTY_HINT_RANGE, "0.1,1000,0.01,or_greater,suffix:px"), "set_path_desired_distance", "get_path_desired_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_desired_distance", PROPERTY_HINT_RANGE, "0.1,1000,0.01,or_greater,suffix:px"), "set_target_desired_distance", "get_target_desired_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "10,1000,1,or_greater,suffix:px"), "set_path_max_distance", "get_path_max_distance"); ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigation_layers", "get_navigation_layers"); ADD_PROPERTY(PropertyInfo(Variant::INT, "path_metadata_flags", PROPERTY_HINT_FLAGS, "Include Types,Include RIDs,Include Owners"), "set_path_metadata_flags", "get_path_metadata_flags"); ADD_GROUP("Avoidance", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.1,500,0.01,suffix:px"), "set_radius", "get_radius"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "neighbor_distance", PROPERTY_HINT_RANGE, "0.1,100000,0.01,suffix:px"), "set_neighbor_distance", "get_neighbor_distance"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "max_neighbors", PROPERTY_HINT_RANGE, "1,10000,1"), "set_max_neighbors", "get_max_neighbors"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon", PROPERTY_HINT_RANGE, "0.1,10,0.01,suffix:s"), "set_time_horizon", "get_time_horizon"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,10000,0.01,suffix:px/s"), "set_max_speed", "get_max_speed"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.1,500,0.01,or_greater,suffix:px"), "set_radius", "get_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "neighbor_distance", PROPERTY_HINT_RANGE, "0.1,100000,0.01,or_greater,suffix:px"), "set_neighbor_distance", "get_neighbor_distance"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_neighbors", PROPERTY_HINT_RANGE, "1,10000,or_greater,1"), "set_max_neighbors", "get_max_neighbors"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon", PROPERTY_HINT_RANGE, "0.1,10,0.01,or_greater,suffix:s"), "set_time_horizon", "get_time_horizon"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,10000,0.01,or_greater,suffix:px/s"), "set_max_speed", "get_max_speed"); ClassDB::bind_method(D_METHOD("set_debug_enabled", "enabled"), &NavigationAgent2D::set_debug_enabled); ClassDB::bind_method(D_METHOD("get_debug_enabled"), &NavigationAgent2D::get_debug_enabled); @@ -623,6 +624,21 @@ void NavigationAgent2D::update_navigation() { } details[SNAME("owner")] = owner; + + if (waypoint_type == NavigationPathQueryResult2D::PATH_SEGMENT_TYPE_LINK) { + const NavigationLink2D *navlink = Object::cast_to<NavigationLink2D>(owner); + if (navlink) { + Vector2 link_global_start_position = navlink->get_global_start_position(); + Vector2 link_global_end_position = navlink->get_global_end_position(); + if (waypoint.distance_to(link_global_start_position) < waypoint.distance_to(link_global_end_position)) { + details[SNAME("link_entry_position")] = link_global_start_position; + details[SNAME("link_exit_position")] = link_global_end_position; + } else { + details[SNAME("link_entry_position")] = link_global_end_position; + details[SNAME("link_exit_position")] = link_global_start_position; + } + } + } } // Emit a signal for the waypoint diff --git a/scene/2d/navigation_link_2d.cpp b/scene/2d/navigation_link_2d.cpp index 26dca40176..8adb7c6305 100644 --- a/scene/2d/navigation_link_2d.cpp +++ b/scene/2d/navigation_link_2d.cpp @@ -54,6 +54,12 @@ void NavigationLink2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_end_position", "position"), &NavigationLink2D::set_end_position); ClassDB::bind_method(D_METHOD("get_end_position"), &NavigationLink2D::get_end_position); + ClassDB::bind_method(D_METHOD("set_global_start_position", "position"), &NavigationLink2D::set_global_start_position); + ClassDB::bind_method(D_METHOD("get_global_start_position"), &NavigationLink2D::get_global_start_position); + + ClassDB::bind_method(D_METHOD("set_global_end_position", "position"), &NavigationLink2D::set_global_end_position); + ClassDB::bind_method(D_METHOD("get_global_end_position"), &NavigationLink2D::get_global_end_position); + ClassDB::bind_method(D_METHOD("set_enter_cost", "enter_cost"), &NavigationLink2D::set_enter_cost); ClassDB::bind_method(D_METHOD("get_enter_cost"), &NavigationLink2D::get_enter_cost); @@ -271,6 +277,38 @@ void NavigationLink2D::set_end_position(Vector2 p_position) { #endif // DEBUG_ENABLED } +void NavigationLink2D::set_global_start_position(Vector2 p_position) { + if (is_inside_tree()) { + set_start_position(to_local(p_position)); + } else { + set_start_position(p_position); + } +} + +Vector2 NavigationLink2D::get_global_start_position() const { + if (is_inside_tree()) { + return to_global(start_position); + } else { + return start_position; + } +} + +void NavigationLink2D::set_global_end_position(Vector2 p_position) { + if (is_inside_tree()) { + set_end_position(to_local(p_position)); + } else { + set_end_position(p_position); + } +} + +Vector2 NavigationLink2D::get_global_end_position() const { + if (is_inside_tree()) { + return to_global(end_position); + } else { + return end_position; + } +} + void NavigationLink2D::set_enter_cost(real_t p_enter_cost) { ERR_FAIL_COND_MSG(p_enter_cost < 0.0, "The enter_cost must be positive."); if (Math::is_equal_approx(enter_cost, p_enter_cost)) { diff --git a/scene/2d/navigation_link_2d.h b/scene/2d/navigation_link_2d.h index 5bf2a72358..8a24d611c9 100644 --- a/scene/2d/navigation_link_2d.h +++ b/scene/2d/navigation_link_2d.h @@ -78,6 +78,12 @@ public: void set_end_position(Vector2 p_position); Vector2 get_end_position() const { return end_position; } + void set_global_start_position(Vector2 p_position); + Vector2 get_global_start_position() const; + + void set_global_end_position(Vector2 p_position); + Vector2 get_global_end_position() const; + void set_enter_cost(real_t p_enter_cost); real_t get_enter_cost() const { return enter_cost; } diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp index 16f357194e..396e4b72af 100644 --- a/scene/3d/navigation_agent_3d.cpp +++ b/scene/3d/navigation_agent_3d.cpp @@ -30,6 +30,7 @@ #include "navigation_agent_3d.h" +#include "scene/3d/navigation_link_3d.h" #include "servers/navigation_server_3d.h" void NavigationAgent3D::_bind_methods() { @@ -98,20 +99,20 @@ void NavigationAgent3D::_bind_methods() { ADD_GROUP("Pathfinding", ""); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "target_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_target_position", "get_target_position"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01,suffix:m"), "set_path_desired_distance", "get_path_desired_distance"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01,suffix:m"), "set_target_desired_distance", "get_target_desired_distance"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_height_offset", PROPERTY_HINT_RANGE, "-100.0,100,0.01,suffix:m"), "set_agent_height_offset", "get_agent_height_offset"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "0.01,100,0.1,suffix:m"), "set_path_max_distance", "get_path_max_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01,or_greater,suffix:m"), "set_path_desired_distance", "get_path_desired_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01,or_greater,suffix:m"), "set_target_desired_distance", "get_target_desired_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_height_offset", PROPERTY_HINT_RANGE, "-100.0,100,0.01,or_greater,suffix:m"), "set_agent_height_offset", "get_agent_height_offset"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "0.01,100,0.1,or_greater,suffix:m"), "set_path_max_distance", "get_path_max_distance"); ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers"); ADD_PROPERTY(PropertyInfo(Variant::INT, "path_metadata_flags", PROPERTY_HINT_FLAGS, "Include Types,Include RIDs,Include Owners"), "set_path_metadata_flags", "get_path_metadata_flags"); ADD_GROUP("Avoidance", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.1,100,0.01,suffix:m"), "set_radius", "get_radius"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "neighbor_distance", PROPERTY_HINT_RANGE, "0.1,10000,0.01,suffix:m"), "set_neighbor_distance", "get_neighbor_distance"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "max_neighbors", PROPERTY_HINT_RANGE, "1,10000,1"), "set_max_neighbors", "get_max_neighbors"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon", PROPERTY_HINT_RANGE, "0.01,100,0.01,suffix:s"), "set_time_horizon", "get_time_horizon"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,10000,0.01,suffix:m/s"), "set_max_speed", "get_max_speed"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.1,100,0.01,or_greater,suffix:m"), "set_radius", "get_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "neighbor_distance", PROPERTY_HINT_RANGE, "0.1,10000,0.01,or_greater,suffix:m"), "set_neighbor_distance", "get_neighbor_distance"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_neighbors", PROPERTY_HINT_RANGE, "1,10000,1,or_greater"), "set_max_neighbors", "get_max_neighbors"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon", PROPERTY_HINT_RANGE, "0.01,10,0.01,or_greater,suffix:s"), "set_time_horizon", "get_time_horizon"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,1000,0.01,or_greater,suffix:m/s"), "set_max_speed", "get_max_speed"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_y"), "set_ignore_y", "get_ignore_y"); ADD_SIGNAL(MethodInfo("path_changed")); @@ -649,6 +650,21 @@ void NavigationAgent3D::update_navigation() { } details[SNAME("owner")] = owner; + + if (waypoint_type == NavigationPathQueryResult3D::PATH_SEGMENT_TYPE_LINK) { + const NavigationLink3D *navlink = Object::cast_to<NavigationLink3D>(owner); + if (navlink) { + Vector3 link_global_start_position = navlink->get_global_start_position(); + Vector3 link_global_end_position = navlink->get_global_end_position(); + if (waypoint.distance_to(link_global_start_position) < waypoint.distance_to(link_global_end_position)) { + details[SNAME("link_entry_position")] = link_global_start_position; + details[SNAME("link_exit_position")] = link_global_end_position; + } else { + details[SNAME("link_entry_position")] = link_global_end_position; + details[SNAME("link_exit_position")] = link_global_start_position; + } + } + } } // Emit a signal for the waypoint diff --git a/scene/3d/navigation_agent_3d.h b/scene/3d/navigation_agent_3d.h index 072ca1d3e8..cde826ed5c 100644 --- a/scene/3d/navigation_agent_3d.h +++ b/scene/3d/navigation_agent_3d.h @@ -52,14 +52,14 @@ class NavigationAgent3D : public Node { real_t path_desired_distance = 1.0; real_t target_desired_distance = 1.0; - real_t radius = 1.0; + real_t radius = 0.5; real_t navigation_height_offset = 0.0; bool ignore_y = true; real_t neighbor_distance = 50.0; int max_neighbors = 10; - real_t time_horizon = 5.0; + real_t time_horizon = 1.0; real_t max_speed = 10.0; - real_t path_max_distance = 3.0; + real_t path_max_distance = 5.0; Vector3 target_position; bool target_position_submitted = false; diff --git a/scene/3d/navigation_link_3d.cpp b/scene/3d/navigation_link_3d.cpp index f47fcfaf51..9c4b8e7905 100644 --- a/scene/3d/navigation_link_3d.cpp +++ b/scene/3d/navigation_link_3d.cpp @@ -163,6 +163,12 @@ void NavigationLink3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_end_position", "position"), &NavigationLink3D::set_end_position); ClassDB::bind_method(D_METHOD("get_end_position"), &NavigationLink3D::get_end_position); + ClassDB::bind_method(D_METHOD("set_global_start_position", "position"), &NavigationLink3D::set_global_start_position); + ClassDB::bind_method(D_METHOD("get_global_start_position"), &NavigationLink3D::get_global_start_position); + + ClassDB::bind_method(D_METHOD("set_global_end_position", "position"), &NavigationLink3D::set_global_end_position); + ClassDB::bind_method(D_METHOD("get_global_end_position"), &NavigationLink3D::get_global_end_position); + ClassDB::bind_method(D_METHOD("set_enter_cost", "enter_cost"), &NavigationLink3D::set_enter_cost); ClassDB::bind_method(D_METHOD("get_enter_cost"), &NavigationLink3D::get_enter_cost); @@ -386,6 +392,38 @@ void NavigationLink3D::set_end_position(Vector3 p_position) { update_configuration_warnings(); } +void NavigationLink3D::set_global_start_position(Vector3 p_position) { + if (is_inside_tree()) { + set_start_position(to_local(p_position)); + } else { + set_start_position(p_position); + } +} + +Vector3 NavigationLink3D::get_global_start_position() const { + if (is_inside_tree()) { + return to_global(start_position); + } else { + return start_position; + } +} + +void NavigationLink3D::set_global_end_position(Vector3 p_position) { + if (is_inside_tree()) { + set_end_position(to_local(p_position)); + } else { + set_end_position(p_position); + } +} + +Vector3 NavigationLink3D::get_global_end_position() const { + if (is_inside_tree()) { + return to_global(end_position); + } else { + return end_position; + } +} + void NavigationLink3D::set_enter_cost(real_t p_enter_cost) { ERR_FAIL_COND_MSG(p_enter_cost < 0.0, "The enter_cost must be positive."); if (Math::is_equal_approx(enter_cost, p_enter_cost)) { diff --git a/scene/3d/navigation_link_3d.h b/scene/3d/navigation_link_3d.h index 5c9ec36189..991f45c85d 100644 --- a/scene/3d/navigation_link_3d.h +++ b/scene/3d/navigation_link_3d.h @@ -83,6 +83,12 @@ public: void set_end_position(Vector3 p_position); Vector3 get_end_position() const { return end_position; } + void set_global_start_position(Vector3 p_position); + Vector3 get_global_start_position() const; + + void set_global_end_position(Vector3 p_position); + Vector3 get_global_end_position() const; + void set_enter_cost(real_t p_enter_cost); real_t get_enter_cost() const { return enter_cost; } diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp index d169999de4..42b0748698 100644 --- a/scene/3d/voxelizer.cpp +++ b/scene/3d/voxelizer.cpp @@ -346,25 +346,29 @@ Voxelizer::MaterialCache Voxelizer::_get_material_cache(Ref<Material> p_material } else { mc.albedo = _get_bake_texture(img_albedo, Color(1, 1, 1), mat->get_albedo()); // no albedo texture, color is additive } + if (mat->get_feature(BaseMaterial3D::FEATURE_EMISSION)) { + Ref<Texture2D> emission_tex = mat->get_texture(BaseMaterial3D::TEXTURE_EMISSION); - Ref<Texture2D> emission_tex = mat->get_texture(BaseMaterial3D::TEXTURE_EMISSION); - - Color emission_col = mat->get_emission(); - float emission_energy = mat->get_emission_energy_multiplier() * exposure_normalization; - if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) { - emission_energy *= mat->get_emission_intensity(); - } + Color emission_col = mat->get_emission(); + float emission_energy = mat->get_emission_energy_multiplier() * exposure_normalization; + if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) { + emission_energy *= mat->get_emission_intensity(); + } - Ref<Image> img_emission; + Ref<Image> img_emission; - if (emission_tex.is_valid()) { - img_emission = emission_tex->get_image(); - } + if (emission_tex.is_valid()) { + img_emission = emission_tex->get_image(); + } - if (mat->get_emission_operator() == BaseMaterial3D::EMISSION_OP_ADD) { - mc.emission = _get_bake_texture(img_emission, Color(1, 1, 1) * emission_energy, emission_col * emission_energy); + if (mat->get_emission_operator() == BaseMaterial3D::EMISSION_OP_ADD) { + mc.emission = _get_bake_texture(img_emission, Color(1, 1, 1) * emission_energy, emission_col * emission_energy); + } else { + mc.emission = _get_bake_texture(img_emission, emission_col * emission_energy, Color(0, 0, 0)); + } } else { - mc.emission = _get_bake_texture(img_emission, emission_col * emission_energy, Color(0, 0, 0)); + Ref<Image> empty; + mc.emission = _get_bake_texture(empty, Color(0, 0, 0), Color(0, 0, 0)); } } else { diff --git a/scene/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/code_edit.cpp b/scene/gui/code_edit.cpp index b084cb5bea..e2f7ec860c 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -2856,7 +2856,7 @@ void CodeEdit::_filter_code_completion_candidates_impl() { const int caret_line = get_caret_line(); const int caret_column = get_caret_column(); const String line = get_line(caret_line); - ERR_FAIL_INDEX_MSG(caret_column - 1, line.length(), "Caret column exceeds line length."); + ERR_FAIL_INDEX_MSG(caret_column, line.length() + 1, "Caret column exceeds line length."); if (caret_column > 0 && line[caret_column - 1] == '(' && !code_completion_forced) { cancel_code_completion(); diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 0b0698188c..48e3759981 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -31,10 +31,12 @@ #include "color_picker.h" #include "core/input/input.h" +#include "core/io/image.h" #include "core/math/color.h" #include "core/os/keyboard.h" #include "core/os/os.h" #include "scene/gui/color_mode.h" +#include "servers/display_server.h" #include "thirdparty/misc/ok_color.h" #include "thirdparty/misc/ok_color_shader.h" @@ -90,8 +92,8 @@ void ColorPicker::_notification(int p_what) { } break; case NOTIFICATION_WM_CLOSE_REQUEST: { - if (screen != nullptr && screen->is_visible()) { - screen->hide(); + if (picker_window != nullptr && picker_window->is_visible()) { + picker_window->hide(); } } break; } @@ -1372,30 +1374,26 @@ void ColorPicker::_recent_preset_pressed(const bool p_pressed, ColorPresetButton emit_signal(SNAME("color_changed"), p_preset->get_preset_color()); } -void ColorPicker::_screen_input(const Ref<InputEvent> &p_event) { +void ColorPicker::_picker_texture_input(const Ref<InputEvent> &p_event) { if (!is_inside_tree()) { return; } Ref<InputEventMouseButton> bev = p_event; if (bev.is_valid() && bev->get_button_index() == MouseButton::LEFT && !bev->is_pressed()) { + set_pick_color(picker_color); emit_signal(SNAME("color_changed"), color); - screen->hide(); + picker_window->hide(); } Ref<InputEventMouseMotion> mev = p_event; if (mev.is_valid()) { - Viewport *r = get_tree()->get_root(); - if (!r->get_visible_rect().has_point(mev->get_global_position())) { - return; - } - - Ref<Image> img = r->get_texture()->get_image(); + Ref<Image> img = picker_texture_rect->get_texture()->get_image(); if (img.is_valid() && !img->is_empty()) { - Vector2 ofs = mev->get_global_position(); - Color c = img->get_pixel(ofs.x, ofs.y); - - set_pick_color(c); + Vector2 ofs = mev->get_position(); + picker_color = img->get_pixel(ofs.x, ofs.y); + picker_preview_style_box->set_bg_color(picker_color); + picker_preview_label->set_self_modulate(picker_color.get_luminance() < 0.5 ? Color(1.0f, 1.0f, 1.0f) : Color(0.0f, 0.0f, 0.0f)); } } } @@ -1409,27 +1407,79 @@ void ColorPicker::_add_preset_pressed() { emit_signal(SNAME("preset_added"), color); } -void ColorPicker::_screen_pick_pressed() { +void ColorPicker::_pick_button_pressed() { if (!is_inside_tree()) { return; } - Viewport *r = get_tree()->get_root(); - if (!screen) { - screen = memnew(Control); - r->add_child(screen); - screen->set_as_top_level(true); - screen->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); - screen->set_default_cursor_shape(CURSOR_POINTING_HAND); - screen->connect("gui_input", callable_mp(this, &ColorPicker::_screen_input)); - // It immediately toggles off in the first press otherwise. - screen->call_deferred(SNAME("connect"), "hidden", Callable(btn_pick, "set_pressed").bind(false)); + if (!picker_window) { + picker_window = memnew(Popup); + picker_window->hide(); + picker_window->set_transient(true); + add_child(picker_window); + + picker_texture_rect = memnew(TextureRect); + picker_texture_rect->set_anchors_preset(Control::PRESET_FULL_RECT); + picker_window->add_child(picker_texture_rect); + picker_texture_rect->set_default_cursor_shape(CURSOR_POINTING_HAND); + picker_texture_rect->connect(SNAME("gui_input"), callable_mp(this, &ColorPicker::_picker_texture_input)); + + picker_preview = memnew(Panel); + picker_preview->set_anchors_preset(Control::PRESET_CENTER_TOP); + picker_preview->set_mouse_filter(MOUSE_FILTER_IGNORE); + picker_window->add_child(picker_preview); + + picker_preview_label = memnew(Label); + picker_preview->set_anchors_preset(Control::PRESET_CENTER_TOP); + picker_preview_label->set_text("Color Picking active"); + picker_preview->add_child(picker_preview_label); + + picker_preview_style_box = (Ref<StyleBoxFlat>)memnew(StyleBoxFlat); + picker_preview_style_box->set_bg_color(Color(1.0, 1.0, 1.0)); + picker_preview->add_theme_style_override("panel", picker_preview_style_box); + } + + Rect2i screen_rect; + if (picker_window->is_embedded()) { + screen_rect = picker_window->get_embedder()->get_visible_rect(); + picker_window->set_position(Point2i()); + picker_texture_rect->set_texture(ImageTexture::create_from_image(picker_window->get_embedder()->get_texture()->get_image())); } else { - screen->show(); + screen_rect = picker_window->get_parent_rect(); + picker_window->set_position(screen_rect.position); + + Ref<Image> target_image = Image::create_empty(screen_rect.size.x, screen_rect.size.y, false, Image::FORMAT_RGB8); + DisplayServer *ds = DisplayServer::get_singleton(); + + // Add the Texture of each Window to the Image. + Vector<DisplayServer::WindowID> wl = ds->get_window_list(); + // FIXME: sort windows by visibility. + for (int index = 0; index < wl.size(); index++) { + DisplayServer::WindowID wid = wl[index]; + if (wid == DisplayServer::INVALID_WINDOW_ID) { + continue; + } + + ObjectID woid = DisplayServer::get_singleton()->window_get_attached_instance_id(wid); + if (woid == ObjectID()) { + continue; + } + + Window *w = Object::cast_to<Window>(ObjectDB::get_instance(woid)); + Ref<Image> img = w->get_texture()->get_image(); + if (!img.is_valid() || img->is_empty()) { + continue; + } + img->convert(Image::FORMAT_RGB8); + target_image->blit_rect(img, Rect2i(Point2i(0, 0), img->get_size()), w->get_position()); + } + + picker_texture_rect->set_texture(ImageTexture::create_from_image(target_image)); } - screen->move_to_front(); - // TODO: show modal no longer works, needs to be converted to a popup. - //screen->show_modal(); + + picker_window->set_size(screen_rect.size); + picker_preview->set_size(screen_rect.size / 10.0); // 10% of size in each axis. + picker_window->popup(); } void ColorPicker::_html_focus_exit() { @@ -1595,9 +1645,8 @@ ColorPicker::ColorPicker() { btn_pick = memnew(Button); sample_hbc->add_child(btn_pick); - btn_pick->set_toggle_mode(true); - btn_pick->set_tooltip_text(RTR("Pick a color from the editor window.")); - btn_pick->connect("pressed", callable_mp(this, &ColorPicker::_screen_pick_pressed)); + btn_pick->set_tooltip_text(RTR("Pick a color from the application window.")); + btn_pick->connect(SNAME("pressed"), callable_mp(this, &ColorPicker::_pick_button_pressed)); sample = memnew(TextureRect); sample_hbc->add_child(sample); diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index f7578612cd..d02c3278e6 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -40,6 +40,7 @@ #include "scene/gui/line_edit.h" #include "scene/gui/menu_button.h" #include "scene/gui/option_button.h" +#include "scene/gui/panel.h" #include "scene/gui/popup.h" #include "scene/gui/separator.h" #include "scene/gui/slider.h" @@ -111,7 +112,12 @@ private: Vector<ColorMode *> modes; - Control *screen = nullptr; + Popup *picker_window = nullptr; + TextureRect *picker_texture_rect = nullptr; + Panel *picker_preview = nullptr; + Label *picker_preview_label = nullptr; + Ref<StyleBoxFlat> picker_preview_style_box; + Color picker_color; Control *uv_edit = nullptr; Control *w_edit = nullptr; AspectRatioContainer *wheel_edit = nullptr; @@ -211,10 +217,10 @@ private: void _line_edit_input(const Ref<InputEvent> &p_event); void _preset_input(const Ref<InputEvent> &p_event, const Color &p_color); void _recent_preset_pressed(const bool pressed, ColorPresetButton *p_preset); - void _screen_input(const Ref<InputEvent> &p_event); + void _picker_texture_input(const Ref<InputEvent> &p_event); void _text_changed(const String &p_new_text); void _add_preset_pressed(); - void _screen_pick_pressed(); + void _pick_button_pressed(); void _html_focus_exit(); inline int _get_preset_size(); diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 5dd8cde342..ee065cccbf 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -347,14 +347,15 @@ void FileDialog::_action_pressed() { } } - if (!valid) { + String file_name = file_text.strip_edges().get_file(); + if (!valid || file_name.is_empty()) { exterr->popup_centered(Size2(250, 80)); return; } if (dir_access->file_exists(f)) { - confirm_save->set_text(RTR("File exists, overwrite?")); - confirm_save->popup_centered(Size2(200, 80)); + confirm_save->set_text(vformat(RTR("File \"%s\" already exists.\nDo you want to overwrite it?"), f)); + confirm_save->popup_centered(Size2(250, 80)); } else { emit_signal(SNAME("file_selected"), f); hide(); @@ -1136,7 +1137,7 @@ FileDialog::FileDialog() { add_child(mkdirerr, false, INTERNAL_MODE_FRONT); exterr = memnew(AcceptDialog); - exterr->set_text(RTR("Must use a valid extension.")); + exterr->set_text(RTR("Invalid extension, or empty filename.")); add_child(exterr, false, INTERNAL_MODE_FRONT); update_filters(); diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index c0ef71ee4f..b861d7af01 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -86,9 +86,7 @@ int Label::get_line_height(int p_line) const { } } -void Label::_shape() { - bool font_was_dirty = font_dirty; - +bool Label::_shape() { Ref<StyleBox> style = theme_cache.normal_style; int width = (get_size().width - style->get_minimum_size().width); @@ -103,7 +101,7 @@ void Label::_shape() { } const Ref<Font> &font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : theme_cache.font; int font_size = settings.is_valid() ? settings->get_font_size() : theme_cache.font_size; - ERR_FAIL_COND(font.is_null()); + ERR_FAIL_COND_V(font.is_null(), true); String txt = (uppercase) ? TS->string_to_upper(xl_text, language) : xl_text; if (visible_chars >= 0 && visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) { txt = txt.substr(0, visible_chars); @@ -123,6 +121,7 @@ void Label::_shape() { dirty = false; font_dirty = false; lines_dirty = true; + // Note for future maintainers: forgetting stable width here (e.g., setting it to -1) may fix still undiscovered bugs. } if (lines_dirty) { @@ -135,129 +134,138 @@ void Label::_shape() { Size2i prev_minsize = minsize; minsize = Size2(); + bool can_process_lines = false; if (xl_text.length() == 0) { + can_process_lines = true; lines_dirty = false; - return; - } - - // Don't compute minimum size until width is stable (two shape requests in a row with the same width.) - // This avoids situations in which the initial width is very narrow and the label would break text - // into many very short lines, causing a very tall label that can leave a deformed container. - bool width_stabilized = get_size().width == stable_width; - stable_width = get_size().width; + } else { + // With autowrap on or off with trimming enabled, we won't compute the minimum size until width is stable + // (two shape requests in a row with the same width.) This avoids situations in which the initial width is + // very narrow and the label would break text into many very short lines, causing a very tall label that can + // leave a deformed container. In the remaining case (namely, autowrap off and no trimming), the label is + // free to dictate its own width, something that will be taken advtantage of. + bool can_dictate_width = autowrap_mode == TextServer::AUTOWRAP_OFF && overrun_behavior == TextServer::OVERRUN_NO_TRIMMING; + bool is_width_stable = get_size().width == stable_width; + can_process_lines = can_dictate_width || is_width_stable; + stable_width = get_size().width; + + if (can_process_lines) { + if (lines_dirty) { + BitField<TextServer::LineBreakFlag> autowrap_flags = TextServer::BREAK_MANDATORY; + switch (autowrap_mode) { + case TextServer::AUTOWRAP_WORD_SMART: + autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_ADAPTIVE | TextServer::BREAK_MANDATORY; + break; + case TextServer::AUTOWRAP_WORD: + autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_MANDATORY; + break; + case TextServer::AUTOWRAP_ARBITRARY: + autowrap_flags = TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_MANDATORY; + break; + case TextServer::AUTOWRAP_OFF: + break; + } + autowrap_flags = autowrap_flags | TextServer::BREAK_TRIM_EDGE_SPACES; - // With autowrap off, there's still a point in shaping before width is stable: to contribute a min width. - if (lines_dirty && (width_stabilized || autowrap_mode == TextServer::AUTOWRAP_OFF)) { - BitField<TextServer::LineBreakFlag> autowrap_flags = TextServer::BREAK_MANDATORY; - switch (autowrap_mode) { - case TextServer::AUTOWRAP_WORD_SMART: - autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_ADAPTIVE | TextServer::BREAK_MANDATORY; - break; - case TextServer::AUTOWRAP_WORD: - autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_MANDATORY; - break; - case TextServer::AUTOWRAP_ARBITRARY: - autowrap_flags = TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_MANDATORY; - break; - case TextServer::AUTOWRAP_OFF: - break; - } - autowrap_flags = autowrap_flags | TextServer::BREAK_TRIM_EDGE_SPACES; + PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags); + for (int i = 0; i < line_breaks.size(); i = i + 2) { + RID line = TS->shaped_text_substr(text_rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]); + lines_rid.push_back(line); + } + } - PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags); - for (int i = 0; i < line_breaks.size(); i = i + 2) { - RID line = TS->shaped_text_substr(text_rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]); - lines_rid.push_back(line); - } - } + if (can_dictate_width) { + for (int i = 0; i < lines_rid.size(); i++) { + if (minsize.width < TS->shaped_text_get_size(lines_rid[i]).x) { + minsize.width = TS->shaped_text_get_size(lines_rid[i]).x; + } + } - if (autowrap_mode == TextServer::AUTOWRAP_OFF) { - for (int i = 0; i < lines_rid.size(); i++) { - if (minsize.width < TS->shaped_text_get_size(lines_rid[i]).x) { - minsize.width = TS->shaped_text_get_size(lines_rid[i]).x; + width = (minsize.width - style->get_minimum_size().width); } - } - // With autowrap off, by now we already know the width the label will take. - width = (minsize.width - style->get_minimum_size().width); - width_stabilized = true; - } - - if (lines_dirty && width_stabilized) { - BitField<TextServer::TextOverrunFlag> overrun_flags = TextServer::OVERRUN_NO_TRIM; - switch (overrun_behavior) { - case TextServer::OVERRUN_TRIM_WORD_ELLIPSIS: - overrun_flags.set_flag(TextServer::OVERRUN_TRIM); - overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY); - overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS); - break; - case TextServer::OVERRUN_TRIM_ELLIPSIS: - overrun_flags.set_flag(TextServer::OVERRUN_TRIM); - overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS); - break; - case TextServer::OVERRUN_TRIM_WORD: - overrun_flags.set_flag(TextServer::OVERRUN_TRIM); - overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY); - break; - case TextServer::OVERRUN_TRIM_CHAR: - overrun_flags.set_flag(TextServer::OVERRUN_TRIM); - break; - case TextServer::OVERRUN_NO_TRIMMING: - break; - } + if (lines_dirty) { + BitField<TextServer::TextOverrunFlag> overrun_flags = TextServer::OVERRUN_NO_TRIM; + switch (overrun_behavior) { + case TextServer::OVERRUN_TRIM_WORD_ELLIPSIS: + overrun_flags.set_flag(TextServer::OVERRUN_TRIM); + overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY); + overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS); + break; + case TextServer::OVERRUN_TRIM_ELLIPSIS: + overrun_flags.set_flag(TextServer::OVERRUN_TRIM); + overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS); + break; + case TextServer::OVERRUN_TRIM_WORD: + overrun_flags.set_flag(TextServer::OVERRUN_TRIM); + overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY); + break; + case TextServer::OVERRUN_TRIM_CHAR: + overrun_flags.set_flag(TextServer::OVERRUN_TRIM); + break; + case TextServer::OVERRUN_NO_TRIMMING: + break; + } - // Fill after min_size calculation. + // Fill after min_size calculation. - int visible_lines = lines_rid.size(); - if (max_lines_visible >= 0 && visible_lines > max_lines_visible) { - visible_lines = max_lines_visible; - } - if (autowrap_mode != TextServer::AUTOWRAP_OFF) { - bool lines_hidden = visible_lines > 0 && visible_lines < lines_rid.size(); - if (lines_hidden) { - overrun_flags.set_flag(TextServer::OVERRUN_ENFORCE_ELLIPSIS); - } - if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) { - for (int i = 0; i < lines_rid.size(); i++) { - if (i < visible_lines - 1 || lines_rid.size() == 1) { - TS->shaped_text_fit_to_width(lines_rid[i], width); - } else if (i == (visible_lines - 1)) { + int visible_lines = lines_rid.size(); + if (max_lines_visible >= 0 && visible_lines > max_lines_visible) { + visible_lines = max_lines_visible; + } + if (autowrap_mode != TextServer::AUTOWRAP_OFF) { + bool lines_hidden = visible_lines > 0 && visible_lines < lines_rid.size(); + if (lines_hidden) { + overrun_flags.set_flag(TextServer::OVERRUN_ENFORCE_ELLIPSIS); + } + if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) { + for (int i = 0; i < lines_rid.size(); i++) { + if (i < visible_lines - 1 || lines_rid.size() == 1) { + TS->shaped_text_fit_to_width(lines_rid[i], width); + } else if (i == (visible_lines - 1)) { + TS->shaped_text_overrun_trim_to_width(lines_rid[visible_lines - 1], width, overrun_flags); + } + } + } else if (lines_hidden) { TS->shaped_text_overrun_trim_to_width(lines_rid[visible_lines - 1], width, overrun_flags); } - } - } else if (lines_hidden) { - TS->shaped_text_overrun_trim_to_width(lines_rid[visible_lines - 1], width, overrun_flags); - } - } else { - // Autowrap disabled. - for (int i = 0; i < lines_rid.size(); i++) { - if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) { - TS->shaped_text_fit_to_width(lines_rid[i], width); - overrun_flags.set_flag(TextServer::OVERRUN_JUSTIFICATION_AWARE); - TS->shaped_text_overrun_trim_to_width(lines_rid[i], width, overrun_flags); - TS->shaped_text_fit_to_width(lines_rid[i], width, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS); } else { - TS->shaped_text_overrun_trim_to_width(lines_rid[i], width, overrun_flags); + // Autowrap disabled. + for (int i = 0; i < lines_rid.size(); i++) { + if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) { + TS->shaped_text_fit_to_width(lines_rid[i], width); + overrun_flags.set_flag(TextServer::OVERRUN_JUSTIFICATION_AWARE); + TS->shaped_text_overrun_trim_to_width(lines_rid[i], width, overrun_flags); + TS->shaped_text_fit_to_width(lines_rid[i], width, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS); + } else { + TS->shaped_text_overrun_trim_to_width(lines_rid[i], width, overrun_flags); + } + } + } + + int last_line = MIN(lines_rid.size(), visible_lines + lines_skipped); + int line_spacing = settings.is_valid() ? settings->get_line_spacing() : theme_cache.line_spacing; + for (int64_t i = lines_skipped; i < last_line; i++) { + minsize.height += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing; } - } - } - int last_line = MIN(lines_rid.size(), visible_lines + lines_skipped); - int line_spacing = settings.is_valid() ? settings->get_line_spacing() : theme_cache.line_spacing; - for (int64_t i = lines_skipped; i < last_line; i++) { - minsize.height += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing; + lines_dirty = false; + } + } else { + callable_mp(this, &Label::_shape).call_deferred(); } + } - lines_dirty = false; + if (draw_pending) { + queue_redraw(); + draw_pending = false; } - if (minsize != prev_minsize || font_was_dirty) { + if (minsize != prev_minsize) { update_minimum_size(); } - if (!width_stabilized) { - callable_mp(this, &Label::_shape).call_deferred(); - } + return can_process_lines; } inline void draw_glyph(const Glyph &p_gl, const RID &p_canvas, const Color &p_font_color, const Vector2 &p_ofs) { @@ -367,10 +375,9 @@ void Label::_notification(int p_what) { } if (dirty || font_dirty || lines_dirty) { - _shape(); - if (lines_dirty) { + if (!_shape()) { // There will be another pass. - queue_redraw(); + draw_pending = true; break; } } @@ -396,7 +403,7 @@ void Label::_notification(int p_what) { style->draw(ci, Rect2(Point2(0, 0), get_size())); float total_h = 0.0; - int visible_lines = 0; + int lines_visible = 0; // Get number of lines to fit to the height. for (int64_t i = lines_skipped; i < lines_rid.size(); i++) { @@ -404,14 +411,14 @@ void Label::_notification(int p_what) { if (total_h > (get_size().height - style->get_minimum_size().height + line_spacing)) { break; } - visible_lines++; + lines_visible++; } - if (max_lines_visible >= 0 && visible_lines > max_lines_visible) { - visible_lines = max_lines_visible; + if (max_lines_visible >= 0 && lines_visible > max_lines_visible) { + lines_visible = max_lines_visible; } - int last_line = MIN(lines_rid.size(), visible_lines + lines_skipped); + int last_line = MIN(lines_rid.size(), lines_visible + lines_skipped); bool trim_chars = (visible_chars >= 0) && (visible_chars_behavior == TextServer::VC_CHARS_AFTER_SHAPING); bool trim_glyphs_ltr = (visible_chars >= 0) && ((visible_chars_behavior == TextServer::VC_GLYPHS_LTR) || ((visible_chars_behavior == TextServer::VC_GLYPHS_AUTO) && !rtl_layout)); bool trim_glyphs_rtl = (visible_chars >= 0) && ((visible_chars_behavior == TextServer::VC_GLYPHS_RTL) || ((visible_chars_behavior == TextServer::VC_GLYPHS_AUTO) && rtl_layout)); @@ -428,7 +435,7 @@ void Label::_notification(int p_what) { total_h += style->get_margin(SIDE_TOP) + style->get_margin(SIDE_BOTTOM); int vbegin = 0, vsep = 0; - if (visible_lines > 0) { + if (lines_visible > 0) { switch (vertical_alignment) { case VERTICAL_ALIGNMENT_TOP: { // Nothing. @@ -445,8 +452,8 @@ void Label::_notification(int p_what) { } break; case VERTICAL_ALIGNMENT_FILL: { vbegin = 0; - if (visible_lines > 1) { - vsep = (size.y - (total_h - line_spacing)) / (visible_lines - 1); + if (lines_visible > 1) { + vsep = (size.y - (total_h - line_spacing)) / (lines_visible - 1); } else { vsep = 0; } @@ -615,6 +622,8 @@ void Label::_notification(int p_what) { } ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + vsep + line_spacing; } + + draw_pending = false; } break; case NOTIFICATION_THEME_CHANGED: { @@ -666,25 +675,25 @@ int Label::get_line_count() const { int Label::get_visible_line_count() const { Ref<StyleBox> style = theme_cache.normal_style; int line_spacing = settings.is_valid() ? settings->get_line_spacing() : theme_cache.line_spacing; - int visible_lines = 0; + int lines_visible = 0; float total_h = 0.0; for (int64_t i = lines_skipped; i < lines_rid.size(); i++) { total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing; if (total_h > (get_size().height - style->get_minimum_size().height + line_spacing)) { break; } - visible_lines++; + lines_visible++; } - if (visible_lines > lines_rid.size()) { - visible_lines = lines_rid.size(); + if (lines_visible > lines_rid.size()) { + lines_visible = lines_rid.size(); } - if (max_lines_visible >= 0 && visible_lines > max_lines_visible) { - visible_lines = max_lines_visible; + if (max_lines_visible >= 0 && lines_visible > max_lines_visible) { + lines_visible = max_lines_visible; } - return visible_lines; + return lines_visible; } void Label::set_horizontal_alignment(HorizontalAlignment p_alignment) { @@ -969,7 +978,7 @@ void Label::_bind_methods() { ClassDB::bind_method(D_METHOD("get_visible_ratio"), &Label::get_visible_ratio); ClassDB::bind_method(D_METHOD("set_lines_skipped", "lines_skipped"), &Label::set_lines_skipped); ClassDB::bind_method(D_METHOD("get_lines_skipped"), &Label::get_lines_skipped); - ClassDB::bind_method(D_METHOD("set_max_lines_visible", "visible_lines"), &Label::set_max_lines_visible); + ClassDB::bind_method(D_METHOD("set_max_lines_visible", "lines_visible"), &Label::set_max_lines_visible); ClassDB::bind_method(D_METHOD("get_max_lines_visible"), &Label::get_max_lines_visible); ClassDB::bind_method(D_METHOD("set_structured_text_bidi_override", "parser"), &Label::set_structured_text_bidi_override); ClassDB::bind_method(D_METHOD("get_structured_text_bidi_override"), &Label::get_structured_text_bidi_override); diff --git a/scene/gui/label.h b/scene/gui/label.h index 448cb245eb..36b85f7af8 100644 --- a/scene/gui/label.h +++ b/scene/gui/label.h @@ -50,7 +50,6 @@ private: bool uppercase = false; bool lines_dirty = true; - bool dirty = true; bool font_dirty = true; RID text_rid; @@ -66,6 +65,7 @@ private: float visible_ratio = 1.0; int lines_skipped = 0; int max_lines_visible = -1; + bool draw_pending = false; Ref<LabelSettings> settings; @@ -83,7 +83,7 @@ private: int font_shadow_outline_size; } theme_cache; - void _shape(); + bool _shape(); void _invalidate(); protected: diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index f9c9906efa..973b02b3a3 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -1179,7 +1179,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o dot_ul_started = false; float y_off = TS->shaped_text_get_underline_position(rid); float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale; - draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, underline_width * 2); + draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, MAX(2.0, underline_width * 2)); } if (_find_strikethrough(it)) { if (!st_started) { @@ -1341,7 +1341,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o dot_ul_started = false; float y_off = TS->shaped_text_get_underline_position(rid); float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale; - draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, underline_width * 2); + draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, MAX(2.0, underline_width * 2)); } if (st_started) { st_started = false; @@ -1363,7 +1363,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o dot_ul_started = false; float y_off = TS->shaped_text_get_underline_position(rid); float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale; - draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, underline_width * 2); + draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, MAX(2.0, underline_width * 2)); } if (st_started) { st_started = false; @@ -5520,34 +5520,6 @@ void RichTextLabel::_bind_methods() { BIND_ENUM_CONSTANT(LIST_ROMAN); BIND_ENUM_CONSTANT(LIST_DOTS); - BIND_ENUM_CONSTANT(ITEM_FRAME); - BIND_ENUM_CONSTANT(ITEM_TEXT); - BIND_ENUM_CONSTANT(ITEM_IMAGE); - BIND_ENUM_CONSTANT(ITEM_NEWLINE); - BIND_ENUM_CONSTANT(ITEM_FONT); - BIND_ENUM_CONSTANT(ITEM_FONT_SIZE); - BIND_ENUM_CONSTANT(ITEM_FONT_FEATURES); - BIND_ENUM_CONSTANT(ITEM_COLOR); - BIND_ENUM_CONSTANT(ITEM_OUTLINE_SIZE); - BIND_ENUM_CONSTANT(ITEM_OUTLINE_COLOR); - BIND_ENUM_CONSTANT(ITEM_UNDERLINE); - BIND_ENUM_CONSTANT(ITEM_STRIKETHROUGH); - BIND_ENUM_CONSTANT(ITEM_PARAGRAPH); - BIND_ENUM_CONSTANT(ITEM_INDENT); - BIND_ENUM_CONSTANT(ITEM_LIST); - BIND_ENUM_CONSTANT(ITEM_TABLE); - BIND_ENUM_CONSTANT(ITEM_FADE); - BIND_ENUM_CONSTANT(ITEM_SHAKE); - BIND_ENUM_CONSTANT(ITEM_WAVE); - BIND_ENUM_CONSTANT(ITEM_TORNADO); - BIND_ENUM_CONSTANT(ITEM_RAINBOW); - BIND_ENUM_CONSTANT(ITEM_BGCOLOR); - BIND_ENUM_CONSTANT(ITEM_FGCOLOR); - BIND_ENUM_CONSTANT(ITEM_META); - BIND_ENUM_CONSTANT(ITEM_HINT); - BIND_ENUM_CONSTANT(ITEM_DROPCAP); - BIND_ENUM_CONSTANT(ITEM_CUSTOMFX); - BIND_ENUM_CONSTANT(MENU_COPY); BIND_ENUM_CONSTANT(MENU_SELECT_ALL); BIND_ENUM_CONSTANT(MENU_MAX); diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index b01fccf14c..1dae8b75ca 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -740,7 +740,6 @@ public: }; VARIANT_ENUM_CAST(RichTextLabel::ListType); -VARIANT_ENUM_CAST(RichTextLabel::ItemType); VARIANT_ENUM_CAST(RichTextLabel::MenuItems); #endif // RICH_TEXT_LABEL_H diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp index eca6cb3eef..5e378a0321 100644 --- a/scene/gui/tab_bar.cpp +++ b/scene/gui/tab_bar.cpp @@ -342,6 +342,8 @@ void TabBar::_notification(int p_what) { _shape(i); } + queue_redraw(); + [[fallthrough]]; } case NOTIFICATION_RESIZED: { diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index e5dcdd2afd..b36353158b 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -513,14 +513,16 @@ bool CanvasItem::is_y_sort_enabled() const { void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, real_t p_dash, bool p_aligned) { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); + ERR_FAIL_COND(p_dash <= 0.0); float length = (p_to - p_from).length(); - if (length < p_dash) { + Vector2 step = p_dash * (p_to - p_from).normalized(); + + if (length < p_dash || step == Vector2()) { RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width); return; } - Vector2 step = p_dash * (p_to - p_from).normalized(); int steps = (p_aligned) ? Math::ceil(length / p_dash) : Math::floor(length / p_dash); if (steps % 2 == 0) { steps--; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 23b7c072be..244e0d5b93 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -166,6 +166,24 @@ ViewportTexture::~ViewportTexture() { } void Viewport::_sub_window_update_order() { + if (gui.sub_windows.size() < 2) { + return; + } + + if (!gui.sub_windows[gui.sub_windows.size() - 1].window->get_flag(Window::FLAG_ALWAYS_ON_TOP)) { + int index = gui.sub_windows.size() - 1; + + while (index > 0 && gui.sub_windows[index - 1].window->get_flag(Window::FLAG_ALWAYS_ON_TOP)) { + --index; + } + + if (index != (gui.sub_windows.size() - 1)) { + SubWindow sw = gui.sub_windows[gui.sub_windows.size() - 1]; + gui.sub_windows.remove_at(gui.sub_windows.size() - 1); + gui.sub_windows.insert(index, sw); + } + } + for (int i = 0; i < gui.sub_windows.size(); i++) { RS::get_singleton()->canvas_item_set_draw_index(gui.sub_windows[i].canvas_item, i); } @@ -1312,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(); } @@ -1833,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 9092be93e6..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) { @@ -984,17 +984,13 @@ void Window::_update_viewport_size() { Size2 margin; Size2 offset; - //black bars and margin + if (content_scale_aspect != CONTENT_SCALE_ASPECT_EXPAND && screen_size.x < video_mode.x) { margin.x = Math::round((video_mode.x - screen_size.x) / 2.0); - //RenderingServer::get_singleton()->black_bars_set_margins(margin.x, 0, margin.x, 0); offset.x = Math::round(margin.x * viewport_size.y / screen_size.y); } else if (content_scale_aspect != CONTENT_SCALE_ASPECT_EXPAND && screen_size.y < video_mode.y) { margin.y = Math::round((video_mode.y - screen_size.y) / 2.0); - //RenderingServer::get_singleton()->black_bars_set_margins(0, margin.y, 0, margin.y); offset.y = Math::round(margin.y * viewport_size.x / screen_size.x); - } else { - //RenderingServer::get_singleton()->black_bars_set_margins(0, 0, 0, 0); } switch (content_scale_mode) { @@ -1057,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) { @@ -1092,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) { @@ -1121,6 +1117,7 @@ void Window::_notification(int p_what) { position = DisplayServer::get_singleton()->window_get_position(window_id); size = DisplayServer::get_singleton()->window_get_size(window_id); } + _update_window_size(); // Inform DisplayServer of minimum and maximum size. _update_viewport_size(); // Then feed back to the viewport. _update_window_callbacks(); RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_WHEN_VISIBLE); @@ -1434,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); @@ -1465,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); @@ -1491,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); @@ -1512,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) { @@ -1548,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); @@ -1590,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 @@ -2157,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()); } @@ -2173,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/mesh.cpp b/scene/resources/mesh.cpp index cf9baa2907..a7b53244e2 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -526,6 +526,9 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { vc = indices.size(); ir = indices.ptrw(); has_indices = true; + } else { + // Ensure there are enough vertices to construct at least one triangle. + ERR_FAIL_COND_V(vertices.size() % 3 != 0, Ref<ArrayMesh>()); } HashMap<Vector3, Vector3> normal_accum; diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 7e3156d2ff..05be40c446 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -2566,73 +2566,6 @@ void GradientTexture2D::_bind_methods() { ////////////////////////////////////// -void ProxyTexture::set_base(const Ref<Texture2D> &p_texture) { - ERR_FAIL_COND(p_texture == this); - - base = p_texture; - if (base.is_valid()) { - ERR_FAIL_NULL(RenderingServer::get_singleton()); - if (proxy_ph.is_valid()) { - RS::get_singleton()->texture_proxy_update(proxy, base->get_rid()); - RS::get_singleton()->free(proxy_ph); - proxy_ph = RID(); - } else if (proxy.is_valid()) { - RS::get_singleton()->texture_proxy_update(proxy, base->get_rid()); - } else { - proxy = RS::get_singleton()->texture_proxy_create(base->get_rid()); - } - } -} - -Ref<Texture2D> ProxyTexture::get_base() const { - return base; -} - -int ProxyTexture::get_width() const { - if (base.is_valid()) { - return base->get_width(); - } - return 1; -} - -int ProxyTexture::get_height() const { - if (base.is_valid()) { - return base->get_height(); - } - return 1; -} - -RID ProxyTexture::get_rid() const { - if (proxy.is_null()) { - proxy_ph = RS::get_singleton()->texture_2d_placeholder_create(); - proxy = RS::get_singleton()->texture_proxy_create(proxy_ph); - } - return proxy; -} - -bool ProxyTexture::has_alpha() const { - if (base.is_valid()) { - return base->has_alpha(); - } - return false; -} - -ProxyTexture::ProxyTexture() { - //proxy = RS::get_singleton()->texture_create(); -} - -ProxyTexture::~ProxyTexture() { - ERR_FAIL_NULL(RenderingServer::get_singleton()); - if (proxy_ph.is_valid()) { - RS::get_singleton()->free(proxy_ph); - } - if (proxy.is_valid()) { - RS::get_singleton()->free(proxy); - } -} - -////////////////////////////////////////////// - void AnimatedTexture::_update_proxy() { RWLockRead r(rw_lock); @@ -2704,6 +2637,7 @@ void AnimatedTexture::set_current_frame(int p_frame) { RWLockWrite r(rw_lock); current_frame = p_frame; + time = 0; } int AnimatedTexture::get_current_frame() const { diff --git a/scene/resources/texture.h b/scene/resources/texture.h index 7f74ae6941..7c4d479da8 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -892,29 +892,6 @@ public: VARIANT_ENUM_CAST(GradientTexture2D::Fill); VARIANT_ENUM_CAST(GradientTexture2D::Repeat); -class ProxyTexture : public Texture2D { -private: - mutable RID proxy_ph; - mutable RID proxy; - Ref<Texture2D> base; - -protected: - static void _bind_methods(); - -public: - void set_base(const Ref<Texture2D> &p_texture); - Ref<Texture2D> get_base() const; - - virtual int get_width() const override; - virtual int get_height() const override; - virtual RID get_rid() const override; - - virtual bool has_alpha() const override; - - ProxyTexture(); - ~ProxyTexture(); -}; - class AnimatedTexture : public Texture2D { GDCLASS(AnimatedTexture, Texture2D); diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index fee0a4a910..d4b2be355e 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -3308,7 +3308,7 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const { void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { PropertyInfo property_info; // Rendering. - p_list->push_back(PropertyInfo(Variant::NIL, "Rendering", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Rendering", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); for (int i = 0; i < occlusion_layers.size(); i++) { p_list->push_back(PropertyInfo(Variant::INT, vformat("occlusion_layer_%d/light_mask", i), PROPERTY_HINT_LAYERS_2D_RENDER)); @@ -3321,7 +3321,7 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { } // Physics. - p_list->push_back(PropertyInfo(Variant::NIL, "Physics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Physics", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); for (int i = 0; i < physics_layers.size(); i++) { p_list->push_back(PropertyInfo(Variant::INT, vformat("physics_layer_%d/collision_layer", i), PROPERTY_HINT_LAYERS_2D_PHYSICS)); @@ -3341,7 +3341,7 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { } // Terrains. - p_list->push_back(PropertyInfo(Variant::NIL, "Terrains", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Terrains", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); for (int terrain_set_index = 0; terrain_set_index < terrain_sets.size(); terrain_set_index++) { p_list->push_back(PropertyInfo(Variant::INT, vformat("terrain_set_%d/mode", terrain_set_index), PROPERTY_HINT_ENUM, "Match Corners and Sides,Match Corners,Match Sides")); p_list->push_back(PropertyInfo(Variant::NIL, vformat("terrain_set_%d/terrains", terrain_set_index), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ARRAY, vformat("terrain_set_%d/terrain_", terrain_set_index))); @@ -3352,7 +3352,7 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { } // Navigation. - p_list->push_back(PropertyInfo(Variant::NIL, "Navigation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Navigation", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); for (int i = 0; i < navigation_layers.size(); i++) { p_list->push_back(PropertyInfo(Variant::INT, vformat("navigation_layer_%d/layers", i), PROPERTY_HINT_LAYERS_2D_NAVIGATION)); } @@ -3362,7 +3362,7 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { for (int i = 1; i < Variant::VARIANT_MAX; i++) { argt += "," + Variant::get_type_name(Variant::Type(i)); } - p_list->push_back(PropertyInfo(Variant::NIL, "Custom data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Custom Data", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); for (int i = 0; i < custom_data_layers.size(); i++) { p_list->push_back(PropertyInfo(Variant::STRING, vformat("custom_data_layer_%d/name", i))); p_list->push_back(PropertyInfo(Variant::INT, vformat("custom_data_layer_%d/type", i), PROPERTY_HINT_ENUM, argt)); @@ -3376,10 +3376,10 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { // Tile Proxies. // Note: proxies need to be set after sources are set. - p_list->push_back(PropertyInfo(Variant::NIL, "Tile Proxies", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); - p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/source_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); - p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/coords_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); - p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/alternative_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Tile Proxies", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::ARRAY, PNAME("tile_proxies/source_level"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::ARRAY, PNAME("tile_proxies/coords_level"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::ARRAY, PNAME("tile_proxies/alternative_level"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); // Patterns. for (unsigned int pattern_index = 0; pattern_index < patterns.size(); pattern_index++) { @@ -4887,9 +4887,9 @@ bool TileSetScenesCollectionSource::_get(const StringName &p_name, Variant &r_re void TileSetScenesCollectionSource::_get_property_list(List<PropertyInfo> *p_list) const { for (int i = 0; i < scenes_ids.size(); i++) { - p_list->push_back(PropertyInfo(Variant::OBJECT, vformat("scenes/%d/scene", scenes_ids[i]), PROPERTY_HINT_RESOURCE_TYPE, "TileSetScenesCollectionSource")); + p_list->push_back(PropertyInfo(Variant::OBJECT, vformat("%s/%d/%s", PNAME("scenes"), scenes_ids[i], PNAME("scene")), PROPERTY_HINT_RESOURCE_TYPE, "TileSetScenesCollectionSource")); - PropertyInfo property_info = PropertyInfo(Variant::BOOL, vformat("scenes/%d/display_placeholder", scenes_ids[i])); + PropertyInfo property_info = PropertyInfo(Variant::BOOL, vformat("%s/%d/%s", PNAME("scenes"), scenes_ids[i], PNAME("display_placeholder"))); if (scenes[scenes_ids[i]].display_placeholder == false) { property_info.usage ^= PROPERTY_USAGE_STORAGE; } @@ -5692,10 +5692,10 @@ void TileData::_get_property_list(List<PropertyInfo> *p_list) const { // Add the groups manually. if (tile_set) { // Occlusion layers. - p_list->push_back(PropertyInfo(Variant::NIL, "Rendering", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Rendering", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); for (int i = 0; i < occluders.size(); i++) { // occlusion_layer_%d/polygon - property_info = PropertyInfo(Variant::OBJECT, vformat("occlusion_layer_%d/polygon", i), PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D", PROPERTY_USAGE_DEFAULT); + property_info = PropertyInfo(Variant::OBJECT, vformat("occlusion_layer_%d/%s", i, PNAME("polygon")), PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D", PROPERTY_USAGE_DEFAULT); if (!occluders[i].is_valid()) { property_info.usage ^= PROPERTY_USAGE_STORAGE; } @@ -5703,29 +5703,29 @@ void TileData::_get_property_list(List<PropertyInfo> *p_list) const { } // Physics layers. - p_list->push_back(PropertyInfo(Variant::NIL, "Physics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Physics", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); for (int i = 0; i < physics.size(); i++) { - p_list->push_back(PropertyInfo(Variant::VECTOR2, vformat("physics_layer_%d/linear_velocity", i), PROPERTY_HINT_NONE)); - p_list->push_back(PropertyInfo(Variant::FLOAT, vformat("physics_layer_%d/angular_velocity", i), PROPERTY_HINT_NONE)); - p_list->push_back(PropertyInfo(Variant::INT, vformat("physics_layer_%d/polygons_count", i), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR2, vformat("physics_layer_%d/%s", i, PNAME("linear_velocity")), PROPERTY_HINT_NONE)); + p_list->push_back(PropertyInfo(Variant::FLOAT, vformat("physics_layer_%d/%s", i, PNAME("angular_velocity")), PROPERTY_HINT_NONE)); + p_list->push_back(PropertyInfo(Variant::INT, vformat("physics_layer_%d/%s", i, PNAME("polygons_count")), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); for (int j = 0; j < physics[i].polygons.size(); j++) { // physics_layer_%d/points - property_info = PropertyInfo(Variant::ARRAY, vformat("physics_layer_%d/polygon_%d/points", i, j), PROPERTY_HINT_ARRAY_TYPE, "Vector2", PROPERTY_USAGE_DEFAULT); + property_info = PropertyInfo(Variant::ARRAY, vformat("physics_layer_%d/polygon_%d/%s", i, j, PNAME("points")), PROPERTY_HINT_ARRAY_TYPE, "Vector2", PROPERTY_USAGE_DEFAULT); if (physics[i].polygons[j].polygon.is_empty()) { property_info.usage ^= PROPERTY_USAGE_STORAGE; } p_list->push_back(property_info); // physics_layer_%d/polygon_%d/one_way - property_info = PropertyInfo(Variant::BOOL, vformat("physics_layer_%d/polygon_%d/one_way", i, j)); + property_info = PropertyInfo(Variant::BOOL, vformat("physics_layer_%d/polygon_%d/%s", i, j, PNAME("one_way"))); if (physics[i].polygons[j].one_way == false) { property_info.usage ^= PROPERTY_USAGE_STORAGE; } p_list->push_back(property_info); // physics_layer_%d/polygon_%d/one_way_margin - property_info = PropertyInfo(Variant::FLOAT, vformat("physics_layer_%d/polygon_%d/one_way_margin", i, j)); + property_info = PropertyInfo(Variant::FLOAT, vformat("physics_layer_%d/polygon_%d/%s", i, j, PNAME("one_way_margin"))); if (physics[i].polygons[j].one_way_margin == 1.0) { property_info.usage ^= PROPERTY_USAGE_STORAGE; } @@ -5735,7 +5735,7 @@ void TileData::_get_property_list(List<PropertyInfo> *p_list) const { // Terrain data if (terrain_set >= 0) { - p_list->push_back(PropertyInfo(Variant::NIL, "Terrains", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Terrains", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { TileSet::CellNeighbor bit = TileSet::CellNeighbor(i); if (is_valid_terrain_peering_bit(bit)) { @@ -5749,9 +5749,9 @@ void TileData::_get_property_list(List<PropertyInfo> *p_list) const { } // Navigation layers. - p_list->push_back(PropertyInfo(Variant::NIL, "Navigation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Navigation", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); for (int i = 0; i < navigation.size(); i++) { - property_info = PropertyInfo(Variant::OBJECT, vformat("navigation_layer_%d/polygon", i), PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon", PROPERTY_USAGE_DEFAULT); + property_info = PropertyInfo(Variant::OBJECT, vformat("navigation_layer_%d/%s", i, PNAME("polygon")), PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon", PROPERTY_USAGE_DEFAULT); if (!navigation[i].is_valid()) { property_info.usage ^= PROPERTY_USAGE_STORAGE; } @@ -5759,7 +5759,7 @@ void TileData::_get_property_list(List<PropertyInfo> *p_list) const { } // Custom data layers. - p_list->push_back(PropertyInfo(Variant::NIL, "Custom data", PROPERTY_HINT_NONE, "custom_data_", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Custom Data", "custom_data_"), PROPERTY_HINT_NONE, "custom_data_", PROPERTY_USAGE_GROUP)); for (int i = 0; i < custom_data.size(); i++) { Variant default_val; Callable::CallError error; diff --git a/servers/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 02460bdb18..e5cc426708 100644 --- a/servers/navigation_server_3d.cpp +++ b/servers/navigation_server_3d.cpp @@ -115,7 +115,9 @@ void NavigationServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer3D::free); ClassDB::bind_method(D_METHOD("set_active", "active"), &NavigationServer3D::set_active); - ClassDB::bind_method(D_METHOD("process", "delta_time"), &NavigationServer3D::process); + + 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"))); @@ -185,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) { @@ -534,22 +554,6 @@ bool NavigationServer3D::get_debug_navigation_enable_link_connections_xray() con return debug_navigation_enable_link_connections_xray; } -void NavigationServer3D::set_debug_enabled(bool p_enabled) { - if (debug_enabled != p_enabled) { - debug_dirty = true; - } - - debug_enabled = p_enabled; - - if (debug_dirty) { - call_deferred("_emit_navigation_debug_changed_signal"); - } -} - -bool NavigationServer3D::get_debug_enabled() const { - return debug_enabled; -} - void NavigationServer3D::set_debug_navigation_enable_agent_paths(const bool p_value) { if (debug_navigation_enable_agent_paths != p_value) { debug_dirty = true; diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h index 79729c55be..05df5ca0fe 100644 --- a/servers/navigation_server_3d.h +++ b/servers/navigation_server_3d.h @@ -274,9 +274,13 @@ public: virtual int get_process_info(ProcessInfo p_info) const = 0; -#ifdef DEBUG_ENABLED + void set_debug_enabled(bool p_enabled); + bool get_debug_enabled() const; + private: bool debug_enabled = false; + +#ifdef DEBUG_ENABLED bool debug_dirty = true; void _emit_navigation_debug_changed_signal(); @@ -313,9 +317,6 @@ private: Ref<StandardMaterial3D> debug_navigation_agent_path_point_material; public: - void set_debug_enabled(bool p_enabled); - bool get_debug_enabled() const; - void set_debug_navigation_edge_connection_color(const Color &p_color); Color get_debug_navigation_edge_connection_color() const; diff --git a/servers/navigation_server_3d_dummy.h b/servers/navigation_server_3d_dummy.h index d2f8fe6048..fd9226e59e 100644 --- a/servers/navigation_server_3d_dummy.h +++ b/servers/navigation_server_3d_dummy.h @@ -112,6 +112,8 @@ public: void process(real_t delta_time) override {} NavigationUtilities::PathQueryResult _query_path(const NavigationUtilities::PathQueryParameters &p_parameters) const override { return NavigationUtilities::PathQueryResult(); } int get_process_info(ProcessInfo p_info) const override { return 0; } + void set_debug_enabled(bool p_enabled) {} + bool get_debug_enabled() const { return false; } }; #endif // NAVIGATION_SERVER_3D_DUMMY_H diff --git a/servers/physics_3d/godot_shape_3d.cpp b/servers/physics_3d/godot_shape_3d.cpp index 300dca4e08..d566d612ce 100644 --- a/servers/physics_3d/godot_shape_3d.cpp +++ b/servers/physics_3d/godot_shape_3d.cpp @@ -1092,6 +1092,8 @@ void GodotConvexPolygonShape3D::_setup(const Vector<Vector3> &p_vertices) { if (err != OK) { ERR_PRINT("Failed to build convex hull"); } + extreme_vertices.resize(0); + vertex_neighbors.resize(0); AABB _aabb; diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp index e031e33041..9389f8149e 100644 --- a/servers/rendering/renderer_rd/effects/ss_effects.cpp +++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp @@ -484,7 +484,7 @@ void SSEffects::downsample_depth(Ref<RenderSceneBuffersRD> p_render_buffers, uin downsample_uniform_set = uniform_set_cache->get_cache_vec(shader, 2, u_depths); } - float depth_linearize_mul = -p_projection.columns[3][2]; + float depth_linearize_mul = -p_projection.columns[3][2] * 0.5; float depth_linearize_add = p_projection.columns[2][2]; if (depth_linearize_mul * depth_linearize_add < 0) { depth_linearize_add = -depth_linearize_add; @@ -668,8 +668,14 @@ void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_rende ssil.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x; ssil.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y; - ssil.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width; - ssil.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height; + ssil.gather_push_constant.half_screen_pixel_size[0] = 2.0 / p_settings.full_screen_size.x; + ssil.gather_push_constant.half_screen_pixel_size[1] = 2.0 / p_settings.full_screen_size.y; + if (ssil_half_size) { + ssil.gather_push_constant.half_screen_pixel_size[0] *= 2.0; + ssil.gather_push_constant.half_screen_pixel_size[1] *= 2.0; + } + ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.75; + ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.75; float tan_half_fov_x = 1.0 / p_projection.columns[0][0]; float tan_half_fov_y = 1.0 / p_projection.columns[1][1]; ssil.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0; @@ -680,9 +686,6 @@ void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_rende ssil.gather_push_constant.z_far = p_projection.get_z_far(); ssil.gather_push_constant.is_orthogonal = p_projection.is_orthogonal(); - ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.25; - ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.25; - ssil.gather_push_constant.radius = p_settings.radius; float radius_near_limit = (p_settings.radius * 1.2f); if (ssil_quality <= RS::ENV_SSIL_QUALITY_LOW) { @@ -733,7 +736,7 @@ void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_rende RD::Uniform u_depth_texture_view; u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u_depth_texture_view.binding = 0; - u_depth_texture_view.append_id(default_sampler); + u_depth_texture_view.append_id(ss_effects.mirror_sampler); u_depth_texture_view.append_id(depth_texture_view); RD::Uniform u_normal_buffer; @@ -1056,8 +1059,14 @@ void SSEffects::generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORe ssao.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x; ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y; - ssao.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width; - ssao.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height; + ssao.gather_push_constant.half_screen_pixel_size[0] = 2.0 / p_settings.full_screen_size.x; + ssao.gather_push_constant.half_screen_pixel_size[1] = 2.0 / p_settings.full_screen_size.y; + if (ssao_half_size) { + ssao.gather_push_constant.half_screen_pixel_size[0] *= 2.0; + ssao.gather_push_constant.half_screen_pixel_size[1] *= 2.0; + } + ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.75; + ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.75; float tan_half_fov_x = 1.0 / p_projection.columns[0][0]; float tan_half_fov_y = 1.0 / p_projection.columns[1][1]; ssao.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0; @@ -1066,9 +1075,6 @@ void SSEffects::generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORe ssao.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y; ssao.gather_push_constant.is_orthogonal = p_projection.is_orthogonal(); - ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.25; - ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.25; - ssao.gather_push_constant.radius = p_settings.radius; float radius_near_limit = (p_settings.radius * 1.2f); if (ssao_quality <= RS::ENV_SSAO_QUALITY_LOW) { @@ -1105,7 +1111,7 @@ void SSEffects::generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORe RD::Uniform u_depth_texture_view; u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u_depth_texture_view.binding = 0; - u_depth_texture_view.append_id(default_sampler); + u_depth_texture_view.append_id(ss_effects.mirror_sampler); u_depth_texture_view.append_id(depth_texture_view); RD::Uniform u_normal_buffer; diff --git a/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl index b1ff46dd3b..4f81e36c58 100644 --- a/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl @@ -161,17 +161,11 @@ void prepare_depths_and_mips(vec4 p_samples, uvec2 p_output_coord, uvec2 p_gtid) still_alive = p_gtid.x % 16 == depth_array_offset.x && depth_array_offset.y % 16 == depth_array_offset.y; p_output_coord /= 2; - groupMemoryBarrier(); - barrier(); if (still_alive) { + // Use the previous average, not ideal, but still not bad. float sample_00 = depth_buffer[depth_array_index][buffer_coord.x + 0][buffer_coord.y + 0]; - float sample_01 = depth_buffer[depth_array_index][buffer_coord.x + 0][buffer_coord.y + 8]; - float sample_10 = depth_buffer[depth_array_index][buffer_coord.x + 8][buffer_coord.y + 0]; - float sample_11 = depth_buffer[depth_array_index][buffer_coord.x + 8][buffer_coord.y + 8]; - - float avg = mip_smart_average(vec4(sample_00, sample_01, sample_10, sample_11)); - imageStore(dest_image4, ivec3(p_output_coord.x, p_output_coord.y, depth_array_index), vec4(avg)); + imageStore(dest_image4, ivec3(p_output_coord.x, p_output_coord.y, depth_array_index), vec4(sample_00)); } #endif } @@ -190,6 +184,7 @@ void prepare_depths(vec4 p_samples, uvec2 p_tid) { void main() { #ifdef USE_HALF_BUFFERS +// Half buffers means that we divide depth into two half res buffers (we only capture 1/4 of pixels). #ifdef USE_HALF_SIZE float sample_00 = texelFetch(source_depth, ivec2(4 * gl_GlobalInvocationID.x + 0, 4 * gl_GlobalInvocationID.y + 0), 0).x; float sample_11 = texelFetch(source_depth, ivec2(4 * gl_GlobalInvocationID.x + 2, 4 * gl_GlobalInvocationID.y + 2), 0).x; @@ -219,11 +214,11 @@ void main() { vec2 uv = (vec2(depth_buffer_coord) + 0.5f) * params.pixel_size; vec4 samples = textureGather(source_depth, uv); -#endif +#endif //USE_HALF_SIZE #ifdef GENERATE_MIPS prepare_depths_and_mips(samples, output_coord, gl_LocalInvocationID.xy); #else prepare_depths(samples, gl_GlobalInvocationID.xy); #endif -#endif +#endif //USE_HALF_BUFFERS } diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index a727e83513..940363a7e8 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -8780,7 +8780,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f --texture_uniforms; --texture_binding; if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") { - _set_error(RTR("'hint_normal_roughness_texture is not supported in gl_compatibility shaders.")); + _set_error(RTR("'hint_normal_roughness_texture' is not supported in gl_compatibility shaders.")); return ERR_PARSE_ERROR; } } break; diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 05b1a8f87a..3d0443b494 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -2856,8 +2856,8 @@ RenderingServer::RenderingServer() { } void RenderingServer::init() { - GLOBAL_DEF_RST("rendering/textures/vram_compression/import_s3tc_bptc", OS::get_singleton()->get_preferred_texture_format() == OS::PREFERRED_TEXTURE_FORMAT_S3TC_BPTC); - GLOBAL_DEF_RST("rendering/textures/vram_compression/import_etc2_astc", OS::get_singleton()->get_preferred_texture_format() == OS::PREFERRED_TEXTURE_FORMAT_ETC2_ASTC); + GLOBAL_DEF_RST_NOVAL_BASIC("rendering/textures/vram_compression/import_s3tc_bptc", OS::get_singleton()->get_preferred_texture_format() == OS::PREFERRED_TEXTURE_FORMAT_S3TC_BPTC); + GLOBAL_DEF_RST_NOVAL_BASIC("rendering/textures/vram_compression/import_etc2_astc", OS::get_singleton()->get_preferred_texture_format() == OS::PREFERRED_TEXTURE_FORMAT_ETC2_ASTC); GLOBAL_DEF("rendering/textures/lossless_compression/force_png", false); diff --git a/thirdparty/basis_universal/encoder/basisu_comp.cpp b/thirdparty/basis_universal/encoder/basisu_comp.cpp index 41eae2b78a..4e69e9e2ee 100644 --- a/thirdparty/basis_universal/encoder/basisu_comp.cpp +++ b/thirdparty/basis_universal/encoder/basisu_comp.cpp @@ -28,7 +28,7 @@ #endif #if BASISD_SUPPORT_KTX2_ZSTD -#include "../zstd/zstd.h" +#include <zstd.h> #endif // Set to 1 to disable the mipPadding alignment workaround (which only seems to be needed when no key-values are written at all) diff --git a/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp b/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp index 3aeba0ee7a..c698861f3b 100644 --- a/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp +++ b/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp @@ -155,7 +155,7 @@ // If BASISD_SUPPORT_KTX2_ZSTD is 0, UASTC files compressed with Zstd cannot be loaded. #if BASISD_SUPPORT_KTX2_ZSTD // We only use two Zstd API's: ZSTD_decompress() and ZSTD_isError() - #include "../zstd/zstd.h" + #include <zstd.h> #endif #endif |