Merge pull request #55012 from akien-mga/3.4

This commit is contained in:
Rémi Verschelde 2021-11-16 09:18:17 +01:00 committed by GitHub
commit 387876b592
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
68 changed files with 343 additions and 148 deletions

View file

@ -39,7 +39,14 @@
<return type="AABB" />
<argument index="0" name="to_point" type="Vector3" />
<description>
Returns this [AABB] expanded to include a given point.
Returns a copy of this [AABB] expanded to include a given point.
[b]Example:[/b]
[codeblock]
# position (-3, 2, 0), size (1, 1, 1)
var box = AABB(Vector3(-3, 2, 0), Vector3(1, 1, 1))
# position (-3, -1, 0), size (3, 4, 2), so we fit both the original AABB and Vector3(0, -1, 2)
var box2 = box.expand(Vector3(0, -1, 2))
[/codeblock]
</description>
</method>
<method name="get_area">

View file

@ -5,6 +5,7 @@
</brief_description>
<description>
Baked lightmaps are an alternative workflow for adding indirect (or baked) lighting to a scene. Unlike the [GIProbe] approach, baked lightmaps work fine on low-end PCs and mobile devices as they consume almost no resources in run-time.
[b]Procedural generation:[/b] Lightmap baking functionality is only available in the editor. This means [BakedLightmap] is not suited to procedurally generated or user-built levels. For procedurally generated or user-built levels, use [GIProbe] instead.
[b]Note:[/b] Due to how lightmaps work, most properties only have a visible effect once lightmaps are baked again.
</description>
<tutorials>

View file

@ -6,7 +6,9 @@
<description>
[GIProbe]s are used to provide high-quality real-time indirect light to scenes. They precompute the effect of objects that emit light and the effect of static geometry to simulate the behavior of complex light in real-time. [GIProbe]s need to be baked before using, however, once baked, dynamic objects will receive light from them. Further, lights can be fully dynamic or baked.
Having [GIProbe]s in a scene can be expensive, the quality of the probe can be turned down in exchange for better performance in the [ProjectSettings] using [member ProjectSettings.rendering/quality/voxel_cone_tracing/high_quality].
[b]Note:[/b] Meshes should have sufficiently thick walls to avoid light leaks (avoid one-sided walls). For interior levels, enclose your level geometry in a sufficiently large box and bridge the loops to close the mesh.
[b]Procedural generation:[/b] [GIProbe] can be baked in an exported project, which makes it suitable for procedurally generated or user-built levels as long as all the geometry is generated in advance.
[b]Performance:[/b] [GIProbe] is relatively demanding on the GPU and is not suited to low-end hardware such as integrated graphics (consider [BakedLightmap] instead). To provide a fallback for low-end hardware, consider adding an option to disable [GIProbe] in your project's options menus. A [GIProbe] node can be disabled by hiding it.
[b]Note:[/b] Meshes should have sufficiently thick walls to avoid light leaks (avoid one-sided walls). For interior levels, enclose your level geometry in a sufficiently large box and bridge the loops to close the mesh. To further prevent light leaks, you can also strategically place temporary [MeshInstance] nodes with [member GeometryInstance.use_in_baked_light] enabled. These temporary nodes can then be hidden after baking the [GIProbe] node.
[b]Note:[/b] Due to a renderer limitation, emissive [ShaderMaterial]s cannot emit light when used in a [GIProbe]. Only emissive [SpatialMaterial]s can emit light in a [GIProbe].
</description>
<tutorials>
@ -20,6 +22,7 @@
<argument index="1" name="create_visual_debug" type="bool" default="false" />
<description>
Bakes the effect from all [GeometryInstance]s marked with [member GeometryInstance.use_in_baked_light] and [Light]s marked with either [constant Light.BAKE_INDIRECT] or [constant Light.BAKE_ALL]. If [code]create_visual_debug[/code] is [code]true[/code], after baking the light, this will generate a [MultiMesh] that has a cube representing each solid cell with each cube colored to the cell's albedo color. This can be used to visualize the [GIProbe]'s data and debug any issues that may be occurring.
[b]Note:[/b] [method bake] works from the editor and in exported projects. This makes it suitable for procedurally generated or user-built levels. Baking a [GIProbe] generally takes from 5 to 20 seconds in most scenes. Reducing [member subdiv] can speed up baking.
</description>
</method>
<method name="debug_bake">
@ -73,7 +76,7 @@
Use 256 subdivisions.
</constant>
<constant name="SUBDIV_512" value="3" enum="Subdiv">
Use 512 subdivisions. This is the highest quality setting, but the slowest. On lower-end hardware this could cause the GPU to stall.
Use 512 subdivisions. This is the highest quality setting, but the slowest. On lower-end hardware, this could cause the GPU to stall.
</constant>
<constant name="SUBDIV_MAX" value="4" enum="Subdiv">
Represents the size of the [enum Subdiv] enum.

View file

@ -86,7 +86,7 @@
<argument index="2" name="exclude_raycast_shapes" type="bool" default="true" />
<argument index="3" name="test_only" type="bool" default="false" />
<description>
Moves the body along the vector [code]rel_vec[/code]. The body will stop if it collides. Returns a [KinematicCollision], which contains information about the collision.
Moves the body along the vector [code]rel_vec[/code]. The body will stop if it collides. Returns a [KinematicCollision], which contains information about the collision when stopped, or when touching another body along the motion.
If [code]test_only[/code] is [code]true[/code], the body does not move but the would-be collision information is given.
</description>
</method>
@ -139,7 +139,8 @@
<argument index="1" name="rel_vec" type="Vector3" />
<argument index="2" name="infinite_inertia" type="bool" default="true" />
<description>
Checks for collisions without moving the body. Virtually sets the node's position, scale and rotation to that of the given [Transform], then tries to move the body along the vector [code]rel_vec[/code]. Returns [code]true[/code] if a collision would occur.
Checks for collisions without moving the body. Virtually sets the node's position, scale and rotation to that of the given [Transform], then tries to move the body along the vector [code]rel_vec[/code]. Returns [code]true[/code] if a collision would stop the body from moving along the whole path.
Use [method move_and_collide] instead for detecting collision with touching bodies.
</description>
</method>
</methods>

View file

@ -84,7 +84,7 @@
<argument index="2" name="exclude_raycast_shapes" type="bool" default="true" />
<argument index="3" name="test_only" type="bool" default="false" />
<description>
Moves the body along the vector [code]rel_vec[/code]. The body will stop if it collides. Returns a [KinematicCollision2D], which contains information about the collision.
Moves the body along the vector [code]rel_vec[/code]. The body will stop if it collides. Returns a [KinematicCollision2D], which contains information about the collision when stopped, or when touching another body along the motion.
If [code]test_only[/code] is [code]true[/code], the body does not move but the would-be collision information is given.
</description>
</method>
@ -129,7 +129,8 @@
<argument index="1" name="rel_vec" type="Vector2" />
<argument index="2" name="infinite_inertia" type="bool" default="true" />
<description>
Checks for collisions without moving the body. Virtually sets the node's position, scale and rotation to that of the given [Transform2D], then tries to move the body along the vector [code]rel_vec[/code]. Returns [code]true[/code] if a collision would occur.
Checks for collisions without moving the body. Virtually sets the node's position, scale and rotation to that of the given [Transform2D], then tries to move the body along the vector [code]rel_vec[/code]. Returns [code]true[/code] if a collision would stop the body from moving along the whole path.
Use [method move_and_collide] instead for detecting collision with touching bodies.
</description>
</method>
</methods>

View file

@ -18,7 +18,7 @@
var polygon = NavigationPolygon.new()
var vertices = PoolVector2Array([Vector2(0, 0), Vector2(0, 50), Vector2(50, 50), Vector2(50, 0)])
polygon.set_vertices(vertices)
var indices = PoolIntArray(0, 3, 1)
var indices = PoolIntArray([0, 1, 2, 3])
polygon.add_polygon(indices)
$NavigationPolygonInstance.navpoly = polygon
[/codeblock]

View file

@ -350,7 +350,7 @@
<return type="int" />
<argument index="0" name="screen" type="int" default="-1" />
<description>
Returns the dots per inch density of the specified screen. If [code]screen[/code] is [/code]-1[/code] (the default value), the current screen will be used.
Returns the dots per inch density of the specified screen. If [code]screen[/code] is [code]-1[/code] (the default value), the current screen will be used.
[b]Note:[/b] On macOS, returned value is inaccurate if fractional display scaling mode is used.
[b]Note:[/b] On Android devices, the actual screen densities are grouped into six generalized densities:
[codeblock]
@ -376,14 +376,14 @@
<return type="Vector2" />
<argument index="0" name="screen" type="int" default="-1" />
<description>
Returns the position of the specified screen by index. If [code]screen[/code] is [/code]-1[/code] (the default value), the current screen will be used.
Returns the position of the specified screen by index. If [code]screen[/code] is [code]-1[/code] (the default value), the current screen will be used.
</description>
</method>
<method name="get_screen_scale" qualifiers="const">
<return type="float" />
<argument index="0" name="screen" type="int" default="-1" />
<description>
Return the scale factor of the specified screen by index. If [code]screen[/code] is [/code]-1[/code] (the default value), the current screen will be used.
Return the scale factor of the specified screen by index. If [code]screen[/code] is [code]-1[/code] (the default value), the current screen will be used.
[b]Note:[/b] On macOS returned value is [code]2.0[/code] for hiDPI (Retina) screen, and [code]1.0[/code] for all other cases.
[b]Note:[/b] This method is implemented on macOS.
</description>
@ -392,7 +392,7 @@
<return type="Vector2" />
<argument index="0" name="screen" type="int" default="-1" />
<description>
Returns the dimensions in pixels of the specified screen. If [code]screen[/code] is [/code]-1[/code] (the default value), the current screen will be used.
Returns the dimensions in pixels of the specified screen. If [code]screen[/code] is [code]-1[/code] (the default value), the current screen will be used.
</description>
</method>
<method name="get_splash_tick_msec" qualifiers="const">

View file

@ -58,7 +58,8 @@
[code]metadata[/code]: The intersecting shape's metadata. This metadata is different from [method Object.get_meta], and is set with [method Physics2DServer.shape_set_data].
[code]rid[/code]: The intersecting object's [RID].
[code]shape[/code]: The shape index of the colliding shape.
Additionally, the method can take an [code]exclude[/code] array of objects or [RID]s that are to be excluded from collisions, a [code]collision_mask[/code] bitmask representing the physics layers to check in, or booleans to determine if the ray should collide with [PhysicsBody]s or [Area]s, respectively.
The number of intersections can be limited with the [code]max_results[/code] parameter, to reduce the processing time.
Additionally, the method can take an [code]exclude[/code] array of objects or [RID]s that are to be excluded from collisions, a [code]collision_mask[/code] bitmask representing the physics layers to check in, or booleans to determine if the ray should collide with [PhysicsBody2D]s or [Area2D]s, respectively.
[b]Note:[/b] [ConcavePolygonShape2D]s and [CollisionPolygon2D]s in [code]Segments[/code] build mode are not solid shapes. Therefore, they will not be detected.
</description>
</method>
@ -72,6 +73,15 @@
<argument index="5" name="collide_with_bodies" type="bool" default="true" />
<argument index="6" name="collide_with_areas" type="bool" default="false" />
<description>
Checks whether a point is inside any solid shape, in a specific canvas layer given by [code]canvas_instance_id[/code]. The shapes the point is inside of are returned in an array containing dictionaries with the following fields:
[code]collider[/code]: The colliding object.
[code]collider_id[/code]: The colliding object's ID.
[code]metadata[/code]: The intersecting shape's metadata. This metadata is different from [method Object.get_meta], and is set with [method Physics2DServer.shape_set_data].
[code]rid[/code]: The intersecting object's [RID].
[code]shape[/code]: The shape index of the colliding shape.
The number of intersections can be limited with the [code]max_results[/code] parameter, to reduce the processing time.
Additionally, the method can take an [code]exclude[/code] array of objects or [RID]s that are to be excluded from collisions, a [code]collision_mask[/code] bitmask representing the physics layers to check in, or booleans to determine if the ray should collide with [PhysicsBody2D]s or [Area2D]s, respectively.
[b]Note:[/b] [ConcavePolygonShape2D]s and [CollisionPolygon2D]s in [code]Segments[/code] build mode are not solid shapes. Therefore, they will not be detected.
</description>
</method>
<method name="intersect_ray">
@ -92,7 +102,7 @@
[code]rid[/code]: The intersecting object's [RID].
[code]shape[/code]: The shape index of the colliding shape.
If the ray did not intersect anything, then an empty dictionary is returned instead.
Additionally, the method can take an [code]exclude[/code] array of objects or [RID]s that are to be excluded from collisions, a [code]collision_mask[/code] bitmask representing the physics layers to check in, or booleans to determine if the ray should collide with [PhysicsBody]s or [Area]s, respectively.
Additionally, the method can take an [code]exclude[/code] array of objects or [RID]s that are to be excluded from collisions, a [code]collision_mask[/code] bitmask representing the physics layers to check in, or booleans to determine if the ray should collide with [PhysicsBody2D]s or [Area2D]s, respectively.
</description>
</method>
<method name="intersect_shape">

View file

@ -348,7 +348,7 @@
<return type="Physics2DDirectBodyState" />
<argument index="0" name="body" type="RID" />
<description>
Returns the [Physics2DDirectBodyState] of the body.
Returns the [Physics2DDirectBodyState] of the body. Returns [code]null[/code] if the body is destroyed or removed from the physics space.
</description>
</method>
<method name="body_get_max_contacts_reported" qualifiers="const">

View file

@ -43,6 +43,24 @@
If the shape did not intersect anything, then an empty dictionary is returned instead.
</description>
</method>
<method name="intersect_point">
<return type="Array" />
<argument index="0" name="point" type="Vector3" />
<argument index="1" name="max_results" type="int" default="32" />
<argument index="2" name="exclude" type="Array" default="[ ]" />
<argument index="3" name="collision_layer" type="int" default="2147483647" />
<argument index="4" name="collide_with_bodies" type="bool" default="true" />
<argument index="5" name="collide_with_areas" type="bool" default="false" />
<description>
Checks whether a point is inside any solid shape. The shapes the point is inside of are returned in an array containing dictionaries with the following fields:
[code]collider[/code]: The colliding object.
[code]collider_id[/code]: The colliding object's ID.
[code]rid[/code]: The intersecting object's [RID].
[code]shape[/code]: The shape index of the colliding shape.
The number of intersections can be limited with the [code]max_results[/code] parameter, to reduce the processing time.
Additionally, the method can take an [code]exclude[/code] array of objects or [RID]s that are to be excluded from collisions, a [code]collision_mask[/code] bitmask representing the physics layers to check in, or booleans to determine if the ray should collide with [PhysicsBody]s or [Area]s, respectively.
</description>
</method>
<method name="intersect_ray">
<return type="Dictionary" />
<argument index="0" name="from" type="Vector3" />

View file

@ -332,7 +332,7 @@
<return type="PhysicsDirectBodyState" />
<argument index="0" name="body" type="RID" />
<description>
Returns the [PhysicsDirectBodyState] of the body.
Returns the [PhysicsDirectBodyState] of the body. Returns [code]null[/code] if the body is destroyed or removed from the physics space.
</description>
</method>
<method name="body_get_kinematic_safe_margin" qualifiers="const">

View file

@ -276,7 +276,9 @@
Safer override for [member audio/mix_rate] in the Web platform. Here [code]0[/code] means "let the browser choose" (since some browsers do not like forcing the mix rate).
</member>
<member name="audio/output_latency" type="int" setter="" getter="" default="15">
Output latency in milliseconds for audio. Lower values will result in lower audio latency at the cost of increased CPU usage. Low values may result in audible cracking on slower hardware.
Specifies the preferred output latency in milliseconds for audio. Lower values will result in lower audio latency at the cost of increased CPU usage. Low values may result in audible cracking on slower hardware.
Audio output latency may be constrained by the host operating system and audio hardware drivers. If the host can not provide the specified audio output latency then Godot will attempt to use the nearest latency allowed by the host. As such you should always use [method AudioServer.get_output_latency] to determine the actual audio output latency.
[b]Note:[/b] This setting is ignored on Windows.
</member>
<member name="audio/output_latency.web" type="int" setter="" getter="" default="50">
Safer override for [member audio/output_latency] in the Web platform, to avoid audio issues especially on mobile devices.

View file

@ -56,7 +56,14 @@
<return type="Rect2" />
<argument index="0" name="to" type="Vector2" />
<description>
Returns this [Rect2] expanded to include a given point.
Returns a copy of this [Rect2] expanded to include a given point.
[b]Example:[/b]
[codeblock]
# position (-3, 2), size (1, 1)
var rect = Rect2(Vector2(-3, 2), Vector2(1, 1))
# position (-3, -1), size (3, 4), so we fit both rect and Vector2(0, -1)
var rect2 = rect.expand(Vector2(0, -1))
[/codeblock]
</description>
</method>
<method name="get_area">
@ -100,7 +107,8 @@
<return type="bool" />
<argument index="0" name="point" type="Vector2" />
<description>
Returns [code]true[/code] if the [Rect2] contains a point.
Returns [code]true[/code] if the [Rect2] contains a point. By convention, the right and bottom edges of the [Rect2] are considered exclusive, so points on these edges are [b]not[/b] included.
[b]Note:[/b] This method is not reliable for [Rect2] with a [i]negative size[/i]. Use [method abs] to get a positive sized equivalent rectangle to check for contained points.
</description>
</method>
<method name="intersects">

View file

@ -75,6 +75,11 @@
Optionally during conversion the potentially visible set (PVS) of rooms that are potentially visible from each room can be calculated. This can be used either to aid in dynamic portal culling, or to totally replace portal culling.
In [code]Full[/code] PVS Mode, all objects within the potentially visible rooms will be frustum culled, and rendered if they are within the view frustum.
</member>
<member name="roaming_expansion_margin" type="float" setter="set_roaming_expansion_margin" getter="get_roaming_expansion_margin" default="1.0">
In order to reduce processing for roaming objects, an expansion is applied to their AABB as they move. This expanded volume is used to calculate which rooms the roaming object is within. If the object's exact AABB is still within this expanded volume on the next move, there is no need to reprocess the object, which can save considerable CPU.
The downside is that if the expansion is too much, the object may end up unexpectedly sprawling into neighbouring rooms and showing up where it might otherwise be culled.
In order to balance roaming performance against culling accuracy, this expansion margin can be customized by the user. It will typically depend on your room and object sizes, and movement speeds. The default value should work reasonably in most circumstances.
</member>
<member name="room_simplify" type="float" setter="set_room_simplify" getter="get_room_simplify" default="0.5">
During the conversion process, the geometry of objects within [Room]s, or a custom specified manual bound, are used to generate a [b]convex hull bound[/b].
This convex hull is [b]required[/b] in the visibility system, and is used for many purposes. Most importantly, it is used to decide whether the [Camera] (or an object) is within a [Room]. The convex hull generating algorithm is good, but occasionally it can create too many (or too few) planes to give a good representation of the room volume.

View file

@ -113,6 +113,7 @@
<argument index="2" name="transform" type="Transform" />
<description>
Append vertices from a given [Mesh] surface onto the current vertex array with specified [Transform].
[b]Note:[/b] Using [method append_from] on a [Thread] is much slower as the GPU must communicate data back to the CPU, while also causing the main thread to stall (as OpenGL is not thread-safe). Consider requesting a copy of the mesh, converting it to an [ArrayMesh] and adding vertices manually instead.
</description>
</method>
<method name="begin">

View file

@ -2309,7 +2309,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
// UNLESS tangent exists and is also compressed
// then it will be oct16 encoded along with tangent
attribs[i].normalized = GL_TRUE;
attribs[i].size = 4;
attribs[i].size = 2;
attribs[i].type = GL_SHORT;
attributes_stride += 4;
} else {
@ -2330,6 +2330,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
case VS::ARRAY_TANGENT: {
if (p_format & VS::ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
attribs[i].enabled = false;
attribs[VS::ARRAY_NORMAL].size = 4;
if (p_format & VS::ARRAY_COMPRESS_TANGENT && p_format & VS::ARRAY_COMPRESS_NORMAL) {
// normal and tangent will each be oct16 (2 bytes each)
// pack into single vec4<GL_BYTE> for memory bandwidth

View file

@ -107,18 +107,6 @@
#define glClearDepth glClearDepthf
#endif
#ifdef __EMSCRIPTEN__
#include <emscripten/emscripten.h>
void glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data) {
/* clang-format off */
EM_ASM({
GLctx.getBufferSubData($0, $1, HEAPU8, $2, $3);
}, target, offset, data, size);
/* clang-format on */
}
#endif
void glTexStorage2DCustom(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type) {
#ifdef GLES_OVER_GL
@ -3404,7 +3392,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
// UNLESS tangent exists and is also compressed
// then it will be oct16 encoded along with tangent
attribs[i].normalized = GL_TRUE;
attribs[i].size = 4;
attribs[i].size = 2;
attribs[i].type = GL_SHORT;
attributes_stride += 4;
} else {
@ -3425,6 +3413,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
case VS::ARRAY_TANGENT: {
if (p_format & VS::ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
attribs[i].enabled = false;
attribs[VS::ARRAY_NORMAL].size = 4;
if (p_format & VS::ARRAY_COMPRESS_TANGENT && p_format & VS::ARRAY_COMPRESS_NORMAL) {
// normal and tangent will each be oct16 (2 bytes each)
// pack into single vec4<GL_BYTE> for memory bandwidth
@ -6126,6 +6115,9 @@ void RasterizerStorageGLES3::particles_set_emitting(RID p_particles, bool p_emit
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND(!particles);
if (p_emitting && !particles->emitting) {
particles_request_process(p_particles);
}
particles->emitting = p_emitting;
}

View file

@ -44,9 +44,9 @@
#include "shaders/cubemap_filter.glsl.gen.h"
#include "shaders/particles.glsl.gen.h"
// WebGL 2.0 has no MapBufferRange/UnmapBuffer, but offers a non-ES style BufferSubData API instead.
// WebGL 2.0 has no MapBufferRange/UnmapBuffer, but offers a non-ES style BufferSubData API via glGetBufferSubData instead.
#ifdef __EMSCRIPTEN__
void glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data);
#include <webgl/webgl2.h>
#endif
class RasterizerCanvasGLES3;

View file

@ -191,7 +191,7 @@ Error AudioDriverPulseAudio::init_device() {
Error err = detect_channels();
if (err != OK) {
// This most likely means there are no sinks.
ERR_PRINT("PulseAudio: init device failed to detect number of channels");
ERR_PRINT("PulseAudio: init device failed to detect number of output channels");
return err;
}
@ -211,7 +211,7 @@ Error AudioDriverPulseAudio::init_device() {
break;
default:
WARN_PRINT("PulseAudio: Unsupported number of channels: " + itos(pa_map.channels));
WARN_PRINT("PulseAudio: Unsupported number of output channels: " + itos(pa_map.channels));
pa_channel_map_init_stereo(&pa_map);
channels = 2;
break;
@ -221,8 +221,8 @@ Error AudioDriverPulseAudio::init_device() {
buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
pa_buffer_size = buffer_frames * pa_map.channels;
print_verbose("PulseAudio: detected " + itos(pa_map.channels) + " channels");
print_verbose("PulseAudio: audio buffer frames: " + itos(buffer_frames) + " calculated latency: " + itos(buffer_frames * 1000 / mix_rate) + "ms");
print_verbose("PulseAudio: detected " + itos(pa_map.channels) + " output channels");
print_verbose("PulseAudio: audio buffer frames: " + itos(buffer_frames) + " calculated output latency: " + itos(buffer_frames * 1000 / mix_rate) + "ms");
pa_sample_spec spec;
spec.format = PA_SAMPLE_S16LE;
@ -381,16 +381,18 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) {
ad->lock();
ad->start_counting_ticks();
int16_t *out_ptr = ad->samples_out.ptrw();
if (!ad->active) {
for (unsigned int i = 0; i < ad->pa_buffer_size; i++) {
ad->samples_out.write[i] = 0;
out_ptr[i] = 0;
}
} else {
ad->audio_server_process(ad->buffer_frames, ad->samples_in.ptrw());
if (ad->channels == ad->pa_map.channels) {
for (unsigned int i = 0; i < ad->pa_buffer_size; i++) {
ad->samples_out.write[i] = ad->samples_in[i] >> 16;
out_ptr[i] = ad->samples_in[i] >> 16;
}
} else {
// Uneven amount of channels
@ -399,11 +401,11 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) {
for (unsigned int i = 0; i < ad->buffer_frames; i++) {
for (int j = 0; j < ad->pa_map.channels - 1; j++) {
ad->samples_out.write[out_idx++] = ad->samples_in[in_idx++] >> 16;
out_ptr[out_idx++] = ad->samples_in[in_idx++] >> 16;
}
uint32_t l = ad->samples_in[in_idx++] >> 16;
uint32_t r = ad->samples_in[in_idx++] >> 16;
ad->samples_out.write[out_idx++] = (l + r) / 2;
out_ptr[out_idx++] = (l + r) / 2;
}
}
}
@ -689,6 +691,8 @@ Error AudioDriverPulseAudio::capture_init_device() {
break;
}
print_verbose("PulseAudio: detected " + itos(pa_rec_map.channels) + " input channels");
pa_sample_spec spec;
spec.format = PA_SAMPLE_S16LE;

View file

@ -1621,7 +1621,7 @@ void EditorNode::_save_all_scenes() {
} else {
_save_scene_with_preview(scene->get_filename());
}
} else {
} else if (scene->get_filename() != "") {
all_saved = false;
}
}

View file

@ -36,7 +36,7 @@
#include "editor_scale.h"
#include "editor_settings.h"
#include "modules/modules_enabled.gen.h"
#include "modules/modules_enabled.gen.h" // For svg.
#ifdef MODULE_SVG_ENABLED
#include "modules/svg/image_loader_svg.h"
#endif

View file

@ -391,11 +391,11 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_
current_material_library = l.replace("mtllib", "").strip_edges();
if (!material_map.has(current_material_library)) {
Map<String, Ref<SpatialMaterial>> lib;
Error err = _parse_material_library(current_material_library, lib, r_missing_deps);
if (err == ERR_CANT_OPEN) {
String dir = p_path.get_base_dir();
err = _parse_material_library(dir.plus_file(current_material_library), lib, r_missing_deps);
String lib_path = current_material_library;
if (lib_path.is_rel_path()) {
lib_path = p_path.get_base_dir().plus_file(current_material_library);
}
Error err = _parse_material_library(lib_path, lib, r_missing_deps);
if (err == OK) {
material_map[current_material_library] = lib;
}

View file

@ -29,6 +29,7 @@
/*************************************************************************/
#include "plugin_config_dialog.h"
#include "core/io/config_file.h"
#include "core/os/dir_access.h"
#include "editor/editor_node.h"
@ -37,7 +38,7 @@
#include "editor/project_settings_editor.h"
#include "scene/gui/grid_container.h"
#include "modules/modules_enabled.gen.h"
#include "modules/modules_enabled.gen.h" // For gdscript.
#ifdef MODULE_GDSCRIPT_ENABLED
#include "modules/gdscript/gdscript.h"
#endif

View file

@ -52,22 +52,6 @@ void Skeleton2DEditor::_menu_option(int p_option) {
}
switch (p_option) {
case MENU_OPTION_MAKE_REST: {
if (node->get_bone_count() == 0) {
err_dialog->set_text(TTR("This skeleton has no bones, create some children Bone2D nodes."));
err_dialog->popup_centered_minsize();
return;
}
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action(TTR("Create Rest Pose from Bones"));
for (int i = 0; i < node->get_bone_count(); i++) {
Bone2D *bone = node->get_bone(i);
ur->add_do_method(bone, "set_rest", bone->get_transform());
ur->add_undo_method(bone, "set_rest", bone->get_rest());
}
ur->commit_action();
} break;
case MENU_OPTION_SET_REST: {
if (node->get_bone_count() == 0) {
err_dialog->set_text(TTR("This skeleton has no bones, create some children Bone2D nodes."));
@ -84,6 +68,22 @@ void Skeleton2DEditor::_menu_option(int p_option) {
ur->commit_action();
} break;
case MENU_OPTION_MAKE_REST: {
if (node->get_bone_count() == 0) {
err_dialog->set_text(TTR("This skeleton has no bones, create some children Bone2D nodes."));
err_dialog->popup_centered_minsize();
return;
}
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action(TTR("Create Rest Pose from Bones"));
for (int i = 0; i < node->get_bone_count(); i++) {
Bone2D *bone = node->get_bone(i);
ur->add_do_method(bone, "set_rest", bone->get_transform());
ur->add_undo_method(bone, "set_rest", bone->get_rest());
}
ur->commit_action();
} break;
}
}
@ -99,10 +99,10 @@ Skeleton2DEditor::Skeleton2DEditor() {
options->set_text(TTR("Skeleton2D"));
options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Skeleton2D", "EditorIcons"));
options->get_popup()->add_item(TTR("Reset to Rest Pose"), MENU_OPTION_MAKE_REST);
options->get_popup()->add_item(TTR("Reset to Rest Pose"), MENU_OPTION_SET_REST);
options->get_popup()->add_separator();
// Use the "Overwrite" word to highlight that this is a destructive operation.
options->get_popup()->add_item(TTR("Overwrite Rest Pose"), MENU_OPTION_SET_REST);
options->get_popup()->add_item(TTR("Overwrite Rest Pose"), MENU_OPTION_MAKE_REST);
options->set_switch_on_hover(true);
options->get_popup()->connect("id_pressed", this, "_menu_option");

View file

@ -40,8 +40,8 @@ class Skeleton2DEditor : public Control {
GDCLASS(Skeleton2DEditor, Control);
enum Menu {
MENU_OPTION_MAKE_REST,
MENU_OPTION_SET_REST,
MENU_OPTION_MAKE_REST,
};
Skeleton2D *node;

View file

@ -2043,12 +2043,14 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
_menu_option(VIEW_RIGHT);
}
if (ED_IS_SHORTCUT("spatial_editor/orbit_view_down", p_event)) {
cursor.x_rot -= Math_PI / 12.0;
// Clamp rotation to roughly -90..90 degrees so the user can't look upside-down and end up disoriented.
cursor.x_rot = CLAMP(cursor.x_rot - Math_PI / 12.0, -1.57, 1.57);
view_type = VIEW_TYPE_USER;
_update_name();
}
if (ED_IS_SHORTCUT("spatial_editor/orbit_view_up", p_event)) {
cursor.x_rot += Math_PI / 12.0;
// Clamp rotation to roughly -90..90 degrees so the user can't look upside-down and end up disoriented.
cursor.x_rot = CLAMP(cursor.x_rot + Math_PI / 12.0, -1.57, 1.57);
view_type = VIEW_TYPE_USER;
_update_name();
}

View file

@ -30,6 +30,7 @@
#include "rename_dialog.h"
#include "modules/modules_enabled.gen.h" // For regex.
#ifdef MODULE_REGEX_ENABLED
#include "core/print_string.h"

View file

@ -31,7 +31,7 @@
#ifndef RENAME_DIALOG_H
#define RENAME_DIALOG_H
#include "modules/modules_enabled.gen.h"
#include "modules/modules_enabled.gen.h" // For regex.
#ifdef MODULE_REGEX_ENABLED
#include "scene/gui/check_box.h"

View file

@ -48,6 +48,8 @@
#include "scene/main/viewport.h"
#include "scene/resources/packed_scene.h"
#include "modules/modules_enabled.gen.h" // For regex.
void SceneTreeDock::_nodes_drag_begin() {
if (restore_script_editor_on_drag) {
EditorNode::get_singleton()->set_visible_editor(EditorNode::EDITOR_SCRIPT);

View file

@ -50,13 +50,14 @@
#include "scene/gui/tree.h"
#include "scene_tree_editor.h"
#include "modules/modules_enabled.gen.h" // For regex.
class EditorNode;
class SceneTreeDock : public VBoxContainer {
GDCLASS(SceneTreeDock, VBoxContainer);
enum Tool {
TOOL_NEW,
TOOL_INSTANCE,
TOOL_EXPAND_COLLAPSE,
@ -96,7 +97,6 @@ class SceneTreeDock : public VBoxContainer {
TOOL_CREATE_3D_SCENE,
TOOL_CREATE_USER_INTERFACE,
TOOL_CREATE_FAVORITE,
};
enum {

View file

@ -34,7 +34,7 @@
#include "core/os/main_loop.h"
#include "core/os/os.h"
#include "modules/modules_enabled.gen.h"
#include "modules/modules_enabled.gen.h" // For gdscript.
#ifdef MODULE_GDSCRIPT_ENABLED
#include "modules/gdscript/gdscript.h"

View file

@ -34,7 +34,7 @@
#include "core/os/os.h"
#include "core/ustring.h"
#include "modules/modules_enabled.gen.h"
#include "modules/modules_enabled.gen.h" // For regex.
#ifdef MODULE_REGEX_ENABLED
#include "modules/regex/regex.h"
#endif

View file

@ -851,8 +851,17 @@ bool BulletPhysicsServer::body_is_ray_pickable(RID p_body) const {
}
PhysicsDirectBodyState *BulletPhysicsServer::body_get_direct_state(RID p_body) {
if (!rigid_body_owner.owns(p_body)) {
return nullptr;
}
RigidBodyBullet *body = rigid_body_owner.get(p_body);
ERR_FAIL_COND_V(!body, nullptr);
if (!body->get_space()) {
return nullptr;
}
return BulletPhysicsDirectBodyState::get_singleton(body);
}

View file

@ -961,6 +961,8 @@ bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) {
call(member->setter, &val, 1, err);
if (err.error == Variant::CallError::CALL_OK) {
return true; //function exists, call was successful
} else {
return false;
}
} else {
if (!member->data_type.is_type(p_value)) {

View file

@ -1537,7 +1537,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
int err_line = line;
if (err_text == "") {
err_text = "Internal Script Error! - opcode #" + itos(last_opcode) + " (report please).";
err_text = "Internal script error! Opcode: " + itos(last_opcode) + " (please report).";
}
if (!GDScriptLanguage::get_singleton()->debug_break(err_text, false)) {

View file

@ -1223,7 +1223,9 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
tokenizer->advance(1);
parenthesis++;
Node *subexpr = _parse_expression(op, p_static, p_allow_assign, p_parsing_constant);
parenthesis--;
if (!subexpr) {
return nullptr;
}

View file

@ -29,9 +29,7 @@
/*************************************************************************/
#include "gltf_document.h"
#include "core/error_list.h"
#include "core/error_macros.h"
#include "core/variant.h"
#include "gltf_accessor.h"
#include "gltf_animation.h"
#include "gltf_camera.h"
@ -44,11 +42,9 @@
#include "gltf_state.h"
#include "gltf_texture.h"
#include <stdio.h>
#include <stdlib.h>
#include "core/bind/core_bind.h"
#include "core/crypto/crypto_core.h"
#include "core/error_list.h"
#include "core/error_macros.h"
#include "core/io/json.h"
#include "core/math/disjoint_set.h"
@ -58,15 +54,6 @@
#include "core/version_hash.gen.h"
#include "drivers/png/png_driver_common.h"
#include "editor/import/resource_importer_scene.h"
#ifdef MODULE_CSG_ENABLED
#include "modules/csg/csg_shape.h"
#endif // MODULE_CSG_ENABLED
#ifdef MODULE_GRIDMAP_ENABLED
#include "modules/gridmap/grid_map.h"
#endif // MODULE_GRIDMAP_ENABLED
#ifdef MODULE_REGEX_ENABLED
#include "modules/regex/regex.h"
#endif // MODULE_REGEX_ENABLED
#include "scene/2d/node_2d.h"
#include "scene/3d/bone_attachment.h"
#include "scene/3d/camera.h"
@ -77,6 +64,21 @@
#include "scene/animation/animation_player.h"
#include "scene/main/node.h"
#include "scene/resources/surface_tool.h"
#include "modules/modules_enabled.gen.h" // For csg, gridmap, regex.
#ifdef MODULE_CSG_ENABLED
#include "modules/csg/csg_shape.h"
#endif // MODULE_CSG_ENABLED
#ifdef MODULE_GRIDMAP_ENABLED
#include "modules/gridmap/grid_map.h"
#endif // MODULE_GRIDMAP_ENABLED
#ifdef MODULE_REGEX_ENABLED
#include "modules/regex/regex.h"
#endif // MODULE_REGEX_ENABLED
#include <stdio.h>
#include <stdlib.h>
#include <limits>
Error GLTFDocument::serialize(Ref<GLTFState> state, Node *p_root, const String &p_path) {
@ -5424,18 +5426,18 @@ void GLTFDocument::_convert_grid_map_to_gltf(GridMap *p_grid_map, GLTFNodeIndex
state->nodes.push_back(new_gltf_node);
Vector3 cell_location = cells[k];
int32_t cell = p_grid_map->get_cell_item(
Vector3(cell_location.x, cell_location.y, cell_location.z));
cell_location.x, cell_location.y, cell_location.z);
MeshInstance *import_mesh_node = memnew(MeshInstance);
import_mesh_node->set_mesh(p_grid_map->get_mesh_library()->get_item_mesh(cell));
Transform cell_xform;
cell_xform.basis.set_orthogonal_index(
p_grid_map->get_cell_item_orientation(
Vector3(cell_location.x, cell_location.y, cell_location.z)));
cell_location.x, cell_location.y, cell_location.z));
cell_xform.basis.scale(Vector3(p_grid_map->get_cell_scale(),
p_grid_map->get_cell_scale(),
p_grid_map->get_cell_scale()));
cell_xform.set_origin(p_grid_map->map_to_world(
Vector3(cell_location.x, cell_location.y, cell_location.z)));
cell_location.x, cell_location.y, cell_location.z));
Ref<GLTFMesh> gltf_mesh;
gltf_mesh.instance();
gltf_mesh = import_mesh_node;
@ -5770,7 +5772,7 @@ struct EditorSceneImporterGLTFInterpolate<Quat> {
template <class T>
T GLTFDocument::_interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, const float p_time, const GLTFAnimation::Interpolation p_interp) {
ERR_FAIL_COND_V(!p_values.size(), T());
if (p_times.size() != p_values.size()) {
if (p_times.size() != (p_values.size() / (p_interp == GLTFAnimation::INTERP_CUBIC_SPLINE ? 3 : 1))) {
ERR_PRINT_ONCE("The interpolated values are not corresponding to its times.");
return p_values[0];
}

View file

@ -31,7 +31,6 @@
#ifndef GLTF_DOCUMENT_H
#define GLTF_DOCUMENT_H
#include "editor/import/resource_importer_scene.h"
#include "gltf_animation.h"
#include "scene/2d/node_2d.h"
#include "scene/3d/bone_attachment.h"
@ -43,6 +42,8 @@
#include "scene/resources/material.h"
#include "scene/resources/texture.h"
#include "modules/modules_enabled.gen.h" // For csg, gridmap.
class GLTFState;
class GLTFSkin;
class GLTFNode;

View file

@ -109,16 +109,18 @@ bool jni_exception_check(JNIEnv *p_env) {
String app_native_lib_dir_cache;
String determine_app_native_lib_dir() {
// The JNI code is the equivalent of:
//
// return godotActivity.getApplicationInfo().nativeLibraryDir;
JNIEnv *env = get_jni_env();
ScopedLocalRef<jclass> activityThreadClass(env, env->FindClass("android/app/ActivityThread"));
jmethodID currentActivityThread = env->GetStaticMethodID(activityThreadClass, "currentActivityThread", "()Landroid/app/ActivityThread;");
ScopedLocalRef<jobject> activityThread(env, env->CallStaticObjectMethod(activityThreadClass, currentActivityThread));
jmethodID getApplication = env->GetMethodID(activityThreadClass, "getApplication", "()Landroid/app/Application;");
ScopedLocalRef<jobject> ctx(env, env->CallObjectMethod(activityThread, getApplication));
GodotJavaWrapper *godot_java = static_cast<OS_Android *>(OS::get_singleton())->get_godot_java();
jobject activity = godot_java->get_activity();
jmethodID getApplicationInfo = env->GetMethodID(env->GetObjectClass(ctx), "getApplicationInfo", "()Landroid/content/pm/ApplicationInfo;");
ScopedLocalRef<jobject> applicationInfo(env, env->CallObjectMethod(ctx, getApplicationInfo));
ScopedLocalRef<jclass> contextClass(env, env->FindClass("android/content/Context"));
jmethodID getApplicationInfo = env->GetMethodID(contextClass, "getApplicationInfo", "()Landroid/content/pm/ApplicationInfo;");
ScopedLocalRef<jobject> applicationInfo(env, env->CallObjectMethod(activity, getApplicationInfo));
jfieldID nativeLibraryDirField = env->GetFieldID(env->GetObjectClass(applicationInfo), "nativeLibraryDir", "Ljava/lang/String;");
ScopedLocalRef<jstring> nativeLibraryDir(env, (jstring)env->GetObjectField(applicationInfo, nativeLibraryDirField));
@ -369,6 +371,7 @@ void initialize() {
String so_path = path::join(app_native_lib_dir, godot_so_name);
godot_dl_handle = try_dlopen(so_path, gd_mono_convert_dl_flags(MONO_DL_LAZY));
ERR_FAIL_COND(!godot_dl_handle);
}
void cleanup() {

View file

@ -46,7 +46,7 @@
#include "scene/resources/shape.h"
#include "scene/resources/sphere_shape.h"
#include "modules/modules_enabled.gen.h"
#include "modules/modules_enabled.gen.h" // For csg, gridmap.
#ifdef MODULE_CSG_ENABLED
#include "modules/csg/csg_shape.h"
#endif

View file

@ -1959,8 +1959,10 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
archive_args.push_back("archive");
archive_args.push_back("-archivePath");
archive_args.push_back(archive_path);
err = OS::get_singleton()->execute("xcodebuild", archive_args, true);
String archive_str;
err = OS::get_singleton()->execute("xcodebuild", archive_args, true, NULL, &archive_str, NULL, true);
ERR_FAIL_COND_V(err, err);
print_line("xcodebuild (.xcarchive):\n" + archive_str);
if (ep.step("Making .ipa", 4)) {
return ERR_SKIP;
@ -1974,8 +1976,10 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
export_args.push_back("-allowProvisioningUpdates");
export_args.push_back("-exportPath");
export_args.push_back(dest_dir);
err = OS::get_singleton()->execute("xcodebuild", export_args, true);
String export_str;
err = OS::get_singleton()->execute("xcodebuild", export_args, true, NULL, &export_str, NULL, true);
ERR_FAIL_COND_V(err, err);
print_line("xcodebuild (.ipa):\n" + export_str);
#else
print_line(".ipa can only be built on macOS. Leaving Xcode project without building the package.");
#endif

View file

@ -82,7 +82,7 @@ def configure(env):
env.Append(CCFLAGS=["-arch", "arm64", "-mmacosx-version-min=10.15"])
env.Append(LINKFLAGS=["-arch", "arm64", "-mmacosx-version-min=10.15"])
else:
print("Building for macOS 10.9+, platform x86-64.")
print("Building for macOS 10.12+, platform x86-64.")
env.Append(CCFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.12"])
env.Append(LINKFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.12"])

View file

@ -1098,8 +1098,21 @@ void EditorExportPlatformOSX::_zip_folder_recursive(zipFile &p_zip, const String
0x0314, // "version made by", 0x03 - Unix, 0x14 - ZIP specification version 2.0, required to store Unix file permissions
0);
Vector<uint8_t> array = FileAccess::get_file_as_array(dir.plus_file(f));
zipWriteInFileInZip(p_zip, array.ptr(), array.size());
FileAccessRef fa = FileAccess::open(dir.plus_file(f), FileAccess::READ);
if (!fa) {
ERR_FAIL_MSG("Can't open file to read from path '" + String(dir.plus_file(f)) + "'.");
}
const int bufsize = 16384;
uint8_t buf[bufsize];
while (true) {
uint64_t got = fa->get_buffer(buf, bufsize);
if (got == 0) {
break;
}
zipWriteInFileInZip(p_zip, buf, got);
}
zipCloseFileInZip(p_zip);
}
}

View file

@ -1682,6 +1682,11 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
CGLSetParameter((CGLContextObj)[context CGLContextObj], kCGLCPSurfaceBackingSize, &dim[0]);
CGLEnable((CGLContextObj)[context CGLContextObj], kCGLCESurfaceBackingSize);
if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) {
CGLError err = CGLEnable((CGLContextObj)[context CGLContextObj], kCGLCEMPEngine); // Enable multithreading.
ERR_FAIL_COND_V(err != kCGLNoError, ERR_UNAVAILABLE);
}
set_use_vsync(p_desired.use_vsync);
if (!is_no_window_mode_enabled()) {

View file

@ -345,10 +345,21 @@ struct _RigidBody2DInOut {
bool RigidBody2D::_test_motion(const Vector2 &p_motion, bool p_infinite_inertia, float p_margin, const Ref<Physics2DTestMotionResult> &p_result) {
Physics2DServer::MotionResult *r = nullptr;
Physics2DServer::MotionResult temp_result;
if (p_result.is_valid()) {
r = p_result->get_result_ptr();
} else {
r = &temp_result;
}
bool colliding = Physics2DServer::get_singleton()->body_test_motion(get_rid(), get_global_transform(), p_motion, p_infinite_inertia, p_margin, r);
if (colliding) {
// Don't report collision when the whole motion is done.
return (r->collision_safe_fraction < 1.0);
} else {
return false;
}
return Physics2DServer::get_singleton()->body_test_motion(get_rid(), get_global_transform(), p_motion, p_infinite_inertia, p_margin, r);
}
void RigidBody2D::_direct_state_changed(Object *p_state) {
@ -1120,6 +1131,10 @@ Vector2 KinematicBody2D::_move_and_slide_internal(const Vector2 &p_linear_veloci
Transform2D gt = get_global_transform();
Vector2 local_position = gt.elements[2] - bs->get_transform().elements[2];
current_floor_velocity = bs->get_velocity_at_local_position(local_position);
} else {
// Body is removed or destroyed, invalidate floor.
current_floor_velocity = Vector2();
on_floor_body = RID();
}
}
@ -1295,7 +1310,15 @@ Vector2 KinematicBody2D::get_floor_velocity() const {
bool KinematicBody2D::test_move(const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia) {
ERR_FAIL_COND_V(!is_inside_tree(), false);
return Physics2DServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia, margin);
Physics2DServer::MotionResult result;
bool colliding = Physics2DServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia, margin, &result);
if (colliding) {
// Don't report collision when the whole motion is done.
return (result.collision_safe_fraction < 1.0);
} else {
return false;
}
}
void KinematicBody2D::set_safe_margin(float p_margin) {

View file

@ -111,6 +111,15 @@ void TileMap::_notification(int p_what) {
}
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
for (Map<PosKey, Quadrant::Occluder>::Element *F = E->get().occluder_instances.front(); F; F = F->next()) {
VS::get_singleton()->canvas_light_occluder_set_enabled(F->get().id, is_visible());
}
}
} break;
}
}
@ -675,6 +684,7 @@ void TileMap::update_dirty_quadrants() {
VS::get_singleton()->canvas_light_occluder_set_polygon(orid, occluder->get_rid());
VS::get_singleton()->canvas_light_occluder_attach_to_canvas(orid, get_canvas());
VS::get_singleton()->canvas_light_occluder_set_light_mask(orid, occluder_light_mask);
VS::get_singleton()->canvas_light_occluder_set_enabled(orid, is_visible());
Quadrant::Occluder oc;
oc.xform = xform;
oc.id = orid;

View file

@ -1074,6 +1074,10 @@ Vector3 KinematicBody::_move_and_slide_internal(const Vector3 &p_linear_velocity
Transform gt = get_global_transform();
Vector3 local_position = gt.origin - bs->get_transform().origin;
current_floor_velocity = bs->get_velocity_at_local_position(local_position);
} else {
// Body is removed or destroyed, invalidate floor.
current_floor_velocity = Vector3();
on_floor_body = RID();
}
}
@ -1255,7 +1259,15 @@ Vector3 KinematicBody::get_floor_velocity() const {
bool KinematicBody::test_move(const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia) {
ERR_FAIL_COND_V(!is_inside_tree(), false);
return PhysicsServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia);
PhysicsServer::MotionResult result;
bool colliding = PhysicsServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia, &result);
if (colliding) {
// Don't report collision when the whole motion is done.
return (result.collision_safe_fraction < 1.0);
} else {
return false;
}
}
bool KinematicBody::separate_raycast_shapes(bool p_infinite_inertia, Collision &r_collision) {

View file

@ -48,7 +48,7 @@
#include "editor/plugins/spatial_editor_plugin.h"
#endif
#include "modules/modules_enabled.gen.h"
#include "modules/modules_enabled.gen.h" // For csg.
#ifdef MODULE_CSG_ENABLED
#include "modules/csg/csg_shape.h"
#endif
@ -313,6 +313,7 @@ void RoomManager::_bind_methods() {
LIMPL_PROPERTY_RANGE(Variant::INT, portal_depth_limit, set_portal_depth_limit, get_portal_depth_limit, "0,255,1");
LIMPL_PROPERTY_RANGE(Variant::REAL, room_simplify, set_room_simplify, get_room_simplify, "0.0,1.0,0.005");
LIMPL_PROPERTY_RANGE(Variant::REAL, default_portal_margin, set_default_portal_margin, get_default_portal_margin, "0.0, 10.0, 0.01");
LIMPL_PROPERTY_RANGE(Variant::REAL, roaming_expansion_margin, set_roaming_expansion_margin, get_roaming_expansion_margin, "0.0, 3.0, 0.01");
#undef LIMPL_PROPERTY
#undef LIMPL_PROPERTY_RANGE
@ -382,7 +383,15 @@ void RoomManager::set_portal_depth_limit(int p_limit) {
_settings_portal_depth_limit = p_limit;
if (is_inside_world() && get_world().is_valid()) {
VisualServer::get_singleton()->rooms_set_params(get_world()->get_scenario(), p_limit);
VisualServer::get_singleton()->rooms_set_params(get_world()->get_scenario(), p_limit, _settings_roaming_expansion_margin);
}
}
void RoomManager::set_roaming_expansion_margin(real_t p_dist) {
_settings_roaming_expansion_margin = p_dist;
if (is_inside_world() && get_world().is_valid()) {
VisualServer::get_singleton()->rooms_set_params(get_world()->get_scenario(), _settings_portal_depth_limit, _settings_roaming_expansion_margin);
}
}

View file

@ -88,6 +88,9 @@ public:
void set_portal_depth_limit(int p_limit);
int get_portal_depth_limit() const { return _settings_portal_depth_limit; }
void set_roaming_expansion_margin(real_t p_dist);
real_t get_roaming_expansion_margin() const { return _settings_roaming_expansion_margin; }
void set_pvs_mode(PVSMode p_mode);
PVSMode get_pvs_mode() const;
@ -256,6 +259,7 @@ private:
real_t _overlap_warning_threshold = 1.0;
Room::SimplifyInfo _room_simplify_info;
int _settings_portal_depth_limit = 16;
real_t _settings_roaming_expansion_margin = 1.0;
// debug override camera
ObjectID _godot_preview_camera_ID = -1;

View file

@ -471,6 +471,8 @@ void Control::_notification(int p_notification) {
_size_changed();
} break;
case NOTIFICATION_EXIT_TREE: {
ERR_FAIL_COND(!get_viewport());
get_viewport()->_gui_remove_control(this);
} break;

View file

@ -35,15 +35,15 @@
#include "core/os/os.h"
#include "scene/scene_string_names.h"
#include "modules/modules_enabled.gen.h"
#ifdef MODULE_REGEX_ENABLED
#include "modules/regex/regex.h"
#endif
#ifdef TOOLS_ENABLED
#include "editor/editor_scale.h"
#endif
#include "modules/modules_enabled.gen.h" // For regex.
#ifdef MODULE_REGEX_ENABLED
#include "modules/regex/regex.h"
#endif
RichTextLabel::Item *RichTextLabel::_get_next_item(Item *p_item, bool p_free) {
if (p_free) {
if (p_item->subitems.size()) {

View file

@ -383,7 +383,7 @@ bool HTTPRequest::_update_connection() {
void HTTPRequest::_request_done(int p_status, int p_code, const PoolStringArray &p_headers, const PoolByteArray &p_data) {
cancel_request();
emit_signal("request_completed", p_status, p_code, headers, p_data);
emit_signal("request_completed", p_status, p_code, p_headers, p_data);
}
void HTTPRequest::_notification(int p_what) {

View file

@ -30,8 +30,6 @@
#include "scene_tree.h"
#include "modules/modules_enabled.gen.h"
#include "core/io/marshalls.h"
#include "core/io/resource_loader.h"
#include "core/message_queue.h"
@ -52,6 +50,8 @@
#include "servers/physics_server.h"
#include "viewport.h"
#include "modules/modules_enabled.gen.h" // For freetype.
#include <stdio.h>
#include <stdlib.h>

View file

@ -218,6 +218,8 @@
#include "scene/resources/occluder_shape.h"
#endif
#include "modules/modules_enabled.gen.h" // For freetype.
static Ref<ResourceFormatSaverText> resource_saver_text;
static Ref<ResourceFormatLoaderText> resource_loader_text;

View file

@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "modules/modules_enabled.gen.h"
#include "modules/modules_enabled.gen.h" // For freetype.
#ifdef MODULE_FREETYPE_ENABLED
#include "dynamic_font.h"

View file

@ -31,7 +31,7 @@
#ifndef DYNAMIC_FONT_H
#define DYNAMIC_FONT_H
#include "modules/modules_enabled.gen.h"
#include "modules/modules_enabled.gen.h" // For freetype.
#ifdef MODULE_FREETYPE_ENABLED
#include "core/io/resource_loader.h"

View file

@ -883,8 +883,17 @@ int PhysicsServerSW::body_test_ray_separation(RID p_body, const Transform &p_tra
}
PhysicsDirectBodyState *PhysicsServerSW::body_get_direct_state(RID p_body) {
if (!body_owner.owns(p_body)) {
return nullptr;
}
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body, nullptr);
if (!body->get_space()) {
return nullptr;
}
ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
direct_state->body = body;

View file

@ -239,7 +239,7 @@ public:
_FORCE_INLINE_ real_t get_height() const { return height; }
_FORCE_INLINE_ real_t get_radius() const { return radius; }
virtual real_t get_area() const { return 4.0 / 3.0 * Math_PI * radius * radius * radius + height * Math_PI * radius * radius; }
virtual real_t get_area() const { return height * Math_PI * radius * radius; }
virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_CAPSULE; }

View file

@ -962,7 +962,11 @@ Physics2DDirectBodyState *Physics2DServerSW::body_get_direct_state(RID p_body) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body, nullptr);
ERR_FAIL_COND_V(!body->get_space(), nullptr);
if (!body->get_space()) {
return nullptr;
}
ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
direct_state->body = body;

View file

@ -273,6 +273,34 @@ Dictionary PhysicsDirectSpaceState::_intersect_ray(const Vector3 &p_from, const
return d;
}
Array PhysicsDirectSpaceState::_intersect_point(const Vector3 &p_point, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) {
Set<RID> exclude;
for (int i = 0; i < p_exclude.size(); i++) {
exclude.insert(p_exclude[i]);
}
Vector<ShapeResult> ret;
ret.resize(p_max_results);
int rc = intersect_point(p_point, ret.ptrw(), ret.size(), exclude, p_layers, p_collide_with_bodies, p_collide_with_areas);
if (rc == 0) {
return Array();
}
Array r;
r.resize(rc);
for (int i = 0; i < rc; i++) {
Dictionary d;
d["rid"] = ret[i].rid;
d["collider_id"] = ret[i].collider_id;
d["collider"] = ret[i].collider;
d["shape"] = ret[i].shape;
r[i] = d;
}
return r;
}
Array PhysicsDirectSpaceState::_intersect_shape(const Ref<PhysicsShapeQueryParameters> &p_shape_query, int p_max_results) {
ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
@ -349,6 +377,7 @@ PhysicsDirectSpaceState::PhysicsDirectSpaceState() {
}
void PhysicsDirectSpaceState::_bind_methods() {
ClassDB::bind_method(D_METHOD("intersect_point", "point", "max_results", "exclude", "collision_layer", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState::_intersect_point, DEFVAL(32), DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false));
ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState::_intersect_ray, DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false));
ClassDB::bind_method(D_METHOD("intersect_shape", "shape", "max_results"), &PhysicsDirectSpaceState::_intersect_shape, DEFVAL(32));
ClassDB::bind_method(D_METHOD("cast_motion", "shape", "motion"), &PhysicsDirectSpaceState::_cast_motion);

View file

@ -143,6 +143,7 @@ class PhysicsDirectSpaceState : public Object {
private:
Dictionary _intersect_ray(const Vector3 &p_from, const Vector3 &p_to, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_collision_mask = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
Array _intersect_point(const Vector3 &p_point, int p_max_results = 32, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
Array _intersect_shape(const Ref<PhysicsShapeQueryParameters> &p_shape_query, int p_max_results = 32);
Array _cast_motion(const Ref<PhysicsShapeQueryParameters> &p_shape_query, const Vector3 &p_motion);
Array _collide_shape(const Ref<PhysicsShapeQueryParameters> &p_shape_query, int p_max_results = 32);

View file

@ -822,20 +822,6 @@ void PortalRenderer::rooms_finalize(bool p_generate_pvs, bool p_cull_using_pvs,
// from position
_rooms_lookup_bsp.create(*this);
// calculate the roaming expansion margin based on the average room size
Vector3 total_size = Vector3(0, 0, 0);
for (int n = 0; n < get_num_rooms(); n++) {
total_size += get_room(n)._aabb.size;
}
if (get_num_rooms()) {
total_size /= get_num_rooms();
AABB temp;
temp.size = total_size;
// longest axis of average room * fudge factor
_roaming_expansion_margin = temp.get_longest_axis_size() * 0.08;
}
// calculate PVS
if (p_generate_pvs) {
PVSBuilder pvs;

View file

@ -156,7 +156,10 @@ public:
void rooms_finalize(bool p_generate_pvs, bool p_cull_using_pvs, bool p_use_secondary_pvs, bool p_use_signals, String p_pvs_filename, bool p_use_simple_pvs, bool p_log_pvs_generation);
void rooms_override_camera(bool p_override, const Vector3 &p_point, const Vector<Plane> *p_convex);
void rooms_set_active(bool p_active) { _active = p_active; }
void rooms_set_params(int p_portal_depth_limit) { _tracer.set_depth_limit(p_portal_depth_limit); }
void rooms_set_params(int p_portal_depth_limit, real_t p_roaming_expansion_margin) {
_tracer.set_depth_limit(p_portal_depth_limit);
_roaming_expansion_margin = p_roaming_expansion_margin;
}
void rooms_set_cull_using_pvs(bool p_enable) { _cull_using_pvs = p_enable; }
void rooms_update_gameplay_monitor(const Vector<Vector3> &p_camera_positions);

View file

@ -598,7 +598,7 @@ public:
BIND8(rooms_finalize, RID, bool, bool, bool, bool, String, bool, bool)
BIND4(rooms_override_camera, RID, bool, const Vector3 &, const Vector<Plane> *)
BIND2(rooms_set_active, RID, bool)
BIND2(rooms_set_params, RID, int)
BIND3(rooms_set_params, RID, int, real_t)
BIND3(rooms_set_debug_feature, RID, RoomsDebugFeature, bool)
BIND2(rooms_update_gameplay_monitor, RID, const Vector<Vector3> &)

View file

@ -1346,10 +1346,10 @@ void VisualServerScene::rooms_set_active(RID p_scenario, bool p_active) {
scenario->_portal_renderer.rooms_set_active(p_active);
}
void VisualServerScene::rooms_set_params(RID p_scenario, int p_portal_depth_limit) {
void VisualServerScene::rooms_set_params(RID p_scenario, int p_portal_depth_limit, real_t p_roaming_expansion_margin) {
Scenario *scenario = scenario_owner.getornull(p_scenario);
ERR_FAIL_COND(!scenario);
scenario->_portal_renderer.rooms_set_params(p_portal_depth_limit);
scenario->_portal_renderer.rooms_set_params(p_portal_depth_limit, p_roaming_expansion_margin);
}
void VisualServerScene::rooms_set_debug_feature(RID p_scenario, VisualServer::RoomsDebugFeature p_feature, bool p_active) {

View file

@ -668,7 +668,7 @@ public:
virtual void rooms_finalize(RID p_scenario, bool p_generate_pvs, bool p_cull_using_pvs, bool p_use_secondary_pvs, bool p_use_signals, String p_pvs_filename, bool p_use_simple_pvs, bool p_log_pvs_generation);
virtual void rooms_override_camera(RID p_scenario, bool p_override, const Vector3 &p_point, const Vector<Plane> *p_convex);
virtual void rooms_set_active(RID p_scenario, bool p_active);
virtual void rooms_set_params(RID p_scenario, int p_portal_depth_limit);
virtual void rooms_set_params(RID p_scenario, int p_portal_depth_limit, real_t p_roaming_expansion_margin);
virtual void rooms_set_debug_feature(RID p_scenario, VisualServer::RoomsDebugFeature p_feature, bool p_active);
virtual void rooms_update_gameplay_monitor(RID p_scenario, const Vector<Vector3> &p_camera_positions);

View file

@ -521,7 +521,7 @@ public:
FUNC8(rooms_finalize, RID, bool, bool, bool, bool, String, bool, bool)
FUNC4(rooms_override_camera, RID, bool, const Vector3 &, const Vector<Plane> *)
FUNC2(rooms_set_active, RID, bool)
FUNC2(rooms_set_params, RID, int)
FUNC3(rooms_set_params, RID, int, real_t)
FUNC3(rooms_set_debug_feature, RID, RoomsDebugFeature, bool)
FUNC2(rooms_update_gameplay_monitor, RID, const Vector<Vector3> &)

View file

@ -921,7 +921,7 @@ public:
virtual void rooms_finalize(RID p_scenario, bool p_generate_pvs, bool p_cull_using_pvs, bool p_use_secondary_pvs, bool p_use_signals, String p_pvs_filename, bool p_use_simple_pvs, bool p_log_pvs_generation) = 0;
virtual void rooms_override_camera(RID p_scenario, bool p_override, const Vector3 &p_point, const Vector<Plane> *p_convex) = 0;
virtual void rooms_set_active(RID p_scenario, bool p_active) = 0;
virtual void rooms_set_params(RID p_scenario, int p_portal_depth_limit) = 0;
virtual void rooms_set_params(RID p_scenario, int p_portal_depth_limit, real_t p_roaming_expansion_margin) = 0;
virtual void rooms_set_debug_feature(RID p_scenario, RoomsDebugFeature p_feature, bool p_active) = 0;
virtual void rooms_update_gameplay_monitor(RID p_scenario, const Vector<Vector3> &p_camera_positions) = 0;