summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/io/image.cpp2
-rw-r--r--core/io/marshalls.cpp6
-rw-r--r--doc/classes/ConcavePolygonShape2D.xml2
-rw-r--r--doc/classes/ConcavePolygonShape3D.xml2
-rw-r--r--doc/classes/Dictionary.xml36
-rw-r--r--doc/classes/GPUParticles2D.xml2
-rw-r--r--doc/classes/GPUParticles3D.xml2
-rw-r--r--doc/classes/ImporterMesh.xml2
-rw-r--r--doc/classes/Mesh.xml3
-rw-r--r--doc/classes/Node.xml2
-rw-r--r--doc/classes/ProjectSettings.xml36
-rw-r--r--doc/classes/RenderingServer.xml2
-rw-r--r--doc/classes/Resource.xml1
-rw-r--r--doc/classes/RichTextLabel.xml4
-rw-r--r--doc/classes/Time.xml4
-rw-r--r--drivers/gles3/shader_gles3.cpp12
-rw-r--r--drivers/gles3/storage/config.cpp2
-rw-r--r--drivers/gles3/storage/particles_storage.h2
-rw-r--r--drivers/gles3/storage/utilities.cpp6
-rw-r--r--drivers/unix/os_unix.cpp8
-rw-r--r--drivers/vulkan/vulkan_context.cpp16
-rw-r--r--editor/animation_track_editor.cpp7
-rw-r--r--editor/code_editor.cpp50
-rw-r--r--editor/code_editor.h2
-rw-r--r--editor/editor_node.cpp42
-rw-r--r--editor/editor_node.h4
-rw-r--r--editor/export/project_export.cpp15
-rw-r--r--editor/export/project_export.h1
-rw-r--r--editor/filesystem_dock.cpp4
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp79
-rw-r--r--editor/plugins/animation_player_editor_plugin.h13
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp41
-rw-r--r--editor/plugins/node_3d_editor_plugin.h6
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp47
-rw-r--r--main/main.cpp27
-rw-r--r--modules/csg/csg_shape.cpp5
-rw-r--r--modules/gdscript/SCsub2
-rw-r--r--modules/gltf/gltf_document.cpp8
-rw-r--r--modules/mono/csharp_script.cpp4
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs6
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp6
-rw-r--r--modules/noise/noise.cpp3
-rw-r--r--modules/text_server_adv/text_server_adv.h6
-rw-r--r--platform/android/java/app/AndroidManifest.xml2
-rw-r--r--platform/macos/display_server_macos.mm25
-rw-r--r--scene/3d/bone_attachment_3d.cpp10
-rw-r--r--scene/3d/bone_attachment_3d.h4
-rw-r--r--scene/3d/soft_body_3d.cpp1
-rw-r--r--scene/gui/rich_text_label.cpp27
-rw-r--r--scene/resources/mesh.cpp2
-rw-r--r--scene/resources/particle_process_material.cpp43
-rw-r--r--scene/resources/particle_process_material.h4
-rw-r--r--scene/resources/primitive_meshes.cpp35
-rw-r--r--scene/resources/theme.cpp5
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_raster.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl6
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl6
-rw-r--r--servers/rendering/shader_compiler.cpp6
-rw-r--r--servers/rendering_server.cpp41
-rw-r--r--servers/rendering_server.h2
-rw-r--r--thirdparty/README.md6
-rw-r--r--thirdparty/mbedtls/library/entropy_poll.c32
-rw-r--r--thirdparty/mbedtls/patches/windows-entropy-bcrypt.diff56
63 files changed, 552 insertions, 293 deletions
diff --git a/core/io/image.cpp b/core/io/image.cpp
index 15d0182dfc..ce08b417a8 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -3773,7 +3773,7 @@ void Image::fix_alpha_edges() {
}
int closest_dist = max_dist;
- uint8_t closest_color[3];
+ uint8_t closest_color[3] = { 0 };
int from_x = MAX(0, j - max_radius);
int to_x = MIN(width - 1, j + max_radius);
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index 79e4b207d4..3d384d9345 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -1621,8 +1621,10 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
encode_uint32(datalen, buf);
buf += 4;
const uint8_t *r = data.ptr();
- memcpy(buf, &r[0], datalen * datasize);
- buf += datalen * datasize;
+ if (r) {
+ memcpy(buf, &r[0], datalen * datasize);
+ buf += datalen * datasize;
+ }
}
r_len += 4 + datalen * datasize;
diff --git a/doc/classes/ConcavePolygonShape2D.xml b/doc/classes/ConcavePolygonShape2D.xml
index 31e28bc714..6baf0f380f 100644
--- a/doc/classes/ConcavePolygonShape2D.xml
+++ b/doc/classes/ConcavePolygonShape2D.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
A 2D polyline shape, intended for use in physics. Used internally in [CollisionPolygon2D] when it's in [constant CollisionPolygon2D.BUILD_SEGMENTS] mode.
- Being just a collection of interconnected line segments, [ConcavePolygonShape2D] is the most freely configurable single 2D shape. It can be used to form polygons of any nature, or even shapes that don't enclose an area. However, [ConvexPolygonShape2D] is [i]hollow[/i] even if the interconnected line segments do enclose an area, which often makes it unsuitable for physics or detection.
+ Being just a collection of interconnected line segments, [ConcavePolygonShape2D] is the most freely configurable single 2D shape. It can be used to form polygons of any nature, or even shapes that don't enclose an area. However, [ConcavePolygonShape2D] is [i]hollow[/i] even if the interconnected line segments do enclose an area, which often makes it unsuitable for physics or detection.
[b]Note:[/b] When used for collision, [ConcavePolygonShape2D] is intended to work with static [CollisionShape2D] nodes like [StaticBody2D] and will likely not behave well for [CharacterBody2D]s or [RigidBody2D]s in a mode other than Static.
[b]Warning:[/b] Physics bodies that are small have a chance to clip through this shape when moving fast. This happens because on one frame, the physics body may be on the "outside" of the shape, and on the next frame it may be "inside" it. [ConcavePolygonShape2D] is hollow, so it won't detect a collision.
[b]Performance:[/b] Due to its complexity, [ConcavePolygonShape2D] is the slowest 2D collision shape to check collisions against. Its use should generally be limited to level geometry. If the polyline is closed, [CollisionPolygon2D]'s [constant CollisionPolygon2D.BUILD_SOLIDS] mode can be used, which decomposes the polygon into convex ones; see [ConvexPolygonShape2D]'s documentation for instructions.
diff --git a/doc/classes/ConcavePolygonShape3D.xml b/doc/classes/ConcavePolygonShape3D.xml
index c0d0f43010..7e4df2073f 100644
--- a/doc/classes/ConcavePolygonShape3D.xml
+++ b/doc/classes/ConcavePolygonShape3D.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
A 3D trimesh shape, intended for use in physics. Usually used to provide a shape for a [CollisionShape3D].
- Being just a collection of interconnected triangles, [ConcavePolygonShape3D] is the most freely configurable single 3D shape. It can be used to form polyhedra of any nature, or even shapes that don't enclose a volume. However, [ConvexPolygonShape3D] is [i]hollow[/i] even if the interconnected triangles do enclose a volume, which often makes it unsuitable for physics or detection.
+ Being just a collection of interconnected triangles, [ConcavePolygonShape3D] is the most freely configurable single 3D shape. It can be used to form polyhedra of any nature, or even shapes that don't enclose a volume. However, [ConcavePolygonShape3D] is [i]hollow[/i] even if the interconnected triangles do enclose a volume, which often makes it unsuitable for physics or detection.
[b]Note:[/b] When used for collision, [ConcavePolygonShape3D] is intended to work with static [CollisionShape3D] nodes like [StaticBody3D] and will likely not behave well for [CharacterBody3D]s or [RigidBody3D]s in a mode other than Static.
[b]Warning:[/b] Physics bodies that are small have a chance to clip through this shape when moving fast. This happens because on one frame, the physics body may be on the "outside" of the shape, and on the next frame it may be "inside" it. [ConcavePolygonShape3D] is hollow, so it won't detect a collision.
[b]Performance:[/b] Due to its complexity, [ConcavePolygonShape3D] is the slowest 3D collision shape to check collisions against. Its use should generally be limited to level geometry. For convex geometry, [ConvexPolygonShape3D] should be used. For dynamic physics bodies that need concave collision, several [ConvexPolygonShape3D]s can be used to represent its collision by using convex decomposition; see [ConvexPolygonShape3D]'s documentation for instructions.
diff --git a/doc/classes/Dictionary.xml b/doc/classes/Dictionary.xml
index b39c5c9699..955d80fcb7 100644
--- a/doc/classes/Dictionary.xml
+++ b/doc/classes/Dictionary.xml
@@ -294,6 +294,42 @@
<param index="1" name="overwrite" type="bool" default="false" />
<description>
Adds entries from [param dictionary] to this dictionary. By default, duplicate keys are not copied over, unless [param overwrite] is [code]true[/code].
+ [codeblocks]
+ [gdscript]
+ var dict = { "item": "sword", "quantity": 2 }
+ var other_dict = { "quantity": 15, "color": "silver" }
+
+ # Overwriting of existing keys is disabled by default.
+ dict.merge(other_dict)
+ print(dict) # { "item": "sword", "quantity": 2, "color": "silver" }
+
+ # With overwriting of existing keys enabled.
+ dict.merge(other_dict, true)
+ print(dict) # { "item": "sword", "quantity": 15, "color": "silver" }
+ [/gdscript]
+ [csharp]
+ var dict = new Godot.Collections.Dictionary
+ {
+ ["item"] = "sword",
+ ["quantity"] = 2,
+ };
+
+ var otherDict = new Godot.Collections.Dictionary
+ {
+ ["quantity"] = 15,
+ ["color"] = "silver",
+ };
+
+ // Overwriting of existing keys is disabled by default.
+ dict.Merge(otherDict);
+ GD.Print(dict); // { "item": "sword", "quantity": 2, "color": "silver" }
+
+ // With overwriting of existing keys enabled.
+ dict.Merge(otherDict, true);
+ GD.Print(dict); // { "item": "sword", "quantity": 15, "color": "silver" }
+ [/csharp]
+ [/codeblocks]
+ [b]Note:[/b] [method merge] is [i]not[/i] recursive. Nested dictionaries are considered as keys that can be overwritten or not depending on the value of [param overwrite], but they will never be merged together.
</description>
</method>
<method name="size" qualifiers="const">
diff --git a/doc/classes/GPUParticles2D.xml b/doc/classes/GPUParticles2D.xml
index dd731c6c0f..08dc6a5331 100644
--- a/doc/classes/GPUParticles2D.xml
+++ b/doc/classes/GPUParticles2D.xml
@@ -76,7 +76,7 @@
</member>
<member name="interp_to_end" type="float" setter="set_interp_to_end" getter="get_interp_to_end" default="0.0">
Causes all the particles in this node to interpolate towards the end of their lifetime.
- [b]Note[/b]: This only works when used with a [ParticleProcessMaterial]. It needs to be manually implemented for custom process shaders.
+ [b]Note:[/b] This only works when used with a [ParticleProcessMaterial]. It needs to be manually implemented for custom process shaders.
</member>
<member name="interpolate" type="bool" setter="set_interpolate" getter="get_interpolate" default="true">
Enables particle interpolation, which makes the particle movement smoother when their [member fixed_fps] is lower than the screen refresh rate.
diff --git a/doc/classes/GPUParticles3D.xml b/doc/classes/GPUParticles3D.xml
index 398905ea13..a982c7e40e 100644
--- a/doc/classes/GPUParticles3D.xml
+++ b/doc/classes/GPUParticles3D.xml
@@ -107,7 +107,7 @@
</member>
<member name="interp_to_end" type="float" setter="set_interp_to_end" getter="get_interp_to_end" default="0.0">
Causes all the particles in this node to interpolate towards the end of their lifetime.
- [b]Note[/b]: This only works when used with a [ParticleProcessMaterial]. It needs to be manually implemented for custom process shaders.
+ [b]Note:[/b] This only works when used with a [ParticleProcessMaterial]. It needs to be manually implemented for custom process shaders.
</member>
<member name="interpolate" type="bool" setter="set_interpolate" getter="get_interpolate" default="true">
Enables particle interpolation, which makes the particle movement smoother when their [member fixed_fps] is lower than the screen refresh rate.
diff --git a/doc/classes/ImporterMesh.xml b/doc/classes/ImporterMesh.xml
index 657d5659f8..9bc1bf035e 100644
--- a/doc/classes/ImporterMesh.xml
+++ b/doc/classes/ImporterMesh.xml
@@ -92,7 +92,7 @@
<return type="Array" />
<param index="0" name="surface_idx" type="int" />
<description>
- Returns the arrays for the vertices, normals, uvs, etc. that make up the requested surface. See [method add_surface].
+ Returns the arrays for the vertices, normals, UVs, etc. that make up the requested surface. See [method add_surface].
</description>
</method>
<method name="get_surface_blend_shape_arrays" qualifiers="const">
diff --git a/doc/classes/Mesh.xml b/doc/classes/Mesh.xml
index 6f06628122..2b2dc63a33 100644
--- a/doc/classes/Mesh.xml
+++ b/doc/classes/Mesh.xml
@@ -366,6 +366,9 @@
<constant name="ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY" value="268435456" enum="ArrayFormat" is_bitfield="true">
Flag used to mark that the mesh intentionally contains no vertex array.
</constant>
+ <constant name="ARRAY_FLAG_COMPRESS_ATTRIBUTES" value="536870912" enum="ArrayFormat" is_bitfield="true">
+ Flag used to mark that a mesh is using compressed attributes (vertices, normals, tangents, UVs). When this form of compression is enabled, vertex positions will be packed into an RGBA16UNORM attribute and scaled in the vertex shader. The normal and tangent will be packed into an RG16UNORM representing an axis, and a 16-bit float stored in the A-channel of the vertex. UVs will use 16-bit normalized floats instead of full 32-bit signed floats. When using this compression mode you must use either vertices, normals, and tangents or only vertices. You cannot use normals without tangents. Importers will automatically enable this compression if they can.
+ </constant>
<constant name="BLEND_SHAPE_MODE_NORMALIZED" value="0" enum="BlendShapeMode">
Blend shapes are normalized.
</constant>
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml
index 98b71e32df..ecb05efa2d 100644
--- a/doc/classes/Node.xml
+++ b/doc/classes/Node.xml
@@ -1034,7 +1034,7 @@
Notification received every frame when the internal physics process flag is set (see [method set_physics_process_internal]).
</constant>
<constant name="NOTIFICATION_POST_ENTER_TREE" value="27">
- Notification received when the node is ready, just before [constant NOTIFICATION_READY] is received. Unlike the latter, it's sent every time the node enters tree, instead of only once.
+ Notification received when the node is ready, just before [constant NOTIFICATION_READY] is received. Unlike the latter, it's sent every time the node enters the tree, instead of only once.
</constant>
<constant name="NOTIFICATION_DISABLED" value="28">
Notification received when the node is disabled. See [constant PROCESS_MODE_DISABLED].
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index be8c99d7ed..d8efdb455b 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -569,6 +569,7 @@
</member>
<member name="debug/gdscript/warnings/untyped_declaration" type="int" setter="" getter="" default="0">
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when a variable or parameter has no static type, or if a function has no static return type.
+ [b]Note:[/b] This warning is recommended together with [member EditorSettings.text_editor/completion/add_type_hints] to help achieve type safety.
</member>
<member name="debug/gdscript/warnings/unused_local_constant" type="int" setter="" getter="" default="1">
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when a local constant is never used.
@@ -843,6 +844,9 @@
</member>
<member name="display/window/stretch/scale_mode" type="String" setter="" getter="" default="&quot;fractional&quot;">
The policy to use to determine the final scale factor for 2D elements. This affects how [member display/window/stretch/scale] is applied, in addition to the automatic scale factor determined by [member display/window/stretch/mode].
+ [b]"fractional"[/b]: The scale factor will not be modified.
+ [b]"integer"[/b]: The scale factor will be floored to an integer value, which means that the screen size will always be an integer multiple of the base viewport size. This provides a crisp pixel art appearance.
+ [b]Note:[/b] When using integer scaling with a stretch mode, resizing the window to be smaller than the base viewport size will clip the contents. Consider preventing that by setting [member Window.min_size] to the same value as the base viewport size defined in [member display/window/size/viewport_width] and [member display/window/size/viewport_height].
</member>
<member name="display/window/subwindows/embed_subwindows" type="bool" setter="" getter="" default="true">
If [code]true[/code] subwindows are embedded in the main window.
@@ -2364,33 +2368,39 @@
<member name="rendering/environment/volumetric_fog/volume_size" type="int" setter="" getter="" default="64">
Base size used to determine size of froxel buffer in the camera X-axis and Y-axis. The final size is scaled by the aspect ratio of the screen, so actual values may differ from what is set. Set a larger size for more detailed fog, set a smaller size for better performance.
</member>
- <member name="rendering/gl_compatibility/driver" type="String" setter="" getter="" default="&quot;opengl3&quot;">
+ <member name="rendering/gl_compatibility/driver" type="String" setter="" getter="">
Sets the driver to be used by the renderer when using the Compatibility renderer. This property can not be edited directly, instead, set the driver using the platform-specific overrides.
</member>
- <member name="rendering/gl_compatibility/driver.android" type="String" setter="" getter="" default="&quot;opengl3&quot;">
+ <member name="rendering/gl_compatibility/driver.android" type="String" setter="" getter="">
Android override for [member rendering/gl_compatibility/driver].
</member>
- <member name="rendering/gl_compatibility/driver.ios" type="String" setter="" getter="" default="&quot;opengl3&quot;">
+ <member name="rendering/gl_compatibility/driver.ios" type="String" setter="" getter="">
iOS override for [member rendering/gl_compatibility/driver].
</member>
- <member name="rendering/gl_compatibility/driver.linuxbsd" type="String" setter="" getter="" default="&quot;opengl3&quot;">
+ <member name="rendering/gl_compatibility/driver.linuxbsd" type="String" setter="" getter="">
LinuxBSD override for [member rendering/gl_compatibility/driver].
</member>
- <member name="rendering/gl_compatibility/driver.macos" type="String" setter="" getter="" default="&quot;opengl3&quot;">
+ <member name="rendering/gl_compatibility/driver.macos" type="String" setter="" getter="">
macOS override for [member rendering/gl_compatibility/driver].
</member>
- <member name="rendering/gl_compatibility/driver.web" type="String" setter="" getter="" default="&quot;opengl3&quot;">
+ <member name="rendering/gl_compatibility/driver.web" type="String" setter="" getter="">
Web override for [member rendering/gl_compatibility/driver].
</member>
- <member name="rendering/gl_compatibility/driver.windows" type="String" setter="" getter="" default="&quot;opengl3&quot;">
+ <member name="rendering/gl_compatibility/driver.windows" type="String" setter="" getter="">
Windows override for [member rendering/gl_compatibility/driver].
</member>
<member name="rendering/gl_compatibility/fallback_to_angle" type="bool" setter="" getter="" default="true">
If [code]true[/code], the compatibility renderer will fall back to ANGLE if native OpenGL is not supported or the device is listed in [member rendering/gl_compatibility/force_angle_on_devices].
+ [b]Note:[/b] This setting is implemented only on Windows.
+ </member>
+ <member name="rendering/gl_compatibility/fallback_to_native" type="bool" setter="" getter="" default="true">
+ If [code]true[/code], the compatibility renderer will fall back to native OpenGL if ANGLE over Metal is not supported.
+ [b]Note:[/b] This setting is implemented only on macOS.
</member>
<member name="rendering/gl_compatibility/force_angle_on_devices" type="Array" setter="" getter="" default="[]">
An [Array] of devices which should always use the ANGLE renderer.
Each entry is a [Dictionary] with the following keys: [code]vendor[/code] and [code]name[/code]. [code]name[/code] can be set to [code]*[/code] to add all devices with the specified [code]vendor[/code].
+ [b]Note:[/b] This setting is implemented only on Windows.
</member>
<member name="rendering/gl_compatibility/item_buffer_size" type="int" setter="" getter="" default="16384">
Maximum number of canvas items commands that can be drawn in a single viewport update. If more render commands are issued they will be ignored. Decreasing this limit may improve performance on bandwidth limited devices. Increase this limit if you find that not all objects are being drawn in a frame.
@@ -2601,22 +2611,22 @@
<member name="rendering/renderer/rendering_method.web" type="String" setter="" getter="" default="&quot;gl_compatibility&quot;">
Override for [member rendering/renderer/rendering_method] on web.
</member>
- <member name="rendering/rendering_device/driver" type="String" setter="" getter="" default="&quot;vulkan&quot;">
+ <member name="rendering/rendering_device/driver" type="String" setter="" getter="">
Sets the driver to be used by the renderer when using a RenderingDevice-based renderer like the clustered renderer or the mobile renderer. This property can not be edited directly, instead, set the driver using the platform-specific overrides.
</member>
- <member name="rendering/rendering_device/driver.android" type="String" setter="" getter="" default="&quot;vulkan&quot;">
+ <member name="rendering/rendering_device/driver.android" type="String" setter="" getter="">
Android override for [member rendering/rendering_device/driver].
</member>
- <member name="rendering/rendering_device/driver.ios" type="String" setter="" getter="" default="&quot;vulkan&quot;">
+ <member name="rendering/rendering_device/driver.ios" type="String" setter="" getter="">
iOS override for [member rendering/rendering_device/driver].
</member>
- <member name="rendering/rendering_device/driver.linuxbsd" type="String" setter="" getter="" default="&quot;vulkan&quot;">
+ <member name="rendering/rendering_device/driver.linuxbsd" type="String" setter="" getter="">
LinuxBSD override for [member rendering/rendering_device/driver].
</member>
- <member name="rendering/rendering_device/driver.macos" type="String" setter="" getter="" default="&quot;vulkan&quot;">
+ <member name="rendering/rendering_device/driver.macos" type="String" setter="" getter="">
macOS override for [member rendering/rendering_device/driver].
</member>
- <member name="rendering/rendering_device/driver.windows" type="String" setter="" getter="" default="&quot;vulkan&quot;">
+ <member name="rendering/rendering_device/driver.windows" type="String" setter="" getter="">
Windows override for [member rendering/rendering_device/driver].
</member>
<member name="rendering/rendering_device/pipeline_cache/save_chunk_size_mb" type="float" setter="" getter="" default="3.0">
diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml
index dd279206ab..e5409a6e8a 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -4226,7 +4226,7 @@
Flag used to mark that the mesh does not have a vertex array and instead will infer vertex positions in the shader using indices and other information.
</constant>
<constant name="ARRAY_FLAG_COMPRESS_ATTRIBUTES" value="536870912" enum="ArrayFormat" is_bitfield="true">
- Flag used to mark that a mesh is using compressed attributes (vertices, normals, tangents, uvs). When this form of compression is enabled, vertex positions will be packed into into an RGBA16UNORM attribute and scaled in the vertex shader. The normal and tangent will be packed into a RG16UNORM representing an axis, and an 16 bit float stored in the A-channel of the vertex. UVs will use 16-bit normalized floats instead of full 32 bit signed floats. When using this compression mode you must either use vertices, normals, and tangents or only vertices. You cannot use normals without tangents. Importers will automatically enable this compression if they can.
+ Flag used to mark that a mesh is using compressed attributes (vertices, normals, tangents, UVs). When this form of compression is enabled, vertex positions will be packed into an RGBA16UNORM attribute and scaled in the vertex shader. The normal and tangent will be packed into an RG16UNORM representing an axis, and a 16-bit float stored in the A-channel of the vertex. UVs will use 16-bit normalized floats instead of full 32-bit signed floats. When using this compression mode you must use either vertices, normals, and tangents or only vertices. You cannot use normals without tangents. Importers will automatically enable this compression if they can.
</constant>
<constant name="ARRAY_FLAG_FORMAT_VERSION_BASE" value="35" enum="ArrayFormat" is_bitfield="true">
Flag used to mark the start of the bits used to store the mesh version.
diff --git a/doc/classes/Resource.xml b/doc/classes/Resource.xml
index 75c258253d..c8146bb48f 100644
--- a/doc/classes/Resource.xml
+++ b/doc/classes/Resource.xml
@@ -92,6 +92,7 @@
</member>
<member name="resource_name" type="String" setter="set_name" getter="get_name" default="&quot;&quot;">
An optional name for this resource. When defined, its value is displayed to represent the resource in the Inspector dock. For built-in scripts, the name is displayed as part of the tab name in the script editor.
+ [b]Note:[/b] Some resource formats do not support resource names. You can still set the name in the editor or via code, but it will be lost when the resource is reloaded. For example, only built-in scripts can have a resource name, while scripts stored in separate files cannot.
</member>
<member name="resource_path" type="String" setter="set_path" getter="get_path" default="&quot;&quot;">
The unique path to this resource. If it has been saved to disk, the value will be its filepath. If the resource is exclusively contained within a scene, the value will be the [PackedScene]'s filepath, followed by a unique identifier.
diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml
index 405d189c54..c9a48e46b2 100644
--- a/doc/classes/RichTextLabel.xml
+++ b/doc/classes/RichTextLabel.xml
@@ -764,10 +764,10 @@
The vertical separation of elements in a table.
</theme_item>
<theme_item name="text_highlight_h_padding" data_type="constant" type="int" default="3">
- The horizontal padding around a highlighting and background color box.
+ The horizontal padding around boxes drawn by the [code][fgcolor][/code] and [code][bgcolor][/code] tags. This does not affect the appearance of text selection.
</theme_item>
<theme_item name="text_highlight_v_padding" data_type="constant" type="int" default="3">
- The vertical padding around a highlighting and background color box.
+ The vertical padding around boxes drawn by the [code][fgcolor][/code] and [code][bgcolor][/code] tags. This does not affect the appearance of text selection.
</theme_item>
<theme_item name="bold_font" data_type="font" type="Font">
The font used for bold text.
diff --git a/doc/classes/Time.xml b/doc/classes/Time.xml
index 9dc567562a..0313381ff0 100644
--- a/doc/classes/Time.xml
+++ b/doc/classes/Time.xml
@@ -152,7 +152,9 @@
<method name="get_time_zone_from_system" qualifiers="const">
<return type="Dictionary" />
<description>
- Returns the current time zone as a dictionary of keys: [code]bias[/code] and [code]name[/code]. The [code]bias[/code] value is the offset from UTC in minutes, since not all time zones are multiples of an hour from UTC.
+ Returns the current time zone as a dictionary of keys: [code]bias[/code] and [code]name[/code].
+ - [code]bias[/code] is the offset from UTC in minutes, since not all time zones are multiples of an hour from UTC.
+ - [code]name[/code] is localized according to the current user default UI language.
</description>
</method>
<method name="get_unix_time_from_datetime_dict" qualifiers="const">
diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp
index 0341f531d9..77b870f8b2 100644
--- a/drivers/gles3/shader_gles3.cpp
+++ b/drivers/gles3/shader_gles3.cpp
@@ -141,12 +141,12 @@ void ShaderGLES3::_setup(const char *p_vertex_code, const char *p_fragment_code,
tohash.append(p_fragment_code ? p_fragment_code : "");
tohash.append("[gl_implementation]");
- const char *vendor = (const char *)glGetString(GL_VENDOR);
- tohash.append(vendor ? vendor : "unknown");
- const char *renderer = (const char *)glGetString(GL_RENDERER);
- tohash.append(renderer ? renderer : "unknown");
- const char *version = (const char *)glGetString(GL_VERSION);
- tohash.append(version ? version : "unknown");
+ const String &vendor = String::utf8((const char *)glGetString(GL_VENDOR));
+ tohash.append(vendor.is_empty() ? "unknown" : vendor);
+ const String &renderer = String::utf8((const char *)glGetString(GL_RENDERER));
+ tohash.append(renderer.is_empty() ? "unknown" : renderer);
+ const String &version = String::utf8((const char *)glGetString(GL_VERSION));
+ tohash.append(version.is_empty() ? "unknown" : version);
base_sha256 = tohash.as_string().sha256_text();
}
diff --git a/drivers/gles3/storage/config.cpp b/drivers/gles3/storage/config.cpp
index be7555788a..4bf6165fe9 100644
--- a/drivers/gles3/storage/config.cpp
+++ b/drivers/gles3/storage/config.cpp
@@ -109,7 +109,7 @@ Config::Config() {
if (use_depth_prepass) {
String vendors = GLOBAL_GET("rendering/driver/depth_prepass/disable_for_vendors");
Vector<String> vendor_match = vendors.split(",");
- String renderer = (const char *)glGetString(GL_RENDERER);
+ const String &renderer = String::utf8((const char *)glGetString(GL_RENDERER));
for (int i = 0; i < vendor_match.size(); i++) {
String v = vendor_match[i].strip_edges();
if (v == String()) {
diff --git a/drivers/gles3/storage/particles_storage.h b/drivers/gles3/storage/particles_storage.h
index 8451986a61..ca347ed070 100644
--- a/drivers/gles3/storage/particles_storage.h
+++ b/drivers/gles3/storage/particles_storage.h
@@ -233,7 +233,7 @@ private:
Transform3D emission_transform;
Vector3 emitter_velocity;
- float interp_to_end;
+ float interp_to_end = 0.0;
HashSet<RID> collisions;
diff --git a/drivers/gles3/storage/utilities.cpp b/drivers/gles3/storage/utilities.cpp
index 7deeefc37d..72bcbe879c 100644
--- a/drivers/gles3/storage/utilities.cpp
+++ b/drivers/gles3/storage/utilities.cpp
@@ -372,13 +372,13 @@ uint64_t Utilities::get_rendering_info(RS::RenderingInfo p_info) {
}
String Utilities::get_video_adapter_name() const {
- const String rendering_device_name = (const char *)glGetString(GL_RENDERER);
+ const String rendering_device_name = String::utf8((const char *)glGetString(GL_RENDERER));
// NVIDIA suffixes all GPU model names with "/PCIe/SSE2" in OpenGL (but not Vulkan). This isn't necessary to display nowadays, so it can be trimmed.
return rendering_device_name.trim_suffix("/PCIe/SSE2");
}
String Utilities::get_video_adapter_vendor() const {
- const String rendering_device_vendor = (const char *)glGetString(GL_VENDOR);
+ const String rendering_device_vendor = String::utf8((const char *)glGetString(GL_VENDOR));
// NVIDIA suffixes its vendor name with " Corporation". This is neither necessary to process nor display.
return rendering_device_vendor.trim_suffix(" Corporation");
}
@@ -388,7 +388,7 @@ RenderingDevice::DeviceType Utilities::get_video_adapter_type() const {
}
String Utilities::get_video_adapter_api_version() const {
- return (const char *)glGetString(GL_VERSION);
+ return String::utf8((const char *)glGetString(GL_VERSION));
}
Size2i Utilities::get_maximum_viewport_size() const {
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 581daaca05..9a77930d75 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -85,6 +85,12 @@
#define RTLD_DEEPBIND 0
#endif
+#ifndef SANITIZERS_ENABLED
+#define GODOT_DLOPEN_MODE RTLD_NOW | RTLD_DEEPBIND
+#else
+#define GODOT_DLOPEN_MODE RTLD_NOW
+#endif
+
#if defined(MACOS_ENABLED) || (defined(__ANDROID_API__) && __ANDROID_API__ >= 28)
// Random location for getentropy. Fitting.
#include <sys/random.h>
@@ -650,7 +656,7 @@ Error OS_Unix::open_dynamic_library(const String p_path, void *&p_library_handle
path = get_executable_path().get_base_dir().path_join("../lib").path_join(p_path.get_file());
}
- p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW | RTLD_DEEPBIND);
+ p_library_handle = dlopen(path.utf8().get_data(), GODOT_DLOPEN_MODE);
ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror()));
if (r_resolved_path != nullptr) {
diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp
index 890fd7277f..7a397a170d 100644
--- a/drivers/vulkan/vulkan_context.cpp
+++ b/drivers/vulkan/vulkan_context.cpp
@@ -448,7 +448,7 @@ Error VulkanContext::_initialize_instance_extensions() {
}
#ifdef DEV_ENABLED
for (uint32_t i = 0; i < instance_extension_count; i++) {
- print_verbose(String("VULKAN: Found instance extension ") + String(instance_extensions[i].extensionName));
+ print_verbose(String("VULKAN: Found instance extension ") + String::utf8(instance_extensions[i].extensionName));
}
#endif
@@ -465,9 +465,9 @@ Error VulkanContext::_initialize_instance_extensions() {
if (!enabled_instance_extension_names.has(requested_extension.key)) {
if (requested_extension.value) {
free(instance_extensions);
- ERR_FAIL_V_MSG(ERR_BUG, String("Required extension ") + String(requested_extension.key) + String(" not found, is a driver installed?"));
+ ERR_FAIL_V_MSG(ERR_BUG, String("Required extension ") + String::utf8(requested_extension.key) + String(" not found, is a driver installed?"));
} else {
- print_verbose(String("Optional extension ") + String(requested_extension.key) + String(" not found"));
+ print_verbose(String("Optional extension ") + String::utf8(requested_extension.key) + String(" not found"));
}
}
}
@@ -546,7 +546,7 @@ Error VulkanContext::_initialize_device_extensions() {
#ifdef DEV_ENABLED
for (uint32_t i = 0; i < device_extension_count; i++) {
- print_verbose(String("VULKAN: Found device extension ") + String(device_extensions[i].extensionName));
+ print_verbose(String("VULKAN: Found device extension ") + String::utf8(device_extensions[i].extensionName));
}
#endif
@@ -564,9 +564,9 @@ Error VulkanContext::_initialize_device_extensions() {
if (requested_extension.value) {
free(device_extensions);
ERR_FAIL_V_MSG(ERR_BUG,
- String("vkEnumerateDeviceExtensionProperties failed to find the ") + String(requested_extension.key) + String(" extension.\n\nDo you have a compatible Vulkan installable client driver (ICD) installed?\nvkCreateInstance Failure"));
+ String("vkEnumerateDeviceExtensionProperties failed to find the ") + String::utf8(requested_extension.key) + String(" extension.\n\nDo you have a compatible Vulkan installable client driver (ICD) installed?\nvkCreateInstance Failure"));
} else {
- print_verbose(String("Optional extension ") + String(requested_extension.key) + String(" not found"));
+ print_verbose(String("Optional extension ") + String::utf8(requested_extension.key) + String(" not found"));
}
}
}
@@ -1248,7 +1248,7 @@ Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) {
}
}
}
- String name = props.deviceName;
+ String name = String::utf8(props.deviceName);
String vendor = "Unknown";
String dev_type;
switch (props.deviceType) {
@@ -1330,7 +1330,7 @@ Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) {
// Get identifier properties.
vkGetPhysicalDeviceProperties(gpu, &gpu_props);
- device_name = gpu_props.deviceName;
+ device_name = String::utf8(gpu_props.deviceName);
device_type = gpu_props.deviceType;
pipeline_cache_id = String::hex_encode_buffer(gpu_props.pipelineCacheUUID, VK_UUID_SIZE);
pipeline_cache_id += "-driver-" + itos(gpu_props.driverVersion);
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index a2011144ce..cf36a42be4 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -31,6 +31,7 @@
#include "animation_track_editor.h"
#include "animation_track_editor_plugins.h"
+#include "core/error/error_macros.h"
#include "core/input/input.h"
#include "editor/animation_bezier_editor.h"
#include "editor/editor_node.h"
@@ -4107,6 +4108,12 @@ PropertyInfo AnimationTrackEditor::_find_hint_for_track(int p_idx, NodePath &r_b
property_info_base = property_info_base.get_named(leftover_path[i], valid);
}
+ if (property_info_base.is_null()) {
+ WARN_PRINT(vformat("Could not determine track hint for '%s:%s' because its base property is null.",
+ String(path.get_concatenated_names()), String(path.get_concatenated_subnames())));
+ return PropertyInfo();
+ }
+
List<PropertyInfo> pinfo;
property_info_base.get_property_list(&pinfo);
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 1842e8c1c4..9a10766900 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -141,6 +141,20 @@ void FindReplaceBar::_focus_lost() {
}
}
+void FindReplaceBar::_update_flags(bool p_direction_backwards) {
+ flags = 0;
+
+ if (is_whole_words()) {
+ flags |= TextEdit::SEARCH_WHOLE_WORDS;
+ }
+ if (is_case_sensitive()) {
+ flags |= TextEdit::SEARCH_MATCH_CASE;
+ }
+ if (p_direction_backwards) {
+ flags |= TextEdit::SEARCH_BACKWARDS;
+ }
+}
+
bool FindReplaceBar::_search(uint32_t p_flags, int p_from_line, int p_from_col) {
if (!preserve_cursor) {
text_editor->remove_secondary_carets();
@@ -431,14 +445,7 @@ void FindReplaceBar::_update_matches_label() {
}
bool FindReplaceBar::search_current() {
- flags = 0;
-
- if (is_whole_words()) {
- flags |= TextEdit::SEARCH_WHOLE_WORDS;
- }
- if (is_case_sensitive()) {
- flags |= TextEdit::SEARCH_MATCH_CASE;
- }
+ _update_flags(false);
int line, col;
_get_search_from(line, col);
@@ -455,17 +462,9 @@ bool FindReplaceBar::search_prev() {
popup_search(true);
}
- flags = 0;
String text = get_search_text();
- if (is_whole_words()) {
- flags |= TextEdit::SEARCH_WHOLE_WORDS;
- }
- if (is_case_sensitive()) {
- flags |= TextEdit::SEARCH_MATCH_CASE;
- }
-
- flags |= TextEdit::SEARCH_BACKWARDS;
+ _update_flags(true);
int line, col;
_get_search_from(line, col);
@@ -491,14 +490,7 @@ bool FindReplaceBar::search_next() {
popup_search(true);
}
- flags = 0;
-
- if (is_whole_words()) {
- flags |= TextEdit::SEARCH_WHOLE_WORDS;
- }
- if (is_case_sensitive()) {
- flags |= TextEdit::SEARCH_MATCH_CASE;
- }
+ _update_flags(false);
int line, col;
_get_search_from(line, col, true);
@@ -546,11 +538,9 @@ void FindReplaceBar::_show_search(bool p_focus_replace, bool p_show_only) {
search_text->set_caret_column(search_text->get_text().length());
}
- results_count = -1;
- results_count_to_current = -1;
- needs_to_count_results = true;
- _update_results_count();
- _update_matches_label();
+ preserve_cursor = true;
+ _search_text_changed(get_search_text());
+ preserve_cursor = false;
}
}
diff --git a/editor/code_editor.h b/editor/code_editor.h
index 911b7193f5..9d8a3a2229 100644
--- a/editor/code_editor.h
+++ b/editor/code_editor.h
@@ -110,6 +110,8 @@ protected:
virtual void unhandled_input(const Ref<InputEvent> &p_event) override;
void _focus_lost();
+ void _update_flags(bool p_direction_backwards);
+
bool _search(uint32_t p_flags, int p_from_line, int p_from_col);
void _replace();
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index f73eb81473..6d28b9abc8 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -47,6 +47,7 @@
#include "core/version.h"
#include "editor/editor_string_names.h"
#include "main/main.h"
+#include "scene/3d/bone_attachment_3d.h"
#include "scene/gui/color_picker.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/file_dialog.h"
@@ -314,6 +315,7 @@ void EditorNode::shortcut_input(const Ref<InputEvent> &p_event) {
if (ED_IS_SHORTCUT("editor/filter_files", p_event)) {
FileSystemDock::get_singleton()->focus_on_filter();
+ get_tree()->get_root()->set_input_as_handled();
}
if (ED_IS_SHORTCUT("editor/editor_2d", p_event)) {
@@ -825,12 +827,12 @@ void EditorNode::_on_plugin_ready(Object *p_script, const String &p_activate_nam
if (scr.is_null()) {
return;
}
- if (p_activate_name.length()) {
- set_addon_plugin_enabled(p_activate_name, true);
- }
project_settings_editor->update_plugins();
project_settings_editor->hide();
push_item(scr.operator->());
+ if (p_activate_name.length()) {
+ set_addon_plugin_enabled(p_activate_name, true);
+ }
}
void EditorNode::_remove_plugin_from_enabled(const String &p_name) {
@@ -2315,7 +2317,7 @@ void EditorNode::_edit_current(bool p_skip_foreign) {
}
// Update the use folding setting and state.
- bool disable_folding = bool(EDITOR_GET("interface/inspector/disable_folding"));
+ bool disable_folding = bool(EDITOR_GET("interface/inspector/disable_folding")) || current_obj->is_class("EditorDebuggerRemoteObject");
if (InspectorDock::get_inspector_singleton()->is_using_folding() == disable_folding) {
InspectorDock::get_inspector_singleton()->set_use_folding(!disable_folding, false);
}
@@ -2391,9 +2393,7 @@ void EditorNode::_edit_current(bool p_skip_foreign) {
} else {
Node *selected_node = nullptr;
- if (current_obj->is_class("EditorDebuggerRemoteObject")) {
- disable_folding = true;
- } else if (current_obj->is_class("MultiNodeEdit")) {
+ if (current_obj->is_class("MultiNodeEdit")) {
Node *scene = get_edited_scene();
if (scene) {
MultiNodeEdit *multi_node_edit = Object::cast_to<MultiNodeEdit>(current_obj);
@@ -6066,6 +6066,27 @@ void EditorNode::_file_access_close_error_notify_impl(const String &p_str) {
add_io_error(vformat(TTR("Unable to write to file '%s', file in use, locked or lacking permissions."), p_str));
}
+// Since we felt that a bespoke NOTIFICATION might not be desirable, this function
+// provides the hardcoded callbacks to address known bugs which occur on certain
+// nodes during reimport.
+// Ideally, we should probably agree on a standardized method name which could be
+// called from here instead.
+void EditorNode::_notify_scene_updated(Node *p_node) {
+ Skeleton3D *skel_3d = Object::cast_to<Skeleton3D>(p_node);
+ if (skel_3d) {
+ skel_3d->reset_bone_poses();
+ } else {
+ BoneAttachment3D *attachment = Object::cast_to<BoneAttachment3D>(p_node);
+ if (attachment) {
+ attachment->notify_rebind_required();
+ }
+ }
+
+ for (int i = 0; i < p_node->get_child_count(); i++) {
+ _notify_scene_updated(p_node->get_child(i));
+ }
+}
+
void EditorNode::reload_scene(const String &p_path) {
int scene_idx = -1;
for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
@@ -6449,10 +6470,11 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins
}
}
}
+
// Cleanup the history of the changes.
editor_history.cleanup_history();
- current_edited_scene->propagate_notification(NOTIFICATION_NODE_RECACHE_REQUESTED);
+ _notify_scene_updated(current_edited_scene);
}
edited_scene_map.clear();
}
@@ -7348,10 +7370,6 @@ EditorNode::EditorNode() {
project_menu->add_item(TTR("Customize Engine Build Configuration..."), TOOLS_BUILD_PROFILE_MANAGER);
project_menu->add_separator();
- plugin_config_dialog = memnew(PluginConfigDialog);
- plugin_config_dialog->connect("plugin_ready", callable_mp(this, &EditorNode::_on_plugin_ready));
- gui_base->add_child(plugin_config_dialog);
-
tool_menu = memnew(PopupMenu);
tool_menu->set_name("Tools");
tool_menu->connect("index_pressed", callable_mp(this, &EditorNode::_tool_menu_option));
diff --git a/editor/editor_node.h b/editor/editor_node.h
index bc7da69e75..b2fb03be6b 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -356,8 +356,6 @@ private:
uint64_t started_timestamp = 0;
- PluginConfigDialog *plugin_config_dialog = nullptr;
-
RichTextLabel *load_errors = nullptr;
AcceptDialog *load_error_dialog = nullptr;
@@ -692,6 +690,8 @@ private:
void _begin_first_scan();
+ void _notify_scene_updated(Node *p_node);
+
protected:
friend class FileSystemDock;
diff --git a/editor/export/project_export.cpp b/editor/export/project_export.cpp
index 58e4dc1069..05f012e5fb 100644
--- a/editor/export/project_export.cpp
+++ b/editor/export/project_export.cpp
@@ -281,7 +281,7 @@ void ProjectExportDialog::_edit_preset(int p_index) {
export_filter->select(current->get_export_filter());
include_filters->set_text(current->get_include_filter());
- include_label->set_text(current->get_export_filter() == EditorExportPreset::EXCLUDE_SELECTED_RESOURCES ? TTR("Resources to exclude:") : TTR("Resources to export:"));
+ include_label->set_text(_get_resource_export_header(current->get_export_filter()));
exclude_filters->set_text(current->get_exclude_filter());
server_strip_message->set_visible(current->get_export_filter() == EditorExportPreset::EXPORT_CUSTOMIZED);
@@ -750,13 +750,24 @@ void ProjectExportDialog::_export_type_changed(int p_which) {
if (filter_type == EditorExportPreset::EXPORT_CUSTOMIZED && current->get_customized_files_count() == 0) {
current->set_file_export_mode("res://", EditorExportPreset::MODE_FILE_STRIP);
}
- include_label->set_text(current->get_export_filter() == EditorExportPreset::EXCLUDE_SELECTED_RESOURCES ? TTR("Resources to exclude:") : TTR("Resources to export:"));
+ include_label->set_text(_get_resource_export_header(current->get_export_filter()));
updating = true;
_fill_resource_tree();
updating = false;
}
+String ProjectExportDialog::_get_resource_export_header(EditorExportPreset::ExportFilter p_filter) const {
+ switch (p_filter) {
+ case EditorExportPreset::EXCLUDE_SELECTED_RESOURCES:
+ return TTR("Resources to exclude:");
+ case EditorExportPreset::EXPORT_CUSTOMIZED:
+ return TTR("Resources to override export behavior:");
+ default:
+ return TTR("Resources to export:");
+ }
+}
+
void ProjectExportDialog::_filter_changed(const String &p_filter) {
if (updating) {
return;
diff --git a/editor/export/project_export.h b/editor/export/project_export.h
index 4f76167e22..219f45f59b 100644
--- a/editor/export/project_export.h
+++ b/editor/export/project_export.h
@@ -135,6 +135,7 @@ private:
void _export_type_changed(int p_which);
void _filter_changed(const String &p_filter);
+ String _get_resource_export_header(EditorExportPreset::ExportFilter p_filter) const;
void _fill_resource_tree();
void _setup_item_for_file_mode(TreeItem *p_item, EditorExportPreset::FileExportMode p_mode);
bool _fill_tree(EditorFileSystemDirectory *p_dir, TreeItem *p_item, Ref<EditorExportPreset> &current, EditorExportPreset::ExportFilter p_export_filter);
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index ea043b42d1..0aa8ef66e7 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -1790,7 +1790,9 @@ void FileSystemDock::_rename_operation_confirm() {
}
if (new_exist) {
EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists."));
- ti->set_text(col_index, old_name);
+ if (ti) {
+ ti->set_text(col_index, old_name);
+ }
return;
}
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 440496b948..09481ce48b 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -653,26 +653,23 @@ void AnimationPlayerEditor::_blend_editor_next_changed(const int p_idx) {
undo_redo->commit_action();
}
-void AnimationPlayerEditor::_animation_blend() {
- if (updating_blends) {
+void AnimationPlayerEditor::_edit_animation_blend() {
+ if (updating_blends || !animation->has_selectable_items()) {
return;
}
- blend_editor.tree->clear();
+ blend_editor.dialog->popup_centered(Size2(400, 400) * EDSCALE);
+ _update_animation_blend();
+}
- if (!animation->has_selectable_items()) {
+void AnimationPlayerEditor::_update_animation_blend() {
+ if (updating_blends || !animation->has_selectable_items()) {
return;
}
- String current = animation->get_item_text(animation->get_selected());
-
- blend_editor.dialog->popup_centered(Size2(400, 400) * EDSCALE);
+ blend_editor.tree->clear();
- blend_editor.tree->set_hide_root(true);
- blend_editor.tree->set_column_expand_ratio(0, 10);
- blend_editor.tree->set_column_clip_content(0, true);
- blend_editor.tree->set_column_expand_ratio(1, 3);
- blend_editor.tree->set_column_clip_content(1, true);
+ String current = animation->get_item_text(animation->get_selected());
List<StringName> anims;
player->get_animation_list(&anims);
@@ -711,21 +708,17 @@ void AnimationPlayerEditor::_animation_blend() {
}
void AnimationPlayerEditor::_blend_edited() {
- if (updating_blends) {
+ if (updating_blends || !animation->has_selectable_items()) {
return;
}
- if (!animation->has_selectable_items()) {
- return;
- }
-
- String current = animation->get_item_text(animation->get_selected());
-
TreeItem *selected = blend_editor.tree->get_edited();
if (!selected) {
return;
}
+ String current = animation->get_item_text(animation->get_selected());
+
updating_blends = true;
String to = selected->get_text(0);
float blend_time = selected->get_range(1);
@@ -1265,7 +1258,9 @@ void AnimationPlayerEditor::_seek_value_changed(float p_value, bool p_set, bool
player->seek(pos, true, true);
player->seek(pos + delta, true, true);
} else {
- player->stop();
+ if (player->is_playing()) {
+ player->stop();
+ }
player->seek(pos, true, true);
}
}
@@ -1275,9 +1270,11 @@ void AnimationPlayerEditor::_seek_value_changed(float p_value, bool p_set, bool
void AnimationPlayerEditor::_animation_player_changed(Object *p_pl) {
_update_player();
+
if (blend_editor.dialog->is_visible()) {
- _animation_blend(); // Update.
+ _update_animation_blend(); // Update.
}
+
if (library_editor->is_visible()) {
library_editor->update_tree();
}
@@ -1364,7 +1361,7 @@ void AnimationPlayerEditor::_animation_tool_menu(int p_option) {
_animation_rename();
} break;
case TOOL_EDIT_TRANSITIONS: {
- _animation_blend();
+ _edit_animation_blend();
} break;
case TOOL_REMOVE_ANIM: {
_animation_remove();
@@ -1800,17 +1797,8 @@ bool AnimationPlayerEditor::_validate_tracks(const Ref<Animation> p_anim) {
}
void AnimationPlayerEditor::_bind_methods() {
- ClassDB::bind_method(D_METHOD("_animation_new"), &AnimationPlayerEditor::_animation_new);
- ClassDB::bind_method(D_METHOD("_animation_rename"), &AnimationPlayerEditor::_animation_rename);
- ClassDB::bind_method(D_METHOD("_animation_remove"), &AnimationPlayerEditor::_animation_remove);
- ClassDB::bind_method(D_METHOD("_animation_blend"), &AnimationPlayerEditor::_animation_blend);
- ClassDB::bind_method(D_METHOD("_animation_edit"), &AnimationPlayerEditor::_animation_edit);
- ClassDB::bind_method(D_METHOD("_animation_resource_edit"), &AnimationPlayerEditor::_animation_resource_edit);
+ // Needed for UndoRedo.
ClassDB::bind_method(D_METHOD("_animation_player_changed"), &AnimationPlayerEditor::_animation_player_changed);
- ClassDB::bind_method(D_METHOD("_animation_libraries_updated"), &AnimationPlayerEditor::_animation_libraries_updated);
- ClassDB::bind_method(D_METHOD("_list_changed"), &AnimationPlayerEditor::_list_changed);
- ClassDB::bind_method(D_METHOD("_animation_duplicate"), &AnimationPlayerEditor::_animation_duplicate);
-
ClassDB::bind_method(D_METHOD("_start_onion_skinning"), &AnimationPlayerEditor::_start_onion_skinning);
ClassDB::bind_method(D_METHOD("_stop_onion_skinning"), &AnimationPlayerEditor::_stop_onion_skinning);
@@ -1831,11 +1819,8 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug
plugin = p_plugin;
singleton = this;
- updating = false;
-
set_focus_mode(FOCUS_ALL);
-
- player = nullptr;
+ set_process_shortcut_input(true);
HBoxContainer *hb = memnew(HBoxContainer);
add_child(hb);
@@ -1919,7 +1904,6 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug
hb->add_child(memnew(VSeparator));
track_editor = memnew(AnimationTrackEditor);
-
hb->add_child(track_editor->get_edit_menu());
hb->add_child(memnew(VSeparator));
@@ -1990,21 +1974,27 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug
name_dialog->connect(SNAME("confirmed"), callable_mp(this, &AnimationPlayerEditor::_animation_name_edited));
blend_editor.dialog = memnew(AcceptDialog);
- add_child(blend_editor.dialog);
+ blend_editor.dialog->set_title(TTR("Cross-Animation Blend Times"));
blend_editor.dialog->set_ok_button_text(TTR("Close"));
blend_editor.dialog->set_hide_on_ok(true);
+ add_child(blend_editor.dialog);
+
VBoxContainer *blend_vb = memnew(VBoxContainer);
blend_editor.dialog->add_child(blend_vb);
+
blend_editor.tree = memnew(Tree);
+ blend_editor.tree->set_hide_root(true);
blend_editor.tree->set_columns(2);
+ blend_editor.tree->set_column_expand_ratio(0, 10);
+ blend_editor.tree->set_column_clip_content(0, true);
+ blend_editor.tree->set_column_expand_ratio(1, 3);
+ blend_editor.tree->set_column_clip_content(1, true);
blend_vb->add_margin_child(TTR("Blend Times:"), blend_editor.tree, true);
+ blend_editor.tree->connect(SNAME("item_edited"), callable_mp(this, &AnimationPlayerEditor::_blend_edited));
+
blend_editor.next = memnew(OptionButton);
blend_editor.next->set_auto_translate(false);
blend_vb->add_margin_child(TTR("Next (Auto Queue):"), blend_editor.next);
- blend_editor.dialog->set_title(TTR("Cross-Animation Blend Times"));
- updating_blends = false;
-
- blend_editor.tree->connect(SNAME("item_edited"), callable_mp(this, &AnimationPlayerEditor::_blend_edited));
autoplay->connect(SNAME("pressed"), callable_mp(this, &AnimationPlayerEditor::_autoplay_pressed));
autoplay->set_toggle_mode(true);
@@ -2019,11 +2009,6 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug
frame->connect(SNAME("value_changed"), callable_mp(this, &AnimationPlayerEditor::_seek_value_changed).bind(true, false));
scale->connect(SNAME("text_submitted"), callable_mp(this, &AnimationPlayerEditor::_scale_changed));
- last_active = false;
- timeline_position = 0;
-
- set_process_shortcut_input(true);
-
add_child(track_editor);
track_editor->set_v_size_flags(SIZE_EXPAND_FILL);
track_editor->connect(SNAME("timeline_changed"), callable_mp(this, &AnimationPlayerEditor::_animation_key_editor_seek));
diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h
index 6751933839..3db9ac2a54 100644
--- a/editor/plugins/animation_player_editor_plugin.h
+++ b/editor/plugins/animation_player_editor_plugin.h
@@ -111,8 +111,9 @@ class AnimationPlayerEditor : public VBoxContainer {
Ref<Texture2D> autoplay_icon;
Ref<Texture2D> reset_icon;
Ref<ImageTexture> autoplay_reset_icon;
- bool last_active;
- float timeline_position;
+
+ bool last_active = false;
+ float timeline_position = 0;
EditorFileDialog *file = nullptr;
ConfirmationDialog *delete_dialog = nullptr;
@@ -130,8 +131,8 @@ class AnimationPlayerEditor : public VBoxContainer {
ConfirmationDialog *error_dialog = nullptr;
int name_dialog_op = TOOL_NEW_ANIM;
- bool updating;
- bool updating_blends;
+ bool updating = false;
+ bool updating_blends = false;
AnimationTrackEditor *track_editor = nullptr;
static AnimationPlayerEditor *singleton;
@@ -190,7 +191,6 @@ class AnimationPlayerEditor : public VBoxContainer {
void _animation_remove();
void _animation_remove_confirmed();
- void _animation_blend();
void _animation_edit();
void _animation_duplicate();
Ref<Animation> _animation_clone(const Ref<Animation> p_anim);
@@ -199,6 +199,9 @@ class AnimationPlayerEditor : public VBoxContainer {
void _seek_value_changed(float p_value, bool p_set = false, bool p_timeline_only = false);
void _blend_editor_next_changed(const int p_idx);
+ void _edit_animation_blend();
+ void _update_animation_blend();
+
void _list_changed();
void _current_animation_changed(const String &p_name);
void _update_animation();
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 792d9985aa..d465b9f27a 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -4882,8 +4882,7 @@ void Node3DEditorViewport::update_transform(bool p_shift) {
if (_edit.snap || spatial_editor->is_snap_enabled()) {
snap = spatial_editor->get_rotate_snap();
}
- angle = Math::rad_to_deg(angle) + snap * 0.5; //else it won't reach +180
- angle -= Math::fmod(angle, snap);
+ angle = Math::snapped(Math::rad_to_deg(angle), snap);
set_message(vformat(TTR("Rotating %s degrees."), String::num(angle, snap_step_decimals)));
angle = Math::deg_to_rad(angle);
@@ -5857,9 +5856,9 @@ Dictionary Node3DEditor::get_state() const {
Dictionary d;
d["snap_enabled"] = snap_enabled;
- d["translate_snap"] = get_translate_snap();
- d["rotate_snap"] = get_rotate_snap();
- d["scale_snap"] = get_scale_snap();
+ d["translate_snap"] = snap_translate_value;
+ d["rotate_snap"] = snap_rotate_value;
+ d["scale_snap"] = snap_scale_value;
d["local_coords"] = tool_option_button[TOOL_OPT_LOCAL_COORDS]->is_pressed();
@@ -8872,9 +8871,8 @@ void Node3DEditorPlugin::set_state(const Dictionary &p_state) {
Vector3 Node3DEditor::snap_point(Vector3 p_target, Vector3 p_start) const {
if (is_snap_enabled()) {
- p_target.x = Math::snap_scalar(0.0, get_translate_snap(), p_target.x);
- p_target.y = Math::snap_scalar(0.0, get_translate_snap(), p_target.y);
- p_target.z = Math::snap_scalar(0.0, get_translate_snap(), p_target.z);
+ real_t snap = get_translate_snap();
+ p_target.snap(Vector3(snap, snap, snap));
}
return p_target;
}
@@ -8886,36 +8884,27 @@ bool Node3DEditor::is_gizmo_visible() const {
return gizmo.visible;
}
-double Node3DEditor::get_translate_snap() const {
- double snap_value;
+real_t Node3DEditor::get_translate_snap() const {
+ real_t snap_value = snap_translate_value;
if (Input::get_singleton()->is_key_pressed(Key::SHIFT)) {
- snap_value = snap_translate->get_text().to_float() / 10.0;
- } else {
- snap_value = snap_translate->get_text().to_float();
+ snap_value /= 10.0f;
}
-
return snap_value;
}
-double Node3DEditor::get_rotate_snap() const {
- double snap_value;
+real_t Node3DEditor::get_rotate_snap() const {
+ real_t snap_value = snap_rotate_value;
if (Input::get_singleton()->is_key_pressed(Key::SHIFT)) {
- snap_value = snap_rotate->get_text().to_float() / 3.0;
- } else {
- snap_value = snap_rotate->get_text().to_float();
+ snap_value /= 3.0f;
}
-
return snap_value;
}
-double Node3DEditor::get_scale_snap() const {
- double snap_value;
+real_t Node3DEditor::get_scale_snap() const {
+ real_t snap_value = snap_scale_value;
if (Input::get_singleton()->is_key_pressed(Key::SHIFT)) {
- snap_value = snap_scale->get_text().to_float() / 2.0;
- } else {
- snap_value = snap_scale->get_text().to_float();
+ snap_value /= 2.0f;
}
-
return snap_value;
}
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index 8b066185c7..1ce09a2bcb 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -850,9 +850,9 @@ public:
bool are_local_coords_enabled() const { return tool_option_button[Node3DEditor::TOOL_OPT_LOCAL_COORDS]->is_pressed(); }
void set_local_coords_enabled(bool on) const { tool_option_button[Node3DEditor::TOOL_OPT_LOCAL_COORDS]->set_pressed(on); }
bool is_snap_enabled() const { return snap_enabled ^ snap_key_enabled; }
- double get_translate_snap() const;
- double get_rotate_snap() const;
- double get_scale_snap() const;
+ real_t get_translate_snap() const;
+ real_t get_rotate_snap() const;
+ real_t get_scale_snap() const;
Ref<ArrayMesh> get_move_gizmo(int idx) const { return move_gizmo[idx]; }
Ref<ArrayMesh> get_axis_gizmo(int idx) const { return axis_gizmo[idx]; }
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index f18585e9df..5e16361bae 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -63,6 +63,7 @@
#include "scene/resources/visual_shader_nodes.h"
#include "scene/resources/visual_shader_particle_nodes.h"
#include "servers/display_server.h"
+#include "servers/rendering/shader_preprocessor.h"
#include "servers/rendering/shader_types.h"
struct FloatConstantDef {
@@ -5094,20 +5095,52 @@ void VisualShaderEditor::_update_preview() {
info.shader_types = ShaderTypes::get_singleton()->get_types();
info.global_shader_uniform_type_func = _visual_shader_editor_get_global_shader_uniform_type;
- ShaderLanguage sl;
-
- Error err = sl.compile(code, info);
-
for (int i = 0; i < preview_text->get_line_count(); i++) {
preview_text->set_line_background_color(i, Color(0, 0, 0, 0));
}
+
+ String preprocessed_code;
+ {
+ String path = visual_shader->get_path();
+ String error_pp;
+ List<ShaderPreprocessor::FilePosition> err_positions;
+ ShaderPreprocessor preprocessor;
+ Error err = preprocessor.preprocess(code, path, preprocessed_code, &error_pp, &err_positions);
+ if (err != OK) {
+ ERR_FAIL_COND(err_positions.is_empty());
+
+ String file = err_positions.front()->get().file;
+ int err_line = err_positions.front()->get().line;
+ Color error_line_color = EDITOR_GET("text_editor/theme/highlighting/mark_color");
+ preview_text->set_line_background_color(err_line - 1, error_line_color);
+ error_panel->show();
+
+ error_label->set_text("error(" + file + ":" + itos(err_line) + "): " + error_pp);
+ shader_error = true;
+ return;
+ }
+ }
+
+ ShaderLanguage sl;
+ Error err = sl.compile(preprocessed_code, info);
if (err != OK) {
+ int err_line;
+ String err_text;
+ Vector<ShaderLanguage::FilePosition> include_positions = sl.get_include_positions();
+ if (include_positions.size() > 1) {
+ // Error is in an include.
+ err_line = include_positions[0].line;
+ err_text = "error(" + itos(err_line) + ") in include " + include_positions[include_positions.size() - 1].file + ":" + itos(include_positions[include_positions.size() - 1].line) + ": " + sl.get_error_text();
+ } else {
+ err_line = sl.get_error_line();
+ err_text = "error(" + itos(err_line) + "): " + sl.get_error_text();
+ }
+
Color error_line_color = EDITOR_GET("text_editor/theme/highlighting/mark_color");
- preview_text->set_line_background_color(sl.get_error_line() - 1, error_line_color);
+ preview_text->set_line_background_color(err_line - 1, error_line_color);
error_panel->show();
- String text = "error(" + itos(sl.get_error_line()) + "): " + sl.get_error_text();
- error_label->set_text(text);
+ error_label->set_text(err_text);
shader_error = true;
} else {
error_panel->hide();
diff --git a/main/main.cpp b/main/main.cpp
index dff661d207..7b46957904 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -1739,12 +1739,12 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
String default_driver = driver_hints.get_slice(",", 0);
// For now everything defaults to vulkan when available. This can change in future updates.
- GLOBAL_DEF_RST("rendering/rendering_device/driver", default_driver);
- GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.windows", PROPERTY_HINT_ENUM, driver_hints), default_driver);
- GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.linuxbsd", PROPERTY_HINT_ENUM, driver_hints), default_driver);
- GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.android", PROPERTY_HINT_ENUM, driver_hints), default_driver);
- GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.ios", PROPERTY_HINT_ENUM, driver_hints), default_driver);
- GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.macos", PROPERTY_HINT_ENUM, driver_hints), default_driver);
+ GLOBAL_DEF_RST_NOVAL("rendering/rendering_device/driver", default_driver);
+ GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.windows", PROPERTY_HINT_ENUM, driver_hints), default_driver);
+ GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.linuxbsd", PROPERTY_HINT_ENUM, driver_hints), default_driver);
+ GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.android", PROPERTY_HINT_ENUM, driver_hints), default_driver);
+ GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.ios", PROPERTY_HINT_ENUM, driver_hints), default_driver);
+ GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.macos", PROPERTY_HINT_ENUM, driver_hints), default_driver);
}
{
@@ -1763,16 +1763,17 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
default_driver_macos = "opengl3_angle"; // Default to ANGLE if it's built-in.
#endif
- GLOBAL_DEF_RST("rendering/gl_compatibility/driver", default_driver);
- GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.windows", PROPERTY_HINT_ENUM, driver_hints_angle), default_driver);
- GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.linuxbsd", PROPERTY_HINT_ENUM, driver_hints_egl), default_driver);
- GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.web", PROPERTY_HINT_ENUM, driver_hints), default_driver);
- GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.android", PROPERTY_HINT_ENUM, driver_hints), default_driver);
- GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.ios", PROPERTY_HINT_ENUM, driver_hints), default_driver);
- GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.macos", PROPERTY_HINT_ENUM, driver_hints_angle), default_driver_macos);
+ GLOBAL_DEF_RST_NOVAL("rendering/gl_compatibility/driver", default_driver);
+ GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.windows", PROPERTY_HINT_ENUM, driver_hints_angle), default_driver);
+ GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.linuxbsd", PROPERTY_HINT_ENUM, driver_hints_egl), default_driver);
+ GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.web", PROPERTY_HINT_ENUM, driver_hints), default_driver);
+ GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.android", PROPERTY_HINT_ENUM, driver_hints), default_driver);
+ GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.ios", PROPERTY_HINT_ENUM, driver_hints), default_driver);
+ GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.macos", PROPERTY_HINT_ENUM, driver_hints_angle), default_driver_macos);
GLOBAL_DEF_RST("rendering/gl_compatibility/nvidia_disable_threaded_optimization", true);
GLOBAL_DEF_RST("rendering/gl_compatibility/fallback_to_angle", true);
+ GLOBAL_DEF_RST("rendering/gl_compatibility/fallback_to_native", true);
GLOBAL_DEF_RST(PropertyInfo(Variant::ARRAY, "rendering/gl_compatibility/force_angle_on_devices", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::DICTIONARY, PROPERTY_HINT_NONE, String())), Array());
}
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index 0656f8224c..0fc61dfe92 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -573,6 +573,11 @@ void CSGShape3D::_notification(int p_what) {
// Update this node's parent only if its own visibility has changed, not the visibility of parent nodes
parent_shape->_make_dirty();
}
+ if (is_visible()) {
+ _update_debug_collision_shape();
+ } else {
+ _clear_debug_collision_shape();
+ }
last_visible = is_visible();
} break;
diff --git a/modules/gdscript/SCsub b/modules/gdscript/SCsub
index 1dc4768186..61accd4fc9 100644
--- a/modules/gdscript/SCsub
+++ b/modules/gdscript/SCsub
@@ -19,6 +19,8 @@ if env.editor_build:
# Using a define in the disabled case, to avoid having an extra define
# in regular builds where all modules are enabled.
env_gdscript.Append(CPPDEFINES=["GDSCRIPT_NO_LSP"])
+ # Also needed in main env to unexpose --lsp-port option.
+ env.Append(CPPDEFINES=["GDSCRIPT_NO_LSP"])
if env["tests"]:
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index 47fc58fe43..ecfb035b82 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -5846,6 +5846,10 @@ void GLTFDocument::_generate_scene_node(Ref<GLTFState> p_state, const GLTFNodeIn
BoneAttachment3D *bone_attachment = _generate_bone_attachment(p_state, active_skeleton, p_node_index, gltf_node->parent);
p_scene_parent->add_child(bone_attachment, true);
+
+ // Find the correct bone_idx so we can properly serialize it.
+ bone_attachment->set_bone_idx(active_skeleton->find_bone(gltf_node->get_name()));
+
bone_attachment->set_owner(p_scene_root);
// There is no gltf_node that represent this, so just directly create a unique name
@@ -5949,6 +5953,10 @@ void GLTFDocument::_generate_skeleton_bone_node(Ref<GLTFState> p_state, const GL
BoneAttachment3D *bone_attachment = _generate_bone_attachment(p_state, active_skeleton, p_node_index, p_node_index);
p_scene_parent->add_child(bone_attachment, true);
+
+ // Find the correct bone_idx so we can properly serialize it.
+ bone_attachment->set_bone_idx(active_skeleton->find_bone(gltf_node->get_name()));
+
bone_attachment->set_owner(p_scene_root);
// There is no gltf_node that represent this, so just directly create a unique name
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 44bcd4cfe4..3cc32bff10 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -142,6 +142,10 @@ void CSharpLanguage::finalize() {
return;
}
+ if (gdmono && gdmono->is_runtime_initialized() && GDMonoCache::godot_api_cache_updated) {
+ GDMonoCache::managed_callbacks.DisposablesTracker_OnGodotShuttingDown();
+ }
+
finalizing = true;
// Make sure all script binding gchandles are released before finalizing GDMono
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
index 413f6f0029..6bdf207873 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
@@ -626,6 +626,12 @@ namespace GodotTools
_editorSettings.SettingsChanged -= OnSettingsChanged;
}
+ public override void _ExitTree()
+ {
+ _errorDialog?.QueueFree();
+ _confirmCreateSlnDialog?.QueueFree();
+ }
+
private void OnSettingsChanged()
{
// We want to force NoConsoleLogging to true when the VerbosityLevel is at Detailed or above.
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index ca2ad315a7..3eb746677d 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -556,12 +556,6 @@ GDMono::GDMono() {
GDMono::~GDMono() {
finalizing_scripts_domain = true;
- if (is_runtime_initialized()) {
- if (GDMonoCache::godot_api_cache_updated) {
- GDMonoCache::managed_callbacks.DisposablesTracker_OnGodotShuttingDown();
- }
- }
-
if (hostfxr_dll_handle) {
OS::get_singleton()->close_dynamic_library(hostfxr_dll_handle);
}
diff --git a/modules/noise/noise.cpp b/modules/noise/noise.cpp
index 65ef07e284..9b9fd640f4 100644
--- a/modules/noise/noise.cpp
+++ b/modules/noise/noise.cpp
@@ -166,6 +166,9 @@ Vector<Ref<Image>> Noise::_get_image(int p_width, int p_height, int p_depth, boo
Ref<Image> Noise::get_image(int p_width, int p_height, bool p_invert, bool p_in_3d_space, bool p_normalize) const {
Vector<Ref<Image>> images = _get_image(p_width, p_height, 1, p_invert, p_in_3d_space, p_normalize);
+ if (images.is_empty()) {
+ return Ref<Image>();
+ }
return images[0];
}
diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h
index 6ce2692fd3..cbd2911aaf 100644
--- a/modules/text_server_adv/text_server_adv.h
+++ b/modules/text_server_adv/text_server_adv.h
@@ -681,11 +681,7 @@ class TextServerAdvanced : public TextServerExtension {
_FORCE_INLINE_ bool operator()(const Glyph &l, const Glyph &r) const {
if (l.start == r.start) {
if (l.count == r.count) {
- if ((l.flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL) {
- return false;
- } else {
- return true;
- }
+ return (l.flags & TextServer::GRAPHEME_IS_VIRTUAL) < (r.flags & TextServer::GRAPHEME_IS_VIRTUAL);
}
return l.count > r.count; // Sort first glyph with count & flags, order of the rest are irrelevant.
} else {
diff --git a/platform/android/java/app/AndroidManifest.xml b/platform/android/java/app/AndroidManifest.xml
index 56d403a263..079f629b12 100644
--- a/platform/android/java/app/AndroidManifest.xml
+++ b/platform/android/java/app/AndroidManifest.xml
@@ -35,7 +35,7 @@
android:name=".GodotApp"
android:label="@string/godot_project_name_string"
android:theme="@style/GodotAppSplashTheme"
- android:launchMode="singleInstance"
+ android:launchMode="singleInstancePerTask"
android:excludeFromRecents="false"
android:exported="true"
android:screenOrientation="landscape"
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index 53db9a5abf..09df60bf06 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -4499,6 +4499,22 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM
rendering_driver = p_rendering_driver;
#if defined(GLES3_ENABLED)
+ if (rendering_driver == "opengl3_angle") {
+ gl_manager_angle = memnew(GLManagerANGLE_MacOS);
+ if (gl_manager_angle->initialize() != OK) {
+ memdelete(gl_manager_angle);
+ gl_manager_angle = nullptr;
+ bool fallback = GLOBAL_GET("rendering/gl_compatibility/fallback_to_native");
+ if (fallback) {
+ WARN_PRINT("Your video card drivers seem not to support the required Metal version, switching to native OpenGL.");
+ rendering_driver = "opengl3";
+ } else {
+ ERR_FAIL_MSG("Could not initialize OpenGL.");
+ return;
+ }
+ }
+ }
+
if (rendering_driver == "opengl3") {
gl_manager_legacy = memnew(GLManagerLegacy_MacOS);
if (gl_manager_legacy->initialize() != OK) {
@@ -4509,15 +4525,6 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM
return;
}
}
- if (rendering_driver == "opengl3_angle") {
- gl_manager_angle = memnew(GLManagerANGLE_MacOS);
- if (gl_manager_angle->initialize() != OK) {
- memdelete(gl_manager_angle);
- gl_manager_angle = nullptr;
- r_error = ERR_UNAVAILABLE;
- ERR_FAIL_MSG("Could not initialize OpenGL.");
- }
- }
#endif
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
diff --git a/scene/3d/bone_attachment_3d.cpp b/scene/3d/bone_attachment_3d.cpp
index 60fb6f87c9..45de9b907c 100644
--- a/scene/3d/bone_attachment_3d.cpp
+++ b/scene/3d/bone_attachment_3d.cpp
@@ -349,6 +349,16 @@ void BoneAttachment3D::notify_skeleton_bones_renamed(Node *p_base_scene, Skeleto
}
}
}
+
+void BoneAttachment3D::notify_rebind_required() {
+ // Ensures bindings are properly updated after a scene reload.
+ _check_unbind();
+ if (use_external_skeleton) {
+ _update_external_skeleton_cache();
+ }
+ bone_idx = -1;
+ _check_bind();
+}
#endif // TOOLS_ENABLED
BoneAttachment3D::BoneAttachment3D() {
diff --git a/scene/3d/bone_attachment_3d.h b/scene/3d/bone_attachment_3d.h
index bfa3db476d..1bf44c2756 100644
--- a/scene/3d/bone_attachment_3d.h
+++ b/scene/3d/bone_attachment_3d.h
@@ -89,6 +89,10 @@ public:
virtual void on_bone_pose_update(int p_bone_index);
+#ifdef TOOLS_ENABLED
+ virtual void notify_rebind_required();
+#endif
+
BoneAttachment3D();
};
diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp
index 1f12f96fb3..db2c0e1387 100644
--- a/scene/3d/soft_body_3d.cpp
+++ b/scene/3d/soft_body_3d.cpp
@@ -471,6 +471,7 @@ void SoftBody3D::_become_mesh_owner() {
uint32_t surface_format = mesh->surface_get_format(0);
surface_format |= Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE;
+ surface_format &= ~Mesh::ARRAY_FLAG_COMPRESS_ATTRIBUTES;
Ref<ArrayMesh> soft_mesh;
soft_mesh.instantiate();
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 7768c2d84e..1e2f010aad 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -1219,7 +1219,14 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
Item *it = _get_item_at_pos(it_from, it_to, glyphs[i].start);
Color font_color = _find_color(it, p_base_color);
if (_find_underline(it) || (_find_meta(it, nullptr) && underline_meta)) {
- if (!ul_started) {
+ if (ul_started && font_color != ul_color) {
+ float y_off = TS->shaped_text_get_underline_position(rid);
+ float underline_width = MAX(1.0, TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale);
+ draw_line(ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), ul_color, underline_width);
+ ul_start = p_ofs + Vector2(off.x, off.y);
+ ul_color = font_color;
+ ul_color.a *= 0.5;
+ } else if (!ul_started) {
ul_started = true;
ul_start = p_ofs + Vector2(off.x, off.y);
ul_color = font_color;
@@ -1232,7 +1239,14 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
draw_line(ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), ul_color, underline_width);
}
if (_find_hint(it, nullptr) && underline_hint) {
- if (!dot_ul_started) {
+ if (dot_ul_started && font_color != dot_ul_color) {
+ float y_off = TS->shaped_text_get_underline_position(rid);
+ float underline_width = MAX(1.0, 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, MAX(2.0, underline_width * 2));
+ dot_ul_start = p_ofs + Vector2(off.x, off.y);
+ dot_ul_color = font_color;
+ dot_ul_color.a *= 0.5;
+ } else if (!dot_ul_started) {
dot_ul_started = true;
dot_ul_start = p_ofs + Vector2(off.x, off.y);
dot_ul_color = font_color;
@@ -1245,7 +1259,14 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
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) {
+ if (st_started && font_color != st_color) {
+ float y_off = -TS->shaped_text_get_ascent(rid) + TS->shaped_text_get_size(rid).y / 2;
+ float underline_width = MAX(1.0, TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale);
+ draw_line(st_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), st_color, underline_width);
+ st_start = p_ofs + Vector2(off.x, off.y);
+ st_color = font_color;
+ st_color.a *= 0.5;
+ } else if (!st_started) {
st_started = true;
st_start = p_ofs + Vector2(off.x, off.y);
st_color = font_color;
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index b122189558..6f12539a6d 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -870,6 +870,8 @@ void Mesh::_bind_methods() {
BIND_BITFIELD_FLAG(ARRAY_FLAG_USE_8_BONE_WEIGHTS);
BIND_BITFIELD_FLAG(ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY);
+ BIND_BITFIELD_FLAG(ARRAY_FLAG_COMPRESS_ATTRIBUTES);
+
BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_NORMALIZED);
BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_RELATIVE);
diff --git a/scene/resources/particle_process_material.cpp b/scene/resources/particle_process_material.cpp
index 968ec77d1d..b58c3ad433 100644
--- a/scene/resources/particle_process_material.cpp
+++ b/scene/resources/particle_process_material.cpp
@@ -31,7 +31,6 @@
#include "particle_process_material.h"
#include "core/version.h"
-#include "scene/resources/curve_texture.h"
Mutex ParticleProcessMaterial::material_mutex;
SelfList<ParticleProcessMaterial>::List *ParticleProcessMaterial::dirty_materials = nullptr;
@@ -672,13 +671,18 @@ void ParticleProcessMaterial::_update_shader() {
code += " float orbit_amount = param.orbit_velocity;\n";
if (tex_parameters[PARAM_ORBIT_VELOCITY].is_valid()) {
- code += " orbit_amount *= texture(orbit_velocity_curve, vec2(lifetime)).r;\n";
+ CurveTexture *texture = Object::cast_to<CurveTexture>(tex_parameters[PARAM_ORBIT_VELOCITY].ptr());
+ if (texture) {
+ code += " orbit_amount *= texture(orbit_velocity_curve, vec2(lifetime)).r;\n";
+ } else {
+ code += " orbit_amount *= texture(orbit_velocity_curve, vec2(lifetime)).b;\n";
+ }
}
code += " if (orbit_amount != 0.0) {\n";
code += " vec3 pos = transform[3].xyz;\n";
code += " vec3 org = emission_transform[3].xyz;\n";
code += " vec3 diff = pos - org;\n";
- code += " float ang = orbit_amount * pi * 2.0;\n";
+ code += " float ang = orbit_amount * pi * 2.0 * delta;\n";
code += " mat2 rot = mat2(vec2(cos(ang), -sin(ang)), vec2(sin(ang), cos(ang)));\n";
code += " displacement.xy -= diff.xy;\n";
code += " displacement.xy += rot * diff.xy;\n";
@@ -687,8 +691,8 @@ void ParticleProcessMaterial::_update_shader() {
code += " vec3 orbit_velocities = vec3(param.orbit_velocity);\n";
code += " orbit_velocities *= texture(orbit_velocity_curve, vec2(lifetime)).rgb;\n";
- code += " orbit_velocities *= degree_to_rad;\n";
- code += " orbit_velocities *= delta/total_lifetime; // we wanna process those by the delta angle\n";
+ code += " orbit_velocities *= pi * 2.0;\n";
+ code += " orbit_velocities *= delta; // we wanna process those by the delta angle\n";
code += " //vec3 local_velocity_pivot = ((emission_transform) * vec4(velocity_pivot,1.0)).xyz;\n";
code += " // X axis\n";
code += " vec3 local_pos = (inverse(emission_transform) * transform[3]).xyz;\n";
@@ -719,7 +723,7 @@ void ParticleProcessMaterial::_update_shader() {
code += " local_pos -= velocity_pivot;\n";
code += " local_pos.z = 0.;\n";
code += " mat3 z_rotation_mat = mat3(\n";
- code += " vec3(cos(orbit_velocities.z),-sin(orbit_velocities.z),0.0),\n";
+ code += " vec3(cos(orbit_velocities.z),sin(orbit_velocities.z),0.0),\n";
code += " vec3(-sin(orbit_velocities.z),cos(orbit_velocities.z), 0.0),\n";
code += " vec3(0.0,0.0,1.0)\n";
code += " );\n";
@@ -958,21 +962,22 @@ void ParticleProcessMaterial::_update_shader() {
code += " {\n";
code += " // copied from previous version\n";
code += " if (physics_params.damping > 0.0) {\n";
+ code += " float v = length(VELOCITY);\n";
if (!particle_flags[PARTICLE_FLAG_DAMPING_AS_FRICTION]) {
- code += " float v = length(VELOCITY);\n";
+ code += " v -= physics_params.damping * DELTA;\n";
+ } else {
+ code += " if (v > 0.001) {\n";
code += " // Realistic friction formula. We assume the mass of a particle to be 0.05kg.\n";
code += " float damp = v * v * physics_params.damping * 0.05 * DELTA;\n";
code += " v -= damp;\n";
- code += " if (v < 0.0) {\n";
- code += " VELOCITY = vec3(0.0);\n";
- code += " } else {\n";
- code += " VELOCITY = normalize(VELOCITY) * v;\n";
- code += " }\n";
- } else {
- code += " if (length(VELOCITY) > 0.01){\n";
- code += " VELOCITY -= normalize(VELOCITY) * length(VELOCITY) * (physics_params.damping) * DELTA;\n";
- code += " }\n";
+ code += " }\n";
}
+
+ code += " if (v < 0.0) {\n";
+ code += " VELOCITY = vec3(0.0);\n";
+ code += " } else {\n";
+ code += " VELOCITY = normalize(VELOCITY) * v;\n";
+ code += " }\n";
code += " }\n";
code += " \n";
code += " }\n";
@@ -1387,7 +1392,7 @@ void ParticleProcessMaterial::set_param_texture(Parameter p_param, const Ref<Tex
} break;
case PARAM_ORBIT_VELOCITY: {
RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity_texture, tex_rid);
- _adjust_curve_range(p_texture, -500, 500);
+ _adjust_curve_range(p_texture, -2, 2);
notify_property_list_changed();
} break;
case PARAM_LINEAR_ACCEL: {
@@ -2100,8 +2105,8 @@ void ParticleProcessMaterial::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_velocity_max", PROPERTY_HINT_RANGE, "-720,720,0.01,or_less,or_greater"), "set_param_max", "get_param_max", PARAM_DIRECTIONAL_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "directional_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveXYZTexture"), "set_param_texture", "get_param_texture", PARAM_DIRECTIONAL_VELOCITY);
ADD_SUBGROUP("Orbit Velocity", "orbit_");
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "orbit_velocity_min", PROPERTY_HINT_RANGE, "-1000,1000,0.01,or_less,or_greater"), "set_param_min", "get_param_min", PARAM_ORBIT_VELOCITY);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "orbit_velocity_max", PROPERTY_HINT_RANGE, "-1000,1000,0.01,or_less,or_greater"), "set_param_max", "get_param_max", PARAM_ORBIT_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "orbit_velocity_min", PROPERTY_HINT_RANGE, "-2,2,0.001,or_less,or_greater"), "set_param_min", "get_param_min", PARAM_ORBIT_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "orbit_velocity_max", PROPERTY_HINT_RANGE, "-2,2,0.001,or_less,or_greater"), "set_param_max", "get_param_max", PARAM_ORBIT_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "orbit_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture,CurveXYZTexture"), "set_param_texture", "get_param_texture", PARAM_ORBIT_VELOCITY);
ADD_SUBGROUP("Radial Velocity", "radial_");
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "radial_velocity_min", PROPERTY_HINT_RANGE, "-1000,1000,0.01,or_less,or_greater"), "set_param_min", "get_param_min", PARAM_RADIAL_VELOCITY);
diff --git a/scene/resources/particle_process_material.h b/scene/resources/particle_process_material.h
index d3d8f89a15..5ed8b61c77 100644
--- a/scene/resources/particle_process_material.h
+++ b/scene/resources/particle_process_material.h
@@ -33,6 +33,7 @@
#include "core/templates/rid.h"
#include "core/templates/self_list.h"
+#include "scene/resources/curve_texture.h"
#include "scene/resources/material.h"
/*
@@ -125,6 +126,7 @@ private:
uint64_t alpha_curve : 1;
uint64_t emission_curve : 1;
uint64_t has_initial_ramp : 1;
+ uint64_t orbit_uses_curve_xyz : 1;
MaterialKey() {
memset(this, 0, sizeof(MaterialKey));
@@ -165,6 +167,8 @@ private:
mk.alpha_curve = alpha_curve.is_valid() ? 1 : 0;
mk.emission_curve = emission_curve.is_valid() ? 1 : 0;
mk.has_initial_ramp = color_initial_ramp.is_valid() ? 1 : 0;
+ CurveXYZTexture *texture = Object::cast_to<CurveXYZTexture>(tex_parameters[PARAM_ORBIT_VELOCITY].ptr());
+ mk.orbit_uses_curve_xyz = texture ? 1 : 0;
for (int i = 0; i < PARAM_MAX; i++) {
if (tex_parameters[i].is_valid()) {
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index b323710743..13791d8c2b 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -1300,7 +1300,11 @@ void PlaneMesh::_create_mesh_array(Array &p_arr) const {
points.push_back(Vector3(-x, z, 0.0) + center_offset);
}
normals.push_back(normal);
- ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
+ if (orientation == FACE_X) {
+ ADD_TANGENT(0.0, 0.0, -1.0, 1.0);
+ } else {
+ ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
+ }
uvs.push_back(Vector2(1.0 - u, 1.0 - v)); /* 1.0 - uv to match orientation with Quad */
point++;
@@ -2722,7 +2726,6 @@ void TextMesh::_generate_glyph_mesh_data(const GlyphMeshKey &p_key, const Glyph
GlyphMeshData &gl_data = cache[p_key];
Dictionary d = TS->font_get_glyph_contours(p_gl.font_rid, p_gl.font_size, p_gl.index);
- Vector2 origin = Vector2(p_gl.x_off, p_gl.y_off) * pixel_size;
PackedVector3Array points = d["points"];
PackedInt32Array contours = d["contours"];
@@ -2742,7 +2745,7 @@ void TextMesh::_generate_glyph_mesh_data(const GlyphMeshKey &p_key, const Glyph
for (int32_t j = start; j <= end; j++) {
if (points[j].z == TextServer::CONTOUR_CURVE_TAG_ON) {
// Point on the curve.
- Vector2 p = Vector2(points[j].x, points[j].y) * pixel_size + origin;
+ Vector2 p = Vector2(points[j].x, points[j].y) * pixel_size;
polygon.push_back(ContourPoint(p, true));
} else if (points[j].z == TextServer::CONTOUR_CURVE_TAG_OFF_CONIC) {
// Conic Bezier arc.
@@ -2776,7 +2779,7 @@ void TextMesh::_generate_glyph_mesh_data(const GlyphMeshKey &p_key, const Glyph
real_t t2 = t * t;
Vector2 point = p1 + omt2 * (p0 - p1) + t2 * (p2 - p1);
- Vector2 p = point * pixel_size + origin;
+ Vector2 p = point * pixel_size;
polygon.push_back(ContourPoint(p, false));
t += step;
}
@@ -2810,7 +2813,7 @@ void TextMesh::_generate_glyph_mesh_data(const GlyphMeshKey &p_key, const Glyph
real_t t = step;
while (t < 1.0) {
Vector2 point = p0.bezier_interpolate(p1, p2, p3, t);
- Vector2 p = point * pixel_size + origin;
+ Vector2 p = point * pixel_size;
polygon.push_back(ContourPoint(p, false));
t += step;
}
@@ -3045,6 +3048,7 @@ void TextMesh::_create_mesh_array(Array &p_arr) const {
GlyphMeshKey key = GlyphMeshKey(glyphs[j].font_rid.get_id(), glyphs[j].index);
_generate_glyph_mesh_data(key, glyphs[j]);
GlyphMeshData &gl_data = cache[key];
+ const Vector2 gl_of = Vector2(glyphs[j].x_off, glyphs[j].y_off) * pixel_size;
p_size += glyphs[j].repeat * gl_data.triangles.size() * ((has_depth) ? 2 : 1);
i_size += glyphs[j].repeat * gl_data.triangles.size() * ((has_depth) ? 2 : 1);
@@ -3057,10 +3061,10 @@ void TextMesh::_create_mesh_array(Array &p_arr) const {
}
for (int r = 0; r < glyphs[j].repeat; r++) {
- min_p.x = MIN(gl_data.min_p.x + offset.x, min_p.x);
- min_p.y = MIN(gl_data.min_p.y - offset.y, min_p.y);
- max_p.x = MAX(gl_data.max_p.x + offset.x, max_p.x);
- max_p.y = MAX(gl_data.max_p.y - offset.y, max_p.y);
+ min_p.x = MIN(gl_data.min_p.x + offset.x + gl_of.x, min_p.x);
+ min_p.y = MIN(gl_data.min_p.y - offset.y + gl_of.y, min_p.y);
+ max_p.x = MAX(gl_data.max_p.x + offset.x + gl_of.x, max_p.x);
+ max_p.y = MAX(gl_data.max_p.y - offset.y + gl_of.y, max_p.y);
offset.x += glyphs[j].advance * pixel_size;
}
@@ -3126,12 +3130,13 @@ void TextMesh::_create_mesh_array(Array &p_arr) const {
int64_t ts = gl_data.triangles.size();
const Vector2 *ts_ptr = gl_data.triangles.ptr();
+ const Vector2 gl_of = Vector2(glyphs[j].x_off, glyphs[j].y_off) * pixel_size;
for (int r = 0; r < glyphs[j].repeat; r++) {
for (int k = 0; k < ts; k += 3) {
// Add front face.
for (int l = 0; l < 3; l++) {
- Vector3 point = Vector3(ts_ptr[k + l].x + offset.x, -ts_ptr[k + l].y + offset.y, depth / 2.0);
+ Vector3 point = Vector3(ts_ptr[k + l].x + offset.x + gl_of.x, -ts_ptr[k + l].y + offset.y - gl_of.y, depth / 2.0);
vertices_ptr[p_idx] = point;
normals_ptr[p_idx] = Vector3(0.0, 0.0, 1.0);
if (has_depth) {
@@ -3149,7 +3154,7 @@ void TextMesh::_create_mesh_array(Array &p_arr) const {
if (has_depth) {
// Add back face.
for (int l = 2; l >= 0; l--) {
- Vector3 point = Vector3(ts_ptr[k + l].x + offset.x, -ts_ptr[k + l].y + offset.y, -depth / 2.0);
+ Vector3 point = Vector3(ts_ptr[k + l].x + offset.x + gl_of.x, -ts_ptr[k + l].y + offset.y - gl_of.y, -depth / 2.0);
vertices_ptr[p_idx] = point;
normals_ptr[p_idx] = Vector3(0.0, 0.0, -1.0);
uvs_ptr[p_idx] = Vector2(Math::remap(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::remap(point.y, -max_p.y, -min_p.y, real_t(0.8), real_t(0.4)));
@@ -3182,10 +3187,10 @@ void TextMesh::_create_mesh_array(Array &p_arr) const {
real_t seg_len = (ps_ptr[next].point - ps_ptr[l].point).length();
Vector3 quad_faces[4] = {
- Vector3(ps_ptr[l].point.x + offset.x, -ps_ptr[l].point.y + offset.y, -depth / 2.0),
- Vector3(ps_ptr[next].point.x + offset.x, -ps_ptr[next].point.y + offset.y, -depth / 2.0),
- Vector3(ps_ptr[l].point.x + offset.x, -ps_ptr[l].point.y + offset.y, depth / 2.0),
- Vector3(ps_ptr[next].point.x + offset.x, -ps_ptr[next].point.y + offset.y, depth / 2.0),
+ Vector3(ps_ptr[l].point.x + offset.x + gl_of.x, -ps_ptr[l].point.y + offset.y - gl_of.y, -depth / 2.0),
+ Vector3(ps_ptr[next].point.x + offset.x + gl_of.x, -ps_ptr[next].point.y + offset.y - gl_of.y, -depth / 2.0),
+ Vector3(ps_ptr[l].point.x + offset.x + gl_of.x, -ps_ptr[l].point.y + offset.y - gl_of.y, depth / 2.0),
+ Vector3(ps_ptr[next].point.x + offset.x + gl_of.x, -ps_ptr[next].point.y + offset.y - gl_of.y, depth / 2.0),
};
for (int m = 0; m < 4; m++) {
const Vector2 &d = ((m % 2) == 0) ? d1 : d2;
diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp
index d2a1519d49..d57a0f6b38 100644
--- a/scene/resources/theme.cpp
+++ b/scene/resources/theme.cpp
@@ -1240,6 +1240,11 @@ void Theme::get_type_list(List<StringName> *p_list) const {
types.insert(E.key);
}
+ // Variations.
+ for (const KeyValue<StringName, StringName> &E : variation_map) {
+ types.insert(E.key);
+ }
+
for (const StringName &E : types) {
p_list->push_back(E);
}
diff --git a/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_raster.glsl
index 7b3c2f1c3b..6c77ab4a91 100644
--- a/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_raster.glsl
@@ -33,7 +33,7 @@ layout(location = 0) out vec2 uv_interp;
void main() {
vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0));
gl_Position = vec4(base_arr[gl_VertexIndex], 0.0, 1.0);
- uv_interp = clamp(gl_Position.xy, vec2(0.0, 0.0), vec2(1.0, 1.0)) * 2.0; // saturate(x) * 2.0
+ uv_interp = clamp(gl_Position.xy, vec2(0.0, 0.0), vec2(1.0, 1.0)) * 2.0 * float(params.face_size); // saturate(x) * 2.0
}
/* clang-format off */
diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
index 8e6db7583e..206c2fb245 100644
--- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
@@ -1019,13 +1019,11 @@ void fragment_shader(in SceneData scene_data) {
#endif // ALPHA_ANTIALIASING_EDGE_USED
#ifdef MODE_RENDER_DEPTH
-#ifdef USE_OPAQUE_PREPASS
-#ifndef ALPHA_SCISSOR_USED
+#if defined(USE_OPAQUE_PREPASS) || defined(ALPHA_ANTIALIASING_EDGE_USED)
if (alpha < scene_data.opaque_prepass_threshold) {
discard;
}
-#endif // !ALPHA_SCISSOR_USED
-#endif // USE_OPAQUE_PREPASS
+#endif // USE_OPAQUE_PREPASS || ALPHA_ANTIALIASING_EDGE_USED
#endif // MODE_RENDER_DEPTH
#endif // !USE_SHADOW_TO_OPACITY
diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
index a9e9a617d6..5ed3669703 100644
--- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
@@ -854,13 +854,11 @@ void main() {
#endif // ALPHA_ANTIALIASING_EDGE_USED
#ifdef MODE_RENDER_DEPTH
-#ifdef USE_OPAQUE_PREPASS
-#ifndef ALPHA_SCISSOR_USED
+#if defined(USE_OPAQUE_PREPASS) || defined(ALPHA_ANTIALIASING_EDGE_USED)
if (alpha < scene_data.opaque_prepass_threshold) {
discard;
}
-#endif // !ALPHA_SCISSOR_USED
-#endif // USE_OPAQUE_PREPASS
+#endif // USE_OPAQUE_PREPASS || ALPHA_ANTIALIASING_EDGE_USED
#endif // MODE_RENDER_DEPTH
#endif // !USE_SHADOW_TO_OPACITY
diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp
index 71f821205e..1e95cdde0c 100644
--- a/servers/rendering/shader_compiler.cpp
+++ b/servers/rendering/shader_compiler.cpp
@@ -432,13 +432,13 @@ static String _get_global_shader_uniform_from_type_and_index(const String &p_buf
return "(" + p_buffer + "[" + p_index + "].xyzw)";
}
case ShaderLanguage::TYPE_MAT2: {
- return "mat2(" + p_buffer + "[" + p_index + "].xy," + p_buffer + "[" + p_index + "+1].xy)";
+ return "mat2(" + p_buffer + "[" + p_index + "].xy," + p_buffer + "[" + p_index + "+1u].xy)";
}
case ShaderLanguage::TYPE_MAT3: {
- return "mat3(" + p_buffer + "[" + p_index + "].xyz," + p_buffer + "[" + p_index + "+1].xyz," + p_buffer + "[" + p_index + "+2].xyz)";
+ return "mat3(" + p_buffer + "[" + p_index + "].xyz," + p_buffer + "[" + p_index + "+1u].xyz," + p_buffer + "[" + p_index + "+2u].xyz)";
}
case ShaderLanguage::TYPE_MAT4: {
- return "mat4(" + p_buffer + "[" + p_index + "].xyzw," + p_buffer + "[" + p_index + "+1].xyzw," + p_buffer + "[" + p_index + "+2].xyzw," + p_buffer + "[" + p_index + "+3].xyzw)";
+ return "mat4(" + p_buffer + "[" + p_index + "].xyzw," + p_buffer + "[" + p_index + "+1u].xyzw," + p_buffer + "[" + p_index + "+2u].xyzw," + p_buffer + "[" + p_index + "+3u].xyzw)";
}
default: {
ERR_FAIL_V("void");
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index d0a62ddb4d..eb940cdd56 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -400,7 +400,14 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
max_val = max_val.abs().max(min_val.abs());
max_val2 = max_val2.abs().max(min_val2.abs());
- r_uv_scale = Vector4(max_val.x, max_val.y, max_val2.x, max_val2.y) * Vector4(2.0, 2.0, 2.0, 2.0);
+ if (min_val.x >= 0.0 && min_val2.x >= 0.0 && max_val.x <= 1.0 && max_val2.x <= 1.0 &&
+ min_val.y >= 0.0 && min_val2.y >= 0.0 && max_val.y <= 1.0 && max_val2.y <= 1.0) {
+ // When all channels are in the 0-1 range, we will compress to 16-bit without scaling to
+ // preserve the bits as best as possible.
+ r_uv_scale = Vector4(0.0, 0.0, 0.0, 0.0);
+ } else {
+ r_uv_scale = Vector4(max_val.x, max_val.y, max_val2.x, max_val2.y) * Vector4(2.0, 2.0, 2.0, 2.0);
+ }
}
for (int ai = 0; ai < RS::ARRAY_MAX; ai++) {
@@ -670,8 +677,11 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
if (p_format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
for (int i = 0; i < p_vertex_array_len; i++) {
Vector2 vec = src[i];
- // Normalize into 0-1 from possible range -uv_scale - uv_scale.
- vec = vec / (Vector2(r_uv_scale.x, r_uv_scale.y)) + Vector2(0.5, 0.5);
+ if (!r_uv_scale.is_zero_approx()) {
+ // Normalize into 0-1 from possible range -uv_scale - uv_scale.
+ vec = vec / (Vector2(r_uv_scale.x, r_uv_scale.y)) + Vector2(0.5, 0.5);
+ }
+
uint16_t uv[2] = { (uint16_t)CLAMP(vec.x * 65535, 0, 65535), (uint16_t)CLAMP(vec.y * 65535, 0, 65535) };
memcpy(&aw[p_offsets[ai] + i * p_attrib_stride], uv, 4);
}
@@ -695,8 +705,10 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
if (p_format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
for (int i = 0; i < p_vertex_array_len; i++) {
Vector2 vec = src[i];
- // Normalize into 0-1 from possible range -uv_scale - uv_scale.
- vec = vec / (Vector2(r_uv_scale.z, r_uv_scale.w)) + Vector2(0.5, 0.5);
+ if (!r_uv_scale.is_zero_approx()) {
+ // Normalize into 0-1 from possible range -uv_scale - uv_scale.
+ vec = vec / (Vector2(r_uv_scale.z, r_uv_scale.w)) + Vector2(0.5, 0.5);
+ }
uint16_t uv[2] = { (uint16_t)CLAMP(vec.x * 65535, 0, 65535), (uint16_t)CLAMP(vec.y * 65535, 0, 65535) };
memcpy(&aw[p_offsets[ai] + i * p_attrib_stride], uv, 4);
}
@@ -1311,7 +1323,7 @@ void RenderingServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_p
mesh_add_surface(p_mesh, sd);
}
-Array RenderingServer::_get_array_from_surface(uint64_t p_format, Vector<uint8_t> p_vertex_data, Vector<uint8_t> p_attrib_data, Vector<uint8_t> p_skin_data, int p_vertex_len, Vector<uint8_t> p_index_data, int p_index_len, const AABB &p_aabb) const {
+Array RenderingServer::_get_array_from_surface(uint64_t p_format, Vector<uint8_t> p_vertex_data, Vector<uint8_t> p_attrib_data, Vector<uint8_t> p_skin_data, int p_vertex_len, Vector<uint8_t> p_index_data, int p_index_len, const AABB &p_aabb, const Vector4 &p_uv_scale) const {
uint32_t offsets[RS::ARRAY_MAX];
uint32_t vertex_elem_size;
@@ -1469,7 +1481,12 @@ Array RenderingServer::_get_array_from_surface(uint64_t p_format, Vector<uint8_t
if (p_format & ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
for (int j = 0; j < p_vertex_len; j++) {
const uint16_t *v = reinterpret_cast<const uint16_t *>(&ar[j * attrib_elem_size + offsets[i]]);
- w[j] = Vector2(float(v[0]) / 65535.0, float(v[1]) / 65535.0);
+ Vector2 vec = Vector2(float(v[0]) / 65535.0, float(v[1]) / 65535.0);
+ if (!p_uv_scale.is_zero_approx()) {
+ vec = (vec - Vector2(0.5, 0.5)) * Vector2(p_uv_scale.x, p_uv_scale.y);
+ }
+
+ w[j] = vec;
}
} else {
for (int j = 0; j < p_vertex_len; j++) {
@@ -1489,7 +1506,11 @@ Array RenderingServer::_get_array_from_surface(uint64_t p_format, Vector<uint8_t
if (p_format & ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
for (int j = 0; j < p_vertex_len; j++) {
const uint16_t *v = reinterpret_cast<const uint16_t *>(&ar[j * attrib_elem_size + offsets[i]]);
- w[j] = Vector2(float(v[0]) / 65535.0, float(v[1]) / 65535.0);
+ Vector2 vec = Vector2(float(v[0]) / 65535.0, float(v[1]) / 65535.0);
+ if (!p_uv_scale.is_zero_approx()) {
+ vec = (vec - Vector2(0.5, 0.5)) * Vector2(p_uv_scale.z, p_uv_scale.w);
+ }
+ w[j] = vec;
}
} else {
for (int j = 0; j < p_vertex_len; j++) {
@@ -1686,7 +1707,7 @@ TypedArray<Array> RenderingServer::mesh_surface_get_blend_shape_arrays(RID p_mes
for (uint32_t i = 0; i < blend_shape_count; i++) {
Vector<uint8_t> bs_data = blend_shape_data.slice(i * divisor, (i + 1) * divisor);
Vector<uint8_t> unused;
- blend_shape_array.set(i, _get_array_from_surface(bs_format, bs_data, unused, unused, sd.vertex_count, unused, 0, sd.aabb));
+ blend_shape_array.set(i, _get_array_from_surface(bs_format, bs_data, unused, unused, sd.vertex_count, unused, 0, sd.aabb, sd.uv_scale));
}
return blend_shape_array;
@@ -1708,7 +1729,7 @@ Array RenderingServer::mesh_create_arrays_from_surface_data(const SurfaceData &p
uint64_t format = p_data.format;
- return _get_array_from_surface(format, vertex_data, attrib_data, skin_data, vertex_len, index_data, index_len, p_data.aabb);
+ return _get_array_from_surface(format, vertex_data, attrib_data, skin_data, vertex_len, index_data, index_len, p_data.aabb, p_data.uv_scale);
}
#if 0
Array RenderingServer::_mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_surface) const {
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index d23e0fb48d..fbc67fc84d 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -52,7 +52,7 @@ class RenderingServer : public Object {
int mm_policy = 0;
bool render_loop_enabled = true;
- Array _get_array_from_surface(uint64_t p_format, Vector<uint8_t> p_vertex_data, Vector<uint8_t> p_attrib_data, Vector<uint8_t> p_skin_data, int p_vertex_len, Vector<uint8_t> p_index_data, int p_index_len, const AABB &p_aabb) const;
+ Array _get_array_from_surface(uint64_t p_format, Vector<uint8_t> p_vertex_data, Vector<uint8_t> p_attrib_data, Vector<uint8_t> p_skin_data, int p_vertex_len, Vector<uint8_t> p_index_data, int p_index_len, const AABB &p_aabb, const Vector4 &p_uv_scale) const;
const Vector2 SMALL_VEC2 = Vector2(CMP_EPSILON, CMP_EPSILON);
const Vector3 SMALL_VEC3 = Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON);
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 946bcd8a8c..be0693bc34 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -480,7 +480,7 @@ in the MSVC debugger.
## mbedtls
- Upstream: https://github.com/Mbed-TLS/mbedtls
-- Version: 2.28.4 (aeb97a18913a86f051afab11b2c92c6be0c2eb83, 2023)
+- Version: 2.28.5 (47e8cc9db2e469d902b0e3093ae9e482c3d87188, 2023)
- License: Apache 2.0
File extracted from upstream release tarball:
@@ -490,8 +490,8 @@ File extracted from upstream release tarball:
- All `.c` and `.h` from `library/` to `thirdparty/mbedtls/library/` except
those starting with `psa_*`
- The `LICENSE` file
-- Applied the patch in `patches/windows-arm64-hardclock.diff`
- Applied the patch in `aesni-no-arm-intrinsics.patch` to fix MSVC ARM build
+- Applied the patch `windows-arm64-hardclock.diff` to fix Windows ARM64 build
+ Applied the patch `windows-entropy-bcrypt.diff` to fix Windows Store support
- Added 2 files `godot_core_mbedtls_platform.c` and `godot_core_mbedtls_config.h`
providing configuration for light bundling with core
- Added the file `godot_module_mbedtls_config.h` to customize the build
diff --git a/thirdparty/mbedtls/library/entropy_poll.c b/thirdparty/mbedtls/library/entropy_poll.c
index 3420616a06..fec2abc2e4 100644
--- a/thirdparty/mbedtls/library/entropy_poll.c
+++ b/thirdparty/mbedtls/library/entropy_poll.c
@@ -51,32 +51,34 @@
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
-#if !defined(_WIN32_WINNT)
-#define _WIN32_WINNT 0x0400
-#endif
#include <windows.h>
-#include <wincrypt.h>
+#include <bcrypt.h>
+#include <intsafe.h>
int mbedtls_platform_entropy_poll(void *data, unsigned char *output, size_t len,
size_t *olen)
{
- HCRYPTPROV provider;
((void) data);
*olen = 0;
- if (CryptAcquireContext(&provider, NULL, NULL,
- PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) == FALSE) {
- return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
- }
+ /*
+ * BCryptGenRandom takes ULONG for size, which is smaller than size_t on
+ * 64-bit Windows platforms. Extract entropy in chunks of len (dependent
+ * on ULONG_MAX) size.
+ */
+ while (len != 0) {
+ unsigned long ulong_bytes =
+ (len > ULONG_MAX) ? ULONG_MAX : (unsigned long) len;
+
+ if (!BCRYPT_SUCCESS(BCryptGenRandom(NULL, output, ulong_bytes,
+ BCRYPT_USE_SYSTEM_PREFERRED_RNG))) {
+ return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
+ }
- if (CryptGenRandom(provider, (DWORD) len, output) == FALSE) {
- CryptReleaseContext(provider, 0);
- return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
+ *olen += ulong_bytes;
+ len -= ulong_bytes;
}
- CryptReleaseContext(provider, 0);
- *olen = len;
-
return 0;
}
#else /* _WIN32 && !EFIX64 && !EFI32 */
diff --git a/thirdparty/mbedtls/patches/windows-entropy-bcrypt.diff b/thirdparty/mbedtls/patches/windows-entropy-bcrypt.diff
new file mode 100644
index 0000000000..2517687be6
--- /dev/null
+++ b/thirdparty/mbedtls/patches/windows-entropy-bcrypt.diff
@@ -0,0 +1,56 @@
+Backported from: https://github.com/Mbed-TLS/mbedtls/pull/8047
+
+diff --git a/thirdparty/mbedtls/library/entropy_poll.c b/thirdparty/mbedtls/library/entropy_poll.c
+index 3420616a06..fec2abc2e4 100644
+--- a/thirdparty/mbedtls/library/entropy_poll.c
++++ b/thirdparty/mbedtls/library/entropy_poll.c
+@@ -51,32 +51,34 @@
+
+ #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
+
+-#if !defined(_WIN32_WINNT)
+-#define _WIN32_WINNT 0x0400
+-#endif
+ #include <windows.h>
+-#include <wincrypt.h>
++#include <bcrypt.h>
++#include <intsafe.h>
+
+ int mbedtls_platform_entropy_poll(void *data, unsigned char *output, size_t len,
+ size_t *olen)
+ {
+- HCRYPTPROV provider;
+ ((void) data);
+ *olen = 0;
+
+- if (CryptAcquireContext(&provider, NULL, NULL,
+- PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) == FALSE) {
+- return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
+- }
++ /*
++ * BCryptGenRandom takes ULONG for size, which is smaller than size_t on
++ * 64-bit Windows platforms. Extract entropy in chunks of len (dependent
++ * on ULONG_MAX) size.
++ */
++ while (len != 0) {
++ unsigned long ulong_bytes =
++ (len > ULONG_MAX) ? ULONG_MAX : (unsigned long) len;
++
++ if (!BCRYPT_SUCCESS(BCryptGenRandom(NULL, output, ulong_bytes,
++ BCRYPT_USE_SYSTEM_PREFERRED_RNG))) {
++ return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
++ }
+
+- if (CryptGenRandom(provider, (DWORD) len, output) == FALSE) {
+- CryptReleaseContext(provider, 0);
+- return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
++ *olen += ulong_bytes;
++ len -= ulong_bytes;
+ }
+
+- CryptReleaseContext(provider, 0);
+- *olen = len;
+-
+ return 0;
+ }
+ #else /* _WIN32 && !EFIX64 && !EFI32 */