Merge pull request #87540 from YuriSizov/4.1-cherrypicks

Cherry-picks for the 4.1 branch (future 4.1.4) - 2nd batch
This commit is contained in:
Yuri Sizov 2024-01-24 20:09:52 +01:00 committed by GitHub
commit c39ad18bfa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
72 changed files with 655 additions and 320 deletions

View File

@ -487,7 +487,7 @@ License: Expat
Files: ./thirdparty/zlib/
Comment: zlib
Copyright: 1995-2023, Jean-loup Gailly and Mark Adler
Copyright: 1995-2024, Jean-loup Gailly and Mark Adler
License: Zlib
Files: ./thirdparty/zstd/

View File

@ -509,6 +509,7 @@ static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p
}
void Image::convert(Format p_new_format) {
ERR_FAIL_INDEX_MSG(p_new_format, FORMAT_MAX, "The Image format specified (" + itos(p_new_format) + ") is out of range. See Image's Format enum.");
if (data.size() == 0) {
return;
}

View File

@ -8,21 +8,23 @@
[codeblocks]
[gdscript]
# This creates an animation that makes the node "Enemy" move to the right by
# 100 pixels in 0.5 seconds.
# 100 pixels in 2.0 seconds.
var animation = Animation.new()
var track_index = animation.add_track(Animation.TYPE_VALUE)
animation.track_set_path(track_index, "Enemy:position:x")
animation.track_insert_key(track_index, 0.0, 0)
animation.track_insert_key(track_index, 0.5, 100)
animation.track_insert_key(track_index, 2.0, 100)
animation.length = 2.0
[/gdscript]
[csharp]
// This creates an animation that makes the node "Enemy" move to the right by
// 100 pixels in 0.5 seconds.
// 100 pixels in 2.0 seconds.
var animation = new Animation();
int trackIndex = animation.AddTrack(Animation.TrackType.Value);
animation.TrackSetPath(trackIndex, "Enemy:position:x");
animation.TrackInsertKey(trackIndex, 0.0f, 0);
animation.TrackInsertKey(trackIndex, 0.5f, 100);
animation.TrackInsertKey(trackIndex, 2.0f, 100);
animation.Length = 2.0f;
[/csharp]
[/codeblocks]
Animations are just data containers, and must be added to nodes such as an [AnimationPlayer] to be played back. Animation tracks have different types, each with its own set of dedicated methods. Check [enum TrackType] to see available types.

View File

@ -25,6 +25,7 @@
</member>
<member name="polygon" type="PackedVector2Array" setter="set_polygon" getter="get_polygon" default="PackedVector2Array()">
The polygon's list of vertices. Each point will be connected to the next, and the final point will be connected to the first.
[b]Note:[/b] The returned vertices are in the local coordinate space of the given [CollisionPolygon2D].
[b]Warning:[/b] The returned value is a clone of the [PackedVector2Array], not a reference.
</member>
</members>

View File

@ -18,6 +18,7 @@
<param index="1" name="contrast" type="float" />
<param index="2" name="saturation" type="float" />
<description>
Adjusts this image's [param brightness], [param contrast], and [param saturation] by the given values. Does not work if the image is compressed (see [method is_compressed]).
</description>
</method>
<method name="blend_rect">
@ -162,6 +163,7 @@
<return type="int" enum="Image.UsedChannels" />
<param index="0" name="source" type="int" enum="Image.CompressSource" default="0" />
<description>
Returns the color channels used by this image, as one of the [enum UsedChannels] constants. If the image is compressed, the original [param source] must be specified.
</description>
</method>
<method name="fill">
@ -572,6 +574,7 @@
OpenGL texture format [code]RGBA[/code] with four components, each with a bitdepth of 4.
</constant>
<constant name="FORMAT_RGB565" value="7" enum="Format">
OpenGL texture format [code]RGB[/code] with three components. Red and blue have a bitdepth of 5, and green has a bitdepth of 6.
</constant>
<constant name="FORMAT_RF" value="8" enum="Format">
OpenGL texture format [code]GL_R32F[/code] where there's one component, a 32-bit floating-point value.
@ -656,8 +659,10 @@
[b]Note:[/b] When creating an [ImageTexture], an sRGB to linear color space conversion is performed.
</constant>
<constant name="FORMAT_ETC2_RA_AS_RG" value="33" enum="Format">
[url=https://en.wikipedia.org/wiki/Ericsson_Texture_Compression#ETC2_and_EAC]Ericsson Texture Compression format 2[/url] ([code]RGBA8[/code] variant), which compresses RA data and interprets it as two channels (red and green). See also [constant FORMAT_ETC2_RGBA8].
</constant>
<constant name="FORMAT_DXT5_RA_AS_RG" value="34" enum="Format">
The [url=https://en.wikipedia.org/wiki/S3_Texture_Compression]S3TC[/url] texture format also known as Block Compression 3 or BC3, which compresses RA data and interprets it as two channels (red and green). See also [constant FORMAT_DXT5].
</constant>
<constant name="FORMAT_ASTC_4x4" value="35" enum="Format">
[url=https://en.wikipedia.org/wiki/Adaptive_scalable_texture_compression]Adaptive Scalable Texutre Compression[/url]. This implements the 4x4 (high quality) mode.
@ -721,16 +726,22 @@
Represents the size of the [enum CompressMode] enum.
</constant>
<constant name="USED_CHANNELS_L" value="0" enum="UsedChannels">
The image only uses one channel for luminance (grayscale).
</constant>
<constant name="USED_CHANNELS_LA" value="1" enum="UsedChannels">
The image uses two channels for luminance and alpha, respectively.
</constant>
<constant name="USED_CHANNELS_R" value="2" enum="UsedChannels">
The image only uses the red channel.
</constant>
<constant name="USED_CHANNELS_RG" value="3" enum="UsedChannels">
The image uses two channels for red and green.
</constant>
<constant name="USED_CHANNELS_RGB" value="4" enum="UsedChannels">
The image uses three channels for red, green, and blue.
</constant>
<constant name="USED_CHANNELS_RGBA" value="5" enum="UsedChannels">
The image uses four channels for red, green, blue, and alpha.
</constant>
<constant name="COMPRESS_SOURCE_GENERIC" value="0" enum="CompressSource">
Source texture (before compression) is a regular texture. Default for all textures.

View File

@ -174,6 +174,7 @@
<param index="1" name="compression_mode" type="int" default="0" />
<description>
Returns a new [PackedByteArray] with the data decompressed. Set [param buffer_size] to the size of the uncompressed data. Set the compression mode using one of [enum FileAccess.CompressionMode]'s constants.
[b]Note:[/b] Decompression is not guaranteed to work with data not compressed by Godot, for example if data compressed with the deflate compression mode lacks a checksum or header.
</description>
</method>
<method name="decompress_dynamic" qualifiers="const">
@ -184,6 +185,7 @@
Returns a new [PackedByteArray] with the data decompressed. Set the compression mode using one of [enum FileAccess.CompressionMode]'s constants. [b]This method only accepts brotli, gzip, and deflate compression modes.[/b]
This method is potentially slower than [code]decompress[/code], as it may have to re-allocate its output buffer multiple times while decompressing, whereas [code]decompress[/code] knows it's output buffer size from the beginning.
GZIP has a maximal compression ratio of 1032:1, meaning it's very possible for a small compressed payload to decompress to a potentially very large output. To guard against this, you may provide a maximum size this function is allowed to allocate in bytes via [param max_output_size]. Passing -1 will allow for unbounded output. If any positive value is passed, and the decompression exceeds that amount in bytes, then an error will be returned.
[b]Note:[/b] Decompression is not guaranteed to work with data not compressed by Godot, for example if data compressed with the deflate compression mode lacks a checksum or header.
</description>
</method>
<method name="duplicate">

View File

@ -12,6 +12,7 @@
<method name="_create_mesh_array" qualifiers="virtual const">
<return type="Array" />
<description>
Override this method to customize how this primitive mesh should be generated. Should return an [Array] where each element is another Array of values required for the mesh (see the [enum Mesh.ArrayType] constants).
</description>
</method>
<method name="get_mesh_arrays" qualifiers="const">

View File

@ -774,7 +774,9 @@
Main window can't be focused. No-focus window will ignore all input, except mouse clicks.
</member>
<member name="display/window/size/resizable" type="bool" setter="" getter="" default="true">
Allows the window to be resizable by default.
If [code]true[/code], allows the window to be resizable by default.
[b]Note:[/b] This property is only read when the project starts. To change whether the window is resizable at runtime, set [member Window.unresizable] instead on the root Window, which can be retrieved using [code]get_viewport().get_window()[/code]. [member Window.unresizable] takes the opposite value of this setting.
[b]Note:[/b] Certain window managers can be configured to ignore the non-resizable status of a window. Do not rely on this setting as a guarantee that the window will [i]never[/i] be resizable.
[b]Note:[/b] This setting is ignored on iOS.
</member>
<member name="display/window/size/transparent" type="bool" setter="" getter="" default="false">
@ -2467,6 +2469,7 @@
[b]Note:[/b] This setting is only effective when using the Compatibility rendering method, not Forward+ and Mobile.
</member>
<member name="rendering/limits/spatial_indexer/threaded_cull_minimum_instances" type="int" setter="" getter="" default="1000">
The minimum number of instances that must be present in a scene to enable culling computations on multiple threads. If a scene has fewer instances than this number, culling is done on a single thread.
</member>
<member name="rendering/limits/spatial_indexer/update_iterations_per_frame" type="int" setter="" getter="" default="10">
</member>

View File

@ -74,7 +74,7 @@
<method name="get_collision_point" qualifiers="const">
<return type="Vector2" />
<description>
Returns the collision point at which the ray intersects the closest object.
Returns the collision point at which the ray intersects the closest object. If [member hit_from_inside] is [code]true[/code] and the ray starts inside of a collision shape, this function will return the origin point of the ray.
[b]Note:[/b] This point is in the [b]global[/b] coordinate system.
</description>
</method>

View File

@ -75,7 +75,7 @@
<method name="get_collision_point" qualifiers="const">
<return type="Vector3" />
<description>
Returns the collision point at which the ray intersects the closest object.
Returns the collision point at which the ray intersects the closest object. If [member hit_from_inside] is [code]true[/code] and the ray starts inside of a collision shape, this function will return the origin point of the ray.
[b]Note:[/b] This point is in the [b]global[/b] coordinate system.
</description>
</method>

View File

@ -918,6 +918,14 @@
[b]Note:[/b] When using the OpenGL backend or when running in headless mode, this function always returns [code]null[/code].
</description>
</method>
<method name="debug_canvas_item_get_rect">
<return type="Rect2" />
<param index="0" name="item" type="RID" />
<description>
Returns the bounding rectangle for a canvas item in local space, as calculated by the renderer. This bound is used internally for culling.
[b]Warning:[/b] This function is intended for debugging in the editor, and will pass through and return a zero [Rect2] in exported projects.
</description>
</method>
<method name="decal_create">
<return type="RID" />
<description>

View File

@ -4,7 +4,7 @@
A custom effect for a [RichTextLabel].
</brief_description>
<description>
A custom effect for a [RichTextLabel].
A custom effect for a [RichTextLabel], which can be loaded in the [RichTextLabel] inspector or using [method RichTextLabel.install_effect].
[b]Note:[/b] For a [RichTextEffect] to be usable, a BBCode tag must be defined as a member variable called [code]bbcode[/code] in the script.
[codeblocks]
[gdscript]

View File

@ -218,7 +218,28 @@
<return type="void" />
<param index="0" name="effect" type="Variant" />
<description>
Installs a custom effect. [param effect] should be a valid [RichTextEffect].
Installs a custom effect. This can also be done in the RichTextLabel inspector using the [member custom_effects] property. [param effect] should be a valid [RichTextEffect].
Example RichTextEffect:
[codeblock]
# effect.gd
class_name MyCustomEffect
extends RichTextEffect
var bbcode = "my_custom_effect"
# ...
[/codeblock]
Registering the above effect in RichTextLabel from script:
[codeblock]
# rich_text_label.gd
extends RichTextLabel
func _ready():
install_effect(MyCustomEffect.new())
# Alternatively, if not using `class_name` in the script that extends RichTextEffect:
install_effect(preload("res://effect.gd").new())
[/codeblock]
</description>
</method>
<method name="is_menu_visible" qualifiers="const">

View File

@ -7,7 +7,6 @@
[Skeleton3D] provides an interface for managing a hierarchy of bones, including pose, rest and animation (see [Animation]). It can also use ragdoll physics.
The overall transform of a bone with respect to the skeleton is determined by bone pose. Bone rest defines the initial transform of the bone pose.
Note that "global pose" below refers to the overall transform of the bone with respect to skeleton, so it is not the actual global/world transform of the bone.
To setup different types of inverse kinematics, consider using [SkeletonIK3D], or add a custom IK implementation in [method Node._process] as a child node.
</description>
<tutorials>
<link title="3D Inverse Kinematics Demo">https://godotengine.org/asset-library/asset/523</link>

View File

@ -41,6 +41,7 @@
<method name="get_physics_rid" qualifiers="const">
<return type="RID" />
<description>
Returns the internal [RID] used by the [PhysicsServer3D] for this body.
</description>
</method>
<method name="get_point_transform">
@ -100,11 +101,14 @@
[b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information.
</member>
<member name="damping_coefficient" type="float" setter="set_damping_coefficient" getter="get_damping_coefficient" default="0.01">
The body's damping coefficient. Higher values will slow down the body more noticeably when forces are applied.
</member>
<member name="disable_mode" type="int" setter="set_disable_mode" getter="get_disable_mode" enum="SoftBody3D.DisableMode" default="0">
Defines the behavior in physics when [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED]. See [enum DisableMode] for more details about the different modes.
</member>
<member name="drag_coefficient" type="float" setter="set_drag_coefficient" getter="get_drag_coefficient" default="0.0">
The body's drag coefficient. Higher values increase this body's air resistance.
[b]Note:[/b] This value is currently unused by Godot's default physics implementation.
</member>
<member name="linear_stiffness" type="float" setter="set_linear_stiffness" getter="get_linear_stiffness" default="0.5">
Higher values will result in a stiffer body, while lower values will increase the body's ability to bend. The value can be between [code]0.0[/code] and [code]1.0[/code] (inclusive).
@ -113,6 +117,7 @@
[NodePath] to a [CollisionObject3D] this SoftBody3D should avoid clipping.
</member>
<member name="pressure_coefficient" type="float" setter="set_pressure_coefficient" getter="get_pressure_coefficient" default="0.0">
The pressure coefficient of this soft body. Simulate pressure build-up from inside this body. Higher values increase the strength of this effect.
</member>
<member name="ray_pickable" type="bool" setter="set_ray_pickable" getter="is_ray_pickable" default="true">
If [code]true[/code], the [SoftBody3D] will respond to [RayCast3D]s.

View File

@ -96,13 +96,14 @@
[gdscript]
"move_local_x".capitalize() # Returns "Move Local X"
"sceneFile_path".capitalize() # Returns "Scene File Path"
"2D, FPS, PNG".capitalize() # Returns "2d, Fps, Png"
[/gdscript]
[csharp]
"move_local_x".Capitalize(); // Returns "Move Local X"
"sceneFile_path".Capitalize(); // Returns "Scene File Path"
"2D, FPS, PNG".Capitalize(); // Returns "2d, Fps, Png"
[/csharp]
[/codeblocks]
[b]Note:[/b] This method not the same as the default appearance of properties in the Inspector dock, as it does not capitalize acronyms ([code]"2D"[/code], [code]"FPS"[/code], [code]"PNG"[/code], etc.) as you may expect.
</description>
</method>
<method name="casecmp_to" qualifiers="const">
@ -943,7 +944,7 @@
<method name="to_lower" qualifiers="const">
<return type="String" />
<description>
Returns the string converted to lowercase.
Returns the string converted to [code]lowercase[/code].
</description>
</method>
<method name="to_pascal_case" qualifiers="const">
@ -956,12 +957,25 @@
<return type="String" />
<description>
Returns the string converted to [code]snake_case[/code].
[b]Note:[/b] Numbers followed by a [i]single[/i] letter are not separated in the conversion to keep some words (such as "2D") together.
[codeblocks]
[gdscript]
"Node2D".to_snake_case() # Returns "node_2d"
"2nd place".to_snake_case() # Returns "2_nd_place"
"Texture3DAssetFolder".to_snake_case() # Returns "texture_3d_asset_folder"
[/gdscript]
[csharp]
"Node2D".ToSnakeCase(); // Returns "node_2d"
"2nd place".ToSnakeCase(); // Returns "2_nd_place"
"Texture3DAssetFolder".ToSnakeCase(); // Returns "texture_3d_asset_folder"
[/csharp]
[/codeblocks]
</description>
</method>
<method name="to_upper" qualifiers="const">
<return type="String" />
<description>
Returns the string converted to uppercase.
Returns the string converted to [code]UPPERCASE[/code].
</description>
</method>
<method name="to_utf8_buffer" qualifiers="const">

View File

@ -8,6 +8,7 @@
You will usually just pass a [String] to methods expecting a [StringName] and it will be automatically converted, but you may occasionally want to construct a [StringName] ahead of time with the [StringName] constructor or, in GDScript, the literal syntax [code]&amp;"example"[/code].
See also [NodePath], which is a similar concept specifically designed to store pre-parsed scene tree paths.
All of [String]'s methods are available in this class too. They convert the [StringName] into a string, and they also return a string. This is highly inefficient and should only be used if the string is desired.
[b]Note:[/b] In C#, an explicit conversion to [code]System.String[/code] is required to use the methods listed on this page. Use the [code]ToString()[/code] method to cast a [StringName] to a string, and then use the equivalent methods in [code]System.String[/code] or [code]StringExtensions[/code].
[b]Note:[/b] In a boolean context, a [StringName] will evaluate to [code]false[/code] if it is empty ([code]StringName("")[/code]). Otherwise, a [StringName] will always evaluate to [code]true[/code]. The [code]not[/code] operator cannot be used. Instead, [method is_empty] should be used to check for empty [StringName]s.
</description>
<tutorials>
@ -90,13 +91,14 @@
[gdscript]
"move_local_x".capitalize() # Returns "Move Local X"
"sceneFile_path".capitalize() # Returns "Scene File Path"
"2D, FPS, PNG".capitalize() # Returns "2d, Fps, Png"
[/gdscript]
[csharp]
"move_local_x".Capitalize(); // Returns "Move Local X"
"sceneFile_path".Capitalize(); // Returns "Scene File Path"
"2D, FPS, PNG".Capitalize(); // Returns "2d, Fps, Png"
[/csharp]
[/codeblocks]
[b]Note:[/b] This method not the same as the default appearance of properties in the Inspector dock, as it does not capitalize acronyms ([code]"2D"[/code], [code]"FPS"[/code], [code]"PNG"[/code], etc.) as you may expect.
</description>
</method>
<method name="casecmp_to" qualifiers="const">
@ -850,7 +852,7 @@
<method name="to_lower" qualifiers="const">
<return type="String" />
<description>
Returns the string converted to lowercase.
Returns the string converted to [code]lowercase[/code].
</description>
</method>
<method name="to_pascal_case" qualifiers="const">
@ -863,12 +865,25 @@
<return type="String" />
<description>
Returns the string converted to [code]snake_case[/code].
[b]Note:[/b] Numbers followed by a [i]single[/i] letter are not separated in the conversion to keep some words (such as "2D") together.
[codeblocks]
[gdscript]
"Node2D".to_snake_case() # Returns "node_2d"
"2nd place".to_snake_case() # Returns "2_nd_place"
"Texture3DAssetFolder".to_snake_case() # Returns "texture_3d_asset_folder"
[/gdscript]
[csharp]
"Node2D".ToSnakeCase(); // Returns "node_2d"
"2nd place".ToSnakeCase(); // Returns "2_nd_place"
"Texture3DAssetFolder".ToSnakeCase(); // Returns "texture_3d_asset_folder"
[/csharp]
[/codeblocks]
</description>
</method>
<method name="to_upper" qualifiers="const">
<return type="String" />
<description>
Returns the string converted to uppercase.
Returns the string converted to [code]UPPERCASE[/code].
</description>
</method>
<method name="to_utf8_buffer" qualifiers="const">

View File

@ -1647,6 +1647,7 @@
Vertical BGR subpixel layout.
</constant>
<constant name="FONT_LCD_SUBPIXEL_LAYOUT_MAX" value="5" enum="FontLCDSubpixelLayout">
Represents the size of the [enum FontLCDSubpixelLayout] enum.
</constant>
<constant name="DIRECTION_AUTO" value="0" enum="Direction">
Text direction is determined based on contents and current locale.
@ -1770,6 +1771,7 @@
Determines whether the ellipsis at the end of the text is enforced and may not be hidden.
</constant>
<constant name="OVERRUN_JUSTIFICATION_AWARE" value="16" enum="TextOverrunFlag" is_bitfield="true">
Accounts for the text being justified before attempting to trim it (see [enum JustificationFlag]).
</constant>
<constant name="GRAPHEME_IS_VALID" value="1" enum="GraphemeFlag" is_bitfield="true">
Grapheme is supported by the font, and can be drawn.
@ -1908,6 +1910,7 @@
Spacing at the bottom of the line.
</constant>
<constant name="SPACING_MAX" value="4" enum="SpacingType">
Represents the size of the [enum SpacingType] enum.
</constant>
<constant name="FONT_BOLD" value="1" enum="FontStyle" is_bitfield="true">
Font is bold.

View File

@ -81,7 +81,7 @@
This is the distance in meters the wheel is lowered from its origin point. Don't set this to 0.0 and move the wheel into position, instead move the origin point of your wheel (the gizmo in Godot) to the position the wheel will take when bottoming out, then use the rest length to move the wheel down to the position it should be in when the car is in rest.
</member>
<member name="wheel_roll_influence" type="float" setter="set_roll_influence" getter="get_roll_influence" default="0.1">
This value affects the roll of your vehicle. If set to 1.0 for all wheels, your vehicle will be prone to rolling over, while a value of 0.0 will resist body roll.
This value affects the roll of your vehicle. If set to 1.0 for all wheels, your vehicle will resist body roll, while a value of 0.0 will be prone to rolling over.
</member>
</members>
</class>

View File

@ -774,6 +774,7 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
_render_batch(p_lights, i);
}
glDisable(GL_SCISSOR_TEST);
state.current_batch_index = 0;
state.canvas_instance_batches.clear();
state.last_item_index += index;

View File

@ -434,8 +434,7 @@ layout(std140) uniform GlobalShaderUniformData { //ubo:1
vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS];
};
/* Material Uniforms */
/* Material Uniforms */
#ifdef MATERIAL_UNIFORMS_USED
/* clang-format off */

View File

@ -248,6 +248,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
s->aabb = p_surface.aabb;
s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
s->mesh_to_skeleton_xform = p_surface.mesh_to_skeleton_xform;
if (p_surface.skin_data.size() || mesh->blend_shape_count > 0) {
// Size must match the size of the vertex array.
@ -471,6 +472,7 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
}
sd.bone_aabbs = s.bone_aabbs;
sd.mesh_to_skeleton_xform = s.mesh_to_skeleton_xform;
if (mesh->blend_shape_count) {
sd.blend_shape_data = Vector<uint8_t>();
@ -522,15 +524,16 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
for (uint32_t i = 0; i < mesh->surface_count; i++) {
AABB laabb;
if ((mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->bone_aabbs.size()) {
int bs = mesh->surfaces[i]->bone_aabbs.size();
const AABB *skbones = mesh->surfaces[i]->bone_aabbs.ptr();
const Mesh::Surface &surface = *mesh->surfaces[i];
if ((surface.format & RS::ARRAY_FORMAT_BONES) && surface.bone_aabbs.size()) {
int bs = surface.bone_aabbs.size();
const AABB *skbones = surface.bone_aabbs.ptr();
int sbs = skeleton->size;
ERR_CONTINUE(bs > sbs);
const float *baseptr = skeleton->data.ptr();
bool first = true;
bool found_bone_aabb = false;
if (skeleton->use_2d) {
for (int j = 0; j < bs; j++) {
@ -550,11 +553,13 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
mtx.basis.rows[1][1] = dataptr[5];
mtx.origin.y = dataptr[7];
AABB baabb = mtx.xform(skbones[j]);
// Transform bounds to skeleton's space before applying animation data.
AABB baabb = surface.mesh_to_skeleton_xform.xform(skbones[j]);
baabb = mtx.xform(baabb);
if (first) {
if (!found_bone_aabb) {
laabb = baabb;
first = false;
found_bone_aabb = true;
} else {
laabb.merge_with(baabb);
}
@ -582,21 +587,29 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
mtx.basis.rows[2][2] = dataptr[10];
mtx.origin.z = dataptr[11];
AABB baabb = mtx.xform(skbones[j]);
if (first) {
// Transform bounds to skeleton's space before applying animation data.
AABB baabb = surface.mesh_to_skeleton_xform.xform(skbones[j]);
baabb = mtx.xform(baabb);
if (!found_bone_aabb) {
laabb = baabb;
first = false;
found_bone_aabb = true;
} else {
laabb.merge_with(baabb);
}
}
}
if (found_bone_aabb) {
// Transform skeleton bounds back to mesh's space if any animated AABB applied.
laabb = surface.mesh_to_skeleton_xform.affine_inverse().xform(laabb);
}
if (laabb.size == Vector3()) {
laabb = mesh->surfaces[i]->aabb;
laabb = surface.aabb;
}
} else {
laabb = mesh->surfaces[i]->aabb;
laabb = surface.aabb;
}
if (i == 0) {

View File

@ -103,6 +103,10 @@ struct Mesh {
Vector<AABB> bone_aabbs;
// Transform used in runtime bone AABBs compute.
// As bone AABBs are saved in Mesh space, but bones animation is in Skeleton space.
Transform3D mesh_to_skeleton_xform;
struct BlendShape {
GLuint vertex_buffer = 0;
GLuint vertex_array = 0;

View File

@ -6713,24 +6713,24 @@ Error RenderingDeviceVulkan::_draw_list_setup_framebuffer(Framebuffer *p_framebu
return OK;
}
Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i viewport_offset, Point2i viewport_size, VkFramebuffer vkframebuffer, VkRenderPass render_pass, VkCommandBuffer command_buffer, VkSubpassContents subpass_contents, const Vector<RID> &p_storage_textures) {
Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i viewport_offset, Point2i viewport_size, VkFramebuffer vkframebuffer, VkRenderPass render_pass, VkCommandBuffer command_buffer, VkSubpassContents subpass_contents, const Vector<RID> &p_storage_textures, bool p_constrained_to_region) {
VkRenderPassBeginInfo render_pass_begin;
render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
render_pass_begin.pNext = nullptr;
render_pass_begin.renderPass = render_pass;
render_pass_begin.framebuffer = vkframebuffer;
/*
* Given how API works, it makes sense to always fully operate on the whole framebuffer.
* This allows better continue operations for operations like shadowmapping.
render_pass_begin.renderArea.extent.width = viewport_size.width;
render_pass_begin.renderArea.extent.height = viewport_size.height;
render_pass_begin.renderArea.offset.x = viewport_offset.x;
render_pass_begin.renderArea.offset.y = viewport_offset.y;
*/
render_pass_begin.renderArea.extent.width = framebuffer->size.width;
render_pass_begin.renderArea.extent.height = framebuffer->size.height;
render_pass_begin.renderArea.offset.x = 0;
render_pass_begin.renderArea.offset.y = 0;
if (p_constrained_to_region) {
render_pass_begin.renderArea.extent.width = viewport_size.width;
render_pass_begin.renderArea.extent.height = viewport_size.height;
render_pass_begin.renderArea.offset.x = viewport_offset.x;
render_pass_begin.renderArea.offset.y = viewport_offset.y;
} else {
render_pass_begin.renderArea.extent.width = framebuffer->size.width;
render_pass_begin.renderArea.extent.height = framebuffer->size.height;
render_pass_begin.renderArea.offset.x = 0;
render_pass_begin.renderArea.offset.y = 0;
}
Vector<VkClearValue> clear_values;
clear_values.resize(framebuffer->texture_ids.size());
@ -6880,6 +6880,7 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
Point2i viewport_offset;
Point2i viewport_size = framebuffer->size;
bool constrained_to_region = false;
bool needs_clear_color = false;
bool needs_clear_depth = false;
@ -6894,21 +6895,30 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
viewport_offset = regioni.position;
viewport_size = regioni.size;
if (p_initial_color_action == INITIAL_ACTION_CLEAR_REGION_CONTINUE) {
needs_clear_color = true;
p_initial_color_action = INITIAL_ACTION_CONTINUE;
}
if (p_initial_depth_action == INITIAL_ACTION_CLEAR_REGION_CONTINUE) {
needs_clear_depth = true;
p_initial_depth_action = INITIAL_ACTION_CONTINUE;
}
if (p_initial_color_action == INITIAL_ACTION_CLEAR_REGION) {
needs_clear_color = true;
p_initial_color_action = INITIAL_ACTION_KEEP;
}
if (p_initial_depth_action == INITIAL_ACTION_CLEAR_REGION) {
needs_clear_depth = true;
p_initial_depth_action = INITIAL_ACTION_KEEP;
// If clearing regions both in color and depth, we can switch to a fast path where we let Vulkan to the clears
// and we constrain the render area to the region.
if (p_initial_color_action == INITIAL_ACTION_CLEAR_REGION && p_initial_depth_action == INITIAL_ACTION_CLEAR_REGION) {
constrained_to_region = true;
p_initial_color_action = INITIAL_ACTION_CLEAR;
p_initial_depth_action = INITIAL_ACTION_CLEAR;
} else {
if (p_initial_color_action == INITIAL_ACTION_CLEAR_REGION_CONTINUE) {
needs_clear_color = true;
p_initial_color_action = INITIAL_ACTION_CONTINUE;
}
if (p_initial_depth_action == INITIAL_ACTION_CLEAR_REGION_CONTINUE) {
needs_clear_depth = true;
p_initial_depth_action = INITIAL_ACTION_CONTINUE;
}
if (p_initial_color_action == INITIAL_ACTION_CLEAR_REGION) {
needs_clear_color = true;
p_initial_color_action = INITIAL_ACTION_KEEP;
}
if (p_initial_depth_action == INITIAL_ACTION_CLEAR_REGION) {
needs_clear_depth = true;
p_initial_depth_action = INITIAL_ACTION_KEEP;
}
}
}
@ -6935,7 +6945,7 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
ERR_FAIL_COND_V(err != OK, INVALID_ID);
VkCommandBuffer command_buffer = frames[frame].draw_command_buffer;
err = _draw_list_render_pass_begin(framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, viewport_offset, viewport_size, vkframebuffer, render_pass, command_buffer, VK_SUBPASS_CONTENTS_INLINE, p_storage_textures);
err = _draw_list_render_pass_begin(framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, viewport_offset, viewport_size, vkframebuffer, render_pass, command_buffer, VK_SUBPASS_CONTENTS_INLINE, p_storage_textures, constrained_to_region);
if (err != OK) {
return INVALID_ID;
@ -6951,6 +6961,7 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
draw_list_current_subpass = 0;
if (needs_clear_color || needs_clear_depth) {
DEV_ASSERT(!constrained_to_region);
_draw_list_insert_clear_region(draw_list, framebuffer, viewport_offset, viewport_size, needs_clear_color, p_clear_color_values, needs_clear_depth, p_clear_depth, p_clear_stencil);
}
@ -6989,6 +7000,7 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p
Point2i viewport_offset;
Point2i viewport_size = framebuffer->size;
bool constrained_to_region = false;
bool needs_clear_color = false;
bool needs_clear_depth = false;
@ -7004,13 +7016,29 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p
viewport_offset = regioni.position;
viewport_size = regioni.size;
if (p_initial_color_action == INITIAL_ACTION_CLEAR_REGION) {
needs_clear_color = true;
p_initial_color_action = INITIAL_ACTION_KEEP;
}
if (p_initial_depth_action == INITIAL_ACTION_CLEAR_REGION) {
needs_clear_depth = true;
p_initial_depth_action = INITIAL_ACTION_KEEP;
// If clearing regions both in color and depth, we can switch to a fast path where we let Vulkan to the clears
// and we constrain the render area to the region.
if (p_initial_color_action == INITIAL_ACTION_CLEAR_REGION && p_initial_depth_action == INITIAL_ACTION_CLEAR_REGION) {
constrained_to_region = true;
p_initial_color_action = INITIAL_ACTION_CLEAR;
p_initial_depth_action = INITIAL_ACTION_CLEAR;
} else {
if (p_initial_color_action == INITIAL_ACTION_CLEAR_REGION_CONTINUE) {
needs_clear_color = true;
p_initial_color_action = INITIAL_ACTION_CONTINUE;
}
if (p_initial_depth_action == INITIAL_ACTION_CLEAR_REGION_CONTINUE) {
needs_clear_depth = true;
p_initial_depth_action = INITIAL_ACTION_CONTINUE;
}
if (p_initial_color_action == INITIAL_ACTION_CLEAR_REGION) {
needs_clear_color = true;
p_initial_color_action = INITIAL_ACTION_KEEP;
}
if (p_initial_depth_action == INITIAL_ACTION_CLEAR_REGION) {
needs_clear_depth = true;
p_initial_depth_action = INITIAL_ACTION_KEEP;
}
}
}
@ -7036,7 +7064,7 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
VkCommandBuffer frame_command_buffer = frames[frame].draw_command_buffer;
err = _draw_list_render_pass_begin(framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, viewport_offset, viewport_size, vkframebuffer, render_pass, frame_command_buffer, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, p_storage_textures);
err = _draw_list_render_pass_begin(framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, viewport_offset, viewport_size, vkframebuffer, render_pass, frame_command_buffer, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, p_storage_textures, constrained_to_region);
if (err != OK) {
return ERR_CANT_CREATE;
@ -7056,6 +7084,7 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p
}
if (needs_clear_color || needs_clear_depth) {
DEV_ASSERT(!constrained_to_region);
_draw_list_insert_clear_region(&draw_list[0], framebuffer, viewport_offset, viewport_size, needs_clear_color, p_clear_color_values, needs_clear_depth, p_clear_depth, p_clear_stencil);
}

View File

@ -159,7 +159,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
RID owner;
};
RID_Owner<Texture, true> texture_owner;
RID_Owner<Texture> texture_owner;
uint32_t texture_upload_region_size_px = 0;
Vector<uint8_t> _texture_get_data_from_image(Texture *tex, VkImage p_image, VmaAllocation p_allocation, uint32_t p_layer, bool p_2d = false);
@ -409,7 +409,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
uint32_t view_count;
};
RID_Owner<Framebuffer, true> framebuffer_owner;
RID_Owner<Framebuffer> framebuffer_owner;
/***********************/
/**** VERTEX BUFFER ****/
@ -424,7 +424,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
// This mapping is done here internally, and it's not
// exposed.
RID_Owner<Buffer, true> vertex_buffer_owner;
RID_Owner<Buffer> vertex_buffer_owner;
struct VertexDescriptionKey {
Vector<VertexAttribute> vertex_formats;
@ -506,7 +506,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
Vector<VkDeviceSize> offsets;
};
RID_Owner<VertexArray, true> vertex_array_owner;
RID_Owner<VertexArray> vertex_array_owner;
struct IndexBuffer : public Buffer {
uint32_t max_index = 0; // Used for validation.
@ -515,7 +515,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
bool supports_restart_indices = false;
};
RID_Owner<IndexBuffer, true> index_buffer_owner;
RID_Owner<IndexBuffer> index_buffer_owner;
struct IndexArray {
uint32_t max_index = 0; // Remember the maximum index here too, for validation.
@ -526,7 +526,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
bool supports_restart_indices = false;
};
RID_Owner<IndexArray, true> index_array_owner;
RID_Owner<IndexArray> index_array_owner;
/****************/
/**** SHADER ****/
@ -649,7 +649,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
String _shader_uniform_debug(RID p_shader, int p_set = -1);
RID_Owner<Shader, true> shader_owner;
RID_Owner<Shader> shader_owner;
/******************/
/**** UNIFORMS ****/
@ -713,8 +713,8 @@ class RenderingDeviceVulkan : public RenderingDevice {
DescriptorPool *_descriptor_pool_allocate(const DescriptorPoolKey &p_key);
void _descriptor_pool_free(const DescriptorPoolKey &p_key, DescriptorPool *p_pool);
RID_Owner<Buffer, true> uniform_buffer_owner;
RID_Owner<Buffer, true> storage_buffer_owner;
RID_Owner<Buffer> uniform_buffer_owner;
RID_Owner<Buffer> storage_buffer_owner;
// Texture buffer needs a view.
struct TextureBuffer {
@ -722,7 +722,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
VkBufferView view = VK_NULL_HANDLE;
};
RID_Owner<TextureBuffer, true> texture_buffer_owner;
RID_Owner<TextureBuffer> texture_buffer_owner;
// This structure contains the descriptor set. They _need_ to be allocated
// for a shader (and will be erased when this shader is erased), but should
@ -752,7 +752,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
void *invalidated_callback_userdata = nullptr;
};
RID_Owner<UniformSet, true> uniform_set_owner;
RID_Owner<UniformSet> uniform_set_owner;
/*******************/
/**** PIPELINES ****/
@ -791,7 +791,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
uint32_t push_constant_stages_mask = 0;
};
RID_Owner<RenderPipeline, true> render_pipeline_owner;
RID_Owner<RenderPipeline> render_pipeline_owner;
struct PipelineCacheHeader {
uint32_t magic;
@ -828,7 +828,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
uint32_t local_group_size[3] = { 0, 0, 0 };
};
RID_Owner<ComputePipeline, true> compute_pipeline_owner;
RID_Owner<ComputePipeline> compute_pipeline_owner;
/*******************/
/**** DRAW LIST ****/
@ -929,7 +929,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
void _draw_list_insert_clear_region(DrawList *p_draw_list, Framebuffer *p_framebuffer, Point2i p_viewport_offset, Point2i p_viewport_size, bool p_clear_color, const Vector<Color> &p_clear_colors, bool p_clear_depth, float p_depth, uint32_t p_stencil);
Error _draw_list_setup_framebuffer(Framebuffer *p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, VkFramebuffer *r_framebuffer, VkRenderPass *r_render_pass, uint32_t *r_subpass_count);
Error _draw_list_render_pass_begin(Framebuffer *framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i viewport_offset, Point2i viewport_size, VkFramebuffer vkframebuffer, VkRenderPass render_pass, VkCommandBuffer command_buffer, VkSubpassContents subpass_contents, const Vector<RID> &p_storage_textures);
Error _draw_list_render_pass_begin(Framebuffer *framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i viewport_offset, Point2i viewport_size, VkFramebuffer vkframebuffer, VkRenderPass render_pass, VkCommandBuffer command_buffer, VkSubpassContents subpass_contents, const Vector<RID> &p_storage_textures, bool p_constrained_to_region);
_FORCE_INLINE_ DrawList *_get_draw_list_ptr(DrawListID p_id);
Buffer *_get_buffer_from_owner(RID p_buffer, VkPipelineStageFlags &dst_stage_mask, VkAccessFlags &dst_access, BitField<BarrierMask> p_post_barrier);
Error _draw_list_allocate(const Rect2i &p_viewport, uint32_t p_splits, uint32_t p_subpass);

View File

@ -557,13 +557,11 @@ Error AudioDriverWASAPI::init() {
target_latency_ms = GLOBAL_GET("audio/driver/output_latency");
Error err = init_output_device();
if (err != OK) {
ERR_PRINT("WASAPI: init_output_device error");
}
exit_thread.clear();
Error err = init_output_device();
ERR_FAIL_COND_V_MSG(err != OK, err, "WASAPI: init_output_device error.");
thread.start(thread_func, this);
return OK;

View File

@ -2148,6 +2148,9 @@ Error EditorFileSystem::_reimport_file(const String &p_file, const HashMap<Strin
}
}
// Update cpos, newly created files could've changed the index of the reimported p_file.
_find_file(p_file, &fs, cpos);
//update modified times, to avoid reimport
fs->files[cpos]->modified_time = FileAccess::get_modified_time(p_file);
fs->files[cpos]->import_modified_time = FileAccess::get_modified_time(p_file + ".import");
@ -2342,7 +2345,13 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) {
Error EditorFileSystem::reimport_append(const String &p_file, const HashMap<StringName, Variant> &p_custom_options, const String &p_custom_importer, Variant p_generator_parameters) {
ERR_FAIL_COND_V_MSG(!importing, ERR_INVALID_PARAMETER, "Can only append files to import during a current reimport process.");
return _reimport_file(p_file, p_custom_options, p_custom_importer, &p_generator_parameters);
Error ret = _reimport_file(p_file, p_custom_options, p_custom_importer, &p_generator_parameters);
// Emit the resource_reimported signal for the single file we just reimported.
Vector<String> reloads;
reloads.append(p_file);
emit_signal(SNAME("resources_reimported"), reloads);
return ret;
}
Error EditorFileSystem::_resource_import(const String &p_path) {

View File

@ -2925,6 +2925,16 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
} break;
case SET_RENDERER_NAME_SAVE_AND_RESTART: {
ProjectSettings::get_singleton()->set("rendering/renderer/rendering_method", renderer_request);
if (renderer_request == "mobile" || renderer_request == "gl_compatibility") {
// Also change the mobile override if changing to a compatible rendering method.
// This prevents visual discrepancies between desktop and mobile platforms.
ProjectSettings::get_singleton()->set("rendering/renderer/rendering_method.mobile", renderer_request);
} else if (renderer_request == "forward_plus") {
// Use the equivalent mobile rendering method. This prevents the rendering method from staying
// on its old choice if moving from `gl_compatibility` to `forward_plus`.
ProjectSettings::get_singleton()->set("rendering/renderer/rendering_method.mobile", "mobile");
}
ProjectSettings::get_singleton()->save();
save_all_scenes();
@ -6571,6 +6581,9 @@ void EditorNode::_renderer_selected(int p_which) {
}
renderer_request = rendering_method;
video_restart_dialog->set_text(
vformat(TTR("Changing the renderer requires restarting the editor.\n\nChoosing Save & Restart will change the rendering method to:\n- Desktop platforms: %s\n- Mobile platforms: %s\n- Web platform: gl_compatibility"),
renderer_request, renderer_request.replace("forward_plus", "mobile")));
video_restart_dialog->popup_centered();
renderer->select(renderer_current);
_update_renderer_color();
@ -7583,7 +7596,7 @@ EditorNode::EditorNode() {
renderer->connect("item_selected", callable_mp(this, &EditorNode::_renderer_selected));
renderer->add_theme_font_override("font", gui_base->get_theme_font(SNAME("bold"), SNAME("EditorFonts")));
renderer->add_theme_font_size_override("font_size", gui_base->get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts")));
renderer->set_tooltip_text(TTR("Choose a renderer."));
renderer->set_tooltip_text(TTR("Choose a rendering method.\n\nNotes:\n- On mobile platforms, the Mobile rendering method is used if Forward+ is selected here.\n- On the web platform, the Compatibility rendering method is always used."));
right_menu_hb->add_child(renderer);
@ -7628,7 +7641,6 @@ EditorNode::EditorNode() {
_update_renderer_color();
video_restart_dialog = memnew(ConfirmationDialog);
video_restart_dialog->set_text(TTR("Changing the renderer requires restarting the editor."));
video_restart_dialog->set_ok_button_text(TTR("Save & Restart"));
video_restart_dialog->connect("confirmed", callable_mp(this, &EditorNode::_menu_option).bind(SET_RENDERER_NAME_SAVE_AND_RESTART));
gui_base->add_child(video_restart_dialog);

View File

@ -465,6 +465,13 @@ bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_
break;
}
if (String::utf8(fname).ends_with("/")) {
// File is a directory, ignore it.
// Directories will be created when extracting each file.
ret = unzGoToNextFile(pkg);
continue;
}
String file_path(String::utf8(fname).simplify_path());
String file = file_path.get_file();

View File

@ -536,7 +536,7 @@ void ScriptEditor::_set_breakpoint(Ref<RefCounted> p_script, int p_line, bool p_
}
state["breakpoints"] = breakpoints;
script_editor_cache->set_value(scr->get_path(), "state", state);
EditorDebuggerNode::get_singleton()->set_breakpoint(scr->get_path(), p_line + 1, false);
EditorDebuggerNode::get_singleton()->set_breakpoint(scr->get_path(), p_line + 1, p_enabled);
}
}

View File

@ -1044,107 +1044,108 @@ bool ProjectConverter3To4::test_conversion(RegExContainer &reg_container) {
// get_object_of_execution
{
{ String base = "var roman = kieliszek.";
String expected = "kieliszek.";
String got = get_object_of_execution(base);
if (got != expected) {
ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size()));
String base = "var roman = kieliszek.";
String expected = "kieliszek.";
String got = get_object_of_execution(base);
if (got != expected) {
ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size()));
}
valid = valid && (got == expected);
}
valid = valid && (got == expected);
}
{
String base = "r.";
String expected = "r.";
String got = get_object_of_execution(base);
if (got != expected) {
ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size()));
{
String base = "r.";
String expected = "r.";
String got = get_object_of_execution(base);
if (got != expected) {
ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size()));
}
valid = valid && (got == expected);
}
valid = valid && (got == expected);
}
{
String base = "mortadela(";
String expected = "";
String got = get_object_of_execution(base);
if (got != expected) {
ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size()));
{
String base = "mortadela(";
String expected = "";
String got = get_object_of_execution(base);
if (got != expected) {
ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size()));
}
valid = valid && (got == expected);
}
valid = valid && (got == expected);
}
{
String base = "var node = $world/ukraine/lviv.";
String expected = "$world/ukraine/lviv.";
String got = get_object_of_execution(base);
if (got != expected) {
ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size()));
{
String base = "var node = $world/ukraine/lviv.";
String expected = "$world/ukraine/lviv.";
String got = get_object_of_execution(base);
if (got != expected) {
ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size()));
}
valid = valid && (got == expected);
}
valid = valid && (got == expected);
}
}
// get_starting_space
{
String base = "\t\t\t var roman = kieliszek.";
String expected = "\t\t\t";
String got = get_starting_space(base);
if (got != expected) {
ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size()));
}
valid = valid && (got == expected);
}
// Parse Arguments
{
String line = "( )";
Vector<String> got_vector = parse_arguments(line);
String got = "";
String expected = "";
for (String &part : got_vector) {
got += part + "|||";
}
if (got != expected) {
ERR_PRINT(vformat("Failed to get proper data from parse_arguments. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", line, expected, expected.size(), got, got.size()));
}
valid = valid && (got == expected);
}
{
String line = "(a , b , c)";
Vector<String> got_vector = parse_arguments(line);
String got = "";
String expected = "a|||b|||c|||";
for (String &part : got_vector) {
got += part + "|||";
}
if (got != expected) {
ERR_PRINT(vformat("Failed to get proper data from parse_arguments. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", line, expected, expected.size(), got, got.size()));
}
valid = valid && (got == expected);
}
{
String line = "(a , \"b,\" , c)";
Vector<String> got_vector = parse_arguments(line);
String got = "";
String expected = "a|||\"b,\"|||c|||";
for (String &part : got_vector) {
got += part + "|||";
}
if (got != expected) {
ERR_PRINT(vformat("Failed to get proper data from parse_arguments. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", line, expected, expected.size(), got, got.size()));
}
valid = valid && (got == expected);
}
{
String line = "(a , \"(,),,,,\" , c)";
Vector<String> got_vector = parse_arguments(line);
String got = "";
String expected = "a|||\"(,),,,,\"|||c|||";
for (String &part : got_vector) {
got += part + "|||";
}
if (got != expected) {
ERR_PRINT(vformat("Failed to get proper data from parse_arguments. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", line, expected, expected.size(), got, got.size()));
}
valid = valid && (got == expected);
}
return valid;
// get_starting_space
{
String base = "\t\t\t var roman = kieliszek.";
String expected = "\t\t\t";
String got = get_starting_space(base);
if (got != expected) {
ERR_PRINT(vformat("Failed to get proper data from get_object_of_execution. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", base, expected, expected.size(), got, got.size()));
}
valid = valid && (got == expected);
}
// Parse Arguments
{
String line = "( )";
Vector<String> got_vector = parse_arguments(line);
String got = "";
String expected = "";
for (String &part : got_vector) {
got += part + "|||";
}
if (got != expected) {
ERR_PRINT(vformat("Failed to get proper data from parse_arguments. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", line, expected, expected.size(), got, got.size()));
}
valid = valid && (got == expected);
}
{
String line = "(a , b , c)";
Vector<String> got_vector = parse_arguments(line);
String got = "";
String expected = "a|||b|||c|||";
for (String &part : got_vector) {
got += part + "|||";
}
if (got != expected) {
ERR_PRINT(vformat("Failed to get proper data from parse_arguments. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", line, expected, expected.size(), got, got.size()));
}
valid = valid && (got == expected);
}
{
String line = "(a , \"b,\" , c)";
Vector<String> got_vector = parse_arguments(line);
String got = "";
String expected = "a|||\"b,\"|||c|||";
for (String &part : got_vector) {
got += part + "|||";
}
if (got != expected) {
ERR_PRINT(vformat("Failed to get proper data from parse_arguments. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", line, expected, expected.size(), got, got.size()));
}
valid = valid && (got == expected);
}
{
String line = "(a , \"(,),,,,\" , c)";
Vector<String> got_vector = parse_arguments(line);
String got = "";
String expected = "a|||\"(,),,,,\"|||c|||";
for (String &part : got_vector) {
got += part + "|||";
}
if (got != expected) {
ERR_PRINT(vformat("Failed to get proper data from parse_arguments. \"%s\" should return \"%s\"(%d), got \"%s\"(%d), instead.", line, expected, expected.size(), got, got.size()));
}
valid = valid && (got == expected);
}
return valid;
}
// Validate in all arrays if names don't do cyclic renames "Node" -> "Node2D" | "Node2D" -> "2DNode"

View File

@ -163,6 +163,7 @@ const char *RenamesMap3To4::gdscript_function_renames[][2] = {
// { "_set_name", "get_tracker_name" }, // XRPositionalTracker -- CameraFeed uses this.
// { "_unhandled_input", "_unhandled_key_input" }, // BaseButton, ViewportContainer -- Breaks Node, FileDialog, SubViewportContainer.
// { "add_animation", "add_animation_library" }, // AnimationPlayer -- Breaks SpriteFrames (and isn't a correct conversion).
// { "create_gizmo", "_create_gizmo" }, // EditorNode3DGizmoPlugin -- May be used.
// { "get_dependencies", "_get_dependencies" }, // ResourceFormatLoader -- Breaks ResourceLoader.
// { "get_extents", "get_size" }, // BoxShape, RectangleShape -- Breaks Decal, VoxelGI, GPUParticlesCollisionBox, GPUParticlesCollisionSDF, GPUParticlesCollisionHeightField, GPUParticlesAttractorBox, GPUParticlesAttractorVectorField, FogVolume
@ -214,8 +215,6 @@ const char *RenamesMap3To4::gdscript_function_renames[][2] = {
{ "_set_current", "set_current" }, // Camera2D
{ "_set_editor_description", "set_editor_description" }, // Node
{ "_toplevel_raise_self", "_top_level_raise_self" }, // CanvasItem
{ "_update_wrap_at", "_update_wrap_at_column" }, // TextEdit
{ "add_animation", "add_animation_library" }, // AnimationPlayer
{ "add_cancel", "add_cancel_button" }, // AcceptDialog
{ "add_central_force", "apply_central_force" }, //RigidBody2D
{ "add_child_below_node", "add_sibling" }, // Node
@ -643,8 +642,6 @@ const char *RenamesMap3To4::csharp_function_renames[][2] = {
{ "_SetEditorDescription", "SetEditorDescription" }, // Node
{ "_SetPlaying", "SetPlaying" }, // AnimatedSprite3D
{ "_ToplevelRaiseSelf", "_TopLevelRaiseSelf" }, // CanvasItem
{ "_UpdateWrapAt", "_UpdateWrapAtColumn" }, // TextEdit
{ "AddAnimation", "AddAnimationLibrary" }, // AnimationPlayer
{ "AddCancel", "AddCancelButton" }, // AcceptDialog
{ "AddCentralForce", "AddConstantCentralForce" }, //RigidBody2D
{ "AddChildBelowNode", "AddSibling" }, // Node

View File

@ -29,7 +29,7 @@ so they should work out of the box on Linux/macOS.
##### clang-format
- Download LLVM for Windows (version 13 or later) from
<https://releases.llvm.org/download.html>
<https://github.com/llvm/llvm-project/releases>
- Make sure LLVM is added to the `PATH` during installation
##### black

View File

@ -80,7 +80,7 @@ fi
# To get consistent formatting, we recommend contributors to use the same
# clang-format version as CI.
RECOMMENDED_CLANG_FORMAT_MAJOR_MIN="13"
RECOMMENDED_CLANG_FORMAT_MAJOR_MAX="15"
RECOMMENDED_CLANG_FORMAT_MAJOR_MAX="16"
if [ ! -x "$CLANG_FORMAT" ] ; then
message="Error: clang-format executable not found. Please install clang-format $RECOMMENDED_CLANG_FORMAT_MAJOR_MAX."

View File

@ -221,7 +221,7 @@ static Ref<Image> basis_universal_unpacker_ptr(const uint8_t *p_data, int p_size
imgfmt = Image::FORMAT_DXT5_RA_AS_RG;
} else if (RS::get_singleton()->has_os_feature("etc2")) {
format = basist::transcoder_texture_format::cTFETC2; // get this from renderer
imgfmt = Image::FORMAT_ETC2_RGBA8;
imgfmt = Image::FORMAT_ETC2_RA_AS_RG;
} else {
//opengl most likely, bad for normal maps, nothing to do about this.
format = basist::transcoder_texture_format::cTFRGBA32;

View File

@ -220,8 +220,12 @@ Ref<Resource> ResourceFormatDDS::load(const String &p_path, const String &p_orig
//compressed bc
uint32_t size = MAX(info.divisor, w) / info.divisor * MAX(info.divisor, h) / info.divisor * info.block_size;
ERR_FAIL_COND_V(size != pitch, Ref<Resource>());
ERR_FAIL_COND_V(!(flags & DDSD_LINEARSIZE), Ref<Resource>());
if (flags & DDSD_LINEARSIZE) {
ERR_FAIL_COND_V_MSG(size != pitch, Ref<Resource>(), "DDS header flags specify that a linear size of the top-level image is present, but the specified size does not match the expected value.");
} else {
ERR_FAIL_COND_V_MSG(pitch != 0, Ref<Resource>(), "DDS header flags specify that no linear size will given for the top-level image, but a non-zero linear size value is present in the header.");
}
for (uint32_t i = 1; i < mipmaps; i++) {
w = MAX(1u, w >> 1);

View File

@ -3126,7 +3126,7 @@ void GLTFDocument::_parse_image_save_image(Ref<GLTFState> p_state, const String
bool must_import = true;
Vector<uint8_t> img_data = p_image->get_data();
Dictionary generator_parameters;
String file_path = p_state->get_base_path() + "/" + p_state->filename.get_basename() + "_" + p_image->get_name() + ".png";
String file_path = p_state->get_base_path().path_join(p_state->filename.get_basename() + "_" + p_image->get_name()) + ".png";
if (FileAccess::exists(file_path + ".import")) {
Ref<ConfigFile> config;
config.instantiate();
@ -3137,6 +3137,8 @@ void GLTFDocument::_parse_image_save_image(Ref<GLTFState> p_state, const String
if (!generator_parameters.has("md5")) {
must_import = false; // Didn't come from a gltf document; don't overwrite.
}
}
if (must_import) {
String existing_md5 = generator_parameters["md5"];
unsigned char md5_hash[16];
CryptoCore::md5(img_data.ptr(), img_data.size(), md5_hash);

View File

@ -483,9 +483,14 @@ Error SceneMultiplayer::complete_auth(int p_peer) {
ERR_FAIL_COND_V(!pending_peers.has(p_peer), ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V_MSG(pending_peers[p_peer].local, ERR_FILE_CANT_WRITE, "The authentication session was already marked as completed.");
pending_peers[p_peer].local = true;
// Notify the remote peer that the authentication has completed.
uint8_t buf[2] = { NETWORK_COMMAND_SYS, SYS_COMMAND_AUTH };
multiplayer_peer->set_target_peer(p_peer);
multiplayer_peer->set_transfer_channel(0);
multiplayer_peer->set_transfer_mode(MultiplayerPeer::TRANSFER_MODE_RELIABLE);
Error err = _send(buf, 2);
// The remote peer already reported the authentication as completed, so admit the peer.
// May generate new packets, so it must happen after sending confirmation.
if (pending_peers[p_peer].remote) {

View File

@ -456,7 +456,7 @@ String EditorExportPlatformAndroid::get_valid_basename() const {
if (is_digit(c) && first) {
continue;
}
if (is_ascii_alphanumeric_char(c)) {
if (is_ascii_identifier_char(c)) {
name += String::chr(c);
first = false;
}
@ -533,13 +533,6 @@ bool EditorExportPlatformAndroid::is_package_name_valid(const String &p_package,
return false;
}
if (p_package.find("$genname") >= 0 && !is_project_name_valid()) {
if (r_error) {
*r_error = TTR("The project name does not meet the requirement for the package name format. Please explicitly specify the package name.");
}
return false;
}
return true;
}
@ -2435,6 +2428,13 @@ bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref<Edit
err += "\n";
}
String package_name = p_preset->get("package/unique_name");
if (package_name.find("$genname") >= 0 && !is_project_name_valid()) {
// Warning only, so don't override `valid`.
err += vformat(TTR("The project name does not meet the requirement for the package name format and will be updated to \"%s\". Please explicitly specify the package name if needed."), get_valid_basename());
err += "\n";
}
r_error = err;
return valid;
}

View File

@ -101,7 +101,12 @@ void Polygon2D::_skeleton_bone_setup_changed() {
}
void Polygon2D::_notification(int p_what) {
if (p_what == NOTIFICATION_TRANSFORM_CHANGED && !Engine::get_singleton()->is_editor_hint()) {
return; // Mesh recreation for NOTIFICATION_TRANSFORM_CHANGED is only needed in editor.
}
switch (p_what) {
case NOTIFICATION_TRANSFORM_CHANGED:
case NOTIFICATION_DRAW: {
if (polygon.size() < 3) {
return;
@ -364,7 +369,30 @@ void Polygon2D::_notification(int p_what) {
arr[RS::ARRAY_INDEX] = index_array;
RS::get_singleton()->mesh_add_surface_from_arrays(mesh, RS::PRIMITIVE_TRIANGLES, arr, Array(), Dictionary(), RS::ARRAY_FLAG_USE_2D_VERTICES);
RS::SurfaceData sd;
if (skeleton_node) {
// Compute transform between mesh and skeleton for runtime AABB compute.
const Transform2D mesh_transform = get_global_transform();
const Transform2D skeleton_transform = skeleton_node->get_global_transform();
const Transform2D mesh_to_sk2d = skeleton_transform.affine_inverse() * mesh_transform;
// Convert 2d transform to 3d.
sd.mesh_to_skeleton_xform.basis.rows[0][0] = mesh_to_sk2d.columns[0][0];
sd.mesh_to_skeleton_xform.basis.rows[1][0] = mesh_to_sk2d.columns[0][1];
sd.mesh_to_skeleton_xform.origin.x = mesh_to_sk2d.get_origin().x;
sd.mesh_to_skeleton_xform.basis.rows[0][1] = mesh_to_sk2d.columns[1][0];
sd.mesh_to_skeleton_xform.basis.rows[1][1] = mesh_to_sk2d.columns[1][1];
sd.mesh_to_skeleton_xform.origin.y = mesh_to_sk2d.get_origin().y;
}
Error err = RS::get_singleton()->mesh_create_surface_data_from_arrays(&sd, RS::PRIMITIVE_TRIANGLES, arr, Array(), Dictionary(), RS::ARRAY_FLAG_USE_2D_VERTICES);
if (err != OK) {
return;
}
RS::get_singleton()->mesh_add_surface(mesh, sd);
RS::get_singleton()->canvas_item_add_mesh(get_canvas_item(), mesh, Transform2D(), Color(1, 1, 1), texture.is_valid() ? texture->get_rid() : RID());
}

View File

@ -625,6 +625,7 @@ void CollisionObject3D::shape_owner_add_shape(uint32_t p_owner, const Ref<Shape3
total_subshapes++;
_update_shape_data(p_owner);
update_gizmos();
}
int CollisionObject3D::shape_owner_get_shape_count(uint32_t p_owner) const {
@ -688,6 +689,8 @@ void CollisionObject3D::shape_owner_clear_shapes(uint32_t p_owner) {
while (shape_owner_get_shape_count(p_owner) > 0) {
shape_owner_remove_shape(p_owner, 0);
}
update_gizmos();
}
uint32_t CollisionObject3D::shape_find_owner(int p_shape_index) const {

View File

@ -580,6 +580,8 @@ void TreeItem::set_custom_draw(int p_column, Object *p_object, const StringName
cells.write[p_column].custom_draw_obj = p_object->get_instance_id();
cells.write[p_column].custom_draw_callback = p_callback;
_changed_notify(p_column);
}
void TreeItem::set_collapsed(bool p_collapsed) {
@ -1290,8 +1292,14 @@ void TreeItem::clear_custom_color(int p_column) {
void TreeItem::set_custom_font(int p_column, const Ref<Font> &p_font) {
ERR_FAIL_INDEX(p_column, cells.size());
if (cells[p_column].custom_font == p_font) {
return;
}
cells.write[p_column].custom_font = p_font;
cells.write[p_column].cached_minimum_size_dirty = true;
_changed_notify(p_column);
}
Ref<Font> TreeItem::get_custom_font(int p_column) const {
@ -1302,8 +1310,14 @@ Ref<Font> TreeItem::get_custom_font(int p_column) const {
void TreeItem::set_custom_font_size(int p_column, int p_font_size) {
ERR_FAIL_INDEX(p_column, cells.size());
if (cells[p_column].custom_font_size == p_font_size) {
return;
}
cells.write[p_column].custom_font_size = p_font_size;
cells.write[p_column].cached_minimum_size_dirty = true;
_changed_notify(p_column);
}
int TreeItem::get_custom_font_size(int p_column) const {
@ -1352,8 +1366,14 @@ Color TreeItem::get_custom_bg_color(int p_column) const {
void TreeItem::set_custom_as_button(int p_column, bool p_button) {
ERR_FAIL_INDEX(p_column, cells.size());
if (cells[p_column].custom_button == p_button) {
return;
}
cells.write[p_column].custom_button = p_button;
cells.write[p_column].cached_minimum_size_dirty = true;
_changed_notify(p_column);
}
bool TreeItem::is_custom_set_as_button(int p_column) const {

View File

@ -66,6 +66,7 @@ bool GodotAreaPair2D::pre_solve(real_t p_step) {
if (colliding) {
if (has_space_override) {
body_has_attached_area = true;
body->add_area(area);
}
@ -74,6 +75,7 @@ bool GodotAreaPair2D::pre_solve(real_t p_step) {
}
} else {
if (has_space_override) {
body_has_attached_area = false;
body->remove_area(area);
}
@ -103,7 +105,8 @@ GodotAreaPair2D::GodotAreaPair2D(GodotBody2D *p_body, int p_body_shape, GodotAre
GodotAreaPair2D::~GodotAreaPair2D() {
if (colliding) {
if (has_space_override) {
if (body_has_attached_area) {
body_has_attached_area = false;
body->remove_area(area);
}
if (area->has_monitor_callback()) {

View File

@ -43,6 +43,7 @@ class GodotAreaPair2D : public GodotConstraint2D {
bool colliding = false;
bool has_space_override = false;
bool process_collision = false;
bool body_has_attached_area = false;
public:
virtual bool setup(real_t p_step) override;

View File

@ -67,6 +67,7 @@ bool GodotAreaPair3D::pre_solve(real_t p_step) {
if (colliding) {
if (has_space_override) {
body_has_attached_area = true;
body->add_area(area);
}
@ -75,6 +76,7 @@ bool GodotAreaPair3D::pre_solve(real_t p_step) {
}
} else {
if (has_space_override) {
body_has_attached_area = false;
body->remove_area(area);
}
@ -104,7 +106,8 @@ GodotAreaPair3D::GodotAreaPair3D(GodotBody3D *p_body, int p_body_shape, GodotAre
GodotAreaPair3D::~GodotAreaPair3D() {
if (colliding) {
if (has_space_override) {
if (body_has_attached_area) {
body_has_attached_area = false;
body->remove_area(area);
}
if (area->has_monitor_callback()) {
@ -242,6 +245,7 @@ bool GodotAreaSoftBodyPair3D::pre_solve(real_t p_step) {
if (colliding) {
if (has_space_override) {
body_has_attached_area = true;
soft_body->add_area(area);
}
@ -250,6 +254,7 @@ bool GodotAreaSoftBodyPair3D::pre_solve(real_t p_step) {
}
} else {
if (has_space_override) {
body_has_attached_area = false;
soft_body->remove_area(area);
}
@ -276,7 +281,8 @@ GodotAreaSoftBodyPair3D::GodotAreaSoftBodyPair3D(GodotSoftBody3D *p_soft_body, i
GodotAreaSoftBodyPair3D::~GodotAreaSoftBodyPair3D() {
if (colliding) {
if (has_space_override) {
if (body_has_attached_area) {
body_has_attached_area = false;
soft_body->remove_area(area);
}
if (area->has_monitor_callback()) {

View File

@ -44,6 +44,7 @@ class GodotAreaPair3D : public GodotConstraint3D {
bool colliding = false;
bool process_collision = false;
bool has_space_override = false;
bool body_has_attached_area = false;
public:
virtual bool setup(real_t p_step) override;
@ -83,6 +84,7 @@ class GodotAreaSoftBodyPair3D : public GodotConstraint3D {
bool colliding = false;
bool process_collision = false;
bool has_space_override = false;
bool body_has_attached_area = false;
public:
virtual bool setup(real_t p_step) override;

View File

@ -2030,6 +2030,12 @@ void RendererCanvasCull::update_visibility_notifiers() {
}
}
Rect2 RendererCanvasCull::_debug_canvas_item_get_rect(RID p_item) {
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_NULL_V(canvas_item, Rect2());
return canvas_item->get_rect();
}
bool RendererCanvasCull::free(RID p_rid) {
if (canvas_owner.owns(p_rid)) {
Canvas *canvas = canvas_owner.get_or_null(p_rid);

View File

@ -319,6 +319,8 @@ public:
void update_visibility_notifiers();
Rect2 _debug_canvas_item_get_rect(RID p_item);
bool free(RID p_rid);
RendererCanvasCull();
~RendererCanvasCull();

View File

@ -389,6 +389,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
s->aabb = p_surface.aabb;
s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
s->mesh_to_skeleton_xform = p_surface.mesh_to_skeleton_xform;
if (mesh->blend_shape_count > 0) {
s->blend_shape_buffer = RD::get_singleton()->storage_buffer_create(p_surface.blend_shape_data.size(), p_surface.blend_shape_data);
@ -569,6 +570,7 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
}
sd.bone_aabbs = s.bone_aabbs;
sd.mesh_to_skeleton_xform = s.mesh_to_skeleton_xform;
if (s.blend_shape_buffer.is_valid()) {
sd.blend_shape_data = RD::get_singleton()->buffer_get_data(s.blend_shape_buffer);
@ -615,15 +617,16 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
for (uint32_t i = 0; i < mesh->surface_count; i++) {
AABB laabb;
if ((mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->bone_aabbs.size()) {
int bs = mesh->surfaces[i]->bone_aabbs.size();
const AABB *skbones = mesh->surfaces[i]->bone_aabbs.ptr();
const Mesh::Surface &surface = *mesh->surfaces[i];
if ((surface.format & RS::ARRAY_FORMAT_BONES) && surface.bone_aabbs.size()) {
int bs = surface.bone_aabbs.size();
const AABB *skbones = surface.bone_aabbs.ptr();
int sbs = skeleton->size;
ERR_CONTINUE(bs > sbs);
const float *baseptr = skeleton->data.ptr();
bool first = true;
bool found_bone_aabb = false;
if (skeleton->use_2d) {
for (int j = 0; j < bs; j++) {
@ -643,11 +646,13 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
mtx.basis.rows[1][1] = dataptr[5];
mtx.origin.y = dataptr[7];
AABB baabb = mtx.xform(skbones[j]);
// Transform bounds to skeleton's space before applying animation data.
AABB baabb = surface.mesh_to_skeleton_xform.xform(skbones[j]);
baabb = mtx.xform(baabb);
if (first) {
if (!found_bone_aabb) {
laabb = baabb;
first = false;
found_bone_aabb = true;
} else {
laabb.merge_with(baabb);
}
@ -675,21 +680,29 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
mtx.basis.rows[2][2] = dataptr[10];
mtx.origin.z = dataptr[11];
AABB baabb = mtx.xform(skbones[j]);
if (first) {
// Transform bounds to skeleton's space before applying animation data.
AABB baabb = surface.mesh_to_skeleton_xform.xform(skbones[j]);
baabb = mtx.xform(baabb);
if (!found_bone_aabb) {
laabb = baabb;
first = false;
found_bone_aabb = true;
} else {
laabb.merge_with(baabb);
}
}
}
if (found_bone_aabb) {
// Transform skeleton bounds back to mesh's space if any animated AABB applied.
laabb = surface.mesh_to_skeleton_xform.affine_inverse().xform(laabb);
}
if (laabb.size == Vector3()) {
laabb = mesh->surfaces[i]->aabb;
laabb = surface.aabb;
}
} else {
laabb = mesh->surfaces[i]->aabb;
laabb = surface.aabb;
}
if (i == 0) {

View File

@ -116,6 +116,10 @@ private:
Vector<AABB> bone_aabbs;
// Transform used in runtime bone AABBs compute.
// As bone AABBs are saved in Mesh space, but bones animation is in Skeleton space.
Transform3D mesh_to_skeleton_xform;
RID blend_shape_buffer;
RID material;

View File

@ -925,6 +925,8 @@ public:
FUNC1(canvas_set_shadow_texture_size, int)
FUNC1R(Rect2, _debug_canvas_item_get_rect, RID)
/* GLOBAL SHADER UNIFORMS */
#undef server_name

View File

@ -1410,6 +1410,14 @@ Array RenderingServer::_mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_su
}
#endif
Rect2 RenderingServer::debug_canvas_item_get_rect(RID p_item) {
#ifdef TOOLS_ENABLED
return _debug_canvas_item_get_rect(p_item);
#else
return Rect2();
#endif
}
int RenderingServer::global_shader_uniform_type_get_shader_datatype(GlobalShaderParameterType p_type) {
switch (p_type) {
case RS::GLOBAL_VAR_TYPE_BOOL:
@ -2636,6 +2644,8 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_item_set_visibility_notifier", "item", "enable", "area", "enter_callable", "exit_callable"), &RenderingServer::canvas_item_set_visibility_notifier);
ClassDB::bind_method(D_METHOD("canvas_item_set_canvas_group_mode", "item", "mode", "clear_margin", "fit_empty", "fit_margin", "blur_mipmaps"), &RenderingServer::canvas_item_set_canvas_group_mode, DEFVAL(5.0), DEFVAL(false), DEFVAL(0.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("debug_canvas_item_get_rect", "item"), &RenderingServer::debug_canvas_item_get_rect);
BIND_ENUM_CONSTANT(NINE_PATCH_STRETCH);
BIND_ENUM_CONSTANT(NINE_PATCH_TILE);
BIND_ENUM_CONSTANT(NINE_PATCH_TILE_FIT);

View File

@ -312,6 +312,10 @@ public:
Vector<LOD> lods;
Vector<AABB> bone_aabbs;
// Transforms used in runtime bone AABBs compute.
// Since bone AABBs is saved in Mesh space, but bones is in Skeleton space.
Transform3D mesh_to_skeleton_xform;
Vector<uint8_t> blend_shape_data;
RID material;
@ -1461,6 +1465,9 @@ public:
virtual void canvas_set_shadow_texture_size(int p_size) = 0;
Rect2 debug_canvas_item_get_rect(RID p_item);
virtual Rect2 _debug_canvas_item_get_rect(RID p_item) = 0;
/* GLOBAL SHADER UNIFORMS */
enum GlobalShaderParameterType {

View File

@ -323,6 +323,30 @@ TEST_CASE("[Image] Modifying pixels of an image") {
CHECK_MESSAGE(gray_image->get_pixel(2, 2).is_equal_approx(Color(0.266666681, 0.266666681, 0.266666681, 1)), "convert() RGBA to L8 should be around 0.266666681 (68).");
}
}
TEST_CASE("[Image] Convert image") {
for (int format = Image::FORMAT_RF; format < Image::FORMAT_RGBE9995; format++) {
for (int new_format = Image::FORMAT_RF; new_format < Image::FORMAT_RGBE9995; new_format++) {
Ref<Image> image = memnew(Image(4, 4, false, (Image::Format)format));
image->convert((Image::Format)new_format);
String format_string = Image::format_names[(Image::Format)format];
String new_format_string = Image::format_names[(Image::Format)new_format];
format_string = "Error converting from " + format_string + " to " + new_format_string + ".";
CHECK_MESSAGE(image->get_format() == new_format, format_string);
}
}
Ref<Image> image = memnew(Image(4, 4, false, Image::FORMAT_RGBA8));
PackedByteArray image_data = image->get_data();
image->convert((Image::Format)-1);
CHECK_MESSAGE(image->get_data() == image_data, "Image conversion to invalid type (-1) should not alter image.");
Ref<Image> image2 = memnew(Image(4, 4, false, Image::FORMAT_RGBA8));
image_data = image2->get_data();
image2->convert((Image::Format)(Image::FORMAT_MAX + 1));
CHECK_MESSAGE(image2->get_data() == image_data, "Image conversion to invalid type (Image::FORMAT_MAX + 1) should not alter image.");
}
} // namespace TestImage
#endif // TEST_IMAGE_H

View File

@ -441,7 +441,7 @@ that file when upgrading.
## minizip
- Upstream: https://www.zlib.net
- Version: 1.3 (zlib contrib, 2023)
- Version: 1.3.1 (zlib contrib, 2024)
- License: zlib
Files extracted from the upstream source:
@ -814,7 +814,7 @@ Files extracted from upstream source:
## zlib
- Upstream: https://www.zlib.net
- Version: 1.3 (2023)
- Version: 1.3.1 (2024)
- License: zlib
Files extracted from upstream source:

View File

@ -144,7 +144,7 @@ typedef long (ZCALLBACK *tell_file_func) (voidpf opaque, voidpf stream)
typedef long (ZCALLBACK *seek_file_func) (voidpf opaque, voidpf stream, uLong offset, int origin);
/* here is the "old" 32 bits structure structure */
/* here is the "old" 32 bits structure */
typedef struct zlib_filefunc_def_s
{
open_file_func zopen_file;

View File

@ -26,7 +26,7 @@ index 782d32469a..2e89f5f41a 100644
+*/
+/* GODOT end */
diff --git a/thirdparty/minizip/ioapi.h b/thirdparty/minizip/ioapi.h
index c588a18d03..14266141c6 100644
index a2d2e6e60d..509b52da8a 100644
--- a/thirdparty/minizip/ioapi.h
+++ b/thirdparty/minizip/ioapi.h
@@ -155,6 +155,10 @@ typedef struct zlib_filefunc_def_s
@ -52,7 +52,7 @@ index c588a18d03..14266141c6 100644
void fill_fopen64_filefunc(zlib_filefunc64_def* pzlib_filefunc_def);
diff --git a/thirdparty/minizip/unzip.c b/thirdparty/minizip/unzip.c
index ed763f89f1..2f8c5f3675 100644
index ea05b7d62a..981ba3c0cb 100644
--- a/thirdparty/minizip/unzip.c
+++ b/thirdparty/minizip/unzip.c
@@ -152,6 +152,9 @@ typedef struct
@ -232,7 +232,7 @@ index ed763f89f1..2f8c5f3675 100644
return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
}
diff --git a/thirdparty/minizip/unzip.h b/thirdparty/minizip/unzip.h
index 14105840f6..1a477ecb50 100644
index 5cfc9c6274..0639674574 100644
--- a/thirdparty/minizip/unzip.h
+++ b/thirdparty/minizip/unzip.h
@@ -202,6 +202,10 @@ extern int ZEXPORT unzClose(unzFile file);
@ -261,7 +261,7 @@ index 14105840f6..1a477ecb50 100644
extern ZPOS64_T ZEXPORT unztell64(unzFile file);
diff --git a/thirdparty/minizip/zip.c b/thirdparty/minizip/zip.c
index 3d3d4cadde..e859f9e42f 100644
index 60bdffac34..1d2d918e72 100644
--- a/thirdparty/minizip/zip.c
+++ b/thirdparty/minizip/zip.c
@@ -820,9 +820,11 @@ extern zipFile ZEXPORT zipOpen3(const void *pathname, int append, zipcharpc* glo
@ -279,7 +279,7 @@ index 3d3d4cadde..e859f9e42f 100644
ziinit.z_filefunc = *pzlib_filefunc64_32_def;
ziinit.filestream = ZOPEN64(ziinit.z_filefunc,
@@ -1171,8 +1173,10 @@ extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, const char* filename, c
@@ -1182,8 +1184,10 @@ extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, const char* filename, c
{
if(zi->ci.method == Z_DEFLATED)
{

View File

@ -117,7 +117,7 @@
const char unz_copyright[] =
" unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
/* unz_file_info_interntal contain internal info about a file in zipfile*/
/* unz_file_info64_internal contain internal info about a file in zipfile*/
typedef struct unz_file_info64_internal_s
{
ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */
@ -453,7 +453,7 @@ local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib
if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
return CENTRALDIRINVALID;
/* number of the disk with the start of the zip64 end of central directory */
/* number of the disk with the start of the zip64 end of central directory */
if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
return CENTRALDIRINVALID;
if (uL != 0)
@ -500,9 +500,9 @@ local unzFile unzOpenInternal(const void *path,
ZPOS64_T central_pos;
uLong uL;
uLong number_disk; /* number of the current dist, used for
uLong number_disk; /* number of the current disk, used for
spanning ZIP, unsupported, always 0*/
uLong number_disk_with_CD; /* number the the disk with central dir, used
uLong number_disk_with_CD; /* number the disk with central dir, used
for spanning ZIP, unsupported, always 0*/
ZPOS64_T number_entry_CD; /* total number of entries in
the central dir

View File

@ -310,7 +310,7 @@ extern int ZEXPORT unzGetCurrentFileInfo(unzFile file,
Get Info about the current file
if pfile_info!=NULL, the *pfile_info structure will contain some info about
the current file
if szFileName!=NULL, the filemane string will be copied in szFileName
if szFileName!=NULL, the filename string will be copied in szFileName
(fileNameBufferSize is the size of the buffer)
if extraField!=NULL, the extra field information will be copied in extraField
(extraFieldBufferSize is the size of the buffer).

View File

@ -575,7 +575,7 @@ local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib
if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
return 0;
/* number of the disk with the start of the zip64 end of central directory */
/* number of the disk with the start of the zip64 end of central directory */
if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
return 0;
if (uL != 0)
@ -614,9 +614,9 @@ local int LoadCentralDirectoryRecord(zip64_internal* pziinit) {
ZPOS64_T central_pos;
uLong uL;
uLong number_disk; /* number of the current dist, used for
uLong number_disk; /* number of the current disk, used for
spanning ZIP, unsupported, always 0*/
uLong number_disk_with_CD; /* number the the disk with central dir, used
uLong number_disk_with_CD; /* number of the disk with central dir, used
for spanning ZIP, unsupported, always 0*/
ZPOS64_T number_entry;
ZPOS64_T number_entry_CD; /* total number of entries in
@ -1601,7 +1601,7 @@ extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, ZPOS64_T uncompressed_si
if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree)
{
// we can not write more data to the buffer that we have room for.
// we cannot write more data to the buffer that we have room for.
return ZIP_BADZIPFILE;
}
@ -1865,7 +1865,7 @@ extern int ZEXPORT zipClose(zipFile file, const char* global_comment) {
free_linkedlist(&(zi->central_dir));
pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
if(pos >= 0xffffffff || zi->number_entry > 0xFFFF)
if(pos >= 0xffffffff || zi->number_entry >= 0xFFFF)
{
ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream);
Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip);

View File

@ -177,9 +177,9 @@ extern int ZEXPORT zipOpenNewFileInZip64(zipFile file,
filename : the filename in zip (if NULL, '-' without quote will be used
*zipfi contain supplemental information
if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
contains the extrafield data the the local header
contains the extrafield data for the local header
if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
contains the extrafield data the the local header
contains the extrafield data for the global header
if comment != NULL, comment contain the comment string
method contain the compression method (0 for store, Z_DEFLATED for deflate)
level contain the level of compression (can be Z_DEFAULT_COMPRESSION)

View File

@ -1,5 +1,5 @@
/* deflate.c -- compress data using the deflation algorithm
* Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler
* Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -52,7 +52,7 @@
#include "deflate.h"
const char deflate_copyright[] =
" deflate 1.3 Copyright 1995-2023 Jean-loup Gailly and Mark Adler ";
" deflate 1.3.1 Copyright 1995-2024 Jean-loup Gailly and Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
@ -493,7 +493,7 @@ int ZEXPORT deflateInit2_(z_streamp strm, int level, int method,
* symbols from which it is being constructed.
*/
s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 4);
s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, LIT_BUFS);
s->pending_buf_size = (ulg)s->lit_bufsize * 4;
if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
@ -503,8 +503,14 @@ int ZEXPORT deflateInit2_(z_streamp strm, int level, int method,
deflateEnd (strm);
return Z_MEM_ERROR;
}
#ifdef LIT_MEM
s->d_buf = (ushf *)(s->pending_buf + (s->lit_bufsize << 1));
s->l_buf = s->pending_buf + (s->lit_bufsize << 2);
s->sym_end = s->lit_bufsize - 1;
#else
s->sym_buf = s->pending_buf + s->lit_bufsize;
s->sym_end = (s->lit_bufsize - 1) * 3;
#endif
/* We avoid equality with lit_bufsize*3 because of wraparound at 64K
* on 16 bit machines and because stored blocks are restricted to
* 64K-1 bytes.
@ -720,9 +726,15 @@ int ZEXPORT deflatePrime(z_streamp strm, int bits, int value) {
if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
s = strm->state;
#ifdef LIT_MEM
if (bits < 0 || bits > 16 ||
(uchf *)s->d_buf < s->pending_out + ((Buf_size + 7) >> 3))
return Z_BUF_ERROR;
#else
if (bits < 0 || bits > 16 ||
s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3))
return Z_BUF_ERROR;
#endif
do {
put = Buf_size - s->bi_valid;
if (put > bits)
@ -1294,7 +1306,7 @@ int ZEXPORT deflateCopy(z_streamp dest, z_streamp source) {
ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4);
ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, LIT_BUFS);
if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
ds->pending_buf == Z_NULL) {
@ -1305,10 +1317,15 @@ int ZEXPORT deflateCopy(z_streamp dest, z_streamp source) {
zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos));
zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos));
zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
zmemcpy(ds->pending_buf, ss->pending_buf, ds->lit_bufsize * LIT_BUFS);
ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
#ifdef LIT_MEM
ds->d_buf = (ushf *)(ds->pending_buf + (ds->lit_bufsize << 1));
ds->l_buf = ds->pending_buf + (ds->lit_bufsize << 2);
#else
ds->sym_buf = ds->pending_buf + ds->lit_bufsize;
#endif
ds->l_desc.dyn_tree = ds->dyn_ltree;
ds->d_desc.dyn_tree = ds->dyn_dtree;
@ -1539,13 +1556,21 @@ local uInt longest_match(deflate_state *s, IPos cur_match) {
*/
local void check_match(deflate_state *s, IPos start, IPos match, int length) {
/* check that the match is indeed a match */
if (zmemcmp(s->window + match,
s->window + start, length) != EQUAL) {
fprintf(stderr, " start %u, match %u, length %d\n",
start, match, length);
Bytef *back = s->window + (int)match, *here = s->window + start;
IPos len = length;
if (match == (IPos)-1) {
/* match starts one byte before the current window -- just compare the
subsequent length-1 bytes */
back++;
here++;
len--;
}
if (zmemcmp(back, here, len) != EQUAL) {
fprintf(stderr, " start %u, match %d, length %d\n",
start, (int)match, length);
do {
fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
} while (--length != 0);
fprintf(stderr, "(%02x %02x)", *back++, *here++);
} while (--len != 0);
z_error("invalid match");
}
if (z_verbose > 1) {

View File

@ -1,5 +1,5 @@
/* deflate.h -- internal compression state
* Copyright (C) 1995-2018 Jean-loup Gailly
* Copyright (C) 1995-2024 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -23,6 +23,10 @@
# define GZIP
#endif
/* define LIT_MEM to slightly increase the speed of deflate (order 1% to 2%) at
the cost of a larger memory footprint */
/* #define LIT_MEM */
/* ===========================================================================
* Internal compression state.
*/
@ -217,7 +221,14 @@ typedef struct internal_state {
/* Depth of each subtree used as tie breaker for trees of equal frequency
*/
#ifdef LIT_MEM
# define LIT_BUFS 5
ushf *d_buf; /* buffer for distances */
uchf *l_buf; /* buffer for literals/lengths */
#else
# define LIT_BUFS 4
uchf *sym_buf; /* buffer for distances and literals/lengths */
#endif
uInt lit_bufsize;
/* Size of match buffer for literals/lengths. There are 4 reasons for
@ -239,7 +250,7 @@ typedef struct internal_state {
* - I can't count above 4
*/
uInt sym_next; /* running index in sym_buf */
uInt sym_next; /* running index in symbol buffer */
uInt sym_end; /* symbol table full when sym_next reaches this */
ulg opt_len; /* bit length of current block with optimal trees */
@ -318,6 +329,25 @@ void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf,
extern const uch ZLIB_INTERNAL _dist_code[];
#endif
#ifdef LIT_MEM
# define _tr_tally_lit(s, c, flush) \
{ uch cc = (c); \
s->d_buf[s->sym_next] = 0; \
s->l_buf[s->sym_next++] = cc; \
s->dyn_ltree[cc].Freq++; \
flush = (s->sym_next == s->sym_end); \
}
# define _tr_tally_dist(s, distance, length, flush) \
{ uch len = (uch)(length); \
ush dist = (ush)(distance); \
s->d_buf[s->sym_next] = dist; \
s->l_buf[s->sym_next++] = len; \
dist--; \
s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
s->dyn_dtree[d_code(dist)].Freq++; \
flush = (s->sym_next == s->sym_end); \
}
#else
# define _tr_tally_lit(s, c, flush) \
{ uch cc = (c); \
s->sym_buf[s->sym_next++] = 0; \
@ -337,6 +367,7 @@ void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf,
s->dyn_dtree[d_code(dist)].Freq++; \
flush = (s->sym_next == s->sym_end); \
}
#endif
#else
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
# define _tr_tally_dist(s, distance, length, flush) \

View File

@ -1,5 +1,5 @@
/* gzguts.h -- zlib internal header definitions for gz* operations
* Copyright (C) 2004-2019 Mark Adler
* Copyright (C) 2004-2024 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -210,9 +210,5 @@ char ZLIB_INTERNAL *gz_strwinerror(DWORD error);
/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
value -- needed when comparing unsigned to z_off64_t, which is signed
(possible z_off64_t types off_t, off64_t, and long are all signed) */
#ifdef INT_MAX
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
#else
unsigned ZLIB_INTERNAL gz_intmax(void);
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
#endif
#define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())

View File

@ -1,5 +1,5 @@
/* gzlib.c -- zlib functions common to reading and writing gzip files
* Copyright (C) 2004-2019 Mark Adler
* Copyright (C) 2004-2024 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -563,20 +563,20 @@ void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) {
#endif
}
#ifndef INT_MAX
/* portably return maximum value for an int (when limits.h presumed not
available) -- we need to do this to cover cases where 2's complement not
used, since C standard permits 1's complement and sign-bit representations,
otherwise we could just use ((unsigned)-1) >> 1 */
unsigned ZLIB_INTERNAL gz_intmax(void) {
unsigned p, q;
p = 1;
#ifdef INT_MAX
return INT_MAX;
#else
unsigned p = 1, q;
do {
q = p;
p <<= 1;
p++;
} while (p > q);
return q >> 1;
}
#endif
}

View File

@ -1387,7 +1387,7 @@ int ZEXPORT inflateSync(z_streamp strm) {
/* if first time, start search in bit buffer */
if (state->mode != SYNC) {
state->mode = SYNC;
state->hold <<= state->bits & 7;
state->hold >>= state->bits & 7;
state->bits -= state->bits & 7;
len = 0;
while (state->bits >= 8) {

View File

@ -1,5 +1,5 @@
/* inftrees.c -- generate Huffman trees for efficient decoding
* Copyright (C) 1995-2023 Mark Adler
* Copyright (C) 1995-2024 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -9,7 +9,7 @@
#define MAXBITS 15
const char inflate_copyright[] =
" inflate 1.3 Copyright 1995-2023 Mark Adler ";
" inflate 1.3.1 Copyright 1995-2024 Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
@ -57,7 +57,7 @@ int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 198, 203};
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 203, 77};
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,

View File

@ -41,8 +41,8 @@ typedef struct {
examples/enough.c found in the zlib distribution. The arguments to that
program are the number of symbols, the initial root table size, and the
maximum bit length of a code. "enough 286 9 15" for literal/length codes
returns returns 852, and "enough 30 6 15" for distance codes returns 592.
The initial root table size (9 or 6) is found in the fifth argument of the
returns 852, and "enough 30 6 15" for distance codes returns 592. The
initial root table size (9 or 6) is found in the fifth argument of the
inflate_table() calls in inflate.c and infback.c. If the root table size is
changed, then these maximum sizes would be need to be recalculated and
updated. */

View File

@ -1,5 +1,5 @@
/* trees.c -- output deflated data using Huffman coding
* Copyright (C) 1995-2021 Jean-loup Gailly
* Copyright (C) 1995-2024 Jean-loup Gailly
* detect_data_type() function provided freely by Cosmin Truta, 2006
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -899,14 +899,19 @@ local void compress_block(deflate_state *s, const ct_data *ltree,
const ct_data *dtree) {
unsigned dist; /* distance of matched string */
int lc; /* match length or unmatched char (if dist == 0) */
unsigned sx = 0; /* running index in sym_buf */
unsigned sx = 0; /* running index in symbol buffers */
unsigned code; /* the code to send */
int extra; /* number of extra bits to send */
if (s->sym_next != 0) do {
#ifdef LIT_MEM
dist = s->d_buf[sx];
lc = s->l_buf[sx++];
#else
dist = s->sym_buf[sx++] & 0xff;
dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8;
lc = s->sym_buf[sx++];
#endif
if (dist == 0) {
send_code(s, lc, ltree); /* send a literal byte */
Tracecv(isgraph(lc), (stderr," '%c' ", lc));
@ -931,8 +936,12 @@ local void compress_block(deflate_state *s, const ct_data *ltree,
}
} /* literal or match pair ? */
/* Check that the overlay between pending_buf and sym_buf is ok: */
/* Check for no overlay of pending_buf on needed symbols */
#ifdef LIT_MEM
Assert(s->pending < 2 * (s->lit_bufsize + sx), "pendingBuf overflow");
#else
Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow");
#endif
} while (sx < s->sym_next);
@ -1082,9 +1091,14 @@ void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf,
* the current block must be flushed.
*/
int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc) {
#ifdef LIT_MEM
s->d_buf[s->sym_next] = (ush)dist;
s->l_buf[s->sym_next++] = (uch)lc;
#else
s->sym_buf[s->sym_next++] = (uch)dist;
s->sym_buf[s->sym_next++] = (uch)(dist >> 8);
s->sym_buf[s->sym_next++] = (uch)lc;
#endif
if (dist == 0) {
/* lc is the unmatched char */
s->dyn_ltree[lc].Freq++;

View File

@ -1,5 +1,5 @@
/* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
* Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -300,14 +300,6 @@
# endif
#endif
#ifndef Z_ARG /* function prototypes for stdarg */
# if defined(STDC) || defined(Z_HAVE_STDARG_H)
# define Z_ARG(args) args
# else
# define Z_ARG(args) ()
# endif
#endif
/* The following definitions for FAR are needed only for MSDOS mixed
* model programming (small or medium model with some far allocations).
* This was tested only with MSC; for other MSDOS compilers you may have

View File

@ -1,7 +1,7 @@
/* zlib.h -- interface of the 'zlib' general purpose compression library
version 1.3, August 18th, 2023
version 1.3.1, January 22nd, 2024
Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler
Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -37,11 +37,11 @@
extern "C" {
#endif
#define ZLIB_VERSION "1.3"
#define ZLIB_VERNUM 0x1300
#define ZLIB_VERSION "1.3.1"
#define ZLIB_VERNUM 0x1310
#define ZLIB_VER_MAJOR 1
#define ZLIB_VER_MINOR 3
#define ZLIB_VER_REVISION 0
#define ZLIB_VER_REVISION 1
#define ZLIB_VER_SUBREVISION 0
/*
@ -936,10 +936,10 @@ ZEXTERN int ZEXPORT inflateSync(z_streamp strm);
inflateSync returns Z_OK if a possible full flush point has been found,
Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
In the success case, the application may save the current current value of
total_in which indicates where valid compressed data was found. In the
error case, the application may repeatedly call inflateSync, providing more
input each time, until success or end of the input data.
In the success case, the application may save the current value of total_in
which indicates where valid compressed data was found. In the error case,
the application may repeatedly call inflateSync, providing more input each
time, until success or end of the input data.
*/
ZEXTERN int ZEXPORT inflateCopy(z_streamp dest,
@ -1758,14 +1758,14 @@ ZEXTERN uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2);
seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
len2.
len2. len2 must be non-negative.
*/
/*
ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2);
Return the operator corresponding to length len2, to be used with
crc32_combine_op().
crc32_combine_op(). len2 must be non-negative.
*/
ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op);

View File

@ -1,5 +1,5 @@
/* zutil.h -- internal interface and configuration of the compression library
* Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler
* Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -56,7 +56,7 @@ typedef unsigned long ulg;
extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
/* (size given to avoid silly warnings with Visual C++) */
#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
#define ERR_MSG(err) z_errmsg[(err) < -6 || (err) > 2 ? 9 : 2 - (err)]
#define ERR_RETURN(strm,err) \
return (strm->msg = ERR_MSG(err), (err))
@ -137,17 +137,8 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
# endif
#endif
#if defined(MACOS) || defined(TARGET_OS_MAC)
#if defined(MACOS)
# define OS_CODE 7
# ifndef Z_SOLO
# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
# include <unix.h> /* for fdopen */
# else
# ifndef fdopen
# define fdopen(fd,mode) NULL /* No fdopen() */
# endif
# endif
# endif
#endif
#ifdef __acorn
@ -170,18 +161,6 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
# define OS_CODE 19
#endif
#if defined(_BEOS_) || defined(RISCOS)
# define fdopen(fd,mode) NULL /* No fdopen() */
#endif
#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
# if defined(_WIN32_WCE)
# define fdopen(fd,mode) NULL /* No fdopen() */
# else
# define fdopen(fd,type) _fdopen(fd,type)
# endif
#endif
#if defined(__BORLANDC__) && !defined(MSDOS)
#pragma warn -8004
#pragma warn -8008