From e1af61467a36d5d1e4a319d6fc6c3003c9f96ec2 Mon Sep 17 00:00:00 2001 From: David Snopek Date: Mon, 12 Aug 2024 11:26:23 -0500 Subject: [PATCH 001/190] OpenGL: Unconditionally do `glDisable(GL_FRAMEBUFFER_SRGB)` because we do our own sRGB conversion (cherry picked from commit dfcff4ef46568216318adb37cb84c42697139ac6) --- drivers/gles3/rasterizer_gles3.cpp | 7 ++++++ .../platform/openxr_opengl_extension.cpp | 22 ------------------- .../platform/openxr_opengl_extension.h | 6 ----- 3 files changed, 7 insertions(+), 28 deletions(-) diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index 37e7256d764..19ef3d416ce 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -62,6 +62,10 @@ #define _EXT_DEBUG_SEVERITY_LOW_ARB 0x9148 #define _EXT_DEBUG_OUTPUT 0x92E0 +#ifndef GL_FRAMEBUFFER_SRGB +#define GL_FRAMEBUFFER_SRGB 0x8DB9 +#endif + #ifndef GLAPIENTRY #if defined(WINDOWS_ENABLED) #define GLAPIENTRY APIENTRY @@ -345,6 +349,9 @@ RasterizerGLES3::RasterizerGLES3() { } } + // Disable OpenGL linear to sRGB conversion, because Godot will always do this conversion itself. + glDisable(GL_FRAMEBUFFER_SRGB); + // OpenGL needs to be initialized before initializing the Rasterizers config = memnew(GLES3::Config); utilities = memnew(GLES3::Utilities); diff --git a/modules/openxr/extensions/platform/openxr_opengl_extension.cpp b/modules/openxr/extensions/platform/openxr_opengl_extension.cpp index d92084a220d..de4a9e4b8e9 100644 --- a/modules/openxr/extensions/platform/openxr_opengl_extension.cpp +++ b/modules/openxr/extensions/platform/openxr_opengl_extension.cpp @@ -56,11 +56,6 @@ // feature off. // See: https://registry.khronos.org/OpenGL/extensions/EXT/EXT_sRGB_write_control.txt -// On OpenGLES this is not defined in our standard headers.. -#ifndef GL_FRAMEBUFFER_SRGB -#define GL_FRAMEBUFFER_SRGB 0x8DB9 -#endif - HashMap OpenXROpenGLExtension::get_requested_extensions() { HashMap request_extensions; @@ -196,23 +191,6 @@ void OpenXROpenGLExtension::get_usable_depth_formats(Vector &p_usable_d p_usable_depth_formats.push_back(GL_DEPTH_COMPONENT24); } -void OpenXROpenGLExtension::on_pre_draw_viewport(RID p_render_target) { - if (srgb_ext_is_available) { - hw_linear_to_srgb_is_enabled = glIsEnabled(GL_FRAMEBUFFER_SRGB); - if (hw_linear_to_srgb_is_enabled) { - // Disable this. - glDisable(GL_FRAMEBUFFER_SRGB); - } - } -} - -void OpenXROpenGLExtension::on_post_draw_viewport(RID p_render_target) { - if (srgb_ext_is_available && hw_linear_to_srgb_is_enabled) { - // Re-enable this. - glEnable(GL_FRAMEBUFFER_SRGB); - } -} - bool OpenXROpenGLExtension::get_swapchain_image_data(XrSwapchain p_swapchain, int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size, void **r_swapchain_graphics_data) { GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton(); ERR_FAIL_NULL_V(texture_storage, false); diff --git a/modules/openxr/extensions/platform/openxr_opengl_extension.h b/modules/openxr/extensions/platform/openxr_opengl_extension.h index a3052d3f534..8da3ca48f4f 100644 --- a/modules/openxr/extensions/platform/openxr_opengl_extension.h +++ b/modules/openxr/extensions/platform/openxr_opengl_extension.h @@ -49,9 +49,6 @@ public: virtual void on_instance_created(const XrInstance p_instance) override; virtual void *set_session_create_and_get_next_pointer(void *p_next_pointer) override; - virtual void on_pre_draw_viewport(RID p_render_target) override; - virtual void on_post_draw_viewport(RID p_render_target) override; - virtual void get_usable_swapchain_formats(Vector &p_usable_swap_chains) override; virtual void get_usable_depth_formats(Vector &p_usable_swap_chains) override; virtual String get_swapchain_format_name(int64_t p_swapchain_format) const override; @@ -76,9 +73,6 @@ private: Vector texture_rids; }; - bool srgb_ext_is_available = true; - bool hw_linear_to_srgb_is_enabled = false; - bool check_graphics_api_support(XrVersion p_desired_version); #ifdef ANDROID_ENABLED From 5caaa6ce19ea01201f20dda5636044e6bd1b4239 Mon Sep 17 00:00:00 2001 From: "Silc Lizard (Tokage) Renew" <61938263+TokageItLab@users.noreply.github.com> Date: Thu, 15 Aug 2024 16:53:18 +0900 Subject: [PATCH 002/190] Fix incorrect warning on SkeletonModifier (cherry picked from commit 4727c4f783573c6c7590bfdf4c8d52d6dca485b2) --- scene/3d/skeleton_modifier_3d.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scene/3d/skeleton_modifier_3d.cpp b/scene/3d/skeleton_modifier_3d.cpp index 9851214194b..d5c603112ea 100644 --- a/scene/3d/skeleton_modifier_3d.cpp +++ b/scene/3d/skeleton_modifier_3d.cpp @@ -37,7 +37,7 @@ void SkeletonModifier3D::_validate_property(PropertyInfo &p_property) const { PackedStringArray SkeletonModifier3D::get_configuration_warnings() const { PackedStringArray warnings = Node3D::get_configuration_warnings(); if (skeleton_id.is_null()) { - warnings.push_back(RTR("Skeleton3D node not set! SkeletonModifier3D must be child of Skeleton3D or set a path to an external skeleton.")); + warnings.push_back(RTR("Skeleton3D node not set! SkeletonModifier3D must be child of Skeleton3D.")); } return warnings; } From b9271608dff5b66a0d505a597ef10bcd2f88ea0c Mon Sep 17 00:00:00 2001 From: Chris Cranford Date: Thu, 15 Aug 2024 14:42:51 -0400 Subject: [PATCH 003/190] Remove superfluous `print_line` call (cherry picked from commit b1421a0d9855506d45773ffb56d4e477b1648da9) --- editor/plugins/visual_shader_editor_plugin.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 2da9d66d9a4..f4ce35f8f25 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -154,7 +154,6 @@ VSRerouteNode::VSRerouteNode() { title_lbl->hide(); const Size2 size = Size2(32, 32) * EDSCALE; - print_line("VSRerouteNode size: " + size); Control *slot_area = memnew(Control); slot_area->set_custom_minimum_size(size); From 13d522791122a3c8c415884b3e087843ad04cc65 Mon Sep 17 00:00:00 2001 From: Slashscreen Date: Sat, 10 Aug 2024 19:18:34 -0700 Subject: [PATCH 004/190] Apply patch for considering visual layers for DirectionalLight Co-authored-by: majikayogames <152851004+majikayogames@users.noreply.github.com> (cherry picked from commit 4457b11ff0d8a4344118dee6ab0955c2dd6c68b9) --- servers/rendering/renderer_scene_cull.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index b02d3def88f..b08698d32a3 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -3089,7 +3089,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c Vector lights_with_shadow; for (Instance *E : scenario->directional_lights) { - if (!E->visible) { + if (!E->visible || !(E->layer_mask & p_visible_layers)) { continue; } From 2df506ea15891a4b2299dd734c98257e19df5b0a Mon Sep 17 00:00:00 2001 From: Kyle Appelgate Date: Tue, 17 Oct 2023 08:56:35 -0400 Subject: [PATCH 005/190] fix to ensure generated light probes do not get placed too close to manual light probes (cherry picked from commit 97205ea5b8126c4f1f613288d7bd366e6155eeee) --- scene/3d/lightmap_gi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp index 038a78609fc..bf928580e44 100644 --- a/scene/3d/lightmap_gi.cpp +++ b/scene/3d/lightmap_gi.cpp @@ -709,7 +709,7 @@ void LightmapGI::_gen_new_positions_from_octree(const GenProbesOctree *p_cell, f const Vector3 *pp = probe_positions.ptr(); bool exists = false; for (int j = 0; j < ppcount; j++) { - if (pp[j].is_equal_approx(real_pos)) { + if (pp[j].distance_to(real_pos) < (p_cell_size * 0.5f)) { exists = true; break; } From a7756d530e27e17bede5f223f3f7b6c38fd9ef7c Mon Sep 17 00:00:00 2001 From: Miley Hollenberg Date: Tue, 30 Jul 2024 08:43:04 +0200 Subject: [PATCH 006/190] Fixed crash on PowerVR GE8320 GPUs (cherry picked from commit 1c31e30359cd0e789b9ec476c43bf78350f054a3) --- drivers/gles3/shader_gles3.cpp | 5 +++-- drivers/gles3/storage/config.cpp | 2 ++ drivers/gles3/storage/config.h | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index 4a15ed827a0..5a0f394db0b 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -698,7 +698,8 @@ void ShaderGLES3::_clear_version(Version *p_version) { void ShaderGLES3::_initialize_version(Version *p_version) { ERR_FAIL_COND(p_version->variants.size() > 0); - if (shader_cache_dir_valid && _load_from_cache(p_version)) { + bool use_cache = shader_cache_dir_valid && !(feedback_count > 0 && GLES3::Config::get_singleton()->disable_transform_feedback_shader_cache); + if (use_cache && _load_from_cache(p_version)) { return; } p_version->variants.reserve(variant_count); @@ -709,7 +710,7 @@ void ShaderGLES3::_initialize_version(Version *p_version) { _compile_specialization(spec, i, p_version, specialization_default_mask); p_version->variants[i].insert(specialization_default_mask, spec); } - if (shader_cache_dir_valid) { + if (use_cache) { _save_to_cache(p_version); } } diff --git a/drivers/gles3/storage/config.cpp b/drivers/gles3/storage/config.cpp index a28b050bf80..2b3c19dbb84 100644 --- a/drivers/gles3/storage/config.cpp +++ b/drivers/gles3/storage/config.cpp @@ -218,6 +218,8 @@ Config::Config() { //https://github.com/godotengine/godot/issues/92662#issuecomment-2161199477 //disable_particles_workaround = false; } + } else if (rendering_device_name == "PowerVR Rogue GE8320") { + disable_transform_feedback_shader_cache = true; } } diff --git a/drivers/gles3/storage/config.h b/drivers/gles3/storage/config.h index 0c9f9bc275e..ff72fc5b589 100644 --- a/drivers/gles3/storage/config.h +++ b/drivers/gles3/storage/config.h @@ -96,6 +96,9 @@ public: bool disable_particles_workaround = false; // set to 'true' to disable 'GPUParticles' bool flip_xy_workaround = false; + // PowerVR GE 8320 workaround + bool disable_transform_feedback_shader_cache = false; + #ifdef ANDROID_ENABLED PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC eglFramebufferTextureMultiviewOVR = nullptr; PFNGLTEXSTORAGE3DMULTISAMPLEPROC eglTexStorage3DMultisample = nullptr; From 6595395b8baa1cb6938fad57561326b4aba8ce7e Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Thu, 1 Aug 2024 02:19:01 +0200 Subject: [PATCH 007/190] Fix LightmapGI not taking environment sky rotation into account when baking The sky rotation now affects the baked environment lighting as it should, making it match how real-time ambient light rendering works. Co-authored-by: Per Melin (cherry picked from commit 661cf1f3515ab53c002d2824876dd955b06e9e50) --- scene/3d/lightmap_gi.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp index bf928580e44..3f8b0dfb8ee 100644 --- a/scene/3d/lightmap_gi.cpp +++ b/scene/3d/lightmap_gi.cpp @@ -1072,6 +1072,7 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa if (env.is_valid()) { environment_image = RS::get_singleton()->environment_bake_panorama(env->get_rid(), true, Size2i(128, 64)); + environment_transform = Basis::from_euler(env->get_sky_rotation()).inverse(); } } } break; From 5a33e45fed0b82e05464b10cee4701b7eb7d689e Mon Sep 17 00:00:00 2001 From: clayjohn Date: Fri, 9 Aug 2024 23:53:40 -0700 Subject: [PATCH 008/190] Fail when submit or sync called on main rendering device Fail if submit or sync called multiple times in a row (cherry picked from commit b0e33aa00f661966772a00d98e9bbbb6a1c008a3) --- servers/rendering/rendering_device.cpp | 12 +++++++++--- servers/rendering/rendering_device.h | 3 +++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 22044a8c2d1..da48b24a1a2 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -5065,13 +5065,19 @@ void RenderingDevice::swap_buffers() { void RenderingDevice::submit() { _THREAD_SAFE_METHOD_ + ERR_FAIL_COND_MSG(is_main_instance, "Only local devices can submit and sync."); + ERR_FAIL_COND_MSG(local_device_processing, "device already submitted, call sync to wait until done."); _end_frame(); _execute_frame(false); + local_device_processing = true; } void RenderingDevice::sync() { _THREAD_SAFE_METHOD_ + ERR_FAIL_COND_MSG(is_main_instance, "Only local devices can submit and sync."); + ERR_FAIL_COND_MSG(!local_device_processing, "sync can only be called after a submit"); _begin_frame(); + local_device_processing = false; } void RenderingDevice::_free_pending_resources(int p_frame) { @@ -5323,7 +5329,7 @@ Error RenderingDevice::initialize(RenderingContextDriver *p_context, DisplayServ Error err; RenderingContextDriver::SurfaceID main_surface = 0; - const bool main_instance = (singleton == this) && (p_main_window != DisplayServer::INVALID_WINDOW_ID); + is_main_instance = (singleton == this) && (p_main_window != DisplayServer::INVALID_WINDOW_ID); if (p_main_window != DisplayServer::INVALID_WINDOW_ID) { // Retrieve the surface from the main window if it was specified. main_surface = p_context->surface_get_from_window(p_main_window); @@ -5371,7 +5377,7 @@ Error RenderingDevice::initialize(RenderingContextDriver *p_context, DisplayServ err = driver->initialize(device_index, frame_count); ERR_FAIL_COND_V_MSG(err != OK, FAILED, "Failed to initialize driver for device."); - if (main_instance) { + if (is_main_instance) { // Only the singleton instance with a display should print this information. String rendering_method; if (OS::get_singleton()->get_current_rendering_method() == "mobile") { @@ -5499,7 +5505,7 @@ Error RenderingDevice::initialize(RenderingContextDriver *p_context, DisplayServ compute_list = nullptr; bool project_pipeline_cache_enable = GLOBAL_GET("rendering/rendering_device/pipeline_cache/enable"); - if (main_instance && project_pipeline_cache_enable) { + if (is_main_instance && project_pipeline_cache_enable) { // Only the instance that is not a local device and is also the singleton is allowed to manage a pipeline cache. pipeline_cache_file_path = vformat("user://vulkan/pipelines.%s.%s", OS::get_singleton()->get_current_rendering_method(), diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 38ffd5d23de..52f086e54f9 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -88,6 +88,9 @@ private: RenderingDeviceDriver *driver = nullptr; RenderingContextDriver::Device device; + bool local_device_processing = false; + bool is_main_instance = false; + protected: static void _bind_methods(); From cbee16418a20b64a14a53ae89b384df58d38ce7e Mon Sep 17 00:00:00 2001 From: clayjohn Date: Mon, 12 Aug 2024 16:12:04 -0700 Subject: [PATCH 009/190] Increase precision of skeleton transforms in the skeleton shader in the Compatibility renderer (cherry picked from commit 1bf594fb5acc63b16869c80659bef802cb3dc6d6) --- drivers/gles3/shaders/skeleton.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gles3/shaders/skeleton.glsl b/drivers/gles3/shaders/skeleton.glsl index aad856a5a2f..66befbc3b2c 100644 --- a/drivers/gles3/shaders/skeleton.glsl +++ b/drivers/gles3/shaders/skeleton.glsl @@ -59,7 +59,7 @@ layout(location = 10) in highp uvec4 in_bone_attrib; layout(location = 11) in mediump vec4 in_weight_attrib; #endif -uniform mediump sampler2D skeleton_texture; // texunit:0 +uniform highp sampler2D skeleton_texture; // texunit:0 #endif /* clang-format on */ From a70df8537e494643bd89e03a45a45427e164cbb3 Mon Sep 17 00:00:00 2001 From: jsjtxietian Date: Mon, 29 Jul 2024 11:07:09 +0800 Subject: [PATCH 010/190] Fix uniform subgroup in shader will carry out to next group (cherry picked from commit e6c45fbe5dc38d5e898d8f1058fe7256cdae7559) --- servers/rendering/shader_language.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 0235d72cfa0..431dca0ad48 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -9217,6 +9217,7 @@ Error ShaderLanguage::_parse_shader(const HashMap &p_f tk = _get_token(); if (tk.type == TK_IDENTIFIER) { current_uniform_group_name = tk.text; + current_uniform_subgroup_name = ""; tk = _get_token(); if (tk.type == TK_PERIOD) { tk = _get_token(); From 2eec361f5f6a703f8925498e195d36e76c1c2d64 Mon Sep 17 00:00:00 2001 From: Zi Ye Date: Sun, 11 Aug 2024 14:19:23 -0500 Subject: [PATCH 011/190] Corrected rotation gizmo plane math for off-center perspective view. (cherry picked from commit 1fc8255355db720651fac964c77263dc2818b617) --- editor/plugins/node_3d_editor_plugin.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 59a4ac8075f..97d6010b541 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -5001,14 +5001,24 @@ void Node3DEditorViewport::update_transform(bool p_shift) { } break; case TRANSFORM_ROTATE: { - Plane plane = Plane(_get_camera_normal(), _edit.center); + Plane plane; + if (camera->get_projection() == Camera3D::PROJECTION_PERSPECTIVE) { + Vector3 cam_to_obj = _edit.center - _get_camera_position(); + if (!cam_to_obj.is_zero_approx()) { + plane = Plane(cam_to_obj.normalized(), _edit.center); + } else { + plane = Plane(_get_camera_normal(), _edit.center); + } + } else { + plane = Plane(_get_camera_normal(), _edit.center); + } Vector3 local_axis; Vector3 global_axis; switch (_edit.plane) { case TRANSFORM_VIEW: // local_axis unused - global_axis = _get_camera_normal(); + global_axis = plane.normal; break; case TRANSFORM_X_AXIS: local_axis = Vector3(1, 0, 0); @@ -5039,7 +5049,7 @@ void Node3DEditorViewport::update_transform(bool p_shift) { break; } - static const float orthogonal_threshold = Math::cos(Math::deg_to_rad(87.0f)); + static const float orthogonal_threshold = Math::cos(Math::deg_to_rad(85.0f)); bool axis_is_orthogonal = ABS(plane.normal.dot(global_axis)) < orthogonal_threshold; double angle = 0.0f; From 302af188a1053031546a5babd1e3f235652bed37 Mon Sep 17 00:00:00 2001 From: aaronp64 Date: Tue, 14 May 2024 19:08:40 -0400 Subject: [PATCH 012/190] Fix tooltip content being cut off at some display scales When getting the minimum size for a tooltip, we get the value as a Vector2. Window::set_size() takes a Vector2i, so this size was getting truncated. At certain display scales, this could be enough to cut off part of the tooltip. Updated to call Vector2::ceil() to round up before calling Window::set_size() Fixes #91958 (cherry picked from commit ca8e3d4923f94eebf8d8b16a8625d1de6df32768) --- scene/main/viewport.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 1302e3c53e6..5f9b0b90618 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -1511,6 +1511,7 @@ void Viewport::_gui_show_tooltip() { r.size *= win_scale; vr = window->get_usable_parent_rect(); } + r.size = r.size.ceil(); r.size = r.size.min(panel->get_max_size()); if (r.size.x + r.position.x > vr.size.x + vr.position.x) { From 91ed3cd307ca2adb9eb875b346cf058dff0d50ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20R=C3=B6jder=20Delnavaz?= Date: Fri, 26 Jul 2024 18:15:37 +0200 Subject: [PATCH 013/190] * Changed the VisualShaderNodeCustom template to use the correct overrides and added the GlobalClass attribute (cherry picked from commit 74389e83957ab9476389077d020a047f5831bab7) --- .../VisualShaderNodeCustom/basic.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/modules/mono/editor/script_templates/VisualShaderNodeCustom/basic.cs b/modules/mono/editor/script_templates/VisualShaderNodeCustom/basic.cs index cd335934db0..ece1ab44a2b 100644 --- a/modules/mono/editor/script_templates/VisualShaderNodeCustom/basic.cs +++ b/modules/mono/editor/script_templates/VisualShaderNodeCustom/basic.cs @@ -3,6 +3,8 @@ using _BINDINGS_NAMESPACE_; using System; +[Tool] +[GlobalClass] public partial class VisualShaderNode_CLASS_ : _BASE_ { public override string _GetName() @@ -20,37 +22,37 @@ public partial class VisualShaderNode_CLASS_ : _BASE_ return ""; } - public override long _GetReturnIconType() + public override VisualShaderNode.PortType _GetReturnIconType() { return 0; } - public override long _GetInputPortCount() + public override int _GetInputPortCount() { return 0; } - public override string _GetInputPortName(long port) + public override string _GetInputPortName(int port) { return ""; } - public override long _GetInputPortType(long port) + public override VisualShaderNode.PortType _GetInputPortType(int port) { return 0; } - public override long _GetOutputPortCount() + public override int _GetOutputPortCount() { return 1; } - public override string _GetOutputPortName(long port) + public override string _GetOutputPortName(int port) { return "result"; } - public override long _GetOutputPortType(long port) + public override VisualShaderNode.PortType _GetOutputPortType(int port) { return 0; } From 79848620ce0850c9311fffbc8ea27729a5348292 Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Wed, 14 Aug 2024 23:52:19 +0300 Subject: [PATCH 014/190] [BMFont] Fix importing fonts with `Match char height` enabled. (cherry picked from commit e7f215c2c401944892501c158188301a09622842) --- scene/resources/font.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 104187775d6..6b65ea4cfb9 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -1482,8 +1482,8 @@ Error FontFile::_load_bitmap_font(const String &p_path, List *r_image_fi switch (block_type) { case 1: /* info */ { ERR_FAIL_COND_V_MSG(block_size < 15, ERR_CANT_CREATE, "Invalid BMFont info block size."); - base_size = f->get_16(); - if (base_size <= 0) { + base_size = ABS(static_cast(f->get_16())); + if (base_size == 0) { base_size = 16; } uint8_t flags = f->get_8(); @@ -1776,7 +1776,10 @@ Error FontFile::_load_bitmap_font(const String &p_path, List *r_image_fi if (type == "info") { if (keys.has("size")) { - base_size = keys["size"].to_int(); + base_size = ABS(keys["size"].to_int()); + if (base_size == 0) { + base_size = 16; + } } if (keys.has("outline")) { outline = keys["outline"].to_int(); From 8c5edcb03af76ec93e61c253ca54973702753156 Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Wed, 14 Aug 2024 11:36:29 +0300 Subject: [PATCH 015/190] Run cleanup code on DisplayServer init failure to prevent crash on exit. (cherry picked from commit f15ad7235548130be49e00b44b33e8eb64bb6bc3) --- main/main.cpp | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/main/main.cpp b/main/main.cpp index e42469b51b0..588b8da9bd6 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -2465,7 +2465,10 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph OS::get_singleton()->benchmark_end_measure("Startup", "Main::Setup"); if (p_second_phase) { - return setup2(); + exit_err = setup2(); + if (exit_err != OK) { + goto error; + } } return OK; @@ -2763,6 +2766,30 @@ Error Main::setup2(bool p_show_boot_logo) { if (err != OK || display_server == nullptr) { ERR_PRINT("Unable to create DisplayServer, all display drivers failed.\nUse \"--headless\" command line argument to run the engine in headless mode if this is desired (e.g. for continuous integration)."); + + if (display_server) { + memdelete(display_server); + } + + GDExtensionManager::get_singleton()->deinitialize_extensions(GDExtension::INITIALIZATION_LEVEL_SERVERS); + uninitialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS); + unregister_server_types(); + + if (input) { + memdelete(input); + } + if (tsman) { + memdelete(tsman); + } +#ifndef _3D_DISABLED + if (physics_server_3d_manager) { + memdelete(physics_server_3d_manager); + } +#endif // _3D_DISABLED + if (physics_server_2d_manager) { + memdelete(physics_server_2d_manager); + } + return err; } From fac12603efab36c1dbbc80b936a9ca312b268b02 Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Wed, 14 Aug 2024 00:02:45 +0300 Subject: [PATCH 016/190] [.NET] Move search in files extension list definition to be after Scene level module init. (cherry picked from commit 69d52ed081ac636a0ac696984c304c5284c902a7) --- core/config/project_settings.cpp | 9 --------- doc/classes/ProjectSettings.xml | 2 +- main/main.cpp | 8 ++++++++ 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 37a2608c102..f231e4010f3 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -1489,15 +1489,6 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF(PropertyInfo(Variant::INT, "audio/general/ios/session_category", PROPERTY_HINT_ENUM, "Ambient,Multi Route,Play and Record,Playback,Record,Solo Ambient"), 0); GLOBAL_DEF("audio/general/ios/mix_with_others", false); - PackedStringArray extensions; - extensions.push_back("gd"); - if (ClassDB::class_exists("CSharpScript")) { - extensions.push_back("cs"); - } - extensions.push_back("gdshader"); - - GLOBAL_DEF(PropertyInfo(Variant::PACKED_STRING_ARRAY, "editor/script/search_in_file_extensions"), extensions); - _add_builtin_input_map(); // Keep the enum values in sync with the `DisplayServer::ScreenOrientation` enum. diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index b20b374382e..fef42937920 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -1000,7 +1000,7 @@ prime-run %command% [/codeblock] - + Text-based file extensions to include in the script editor's "Find in Files" feature. You can add e.g. [code]tscn[/code] if you wish to also parse your scene files, especially if you use built-in scripts which are serialized in the scene files. diff --git a/main/main.cpp b/main/main.cpp index 588b8da9bd6..3a6b3aa273a 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -3089,6 +3089,14 @@ Error Main::setup2(bool p_show_boot_logo) { OS::get_singleton()->benchmark_end_measure("Scene", "Modules and Extensions"); } + PackedStringArray extensions; + extensions.push_back("gd"); + if (ClassDB::class_exists("CSharpScript")) { + extensions.push_back("cs"); + } + extensions.push_back("gdshader"); + GLOBAL_DEF_NOVAL(PropertyInfo(Variant::PACKED_STRING_ARRAY, "editor/script/search_in_file_extensions"), extensions); // Note: should be defined after Scene level modules init to see .NET. + OS::get_singleton()->benchmark_end_measure("Startup", "Scene"); #ifdef TOOLS_ENABLED From a7d79f9e6cd78de91deb2d3fa1257ebf1ab116b2 Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Fri, 9 Aug 2024 00:03:00 +0300 Subject: [PATCH 017/190] Fix `TextServer::shaped_text_*_character_pos` for the first character of wrapped string. Allow starting/ending RTL selection before line start. (cherry picked from commit 932acce8f290fe2231e81d685077af084666202e) --- scene/gui/rich_text_label.cpp | 10 +++++++++- servers/text_server.cpp | 6 +++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 1da3668ebed..e9fe78e1629 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -1448,6 +1448,7 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V bool line_clicked = false; float text_rect_begin = 0.0; int char_pos = -1; + bool char_clicked = false; Line &l = p_frame->lines[p_line]; MutexLock lock(l.text_buf->get_mutex()); @@ -1578,6 +1579,9 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V } if (p_click.y >= rect.position.y && p_click.y <= rect.position.y + rect.size.y) { + if (!p_meta) { + char_pos = rtl ? TS->shaped_text_get_range(rid).y : TS->shaped_text_get_range(rid).x; + } if ((!rtl && p_click.x >= rect.position.x) || (rtl && p_click.x <= rect.position.x + rect.size.x)) { if (p_meta) { int64_t glyph_idx = TS->shaped_text_hit_test_grapheme(rid, p_click.x - rect.position.x); @@ -1592,6 +1596,7 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V obj_rect.position.y += baseline_y; if (p_click.y >= obj_rect.position.y && p_click.y <= obj_rect.position.y + obj_rect.size.y) { char_pos = glyphs[glyph_idx].start; + char_clicked = true; } break; } @@ -1602,18 +1607,21 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V float fd = TS->font_get_descent(glyphs[glyph_idx].font_rid, glyphs[glyph_idx].font_size); if (p_click.y >= baseline_y - fa && p_click.y <= baseline_y + fd) { char_pos = glyphs[glyph_idx].start; + char_clicked = true; } } else if (!(glyphs[glyph_idx].flags & TextServer::GRAPHEME_IS_VIRTUAL)) { // Hex code box. Vector2 gl_size = TS->get_hex_code_box_size(glyphs[glyph_idx].font_size, glyphs[glyph_idx].index); if (p_click.y >= baseline_y - gl_size.y * 0.9 && p_click.y <= baseline_y + gl_size.y * 0.2) { char_pos = glyphs[glyph_idx].start; + char_clicked = true; } } } } else { char_pos = TS->shaped_text_hit_test_position(rid, p_click.x - rect.position.x); char_pos = TS->shaped_text_closest_character_pos(rid, char_pos); + char_clicked = true; } } line_clicked = true; @@ -1621,7 +1629,7 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V } // If table hit was detected, and line hit is in the table bounds use table hit. - if (table_hit && (((char_pos + p_frame->lines[p_line].char_offset) >= table_range.x && (char_pos + p_frame->lines[p_line].char_offset) <= table_range.y) || char_pos == -1)) { + if (table_hit && (((char_pos + p_frame->lines[p_line].char_offset) >= table_range.x && (char_pos + p_frame->lines[p_line].char_offset) <= table_range.y) || !char_clicked)) { if (r_click_frame != nullptr) { *r_click_frame = table_click_frame; } diff --git a/servers/text_server.cpp b/servers/text_server.cpp index e7a1511064a..7b1e37a6cc3 100644 --- a/servers/text_server.cpp +++ b/servers/text_server.cpp @@ -1563,7 +1563,7 @@ int64_t TextServer::shaped_text_prev_grapheme_pos(const RID &p_shaped, int64_t p int64_t TextServer::shaped_text_prev_character_pos(const RID &p_shaped, int64_t p_pos) const { const PackedInt32Array &chars = shaped_text_get_character_breaks(p_shaped); - int64_t prev = 0; + int64_t prev = shaped_text_get_range(p_shaped).x; for (const int32_t &E : chars) { if (E >= p_pos) { return prev; @@ -1575,7 +1575,7 @@ int64_t TextServer::shaped_text_prev_character_pos(const RID &p_shaped, int64_t int64_t TextServer::shaped_text_next_character_pos(const RID &p_shaped, int64_t p_pos) const { const PackedInt32Array &chars = shaped_text_get_character_breaks(p_shaped); - int64_t prev = 0; + int64_t prev = shaped_text_get_range(p_shaped).x; for (const int32_t &E : chars) { if (E > p_pos) { return E; @@ -1587,7 +1587,7 @@ int64_t TextServer::shaped_text_next_character_pos(const RID &p_shaped, int64_t int64_t TextServer::shaped_text_closest_character_pos(const RID &p_shaped, int64_t p_pos) const { const PackedInt32Array &chars = shaped_text_get_character_breaks(p_shaped); - int64_t prev = 0; + int64_t prev = shaped_text_get_range(p_shaped).x; for (const int32_t &E : chars) { if (E == p_pos) { return E; From 3dc376ec0be1ba11ffdffbc3ca4f278b1a38cf9d Mon Sep 17 00:00:00 2001 From: Chaosus Date: Sat, 10 Aug 2024 11:07:53 +0300 Subject: [PATCH 018/190] Fix shader crash when the comma used in `for` loop as a trailing (cherry picked from commit d74749fd60c81fd682187ca5eaf08819e55d76d9) --- servers/rendering/shader_language.cpp | 17 +++++++++++++++++ servers/rendering/shader_language.h | 1 + 2 files changed, 18 insertions(+) diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 431dca0ad48..9c4e3fb249f 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -898,6 +898,13 @@ bool ShaderLanguage::_lookup_next(Token &r_tk) { return false; } +ShaderLanguage::Token ShaderLanguage::_peek() { + TkPos pre_pos = _get_tkpos(); + Token tk = _get_token(); + _set_tkpos(pre_pos); + return tk; +} + String ShaderLanguage::token_debug(const String &p_code) { clear(); @@ -8080,6 +8087,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun _set_error(RTR("The middle expression is expected to be a boolean operator.")); return ERR_PARSE_ERROR; } + tk = _peek(); + if (tk.type == TK_SEMICOLON) { + _set_error(vformat(RTR("Expected expression, found: '%s'."), get_token_text(tk))); + return ERR_PARSE_ERROR; + } continue; } if (tk.type != TK_SEMICOLON) { @@ -8088,6 +8100,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } } else if (p_block->block_type == BlockNode::BLOCK_TYPE_FOR_EXPRESSION) { if (tk.type == TK_COMMA) { + tk = _peek(); + if (tk.type == TK_PARENTHESIS_CLOSE) { + _set_error(vformat(RTR("Expected expression, found: '%s'."), get_token_text(tk))); + return ERR_PARSE_ERROR; + } continue; } if (tk.type != TK_PARENTHESIS_CLOSE) { diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 4a67c8f2d2a..ad3b78546d1 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -1037,6 +1037,7 @@ private: Token _make_token(TokenType p_type, const StringName &p_text = StringName()); Token _get_token(); bool _lookup_next(Token &r_tk); + Token _peek(); ShaderNode *shader = nullptr; From cfa33666c9055215746e2c489d9d6110ef78995d Mon Sep 17 00:00:00 2001 From: Ian McCleary Date: Sat, 27 Jul 2024 18:58:12 -0500 Subject: [PATCH 019/190] Fix custom resources using incorrect icons (cherry picked from commit 140f9dc3e76c0f99f9d921042ab9362f609429ea) --- editor/editor_file_system.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index feca12b4099..02a95fd8364 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -1779,7 +1779,9 @@ String EditorFileSystem::_get_global_script_class(const String &p_type, const St void EditorFileSystem::_update_file_icon_path(EditorFileSystemDirectory::FileInfo *file_info) { String icon_path; - if (file_info->script_class_icon_path.is_empty() && !file_info->deps.is_empty()) { + if (file_info->resource_script_class != StringName()) { + icon_path = EditorNode::get_editor_data().script_class_get_icon_path(file_info->resource_script_class); + } else if (file_info->script_class_icon_path.is_empty() && !file_info->deps.is_empty()) { const String &script_dep = file_info->deps[0]; // Assuming the first dependency is a script. const String &script_path = script_dep.contains("::") ? script_dep.get_slice("::", 2) : script_dep; if (!script_path.is_empty()) { From 562e583872036ea9e3683e447f85e94791b2ecc4 Mon Sep 17 00:00:00 2001 From: Haoyu Qiu Date: Fri, 16 Aug 2024 13:23:04 +0800 Subject: [PATCH 020/190] Fix split_floats behavior when spaces are used as separators (cherry picked from commit f483c3aafa5f3cfb1ab763ab4eb077aac74e88d6) --- core/string/ustring.cpp | 10 ++- tests/core/string/test_string.h | 122 +++++++++++++++++++------------- 2 files changed, 82 insertions(+), 50 deletions(-) diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index 3d37e17ef83..07d754daf79 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -1537,13 +1537,16 @@ Vector String::split_floats(const String &p_splitter, bool p_allow_empty int from = 0; int len = length(); + String buffer = *this; while (true) { int end = find(p_splitter, from); if (end < 0) { end = len; } if (p_allow_empty || (end > from)) { - ret.push_back(String::to_float(&get_data()[from])); + buffer[end] = 0; + ret.push_back(String::to_float(&buffer.get_data()[from])); + buffer[end] = _cowdata.get(end); } if (end == len) { @@ -1561,6 +1564,7 @@ Vector String::split_floats_mk(const Vector &p_splitters, bool p_ int from = 0; int len = length(); + String buffer = *this; while (true) { int idx; int end = findmk(p_splitters, from, &idx); @@ -1572,7 +1576,9 @@ Vector String::split_floats_mk(const Vector &p_splitters, bool p_ } if (p_allow_empty || (end > from)) { - ret.push_back(String::to_float(&get_data()[from])); + buffer[end] = 0; + ret.push_back(String::to_float(&buffer.get_data()[from])); + buffer[end] = _cowdata.get(end); } if (end == len) { diff --git a/tests/core/string/test_string.h b/tests/core/string/test_string.h index cf57183a025..393ae16d0a8 100644 --- a/tests/core/string/test_string.h +++ b/tests/core/string/test_string.h @@ -638,64 +638,90 @@ TEST_CASE("[String] Ends with") { } TEST_CASE("[String] Splitting") { - String s = "Mars,Jupiter,Saturn,Uranus"; - const char *slices_l[3] = { "Mars", "Jupiter", "Saturn,Uranus" }; - MULTICHECK_SPLIT(s, split, ",", true, 2, slices_l, 3); + { + const String s = "Mars,Jupiter,Saturn,Uranus"; - const char *slices_r[3] = { "Mars,Jupiter", "Saturn", "Uranus" }; - MULTICHECK_SPLIT(s, rsplit, ",", true, 2, slices_r, 3); + const char *slices_l[3] = { "Mars", "Jupiter", "Saturn,Uranus" }; + MULTICHECK_SPLIT(s, split, ",", true, 2, slices_l, 3); - s = "test"; - const char *slices_3[4] = { "t", "e", "s", "t" }; - MULTICHECK_SPLIT(s, split, "", true, 0, slices_3, 4); - - s = ""; - const char *slices_4[1] = { "" }; - MULTICHECK_SPLIT(s, split, "", true, 0, slices_4, 1); - MULTICHECK_SPLIT(s, split, "", false, 0, slices_4, 0); - - s = "Mars Jupiter Saturn Uranus"; - const char *slices_s[4] = { "Mars", "Jupiter", "Saturn", "Uranus" }; - Vector l = s.split_spaces(); - for (int i = 0; i < l.size(); i++) { - CHECK(l[i] == slices_s[i]); + const char *slices_r[3] = { "Mars,Jupiter", "Saturn", "Uranus" }; + MULTICHECK_SPLIT(s, rsplit, ",", true, 2, slices_r, 3); } - s = "1.2;2.3 4.5"; - const double slices_d[3] = { 1.2, 2.3, 4.5 }; - - Vector d_arr; - d_arr = s.split_floats(";"); - CHECK(d_arr.size() == 2); - for (int i = 0; i < d_arr.size(); i++) { - CHECK(ABS(d_arr[i] - slices_d[i]) <= 0.00001); + { + const String s = "test"; + const char *slices[4] = { "t", "e", "s", "t" }; + MULTICHECK_SPLIT(s, split, "", true, 0, slices, 4); } - Vector keys; - keys.push_back(";"); - keys.push_back(" "); - - Vector f_arr; - f_arr = s.split_floats_mk(keys); - CHECK(f_arr.size() == 3); - for (int i = 0; i < f_arr.size(); i++) { - CHECK(ABS(f_arr[i] - slices_d[i]) <= 0.00001); + { + const String s = ""; + const char *slices[1] = { "" }; + MULTICHECK_SPLIT(s, split, "", true, 0, slices, 1); + MULTICHECK_SPLIT(s, split, "", false, 0, slices, 0); } - s = "1;2 4"; - const int slices_i[3] = { 1, 2, 4 }; - - Vector ii; - ii = s.split_ints(";"); - CHECK(ii.size() == 2); - for (int i = 0; i < ii.size(); i++) { - CHECK(ii[i] == slices_i[i]); + { + const String s = "Mars Jupiter Saturn Uranus"; + const char *slices[4] = { "Mars", "Jupiter", "Saturn", "Uranus" }; + Vector l = s.split_spaces(); + for (int i = 0; i < l.size(); i++) { + CHECK(l[i] == slices[i]); + } } - ii = s.split_ints_mk(keys); - CHECK(ii.size() == 3); - for (int i = 0; i < ii.size(); i++) { - CHECK(ii[i] == slices_i[i]); + { + const String s = "1.2;2.3 4.5"; + const double slices[3] = { 1.2, 2.3, 4.5 }; + + const Vector d_arr = s.split_floats(";"); + CHECK(d_arr.size() == 2); + for (int i = 0; i < d_arr.size(); i++) { + CHECK(ABS(d_arr[i] - slices[i]) <= 0.00001); + } + + const Vector keys = { ";", " " }; + const Vector f_arr = s.split_floats_mk(keys); + CHECK(f_arr.size() == 3); + for (int i = 0; i < f_arr.size(); i++) { + CHECK(ABS(f_arr[i] - slices[i]) <= 0.00001); + } + } + + { + const String s = " -2.0 5"; + const double slices[10] = { 0, -2, 0, 0, 0, 0, 0, 0, 0, 5 }; + + const Vector arr = s.split_floats(" "); + CHECK(arr.size() == 10); + for (int i = 0; i < arr.size(); i++) { + CHECK(ABS(arr[i] - slices[i]) <= 0.00001); + } + + const Vector keys = { ";", " " }; + const Vector mk = s.split_floats_mk(keys); + CHECK(mk.size() == 10); + for (int i = 0; i < mk.size(); i++) { + CHECK(mk[i] == slices[i]); + } + } + + { + const String s = "1;2 4"; + const int slices[3] = { 1, 2, 4 }; + + const Vector arr = s.split_ints(";"); + CHECK(arr.size() == 2); + for (int i = 0; i < arr.size(); i++) { + CHECK(arr[i] == slices[i]); + } + + const Vector keys = { ";", " " }; + const Vector mk = s.split_ints_mk(keys); + CHECK(mk.size() == 3); + for (int i = 0; i < mk.size(); i++) { + CHECK(mk[i] == slices[i]); + } } } From 2b4ade1ed605bcbc85bbb5beaacd0f77831270c4 Mon Sep 17 00:00:00 2001 From: Yahkub-R <62478788+Yahkub-R@users.noreply.github.com> Date: Tue, 6 Aug 2024 09:46:37 -0400 Subject: [PATCH 021/190] Fix AudioStreamPlayer get_playback_position() for web build (cherry picked from commit bcd776e44174677f1995a49b697f9651f1f692ec) --- platform/web/audio_driver_web.cpp | 5 + platform/web/audio_driver_web.h | 1 + platform/web/emscripten_helpers.py | 3 + platform/web/export/export_plugin.cpp | 2 + platform/web/godot_audio.h | 1 + platform/web/js/engine/config.js | 2 + .../web/js/libs/audio.position.worklet.js | 50 ++++++++ platform/web/js/libs/library_godot_audio.js | 109 +++++++++++++++++- servers/audio_server.cpp | 11 ++ servers/audio_server.h | 2 + 10 files changed, 183 insertions(+), 3 deletions(-) create mode 100644 platform/web/js/libs/audio.position.worklet.js diff --git a/platform/web/audio_driver_web.cpp b/platform/web/audio_driver_web.cpp index 22487d2756a..5e046d7050d 100644 --- a/platform/web/audio_driver_web.cpp +++ b/platform/web/audio_driver_web.cpp @@ -312,6 +312,11 @@ bool AudioDriverWeb::is_sample_playback_active(const Ref &p return godot_audio_sample_is_active(itos(p_playback->get_instance_id()).utf8().get_data()) != 0; } +double AudioDriverWeb::get_sample_playback_position(const Ref &p_playback) { + ERR_FAIL_COND_V_MSG(p_playback.is_null(), false, "Parameter p_playback is null."); + return godot_audio_get_sample_playback_position(itos(p_playback->get_instance_id()).utf8().get_data()); +} + void AudioDriverWeb::update_sample_playback_pitch_scale(const Ref &p_playback, float p_pitch_scale) { ERR_FAIL_COND_MSG(p_playback.is_null(), "Parameter p_playback is null."); godot_audio_sample_update_pitch_scale( diff --git a/platform/web/audio_driver_web.h b/platform/web/audio_driver_web.h index 46c5ce4de11..d352fa46922 100644 --- a/platform/web/audio_driver_web.h +++ b/platform/web/audio_driver_web.h @@ -96,6 +96,7 @@ public: virtual void stop_sample_playback(const Ref &p_playback) override; virtual void set_sample_playback_pause(const Ref &p_playback, bool p_paused) override; virtual bool is_sample_playback_active(const Ref &p_playback) override; + virtual double get_sample_playback_position(const Ref &p_playback) override; virtual void update_sample_playback_pitch_scale(const Ref &p_playback, float p_pitch_scale = 0.0f) override; virtual void set_sample_playback_bus_volumes_linear(const Ref &p_playback, const HashMap> &p_bus_volumes) override; diff --git a/platform/web/emscripten_helpers.py b/platform/web/emscripten_helpers.py index 2cee3e8110d..8fcabb21c74 100644 --- a/platform/web/emscripten_helpers.py +++ b/platform/web/emscripten_helpers.py @@ -51,11 +51,13 @@ def create_template_zip(env, js, wasm, worker, side): js, wasm, "#platform/web/js/libs/audio.worklet.js", + "#platform/web/js/libs/audio.position.worklet.js", ] out_files = [ zip_dir.File(binary_name + ".js"), zip_dir.File(binary_name + ".wasm"), zip_dir.File(binary_name + ".audio.worklet.js"), + zip_dir.File(binary_name + ".audio.position.worklet.js"), ] if env["threads"]: in_files.append(worker) @@ -74,6 +76,7 @@ def create_template_zip(env, js, wasm, worker, side): "offline.html", "godot.editor.js", "godot.editor.audio.worklet.js", + "godot.editor.audio.position.worklet.js", "logo.svg", "favicon.png", ] diff --git a/platform/web/export/export_plugin.cpp b/platform/web/export/export_plugin.cpp index d83e465e8e5..d8c1b6033d0 100644 --- a/platform/web/export/export_plugin.cpp +++ b/platform/web/export/export_plugin.cpp @@ -242,6 +242,7 @@ Error EditorExportPlatformWeb::_build_pwa(const Ref &p_prese } cache_files.push_back(name + ".worker.js"); cache_files.push_back(name + ".audio.worklet.js"); + cache_files.push_back(name + ".audio.position.worklet.js"); replaces["___GODOT_CACHE___"] = Variant(cache_files).to_json_string(); // Heavy files that are cached on demand. @@ -835,6 +836,7 @@ Error EditorExportPlatformWeb::_export_project(const Ref &p_ DirAccess::remove_file_or_error(basepath + ".js"); DirAccess::remove_file_or_error(basepath + ".worker.js"); DirAccess::remove_file_or_error(basepath + ".audio.worklet.js"); + DirAccess::remove_file_or_error(basepath + ".audio.position.worklet.js"); DirAccess::remove_file_or_error(basepath + ".service.worker.js"); DirAccess::remove_file_or_error(basepath + ".pck"); DirAccess::remove_file_or_error(basepath + ".png"); diff --git a/platform/web/godot_audio.h b/platform/web/godot_audio.h index dd5bec00cf9..4961ebd2bb7 100644 --- a/platform/web/godot_audio.h +++ b/platform/web/godot_audio.h @@ -55,6 +55,7 @@ extern void godot_audio_sample_start(const char *p_playback_object_id, const cha extern void godot_audio_sample_stop(const char *p_playback_object_id); extern void godot_audio_sample_set_pause(const char *p_playback_object_id, bool p_pause); extern int godot_audio_sample_is_active(const char *p_playback_object_id); +extern double godot_audio_get_sample_playback_position(const char *p_playback_object_id); extern void godot_audio_sample_update_pitch_scale(const char *p_playback_object_id, float p_pitch_scale); extern void godot_audio_sample_set_volumes_linear(const char *p_playback_object_id, int *p_buses_buf, int p_buses_size, float *p_volumes_buf, int p_volumes_size); extern void godot_audio_sample_set_finished_callback(void (*p_callback)(const char *)); diff --git a/platform/web/js/engine/config.js b/platform/web/js/engine/config.js index 8c4e1b1b248..61b488cf81c 100644 --- a/platform/web/js/engine/config.js +++ b/platform/web/js/engine/config.js @@ -299,6 +299,8 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused- return `${loadPath}.worker.js`; } else if (path.endsWith('.audio.worklet.js')) { return `${loadPath}.audio.worklet.js`; + } else if (path.endsWith('.audio.position.worklet.js')) { + return `${loadPath}.audio.position.worklet.js`; } else if (path.endsWith('.js')) { return `${loadPath}.js`; } else if (path in gdext) { diff --git a/platform/web/js/libs/audio.position.worklet.js b/platform/web/js/libs/audio.position.worklet.js new file mode 100644 index 00000000000..bf3ac4ae2d2 --- /dev/null +++ b/platform/web/js/libs/audio.position.worklet.js @@ -0,0 +1,50 @@ +/**************************************************************************/ +/* godot.audio.position.worklet.js */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +class GodotPositionReportingProcessor extends AudioWorkletProcessor { + constructor() { + super(); + this.position = 0; + } + + process(inputs, _outputs, _parameters) { + if (inputs.length > 0) { + const input = inputs[0]; + if (input.length > 0) { + this.position += input[0].length; + this.port.postMessage({ 'type': 'position', 'data': this.position }); + return true; + } + } + return true; + } +} + +registerProcessor('godot-position-reporting-processor', GodotPositionReportingProcessor); diff --git a/platform/web/js/libs/library_godot_audio.js b/platform/web/js/libs/library_godot_audio.js index 8b7c5721969..0ba6eed4640 100644 --- a/platform/web/js/libs/library_godot_audio.js +++ b/platform/web/js/libs/library_godot_audio.js @@ -330,6 +330,7 @@ class SampleNodeBus { * startTime?: number * loopMode?: LoopMode * volume?: Float32Array + * start?: boolean * }} SampleNodeOptions */ @@ -421,9 +422,15 @@ class SampleNode { /** @type {number} */ this.offset = options.offset ?? 0; /** @type {number} */ + this._playbackPosition = options.offset; + /** @type {number} */ this.startTime = options.startTime ?? 0; /** @type {boolean} */ this.isPaused = false; + /** @type {boolean} */ + this.isStarted = false; + /** @type {boolean} */ + this.isCanceled = false; /** @type {number} */ this.pauseTime = 0; /** @type {number} */ @@ -440,6 +447,8 @@ class SampleNode { this._source = GodotAudio.ctx.createBufferSource(); this._onended = null; + /** @type {AudioWorkletNode | null} */ + this._positionWorklet = null; this.setPlaybackRate(options.playbackRate ?? 44100); this._source.buffer = this.getSample().getAudioBuffer(); @@ -449,6 +458,8 @@ class SampleNode { const bus = GodotAudio.Bus.getBus(params.busIndex); const sampleNodeBus = this.getSampleNodeBus(bus); sampleNodeBus.setVolume(options.volume); + + this.connectPositionWorklet(options.start); } /** @@ -459,6 +470,14 @@ class SampleNode { return this._playbackRate; } + /** + * Gets the playback position. + * @returns {number} + */ + getPlaybackPosition() { + return this._playbackPosition; + } + /** * Sets the playback rate. * @param {number} val Value to set. @@ -508,8 +527,12 @@ class SampleNode { * @returns {void} */ start() { + if (this.isStarted) { + return; + } this._resetSourceStartTime(); this._source.start(this.startTime, this.offset); + this.isStarted = true; } /** @@ -584,18 +607,74 @@ class SampleNode { return this._sampleNodeBuses.get(bus); } + /** + * Sets up and connects the source to the GodotPositionReportingProcessor + * If the worklet module is not loaded in, it will be added + */ + connectPositionWorklet(start) { + try { + this._positionWorklet = this.createPositionWorklet(); + this._source.connect(this._positionWorklet); + if (start) { + this.start(); + } + } catch (error) { + if (error?.name !== 'InvalidStateError') { + throw error; + } + const path = GodotConfig.locate_file('godot.audio.position.worklet.js'); + GodotAudio.ctx.audioWorklet + .addModule(path) + .then(() => { + if (!this.isCanceled) { + this._positionWorklet = this.createPositionWorklet(); + this._source.connect(this._positionWorklet); + if (start) { + this.start(); + } + } + }).catch((addModuleError) => { + GodotRuntime.error('Failed to create PositionWorklet.', addModuleError); + }); + } + } + + /** + * Creates the AudioWorkletProcessor used to track playback position. + * @returns {AudioWorkletNode} + */ + createPositionWorklet() { + const worklet = new AudioWorkletNode( + GodotAudio.ctx, + 'godot-position-reporting-processor' + ); + worklet.port.onmessage = (event) => { + switch (event.data['type']) { + case 'position': + this._playbackPosition = (parseInt(event.data.data, 10) / this.getSample().sampleRate) + this.offset; + break; + default: + // Do nothing. + } + }; + return worklet; + } + /** * Clears the `SampleNode`. * @returns {void} */ clear() { + this.isCanceled = true; this.isPaused = false; this.pauseTime = 0; if (this._source != null) { this._source.removeEventListener('ended', this._onended); this._onended = null; - this._source.stop(); + if (this.isStarted) { + this._source.stop(); + } this._source.disconnect(); this._source = null; } @@ -605,6 +684,12 @@ class SampleNode { } this._sampleNodeBuses.clear(); + if (this._positionWorklet) { + this._positionWorklet.disconnect(); + this._positionWorklet.port.onmessage = null; + this._positionWorklet = null; + } + GodotAudio.SampleNode.delete(this.id); } @@ -645,7 +730,9 @@ class SampleNode { const pauseTime = this.isPaused ? this.pauseTime : 0; + this.connectPositionWorklet(); this._source.start(this.startTime, this.offset + pauseTime); + this.isStarted = true; } /** @@ -1262,7 +1349,7 @@ const _GodotAudio = { startOptions ) { GodotAudio.SampleNode.stopSampleNode(playbackObjectId); - const sampleNode = GodotAudio.SampleNode.create( + GodotAudio.SampleNode.create( { busIndex, id: playbackObjectId, @@ -1270,7 +1357,6 @@ const _GodotAudio = { }, startOptions ); - sampleNode.start(); }, /** @@ -1590,6 +1676,7 @@ const _GodotAudio = { offset, volume, playbackRate: 1, + start: true, }; GodotAudio.start_sample( playbackObjectId, @@ -1635,6 +1722,22 @@ const _GodotAudio = { return Number(GodotAudio.sampleNodes.has(playbackObjectId)); }, + godot_audio_get_sample_playback_position__proxy: 'sync', + godot_audio_get_sample_playback_position__sig: 'di', + /** + * Returns the position of the playback position. + * @param {number} playbackObjectIdStrPtr Playback object id pointer + * @returns {number} + */ + godot_audio_get_sample_playback_position: function (playbackObjectIdStrPtr) { + const playbackObjectId = GodotRuntime.parseString(playbackObjectIdStrPtr); + const sampleNode = GodotAudio.SampleNode.getSampleNodeOrNull(playbackObjectId); + if (sampleNode == null) { + return 0; + } + return sampleNode.getPlaybackPosition(); + }, + godot_audio_sample_update_pitch_scale__proxy: 'sync', godot_audio_sample_update_pitch_scale__sig: 'vii', /** diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 54840adcae1..f0f894d03b7 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -1379,6 +1379,12 @@ bool AudioServer::is_playback_active(Ref p_playback) { float AudioServer::get_playback_position(Ref p_playback) { ERR_FAIL_COND_V(p_playback.is_null(), 0); + // Samples. + if (p_playback->get_is_sample() && p_playback->get_sample_playback().is_valid()) { + Ref sample_playback = p_playback->get_sample_playback(); + return AudioServer::get_singleton()->get_sample_playback_position(sample_playback); + } + AudioStreamPlaybackListNode *playback_node = _find_playback_list_node(p_playback); if (!playback_node) { return 0; @@ -1847,6 +1853,11 @@ bool AudioServer::is_sample_playback_active(const Ref &p_pl return AudioDriver::get_singleton()->is_sample_playback_active(p_playback); } +double AudioServer::get_sample_playback_position(const Ref &p_playback) { + ERR_FAIL_COND_V_MSG(p_playback.is_null(), false, "Parameter p_playback is null."); + return AudioDriver::get_singleton()->get_sample_playback_position(p_playback); +} + void AudioServer::update_sample_playback_pitch_scale(const Ref &p_playback, float p_pitch_scale) { ERR_FAIL_COND_MSG(p_playback.is_null(), "Parameter p_playback is null."); return AudioDriver::get_singleton()->update_sample_playback_pitch_scale(p_playback, p_pitch_scale); diff --git a/servers/audio_server.h b/servers/audio_server.h index fd6cdb451ee..2d6fc608607 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -141,6 +141,7 @@ public: virtual void stop_sample_playback(const Ref &p_playback) {} virtual void set_sample_playback_pause(const Ref &p_playback, bool p_paused) {} virtual bool is_sample_playback_active(const Ref &p_playback) { return false; } + virtual double get_sample_playback_position(const Ref &p_playback) { return false; } virtual void update_sample_playback_pitch_scale(const Ref &p_playback, float p_pitch_scale = 0.0f) {} virtual void set_sample_playback_bus_volumes_linear(const Ref &p_playback, const HashMap> &p_bus_volumes) {} @@ -484,6 +485,7 @@ public: void stop_sample_playback(const Ref &p_playback); void set_sample_playback_pause(const Ref &p_playback, bool p_paused); bool is_sample_playback_active(const Ref &p_playback); + double get_sample_playback_position(const Ref &p_playback); void update_sample_playback_pitch_scale(const Ref &p_playback, float p_pitch_scale = 0.0f); AudioServer(); From 4a64c95732cd44b34e6a623124e99ea4d83c7562 Mon Sep 17 00:00:00 2001 From: Hilderin <81109165+Hilderin@users.noreply.github.com> Date: Fri, 26 Jul 2024 10:29:38 -0400 Subject: [PATCH 022/190] Fix autoload node cannot be accessed by plugin on start-up (cherry picked from commit 2d4e573b20284409110cf63a81587adb76288753) --- editor/editor_autoload_settings.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp index b62351256e2..32b2133f234 100644 --- a/editor/editor_autoload_settings.cpp +++ b/editor/editor_autoload_settings.cpp @@ -457,7 +457,9 @@ void EditorAutoloadSettings::init_autoloads() { for (const AutoloadInfo &info : autoload_cache) { if (info.node && info.in_editor) { - callable_mp((Node *)get_tree()->get_root(), &Node::add_child).call_deferred(info.node, false, Node::INTERNAL_MODE_DISABLED); + // It's important to add the node without deferring because code in plugins or tool scripts + // could use the autoload node when they are enabled. + get_tree()->get_root()->add_child(info.node); } } } From 1ebf488a4ec8e0a372a6097e7e90b78d47fca5b5 Mon Sep 17 00:00:00 2001 From: Michael Alexsander Date: Mon, 12 Aug 2024 18:05:58 -0300 Subject: [PATCH 023/190] Fix incorrect parsing of nested nodes when generating the POT (cherry picked from commit 84c54035789ceed1e72c91c5790d077093388ecf) --- editor/plugins/packed_scene_translation_parser_plugin.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/editor/plugins/packed_scene_translation_parser_plugin.cpp b/editor/plugins/packed_scene_translation_parser_plugin.cpp index e9ddaeb3fe6..b38965753e8 100644 --- a/editor/plugins/packed_scene_translation_parser_plugin.cpp +++ b/editor/plugins/packed_scene_translation_parser_plugin.cpp @@ -83,9 +83,8 @@ Error PackedSceneEditorTranslationParserPlugin::parse_file(const String &p_path, int idx_last = atr_owners.size() - 1; if (idx_last > 0 && !parent_path.begins_with(atr_owners[idx_last].first)) { - // Switch to the previous auto translation owner this was nested in, if that was the case. + // Exit from the current owner nesting into the previous one. atr_owners.remove_at(idx_last); - idx_last -= 1; } if (property == "auto_translate_mode") { @@ -106,7 +105,7 @@ Error PackedSceneEditorTranslationParserPlugin::parse_file(const String &p_path, // If `auto_translate_mode` wasn't found, that means it is set to its default value (`AUTO_TRANSLATE_MODE_INHERIT`). if (!auto_translate_mode_found) { int idx_last = atr_owners.size() - 1; - if (idx_last > 0 && atr_owners[idx_last].first == parent_path) { + if (idx_last > 0 && parent_path.begins_with(atr_owners[idx_last].first)) { auto_translating = atr_owners[idx_last].second; } else { atr_owners.push_back(Pair(state->get_node_path(i), true)); From b84dbab84d1913934f0e301b137cc6892666813c Mon Sep 17 00:00:00 2001 From: jsjtxietian Date: Thu, 15 Aug 2024 11:44:11 +0800 Subject: [PATCH 024/190] Fix undefined `alpha_scissor` in standard shader (cherry picked from commit 970a237c203cd9a373b1846aa029effd2e4a288d) --- drivers/gles3/shaders/scene.glsl | 2 +- .../shaders/forward_clustered/scene_forward_clustered.glsl | 2 +- .../shaders/forward_mobile/scene_forward_mobile.glsl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 6dd04af6b60..ba70de9e34d 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -1871,7 +1871,7 @@ void main() { alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0)); #if defined(ALPHA_SCISSOR_USED) - if (alpha < alpha_scissor) { + if (alpha < alpha_scissor_threshold) { discard; } #endif // !ALPHA_SCISSOR_USED diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl index 4a630b0b0a0..67ee84b01be 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl @@ -2242,7 +2242,7 @@ void fragment_shader(in SceneData scene_data) { alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0)); #if defined(ALPHA_SCISSOR_USED) - if (alpha < alpha_scissor) { + if (alpha < alpha_scissor_threshold) { discard; } #endif // ALPHA_SCISSOR_USED diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl index 530a7a37db8..24568d7e948 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl @@ -1765,7 +1765,7 @@ void main() { alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0)); #if defined(ALPHA_SCISSOR_USED) - if (alpha < alpha_scissor) { + if (alpha < alpha_scissor_threshold) { discard; } #endif // !ALPHA_SCISSOR_USED From 6073b86e7147dc0a997919dfdd43ab29ea4cca83 Mon Sep 17 00:00:00 2001 From: Jordyfel Date: Mon, 12 Aug 2024 14:57:02 +0300 Subject: [PATCH 025/190] Fix typo in MultiplayerSpawner doc (cherry picked from commit 8c626f23c1452eb72a41bcb6a6de9414940418d5) --- modules/multiplayer/doc_classes/MultiplayerSpawner.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/multiplayer/doc_classes/MultiplayerSpawner.xml b/modules/multiplayer/doc_classes/MultiplayerSpawner.xml index 3da245f806c..b6202925193 100644 --- a/modules/multiplayer/doc_classes/MultiplayerSpawner.xml +++ b/modules/multiplayer/doc_classes/MultiplayerSpawner.xml @@ -48,11 +48,11 @@ - Method called on all peers when for every custom [method spawn] requested by the authority. Will receive the [code]data[/code] parameter, and should return a [Node] that is not in the scene tree. + Method called on all peers when a custom [method spawn] is requested by the authority. Will receive the [code]data[/code] parameter, and should return a [Node] that is not in the scene tree. [b]Note:[/b] The returned node should [b]not[/b] be added to the scene with [method Node.add_child]. This is done automatically. - Maximum nodes that is allowed to be spawned by this spawner. Includes both spawnable scenes and custom spawns. + Maximum number of nodes allowed to be spawned by this spawner. Includes both spawnable scenes and custom spawns. When set to [code]0[/code] (the default), there is no limit. From ea5989e3f5fa324bf730bdd4be7cb69b829b1698 Mon Sep 17 00:00:00 2001 From: smix8 <52464204+smix8@users.noreply.github.com> Date: Tue, 13 Aug 2024 00:46:04 +0200 Subject: [PATCH 026/190] Add NavigationLink function to change navigation map Adds NavigationLink function to change navigation map. (cherry picked from commit e6ff4e56e30a93b1d25b90982ac3b344e228f4a9) --- doc/classes/NavigationLink2D.xml | 13 +++ doc/classes/NavigationLink3D.xml | 13 +++ scene/2d/navigation_link_2d.cpp | 133 +++++++++++++++++++++---------- scene/2d/navigation_link_2d.h | 13 +++ scene/3d/navigation_link_3d.cpp | 106 +++++++++++++++++------- scene/3d/navigation_link_3d.h | 9 +++ 6 files changed, 216 insertions(+), 71 deletions(-) diff --git a/doc/classes/NavigationLink2D.xml b/doc/classes/NavigationLink2D.xml index 0892c9ec440..2e1c962dd15 100644 --- a/doc/classes/NavigationLink2D.xml +++ b/doc/classes/NavigationLink2D.xml @@ -29,6 +29,12 @@ Returns whether or not the specified layer of the [member navigation_layers] bitmask is enabled, given a [param layer_number] between 1 and 32. + + + + Returns the current navigation map [RID] used by this link. + + @@ -57,6 +63,13 @@ Based on [param value], enables or disables the specified layer in the [member navigation_layers] bitmask, given a [param layer_number] between 1 and 32. + + + + + Sets the [RID] of the navigation map this link should use. By default the link will automatically join the [World2D] default navigation map so this function is only required to override the default map. + + diff --git a/doc/classes/NavigationLink3D.xml b/doc/classes/NavigationLink3D.xml index 0fcc106beb7..174228ea5b2 100644 --- a/doc/classes/NavigationLink3D.xml +++ b/doc/classes/NavigationLink3D.xml @@ -29,6 +29,12 @@ Returns whether or not the specified layer of the [member navigation_layers] bitmask is enabled, given a [param layer_number] between 1 and 32. + + + + Returns the current navigation map [RID] used by this link. + + @@ -57,6 +63,13 @@ Based on [param value], enables or disables the specified layer in the [member navigation_layers] bitmask, given a [param layer_number] between 1 and 32. + + + + + Sets the [RID] of the navigation map this link should use. By default the link will automatically join the [World3D] default navigation map so this function is only required to override the default map. + + diff --git a/scene/2d/navigation_link_2d.cpp b/scene/2d/navigation_link_2d.cpp index 04ba550888a..111f5a7b78c 100644 --- a/scene/2d/navigation_link_2d.cpp +++ b/scene/2d/navigation_link_2d.cpp @@ -41,6 +41,9 @@ void NavigationLink2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationLink2D::set_enabled); ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationLink2D::is_enabled); + ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &NavigationLink2D::set_navigation_map); + ClassDB::bind_method(D_METHOD("get_navigation_map"), &NavigationLink2D::get_navigation_map); + ClassDB::bind_method(D_METHOD("set_bidirectional", "bidirectional"), &NavigationLink2D::set_bidirectional); ClassDB::bind_method(D_METHOD("is_bidirectional"), &NavigationLink2D::is_bidirectional); @@ -106,12 +109,7 @@ bool NavigationLink2D::_get(const StringName &p_name, Variant &r_ret) const { void NavigationLink2D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - if (enabled) { - NavigationServer2D::get_singleton()->link_set_map(link, get_world_2d()->get_navigation_map()); - } - current_global_transform = get_global_transform(); - NavigationServer2D::get_singleton()->link_set_start_position(link, current_global_transform.xform(start_position)); - NavigationServer2D::get_singleton()->link_set_end_position(link, current_global_transform.xform(end_position)); + _link_enter_navigation_map(); } break; case NOTIFICATION_TRANSFORM_CHANGED: { @@ -120,36 +118,15 @@ void NavigationLink2D::_notification(int p_what) { case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { set_physics_process_internal(false); - if (is_inside_tree()) { - Transform2D new_global_transform = get_global_transform(); - if (current_global_transform != new_global_transform) { - current_global_transform = new_global_transform; - NavigationServer2D::get_singleton()->link_set_start_position(link, current_global_transform.xform(start_position)); - NavigationServer2D::get_singleton()->link_set_end_position(link, current_global_transform.xform(end_position)); - queue_redraw(); - } - } + _link_update_transform(); } break; case NOTIFICATION_EXIT_TREE: { - NavigationServer2D::get_singleton()->link_set_map(link, RID()); + _link_exit_navigation_map(); } break; case NOTIFICATION_DRAW: { #ifdef DEBUG_ENABLED - if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled())) { - Color color; - if (enabled) { - color = NavigationServer2D::get_singleton()->get_debug_navigation_link_connection_color(); - } else { - color = NavigationServer2D::get_singleton()->get_debug_navigation_link_connection_disabled_color(); - } - - real_t radius = NavigationServer2D::get_singleton()->map_get_link_connection_radius(get_world_2d()->get_navigation_map()); - - draw_line(get_start_position(), get_end_position(), color); - draw_arc(get_start_position(), radius, 0, Math_TAU, 10, color); - draw_arc(get_end_position(), radius, 0, Math_TAU, 10, color); - } + _update_debug_mesh(); #endif // DEBUG_ENABLED } break; } @@ -188,15 +165,32 @@ void NavigationLink2D::set_enabled(bool p_enabled) { enabled = p_enabled; - NavigationServer3D::get_singleton()->link_set_enabled(link, enabled); + NavigationServer2D::get_singleton()->link_set_enabled(link, enabled); #ifdef DEBUG_ENABLED - if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) { - queue_redraw(); - } + queue_redraw(); #endif // DEBUG_ENABLED } +void NavigationLink2D::set_navigation_map(RID p_navigation_map) { + if (map_override == p_navigation_map) { + return; + } + + map_override = p_navigation_map; + + NavigationServer2D::get_singleton()->link_set_map(link, map_override); +} + +RID NavigationLink2D::get_navigation_map() const { + if (map_override.is_valid()) { + return map_override; + } else if (is_inside_tree()) { + return get_world_2d()->get_navigation_map(); + } + return RID(); +} + void NavigationLink2D::set_bidirectional(bool p_bidirectional) { if (bidirectional == p_bidirectional) { return; @@ -255,9 +249,7 @@ void NavigationLink2D::set_start_position(Vector2 p_position) { update_configuration_warnings(); #ifdef DEBUG_ENABLED - if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) { - queue_redraw(); - } + queue_redraw(); #endif // DEBUG_ENABLED } @@ -277,9 +269,7 @@ void NavigationLink2D::set_end_position(Vector2 p_position) { update_configuration_warnings(); #ifdef DEBUG_ENABLED - if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) { - queue_redraw(); - } + queue_redraw(); #endif // DEBUG_ENABLED } @@ -347,6 +337,69 @@ PackedStringArray NavigationLink2D::get_configuration_warnings() const { return warnings; } +void NavigationLink2D::_link_enter_navigation_map() { + if (!is_inside_tree()) { + return; + } + + if (map_override.is_valid()) { + NavigationServer2D::get_singleton()->link_set_map(link, map_override); + } else { + NavigationServer2D::get_singleton()->link_set_map(link, get_world_2d()->get_navigation_map()); + } + + current_global_transform = get_global_transform(); + + NavigationServer2D::get_singleton()->link_set_start_position(link, current_global_transform.xform(start_position)); + NavigationServer2D::get_singleton()->link_set_end_position(link, current_global_transform.xform(end_position)); + NavigationServer2D::get_singleton()->link_set_enabled(link, enabled); + + queue_redraw(); +} + +void NavigationLink2D::_link_exit_navigation_map() { + NavigationServer2D::get_singleton()->link_set_map(link, RID()); +} + +void NavigationLink2D::_link_update_transform() { + if (!is_inside_tree()) { + return; + } + + Transform2D new_global_transform = get_global_transform(); + if (current_global_transform != new_global_transform) { + current_global_transform = new_global_transform; + NavigationServer2D::get_singleton()->link_set_start_position(link, current_global_transform.xform(start_position)); + NavigationServer2D::get_singleton()->link_set_end_position(link, current_global_transform.xform(end_position)); + queue_redraw(); + } +} + +#ifdef DEBUG_ENABLED +void NavigationLink2D::_update_debug_mesh() { + if (!is_inside_tree()) { + return; + } + + if (!Engine::get_singleton()->is_editor_hint() && !NavigationServer2D::get_singleton()->get_debug_enabled()) { + return; + } + + Color color; + if (enabled) { + color = NavigationServer2D::get_singleton()->get_debug_navigation_link_connection_color(); + } else { + color = NavigationServer2D::get_singleton()->get_debug_navigation_link_connection_disabled_color(); + } + + real_t radius = NavigationServer2D::get_singleton()->map_get_link_connection_radius(get_world_2d()->get_navigation_map()); + + draw_line(get_start_position(), get_end_position(), color); + draw_arc(get_start_position(), radius, 0, Math_TAU, 10, color); + draw_arc(get_end_position(), radius, 0, Math_TAU, 10, color); +} +#endif // DEBUG_ENABLED + NavigationLink2D::NavigationLink2D() { link = NavigationServer2D::get_singleton()->link_create(); diff --git a/scene/2d/navigation_link_2d.h b/scene/2d/navigation_link_2d.h index 2929691c045..c724096607d 100644 --- a/scene/2d/navigation_link_2d.h +++ b/scene/2d/navigation_link_2d.h @@ -38,6 +38,7 @@ class NavigationLink2D : public Node2D { bool enabled = true; RID link; + RID map_override; bool bidirectional = true; uint32_t navigation_layers = 1; Vector2 end_position; @@ -47,6 +48,10 @@ class NavigationLink2D : public Node2D { Transform2D current_global_transform; +#ifdef DEBUG_ENABLED + void _update_debug_mesh(); +#endif // DEBUG_ENABLED + protected: static void _bind_methods(); void _notification(int p_what); @@ -66,6 +71,9 @@ public: void set_enabled(bool p_enabled); bool is_enabled() const { return enabled; } + void set_navigation_map(RID p_navigation_map); + RID get_navigation_map() const; + void set_bidirectional(bool p_bidirectional); bool is_bidirectional() const { return bidirectional; } @@ -97,6 +105,11 @@ public: NavigationLink2D(); ~NavigationLink2D(); + +private: + void _link_enter_navigation_map(); + void _link_exit_navigation_map(); + void _link_update_transform(); }; #endif // NAVIGATION_LINK_2D_H diff --git a/scene/3d/navigation_link_3d.cpp b/scene/3d/navigation_link_3d.cpp index dc776ebea25..bebba9a6c04 100644 --- a/scene/3d/navigation_link_3d.cpp +++ b/scene/3d/navigation_link_3d.cpp @@ -152,6 +152,9 @@ void NavigationLink3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationLink3D::set_enabled); ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationLink3D::is_enabled); + ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &NavigationLink3D::set_navigation_map); + ClassDB::bind_method(D_METHOD("get_navigation_map"), &NavigationLink3D::get_navigation_map); + ClassDB::bind_method(D_METHOD("set_bidirectional", "bidirectional"), &NavigationLink3D::set_bidirectional); ClassDB::bind_method(D_METHOD("is_bidirectional"), &NavigationLink3D::is_bidirectional); @@ -217,16 +220,7 @@ bool NavigationLink3D::_get(const StringName &p_name, Variant &r_ret) const { void NavigationLink3D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - if (enabled) { - NavigationServer3D::get_singleton()->link_set_map(link, get_world_3d()->get_navigation_map()); - } - current_global_transform = get_global_transform(); - NavigationServer3D::get_singleton()->link_set_start_position(link, current_global_transform.xform(start_position)); - NavigationServer3D::get_singleton()->link_set_end_position(link, current_global_transform.xform(end_position)); - -#ifdef DEBUG_ENABLED - _update_debug_mesh(); -#endif // DEBUG_ENABLED + _link_enter_navigation_map(); } break; case NOTIFICATION_TRANSFORM_CHANGED: { @@ -235,30 +229,11 @@ void NavigationLink3D::_notification(int p_what) { case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { set_physics_process_internal(false); - if (is_inside_tree()) { - Transform3D new_global_transform = get_global_transform(); - if (current_global_transform != new_global_transform) { - current_global_transform = new_global_transform; - NavigationServer3D::get_singleton()->link_set_start_position(link, current_global_transform.xform(start_position)); - NavigationServer3D::get_singleton()->link_set_end_position(link, current_global_transform.xform(end_position)); -#ifdef DEBUG_ENABLED - if (debug_instance.is_valid()) { - RS::get_singleton()->instance_set_transform(debug_instance, current_global_transform); - } -#endif // DEBUG_ENABLED - } - } + _link_update_transform(); } break; case NOTIFICATION_EXIT_TREE: { - NavigationServer3D::get_singleton()->link_set_map(link, RID()); - -#ifdef DEBUG_ENABLED - if (debug_instance.is_valid()) { - RS::get_singleton()->instance_set_scenario(debug_instance, RID()); - RS::get_singleton()->instance_set_visible(debug_instance, false); - } -#endif // DEBUG_ENABLED + _link_exit_navigation_map(); } break; } } @@ -320,6 +295,25 @@ void NavigationLink3D::set_enabled(bool p_enabled) { update_gizmos(); } +void NavigationLink3D::set_navigation_map(RID p_navigation_map) { + if (map_override == p_navigation_map) { + return; + } + + map_override = p_navigation_map; + + NavigationServer3D::get_singleton()->link_set_map(link, map_override); +} + +RID NavigationLink3D::get_navigation_map() const { + if (map_override.is_valid()) { + return map_override; + } else if (is_inside_tree()) { + return get_world_3d()->get_navigation_map(); + } + return RID(); +} + void NavigationLink3D::set_bidirectional(bool p_bidirectional) { if (bidirectional == p_bidirectional) { return; @@ -467,3 +461,53 @@ PackedStringArray NavigationLink3D::get_configuration_warnings() const { return warnings; } + +void NavigationLink3D::_link_enter_navigation_map() { + if (!is_inside_tree()) { + return; + } + + if (map_override.is_valid()) { + NavigationServer3D::get_singleton()->link_set_map(link, map_override); + } else { + NavigationServer3D::get_singleton()->link_set_map(link, get_world_3d()->get_navigation_map()); + } + + current_global_transform = get_global_transform(); + NavigationServer3D::get_singleton()->link_set_start_position(link, current_global_transform.xform(start_position)); + NavigationServer3D::get_singleton()->link_set_end_position(link, current_global_transform.xform(end_position)); + NavigationServer3D::get_singleton()->link_set_enabled(link, enabled); + +#ifdef DEBUG_ENABLED + if (NavigationServer3D::get_singleton()->get_debug_navigation_enabled()) { + _update_debug_mesh(); + } +#endif // DEBUG_ENABLED +} + +void NavigationLink3D::_link_exit_navigation_map() { + NavigationServer3D::get_singleton()->link_set_map(link, RID()); +#ifdef DEBUG_ENABLED + if (debug_instance.is_valid()) { + RS::get_singleton()->instance_set_visible(debug_instance, false); + } +#endif // DEBUG_ENABLED +} + +void NavigationLink3D::_link_update_transform() { + if (!is_inside_tree()) { + return; + } + + Transform3D new_global_transform = get_global_transform(); + if (current_global_transform != new_global_transform) { + current_global_transform = new_global_transform; + NavigationServer3D::get_singleton()->link_set_start_position(link, current_global_transform.xform(start_position)); + NavigationServer3D::get_singleton()->link_set_end_position(link, current_global_transform.xform(end_position)); +#ifdef DEBUG_ENABLED + if (NavigationServer3D::get_singleton()->get_debug_navigation_enabled()) { + _update_debug_mesh(); + } +#endif // DEBUG_ENABLED + } +} diff --git a/scene/3d/navigation_link_3d.h b/scene/3d/navigation_link_3d.h index 1867082811f..e894761f400 100644 --- a/scene/3d/navigation_link_3d.h +++ b/scene/3d/navigation_link_3d.h @@ -38,6 +38,7 @@ class NavigationLink3D : public Node3D { bool enabled = true; RID link; + RID map_override; bool bidirectional = true; uint32_t navigation_layers = 1; Vector3 end_position; @@ -72,6 +73,9 @@ public: void set_enabled(bool p_enabled); bool is_enabled() const { return enabled; } + void set_navigation_map(RID p_navigation_map); + RID get_navigation_map() const; + void set_bidirectional(bool p_bidirectional); bool is_bidirectional() const { return bidirectional; } @@ -100,6 +104,11 @@ public: real_t get_travel_cost() const { return travel_cost; } PackedStringArray get_configuration_warnings() const override; + +private: + void _link_enter_navigation_map(); + void _link_exit_navigation_map(); + void _link_update_transform(); }; #endif // NAVIGATION_LINK_3D_H From c831bdbbe2307764c6f66cdc6fdb934154b43610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20J=2E=20Est=C3=A9banez?= Date: Thu, 25 Jul 2024 13:06:21 +0200 Subject: [PATCH 027/190] D3D12: Be explicit about all-resources texture barriers (cherry picked from commit 3260437afc95253d525d63b7b1f21affde172cea) --- .../d3d12/rendering_device_driver_d3d12.cpp | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/d3d12/rendering_device_driver_d3d12.cpp b/drivers/d3d12/rendering_device_driver_d3d12.cpp index a33fc977c6a..af84b847579 100644 --- a/drivers/d3d12/rendering_device_driver_d3d12.cpp +++ b/drivers/d3d12/rendering_device_driver_d3d12.cpp @@ -2143,17 +2143,28 @@ void RenderingDeviceDriverD3D12::command_pipeline_barrier(CommandBufferID p_cmd_ for (uint32_t i = 0; i < p_texture_barriers.size(); i++) { const TextureBarrier &texture_barrier_rd = p_texture_barriers[i]; const TextureInfo *texture_info = (const TextureInfo *)(texture_barrier_rd.texture.id); + if (texture_info->main_texture) { + texture_info = texture_info->main_texture; + } _rd_stages_and_access_to_d3d12(p_src_stages, texture_barrier_rd.prev_layout, texture_barrier_rd.src_access, texture_barrier_d3d12.SyncBefore, texture_barrier_d3d12.AccessBefore); _rd_stages_and_access_to_d3d12(p_dst_stages, texture_barrier_rd.next_layout, texture_barrier_rd.dst_access, texture_barrier_d3d12.SyncAfter, texture_barrier_d3d12.AccessAfter); texture_barrier_d3d12.LayoutBefore = _rd_texture_layout_to_d3d12_barrier_layout(texture_barrier_rd.prev_layout); texture_barrier_d3d12.LayoutAfter = _rd_texture_layout_to_d3d12_barrier_layout(texture_barrier_rd.next_layout); texture_barrier_d3d12.pResource = texture_info->resource; - texture_barrier_d3d12.Subresources.IndexOrFirstMipLevel = texture_barrier_rd.subresources.base_mipmap; - texture_barrier_d3d12.Subresources.NumMipLevels = texture_barrier_rd.subresources.mipmap_count; - texture_barrier_d3d12.Subresources.FirstArraySlice = texture_barrier_rd.subresources.base_layer; - texture_barrier_d3d12.Subresources.NumArraySlices = texture_barrier_rd.subresources.layer_count; - texture_barrier_d3d12.Subresources.FirstPlane = _compute_plane_slice(texture_info->format, texture_barrier_rd.subresources.aspect); - texture_barrier_d3d12.Subresources.NumPlanes = format_get_plane_count(texture_info->format); + if (texture_barrier_rd.subresources.mipmap_count == texture_info->mipmaps && texture_barrier_rd.subresources.layer_count == texture_info->layers) { + // So, all resources. Then, let's be explicit about it so D3D12 doesn't think + // we are dealing with a subset of subresources. + texture_barrier_d3d12.Subresources.IndexOrFirstMipLevel = 0xffffffff; + texture_barrier_d3d12.Subresources.NumMipLevels = 0; + // Because NumMipLevels == 0, all the other fields are ignored by D3D12. + } else { + texture_barrier_d3d12.Subresources.IndexOrFirstMipLevel = texture_barrier_rd.subresources.base_mipmap; + texture_barrier_d3d12.Subresources.NumMipLevels = texture_barrier_rd.subresources.mipmap_count; + texture_barrier_d3d12.Subresources.FirstArraySlice = texture_barrier_rd.subresources.base_layer; + texture_barrier_d3d12.Subresources.NumArraySlices = texture_barrier_rd.subresources.layer_count; + texture_barrier_d3d12.Subresources.FirstPlane = _compute_plane_slice(texture_info->format, texture_barrier_rd.subresources.aspect); + texture_barrier_d3d12.Subresources.NumPlanes = format_get_plane_count(texture_info->format); + } texture_barrier_d3d12.Flags = (texture_barrier_rd.prev_layout == RDD::TEXTURE_LAYOUT_UNDEFINED) ? D3D12_TEXTURE_BARRIER_FLAG_DISCARD : D3D12_TEXTURE_BARRIER_FLAG_NONE; texture_barriers.push_back(texture_barrier_d3d12); } From 1f92092b081575867e88d4a9edf1863bed365125 Mon Sep 17 00:00:00 2001 From: kit Date: Thu, 1 Aug 2024 12:14:56 -0400 Subject: [PATCH 028/190] Fix EditorSpinSlider when hidden (cherry picked from commit d357a7d0f99e78586f05e6f5f9a39930dff9ae72) --- editor/gui/editor_spin_slider.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/editor/gui/editor_spin_slider.cpp b/editor/gui/editor_spin_slider.cpp index 4e8d6d63bf1..9f9bdb37b36 100644 --- a/editor/gui/editor_spin_slider.cpp +++ b/editor/gui/editor_spin_slider.cpp @@ -614,13 +614,13 @@ void EditorSpinSlider::_value_focus_exited() { // -> TAB was pressed // -> modal_close was not called // -> need to close/hide manually - if (value_input_closed_frame != Engine::get_singleton()->get_frames_drawn()) { + if (!is_visible_in_tree() || value_input_closed_frame != Engine::get_singleton()->get_frames_drawn()) { + // Hidden or something else took focus. if (value_input_popup) { value_input_popup->hide(); } - //tab was pressed } else { - //enter, click, esc + // Enter or Esc was pressed. grab_focus(); } From 2eb2052cb90ca9bb4f5b4ca6c7631145652716b0 Mon Sep 17 00:00:00 2001 From: tetrapod00 <145553014+tetrapod00@users.noreply.github.com> Date: Mon, 12 Aug 2024 21:04:13 -0700 Subject: [PATCH 029/190] Change "Node3D" to "Spatial" in VisualShader resource (cherry picked from commit b9876b626d431b1061111243376a4b0e07006d26) --- scene/resources/visual_shader.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 4bedcb18200..fac3a2f663a 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -1825,7 +1825,7 @@ void VisualShader::reset_state() { void VisualShader::_get_property_list(List *p_list) const { //mode - p_list->push_back(PropertyInfo(Variant::INT, PNAME("mode"), PROPERTY_HINT_ENUM, "Node3D,CanvasItem,Particles,Sky,Fog")); + p_list->push_back(PropertyInfo(Variant::INT, PNAME("mode"), PROPERTY_HINT_ENUM, "Spatial,CanvasItem,Particles,Sky,Fog")); //render modes HashMap blend_mode_enums; @@ -3004,9 +3004,9 @@ VisualShader::VisualShader() { /////////////////////////////////////////////////////////// const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { - // Node3D + // Spatial - // Node3D, Vertex + // Spatial, Vertex { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "vertex", "VERTEX" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "vertex_id", "VERTEX_ID" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "NORMAL" }, @@ -3043,7 +3043,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom2", "CUSTOM2" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom3", "CUSTOM3" }, - // Node3D, Fragment + // Spatial, Fragment { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "vertex", "VERTEX" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "NORMAL" }, @@ -3075,7 +3075,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_UINT, "camera_visible_layers", "CAMERA_VISIBLE_LAYERS" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "node_position_view", "NODE_POSITION_VIEW" }, - // Node3D, Light + // Spatial, Light { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "NORMAL" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" }, @@ -3883,9 +3883,9 @@ VisualShaderNodeParameterRef::VisualShaderNodeParameterRef() { const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = { //////////////////////////////////////////////////////////////////////// - // Node3D. + // Spatial. //////////////////////////////////////////////////////////////////////// - // Node3D, Vertex. + // Spatial, Vertex. //////////////////////////////////////////////////////////////////////// { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Vertex", "VERTEX" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Normal", "NORMAL" }, @@ -3900,7 +3900,7 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "Model View Matrix", "MODELVIEW_MATRIX" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "Projection Matrix", "PROJECTION_MATRIX" }, //////////////////////////////////////////////////////////////////////// - // Node3D, Fragment. + // Spatial, Fragment. //////////////////////////////////////////////////////////////////////// { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Albedo", "ALBEDO" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Alpha", "ALPHA" }, @@ -3932,7 +3932,7 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Depth", "DEPTH" }, //////////////////////////////////////////////////////////////////////// - // Node3D, Light. + // Spatial, Light. //////////////////////////////////////////////////////////////////////// { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Diffuse", "DIFFUSE_LIGHT" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Specular", "SPECULAR_LIGHT" }, From 26b151a945fa05aedb196270bf9a7383e26a6178 Mon Sep 17 00:00:00 2001 From: Fredia Huya-Kouadio Date: Thu, 15 Aug 2024 12:24:58 -0700 Subject: [PATCH 030/190] Update the Android `fileLastModified` method to return values in seconds instead of milliseconds (cherry picked from commit cde873b4064360da01a9ffd92956e7d89e2c3eae) --- .../java/lib/src/org/godotengine/godot/io/file/FileData.kt | 2 +- .../lib/src/org/godotengine/godot/io/file/MediaStoreData.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/android/java/lib/src/org/godotengine/godot/io/file/FileData.kt b/platform/android/java/lib/src/org/godotengine/godot/io/file/FileData.kt index f2c0577c21e..d0b8a8dffae 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/io/file/FileData.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/io/file/FileData.kt @@ -53,7 +53,7 @@ internal class FileData(filePath: String, accessFlag: FileAccessFlags) : DataAcc fun fileLastModified(filepath: String): Long { return try { - File(filepath).lastModified() + File(filepath).lastModified() / 1000L } catch (e: SecurityException) { 0L } diff --git a/platform/android/java/lib/src/org/godotengine/godot/io/file/MediaStoreData.kt b/platform/android/java/lib/src/org/godotengine/godot/io/file/MediaStoreData.kt index 5410eed7272..146fc04da49 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/io/file/MediaStoreData.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/io/file/MediaStoreData.kt @@ -203,7 +203,7 @@ internal class MediaStoreData(context: Context, filePath: String, accessFlag: Fi } val dataItem = result[0] - return dataItem.dateModified.toLong() + return dataItem.dateModified.toLong() / 1000L } fun rename(context: Context, from: String, to: String): Boolean { From a031407e82d5caa9922387b1e6ba72c996df379f Mon Sep 17 00:00:00 2001 From: kleonc <9283098+kleonc@users.noreply.github.com> Date: Fri, 9 Aug 2024 19:26:02 +0200 Subject: [PATCH 031/190] Fix TileAtlasView bounds checks for transposed tiles (cherry picked from commit 6895f6f8ccab0b22dda5a6151399603cdd7fd060) --- editor/plugins/tiles/tile_atlas_view.cpp | 2 +- editor/plugins/tiles/tile_data_editors.cpp | 6 ++---- scene/resources/2d/tile_set.cpp | 17 ++++++++++++++++- scene/resources/2d/tile_set.h | 1 + 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp index 3942baed8ab..b806d1e0429 100644 --- a/editor/plugins/tiles/tile_atlas_view.cpp +++ b/editor/plugins/tiles/tile_atlas_view.cpp @@ -372,7 +372,7 @@ void TileAtlasView::_draw_base_tiles_shape_grid() { for (int i = 0; i < tile_set_atlas_source->get_tiles_count(); i++) { Vector2i tile_id = tile_set_atlas_source->get_tile_id(i); Vector2 in_tile_base_offset = tile_set_atlas_source->get_tile_data(tile_id, 0)->get_texture_origin(); - if (tile_set_atlas_source->is_position_in_tile_texture_region(tile_id, 0, -tile_shape_size / 2) && tile_set_atlas_source->is_position_in_tile_texture_region(tile_id, 0, tile_shape_size / 2 - Vector2(1, 1))) { + if (tile_set_atlas_source->is_rect_in_tile_texture_region(tile_id, 0, Rect2(Vector2(-tile_shape_size) / 2, tile_shape_size))) { for (int frame = 0; frame < tile_set_atlas_source->get_tile_animation_frames_count(tile_id); frame++) { Color color = grid_color; if (frame > 0) { diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp index f985bbc6290..169eadce93a 100644 --- a/editor/plugins/tiles/tile_data_editors.cpp +++ b/editor/plugins/tiles/tile_data_editors.cpp @@ -1385,10 +1385,8 @@ void TileDataTextureOriginEditor::draw_over_tile(CanvasItem *p_canvas_item, Tran TileSetSource *source = *(tile_set->get_source(p_cell.source_id)); TileSetAtlasSource *atlas_source = Object::cast_to(source); - if (atlas_source->is_position_in_tile_texture_region(p_cell.get_atlas_coords(), p_cell.alternative_tile, -tile_set_tile_size / 2) && atlas_source->is_position_in_tile_texture_region(p_cell.get_atlas_coords(), p_cell.alternative_tile, tile_set_tile_size / 2 - Vector2(1, 1))) { - Transform2D tile_xform; - tile_xform.set_scale(tile_set_tile_size); - tile_set->draw_tile_shape(p_canvas_item, p_transform * tile_xform, color); + if (atlas_source->is_rect_in_tile_texture_region(p_cell.get_atlas_coords(), p_cell.alternative_tile, Rect2(Vector2(-tile_set_tile_size) / 2, tile_set_tile_size))) { + tile_set->draw_tile_shape(p_canvas_item, p_transform.scaled_local(tile_set_tile_size), color); } if (atlas_source->is_position_in_tile_texture_region(p_cell.get_atlas_coords(), p_cell.alternative_tile, Vector2())) { diff --git a/scene/resources/2d/tile_set.cpp b/scene/resources/2d/tile_set.cpp index d124577d25b..6a799e90ce7 100644 --- a/scene/resources/2d/tile_set.cpp +++ b/scene/resources/2d/tile_set.cpp @@ -5275,11 +5275,26 @@ Rect2i TileSetAtlasSource::get_tile_texture_region(Vector2i p_atlas_coords, int bool TileSetAtlasSource::is_position_in_tile_texture_region(const Vector2i p_atlas_coords, int p_alternative_tile, Vector2 p_position) const { Size2 size = get_tile_texture_region(p_atlas_coords).size; - Rect2 rect = Rect2(-size / 2 - get_tile_data(p_atlas_coords, p_alternative_tile)->get_texture_origin(), size); + TileData *tile_data = get_tile_data(p_atlas_coords, p_alternative_tile); + if (tile_data->get_transpose()) { + size = Size2(size.y, size.x); + } + Rect2 rect = Rect2(-size / 2 - tile_data->get_texture_origin(), size); return rect.has_point(p_position); } +bool TileSetAtlasSource::is_rect_in_tile_texture_region(const Vector2i p_atlas_coords, int p_alternative_tile, Rect2 p_rect) const { + Size2 size = get_tile_texture_region(p_atlas_coords).size; + TileData *tile_data = get_tile_data(p_atlas_coords, p_alternative_tile); + if (tile_data->get_transpose()) { + size = Size2(size.y, size.x); + } + Rect2 rect = Rect2(-size / 2 - tile_data->get_texture_origin(), size); + + return p_rect.intersection(rect) == p_rect; +} + int TileSetAtlasSource::alternative_no_transform(int p_alternative_id) { return p_alternative_id & ~(TRANSFORM_FLIP_H | TRANSFORM_FLIP_V | TRANSFORM_TRANSPOSE); } diff --git a/scene/resources/2d/tile_set.h b/scene/resources/2d/tile_set.h index e083fa45b92..51df972c8d3 100644 --- a/scene/resources/2d/tile_set.h +++ b/scene/resources/2d/tile_set.h @@ -763,6 +763,7 @@ public: Vector2i get_atlas_grid_size() const; Rect2i get_tile_texture_region(Vector2i p_atlas_coords, int p_frame = 0) const; bool is_position_in_tile_texture_region(const Vector2i p_atlas_coords, int p_alternative_tile, Vector2 p_position) const; + bool is_rect_in_tile_texture_region(const Vector2i p_atlas_coords, int p_alternative_tile, Rect2 p_rect) const; static int alternative_no_transform(int p_alternative_id); From d915947f3d79858ccc363a353da79239a01d008b Mon Sep 17 00:00:00 2001 From: kleonc <9283098+kleonc@users.noreply.github.com> Date: Fri, 9 Aug 2024 19:26:09 +0200 Subject: [PATCH 032/190] Fix transposed tiles drawing in GenericTilePolygonEditor (cherry picked from commit 3dfac1644d3b1ef4e21ab9377e3498cf8dd4b89f) --- editor/plugins/tiles/tile_data_editors.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp index 169eadce93a..03177b7d291 100644 --- a/editor/plugins/tiles/tile_data_editors.cpp +++ b/editor/plugins/tiles/tile_data_editors.cpp @@ -165,10 +165,14 @@ void GenericTilePolygonEditor::_base_control_draw() { base_control->draw_set_transform_matrix(xform); // Draw fill rect under texture region. - Rect2 texture_rect(-background_region.size / 2, background_region.size); + Rect2 texture_rect(Vector2(), background_region.size); if (tile_data) { texture_rect.position -= tile_data->get_texture_origin(); + if (tile_data->get_transpose()) { + texture_rect.size = Size2(texture_rect.size.y, texture_rect.size.x); + } } + texture_rect.position -= texture_rect.size / 2; // Half-size offset must be applied after transposing. base_control->draw_rect(texture_rect, Color(1, 1, 1, 0.3)); // Draw the background. @@ -180,18 +184,14 @@ void GenericTilePolygonEditor::_base_control_draw() { if (tile_data->get_flip_v()) { region_size.y = -region_size.y; } - base_control->draw_texture_rect_region(background_atlas_source->get_texture(), Rect2(-background_region.size / 2 - tile_data->get_texture_origin(), region_size), background_region, tile_data->get_modulate(), tile_data->get_transpose()); + // Destination rect position must account for transposing, size must not. + base_control->draw_texture_rect_region(background_atlas_source->get_texture(), Rect2(texture_rect.position, region_size), background_region, tile_data->get_modulate(), tile_data->get_transpose()); } // Compute and draw the grid area. Rect2 grid_area = Rect2(-base_tile_size / 2, base_tile_size); - if (tile_data) { - grid_area.expand_to(-background_region.get_size() / 2 - tile_data->get_texture_origin()); - grid_area.expand_to(background_region.get_size() / 2 - tile_data->get_texture_origin()); - } else { - grid_area.expand_to(-background_region.get_size() / 2); - grid_area.expand_to(background_region.get_size() / 2); - } + grid_area.expand_to(texture_rect.position); + grid_area.expand_to(texture_rect.get_end()); base_control->draw_rect(grid_area, Color(1, 1, 1, 0.3), false); // Draw grid. From acba31b746052fec9a0f30fc567047a19031e79a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20=C5=A0vejda?= Date: Mon, 18 Dec 2023 17:28:50 +0100 Subject: [PATCH 033/190] Fix SoftBody3D pinned points breaking when reloading scene (cherry picked from commit bde8c5977b5b3f31619af182ffc521bbec98df78) --- scene/3d/soft_body_3d.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp index f02cd9b700e..4fe5dd2385f 100644 --- a/scene/3d/soft_body_3d.cpp +++ b/scene/3d/soft_body_3d.cpp @@ -218,7 +218,13 @@ bool SoftBody3D::_set_property_pinned_points_attachment(int p_item, const String if ("spatial_attachment_path" == p_what) { PinnedPoint *w = pinned_points.ptrw(); - callable_mp(this, &SoftBody3D::_pin_point_deferred).call_deferred(Variant(w[p_item].point_index), true, p_value); + + if (is_inside_tree()) { + callable_mp(this, &SoftBody3D::_pin_point_deferred).call_deferred(Variant(w[p_item].point_index), true, p_value); + } else { + pin_point(w[p_item].point_index, true, p_value); + _make_cache_dirty(); + } } else if ("offset" == p_what) { PinnedPoint *w = pinned_points.ptrw(); w[p_item].offset = p_value; From 686591b948069650213b3d9395ae61fd26f637b6 Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Thu, 8 Aug 2024 22:41:09 +0300 Subject: [PATCH 034/190] [ImageFont] Fix escape sequence parsing, add note to the docs. (cherry picked from commit 4cc065c2db8cdd0ac3a3bea650a51a10a52d446b) --- doc/classes/ResourceImporterImageFont.xml | 2 +- editor/import/resource_importer_imagefont.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/classes/ResourceImporterImageFont.xml b/doc/classes/ResourceImporterImageFont.xml index 6dbfa1d6514..663c9060019 100644 --- a/doc/classes/ResourceImporterImageFont.xml +++ b/doc/classes/ResourceImporterImageFont.xml @@ -40,7 +40,7 @@ Kerning pairs for the font. Kerning pair adjust the spacing between two characters. - Each string consist of three space separated values: "from" string, "to" string and integer offset. Each combination form the two string for a kerning pair, e.g, [code]ab cd -3[/code] will create kerning pairs [code]ac[/code], [code]ad[/code], [code]bc[/code], and [code]bd[/code] with offset [code]-3[/code]. + Each string consist of three space separated values: "from" string, "to" string and integer offset. Each combination form the two string for a kerning pair, e.g, [code]ab cd -3[/code] will create kerning pairs [code]ac[/code], [code]ad[/code], [code]bc[/code], and [code]bd[/code] with offset [code]-3[/code]. [code]\uXXXX[/code] escape sequences can be used to add Unicode characters. Number of rows in the font image. See also [member columns]. diff --git a/editor/import/resource_importer_imagefont.cpp b/editor/import/resource_importer_imagefont.cpp index f1b6d3a6ac7..f01381904da 100644 --- a/editor/import/resource_importer_imagefont.cpp +++ b/editor/import/resource_importer_imagefont.cpp @@ -293,18 +293,20 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin } String from_tokens; for (int i = 0; i < kp_tokens[0].length(); i++) { - if (i <= kp_tokens[0].length() - 6 && kp_tokens[0][i] == '\\' && kp_tokens[0][i + 1] == 'u') { + if (i <= kp_tokens[0].length() - 6 && kp_tokens[0][i] == '\\' && kp_tokens[0][i + 1] == 'u' && is_hex_digit(kp_tokens[0][i + 2]) && is_hex_digit(kp_tokens[0][i + 3]) && is_hex_digit(kp_tokens[0][i + 4]) && is_hex_digit(kp_tokens[0][i + 5])) { char32_t charcode = kp_tokens[0].substr(i + 2, 4).hex_to_int(); from_tokens += charcode; + i += 5; } else { from_tokens += kp_tokens[0][i]; } } String to_tokens; for (int i = 0; i < kp_tokens[1].length(); i++) { - if (i <= kp_tokens[1].length() - 6 && kp_tokens[1][i] == '\\' && kp_tokens[1][i + 1] == 'u') { + if (i <= kp_tokens[1].length() - 6 && kp_tokens[1][i] == '\\' && kp_tokens[1][i + 1] == 'u' && is_hex_digit(kp_tokens[1][i + 2]) && is_hex_digit(kp_tokens[1][i + 3]) && is_hex_digit(kp_tokens[1][i + 4]) && is_hex_digit(kp_tokens[1][i + 5])) { char32_t charcode = kp_tokens[1].substr(i + 2, 4).hex_to_int(); to_tokens += charcode; + i += 5; } else { to_tokens += kp_tokens[1][i]; } From 6aff947ee55e0bd4105f936ced2efdb61e7c8cc3 Mon Sep 17 00:00:00 2001 From: kevinkuo52 Date: Fri, 16 Aug 2024 06:38:47 -0700 Subject: [PATCH 035/190] pass in render_info to _fill_instance_data for alpha to fix overdraw call count (cherry picked from commit 3388a4a360030ef1365ba1b28b76e6d3432c5ba5) --- .../renderer_rd/forward_clustered/render_forward_clustered.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index ad19f36257e..4c55a2b3114 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -1749,7 +1749,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co int *render_info = p_render_data->render_info ? p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE] : (int *)nullptr; _fill_instance_data(RENDER_LIST_OPAQUE, render_info); _fill_instance_data(RENDER_LIST_MOTION, render_info); - _fill_instance_data(RENDER_LIST_ALPHA); + _fill_instance_data(RENDER_LIST_ALPHA, render_info); RD::get_singleton()->draw_command_end_label(); From 6eea970e8cae85c3f1a091e730540083a9cf0763 Mon Sep 17 00:00:00 2001 From: ocean Date: Fri, 16 Aug 2024 15:22:17 -0400 Subject: [PATCH 036/190] Fix Godot not quitting with `--doctool --gdscript-docs`. (cherry picked from commit 13b20820ba78bff60a8ec293c8c66159e0a949ec) --- main/main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/main/main.cpp b/main/main.cpp index 3a6b3aa273a..ca9b9d732f1 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1511,6 +1511,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph main_args.push_back(arg); main_args.push_back(N->get()); N = N->next(); + // GDScript docgen requires Autoloads, but loading those also creates a main loop. + // This forces main loop to quit without adding more GDScript-specific exceptions to setup. + quit_after = 1; } else { OS::get_singleton()->print("Missing relative or absolute path to project for --gdscript-docs, aborting.\n"); goto error; From 6e78eec37fd21b4f32b26292d252a927c86a5b2a Mon Sep 17 00:00:00 2001 From: Joel Croteau Date: Sun, 4 Aug 2024 11:00:56 -0600 Subject: [PATCH 037/190] Fix reload of GDExtension libraries in framework package on macos `GDExtension::open_library` has a check in it to see if the library was loaded from a temp file, and if it was to restore the original name as that is the one we actually care about. This check is breaking extension reloading on Mac when the library path is to a framework folder, as the file inside the framework will not generally be the same name as the folder. This check also shouldn't be necessary even on Windows, which is the only platform that uses `generate_temp_files`, since disposal of the created temp file is handled within `OS_Windows::open_dynamic_library`, and `GDExtension::open_library` (which is the only function to call `open_dynamic_library` with a `p_data` argument) only cares about the original library file path and has to do extra work to remove the name of the temp file. Instead, I have removed that check and set `OS_Windows::open_dynamic_library` to return the name of the original file and not the name of the copy. This fixes GDExtension reloading on macOS. I do not have a Windows machine available to test that it still works properly on Windows, so someone should check that before merging this. (cherry picked from commit f44d6a235f198e3f8c5189161840315f43cfdd2e) --- core/extension/gdextension.cpp | 11 +---------- drivers/unix/file_access_unix.cpp | 2 +- platform/windows/os_windows.cpp | 30 +++++++++++++++--------------- 3 files changed, 17 insertions(+), 26 deletions(-) diff --git a/core/extension/gdextension.cpp b/core/extension/gdextension.cpp index 8e2366fc95e..cb6832ea398 100644 --- a/core/extension/gdextension.cpp +++ b/core/extension/gdextension.cpp @@ -781,23 +781,14 @@ Error GDExtension::open_library(const String &p_path, const String &p_entry_symb } } - String actual_lib_path; OS::GDExtensionData data = { true, // also_set_library_path - &actual_lib_path, // r_resolved_path + &library_path, // r_resolved_path Engine::get_singleton()->is_editor_hint(), // generate_temp_files &abs_dependencies_paths, // library_dependencies }; Error err = OS::get_singleton()->open_dynamic_library(abs_path, library, &data); - if (actual_lib_path.get_file() != abs_path.get_file()) { - // If temporary files are generated, let's change the library path to point at the original, - // because that's what we want to check to see if it's changed. - library_path = actual_lib_path.get_base_dir().path_join(p_path.get_file()); - } else { - library_path = actual_lib_path; - } - ERR_FAIL_COND_V_MSG(err == ERR_FILE_NOT_FOUND, err, "GDExtension dynamic library not found: " + abs_path); ERR_FAIL_COND_V_MSG(err != OK, err, "Can't open GDExtension dynamic library: " + abs_path); diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp index 210507c2c63..ea8b42b2e4c 100644 --- a/drivers/unix/file_access_unix.cpp +++ b/drivers/unix/file_access_unix.cpp @@ -383,7 +383,7 @@ uint64_t FileAccessUnix::_get_modified_time(const String &p_file) { if (!err) { return status.st_mtime; } else { - print_verbose("Failed to get modified time for: " + p_file + ""); + WARN_PRINT("Failed to get modified time for: " + p_file); return 0; } } diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 9025f53f42b..40b265785f5 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -379,6 +379,8 @@ Error OS_Windows::open_dynamic_library(const String &p_path, void *&p_library_ha //this code exists so gdextension can load .dll files from within the executable path path = get_executable_path().get_base_dir().path_join(p_path.get_file()); } + // Path to load from may be different from original if we make copies. + String load_path = path; ERR_FAIL_COND_V(!FileAccess::exists(path), ERR_FILE_NOT_FOUND); @@ -387,25 +389,22 @@ Error OS_Windows::open_dynamic_library(const String &p_path, void *&p_library_ha if (p_data != nullptr && p_data->generate_temp_files) { // Copy the file to the same directory as the original with a prefix in the name. // This is so relative path to dependencies are satisfied. - String copy_path = path.get_base_dir().path_join("~" + path.get_file()); + load_path = path.get_base_dir().path_join("~" + path.get_file()); // If there's a left-over copy (possibly from a crash) then delete it first. - if (FileAccess::exists(copy_path)) { - DirAccess::remove_absolute(copy_path); + if (FileAccess::exists(load_path)) { + DirAccess::remove_absolute(load_path); } - Error copy_err = DirAccess::copy_absolute(path, copy_path); + Error copy_err = DirAccess::copy_absolute(path, load_path); if (copy_err) { ERR_PRINT("Error copying library: " + path); return ERR_CANT_CREATE; } - FileAccess::set_hidden_attribute(copy_path, true); + FileAccess::set_hidden_attribute(load_path, true); - // Save the copied path so it can be deleted later. - path = copy_path; - - Error pdb_err = WindowsUtils::copy_and_rename_pdb(path); + Error pdb_err = WindowsUtils::copy_and_rename_pdb(load_path); if (pdb_err != OK && pdb_err != ERR_SKIP) { WARN_PRINT(vformat("Failed to rename the PDB file. The original PDB file for '%s' will be loaded.", path)); } @@ -421,21 +420,21 @@ Error OS_Windows::open_dynamic_library(const String &p_path, void *&p_library_ha DLL_DIRECTORY_COOKIE cookie = nullptr; if (p_data != nullptr && p_data->also_set_library_path && has_dll_directory_api) { - cookie = add_dll_directory((LPCWSTR)(path.get_base_dir().utf16().get_data())); + cookie = add_dll_directory((LPCWSTR)(load_path.get_base_dir().utf16().get_data())); } - p_library_handle = (void *)LoadLibraryExW((LPCWSTR)(path.utf16().get_data()), nullptr, (p_data != nullptr && p_data->also_set_library_path && has_dll_directory_api) ? LOAD_LIBRARY_SEARCH_DEFAULT_DIRS : 0); + p_library_handle = (void *)LoadLibraryExW((LPCWSTR)(load_path.utf16().get_data()), nullptr, (p_data != nullptr && p_data->also_set_library_path && has_dll_directory_api) ? LOAD_LIBRARY_SEARCH_DEFAULT_DIRS : 0); if (!p_library_handle) { if (p_data != nullptr && p_data->generate_temp_files) { - DirAccess::remove_absolute(path); + DirAccess::remove_absolute(load_path); } #ifdef DEBUG_ENABLED DWORD err_code = GetLastError(); - HashSet checekd_libs; + HashSet checked_libs; HashSet missing_libs; - debug_dynamic_library_check_dependencies(path, path, checekd_libs, missing_libs); + debug_dynamic_library_check_dependencies(load_path, load_path, checked_libs, missing_libs); if (!missing_libs.is_empty()) { String missing; for (const String &E : missing_libs) { @@ -464,7 +463,8 @@ Error OS_Windows::open_dynamic_library(const String &p_path, void *&p_library_ha } if (p_data != nullptr && p_data->generate_temp_files) { - temp_libraries[p_library_handle] = path; + // Save the copied path so it can be deleted later. + temp_libraries[p_library_handle] = load_path; } return OK; From 63ff665fd06d849e65a0ec186d569b02d17e1374 Mon Sep 17 00:00:00 2001 From: Juan Pablo Arce Date: Sun, 21 Jul 2024 17:07:29 -0300 Subject: [PATCH 038/190] Fix GD0107 not applying to arrays and dictionaries containing nodes (cherry picked from commit 8aa444d2123c9ccdcdcb0df73edd5034eb576083) --- ...D0107_OK_ScriptPropertyDefVal.generated.cs | 18 ++++++- .../Sources/ExportDiagnostics_GD0107.cs | 49 ++++++++++++++++++ .../ScriptPropertyDefValGenerator.cs | 51 ++++++++++++------- 3 files changed, 99 insertions(+), 19 deletions(-) diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportDiagnostics_GD0107_OK_ScriptPropertyDefVal.generated.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportDiagnostics_GD0107_OK_ScriptPropertyDefVal.generated.cs index 217f4676376..9a8b3ea8463 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportDiagnostics_GD0107_OK_ScriptPropertyDefVal.generated.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportDiagnostics_GD0107_OK_ScriptPropertyDefVal.generated.cs @@ -11,11 +11,27 @@ partial class ExportDiagnostics_GD0107_OK [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] internal new static global::System.Collections.Generic.Dictionary GetGodotPropertyDefaultValues() { - var values = new global::System.Collections.Generic.Dictionary(2); + var values = new global::System.Collections.Generic.Dictionary(10); global::Godot.Node __NodeProperty_default_value = default; values.Add(PropertyName.@NodeProperty, global::Godot.Variant.From(__NodeProperty_default_value)); + global::Godot.Node[] __SystemArrayOfNodesProperty_default_value = default; + values.Add(PropertyName.@SystemArrayOfNodesProperty, global::Godot.Variant.CreateFrom(__SystemArrayOfNodesProperty_default_value)); + global::Godot.Collections.Array __GodotArrayOfNodesProperty_default_value = default; + values.Add(PropertyName.@GodotArrayOfNodesProperty, global::Godot.Variant.CreateFrom(__GodotArrayOfNodesProperty_default_value)); + global::Godot.Collections.Dictionary __GodotDictionaryWithNodeAsKeyProperty_default_value = default; + values.Add(PropertyName.@GodotDictionaryWithNodeAsKeyProperty, global::Godot.Variant.CreateFrom(__GodotDictionaryWithNodeAsKeyProperty_default_value)); + global::Godot.Collections.Dictionary __GodotDictionaryWithNodeAsValueProperty_default_value = default; + values.Add(PropertyName.@GodotDictionaryWithNodeAsValueProperty, global::Godot.Variant.CreateFrom(__GodotDictionaryWithNodeAsValueProperty_default_value)); global::Godot.Node __NodeField_default_value = default; values.Add(PropertyName.@NodeField, global::Godot.Variant.From(__NodeField_default_value)); + global::Godot.Node[] __SystemArrayOfNodesField_default_value = default; + values.Add(PropertyName.@SystemArrayOfNodesField, global::Godot.Variant.CreateFrom(__SystemArrayOfNodesField_default_value)); + global::Godot.Collections.Array __GodotArrayOfNodesField_default_value = default; + values.Add(PropertyName.@GodotArrayOfNodesField, global::Godot.Variant.CreateFrom(__GodotArrayOfNodesField_default_value)); + global::Godot.Collections.Dictionary __GodotDictionaryWithNodeAsKeyField_default_value = default; + values.Add(PropertyName.@GodotDictionaryWithNodeAsKeyField, global::Godot.Variant.CreateFrom(__GodotDictionaryWithNodeAsKeyField_default_value)); + global::Godot.Collections.Dictionary __GodotDictionaryWithNodeAsValueField_default_value = default; + values.Add(PropertyName.@GodotDictionaryWithNodeAsValueField, global::Godot.Variant.CreateFrom(__GodotDictionaryWithNodeAsValueField_default_value)); return values; } #endif // TOOLS diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportDiagnostics_GD0107.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportDiagnostics_GD0107.cs index 067783ea66d..4613d883c2c 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportDiagnostics_GD0107.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportDiagnostics_GD0107.cs @@ -1,12 +1,37 @@ using Godot; +using Godot.Collections; public partial class ExportDiagnostics_GD0107_OK : Node { [Export] public Node NodeField; + [Export] + public Node[] SystemArrayOfNodesField; + + [Export] + public Array GodotArrayOfNodesField; + + [Export] + public Dictionary GodotDictionaryWithNodeAsKeyField; + + [Export] + public Dictionary GodotDictionaryWithNodeAsValueField; + [Export] public Node NodeProperty { get; set; } + + [Export] + public Node[] SystemArrayOfNodesProperty { get; set; } + + [Export] + public Array GodotArrayOfNodesProperty { get; set; } + + [Export] + public Dictionary GodotDictionaryWithNodeAsKeyProperty { get; set; } + + [Export] + public Dictionary GodotDictionaryWithNodeAsValueProperty { get; set; } } public partial class ExportDiagnostics_GD0107_KO : Resource @@ -14,6 +39,30 @@ public partial class ExportDiagnostics_GD0107_KO : Resource [Export] public Node {|GD0107:NodeField|}; + [Export] + public Node[] {|GD0107:SystemArrayOfNodesField|}; + + [Export] + public Array {|GD0107:GodotArrayOfNodesField|}; + + [Export] + public Dictionary {|GD0107:GodotDictionaryWithNodeAsKeyField|}; + + [Export] + public Dictionary {|GD0107:GodotDictionaryWithNodeAsValueField|}; + [Export] public Node {|GD0107:NodeProperty|} { get; set; } + + [Export] + public Node[] {|GD0107:SystemArrayOfNodesProperty|} { get; set; } + + [Export] + public Array {|GD0107:GodotArrayOfNodesProperty|} { get; set; } + + [Export] + public Dictionary {|GD0107:GodotDictionaryWithNodeAsKeyProperty|} { get; set; } + + [Export] + public Dictionary {|GD0107:GodotDictionaryWithNodeAsValueProperty|} { get; set; } } diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs index efe88d84680..626f51ecae1 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs @@ -196,16 +196,13 @@ namespace Godot.SourceGenerators continue; } - if (marshalType == MarshalType.GodotObjectOrDerived) + if (!isNode && MemberHasNodeType(propertyType, marshalType.Value)) { - if (!isNode && propertyType.InheritsFrom("GodotSharp", GodotClasses.Node)) - { - context.ReportDiagnostic(Diagnostic.Create( - Common.OnlyNodesShouldExportNodesRule, - property.Locations.FirstLocationWithSourceTreeOrDefault() - )); - continue; - } + context.ReportDiagnostic(Diagnostic.Create( + Common.OnlyNodesShouldExportNodesRule, + property.Locations.FirstLocationWithSourceTreeOrDefault() + )); + continue; } var propertyDeclarationSyntax = property.DeclaringSyntaxReferences @@ -315,16 +312,13 @@ namespace Godot.SourceGenerators continue; } - if (marshalType == MarshalType.GodotObjectOrDerived) + if (!isNode && MemberHasNodeType(fieldType, marshalType.Value)) { - if (!isNode && fieldType.InheritsFrom("GodotSharp", GodotClasses.Node)) - { - context.ReportDiagnostic(Diagnostic.Create( - Common.OnlyNodesShouldExportNodesRule, - field.Locations.FirstLocationWithSourceTreeOrDefault() - )); - continue; - } + context.ReportDiagnostic(Diagnostic.Create( + Common.OnlyNodesShouldExportNodesRule, + field.Locations.FirstLocationWithSourceTreeOrDefault() + )); + continue; } EqualsValueClauseSyntax? initializer = field.DeclaringSyntaxReferences @@ -424,6 +418,27 @@ namespace Godot.SourceGenerators context.AddSource(uniqueHint, SourceText.From(source.ToString(), Encoding.UTF8)); } + private static bool MemberHasNodeType(ITypeSymbol memberType, MarshalType marshalType) + { + if (marshalType == MarshalType.GodotObjectOrDerived) + { + return memberType.InheritsFrom("GodotSharp", GodotClasses.Node); + } + if (marshalType == MarshalType.GodotObjectOrDerivedArray) + { + var elementType = ((IArrayTypeSymbol)memberType).ElementType; + return elementType.InheritsFrom("GodotSharp", GodotClasses.Node); + } + if (memberType is INamedTypeSymbol { IsGenericType: true } genericType) + { + return genericType.TypeArguments + .Any(static typeArgument + => typeArgument.InheritsFrom("GodotSharp", GodotClasses.Node)); + } + + return false; + } + private struct ExportedPropertyMetadata { public ExportedPropertyMetadata(string name, MarshalType type, ITypeSymbol typeSymbol, string? value) From bba8f85945db3b38af0cb18c7609e1d7431ca87b Mon Sep 17 00:00:00 2001 From: jsjtxietian Date: Mon, 5 Aug 2024 14:13:48 +0800 Subject: [PATCH 039/190] Fix Pressing Escape doesn't exit freelook in the 3D editor (cherry picked from commit 78dc310103d2f241fd38fed7895c0a2f0cc7508a) --- editor/plugins/node_3d_editor_plugin.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 97d6010b541..11ee5a2455e 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -2252,6 +2252,11 @@ void Node3DEditorViewport::_sinput(const Ref &p_event) { } if (_edit.mode == TRANSFORM_NONE) { + if (_edit.gizmo.is_null() && is_freelook_active() && k->get_keycode() == Key::ESCAPE) { + set_freelook_active(false); + return; + } + if (_edit.gizmo.is_valid() && (k->get_keycode() == Key::ESCAPE || k->get_keycode() == Key::BACKSPACE)) { // Restore. _edit.gizmo->commit_handle(_edit.gizmo_handle, _edit.gizmo_handle_secondary, _edit.gizmo_initial_value, true); From 7726ced085535f7154fa0ca69baea88985735c9b Mon Sep 17 00:00:00 2001 From: Rio Arswendo Rachmad Date: Thu, 8 Aug 2024 16:20:08 +0700 Subject: [PATCH 040/190] fix: project settings not properly saved after a file removal (cherry picked from commit 138bcc7cfdbddcc05a4f2373fb2cb20fb23e0f2b) --- editor/dependency_editor.cpp | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp index c83e677b37f..8eaeedd92fc 100644 --- a/editor/dependency_editor.cpp +++ b/editor/dependency_editor.cpp @@ -578,32 +578,34 @@ void DependencyRemoveDialog::ok_pressed() { } } + bool project_settings_modified = false; for (int i = 0; i < files_to_delete.size(); ++i) { // If the file we are deleting for e.g. the main scene, default environment, // or audio bus layout, we must clear its definition in Project Settings. if (files_to_delete[i] == String(GLOBAL_GET("application/config/icon"))) { ProjectSettings::get_singleton()->set("application/config/icon", ""); - } - if (files_to_delete[i] == String(GLOBAL_GET("application/run/main_scene"))) { + project_settings_modified = true; + } else if (files_to_delete[i] == String(GLOBAL_GET("application/run/main_scene"))) { ProjectSettings::get_singleton()->set("application/run/main_scene", ""); - } - if (files_to_delete[i] == String(GLOBAL_GET("application/boot_splash/image"))) { + project_settings_modified = true; + } else if (files_to_delete[i] == String(GLOBAL_GET("application/boot_splash/image"))) { ProjectSettings::get_singleton()->set("application/boot_splash/image", ""); - } - if (files_to_delete[i] == String(GLOBAL_GET("rendering/environment/defaults/default_environment"))) { + project_settings_modified = true; + } else if (files_to_delete[i] == String(GLOBAL_GET("rendering/environment/defaults/default_environment"))) { ProjectSettings::get_singleton()->set("rendering/environment/defaults/default_environment", ""); - } - if (files_to_delete[i] == String(GLOBAL_GET("display/mouse_cursor/custom_image"))) { + project_settings_modified = true; + } else if (files_to_delete[i] == String(GLOBAL_GET("display/mouse_cursor/custom_image"))) { ProjectSettings::get_singleton()->set("display/mouse_cursor/custom_image", ""); - } - if (files_to_delete[i] == String(GLOBAL_GET("gui/theme/custom"))) { + project_settings_modified = true; + } else if (files_to_delete[i] == String(GLOBAL_GET("gui/theme/custom"))) { ProjectSettings::get_singleton()->set("gui/theme/custom", ""); - } - if (files_to_delete[i] == String(GLOBAL_GET("gui/theme/custom_font"))) { + project_settings_modified = true; + } else if (files_to_delete[i] == String(GLOBAL_GET("gui/theme/custom_font"))) { ProjectSettings::get_singleton()->set("gui/theme/custom_font", ""); - } - if (files_to_delete[i] == String(GLOBAL_GET("audio/buses/default_bus_layout"))) { + project_settings_modified = true; + } else if (files_to_delete[i] == String(GLOBAL_GET("audio/buses/default_bus_layout"))) { ProjectSettings::get_singleton()->set("audio/buses/default_bus_layout", ""); + project_settings_modified = true; } String path = OS::get_singleton()->get_resource_dir() + files_to_delete[i].replace_first("res://", "/"); @@ -615,6 +617,9 @@ void DependencyRemoveDialog::ok_pressed() { emit_signal(SNAME("file_removed"), files_to_delete[i]); } } + if (project_settings_modified) { + ProjectSettings::get_singleton()->save(); + } if (dirs_to_delete.size() == 0) { // If we only deleted files we should only need to tell the file system about the files we touched. From 2d7266e7649de49e3c60fd4389c5dec1364a929d Mon Sep 17 00:00:00 2001 From: clayjohn Date: Fri, 16 Aug 2024 14:11:08 -0700 Subject: [PATCH 041/190] Ensure fog_sky_affect is used even when using a background color (cherry picked from commit 37be585fdf689e7e29376bc6faab3fbed59cfd02) --- .../forward_clustered/render_forward_clustered.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 4c55a2b3114..cb655f9b04c 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -1827,7 +1827,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co clear_color.r *= bg_energy_multiplier; clear_color.g *= bg_energy_multiplier; clear_color.b *= bg_energy_multiplier; - if (!p_render_data->transparent_bg && rb->has_custom_data(RB_SCOPE_FOG) && environment_get_fog_enabled(p_render_data->environment)) { + if (!p_render_data->transparent_bg && (rb->has_custom_data(RB_SCOPE_FOG) || environment_get_fog_enabled(p_render_data->environment))) { draw_sky_fog_only = true; RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear())); } @@ -1837,7 +1837,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co clear_color.r *= bg_energy_multiplier; clear_color.g *= bg_energy_multiplier; clear_color.b *= bg_energy_multiplier; - if (!p_render_data->transparent_bg && rb->has_custom_data(RB_SCOPE_FOG) && environment_get_fog_enabled(p_render_data->environment)) { + if (!p_render_data->transparent_bg && (rb->has_custom_data(RB_SCOPE_FOG) || environment_get_fog_enabled(p_render_data->environment))) { draw_sky_fog_only = true; RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear())); } From 6b323241b1b648f5c2f723f16880cfa680ce583b Mon Sep 17 00:00:00 2001 From: Nodragem Date: Fri, 9 Aug 2024 10:39:25 +0100 Subject: [PATCH 042/190] prevent the click to get processed further after a paste action (cherry picked from commit e7e633760ae508a5914929da6a5f83a4ba403942) --- modules/gridmap/editor/grid_map_editor_plugin.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/gridmap/editor/grid_map_editor_plugin.cpp b/modules/gridmap/editor/grid_map_editor_plugin.cpp index f402e2a5832..ea63e071042 100644 --- a/modules/gridmap/editor/grid_map_editor_plugin.cpp +++ b/modules/gridmap/editor/grid_map_editor_plugin.cpp @@ -643,6 +643,7 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D _do_paste(); input_action = INPUT_NONE; _update_paste_indicator(); + return EditorPlugin::AFTER_GUI_INPUT_STOP; } else if (mb->is_shift_pressed() && can_edit) { input_action = INPUT_SELECT; last_selection = selection; From 8ea64814edfb408689337542eb5e61b160593f7a Mon Sep 17 00:00:00 2001 From: Kusok <118438257+kus04e4ek@users.noreply.github.com> Date: Sun, 11 Aug 2024 20:27:15 +0800 Subject: [PATCH 043/190] Add `stop_callable` to `AudioStreamPlayerInternal` (cherry picked from commit 8c7dd3cb61b7d134b49c584fb17acd30a4d42fbe) --- scene/2d/audio_stream_player_2d.cpp | 4 ++-- scene/3d/audio_stream_player_3d.cpp | 4 ++-- scene/audio/audio_stream_player.cpp | 4 ++-- scene/audio/audio_stream_player_internal.cpp | 13 +++++++------ scene/audio/audio_stream_player_internal.h | 5 +++-- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index 8e91dce425d..89a0479de3a 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -242,7 +242,7 @@ void AudioStreamPlayer2D::seek(float p_seconds) { void AudioStreamPlayer2D::stop() { setplay.set(-1); - internal->stop(); + internal->stop_basic(); } bool AudioStreamPlayer2D::is_playing() const { @@ -430,7 +430,7 @@ void AudioStreamPlayer2D::_bind_methods() { } AudioStreamPlayer2D::AudioStreamPlayer2D() { - internal = memnew(AudioStreamPlayerInternal(this, callable_mp(this, &AudioStreamPlayer2D::play), true)); + internal = memnew(AudioStreamPlayerInternal(this, callable_mp(this, &AudioStreamPlayer2D::play), callable_mp(this, &AudioStreamPlayer2D::stop), true)); cached_global_panning_strength = GLOBAL_GET("audio/general/2d_panning_strength"); set_hide_clip_children(true); } diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index 6888462876e..4d3f494ccf3 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -562,7 +562,7 @@ void AudioStreamPlayer3D::seek(float p_seconds) { void AudioStreamPlayer3D::stop() { setplay.set(-1); - internal->stop(); + internal->stop_basic(); } bool AudioStreamPlayer3D::is_playing() const { @@ -862,7 +862,7 @@ void AudioStreamPlayer3D::_bind_methods() { } AudioStreamPlayer3D::AudioStreamPlayer3D() { - internal = memnew(AudioStreamPlayerInternal(this, callable_mp(this, &AudioStreamPlayer3D::play), true)); + internal = memnew(AudioStreamPlayerInternal(this, callable_mp(this, &AudioStreamPlayer3D::play), callable_mp(this, &AudioStreamPlayer3D::stop), true)); velocity_tracker.instantiate(); set_disable_scale(true); cached_global_panning_strength = GLOBAL_GET("audio/general/3d_panning_strength"); diff --git a/scene/audio/audio_stream_player.cpp b/scene/audio/audio_stream_player.cpp index e90c1aa2451..183c4af9507 100644 --- a/scene/audio/audio_stream_player.cpp +++ b/scene/audio/audio_stream_player.cpp @@ -112,7 +112,7 @@ void AudioStreamPlayer::seek(float p_seconds) { } void AudioStreamPlayer::stop() { - internal->stop(); + internal->stop_basic(); } bool AudioStreamPlayer::is_playing() const { @@ -283,7 +283,7 @@ void AudioStreamPlayer::_bind_methods() { } AudioStreamPlayer::AudioStreamPlayer() { - internal = memnew(AudioStreamPlayerInternal(this, callable_mp(this, &AudioStreamPlayer::play), false)); + internal = memnew(AudioStreamPlayerInternal(this, callable_mp(this, &AudioStreamPlayer::play), callable_mp(this, &AudioStreamPlayer::stop), false)); } AudioStreamPlayer::~AudioStreamPlayer() { diff --git a/scene/audio/audio_stream_player_internal.cpp b/scene/audio/audio_stream_player_internal.cpp index 36c14e03d54..206408e3a77 100644 --- a/scene/audio/audio_stream_player_internal.cpp +++ b/scene/audio/audio_stream_player_internal.cpp @@ -132,7 +132,7 @@ Ref AudioStreamPlayerInternal::play_basic() { } ERR_FAIL_COND_V_MSG(!node->is_inside_tree(), stream_playback, "Playback can only happen when a node is inside the scene tree"); if (stream->is_monophonic() && is_playing()) { - stop(); + stop_callable.call(); } stream_playback = stream->instantiate_playback(); ERR_FAIL_COND_V_MSG(stream_playback.is_null(), stream_playback, "Failed to instantiate playback."); @@ -242,7 +242,7 @@ void AudioStreamPlayerInternal::set_stream(Ref p_stream) { if (stream.is_valid()) { stream->disconnect(SNAME("parameter_list_changed"), callable_mp(this, &AudioStreamPlayerInternal::_update_stream_parameters)); } - stop(); + stop_callable.call(); stream = p_stream; _update_stream_parameters(); if (stream.is_valid()) { @@ -253,12 +253,12 @@ void AudioStreamPlayerInternal::set_stream(Ref p_stream) { void AudioStreamPlayerInternal::seek(float p_seconds) { if (is_playing()) { - stop(); + stop_callable.call(); play_callable.call(p_seconds); } } -void AudioStreamPlayerInternal::stop() { +void AudioStreamPlayerInternal::stop_basic() { for (Ref &playback : stream_playbacks) { AudioServer::get_singleton()->stop_playback_stream(playback); } @@ -289,7 +289,7 @@ void AudioStreamPlayerInternal::set_playing(bool p_enable) { if (p_enable) { play_callable.call(0.0); } else { - stop(); + stop_callable.call(); } } @@ -339,9 +339,10 @@ StringName AudioStreamPlayerInternal::get_bus() const { return SceneStringName(Master); } -AudioStreamPlayerInternal::AudioStreamPlayerInternal(Node *p_node, const Callable &p_play_callable, bool p_physical) { +AudioStreamPlayerInternal::AudioStreamPlayerInternal(Node *p_node, const Callable &p_play_callable, const Callable &p_stop_callable, bool p_physical) { node = p_node; play_callable = p_play_callable; + stop_callable = p_stop_callable; physical = p_physical; bus = SceneStringName(Master); diff --git a/scene/audio/audio_stream_player_internal.h b/scene/audio/audio_stream_player_internal.h index ec4489067e0..7d8faeba060 100644 --- a/scene/audio/audio_stream_player_internal.h +++ b/scene/audio/audio_stream_player_internal.h @@ -53,6 +53,7 @@ private: Node *node = nullptr; Callable play_callable; + Callable stop_callable; bool physical = false; AudioServer::PlaybackType playback_type = AudioServer::PlaybackType::PLAYBACK_TYPE_DEFAULT; @@ -94,7 +95,7 @@ public: Ref play_basic(); void seek(float p_seconds); - void stop(); + void stop_basic(); bool is_playing() const; float get_playback_position(); @@ -110,7 +111,7 @@ public: void set_playback_type(AudioServer::PlaybackType p_playback_type); AudioServer::PlaybackType get_playback_type() const; - AudioStreamPlayerInternal(Node *p_node, const Callable &p_play_callable, bool p_physical); + AudioStreamPlayerInternal(Node *p_node, const Callable &p_play_callable, const Callable &p_stop_callable, bool p_physical); }; #endif // AUDIO_STREAM_PLAYER_INTERNAL_H From 3876287162d9ae07e482226ed981ec9169313995 Mon Sep 17 00:00:00 2001 From: Cory Petkovsek <632766+TokisanGames@users.noreply.github.com> Date: Mon, 12 Aug 2024 14:03:54 +0700 Subject: [PATCH 044/190] Ensure selected node is a descendant of the edited scene (cherry picked from commit b1a45d948778f76af9349ed3c3983372607e78f1) --- editor/plugins/node_3d_editor_plugin.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 11ee5a2455e..f8a832f3030 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -1064,21 +1064,23 @@ void Node3DEditorViewport::_select_region() { if (found_nodes.has(sp)) { continue; } - found_nodes.insert(sp); Node *node = Object::cast_to(sp); - if (node != edited_scene) { - node = edited_scene->get_deepest_editable_node(node); - } - // Prevent selection of nodes not owned by the edited scene. - while (node && node != edited_scene->get_parent()) { - Node *node_owner = node->get_owner(); - if (node_owner == edited_scene || node == edited_scene || (node_owner != nullptr && edited_scene->is_editable_instance(node_owner))) { - break; + // Selection requires that the node is the edited scene or its descendant, and has an owner. + if (node != edited_scene) { + if (!node->get_owner() || !edited_scene->is_ancestor_of(node)) { + continue; + } + node = edited_scene->get_deepest_editable_node(node); + while (node != edited_scene) { + Node *node_owner = node->get_owner(); + if (node_owner == edited_scene || (node_owner != nullptr && edited_scene->is_editable_instance(node_owner))) { + break; + } + node = node->get_parent(); } - node = node->get_parent(); } // Replace the node by the group if grouped From 6d41487459f1545c8db9bb8927c25fcf28914225 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Fri, 16 Aug 2024 22:51:09 +0200 Subject: [PATCH 045/190] OpenXR: Fix support for building against distro package (cherry picked from commit 2206f5c6a49f3870817f30d8305efe1d61e23317) --- modules/openxr/openxr_interface.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp index cce9c093612..73ac529537a 100644 --- a/modules/openxr/openxr_interface.cpp +++ b/modules/openxr/openxr_interface.cpp @@ -36,7 +36,8 @@ #include "extensions/openxr_eye_gaze_interaction.h" #include "extensions/openxr_hand_interaction_extension.h" -#include "thirdparty/openxr/include/openxr/openxr.h" + +#include void OpenXRInterface::_bind_methods() { // lifecycle signals From 6c202154a7c93c4381f8116962fcd0a81d3c7e58 Mon Sep 17 00:00:00 2001 From: clayjohn Date: Fri, 16 Aug 2024 15:28:19 -0700 Subject: [PATCH 046/190] Add fixed fog to the sky in the Compatibility renderer And apply luminance multiplier after fog in RD renderer (cherry picked from commit 578049b7b9b9ba5d0ad02f89698a593c368ab7fc) --- drivers/gles3/rasterizer_scene_gles3.cpp | 12 +++++- drivers/gles3/shaders/sky.glsl | 37 ++++++++++++++++++- .../renderer_rd/shaders/environment/sky.glsl | 8 ++-- 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 84b6ab4bd8b..2565e610f79 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -777,7 +777,6 @@ void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection, ERR_FAIL_COND(p_env.is_null()); Sky *sky = sky_owner.get_or_null(environment_get_sky(p_env)); - ERR_FAIL_NULL(sky); GLES3::SkyMaterialData *material_data = nullptr; RID sky_material; @@ -851,6 +850,15 @@ void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection, material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::SKY_ENERGY_MULTIPLIER, p_sky_energy_multiplier, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::LUMINANCE_MULTIPLIER, p_luminance_multiplier, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + Color fog_color = environment_get_fog_light_color(p_env).srgb_to_linear() * environment_get_fog_light_energy(p_env); + material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::FOG_ENABLED, environment_get_fog_enabled(p_env), shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::FOG_AERIAL_PERSPECTIVE, environment_get_fog_aerial_perspective(p_env), shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::FOG_LIGHT_COLOR, fog_color, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::FOG_SUN_SCATTER, environment_get_fog_sun_scatter(p_env), shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::FOG_DENSITY, environment_get_fog_density(p_env), shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::FOG_SKY_AFFECT, environment_get_fog_sky_affect(p_env), shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::DIRECTIONAL_LIGHT_COUNT, sky_globals.directional_light_count, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + if (p_use_multiview) { glBindBufferBase(GL_UNIFORM_BUFFER, SKY_MULTIVIEW_UNIFORM_LOCATION, scene_state.multiview_buffer); glBindBuffer(GL_UNIFORM_BUFFER, 0); @@ -2587,7 +2595,7 @@ void RasterizerSceneGLES3::render_scene(const Ref &p_render_ scene_state.enable_gl_depth_draw(false); - if (draw_sky) { + if (draw_sky || draw_sky_fog_only) { RENDER_TIMESTAMP("Render Sky"); scene_state.enable_gl_depth_test(true); diff --git a/drivers/gles3/shaders/sky.glsl b/drivers/gles3/shaders/sky.glsl index 9de65ba960d..f734e4b3554 100644 --- a/drivers/gles3/shaders/sky.glsl +++ b/drivers/gles3/shaders/sky.glsl @@ -108,11 +108,11 @@ uniform float sky_energy_multiplier; uniform float luminance_multiplier; uniform float fog_aerial_perspective; -uniform vec3 fog_light_color; +uniform vec4 fog_light_color; uniform float fog_sun_scatter; uniform bool fog_enabled; uniform float fog_density; -uniform float z_far; +uniform float fog_sky_affect; uniform uint directional_light_count; #ifdef USE_MULTIVIEW @@ -135,6 +135,24 @@ vec3 interleaved_gradient_noise(vec2 pos) { } #endif +#if !defined(DISABLE_FOG) +vec4 fog_process(vec3 view, vec3 sky_color) { + vec3 fog_color = mix(fog_light_color.rgb, sky_color, fog_aerial_perspective); + + if (fog_sun_scatter > 0.001) { + vec4 sun_scatter = vec4(0.0); + float sun_total = 0.0; + for (uint i = 0u; i < directional_light_count; i++) { + vec3 light_color = directional_lights.data[i].color_size.xyz * directional_lights.data[i].direction_energy.w; + float light_amount = pow(max(dot(view, directional_lights.data[i].direction_energy.xyz), 0.0), 8.0); + fog_color += light_color * light_amount * fog_sun_scatter; + } + } + + return vec4(fog_color, 1.0); +} +#endif // !DISABLE_FOG + void main() { vec3 cube_normal; #ifdef USE_MULTIVIEW @@ -203,6 +221,21 @@ void main() { // Convert to Linear for tonemapping so color matches scene shader better color = srgb_to_linear(color); + +#if !defined(DISABLE_FOG) && !defined(USE_CUBEMAP_PASS) + + // Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky. + if (fog_enabled) { + vec4 fog = fog_process(cube_normal, color.rgb); + color.rgb = mix(color.rgb, fog.rgb, fog.a * fog_sky_affect); + } + + if (custom_fog.a > 0.0) { + color.rgb = mix(color.rgb, custom_fog.rgb, custom_fog.a); + } + +#endif // DISABLE_FOG + color *= exposure; #ifdef APPLY_TONEMAPPING color = apply_tonemapping(color, white); diff --git a/servers/rendering/renderer_rd/shaders/environment/sky.glsl b/servers/rendering/renderer_rd/shaders/environment/sky.glsl index 35457a24821..5aa37354948 100644 --- a/servers/rendering/renderer_rd/shaders/environment/sky.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sky.glsl @@ -255,10 +255,6 @@ void main() { frag_color.rgb = color; frag_color.a = alpha; - // For mobile renderer we're multiplying by 0.5 as we're using a UNORM buffer. - // For both mobile and clustered, we also bake in the exposure value for the environment and camera. - frag_color.rgb = frag_color.rgb * params.luminance_multiplier; - #if !defined(DISABLE_FOG) && !defined(USE_CUBEMAP_PASS) // Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky. @@ -278,6 +274,10 @@ void main() { #endif // DISABLE_FOG + // For mobile renderer we're multiplying by 0.5 as we're using a UNORM buffer. + // For both mobile and clustered, we also bake in the exposure value for the environment and camera. + frag_color.rgb = frag_color.rgb * params.luminance_multiplier; + // Blending is disabled for Sky, so alpha doesn't blend. // Alpha is used for subsurface scattering so make sure it doesn't get applied to Sky. if (!AT_CUBEMAP_PASS && !AT_HALF_RES_PASS && !AT_QUARTER_RES_PASS) { From b7fc0630381a766a5065f49b8b14079f581cdc4e Mon Sep 17 00:00:00 2001 From: Hilderin <81109165+Hilderin@users.noreply.github.com> Date: Sat, 17 Aug 2024 07:19:08 -0400 Subject: [PATCH 047/190] Fix uid:// Paths Fail to Load at Editor Startup (cherry picked from commit b1c97313e0c5b0f8b159c578b16a65dfc7c19baa) --- editor/editor_file_system.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index 02a95fd8364..f75e438582c 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -386,6 +386,8 @@ void EditorFileSystem::_scan_filesystem() { // On the first scan, the first_scan_root_dir is created in _first_scan_filesystem. if (first_scan) { sd = first_scan_root_dir; + // Will be updated on scan. + ResourceUID::get_singleton()->clear(); } else { Ref d = DirAccess::create(DirAccess::ACCESS_RESOURCES); sd = memnew(ScannedDirectory); @@ -3061,7 +3063,6 @@ EditorFileSystem::EditorFileSystem() { using_fat32_or_exfat = (da->get_filesystem_type() == "FAT32" || da->get_filesystem_type() == "exFAT"); scan_total = 0; - callable_mp(ResourceUID::get_singleton(), &ResourceUID::clear).call_deferred(); // Will be updated on scan. ResourceSaver::set_get_resource_id_for_path(_resource_saver_get_resource_id_for_path); } From 7266418bdfa0a0b458b8fd3366efb6a271fdfade Mon Sep 17 00:00:00 2001 From: Radiant <69520693+RadiantUwU@users.noreply.github.com> Date: Fri, 2 Aug 2024 16:26:19 +0300 Subject: [PATCH 048/190] Fix node.duplicate, return nullptr if this operation fails. (cherry picked from commit 70f41e414eefd21ecbe98d429c5fc82b4c30ce8a) --- scene/main/node.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 0396f3ab4af..15dee69fa5c 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2783,9 +2783,11 @@ Node *Node::duplicate(int p_flags) const { ERR_THREAD_GUARD_V(nullptr); Node *dupe = _duplicate(p_flags); + ERR_FAIL_NULL_V_MSG(dupe, nullptr, "Failed to duplicate node."); + _duplicate_properties(this, this, dupe, p_flags); - if (dupe && (p_flags & DUPLICATE_SIGNALS)) { + if (p_flags & DUPLICATE_SIGNALS) { _duplicate_signals(this, dupe); } @@ -2801,6 +2803,8 @@ Node *Node::duplicate_from_editor(HashMap &r_duplimap, con int flags = DUPLICATE_SIGNALS | DUPLICATE_GROUPS | DUPLICATE_SCRIPTS | DUPLICATE_USE_INSTANTIATION | DUPLICATE_FROM_EDITOR; Node *dupe = _duplicate(flags, &r_duplimap); + ERR_FAIL_NULL_V_MSG(dupe, nullptr, "Failed to duplicate node."); + _duplicate_properties(this, this, dupe, flags); // This is used by SceneTreeDock's paste functionality. When pasting to foreign scene, resources are duplicated. From d8c13f88ed500b962a95c837929cec6571a8d62c Mon Sep 17 00:00:00 2001 From: Hilderin <81109165+Hilderin@users.noreply.github.com> Date: Fri, 26 Jul 2024 00:35:16 -0400 Subject: [PATCH 049/190] Fix scene node selection problem when no auto expand (cherry picked from commit e46280dbb56dd7d8bdb2b25bbefe363b2a8e455b) --- editor/gui/scene_tree_editor.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/editor/gui/scene_tree_editor.cpp b/editor/gui/scene_tree_editor.cpp index c6cc0e97dde..87d8ddad092 100644 --- a/editor/gui/scene_tree_editor.cpp +++ b/editor/gui/scene_tree_editor.cpp @@ -1000,6 +1000,7 @@ void SceneTreeEditor::set_selected(Node *p_node, bool p_emit_selected) { TreeItem *item = p_node ? _find(tree->get_root(), p_node->get_path()) : nullptr; if (item) { + selected = p_node; if (auto_expand_selected) { // Make visible when it's collapsed. TreeItem *node = item->get_parent(); @@ -1009,8 +1010,24 @@ void SceneTreeEditor::set_selected(Node *p_node, bool p_emit_selected) { } item->select(0); item->set_as_cursor(0); - selected = p_node; tree->ensure_cursor_is_visible(); + } else { + // Ensure the node is selected and visible for the user if the node + // is not collapsed. + bool collapsed = false; + TreeItem *node = item; + while (node && node != tree->get_root()) { + if (node->is_collapsed()) { + collapsed = true; + break; + } + node = node->get_parent(); + } + if (!collapsed) { + item->select(0); + item->set_as_cursor(0); + tree->ensure_cursor_is_visible(); + } } } else { if (!p_node) { From 41682201696b29817abc935ca88edfbf9b60ccab Mon Sep 17 00:00:00 2001 From: Artemy Fedotov Date: Wed, 24 Jul 2024 20:01:11 +0400 Subject: [PATCH 050/190] Fix `EditorInterface.get_selected_paths()` working incorrectly when FileSystemDock is in split mode (cherry picked from commit b55e97cd852d3bc8b0dd101f932beb306ac63ae1) --- editor/filesystem_dock.cpp | 19 ++++++++++++++++++- editor/filesystem_dock.h | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index d4bd97a3938..59351a8efc1 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -685,7 +685,15 @@ void FileSystemDock::_tree_multi_selected(Object *p_item, int p_column, bool p_s } Vector FileSystemDock::get_selected_paths() const { - return _tree_get_selected(false); + if (display_mode == DISPLAY_MODE_TREE_ONLY) { + return _tree_get_selected(false); + } else { + Vector selected = _file_list_get_selected(); + if (selected.is_empty()) { + selected.push_back(get_current_directory()); + } + return selected; + } } String FileSystemDock::get_current_path() const { @@ -2049,6 +2057,15 @@ Vector FileSystemDock::_tree_get_selected(bool remove_self_inclusion, bo return selected_strings; } +Vector FileSystemDock::_file_list_get_selected() const { + Vector selected; + + for (int idx : files->get_selected_items()) { + selected.push_back(files->get_item_metadata(idx)); + } + return selected; +} + Vector FileSystemDock::_remove_self_included_paths(Vector selected_strings) { // Remove paths or files that are included into another. if (selected_strings.size() > 1) { diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index 959ace8eba9..2f54cb91db0 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -359,6 +359,7 @@ private: void _update_display_mode(bool p_force = false); Vector _tree_get_selected(bool remove_self_inclusion = true, bool p_include_unselected_cursor = false) const; + Vector _file_list_get_selected() const; bool _is_file_type_disabled_by_feature_profile(const StringName &p_class); From f0f69a7b7c44aff618f453b29f7ab69074790f28 Mon Sep 17 00:00:00 2001 From: kleonc <9283098+kleonc@users.noreply.github.com> Date: Sun, 18 Aug 2024 19:36:08 +0200 Subject: [PATCH 051/190] Fix Parallax2D repeats being not relative to its transform (cherry picked from commit 1bd8372813d8a329188c05e8cc8c0c66f60b1735) --- doc/classes/RenderingServer.xml | 3 +- drivers/gles3/rasterizer_canvas_gles3.cpp | 31 ++++++----- drivers/gles3/rasterizer_canvas_gles3.h | 2 +- scene/2d/parallax_layer.cpp | 8 +-- servers/rendering/renderer_canvas_cull.cpp | 54 ++++++++++++++----- servers/rendering/renderer_canvas_cull.h | 3 +- servers/rendering/renderer_canvas_render.h | 1 + .../renderer_rd/renderer_canvas_render_rd.cpp | 31 ++++++----- .../renderer_rd/renderer_canvas_render_rd.h | 2 +- 9 files changed, 78 insertions(+), 57 deletions(-) diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 3c9f0fc7aff..c64d5bf0bd9 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -944,7 +944,8 @@ - A copy of the canvas item will be drawn with a local offset of the mirroring [Vector2]. + A copy of the canvas item will be drawn with a local offset of the [param mirroring]. + [b]Note:[/b] This is equivalent to calling [method canvas_set_item_repeat] like [code]canvas_set_item_repeat(item, mirroring, 1)[/code], with an additional check ensuring [param canvas] is a parent of [param item]. diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 941b1a1b280..7a6df3d2a43 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -647,18 +647,17 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou _record_item_commands(ci, p_to_render_target, p_canvas_transform_inverse, current_clip, blend_mode, p_lights, index, batch_broken, r_sdf_used, Point2()); } else { Point2 start_pos = ci->repeat_size * -(ci->repeat_times / 2); - Point2 end_pos = ci->repeat_size * ci->repeat_times + ci->repeat_size + start_pos; - Point2 pos = start_pos; + Point2 offset; - do { - do { - _record_item_commands(ci, p_to_render_target, p_canvas_transform_inverse, current_clip, blend_mode, p_lights, index, batch_broken, r_sdf_used, pos); - pos.y += ci->repeat_size.y; - } while (pos.y < end_pos.y); - - pos.x += ci->repeat_size.x; - pos.y = start_pos.y; - } while (pos.x < end_pos.x); + int repeat_times_x = ci->repeat_size.x ? ci->repeat_times : 0; + int repeat_times_y = ci->repeat_size.y ? ci->repeat_times : 0; + for (int ry = 0; ry <= repeat_times_y; ry++) { + offset.y = start_pos.y + ry * ci->repeat_size.y; + for (int rx = 0; rx <= repeat_times_x; rx++) { + offset.x = start_pos.x + rx * ci->repeat_size.x; + _record_item_commands(ci, p_to_render_target, p_canvas_transform_inverse, current_clip, blend_mode, p_lights, index, batch_broken, r_sdf_used, offset); + } + } } } @@ -809,7 +808,7 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou state.last_item_index += index; } -void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_render_target, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_batch_broken, bool &r_sdf_used, const Point2 &p_offset) { +void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_render_target, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_batch_broken, bool &r_sdf_used, const Point2 &p_repeat_offset) { RenderingServer::CanvasItemTextureFilter texture_filter = p_item->texture_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? state.default_filter : p_item->texture_filter; if (texture_filter != state.canvas_instance_batches[state.current_batch_index].filter) { @@ -826,11 +825,11 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend state.canvas_instance_batches[state.current_batch_index].repeat = texture_repeat; } - Transform2D base_transform = p_canvas_transform_inverse * p_item->final_transform; - - if (p_offset.x || p_offset.y) { - base_transform *= Transform2D(0, p_offset / p_item->xform_curr.get_scale()); // TODO: Interpolate or explain why not needed. + Transform2D base_transform = p_item->final_transform; + if (p_item->repeat_source_item && (p_repeat_offset.x || p_repeat_offset.y)) { + base_transform.columns[2] += p_item->repeat_source_item->final_transform.basis_xform(p_repeat_offset); } + base_transform = p_canvas_transform_inverse * base_transform; Transform2D draw_transform; // Used by transform command diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index 46ed479a3d6..027f717eb7d 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -362,7 +362,7 @@ public: void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used, RenderingMethod::RenderInfo *r_render_info = nullptr) override; void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer = false, RenderingMethod::RenderInfo *r_render_info = nullptr); - void _record_item_commands(const Item *p_item, RID p_render_target, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_break_batch, bool &r_sdf_used, const Point2 &p_offset); + void _record_item_commands(const Item *p_item, RID p_render_target, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_break_batch, bool &r_sdf_used, const Point2 &p_repeat_offset); void _render_batch(Light *p_lights, uint32_t p_index, RenderingMethod::RenderInfo *r_render_info = nullptr); bool _bind_material(GLES3::CanvasMaterialData *p_material_data, CanvasShaderGLES3::ShaderVariant p_variant, uint64_t p_specialization); void _new_batch(bool &r_batch_broken); diff --git a/scene/2d/parallax_layer.cpp b/scene/2d/parallax_layer.cpp index dfe321a4350..023e9201fc5 100644 --- a/scene/2d/parallax_layer.cpp +++ b/scene/2d/parallax_layer.cpp @@ -78,13 +78,7 @@ void ParallaxLayer::_update_mirroring() { } void ParallaxLayer::set_mirroring(const Size2 &p_mirroring) { - mirroring = p_mirroring; - if (mirroring.x < 0) { - mirroring.x = 0; - } - if (mirroring.y < 0) { - mirroring.y = 0; - } + mirroring = p_mirroring.maxf(0); _update_mirroring(); } diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index c4286dcc0c6..0ec161d8cfe 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -51,7 +51,7 @@ void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas memset(z_last_list, 0, z_range * sizeof(RendererCanvasRender::Item *)); for (int i = 0; i < p_child_item_count; i++) { - _cull_canvas_item(p_child_items[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true, p_canvas_cull_mask, p_child_items[i].mirror, 1); + _cull_canvas_item(p_child_items[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true, p_canvas_cull_mask, Point2(), 1, nullptr); } RendererCanvasRender::Item *list = nullptr; @@ -97,6 +97,7 @@ void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, const Tran if (!child_items[i]->repeat_source) { child_items[i]->repeat_size = p_canvas_item->repeat_size; child_items[i]->repeat_times = p_canvas_item->repeat_times; + child_items[i]->repeat_source_item = p_canvas_item->repeat_source_item; } // Y sorted canvas items are flattened into r_items. Calculate their absolute z index to use when rendering r_items. @@ -229,10 +230,13 @@ void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item * ci->visibility_notifier->visible_in_frame = RSG::rasterizer->get_frame_number(); } + } else if (ci->repeat_source) { + // If repeat source does not draw itself it still needs transform updated as its child items' repeat offsets are relative to it. + ci->final_transform = p_transform; } } -void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2D &p_parent_xform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool p_allow_y_sort, uint32_t p_canvas_cull_mask, const Point2 &p_repeat_size, int p_repeat_times) { +void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2D &p_parent_xform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool p_allow_y_sort, uint32_t p_canvas_cull_mask, const Point2 &p_repeat_size, int p_repeat_times, RendererCanvasRender::Item *p_repeat_source_item) { Item *ci = p_canvas_item; if (!ci->visible) { @@ -268,19 +272,16 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 Point2 repeat_size = p_repeat_size; int repeat_times = p_repeat_times; + RendererCanvasRender::Item *repeat_source_item = p_repeat_source_item; if (ci->repeat_source) { repeat_size = ci->repeat_size; repeat_times = ci->repeat_times; + repeat_source_item = ci; } else { ci->repeat_size = repeat_size; ci->repeat_times = repeat_times; - } - - if (repeat_size.x || repeat_size.y) { - Size2 scale = final_xform.get_scale(); - rect.size += repeat_size * repeat_times / scale; - rect.position -= repeat_size / scale * (repeat_times / 2); + ci->repeat_source_item = repeat_source_item; } if (snapping_2d_transforms_to_pixel) { @@ -291,6 +292,25 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 final_xform = parent_xform * final_xform; Rect2 global_rect = final_xform.xform(rect); + if (repeat_source_item && (repeat_size.x || repeat_size.y)) { + // Top-left repeated rect. + Rect2 corner_rect = global_rect; + corner_rect.position -= repeat_source_item->final_transform.basis_xform((repeat_times / 2) * repeat_size); + global_rect = corner_rect; + + // Plus top-right repeated rect. + Size2 size_x_offset = repeat_source_item->final_transform.basis_xform(repeat_times * Size2(repeat_size.x, 0)); + corner_rect.position += size_x_offset; + global_rect = global_rect.merge(corner_rect); + + // Plus bottom-right repeated rect. + corner_rect.position += repeat_source_item->final_transform.basis_xform(repeat_times * Size2(0, repeat_size.y)); + global_rect = global_rect.merge(corner_rect); + + // Plus bottom-left repeated rect. + corner_rect.position -= size_x_offset; + global_rect = global_rect.merge(corner_rect); + } global_rect.position += p_clip_rect.position; if (ci->use_parent_material && p_material_owner) { @@ -357,7 +377,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 sorter.sort(child_items, child_item_count); for (i = 0; i < child_item_count; i++) { - _cull_canvas_item(child_items[i], final_xform * child_items[i]->ysort_xform, p_clip_rect, modulate * child_items[i]->ysort_modulate, child_items[i]->ysort_parent_abs_z_index, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner, false, p_canvas_cull_mask, child_items[i]->repeat_size, child_items[i]->repeat_times); + _cull_canvas_item(child_items[i], final_xform * child_items[i]->ysort_xform, p_clip_rect, modulate * child_items[i]->ysort_modulate, child_items[i]->ysort_parent_abs_z_index, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner, false, p_canvas_cull_mask, child_items[i]->repeat_size, child_items[i]->repeat_times, child_items[i]->repeat_source_item); } } else { RendererCanvasRender::Item *canvas_group_from = nullptr; @@ -381,14 +401,14 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 if (!child_items[i]->behind && !use_canvas_group) { continue; } - _cull_canvas_item(child_items[i], final_xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true, p_canvas_cull_mask, repeat_size, repeat_times); + _cull_canvas_item(child_items[i], final_xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true, p_canvas_cull_mask, repeat_size, repeat_times, repeat_source_item); } _attach_canvas_item_for_draw(ci, p_canvas_clip, r_z_list, r_z_last_list, final_xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from); for (int i = 0; i < child_item_count; i++) { if (child_items[i]->behind || use_canvas_group) { continue; } - _cull_canvas_item(child_items[i], final_xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true, p_canvas_cull_mask, repeat_size, repeat_times); + _cull_canvas_item(child_items[i], final_xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true, p_canvas_cull_mask, repeat_size, repeat_times, repeat_source_item); } } } @@ -431,14 +451,22 @@ void RendererCanvasCull::canvas_set_item_mirroring(RID p_canvas, RID p_item, con int idx = canvas->find_item(canvas_item); ERR_FAIL_COND(idx == -1); - canvas->child_items.write[idx].mirror = p_mirroring; + + bool is_repeat_source = (p_mirroring.x || p_mirroring.y); + canvas_item->repeat_source = is_repeat_source; + canvas_item->repeat_source_item = is_repeat_source ? canvas_item : nullptr; + canvas_item->repeat_size = p_mirroring; + canvas_item->repeat_times = 1; } void RendererCanvasCull::canvas_set_item_repeat(RID p_item, const Point2 &p_repeat_size, int p_repeat_times) { + ERR_FAIL_COND(p_repeat_times < 0); Item *canvas_item = canvas_item_owner.get_or_null(p_item); ERR_FAIL_NULL(canvas_item); - canvas_item->repeat_source = true; + bool is_repeat_source = (p_repeat_size.x || p_repeat_size.y) && p_repeat_times; + canvas_item->repeat_source = is_repeat_source; + canvas_item->repeat_source_item = is_repeat_source ? canvas_item : nullptr; canvas_item->repeat_size = p_repeat_size; canvas_item->repeat_times = p_repeat_times; } diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h index 9f8cbea2e95..91c03054f71 100644 --- a/servers/rendering/renderer_canvas_cull.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -126,7 +126,6 @@ public: struct Canvas : public RendererViewport::CanvasBase { HashSet viewports; struct ChildItem { - Point2 mirror; Item *item = nullptr; bool operator<(const ChildItem &p_item) const { return item->index < p_item.item->index; @@ -188,7 +187,7 @@ public: private: void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t p_canvas_cull_mask, RenderingMethod::RenderInfo *r_render_info = nullptr); - void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_parent_xform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool p_allow_y_sort, uint32_t p_canvas_cull_mask, const Point2 &p_repeat_size, int p_repeat_times); + void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_parent_xform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool p_allow_y_sort, uint32_t p_canvas_cull_mask, const Point2 &p_repeat_size, int p_repeat_times, RendererCanvasRender::Item *p_repeat_source_item); static constexpr int z_range = RS::CANVAS_ITEM_Z_MAX - RS::CANVAS_ITEM_Z_MIN + 1; diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h index cb8180f9895..c57abee1659 100644 --- a/servers/rendering/renderer_canvas_render.h +++ b/servers/rendering/renderer_canvas_render.h @@ -364,6 +364,7 @@ public: bool repeat_source; Point2 repeat_size; int repeat_times = 1; + Item *repeat_source_item = nullptr; Rect2 global_rect_cache; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 5c68fb82b1f..5e4721dfb51 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -407,7 +407,7 @@ _FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primit return (p_indices - subtractor[p_primitive]) / divisor[p_primitive]; } -void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, PipelineVariants *p_pipeline_variants, bool &r_sdf_used, const Point2 &p_offset, RenderingMethod::RenderInfo *r_render_info) { +void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, PipelineVariants *p_pipeline_variants, bool &r_sdf_used, const Point2 &p_repeat_offset, RenderingMethod::RenderInfo *r_render_info) { //create an empty push constant RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); @@ -425,11 +425,11 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend } PushConstant push_constant; - Transform2D base_transform = p_canvas_transform_inverse * p_item->final_transform; - - if (p_offset.x || p_offset.y) { - base_transform *= Transform2D(0, p_offset / p_item->xform_curr.get_scale()); // TODO: Interpolate or explain why not needed. + Transform2D base_transform = p_item->final_transform; + if (p_item->repeat_source_item && (p_repeat_offset.x || p_repeat_offset.y)) { + base_transform.columns[2] += p_item->repeat_source_item->final_transform.basis_xform(p_repeat_offset); } + base_transform = p_canvas_transform_inverse * base_transform; Transform2D draw_transform; _update_transform_2d_to_mat2x3(base_transform, push_constant.world); @@ -1250,18 +1250,17 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co _render_item(draw_list, p_to_render_target, ci, fb_format, canvas_transform_inverse, current_clip, p_lights, pipeline_variants, r_sdf_used, Point2(), r_render_info); } else { Point2 start_pos = ci->repeat_size * -(ci->repeat_times / 2); - Point2 end_pos = ci->repeat_size * ci->repeat_times + ci->repeat_size + start_pos; - Point2 pos = start_pos; + Point2 offset; - do { - do { - _render_item(draw_list, p_to_render_target, ci, fb_format, canvas_transform_inverse, current_clip, p_lights, pipeline_variants, r_sdf_used, pos, r_render_info); - pos.y += ci->repeat_size.y; - } while (pos.y < end_pos.y); - - pos.x += ci->repeat_size.x; - pos.y = start_pos.y; - } while (pos.x < end_pos.x); + int repeat_times_x = ci->repeat_size.x ? ci->repeat_times : 0; + int repeat_times_y = ci->repeat_size.y ? ci->repeat_times : 0; + for (int ry = 0; ry <= repeat_times_y; ry++) { + offset.y = start_pos.y + ry * ci->repeat_size.y; + for (int rx = 0; rx <= repeat_times_x; rx++) { + offset.x = start_pos.x + rx * ci->repeat_size.x; + _render_item(draw_list, p_to_render_target, ci, fb_format, canvas_transform_inverse, current_clip, p_lights, pipeline_variants, r_sdf_used, offset, r_render_info); + } + } } prev_material = material; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index a78ced271a0..9deb4814c71 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -423,7 +423,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { double debug_redraw_time = 1.0; inline void _bind_canvas_texture(RD::DrawListID p_draw_list, RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID &r_last_texture, PushConstant &push_constant, Size2 &r_texpixel_size, bool p_texture_is_data = false); //recursive, so regular inline used instead. - void _render_item(RenderingDevice::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, PipelineVariants *p_pipeline_variants, bool &r_sdf_used, const Point2 &p_offset, RenderingMethod::RenderInfo *r_render_info = nullptr); + void _render_item(RenderingDevice::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, PipelineVariants *p_pipeline_variants, bool &r_sdf_used, const Point2 &p_repeat_offset, RenderingMethod::RenderInfo *r_render_info = nullptr); void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer = false, RenderingMethod::RenderInfo *r_render_info = nullptr); _FORCE_INLINE_ void _update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4); From c7dbcbd6d4974acfc1213d48ceede818bbe1131d Mon Sep 17 00:00:00 2001 From: kleonc <9283098+kleonc@users.noreply.github.com> Date: Sun, 4 Aug 2024 12:28:53 +0200 Subject: [PATCH 052/190] Fix Skeleton2D.{_set|_get} always returning true (cherry picked from commit 115cd47fd637c915d0db57389f433461639bbd3f) --- scene/2d/skeleton_2d.cpp | 36 ++++++++++++++---------------------- scene/3d/skeleton_3d.cpp | 12 ++++++------ 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp index 8aa50668ebb..1bcac938035 100644 --- a/scene/2d/skeleton_2d.cpp +++ b/scene/2d/skeleton_2d.cpp @@ -39,19 +39,17 @@ #endif //TOOLS_ENABLED bool Bone2D::_set(const StringName &p_path, const Variant &p_value) { - String path = p_path; - - if (path.begins_with("auto_calculate_length_and_angle")) { + if (p_path == SNAME("auto_calculate_length_and_angle")) { set_autocalculate_length_and_angle(p_value); - } else if (path.begins_with("length")) { + } else if (p_path == SNAME("length")) { set_length(p_value); - } else if (path.begins_with("bone_angle")) { + } else if (p_path == SNAME("bone_angle")) { set_bone_angle(Math::deg_to_rad(real_t(p_value))); - } else if (path.begins_with("default_length")) { + } else if (p_path == SNAME("default_length")) { set_length(p_value); } #ifdef TOOLS_ENABLED - else if (path.begins_with("editor_settings/show_bone_gizmo")) { + else if (p_path == SNAME("editor_settings/show_bone_gizmo")) { _editor_set_show_bone_gizmo(p_value); } #endif // TOOLS_ENABLED @@ -63,19 +61,17 @@ bool Bone2D::_set(const StringName &p_path, const Variant &p_value) { } bool Bone2D::_get(const StringName &p_path, Variant &r_ret) const { - String path = p_path; - - if (path.begins_with("auto_calculate_length_and_angle")) { + if (p_path == SNAME("auto_calculate_length_and_angle")) { r_ret = get_autocalculate_length_and_angle(); - } else if (path.begins_with("length")) { + } else if (p_path == SNAME("length")) { r_ret = get_length(); - } else if (path.begins_with("bone_angle")) { + } else if (p_path == SNAME("bone_angle")) { r_ret = Math::rad_to_deg(get_bone_angle()); - } else if (path.begins_with("default_length")) { + } else if (p_path == SNAME("default_length")) { r_ret = get_length(); } #ifdef TOOLS_ENABLED - else if (path.begins_with("editor_settings/show_bone_gizmo")) { + else if (p_path == SNAME("editor_settings/show_bone_gizmo")) { r_ret = _editor_get_show_bone_gizmo(); } #endif // TOOLS_ENABLED @@ -518,23 +514,19 @@ Bone2D::~Bone2D() { ////////////////////////////////////// bool Skeleton2D::_set(const StringName &p_path, const Variant &p_value) { - String path = p_path; - - if (path.begins_with("modification_stack")) { + if (p_path == SNAME("modification_stack")) { set_modification_stack(p_value); return true; } - return true; + return false; } bool Skeleton2D::_get(const StringName &p_path, Variant &r_ret) const { - String path = p_path; - - if (path.begins_with("modification_stack")) { + if (p_path == SNAME("modification_stack")) { r_ret = get_modification_stack(); return true; } - return true; + return false; } void Skeleton2D::_get_property_list(List *p_list) const { diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index 5a4e176e99d..c6ece84cdde 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -69,13 +69,13 @@ SkinReference::~SkinReference() { /////////////////////////////////////// bool Skeleton3D::_set(const StringName &p_path, const Variant &p_value) { - String path = p_path; - #ifndef DISABLE_DEPRECATED - if (path.begins_with("animate_physical_bones")) { + if (p_path == SNAME("animate_physical_bones")) { set_animate_physical_bones(p_value); + return true; } #endif + String path = p_path; if (!path.begins_with("bones/")) { return false; @@ -139,13 +139,13 @@ bool Skeleton3D::_set(const StringName &p_path, const Variant &p_value) { } bool Skeleton3D::_get(const StringName &p_path, Variant &r_ret) const { - String path = p_path; - #ifndef DISABLE_DEPRECATED - if (path.begins_with("animate_physical_bones")) { + if (p_path == SNAME("animate_physical_bones")) { r_ret = get_animate_physical_bones(); + return true; } #endif + String path = p_path; if (!path.begins_with("bones/")) { return false; From eaa8ecb182a774d50e536caabb7bb9d92ce17673 Mon Sep 17 00:00:00 2001 From: "Silc Lizard (Tokage) Renew" <61938263+TokageItLab@users.noreply.github.com> Date: Thu, 9 May 2024 03:26:42 +0900 Subject: [PATCH 053/190] Fix bone2d scaling Co-authored-by: Thiago Lages de Alencar (cherry picked from commit de558123bf557ba563e3dcd537585af08471817f) --- scene/2d/skeleton_2d.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp index 1bcac938035..f9e8c831d16 100644 --- a/scene/2d/skeleton_2d.cpp +++ b/scene/2d/skeleton_2d.cpp @@ -326,9 +326,7 @@ bool Bone2D::_editor_get_bone_shape(Vector *p_shape, Vector *p rel = (p_other_bone->get_global_position() - get_global_position()); rel = rel.rotated(-get_global_rotation()); // Undo Bone2D node's rotation so its drawn correctly regardless of the node's rotation } else { - real_t angle_to_use = get_rotation() + bone_angle; - rel = Vector2(cos(angle_to_use), sin(angle_to_use)) * (length * MIN(get_global_scale().x, get_global_scale().y)); - rel = rel.rotated(-get_rotation()); // Undo Bone2D node's rotation so its drawn correctly regardless of the node's rotation + rel = Vector2(Math::cos(bone_angle), Math::sin(bone_angle)) * length * get_global_scale(); } Vector2 relt = rel.rotated(Math_PI * 0.5).normalized() * bone_width; From 39fb87131092cc92de848e0844f59c54e6673a0d Mon Sep 17 00:00:00 2001 From: Hilderin <81109165+Hilderin@users.noreply.github.com> Date: Mon, 29 Jul 2024 20:20:41 -0400 Subject: [PATCH 054/190] Fix no validation on Blender path on importation (cherry picked from commit 2dc9cf50c5d5be344498deb7b5472c3c7212a339) --- modules/gltf/editor/editor_scene_importer_blend.cpp | 11 +++++++++-- modules/gltf/editor/editor_scene_importer_blend.h | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp index ec3ea9bcae4..0b8fb584df2 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.cpp +++ b/modules/gltf/editor/editor_scene_importer_blend.cpp @@ -115,8 +115,15 @@ Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_ List *r_missing_deps, Error *r_err) { String blender_path = EDITOR_GET("filesystem/import/blender/blender_path"); - if (blender_major_version == -1 || blender_minor_version == -1) { - _get_blender_version(blender_path, blender_major_version, blender_minor_version, nullptr); + ERR_FAIL_COND_V_MSG(blender_path.is_empty(), nullptr, "Blender path is empty, check your Editor Settings."); + ERR_FAIL_COND_V_MSG(!FileAccess::exists(blender_path), nullptr, vformat("Invalid Blender path: %s, check your Editor Settings.", blender_path)); + + if (blender_major_version == -1 || blender_minor_version == -1 || last_tested_blender_path != blender_path) { + String error; + if (!_get_blender_version(blender_path, blender_major_version, blender_minor_version, &error)) { + ERR_FAIL_V_MSG(nullptr, error); + } + last_tested_blender_path = blender_path; } // Get global paths for source and sink. diff --git a/modules/gltf/editor/editor_scene_importer_blend.h b/modules/gltf/editor/editor_scene_importer_blend.h index 8a6c65a6248..6adace92763 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.h +++ b/modules/gltf/editor/editor_scene_importer_blend.h @@ -45,6 +45,7 @@ class EditorSceneFormatImporterBlend : public EditorSceneFormatImporter { int blender_major_version = -1; int blender_minor_version = -1; + String last_tested_blender_path; public: enum { From 9af6e04a157d855a63b41649523478478cc5796e Mon Sep 17 00:00:00 2001 From: MrPersonDev Date: Fri, 15 Mar 2024 20:09:23 -0700 Subject: [PATCH 055/190] Fix backspace always unfolding previous line (cherry picked from commit 2860b99077fff229927067948bb731cb61464317) --- scene/gui/code_edit.cpp | 2 +- tests/scene/test_code_edit.h | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index 00b9a3478a9..412eb835152 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -765,7 +765,7 @@ void CodeEdit::_backspace_internal(int p_caret) { continue; } - if (to_line > 0 && _is_line_hidden(to_line - 1)) { + if (to_line > 0 && to_column == 0 && _is_line_hidden(to_line - 1)) { unfold_line(to_line - 1); } diff --git a/tests/scene/test_code_edit.h b/tests/scene/test_code_edit.h index a166002cddb..9ec1b812dfc 100644 --- a/tests/scene/test_code_edit.h +++ b/tests/scene/test_code_edit.h @@ -4609,6 +4609,26 @@ TEST_CASE("[SceneTree][CodeEdit] text manipulation") { CHECK(code_edit->get_text() == "line 1\nline 2\nline 3"); CHECK(code_edit->get_caret_line() == 0); CHECK(code_edit->get_caret_column() == 0); + + // Unfold previous folded line on backspace if the caret is at the first column. + code_edit->set_line_folding_enabled(true); + code_edit->set_text("line 1\n\tline 2\nline 3"); + code_edit->set_caret_line(2); + code_edit->set_caret_column(0); + code_edit->fold_line(0); + code_edit->backspace(); + CHECK_FALSE(code_edit->is_line_folded(0)); + code_edit->set_line_folding_enabled(false); + + // Do not unfold previous line on backspace if the caret is not at the first column. + code_edit->set_line_folding_enabled(true); + code_edit->set_text("line 1\n\tline 2\nline 3"); + code_edit->set_caret_line(2); + code_edit->set_caret_column(4); + code_edit->fold_line(0); + code_edit->backspace(); + CHECK(code_edit->is_line_folded(0)); + code_edit->set_line_folding_enabled(false); } SUBCASE("[TextEdit] cut") { From cff0ebd60356935a096d81ccccc4adc5cf22552f Mon Sep 17 00:00:00 2001 From: Robert Yevdokimov Date: Fri, 12 Jan 2024 19:49:20 -0500 Subject: [PATCH 056/190] Clear drag preview material on `NOTIFICATION_DRAG_END` (cherry picked from commit 6aee6c1fdd69da141410c0d9101f35c4d40bc512) --- editor/plugins/node_3d_editor_plugin.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index f8a832f3030..8dbcdc8ce05 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -3114,6 +3114,7 @@ void Node3DEditorViewport::_notification(int p_what) { case NOTIFICATION_DRAG_END: { // Clear preview material when dropped outside applicable object. if (spatial_editor->get_preview_material().is_valid() && !is_drag_successful()) { + _reset_preview_material(); _remove_preview_material(); } else { _remove_preview_node(); From bf5907b724f132d611bc4b0260a5271a1a2f73a5 Mon Sep 17 00:00:00 2001 From: Gergely Kis Date: Tue, 23 Jul 2024 01:53:02 +0200 Subject: [PATCH 057/190] StringName: Use inline static field definitions Before this change StringName used regular static field definitions for its mutex, _table, configured and debug_stringname fields. Since in the general case the ordering of the static variable and field initialization and destruction is undefined, it was possible that the destruction of StringName's static fields happened prior to the destruction of statically allocated StringName instances. By changing the static field definitions to inline in string_name.h, the C++17 standard guarantees the correct initialization and destruction ordering. (cherry picked from commit 723878bbabfa7f47049e29b1c46c92358517d8d1) --- core/string/string_name.cpp | 9 --------- core/string/string_name.h | 8 ++++---- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/core/string/string_name.cpp b/core/string/string_name.cpp index 658297d805f..5d59d65f92f 100644 --- a/core/string/string_name.cpp +++ b/core/string/string_name.cpp @@ -39,19 +39,10 @@ StaticCString StaticCString::create(const char *p_ptr) { return scs; } -StringName::_Data *StringName::_table[STRING_TABLE_LEN]; - StringName _scs_create(const char *p_chr, bool p_static) { return (p_chr[0] ? StringName(StaticCString::create(p_chr), p_static) : StringName()); } -bool StringName::configured = false; -Mutex StringName::mutex; - -#ifdef DEBUG_ENABLED -bool StringName::debug_stringname = false; -#endif - void StringName::setup() { ERR_FAIL_COND(configured); for (int i = 0; i < STRING_TABLE_LEN; i++) { diff --git a/core/string/string_name.h b/core/string/string_name.h index 89b4c07e0e8..0eb98cf64b5 100644 --- a/core/string/string_name.h +++ b/core/string/string_name.h @@ -67,7 +67,7 @@ class StringName { _Data() {} }; - static _Data *_table[STRING_TABLE_LEN]; + static inline _Data *_table[STRING_TABLE_LEN]; _Data *_data = nullptr; @@ -75,10 +75,10 @@ class StringName { friend void register_core_types(); friend void unregister_core_types(); friend class Main; - static Mutex mutex; + static inline Mutex mutex; static void setup(); static void cleanup(); - static bool configured; + static inline bool configured = false; #ifdef DEBUG_ENABLED struct DebugSortReferences { bool operator()(const _Data *p_left, const _Data *p_right) const { @@ -86,7 +86,7 @@ class StringName { } }; - static bool debug_stringname; + static inline bool debug_stringname = false; #endif StringName(_Data *p_data) { _data = p_data; } From 32f2b851abcbf71848a8e42b11a6a50292527862 Mon Sep 17 00:00:00 2001 From: jordi Date: Mon, 18 Dec 2023 09:08:57 -0600 Subject: [PATCH 058/190] Redraw SubViewportContainer on SubViewport size change (cherry picked from commit 61e2aa79142dfa619d1238172e5c505c7dacc8d0) --- scene/main/viewport.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 5f9b0b90618..77bcd7fb2cc 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -5063,6 +5063,7 @@ void SubViewport::_internal_set_size(const Size2i &p_size, bool p_force) { if (c) { c->update_minimum_size(); + c->queue_redraw(); } } From 5676d398e0d8f542deee5d9096cc7bc1f15bc162 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20J=2E=20Est=C3=A9banez?= Date: Thu, 25 Jul 2024 11:55:53 +0200 Subject: [PATCH 059/190] Avoid potential crash on signal disconnection (cherry picked from commit 32b7f835d8fd7466c58ed84a20c46ba9c802e36b) --- core/object/object.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/object/object.cpp b/core/object/object.cpp index e4d1a8fc9ab..bf24c3a7924 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -2097,7 +2097,11 @@ Object::~Object() { // Disconnect signals that connect to this object. while (connections.size()) { Connection c = connections.front()->get(); - bool disconnected = c.signal.get_object()->_disconnect(c.signal.get_name(), c.callable, true); + Object *obj = c.callable.get_object(); + bool disconnected = false; + if (likely(obj)) { + disconnected = c.signal.get_object()->_disconnect(c.signal.get_name(), c.callable, true); + } if (unlikely(!disconnected)) { // If the disconnect has failed, abandon the connection to avoid getting trapped in an infinite loop here. connections.pop_front(); From c684d65c64800f21ddaf89527aaf1a483ea25fc1 Mon Sep 17 00:00:00 2001 From: clayjohn Date: Mon, 12 Aug 2024 12:04:16 -0700 Subject: [PATCH 060/190] Use transformed roughness instead of raw roughness to calculate roughness fade in SSR (cherry picked from commit b99d0d778a0b1b54b0c0d3d6dbd8d74d371ba8f7) --- .../renderer_rd/shaders/effects/screen_space_reflection.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl index d629f2738d9..b730b2c819a 100644 --- a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl @@ -237,7 +237,7 @@ void main() { // This is an ad-hoc term to fade out the SSR as roughness increases. Values used // are meant to match the visual appearance of a ReflectionProbe. - float roughness_fade = smoothstep(0.4, 0.7, 1.0 - normal_roughness.w); + float roughness_fade = smoothstep(0.4, 0.7, 1.0 - roughness); // Schlick term. float metallic = texelFetch(source_metallic, ssC << 1, 0).w; From df522db6f0e146dcab3dc56fb08d87b4f9aa0376 Mon Sep 17 00:00:00 2001 From: voidedWarranties Date: Sat, 17 Aug 2024 20:45:22 -0700 Subject: [PATCH 061/190] Fix virtual binding for `ScriptLanguageExtension::_reload_scripts` (cherry picked from commit d65ea6fb9cc26359bb6f2aa704b2a6b7604c3fd3) --- core/object/script_language_extension.cpp | 1 + doc/classes/ScriptLanguageExtension.xml | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/core/object/script_language_extension.cpp b/core/object/script_language_extension.cpp index 7b643e46378..73f7ec5a544 100644 --- a/core/object/script_language_extension.cpp +++ b/core/object/script_language_extension.cpp @@ -142,6 +142,7 @@ void ScriptLanguageExtension::_bind_methods() { GDVIRTUAL_BIND(_debug_get_current_stack_info); GDVIRTUAL_BIND(_reload_all_scripts); + GDVIRTUAL_BIND(_reload_scripts, "scripts", "soft_reload"); GDVIRTUAL_BIND(_reload_tool_script, "script", "soft_reload"); GDVIRTUAL_BIND(_get_recognized_extensions); diff --git a/doc/classes/ScriptLanguageExtension.xml b/doc/classes/ScriptLanguageExtension.xml index cc47ca274d1..f9d9e4f513e 100644 --- a/doc/classes/ScriptLanguageExtension.xml +++ b/doc/classes/ScriptLanguageExtension.xml @@ -314,6 +314,13 @@ + + + + + + + From 1d0bcae019f20ae1e78186563c2f7e3e97109f05 Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Sun, 4 Aug 2024 02:23:01 -0700 Subject: [PATCH 062/190] GLTF: Propagate owner for root node children (cherry picked from commit 246cc7e86de951c8eb8475397bb07dc6631142a3) --- modules/gltf/gltf_document.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index dff1e62e824..ec4b240ff89 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -5658,6 +5658,15 @@ void GLTFDocument::_generate_scene_node(Ref p_state, const GLTFNodeIn if (p_scene_root == nullptr) { // If the root node argument is null, this is the root node. p_scene_root = current_node; + // If multiple nodes were generated under the root node, ensure they have the owner set. + if (unlikely(current_node->get_child_count() > 0)) { + Array args; + args.append(p_scene_root); + for (int i = 0; i < current_node->get_child_count(); i++) { + Node *child = current_node->get_child(i); + child->propagate_call(StringName("set_owner"), args); + } + } } else { // Add the node we generated and set the owner to the scene root. p_scene_parent->add_child(current_node, true); From df6bbb25388d560d41031472b43d21109685d7d1 Mon Sep 17 00:00:00 2001 From: kleonc <9283098+kleonc@users.noreply.github.com> Date: Thu, 6 Jun 2024 16:46:13 +0200 Subject: [PATCH 063/190] Fix MenuBar popup placement assuming it's in viewport default canvas (cherry picked from commit 8228d647a9a5a3dd36bad508ebb3746432d3d1fc) --- scene/gui/menu_bar.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scene/gui/menu_bar.cpp b/scene/gui/menu_bar.cpp index 4f8d818a6c3..3264733548b 100644 --- a/scene/gui/menu_bar.cpp +++ b/scene/gui/menu_bar.cpp @@ -121,8 +121,9 @@ void MenuBar::_open_popup(int p_index, bool p_focus_item) { } Rect2 item_rect = _get_menu_item_rect(p_index); - Point2 screen_pos = get_screen_position() + item_rect.position * get_viewport()->get_canvas_transform().get_scale(); - Size2 screen_size = item_rect.size * get_viewport()->get_canvas_transform().get_scale(); + Size2 canvas_scale = get_canvas_transform().get_scale(); + Point2 screen_pos = get_screen_position() + item_rect.position * canvas_scale; + Size2 screen_size = item_rect.size * canvas_scale; active_menu = p_index; From d0c4f19dd2bdd7d2d27096bb2b622dd51d569bf1 Mon Sep 17 00:00:00 2001 From: Juan Pablo Arce Date: Fri, 19 Jul 2024 20:30:33 -0300 Subject: [PATCH 064/190] Fix gizmos without visible geometry not being selectable The issue was that Node3DEditorViewport was using the render server's BVH to filter out nodes, which is not correct for gizmos that have no renderable components, or have collision triangles that exceed the bounds of their renderable components. (cherry picked from commit 45f6110e2634235e4828877a366c029470265ff8) --- editor/plugins/node_3d_editor_gizmos.cpp | 37 +++++++++++++++ editor/plugins/node_3d_editor_gizmos.h | 5 ++ editor/plugins/node_3d_editor_plugin.cpp | 60 ++++++++++++++++++++---- editor/plugins/node_3d_editor_plugin.h | 9 ++++ 4 files changed, 101 insertions(+), 10 deletions(-) diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp index de56767929a..67d5e44ce57 100644 --- a/editor/plugins/node_3d_editor_gizmos.cpp +++ b/editor/plugins/node_3d_editor_gizmos.cpp @@ -81,6 +81,8 @@ void EditorNode3DGizmo::redraw() { gizmo_plugin->redraw(this); } + _update_bvh(); + if (Node3DEditor::get_singleton()->is_current_selected_gizmo(this)) { Node3DEditor::get_singleton()->update_transform_gizmo(); } @@ -244,6 +246,32 @@ void EditorNode3DGizmo::add_mesh(const Ref &p_mesh, const Ref &p instances.push_back(ins); } +void EditorNode3DGizmo::_update_bvh() { + ERR_FAIL_NULL(spatial_node); + + Transform3D transform = spatial_node->get_global_transform(); + + float effective_icon_size = selectable_icon_size > 0.0f ? selectable_icon_size : 0.0f; + Vector3 icon_size_vector3 = Vector3(effective_icon_size, effective_icon_size, effective_icon_size); + AABB aabb(spatial_node->get_position() - icon_size_vector3 * 100.0f, icon_size_vector3 * 200.0f); + + for (const Vector3 &segment_end : collision_segments) { + aabb.expand_to(transform.xform(segment_end)); + } + + if (collision_mesh.is_valid()) { + for (const Face3 &face : collision_mesh->get_faces()) { + aabb.expand_to(transform.xform(face.vertex[0])); + aabb.expand_to(transform.xform(face.vertex[1])); + aabb.expand_to(transform.xform(face.vertex[2])); + } + } + + Node3DEditor::get_singleton()->update_gizmo_bvh_node( + bvh_node_id, + aabb); +} + void EditorNode3DGizmo::add_lines(const Vector &p_lines, const Ref &p_material, bool p_billboard, const Color &p_modulate) { add_vertices(p_lines, p_material, Mesh::PRIMITIVE_LINES, p_billboard, p_modulate); } @@ -765,6 +793,10 @@ void EditorNode3DGizmo::create() { instances.write[i].create_instance(spatial_node, hidden); } + bvh_node_id = Node3DEditor::get_singleton()->insert_gizmo_bvh_node( + spatial_node, + AABB(spatial_node->get_position(), Vector3(0, 0, 0))); + transform(); } @@ -774,6 +806,8 @@ void EditorNode3DGizmo::transform() { for (int i = 0; i < instances.size(); i++) { RS::get_singleton()->instance_set_transform(instances[i].instance, spatial_node->get_global_transform() * instances[i].xform); } + + _update_bvh(); } void EditorNode3DGizmo::free() { @@ -790,6 +824,9 @@ void EditorNode3DGizmo::free() { clear(); + Node3DEditor::get_singleton()->remove_gizmo_bvh_node(bvh_node_id); + bvh_node_id = DynamicBVH::ID(); + valid = false; } diff --git a/editor/plugins/node_3d_editor_gizmos.h b/editor/plugins/node_3d_editor_gizmos.h index d7c368d5d01..c4b275032ab 100644 --- a/editor/plugins/node_3d_editor_gizmos.h +++ b/editor/plugins/node_3d_editor_gizmos.h @@ -31,6 +31,7 @@ #ifndef NODE_3D_EDITOR_GIZMOS_H #define NODE_3D_EDITOR_GIZMOS_H +#include "core/math/dynamic_bvh.h" #include "core/templates/hash_map.h" #include "core/templates/local_vector.h" #include "scene/3d/camera_3d.h" @@ -72,8 +73,12 @@ class EditorNode3DGizmo : public Node3DGizmo { Vector instances; Node3D *spatial_node = nullptr; + DynamicBVH::ID bvh_node_id; + void _set_node_3d(Node *p_node) { set_node_3d(Object::cast_to(p_node)); } + void _update_bvh(); + protected: static void _bind_methods(); diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 8dbcdc8ce05..386a27a20d2 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -800,7 +800,6 @@ ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos) const { RS::get_singleton()->sdfgi_set_debug_probe_select(pos, ray); } - Vector instances = RenderingServer::get_singleton()->instances_cull_ray(pos, pos + ray * camera->get_far(), get_tree()->get_root()->get_world_3d()->get_scenario()); HashSet> found_gizmos; Node *edited_scene = get_tree()->get_edited_scene_root(); @@ -808,9 +807,9 @@ ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos) const { Node *item = nullptr; float closest_dist = 1e20; - for (int i = 0; i < instances.size(); i++) { - Node3D *spat = Object::cast_to(ObjectDB::get_instance(instances[i])); + Vector nodes_with_gizmos = Node3DEditor::get_singleton()->gizmo_bvh_ray_query(pos, pos + ray * camera->get_far()); + for (Node3D *spat : nodes_with_gizmos) { if (!spat) { continue; } @@ -863,12 +862,11 @@ void Node3DEditorViewport::_find_items_at_pos(const Point2 &p_pos, Vector<_RayRe Vector3 ray = get_ray(p_pos); Vector3 pos = get_ray_pos(p_pos); - Vector instances = RenderingServer::get_singleton()->instances_cull_ray(pos, pos + ray * camera->get_far(), get_tree()->get_root()->get_world_3d()->get_scenario()); + Vector nodes_with_gizmos = Node3DEditor::get_singleton()->gizmo_bvh_ray_query(pos, pos + ray * camera->get_far()); + HashSet found_nodes; - for (int i = 0; i < instances.size(); i++) { - Node3D *spat = Object::cast_to(ObjectDB::get_instance(instances[i])); - + for (Node3D *spat : nodes_with_gizmos) { if (!spat) { continue; } @@ -1046,7 +1044,7 @@ void Node3DEditorViewport::_select_region() { _clear_selected(); } - Vector instances = RenderingServer::get_singleton()->instances_cull_convex(frustum, get_tree()->get_root()->get_world_3d()->get_scenario()); + Vector nodes_with_gizmos = Node3DEditor::get_singleton()->gizmo_bvh_frustum_query(frustum); HashSet found_nodes; Vector selected; @@ -1055,8 +1053,7 @@ void Node3DEditorViewport::_select_region() { return; } - for (int i = 0; i < instances.size(); i++) { - Node3D *sp = Object::cast_to(ObjectDB::get_instance(instances[i])); + for (Node3D *sp : nodes_with_gizmos) { if (!sp || _is_node_locked(sp)) { continue; } @@ -9226,6 +9223,49 @@ void Node3DEditor::remove_gizmo_plugin(Ref p_plugin) { _update_gizmos_menu(); } +DynamicBVH::ID Node3DEditor::insert_gizmo_bvh_node(Node3D *p_node, const AABB &p_aabb) { + return gizmo_bvh.insert(p_aabb, p_node); +} + +void Node3DEditor::update_gizmo_bvh_node(DynamicBVH::ID p_id, const AABB &p_aabb) { + gizmo_bvh.update(p_id, p_aabb); + gizmo_bvh.optimize_incremental(1); +} + +void Node3DEditor::remove_gizmo_bvh_node(DynamicBVH::ID p_id) { + gizmo_bvh.remove(p_id); +} + +Vector Node3DEditor::gizmo_bvh_ray_query(const Vector3 &p_ray_start, const Vector3 &p_ray_end) { + struct Result { + Vector nodes; + bool operator()(void *p_data) { + nodes.append((Node3D *)p_data); + return false; + } + } result; + + gizmo_bvh.ray_query(p_ray_start, p_ray_end, result); + + return result.nodes; +} + +Vector Node3DEditor::gizmo_bvh_frustum_query(const Vector &p_frustum) { + Vector points = Geometry3D::compute_convex_mesh_points(&p_frustum[0], p_frustum.size()); + + struct Result { + Vector nodes; + bool operator()(void *p_data) { + nodes.append((Node3D *)p_data); + return false; + } + } result; + + gizmo_bvh.convex_query(p_frustum.ptr(), p_frustum.size(), points.ptr(), points.size(), result); + + return result.nodes; +} + Node3DEditorPlugin::Node3DEditorPlugin() { spatial_editor = memnew(Node3DEditor); spatial_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index 5bd14748c08..9e7d46c5e85 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -31,6 +31,7 @@ #ifndef NODE_3D_EDITOR_PLUGIN_H #define NODE_3D_EDITOR_PLUGIN_H +#include "core/math/dynamic_bvh.h" #include "editor/plugins/editor_plugin.h" #include "editor/plugins/node_3d_editor_gizmos.h" #include "editor/themes/editor_scale.h" @@ -629,6 +630,8 @@ private: int current_hover_gizmo_handle; bool current_hover_gizmo_handle_secondary; + DynamicBVH gizmo_bvh; + real_t snap_translate_value; real_t snap_rotate_value; real_t snap_scale_value; @@ -933,6 +936,12 @@ public: void add_gizmo_plugin(Ref p_plugin); void remove_gizmo_plugin(Ref p_plugin); + DynamicBVH::ID insert_gizmo_bvh_node(Node3D *p_node, const AABB &p_aabb); + void update_gizmo_bvh_node(DynamicBVH::ID p_id, const AABB &p_aabb); + void remove_gizmo_bvh_node(DynamicBVH::ID p_id); + Vector gizmo_bvh_ray_query(const Vector3 &p_ray_start, const Vector3 &p_ray_end); + Vector gizmo_bvh_frustum_query(const Vector &p_frustum); + void edit(Node3D *p_spatial); void clear(); From ecbb9a9c6ae88c9390248108181d971f6d037fc1 Mon Sep 17 00:00:00 2001 From: Orion Lawlor Date: Mon, 19 Aug 2024 18:15:08 -0800 Subject: [PATCH 065/190] Fix GLES3 crash with Mesh surface with exactly 65536 vertices Fixes #95837. (cherry picked from commit bde165ccb3dc26c8414ae6e4ab659014d9428ad0) --- drivers/gles3/storage/mesh_storage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp index d8a5b960b80..89466160c6c 100644 --- a/drivers/gles3/storage/mesh_storage.cpp +++ b/drivers/gles3/storage/mesh_storage.cpp @@ -301,7 +301,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) Vector ir = new_surface.index_data; wr = wf_indices.ptrw(); - if (new_surface.vertex_count < (1 << 16)) { + if (new_surface.vertex_count <= 65536) { // Read 16 bit indices. const uint16_t *src_idx = (const uint16_t *)ir.ptr(); for (uint32_t i = 0; i + 5 < wf_index_count; i += 6) { From bd552ff60930bcc9c7d64ee76ed1c916efa07397 Mon Sep 17 00:00:00 2001 From: matheusmdx Date: Mon, 19 Aug 2024 16:16:06 -0300 Subject: [PATCH 066/190] Fallback to theme icon when no custom icon is set in autocompletion (cherry picked from commit e8254dc3f4a72bae094711a5a07fdad63df85e62) --- editor/code_editor.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index d24b1edd709..8664c167b58 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -994,6 +994,9 @@ Ref CodeTextEditor::_get_completion_icon(const ScriptLanguage::CodeCo tex = get_editor_theme_icon(p_option.display); } else { tex = EditorNode::get_singleton()->get_class_icon(p_option.display); + if (!tex.is_valid()) { + tex = get_editor_theme_icon(SNAME("Object")); + } } } break; case ScriptLanguage::CODE_COMPLETION_KIND_ENUM: From 139f5ee15e3802e6416977e1b5880837a5d57d11 Mon Sep 17 00:00:00 2001 From: jsjtxietian Date: Sun, 10 Dec 2023 21:32:36 +0800 Subject: [PATCH 067/190] Add model_normal_matrix for fragment shader (cherry picked from commit e698351db24df691dc5ea88a6b011c24dad77ebd) --- drivers/gles3/shaders/scene.glsl | 10 ++++++++++ .../forward_clustered/scene_forward_clustered.glsl | 7 +++++++ .../shaders/forward_mobile/scene_forward_mobile.glsl | 7 +++++++ 3 files changed, 24 insertions(+) diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index ba70de9e34d..dde01a84289 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -583,6 +583,8 @@ void main() { #define SHADER_IS_SRGB true +#define FLAGS_NON_UNIFORM_SCALE (1 << 4) + /* Varyings */ #if defined(COLOR_USED) @@ -955,6 +957,7 @@ ivec2 multiview_uv(ivec2 uv) { uniform highp mat4 world_transform; uniform mediump float opaque_prepass_threshold; +uniform highp uint model_flags; #if defined(RENDER_MATERIAL) layout(location = 0) out vec4 albedo_output_buffer; @@ -1521,6 +1524,13 @@ void main() { vec3 light_vertex = vertex; #endif //LIGHT_VERTEX_USED + highp mat3 model_normal_matrix; + if (bool(model_flags & uint(FLAGS_NON_UNIFORM_SCALE))) { + model_normal_matrix = transpose(inverse(mat3(model_matrix))); + } else { + model_normal_matrix = mat3(model_matrix); + } + { #CODE : FRAGMENT } diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl index 67ee84b01be..59838f682f3 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl @@ -1030,6 +1030,13 @@ void fragment_shader(in SceneData scene_data) { vec3 light_vertex = vertex; #endif //LIGHT_VERTEX_USED + mat3 model_normal_matrix; + if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) { + model_normal_matrix = transpose(inverse(mat3(read_model_matrix))); + } else { + model_normal_matrix = mat3(read_model_matrix); + } + mat4 read_view_matrix = scene_data.view_matrix; vec2 read_viewport_size = scene_data.viewport_size; { diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl index 24568d7e948..e13c0ce8272 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl @@ -839,6 +839,13 @@ void main() { vec3 light_vertex = vertex; #endif //LIGHT_VERTEX_USED + mat3 model_normal_matrix; + if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) { + model_normal_matrix = transpose(inverse(mat3(read_model_matrix))); + } else { + model_normal_matrix = mat3(read_model_matrix); + } + mat4 read_view_matrix = scene_data.view_matrix; vec2 read_viewport_size = scene_data.viewport_size; From 433509b4893d11022b4a5bd4e63340e41c91aacd Mon Sep 17 00:00:00 2001 From: aryan-11825114 Date: Sat, 17 Aug 2024 15:01:05 +0530 Subject: [PATCH 068/190] Fix small graph editor pins at higher display scales (cherry picked from commit 3f7efd229187f25fc4395b6a5b6fc5c518a9c285) --- editor/plugins/visual_shader_editor_plugin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index f4ce35f8f25..e55a17b9456 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -115,8 +115,8 @@ void VSGraphNode::_draw_port(int p_slot_index, Point2i p_pos, bool p_left, const icon_offset = -port_icon->get_size() * 0.5; // Draw "shadow"/outline in the connection rim color. - draw_texture_rect(port_icon, Rect2(p_pos + icon_offset - Size2(2, 2), port_icon->get_size() + Size2(4, 4)), false, p_rim_color); - draw_texture(port_icon, p_pos + icon_offset, p_color); + draw_texture_rect(port_icon, Rect2(p_pos + (icon_offset - Size2(2, 2)) * EDSCALE, (port_icon->get_size() + Size2(4, 4)) * EDSCALE), false, p_rim_color); + draw_texture_rect(port_icon, Rect2(p_pos + icon_offset * EDSCALE, port_icon->get_size() * EDSCALE), false, p_color); } void VSGraphNode::draw_port(int p_slot_index, Point2i p_pos, bool p_left, const Color &p_color) { From b05470efd09a53384c7f7521a65ecc0f8174feb7 Mon Sep 17 00:00:00 2001 From: Hilderin <81109165+Hilderin@users.noreply.github.com> Date: Sat, 17 Aug 2024 08:27:10 -0400 Subject: [PATCH 069/190] Fix display dialog while saving scene (cherry picked from commit da31679d126f4620ed98d98e4395b5d2e40501a7) --- editor/editor_node.cpp | 47 ++++++++++++++++++++++++++++++++++++------ editor/editor_node.h | 37 +++++++++------------------------ 2 files changed, 51 insertions(+), 33 deletions(-) diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index f24fa344ae5..9196f59e18c 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -174,6 +174,32 @@ static const String EDITOR_NODE_CONFIG_SECTION = "EditorNode"; static const String REMOVE_ANDROID_BUILD_TEMPLATE_MESSAGE = "The Android build template is already installed in this project and it won't be overwritten.\nRemove the \"%s\" directory manually before attempting this operation again."; static const String INSTALL_ANDROID_BUILD_TEMPLATE_MESSAGE = "This will set up your project for gradle Android builds by installing the source template to \"%s\".\nNote that in order to make gradle builds instead of using pre-built APKs, the \"Use Gradle Build\" option should be enabled in the Android export preset."; +bool EditorProgress::step(const String &p_state, int p_step, bool p_force_refresh) { + if (Thread::is_main_thread()) { + return EditorNode::progress_task_step(task, p_state, p_step, p_force_refresh); + } else { + EditorNode::progress_task_step_bg(task, p_step); + return false; + } +} + +EditorProgress::EditorProgress(const String &p_task, const String &p_label, int p_amount, bool p_can_cancel) { + if (Thread::is_main_thread()) { + EditorNode::progress_add_task(p_task, p_label, p_amount, p_can_cancel); + } else { + EditorNode::progress_add_task_bg(p_task, p_label, p_amount); + } + task = p_task; +} + +EditorProgress::~EditorProgress() { + if (Thread::is_main_thread()) { + EditorNode::progress_end_task(task); + } else { + EditorNode::progress_end_task_bg(task); + } +} + void EditorNode::disambiguate_filenames(const Vector p_full_paths, Vector &r_filenames) { ERR_FAIL_COND_MSG(p_full_paths.size() != r_filenames.size(), vformat("disambiguate_filenames requires two string vectors of same length (%d != %d).", p_full_paths.size(), r_filenames.size())); @@ -1658,17 +1684,17 @@ void EditorNode::_find_node_types(Node *p_node, int &count_2d, int &count_3d) { } void EditorNode::_save_scene_with_preview(String p_file, int p_idx) { - EditorProgress save("save", TTR("Saving Scene"), 4); + save_scene_progress = memnew(EditorProgress("save", TTR("Saving Scene"), 4)); if (editor_data.get_edited_scene_root() != nullptr) { - save.step(TTR("Analyzing"), 0); + save_scene_progress->step(TTR("Analyzing"), 0); int c2d = 0; int c3d = 0; _find_node_types(editor_data.get_edited_scene_root(), c2d, c3d); - save.step(TTR("Creating Thumbnail"), 1); + save_scene_progress->step(TTR("Creating Thumbnail"), 1); // Current view? Ref img; @@ -1696,8 +1722,7 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) { if (img.is_valid() && img->get_width() > 0 && img->get_height() > 0) { img = img->duplicate(); - save.step(TTR("Creating Thumbnail"), 2); - save.step(TTR("Creating Thumbnail"), 3); + save_scene_progress->step(TTR("Creating Thumbnail"), 3); int preview_size = EDITOR_GET("filesystem/file_dialog/thumbnail_size"); preview_size *= EDSCALE; @@ -1733,12 +1758,19 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) { } } - save.step(TTR("Saving Scene"), 4); + save_scene_progress->step(TTR("Saving Scene"), 4); _save_scene(p_file, p_idx); if (!singleton->cmdline_export_mode) { EditorResourcePreview::get_singleton()->check_for_invalidation(p_file); } + + _close_save_scene_progress(); +} + +void EditorNode::_close_save_scene_progress() { + memdelete_notnull(save_scene_progress); + save_scene_progress = nullptr; } bool EditorNode::_validate_scene_recursive(const String &p_filename, Node *p_node) { @@ -5132,6 +5164,7 @@ bool EditorNode::is_project_exporting() const { void EditorNode::show_accept(const String &p_text, const String &p_title) { current_menu_option = -1; if (accept) { + _close_save_scene_progress(); accept->set_ok_button_text(p_title); accept->set_text(p_text); EditorInterface::get_singleton()->popup_dialog_centered(accept); @@ -5141,6 +5174,7 @@ void EditorNode::show_accept(const String &p_text, const String &p_title) { void EditorNode::show_save_accept(const String &p_text, const String &p_title) { current_menu_option = -1; if (save_accept) { + _close_save_scene_progress(); save_accept->set_ok_button_text(p_title); save_accept->set_text(p_text); EditorInterface::get_singleton()->popup_dialog_centered(save_accept); @@ -5149,6 +5183,7 @@ void EditorNode::show_save_accept(const String &p_text, const String &p_title) { void EditorNode::show_warning(const String &p_text, const String &p_title) { if (warning) { + _close_save_scene_progress(); warning->set_text(p_text); warning->set_title(p_title); EditorInterface::get_singleton()->popup_dialog_centered(warning); diff --git a/editor/editor_node.h b/editor/editor_node.h index 0877d458a7c..222b1cf90c7 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -122,6 +122,14 @@ class SurfaceUpgradeTool; class SurfaceUpgradeDialog; class WindowWrapper; +struct EditorProgress { + String task; + bool step(const String &p_state, int p_step = -1, bool p_force_refresh = true); + + EditorProgress(const String &p_task, const String &p_label, int p_amount, bool p_can_cancel = false); + ~EditorProgress(); +}; + class EditorNode : public Node { GDCLASS(EditorNode, Node); @@ -470,6 +478,7 @@ private: String external_file; String open_navigate; String saving_scene; + EditorProgress *save_scene_progress = nullptr; DynamicFontImportSettingsDialog *fontdata_import_settings = nullptr; SceneImportSettingsDialog *scene_import_settings = nullptr; @@ -624,6 +633,7 @@ private: void _find_node_types(Node *p_node, int &count_2d, int &count_3d); void _save_scene_with_preview(String p_file, int p_idx = -1); + void _close_save_scene_progress(); bool _find_scene_in_use(Node *p_node, const String &p_path) const; @@ -952,33 +962,6 @@ public: bool ensure_main_scene(bool p_from_native); }; -struct EditorProgress { - String task; - bool step(const String &p_state, int p_step = -1, bool p_force_refresh = true) { - if (Thread::is_main_thread()) { - return EditorNode::progress_task_step(task, p_state, p_step, p_force_refresh); - } else { - EditorNode::progress_task_step_bg(task, p_step); - return false; - } - } - EditorProgress(const String &p_task, const String &p_label, int p_amount, bool p_can_cancel = false) { - if (Thread::is_main_thread()) { - EditorNode::progress_add_task(p_task, p_label, p_amount, p_can_cancel); - } else { - EditorNode::progress_add_task_bg(p_task, p_label, p_amount); - } - task = p_task; - } - ~EditorProgress() { - if (Thread::is_main_thread()) { - EditorNode::progress_end_task(task); - } else { - EditorNode::progress_end_task_bg(task); - } - } -}; - class EditorPluginList : public Object { private: Vector plugins_list; From 1ecf20c7838a873fd25cb9e49b2455b429747a3a Mon Sep 17 00:00:00 2001 From: Mikael Hermansson Date: Wed, 14 Aug 2024 11:58:27 +0200 Subject: [PATCH 070/190] Fix errors about `UndoRedo` history mismatch when deleting bezier track (cherry picked from commit 4db3e6e6cd08a0121cdb3b93d5638a667b6665a3) --- editor/animation_bezier_editor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index 48b9e01fd83..f74bdd8bb9f 100644 --- a/editor/animation_bezier_editor.cpp +++ b/editor/animation_bezier_editor.cpp @@ -1083,7 +1083,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref &p_event) { if (I.key == REMOVE_ICON) { if (!read_only) { EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); - undo_redo->create_action("Remove Bezier Track"); + undo_redo->create_action("Remove Bezier Track", UndoRedo::MERGE_DISABLE, animation.ptr()); undo_redo->add_do_method(this, "_update_locked_tracks_after", track); undo_redo->add_do_method(this, "_update_hidden_tracks_after", track); From cf40a5bc5a354f444cb0c08363a9dec13f8f3778 Mon Sep 17 00:00:00 2001 From: Giganzo <158825920+Giganzo@users.noreply.github.com> Date: Thu, 8 Aug 2024 11:59:14 +0200 Subject: [PATCH 071/190] Fix huge tscn icon in FileSystem split mode using list view (cherry picked from commit 36c9d31a9e31525de05396fa775808e8ab7c2c79) --- editor/filesystem_dock.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 59351a8efc1..a9de8e3bc5d 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -961,7 +961,8 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) { files->set_max_columns(1); files->set_max_text_lines(1); files->set_fixed_column_width(0); - files->set_fixed_icon_size(Size2()); + const int icon_size = get_theme_constant(SNAME("class_icon_size"), EditorStringName(Editor)); + files->set_fixed_icon_size(Size2(icon_size, icon_size)); } Ref folder_icon = (use_thumbnails) ? folder_thumbnail : get_theme_icon(SNAME("folder"), SNAME("FileDialog")); From b2c83b42f6502d03457e4276417b5ab84b5c805b Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Sat, 17 Aug 2024 09:28:40 -0700 Subject: [PATCH 072/190] Relax motion vector updates to allow skipped frames for skeletons Before this change, a skeleton that was not updated every frame would result in a difference of 2+ between last_change and frame index every frame, which would disable the buffer rotation and set motion vectors to zero. This results in significant visual artifacts for FSR2 that are especially prominent on the characters that move together with the view such as the main character in third person mode. This is a significant problem for high refresh rate displays: at 120 Hz, we are effectively guaranteed to skip skeleton updates every other frame with skeleton update happening during physics processing, and the lack of physics interpolation for skeletons. This happens by default in TPS demo when FSR2 is enabled. In other places where motion vectors are disabled, such as multi-mesh and mesh rendering (where previous transform is updated), the logic effectively allows for a single-frame gap in updates, because it compares the frame where the update happened (which is the current frame if updates are consistent) with the current frame, so the latency of 0 means "update just happened", but both multi-mesh and mesh transform updates permit a latency of 1 as well. Here, however, last_change is updated *after* the frame processing has concluded, so a zero-latency update has a distance of 1. Allowing a distance of 2 (latency 1) reduces the severity of the problem and aligns the logic with transform updates. Note that the problem will still happen when refresh rate is noticeably higher than physics rate times 2. For example, it still happens at 240 Hz. However, a longer latency allowance is inconsistent with other transforms and could lead to issues, so ideally long term physical interpolation of skeleton transforms would completely solve this. (cherry picked from commit 92f2bc70dd734e0de3b6c7f18c57680c63715343) --- servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index 99622996d45..057c0450813 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -1056,8 +1056,9 @@ void MeshStorage::update_mesh_instances() { mi->surfaces[i].previous_buffer = mi->surfaces[i].current_buffer; - if (uses_motion_vectors && (frame - mi->surfaces[i].last_change) == 1) { - // Previous buffer's data can only be one frame old to be able to use motion vectors. + if (uses_motion_vectors && mi->surfaces[i].last_change && (frame - mi->surfaces[i].last_change) <= 2) { + // Use a 2-frame tolerance so that stepped skeletal animations have correct motion vectors + // (stepped animation is common for distant NPCs). uint32_t new_buffer_index = mi->surfaces[i].current_buffer ^ 1; if (mi->surfaces[i].uniform_set[new_buffer_index].is_null()) { From 40dcdcbe7902ee71f897fd73adfe1a4e337da81b Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Fri, 16 Aug 2024 22:08:21 -0700 Subject: [PATCH 073/190] Fix double free in FSR2 destructor Before this change, using FSR2 resulted in the following error when the effect was destroyed: ERROR: Attempted to free invalid ID: 662734928609453 at: _free_internal (servers/rendering/rendering_device.cpp:4957) This happened because ACCUMULATE and ACCUMULATE_SHARPEN passes shared the same shader_version object but had different pipeline IDs. When version_free was called for ACCUMULATE pass, it destroyed pipelines created from that version, including the pipeline for the ACCUMULATE_SHARPEN pass. Using a unique version could work around this problem, but it's easier to rely on version_free destroying the created pipelines through the dependency mechanism. (cherry picked from commit 0024cface56be436f6e5cd12d090333e8a6b3ef0) --- servers/rendering/renderer_rd/effects/fsr2.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/servers/rendering/renderer_rd/effects/fsr2.cpp b/servers/rendering/renderer_rd/effects/fsr2.cpp index 925352a7d1e..551ea5dd972 100644 --- a/servers/rendering/renderer_rd/effects/fsr2.cpp +++ b/servers/rendering/renderer_rd/effects/fsr2.cpp @@ -800,9 +800,6 @@ FSR2Effect::~FSR2Effect() { RD::get_singleton()->free(device.linear_clamp_sampler); for (uint32_t i = 0; i < FFX_FSR2_PASS_COUNT; i++) { - if (device.passes[i].pipeline.pipeline_rid.is_valid()) { - RD::get_singleton()->free(device.passes[i].pipeline.pipeline_rid); - } device.passes[i].shader->version_free(device.passes[i].shader_version); } } From 20ce427a6caf5f86f77dcdd4e548e48bcf93926c Mon Sep 17 00:00:00 2001 From: tetrapod00 <145553014+tetrapod00@users.noreply.github.com> Date: Tue, 20 Aug 2024 15:59:07 -0700 Subject: [PATCH 074/190] Remember "View Grid" (per-viewport) setting between editor sessions (cherry picked from commit 080acd72461fff6bef7d10975fca76e082c302ac) --- editor/plugins/node_3d_editor_plugin.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 386a27a20d2..a6b4823489d 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -4006,6 +4006,14 @@ void Node3DEditorViewport::set_state(const Dictionary &p_state) { _menu_option(VIEW_GIZMOS); } } + if (p_state.has("grid")) { + bool grid = p_state["grid"]; + + int idx = view_menu->get_popup()->get_item_index(VIEW_GRID); + if (view_menu->get_popup()->is_item_checked(idx) != grid) { + _menu_option(VIEW_GRID); + } + } if (p_state.has("information")) { bool information = p_state["information"]; @@ -4084,6 +4092,7 @@ Dictionary Node3DEditorViewport::get_state() const { d["listener"] = viewport->is_audio_listener_3d(); d["doppler"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_AUDIO_DOPPLER)); d["gizmos"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_GIZMOS)); + d["grid"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_GRID)); d["information"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_INFORMATION)); d["frame_time"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_FRAME_TIME)); d["half_res"] = subviewport_container->get_stretch_shrink() > 1; From 8496e0738f8e5d0fbced34572fa8aa8dc7cb483f Mon Sep 17 00:00:00 2001 From: Hilderin <81109165+Hilderin@users.noreply.github.com> Date: Fri, 16 Aug 2024 18:40:46 -0400 Subject: [PATCH 075/190] Fix drag&drop between window on Windows (cherry picked from commit 0987a9dc0690c272534d2e550296b233a7e53eb3) --- platform/windows/display_server_windows.cpp | 10 ++++++++++ platform/windows/display_server_windows.h | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 88ab9a4af08..ca143b3a4aa 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -4805,6 +4805,16 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA Input::get_singleton()->parse_input_event(mbd); } + // Propagate the button up event to the window on which the button down + // event was triggered. This is needed for drag & drop to work between windows, + // because the engine expects events to keep being processed + // on the same window dragging started. + if (mb->is_pressed()) { + last_mouse_button_down_window = window_id; + } else if (last_mouse_button_down_window != INVALID_WINDOW_ID) { + mb->set_window_id(last_mouse_button_down_window); + last_mouse_button_down_window = INVALID_WINDOW_ID; + } } break; case WM_WINDOWPOSCHANGED: { diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index de5b8139533..532cf22d053 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -523,7 +523,7 @@ class DisplayServerWindows : public DisplayServer { RBMap windows; WindowID last_focused_window = INVALID_WINDOW_ID; - + WindowID last_mouse_button_down_window = INVALID_WINDOW_ID; HCURSOR hCursor; WNDPROC user_proc = nullptr; From 05860062a5ae3c52490c3f8e0f73ba1be3bca1e6 Mon Sep 17 00:00:00 2001 From: jsjtxietian Date: Wed, 21 Aug 2024 12:41:12 +0800 Subject: [PATCH 076/190] Fix curve2d incorrect sample range description (cherry picked from commit 5183588499692da71d3ec582d69c805c6f91f095) --- doc/classes/Curve2D.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/classes/Curve2D.xml b/doc/classes/Curve2D.xml index 0e75c65f50a..6ce9616fb61 100644 --- a/doc/classes/Curve2D.xml +++ b/doc/classes/Curve2D.xml @@ -88,7 +88,7 @@ - Returns the position between the vertex [param idx] and the vertex [code]idx + 1[/code], where [param t] controls if the point is the first vertex ([code]t = 0.0[/code]), the last vertex ([code]t = 1.0[/code]), or in between. Values of [param t] outside the range ([code]0.0 >= t <=1[/code]) give strange, but predictable results. + Returns the position between the vertex [param idx] and the vertex [code]idx + 1[/code], where [param t] controls if the point is the first vertex ([code]t = 0.0[/code]), the last vertex ([code]t = 1.0[/code]), or in between. Values of [param t] outside the range ([code]0.0 <= t <= 1.0[/code]) give strange, but predictable results. If [param idx] is out of bounds it is truncated to the first or last vertex, and [param t] is ignored. If the curve has no points, the function sends an error to the console, and returns [code](0, 0)[/code]. From 7874dad279a3af1794a217bc33bde6b07b322a40 Mon Sep 17 00:00:00 2001 From: aaronp64 Date: Fri, 16 Aug 2024 15:13:36 -0400 Subject: [PATCH 077/190] Minor AnimationNodeBlendSpace2D documentation fixes Updated a couple parts that seemed to be copied over from AnimationNodeBlendSpace1D (cherry picked from commit 05bcfda784b953952f17688e0b8a6941b6ecf038) --- doc/classes/AnimationNodeBlendSpace2D.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/classes/AnimationNodeBlendSpace2D.xml b/doc/classes/AnimationNodeBlendSpace2D.xml index 596767599c0..da79e15be15 100644 --- a/doc/classes/AnimationNodeBlendSpace2D.xml +++ b/doc/classes/AnimationNodeBlendSpace2D.xml @@ -5,7 +5,7 @@ A resource used by [AnimationNodeBlendTree]. - [AnimationNodeBlendSpace1D] represents a virtual 2D space on which [AnimationRootNode]s are placed. Outputs the linear blend of the three adjacent animations using a [Vector2] weight. Adjacent in this context means the three [AnimationRootNode]s making up the triangle that contains the current value. + [AnimationNodeBlendSpace2D] represents a virtual 2D space on which [AnimationRootNode]s are placed. Outputs the linear blend of the three adjacent animations using a [Vector2] weight. Adjacent in this context means the three [AnimationRootNode]s making up the triangle that contains the current value. You can add vertices to the blend space with [method add_blend_point] and automatically triangulate it by setting [member auto_triangles] to [code]true[/code]. Otherwise, use [method add_triangle] and [method remove_triangle] to triangulate the blend space by hand. @@ -93,7 +93,7 @@ - Updates the position of the point at index [param point] on the blend axis. + Updates the position of the point at index [param point] in the blend space. From 19bed8fee7ee2afe964ae4e7583f41294b3f54ed Mon Sep 17 00:00:00 2001 From: Z0rb14n Date: Thu, 25 Jul 2024 18:40:29 -0700 Subject: [PATCH 078/190] Fix Vector3 Slerp Normalizing Zero Vectors Ported the existing zero length check in C++ into C#. (cherry picked from commit 0d6e9de0b904aa5acdfcc56607a3aded431c2f6c) --- .../mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs index 27f2713efa7..ef66d5bbe0d 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs @@ -692,10 +692,18 @@ namespace Godot // Zero length vectors have no angle, so the best we can do is either lerp or throw an error. return Lerp(to, weight); } + Vector3 axis = Cross(to); + real_t axisLengthSquared = axis.LengthSquared(); + if (axisLengthSquared == 0.0) + { + // Colinear vectors have no rotation axis or angle between them, so the best we can do is lerp. + return Lerp(to, weight); + } + axis /= Mathf.Sqrt(axisLengthSquared); real_t startLength = Mathf.Sqrt(startLengthSquared); real_t resultLength = Mathf.Lerp(startLength, Mathf.Sqrt(endLengthSquared), weight); real_t angle = AngleTo(to); - return Rotated(Cross(to).Normalized(), angle * weight) * (resultLength / startLength); + return Rotated(axis, angle * weight) * (resultLength / startLength); } /// From 70a8761deb3a8d682f091625a64fbceb2ef26a8c Mon Sep 17 00:00:00 2001 From: David Snopek Date: Thu, 22 Aug 2024 13:03:05 -0500 Subject: [PATCH 079/190] Fix crash when calling OpenXRAPI::get_hand_tracker() and hand-tracking is disabled (cherry picked from commit 11dd1f52aeb10e3fb8f236e2e5e050c280764fb9) --- modules/openxr/openxr_api.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp index 98e54841578..5002d40061b 100644 --- a/modules/openxr/openxr_api.cpp +++ b/modules/openxr/openxr_api.cpp @@ -1733,8 +1733,12 @@ void OpenXRAPI::cleanup_extension_wrappers() { XrHandTrackerEXT OpenXRAPI::get_hand_tracker(int p_hand_index) { ERR_FAIL_INDEX_V(p_hand_index, OpenXRHandTrackingExtension::HandTrackedHands::OPENXR_MAX_TRACKED_HANDS, XR_NULL_HANDLE); + + OpenXRHandTrackingExtension *hand_tracking = OpenXRHandTrackingExtension::get_singleton(); + ERR_FAIL_NULL_V(hand_tracking, XR_NULL_HANDLE); + OpenXRHandTrackingExtension::HandTrackedHands hand = static_cast(p_hand_index); - return OpenXRHandTrackingExtension::get_singleton()->get_hand_tracker(hand)->hand_tracker; + return hand_tracking->get_hand_tracker(hand)->hand_tracker; } Size2 OpenXRAPI::get_recommended_target_size() { From 497570b1cf1c235d6f569336194a5470598ea202 Mon Sep 17 00:00:00 2001 From: Tallivm <30693065+Tallivm@users.noreply.github.com> Date: Sat, 24 Aug 2024 16:49:48 +0300 Subject: [PATCH 080/190] Fix typo in Array code example (cherry picked from commit b516742358ba6171543399eecfc0af13e8f842d8) --- doc/classes/Array.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml index bd0e05f8e02..b60a65e9890 100644 --- a/doc/classes/Array.xml +++ b/doc/classes/Array.xml @@ -243,7 +243,7 @@ var numbers = [1, 2, 3] var extra = [4, 5, 6] numbers.append_array(extra) - print(nums) # Prints [1, 2, 3, 4, 5, 6] + print(numbers) # Prints [1, 2, 3, 4, 5, 6] [/codeblock] From 9cf21b4b03d754997b5bc284b1f8a480ddaf33eb Mon Sep 17 00:00:00 2001 From: Dungeon Master <70334983+ItzCog@users.noreply.github.com> Date: Fri, 23 Aug 2024 00:11:40 +0800 Subject: [PATCH 081/190] Fix some C# variable types In `AStar2D/3D` Class Reference (cherry picked from commit 1928a84f6e7980e09ea5c3668aecc28ead55beb2) --- doc/classes/AStar2D.xml | 4 ++-- doc/classes/AStar3D.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/classes/AStar2D.xml b/doc/classes/AStar2D.xml index 2ea6aa15bdb..cfb7d00861f 100644 --- a/doc/classes/AStar2D.xml +++ b/doc/classes/AStar2D.xml @@ -169,7 +169,7 @@ astar.ConnectPoints(2, 3, false); astar.ConnectPoints(4, 3, false); astar.ConnectPoints(1, 4, false); - int[] res = astar.GetIdPath(1, 3); // Returns [1, 2, 3] + long[] res = astar.GetIdPath(1, 3); // Returns [1, 2, 3] [/csharp] [/codeblocks] If you change the 2nd point's weight to 3, then the result will be [code][1, 4, 3][/code] instead, because now even though the distance is longer, it's "easier" to get through point 4 than through point 2. @@ -209,7 +209,7 @@ astar.ConnectPoints(1, 2, true); astar.ConnectPoints(1, 3, true); - int[] neighbors = astar.GetPointConnections(1); // Returns [2, 3] + long[] neighbors = astar.GetPointConnections(1); // Returns [2, 3] [/csharp] [/codeblocks] diff --git a/doc/classes/AStar3D.xml b/doc/classes/AStar3D.xml index 281f4edcc1f..4448698c320 100644 --- a/doc/classes/AStar3D.xml +++ b/doc/classes/AStar3D.xml @@ -197,7 +197,7 @@ astar.ConnectPoints(2, 3, false); astar.ConnectPoints(4, 3, false); astar.ConnectPoints(1, 4, false); - int[] res = astar.GetIdPath(1, 3); // Returns [1, 2, 3] + long[] res = astar.GetIdPath(1, 3); // Returns [1, 2, 3] [/csharp] [/codeblocks] If you change the 2nd point's weight to 3, then the result will be [code][1, 4, 3][/code] instead, because now even though the distance is longer, it's "easier" to get through point 4 than through point 2. @@ -236,7 +236,7 @@ astar.ConnectPoints(1, 2, true); astar.ConnectPoints(1, 3, true); - int[] neighbors = astar.GetPointConnections(1); // Returns [2, 3] + long[] neighbors = astar.GetPointConnections(1); // Returns [2, 3] [/csharp] [/codeblocks] From 2dd696867f3087e1d95f16fd6a875331629bde99 Mon Sep 17 00:00:00 2001 From: kobewi Date: Tue, 20 Aug 2024 12:38:33 +0200 Subject: [PATCH 082/190] Always store ID of PopupMenu items (cherry picked from commit 5279fec60fb183029795a1ed621eafa405eea67d) --- scene/gui/menu_button.cpp | 2 +- scene/gui/option_button.cpp | 2 +- scene/gui/popup_menu.cpp | 2 +- scene/property_list_helper.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index c60f728f34e..8c5bb1b33d8 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -198,7 +198,7 @@ void MenuButton::_bind_methods() { base_property_helper.register_property(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), defaults.icon); base_property_helper.register_property(PropertyInfo(Variant::INT, "checkable", PROPERTY_HINT_ENUM, "No,As Checkbox,As Radio Button"), defaults.checkable_type); base_property_helper.register_property(PropertyInfo(Variant::BOOL, "checked"), defaults.checked); - base_property_helper.register_property(PropertyInfo(Variant::INT, "id", PROPERTY_HINT_RANGE, "0,10,1,or_greater"), defaults.id); + base_property_helper.register_property(PropertyInfo(Variant::INT, "id", PROPERTY_HINT_RANGE, "0,10,1,or_greater", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NULL), defaults.id); base_property_helper.register_property(PropertyInfo(Variant::BOOL, "disabled"), defaults.disabled); base_property_helper.register_property(PropertyInfo(Variant::BOOL, "separator"), defaults.separator); PropertyListHelper::register_base_helper(&base_property_helper); diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index a1425fb8472..5432058f7b3 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -574,7 +574,7 @@ void OptionButton::_bind_methods() { base_property_helper.set_array_length_getter(&OptionButton::get_item_count); base_property_helper.register_property(PropertyInfo(Variant::STRING, "text"), defaults.text, &OptionButton::_dummy_setter, &OptionButton::get_item_text); base_property_helper.register_property(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), defaults.icon, &OptionButton::_dummy_setter, &OptionButton::get_item_icon); - base_property_helper.register_property(PropertyInfo(Variant::INT, "id", PROPERTY_HINT_RANGE, "0,10,1,or_greater"), defaults.id, &OptionButton::_dummy_setter, &OptionButton::get_item_id); + base_property_helper.register_property(PropertyInfo(Variant::INT, "id", PROPERTY_HINT_RANGE, "0,10,1,or_greater", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NULL), defaults.id, &OptionButton::_dummy_setter, &OptionButton::get_item_id); base_property_helper.register_property(PropertyInfo(Variant::BOOL, "disabled"), defaults.disabled, &OptionButton::_dummy_setter, &OptionButton::is_item_disabled); base_property_helper.register_property(PropertyInfo(Variant::BOOL, "separator"), defaults.separator, &OptionButton::_dummy_setter, &OptionButton::is_item_separator); PropertyListHelper::register_base_helper(&base_property_helper); diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 86b01657545..5de4cdaf599 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -2823,7 +2823,7 @@ void PopupMenu::_bind_methods() { base_property_helper.register_property(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), defaults.icon, &PopupMenu::set_item_icon, &PopupMenu::get_item_icon); base_property_helper.register_property(PropertyInfo(Variant::INT, "checkable", PROPERTY_HINT_ENUM, "No,As checkbox,As radio button"), defaults.checkable_type, &PopupMenu::_set_item_checkable_type, &PopupMenu::_get_item_checkable_type); base_property_helper.register_property(PropertyInfo(Variant::BOOL, "checked"), defaults.checked, &PopupMenu::set_item_checked, &PopupMenu::is_item_checked); - base_property_helper.register_property(PropertyInfo(Variant::INT, "id", PROPERTY_HINT_RANGE, "0,10,1,or_greater"), defaults.id, &PopupMenu::set_item_id, &PopupMenu::get_item_id); + base_property_helper.register_property(PropertyInfo(Variant::INT, "id", PROPERTY_HINT_RANGE, "0,10,1,or_greater", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NULL), defaults.id, &PopupMenu::set_item_id, &PopupMenu::get_item_id); base_property_helper.register_property(PropertyInfo(Variant::BOOL, "disabled"), defaults.disabled, &PopupMenu::set_item_disabled, &PopupMenu::is_item_disabled); base_property_helper.register_property(PropertyInfo(Variant::BOOL, "separator"), defaults.separator, &PopupMenu::set_item_as_separator, &PopupMenu::is_item_separator); PropertyListHelper::register_base_helper(&base_property_helper); diff --git a/scene/property_list_helper.cpp b/scene/property_list_helper.cpp index f840aaa759a..c6c21e0dba3 100644 --- a/scene/property_list_helper.cpp +++ b/scene/property_list_helper.cpp @@ -142,7 +142,7 @@ void PropertyListHelper::get_property_list(List *p_list) const { const Property &property = E.value; PropertyInfo info = property.info; - if (_call_getter(&property, i) == property.default_value) { + if (!(info.usage & PROPERTY_USAGE_STORE_IF_NULL) && _call_getter(&property, i) == property.default_value) { info.usage &= (~PROPERTY_USAGE_STORAGE); } From 219ddde30c8d6a27548d5e237e0951b9a5d8ff9f Mon Sep 17 00:00:00 2001 From: Adam Scott Date: Tue, 20 Aug 2024 10:29:32 -0400 Subject: [PATCH 083/190] Honor `pitch_scale` value before playing audio sample (cherry picked from commit aaafd163b29180090161c0169c70ab2772dfdcd7) --- platform/web/audio_driver_web.cpp | 1 + platform/web/godot_audio.h | 2 +- platform/web/js/libs/library_godot_audio.js | 10 +++++++--- scene/audio/audio_stream_player_internal.cpp | 1 + servers/audio/audio_stream.h | 1 + 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/platform/web/audio_driver_web.cpp b/platform/web/audio_driver_web.cpp index 5e046d7050d..0108f407262 100644 --- a/platform/web/audio_driver_web.cpp +++ b/platform/web/audio_driver_web.cpp @@ -294,6 +294,7 @@ void AudioDriverWeb::start_sample_playback(const Ref &p_pla itos(p_playback->stream->get_instance_id()).utf8().get_data(), AudioServer::get_singleton()->get_bus_index(p_playback->bus), p_playback->offset, + p_playback->pitch_scale, volume_ptrw); } diff --git a/platform/web/godot_audio.h b/platform/web/godot_audio.h index 4961ebd2bb7..f5a2a856052 100644 --- a/platform/web/godot_audio.h +++ b/platform/web/godot_audio.h @@ -51,7 +51,7 @@ extern void godot_audio_input_stop(); extern int godot_audio_sample_stream_is_registered(const char *p_stream_object_id); extern void godot_audio_sample_register_stream(const char *p_stream_object_id, float *p_frames_buf, int p_frames_total, const char *p_loop_mode, int p_loop_begin, int p_loop_end); extern void godot_audio_sample_unregister_stream(const char *p_stream_object_id); -extern void godot_audio_sample_start(const char *p_playback_object_id, const char *p_stream_object_id, int p_bus_index, float p_offset, float *p_volume_ptr); +extern void godot_audio_sample_start(const char *p_playback_object_id, const char *p_stream_object_id, int p_bus_index, float p_offset, float p_pitch_scale, float *p_volume_ptr); extern void godot_audio_sample_stop(const char *p_playback_object_id); extern void godot_audio_sample_set_pause(const char *p_playback_object_id, bool p_pause); extern int godot_audio_sample_is_active(const char *p_playback_object_id); diff --git a/platform/web/js/libs/library_godot_audio.js b/platform/web/js/libs/library_godot_audio.js index 0ba6eed4640..40fb0c356ca 100644 --- a/platform/web/js/libs/library_godot_audio.js +++ b/platform/web/js/libs/library_godot_audio.js @@ -328,6 +328,7 @@ class SampleNodeBus { * offset?: number * playbackRate?: number * startTime?: number + * pitchScale?: number * loopMode?: LoopMode * volume?: Float32Array * start?: boolean @@ -438,7 +439,7 @@ class SampleNode { /** @type {LoopMode} */ this.loopMode = options.loopMode ?? this.getSample().loopMode ?? 'disabled'; /** @type {number} */ - this._pitchScale = 1; + this._pitchScale = options.pitchScale ?? 1; /** @type {number} */ this._sourceStartTime = 0; /** @type {Map} */ @@ -1648,13 +1649,14 @@ const _GodotAudio = { }, godot_audio_sample_start__proxy: 'sync', - godot_audio_sample_start__sig: 'viiiii', + godot_audio_sample_start__sig: 'viiiifi', /** * Starts a sample. * @param {number} playbackObjectIdStrPtr Playback object id pointer * @param {number} streamObjectIdStrPtr Stream object id pointer * @param {number} busIndex Bus index * @param {number} offset Sample offset + * @param {number} pitchScale Pitch scale * @param {number} volumePtr Volume pointer * @returns {void} */ @@ -1663,6 +1665,7 @@ const _GodotAudio = { streamObjectIdStrPtr, busIndex, offset, + pitchScale, volumePtr ) { /** @type {string} */ @@ -1671,11 +1674,12 @@ const _GodotAudio = { const streamObjectId = GodotRuntime.parseString(streamObjectIdStrPtr); /** @type {Float32Array} */ const volume = GodotRuntime.heapSub(HEAPF32, volumePtr, 8); - /** @type {SampleNodeConstructorOptions} */ + /** @type {SampleNodeOptions} */ const startOptions = { offset, volume, playbackRate: 1, + pitchScale, start: true, }; GodotAudio.start_sample( diff --git a/scene/audio/audio_stream_player_internal.cpp b/scene/audio/audio_stream_player_internal.cpp index 206408e3a77..7d1ed56ca8e 100644 --- a/scene/audio/audio_stream_player_internal.cpp +++ b/scene/audio/audio_stream_player_internal.cpp @@ -152,6 +152,7 @@ Ref AudioStreamPlayerInternal::play_basic() { Ref sample_playback; sample_playback.instantiate(); sample_playback->stream = stream; + sample_playback->pitch_scale = pitch_scale; stream_playback->set_sample_playback(sample_playback); } } else if (!stream->is_meta_stream()) { diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h index 0ca4777d5c4..c995fb01abf 100644 --- a/servers/audio/audio_stream.h +++ b/servers/audio/audio_stream.h @@ -50,6 +50,7 @@ public: Ref stream; float offset = 0.0f; + float pitch_scale = 1.0; Vector volume_vector; StringName bus; }; From afc330e33f0a4279b2d634ff6a3976b55c8f9f97 Mon Sep 17 00:00:00 2001 From: Joel Winarske Date: Fri, 23 Aug 2024 14:16:37 -0700 Subject: [PATCH 084/190] Use wayland-egl-core.h instead of wayland-egl.h -avoid use of transitive wayland include -resolves https://github.com/godotengine/godot/issues/95830 Signed-off-by: Joel Winarske (cherry picked from commit 6ce71f0fb0a091cffb6adb4af8ab3f716ad8930b) --- platform/linuxbsd/wayland/wayland_thread.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/linuxbsd/wayland/wayland_thread.h b/platform/linuxbsd/wayland/wayland_thread.h index 775ca71346b..76a14dbd6a4 100644 --- a/platform/linuxbsd/wayland/wayland_thread.h +++ b/platform/linuxbsd/wayland/wayland_thread.h @@ -44,7 +44,7 @@ #include #include #ifdef GLES3_ENABLED -#include +#include #endif #include #endif // SOWRAP_ENABLED From e59f59a4394e86eb344c70df75a9d63da743217d Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Tue, 20 Aug 2024 10:13:46 +0300 Subject: [PATCH 085/190] [Editor] Prevent unnecessary editor theme regeneration on unrelated system setting update. (cherry picked from commit 97085358ce154f34d6ab571c35529a8b0e063513) --- editor/editor_node.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 9196f59e18c..0eff674e3c3 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -696,7 +696,10 @@ void EditorNode::_notification(int p_what) { callable_mp(this, &EditorNode::_begin_first_scan).call_deferred(); - DisplayServer::get_singleton()->set_system_theme_change_callback(callable_mp(this, &EditorNode::_update_theme).bind(false)); + last_dark_mode_state = DisplayServer::get_singleton()->is_dark_mode(); + last_system_accent_color = DisplayServer::get_singleton()->get_accent_color(); + last_system_base_color = DisplayServer::get_singleton()->get_base_color(); + DisplayServer::get_singleton()->set_system_theme_change_callback(callable_mp(this, &EditorNode::_check_system_theme_changed)); /* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */ } break; From 99dde70ad39b8acecabca51cf80b2bfaa85cc44c Mon Sep 17 00:00:00 2001 From: Paul Joannon Date: Mon, 19 Aug 2024 18:09:58 +0200 Subject: [PATCH 086/190] Fix relative paths for global class icons in C# (cherry picked from commit 3c0eaec39f62ba1d86ba12abdf3f95779e608c25) --- .../GodotSharp/Core/Bridge/ScriptManagerBridge.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs index 5cc2a8026eb..901700067df 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs @@ -241,11 +241,17 @@ namespace Godot.Bridge if (outIconPath != null) { - var iconAttr = scriptType.GetCustomAttributes(inherit: false) + IconAttribute? iconAttr = scriptType.GetCustomAttributes(inherit: false) .OfType() .FirstOrDefault(); - *outIconPath = Marshaling.ConvertStringToNative(iconAttr?.Path); + if (!string.IsNullOrEmpty(iconAttr?.Path)) + { + string iconPath = iconAttr.Path.IsAbsolutePath() + ? iconAttr.Path.SimplifyPath() + : scriptPathStr.GetBaseDir().PathJoin(iconAttr.Path).SimplifyPath(); + *outIconPath = Marshaling.ConvertStringToNative(iconPath); + } } if (outBaseType != null) From 8e1d1a54fe9b44d7a509cb5ae52ee1e00e48e5ac Mon Sep 17 00:00:00 2001 From: BlueCube3310 <53150244+BlueCube3310@users.noreply.github.com> Date: Mon, 26 Aug 2024 13:24:00 +0200 Subject: [PATCH 087/190] Compatibility: Fix crash when initializing certain compressed layered textures (cherry picked from commit e8b4568900c42544b79b3b17bfb80cd3f663021d) --- drivers/gles3/storage/texture_storage.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp index 3b1373c9287..b074838ee8e 100644 --- a/drivers/gles3/storage/texture_storage.cpp +++ b/drivers/gles3/storage/texture_storage.cpp @@ -1497,11 +1497,9 @@ void TextureStorage::_texture_set_data(RID p_texture, const Ref &p_image, glPixelStorei(GL_UNPACK_ALIGNMENT, 4); if (texture->target == GL_TEXTURE_2D_ARRAY) { if (p_initialize) { - glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, i, internal_format, w, h, texture->layers, 0, - size * texture->layers, &read[ofs]); - } else { - glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, i, 0, 0, p_layer, w, h, 1, internal_format, size, &read[ofs]); + glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, i, internal_format, w, h, texture->layers, 0, size * texture->layers, nullptr); } + glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, i, 0, 0, p_layer, w, h, 1, internal_format, size, &read[ofs]); } else { glCompressedTexImage2D(blit_target, i, internal_format, w, h, 0, size, &read[ofs]); } From 95a0525361d0ac7396b12fd5ee9c2f779d3a23db Mon Sep 17 00:00:00 2001 From: Mikael Hermansson Date: Tue, 16 Jul 2024 11:34:44 +0200 Subject: [PATCH 088/190] Fix animation library copy-paste not preserving resource reference (cherry picked from commit 08ef14a037ab3d7f74c00d5b4f034417735e32ab) --- editor/plugins/animation_library_editor.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/editor/plugins/animation_library_editor.cpp b/editor/plugins/animation_library_editor.cpp index b07db993ba9..38f8b16b341 100644 --- a/editor/plugins/animation_library_editor.cpp +++ b/editor/plugins/animation_library_editor.cpp @@ -561,7 +561,9 @@ void AnimationLibraryEditor::_button_pressed(TreeItem *p_item, int p_column, int return; } - anim = anim->duplicate(); // Users simply dont care about referencing, so making a copy works better here. + if (!anim->get_path().is_resource_file()) { + anim = anim->duplicate(); // Users simply dont care about referencing, so making a copy works better here. + } String base_name; if (anim->get_name() != "") { From 169b568e650b6ef319fa48e8b85e90d3742c8f8e Mon Sep 17 00:00:00 2001 From: Jason Wodicka Date: Fri, 23 Aug 2024 17:52:00 -0700 Subject: [PATCH 089/190] Fix C# code example for Object._get_property_list There were two small errors in this code example that kept it from working when copied to a new node locally. These are the fixes I used locally to test the example. (cherry picked from commit 97cf2c147e42ac44092d22538fb6f2748a8b4584) --- doc/classes/Object.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml index ed420f4587d..0cfa3a5d4a0 100644 --- a/doc/classes/Object.xml +++ b/doc/classes/Object.xml @@ -136,7 +136,7 @@ } } - private List<int> _numbers = new(); + private Godot.Collections.Array<int> _numbers = new(); public override Godot.Collections.Array<Godot.Collections.Dictionary> _GetPropertyList() { @@ -173,7 +173,7 @@ if (propertyName.StartsWith("number_")) { int index = int.Parse(propertyName.Substring("number_".Length)); - numbers[index] = value.As<int>(); + _numbers[index] = value.As<int>(); return true; } return false; From f9bcd4f0caaf24b1b2e260f4514ab0c7e2b10e2c Mon Sep 17 00:00:00 2001 From: Rakka Rage Date: Thu, 22 Aug 2024 01:29:23 -0400 Subject: [PATCH 090/190] Enable revert button for `ShaderMaterial::next_pass` and `ShaderMaterial::render_priority`. (cherry picked from commit ba23b22153c21fa0f3b253900009ac7221e5a7a8) --- scene/resources/material.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 7d121c9d87f..d07dee66742 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -379,6 +379,8 @@ bool ShaderMaterial::_property_can_revert(const StringName &p_name) const { Variant default_value = RenderingServer::get_singleton()->shader_get_parameter_default(shader->get_rid(), *pr); Variant current_value = get_shader_parameter(*pr); return default_value.get_type() != Variant::NIL && default_value != current_value; + } else if (p_name == "render_priority" || p_name == "next_pass") { + return true; } } return false; @@ -390,6 +392,12 @@ bool ShaderMaterial::_property_get_revert(const StringName &p_name, Variant &r_p if (pr) { r_property = RenderingServer::get_singleton()->shader_get_parameter_default(shader->get_rid(), *pr); return true; + } else if (p_name == "render_priority") { + r_property = 0; + return true; + } else if (p_name == "next_pass") { + r_property = Variant(); + return true; } } return false; From 0f33a4b97ede3821495b24df70375cb61a779cb4 Mon Sep 17 00:00:00 2001 From: Fredia Huya-Kouadio Date: Sun, 25 Aug 2024 17:04:46 -0700 Subject: [PATCH 091/190] Fix invalid `Skeleton3D` bone pose updates The issue would cause log spams when trying to update the bone pose position or rotation with an invalid bone index. (cherry picked from commit 039722a3418dfd8f16cd3e956527ef93e639ddba) --- scene/3d/xr_hand_modifier_3d.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scene/3d/xr_hand_modifier_3d.cpp b/scene/3d/xr_hand_modifier_3d.cpp index baaa9eee48d..aa63fb623f1 100644 --- a/scene/3d/xr_hand_modifier_3d.cpp +++ b/scene/3d/xr_hand_modifier_3d.cpp @@ -207,6 +207,11 @@ void XRHandModifier3D::_process_modification() { // Apply previous relative transforms if they are stored. for (int joint = 0; joint < XRHandTracker::HAND_JOINT_MAX; joint++) { + const int bone = joints[joint].bone; + if (bone == -1) { + continue; + } + if (bone_update == BONE_UPDATE_FULL) { skeleton->set_bone_pose_position(joints[joint].bone, previous_relative_transforms[joint].origin); } From e5be133032cba65d78ac26d7bb8b623f8663010c Mon Sep 17 00:00:00 2001 From: Sen Date: Thu, 8 Aug 2024 08:14:43 +0200 Subject: [PATCH 092/190] Fix for multimesh motion vector corruption by resetting motion vector state and filling both halves of buffer (cherry picked from commit 52cd5acdda120776775e73babf3fbb65ef0a5c2e) --- .../rendering/renderer_rd/storage_rd/mesh_storage.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index 057c0450813..a95c4ec83ae 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -1440,12 +1440,10 @@ void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS:: multimesh->motion_vectors_current_offset = 0; multimesh->motion_vectors_previous_offset = 0; multimesh->motion_vectors_last_change = -1; + multimesh->motion_vectors_enabled = false; if (multimesh->instances) { uint32_t buffer_size = multimesh->instances * multimesh->stride_cache * sizeof(float); - if (multimesh->motion_vectors_enabled) { - buffer_size *= 2; - } multimesh->buffer = RD::get_singleton()->storage_buffer_create(buffer_size); } @@ -1935,6 +1933,7 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector &p_b ERR_FAIL_NULL(multimesh); ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache)); + bool used_motion_vectors = multimesh->motion_vectors_enabled; bool uses_motion_vectors = (RSG::viewport->get_num_viewports_with_motion_vectors() > 0) || (RendererCompositorStorage::get_singleton()->get_num_compositor_effects_with_motion_vectors() > 0); if (uses_motion_vectors) { _multimesh_enable_motion_vectors(multimesh); @@ -1953,6 +1952,11 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector &p_b { const float *r = p_buffer.ptr(); RD::get_singleton()->buffer_update(multimesh->buffer, multimesh->motion_vectors_current_offset * multimesh->stride_cache * sizeof(float), p_buffer.size() * sizeof(float), r); + if (multimesh->motion_vectors_enabled && !used_motion_vectors) { + // Motion vectors were just enabled, and the other half of the buffer will be empty. + // Need to ensure that both halves are filled for correct operation. + RD::get_singleton()->buffer_update(multimesh->buffer, multimesh->motion_vectors_previous_offset * multimesh->stride_cache * sizeof(float), p_buffer.size() * sizeof(float), r); + } multimesh->buffer_set = true; } From b6055941b95128af35eff30fd7fc9313588e00b3 Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Tue, 27 Aug 2024 08:44:05 +0300 Subject: [PATCH 093/190] [Windows] Hide cursor before moving. (cherry picked from commit 9a2977fef170115f600fc4e36734ae7af00cbe77) --- platform/windows/display_server_windows.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index ca143b3a4aa..89cf90829fc 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -133,9 +133,17 @@ String DisplayServerWindows::get_name() const { } void DisplayServerWindows::_set_mouse_mode_impl(MouseMode p_mode) { + if (p_mode == MOUSE_MODE_HIDDEN || p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED_HIDDEN) { + // Hide cursor before moving. + if (hCursor == nullptr) { + hCursor = SetCursor(nullptr); + } else { + SetCursor(nullptr); + } + } + if (windows.has(MAIN_WINDOW_ID) && (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED || p_mode == MOUSE_MODE_CONFINED_HIDDEN)) { // Mouse is grabbed (captured or confined). - WindowID window_id = _get_focused_window_or_popup(); if (!windows.has(window_id)) { window_id = MAIN_WINDOW_ID; @@ -165,13 +173,8 @@ void DisplayServerWindows::_set_mouse_mode_impl(MouseMode p_mode) { _register_raw_input_devices(INVALID_WINDOW_ID); } - if (p_mode == MOUSE_MODE_HIDDEN || p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED_HIDDEN) { - if (hCursor == nullptr) { - hCursor = SetCursor(nullptr); - } else { - SetCursor(nullptr); - } - } else { + if (p_mode == MOUSE_MODE_VISIBLE || p_mode == MOUSE_MODE_CONFINED) { + // Show cursor. CursorShape c = cursor_shape; cursor_shape = CURSOR_MAX; cursor_set_shape(c); From 1d775b5b97053ed76d620e43c44ca3e799e3f5ed Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Tue, 27 Aug 2024 13:10:09 +0200 Subject: [PATCH 094/190] [mbedTLS] Fix incorrect cert pinning with client_unsafe (cherry picked from commit ccae47ab667174ac521b7d1a1b2fe330ea11ce1e) --- modules/mbedtls/tls_context_mbedtls.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/mbedtls/tls_context_mbedtls.cpp b/modules/mbedtls/tls_context_mbedtls.cpp index eaea7b92933..f5c196596eb 100644 --- a/modules/mbedtls/tls_context_mbedtls.cpp +++ b/modules/mbedtls/tls_context_mbedtls.cpp @@ -153,7 +153,7 @@ Error TLSContextMbedTLS::init_client(int p_transport, const String &p_hostname, int authmode = MBEDTLS_SSL_VERIFY_REQUIRED; bool unsafe = p_options->is_unsafe_client(); - if (unsafe && p_options->get_trusted_ca_chain().is_valid()) { + if (unsafe && p_options->get_trusted_ca_chain().is_null()) { authmode = MBEDTLS_SSL_VERIFY_NONE; } From 4d7feff723074f0a601ac499a266c23914c400f7 Mon Sep 17 00:00:00 2001 From: kleonc <9283098+kleonc@users.noreply.github.com> Date: Wed, 7 Aug 2024 21:17:09 +0200 Subject: [PATCH 095/190] Fix snapping when zoomed in Polygon2D UV editor (cherry picked from commit 1b7626f391736160e26805932c6376eb3d3dc1e0) --- editor/plugins/polygon_2d_editor_plugin.cpp | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index e442c37edd5..310250b3a19 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -181,7 +181,7 @@ void Polygon2DEditor::_sync_bones() { } if (weights.size() == 0) { //create them - weights.resize(node->get_polygon().size()); + weights.resize(wc); float *w = weights.ptrw(); for (int j = 0; j < wc; j++) { w[j] = 0.0; @@ -850,8 +850,8 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { if (mm.is_valid()) { if (uv_drag) { Vector2 uv_drag_to = mm->get_position(); - uv_drag_to = snap_point(uv_drag_to); // FIXME: Only works correctly with 'UV_MODE_EDIT_POINT', it's imprecise with the rest. - Vector2 drag = mtx.affine_inverse().xform(uv_drag_to) - mtx.affine_inverse().xform(uv_drag_from); + uv_drag_to = snap_point(uv_drag_to); + Vector2 drag = mtx.affine_inverse().basis_xform(uv_drag_to - uv_drag_from); switch (uv_move_current) { case UV_MODE_CREATE: { @@ -1166,12 +1166,8 @@ void Polygon2DEditor::_uv_draw() { poly_line_color.a *= 0.25; } Color polygon_line_color = Color(0.5, 0.5, 0.9); - Vector polygon_fill_color; - { - Color pf = polygon_line_color; - pf.a *= 0.5; - polygon_fill_color.push_back(pf); - } + Color polygon_fill_color = polygon_line_color; + polygon_fill_color.a *= 0.5; Color prev_color = Color(0.5, 0.5, 0.5); int uv_draw_max = uvs.size(); @@ -1216,7 +1212,7 @@ void Polygon2DEditor::_uv_draw() { uv_edit_draw->draw_line(mtx.xform(uvs[idx]), mtx.xform(uvs[idx_next]), polygon_line_color, Math::round(EDSCALE)); } if (points.size() >= 3) { - uv_edit_draw->draw_polygon(polypoints, polygon_fill_color); + uv_edit_draw->draw_colored_polygon(polypoints, polygon_fill_color); } } @@ -1309,8 +1305,8 @@ void Polygon2DEditor::_bind_methods() { Vector2 Polygon2DEditor::snap_point(Vector2 p_target) const { if (use_snap) { - p_target.x = Math::snap_scalar(snap_offset.x * uv_draw_zoom - uv_draw_ofs.x, snap_step.x * uv_draw_zoom, p_target.x); - p_target.y = Math::snap_scalar(snap_offset.y * uv_draw_zoom - uv_draw_ofs.y, snap_step.y * uv_draw_zoom, p_target.y); + p_target.x = Math::snap_scalar((snap_offset.x - uv_draw_ofs.x) * uv_draw_zoom, snap_step.x * uv_draw_zoom, p_target.x); + p_target.y = Math::snap_scalar((snap_offset.y - uv_draw_ofs.y) * uv_draw_zoom, snap_step.y * uv_draw_zoom, p_target.y); } return p_target; From 4fabc1ba58c2be07928ada95a92904ff5ac3b432 Mon Sep 17 00:00:00 2001 From: kit Date: Fri, 23 Aug 2024 16:34:24 -0400 Subject: [PATCH 096/190] Fix script overwriting with external editor (cherry picked from commit 23927c3d9b960929b3fb350b3f11ab6ae07936f9) --- editor/plugins/script_editor_plugin.cpp | 8 +++++--- editor/plugins/script_editor_plugin.h | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index c51eb44aee4..f7ced2b1796 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -2711,9 +2711,11 @@ void ScriptEditor::apply_scripts() const { } void ScriptEditor::reload_scripts(bool p_refresh_only) { - if (external_editor_active) { - return; - } + // Call deferred to make sure it runs on the main thread. + callable_mp(this, &ScriptEditor::_reload_scripts).call_deferred(p_refresh_only); +} + +void ScriptEditor::_reload_scripts(bool p_refresh_only) { for (int i = 0; i < tab_container->get_tab_count(); i++) { ScriptEditorBase *se = Object::cast_to(tab_container->get_tab_control(i)); if (!se) { diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index 9db1aff76ac..ef88bc107b0 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -436,6 +436,7 @@ class ScriptEditor : public PanelContainer { void _file_removed(const String &p_file); void _autosave_scripts(); void _update_autosave_timer(); + void _reload_scripts(bool p_refresh_only = false); void _update_members_overview_visibility(); void _update_members_overview(); From e2184c5da0c1a5b0da69509cc71c56b90f0dac6f Mon Sep 17 00:00:00 2001 From: jsjtxietian Date: Tue, 27 Aug 2024 11:42:18 +0800 Subject: [PATCH 097/190] Support opening custom class documentation with "Open Documentation" menu entry (cherry picked from commit b5fa2a3d3af439a14ca1b4d85f6deb3f53aea914) --- editor/scene_tree_dock.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 56924fc1fe7..bf882f1d170 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -1181,7 +1181,16 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { case TOOL_OPEN_DOCUMENTATION: { List selection = editor_selection->get_selected_node_list(); for (const Node *node : selection) { - ScriptEditor::get_singleton()->goto_help("class_name:" + node->get_class()); + String class_name; + Ref