From d8f0c2bdca653b4a1ec5ef3d173d798efc5005b2 Mon Sep 17 00:00:00 2001 From: Ricardo Buring Date: Mon, 13 Mar 2023 13:54:10 +0100 Subject: [PATCH 01/73] Revert attempted fix of trimesh CCD (cherry picked from commit bec1182093febd37362766d67b6e78895343434a) --- servers/physics_3d/godot_body_pair_3d.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/servers/physics_3d/godot_body_pair_3d.cpp b/servers/physics_3d/godot_body_pair_3d.cpp index 3a91e5e4805..292563b6ab5 100644 --- a/servers/physics_3d/godot_body_pair_3d.cpp +++ b/servers/physics_3d/godot_body_pair_3d.cpp @@ -237,17 +237,10 @@ bool GodotBodyPair3D::_test_ccd(real_t p_step, GodotBody3D *p_A, int p_shape_A, Vector3 hitpos = p_xform_B.xform(segment_hit_local); real_t newlen = hitpos.distance_to(supports_A[segment_support_idx]); - if (shape_B_ptr->is_concave()) { - // Subtracting 5% of body length from the distance between collision and support point - // should cause body A's support point to arrive just before a face of B next frame. - newlen = MAX(newlen - (max - min) * 0.05, 0.0); - // NOTE: This may stop body A completely, without a proper collision response. - // We consider this preferable to tunneling. - } else { - // Adding 1% of body length to the distance between collision and support point - // should cause body A's support point to arrive just within B's collider next frame. - newlen += (max - min) * 0.01; - } + // Adding 1% of body length to the distance between collision and support point + // should cause body A's support point to arrive just within B's collider next frame. + newlen += (max - min) * 0.01; + // FIXME: This doesn't always work well when colliding with a triangle face of a trimesh shape. p_A->set_linear_velocity((mnormal * newlen) / p_step); From 5262fe21de8ec04a6b25b1a73c2789a7bdc3dc03 Mon Sep 17 00:00:00 2001 From: clayjohn Date: Thu, 9 Mar 2023 12:49:00 -0800 Subject: [PATCH 02/73] Delete unused compression formats from .imoprt files when exporting (cherry picked from commit dec86164e123fe34b0406521e156aa967a96e66b) --- editor/export/editor_export_platform.cpp | 35 ++++++++++++++++-------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp index fe3c2333ed2..fa6b0a77163 100644 --- a/editor/export/editor_export_platform.cpp +++ b/editor/export/editor_export_platform.cpp @@ -1026,13 +1026,13 @@ Error EditorExportPlatform::export_project_files(const Ref & String type = ResourceLoader::get_resource_type(path); if (FileAccess::exists(path + ".import")) { - // Before doing this, try to see if it can be customized + // Before doing this, try to see if it can be customized. String export_path = _export_customize(path, customize_resources_plugins, customize_scenes_plugins, export_cache, export_base_path, false); if (export_path != path) { - // It was actually customized.. - // Since the original file is likely not recognized, just use the import system + // It was actually customized. + // Since the original file is likely not recognized, just use the import system. Ref config; config.instantiate(); @@ -1043,18 +1043,18 @@ Error EditorExportPlatform::export_project_files(const Ref & } config->set_value("remap", "type", ResourceLoader::get_resource_type(export_path)); - // Erase all PAths + // Erase all Paths. List keys; config->get_section_keys("remap", &keys); for (const String &K : keys) { - if (E.begins_with("path")) { + if (K.begins_with("path")) { config->erase_section_key("remap", K); } } // Set actual converted path. config->set_value("remap", "path", export_path); - // erase useless sections + // Erase useless sections. config->erase_section("deps"); config->erase_section("params"); @@ -1075,7 +1075,7 @@ Error EditorExportPlatform::export_project_files(const Ref & return err; } } else { - // file is imported and not customized, replace by what it imports + // File is imported and not customized, replace by what it imports. Ref config; config.instantiate(); err = config->load(path + ".import"); @@ -1087,7 +1087,7 @@ Error EditorExportPlatform::export_project_files(const Ref & String importer_type = config->get_value("remap", "importer"); if (importer_type == "keep") { - //just keep file as-is + // Just keep file as-is. Vector array = FileAccess::get_file_as_bytes(path); err = p_func(p_udata, path, array, idx, total, enc_in_filters, enc_ex_filters, key); @@ -1130,6 +1130,9 @@ Error EditorExportPlatform::export_project_files(const Ref & String remapped_path = config->get_value("remap", remap); Vector array = FileAccess::get_file_as_bytes(remapped_path); err = p_func(p_udata, remapped_path, array, idx, total, enc_in_filters, enc_ex_filters, key); + } else { + // Remove paths if feature not enabled. + config->erase_section_key("remap", remap); } } } @@ -1138,9 +1141,17 @@ Error EditorExportPlatform::export_project_files(const Ref & return err; } - //also save the .import file - Vector array = FileAccess::get_file_as_bytes(path + ".import"); - err = p_func(p_udata, path + ".import", array, idx, total, enc_in_filters, enc_ex_filters, key); + // Erase useless sections. + config->erase_section("deps"); + config->erase_section("params"); + + String import_text = config->encode_to_text(); + CharString cs = import_text.utf8(); + Vector sarr; + sarr.resize(cs.size()); + memcpy(sarr.ptrw(), cs.ptr(), sarr.size()); + + err = p_func(p_udata, path + ".import", sarr, idx, total, enc_in_filters, enc_ex_filters, key); if (err != OK) { return err; @@ -1148,7 +1159,7 @@ Error EditorExportPlatform::export_project_files(const Ref & } } else { - // Customize + // Customize. bool do_export = true; for (int i = 0; i < export_plugins.size(); i++) { From ca0ba83f0307cad3e8119945e6e2de9570190803 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82?= Date: Wed, 26 Oct 2022 19:43:50 +0200 Subject: [PATCH 03/73] Fix scrolling behaviour with low page value (cherry picked from commit 1608bea18809dcb4e744ee936f8de8f5660adfbe) --- scene/gui/scroll_bar.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp index b8faf22a59a..fcf93029530 100644 --- a/scene/gui/scroll_bar.cpp +++ b/scene/gui/scroll_bar.cpp @@ -55,12 +55,14 @@ void ScrollBar::gui_input(const Ref &p_event) { accept_event(); if (b->get_button_index() == MouseButton::WHEEL_DOWN && b->is_pressed()) { - set_value(get_value() + get_page() / 4.0); + double change = get_page() != 0.0 ? get_page() / 4.0 : (get_max() - get_min()) / 16.0; + set_value(get_value() + MAX(change, get_step())); accept_event(); } if (b->get_button_index() == MouseButton::WHEEL_UP && b->is_pressed()) { - set_value(get_value() - get_page() / 4.0); + double change = get_page() != 0.0 ? get_page() / 4.0 : (get_max() - get_min()) / 16.0; + set_value(get_value() - MAX(change, get_step())); accept_event(); } @@ -99,7 +101,8 @@ void ScrollBar::gui_input(const Ref &p_event) { if (scrolling) { target_scroll = CLAMP(target_scroll - get_page(), get_min(), get_max() - get_page()); } else { - target_scroll = CLAMP(get_value() - get_page(), get_min(), get_max() - get_page()); + double change = get_page() != 0.0 ? get_page() : (get_max() - get_min()) / 16.0; + target_scroll = CLAMP(get_value() - change, get_min(), get_max() - get_page()); } if (smooth_scroll_enabled) { @@ -122,7 +125,8 @@ void ScrollBar::gui_input(const Ref &p_event) { if (scrolling) { target_scroll = CLAMP(target_scroll + get_page(), get_min(), get_max() - get_page()); } else { - target_scroll = CLAMP(get_value() + get_page(), get_min(), get_max() - get_page()); + double change = get_page() != 0.0 ? get_page() : (get_max() - get_min()) / 16.0; + target_scroll = CLAMP(get_value() + change, get_min(), get_max() - get_page()); } if (smooth_scroll_enabled) { From 74b5a0ca4f3223f7d26fb7f5f80266bfca58c79c Mon Sep 17 00:00:00 2001 From: Eric M Date: Tue, 10 Jan 2023 21:30:07 +1000 Subject: [PATCH 04/73] Fix cancelling selection (pressing escape) while gizmo editing making uncommitted changes. * Pressing escape while gizmo editing will discard the changes made during that edit 'session' (cherry picked from commit 871ddf80c097717ad55026ce0cf60481af489eae) --- editor/plugins/collision_shape_2d_editor_plugin.cpp | 6 ++++++ editor/plugins/collision_shape_2d_editor_plugin.h | 1 + editor/plugins/node_3d_editor_plugin.cpp | 5 +++++ 3 files changed, 12 insertions(+) diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp index c2d5885e437..4afbb87197a 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.cpp +++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp @@ -356,6 +356,7 @@ bool CollisionShape2DEditor::forward_canvas_gui_input(const Ref &p_e return false; } + original_point = handles[edit_handle]; original = get_handle_value(edit_handle); original_transform = node->get_global_transform(); last_point = original; @@ -572,6 +573,11 @@ void CollisionShape2DEditor::edit(Node *p_node) { _get_current_shape_type(); } else { + if (pressed) { + set_handle(edit_handle, original_point); + pressed = false; + } + edit_handle = -1; shape_type = -1; diff --git a/editor/plugins/collision_shape_2d_editor_plugin.h b/editor/plugins/collision_shape_2d_editor_plugin.h index 68fc0ddbdf1..9c37b6cf9de 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.h +++ b/editor/plugins/collision_shape_2d_editor_plugin.h @@ -71,6 +71,7 @@ class CollisionShape2DEditor : public Control { bool pressed; Variant original; Transform2D original_transform; + Vector2 original_point; Point2 last_point; Variant get_handle_value(int idx) const; diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 333771ceb4a..7c5b8600d44 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -2102,6 +2102,11 @@ void Node3DEditorViewport::_sinput(const Ref &p_event) { } if (_edit.mode == TRANSFORM_NONE) { + if (_edit.gizmo.is_valid()) { + // Restore. + _edit.gizmo->commit_handle(_edit.gizmo_handle, _edit.gizmo_handle_secondary, _edit.gizmo_initial_value, true); + _edit.gizmo = Ref(); + } if (k->get_keycode() == Key::ESCAPE && !cursor.region_select) { _clear_selected(); return; From 34a087cc2c8f7c1444642723bbb4178e359dad61 Mon Sep 17 00:00:00 2001 From: LandoUWB Date: Wed, 1 Feb 2023 01:59:56 -0800 Subject: [PATCH 05/73] Incorporating the availability of screen and depth textures for the GLES3 backend (cherry picked from commit 98697b05d86b0bc81a950278be7aaafcdcfa7f82) --- drivers/gles3/rasterizer_scene_gles3.cpp | 22 ++++++++ drivers/gles3/storage/texture_storage.cpp | 61 +++++++++++++++++++++++ drivers/gles3/storage/texture_storage.h | 3 ++ 3 files changed, 86 insertions(+) diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 6cc6b8224c3..eb9ca49c5d4 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1994,6 +1994,28 @@ void RasterizerSceneGLES3::render_scene(const Ref &p_render_ _draw_sky(render_data.environment, render_data.cam_projection, render_data.cam_transform, sky_energy_multiplier, p_camera_data->view_count > 1, flip_y); } + if (scene_state.used_screen_texture || scene_state.used_depth_texture) { + texture_storage->copy_scene_to_backbuffer(rt, scene_state.used_screen_texture, scene_state.used_depth_texture); + glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->fbo); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, rt->backbuffer_fbo); + if (scene_state.used_screen_texture) { + glBlitFramebuffer(0, 0, rt->size.x, rt->size.y, + 0, 0, rt->size.x, rt->size.y, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 5); + glBindTexture(GL_TEXTURE_2D, rt->backbuffer); + } + if (scene_state.used_depth_texture) { + glBlitFramebuffer(0, 0, rt->size.x, rt->size.y, + 0, 0, rt->size.x, rt->size.y, + GL_DEPTH_BUFFER_BIT, GL_NEAREST); + glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 6); + glBindTexture(GL_TEXTURE_2D, rt->backbuffer_depth); + } + glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo); + } + RENDER_TIMESTAMP("Render 3D Transparent Pass"); glEnable(GL_BLEND); diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp index dae722186cc..4baffa93d5d 100644 --- a/drivers/gles3/storage/texture_storage.cpp +++ b/drivers/gles3/storage/texture_storage.cpp @@ -1782,7 +1782,64 @@ void TextureStorage::_create_render_target_backbuffer(RenderTarget *rt) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } } +void GLES3::TextureStorage::copy_scene_to_backbuffer(RenderTarget *rt, const bool uses_screen_texture, const bool uses_depth_texture) { + if (rt->backbuffer != 0 && rt->backbuffer_depth != 0) { + return; + } + Config *config = Config::get_singleton(); + bool use_multiview = rt->view_count > 1 && config->multiview_supported; + GLenum texture_target = use_multiview ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D; + if (rt->backbuffer_fbo == 0) { + glGenFramebuffers(1, &rt->backbuffer_fbo); + } + glBindFramebuffer(GL_FRAMEBUFFER, rt->backbuffer_fbo); + if (rt->backbuffer == 0 && uses_screen_texture) { + glGenTextures(1, &rt->backbuffer); + glBindTexture(texture_target, rt->backbuffer); + if (use_multiview) { + glTexImage3D(texture_target, 0, rt->color_internal_format, rt->size.x, rt->size.y, rt->view_count, 0, rt->color_format, rt->color_type, nullptr); + } else { + glTexImage2D(texture_target, 0, rt->color_internal_format, rt->size.x, rt->size.y, 0, rt->color_format, rt->color_type, nullptr); + } + + glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); +#ifndef IOS_ENABLED + if (use_multiview) { + glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, rt->backbuffer, 0, 0, rt->view_count); + } else { +#else + { +#endif + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->backbuffer, 0); + } + } + if (rt->backbuffer_depth == 0 && uses_depth_texture) { + glGenTextures(1, &rt->backbuffer_depth); + glBindTexture(texture_target, rt->backbuffer_depth); + if (use_multiview) { + glTexImage3D(texture_target, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, rt->view_count, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); + } else { + glTexImage2D(texture_target, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); + } + glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); +#ifndef IOS_ENABLED + if (use_multiview) { + glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, rt->backbuffer_depth, 0, 0, rt->view_count); + } else { +#else + { +#endif + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->backbuffer_depth, 0); + } + } +} void TextureStorage::_clear_render_target(RenderTarget *rt) { // there is nothing to clear when DIRECT_TO_SCREEN is used if (rt->direct_to_screen) { @@ -1848,6 +1905,10 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) { rt->backbuffer = 0; rt->backbuffer_fbo = 0; } + if (rt->backbuffer_depth != 0) { + glDeleteTextures(1, &rt->backbuffer_depth); + rt->backbuffer_depth = 0; + } _render_target_clear_sdf(rt); } diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h index fedda6b260a..9803e9548a2 100644 --- a/drivers/gles3/storage/texture_storage.h +++ b/drivers/gles3/storage/texture_storage.h @@ -345,6 +345,7 @@ struct RenderTarget { GLuint depth = 0; GLuint backbuffer_fbo = 0; GLuint backbuffer = 0; + GLuint backbuffer_depth = 0; GLuint color_internal_format = GL_RGBA8; GLuint color_format = GL_RGBA; @@ -604,6 +605,8 @@ public: RenderTarget *get_render_target(RID p_rid) { return render_target_owner.get_or_null(p_rid); }; bool owns_render_target(RID p_rid) { return render_target_owner.owns(p_rid); }; + void copy_scene_to_backbuffer(RenderTarget *rt, const bool uses_screen_texture, const bool uses_depth_texture); + virtual RID render_target_create() override; virtual void render_target_free(RID p_rid) override; From 3cae980c178905ac5be51c168698af7b355c4e9c Mon Sep 17 00:00:00 2001 From: Markus Sauermann <6299227+Sauermann@users.noreply.github.com> Date: Mon, 13 Feb 2023 00:34:16 +0100 Subject: [PATCH 06/73] Fix some ways to create inconsistent Viewport sizes In the editor, it was possible to set the size of a `SubViewport` even in cases where a parent `SubViewportContainer` had stretch enabled. This PR disables editing a `SubViewport.size` while the parent disallows it and it makes necessary adjustments during `NOTIFICATION_ENTER_TREE`. (cherry picked from commit 34a7fc744762dcf66eff7e3b5e4d46e09e7c0bdc) --- scene/gui/subviewport_container.cpp | 22 ++++++++-------------- scene/gui/subviewport_container.h | 1 + scene/main/viewport.cpp | 16 ++++++++++++++++ scene/main/viewport.h | 1 + 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/scene/gui/subviewport_container.cpp b/scene/gui/subviewport_container.cpp index f10e1c2cd18..f9e96a44edb 100644 --- a/scene/gui/subviewport_container.cpp +++ b/scene/gui/subviewport_container.cpp @@ -58,6 +58,7 @@ void SubViewportContainer::set_stretch(bool p_enable) { } stretch = p_enable; + recalc_force_viewport_sizes(); update_minimum_size(); queue_sort(); queue_redraw(); @@ -75,10 +76,16 @@ void SubViewportContainer::set_stretch_shrink(int p_shrink) { shrink = p_shrink; + recalc_force_viewport_sizes(); + queue_redraw(); +} + +void SubViewportContainer::recalc_force_viewport_sizes() { if (!stretch) { return; } + // If stretch is enabled, make sure that all child SubViwewports have the correct size. for (int i = 0; i < get_child_count(); i++) { SubViewport *c = Object::cast_to(get_child(i)); if (!c) { @@ -87,8 +94,6 @@ void SubViewportContainer::set_stretch_shrink(int p_shrink) { c->set_size_force(get_size() / shrink); } - - queue_redraw(); } int SubViewportContainer::get_stretch_shrink() const { @@ -106,18 +111,7 @@ Vector SubViewportContainer::get_allowed_size_flags_vertical() const { void SubViewportContainer::_notification(int p_what) { switch (p_what) { case NOTIFICATION_RESIZED: { - if (!stretch) { - return; - } - - for (int i = 0; i < get_child_count(); i++) { - SubViewport *c = Object::cast_to(get_child(i)); - if (!c) { - continue; - } - - c->set_size_force(get_size() / shrink); - } + recalc_force_viewport_sizes(); } break; case NOTIFICATION_ENTER_TREE: diff --git a/scene/gui/subviewport_container.h b/scene/gui/subviewport_container.h index d3236b0c4e9..c1a74e5b988 100644 --- a/scene/gui/subviewport_container.h +++ b/scene/gui/subviewport_container.h @@ -58,6 +58,7 @@ public: virtual void unhandled_input(const Ref &p_event) override; void set_stretch_shrink(int p_shrink); int get_stretch_shrink() const; + void recalc_force_viewport_sizes(); virtual Size2 get_minimum_size() const override; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 244e0d5b93d..8cd57536bf0 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -4281,6 +4281,11 @@ void SubViewport::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { RS::get_singleton()->viewport_set_active(get_viewport_rid(), true); + + SubViewportContainer *parent_svc = Object::cast_to(get_parent()); + if (parent_svc) { + parent_svc->recalc_force_viewport_sizes(); + } } break; case NOTIFICATION_EXIT_TREE: { @@ -4323,6 +4328,17 @@ void SubViewport::_bind_methods() { BIND_ENUM_CONSTANT(UPDATE_ALWAYS); } +void SubViewport::_validate_property(PropertyInfo &p_property) const { + if (p_property.name == "size") { + SubViewportContainer *parent_svc = Object::cast_to(get_parent()); + if (parent_svc && parent_svc->is_stretch_enabled()) { + p_property.usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY; + } else { + p_property.usage = PROPERTY_USAGE_DEFAULT; + } + } +} + SubViewport::SubViewport() { RS::get_singleton()->viewport_set_size(get_viewport_rid(), get_size().width, get_size().height); } diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 055fad5369a..5213c0db018 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -784,6 +784,7 @@ public: virtual Transform2D get_screen_transform_internal(bool p_absolute_position = false) const override; virtual Transform2D get_popup_base_transform() const override; + void _validate_property(PropertyInfo &p_property) const; SubViewport(); ~SubViewport(); }; From 24c4b5e8adb1084047ce695b90d34915cd497db0 Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Thu, 16 Feb 2023 13:43:32 +0200 Subject: [PATCH 07/73] [macOS] Re-add support for the _sc_ inside app bundle. Update docs. (cherry picked from commit 174e0837e0826179a2e51e581aa895cb5cc90885) --- doc/classes/EditorPaths.xml | 4 +++- editor/editor_paths.cpp | 14 ++++++++++---- modules/mono/godotsharp_dirs.cpp | 22 ++++++++++++---------- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/doc/classes/EditorPaths.xml b/doc/classes/EditorPaths.xml index 67332122085..0d02685f98f 100644 --- a/doc/classes/EditorPaths.xml +++ b/doc/classes/EditorPaths.xml @@ -64,7 +64,9 @@ Returns [code]true[/code] if the editor is marked as self-contained, [code]false[/code] otherwise. When self-contained mode is enabled, user configuration, data and cache files are saved in an [code]editor_data/[/code] folder next to the editor binary. This makes portable usage easier and ensures the Godot editor minimizes file writes outside its own folder. Self-contained mode is not available for exported projects. - Self-contained mode can be enabled by creating a file named [code]._sc_[/code] or [code]_sc_[/code] in the same folder as the editor binary while the editor is not running. See also [method get_self_contained_file]. + Self-contained mode can be enabled by creating a file named [code]._sc_[/code] or [code]_sc_[/code] in the same folder as the editor binary or macOS .app bundle while the editor is not running. See also [method get_self_contained_file]. + [b]Note:[/b] On macOS, quarantine flag should be manually removed before using self-contained mode, see [url=https://docs.godotengine.org/en/stable/tutorials/export/running_on_macos.html]Running on macOS[/url]. + [b]Note:[/b] On macOS, placing [code]_sc_[/code] or any other file inside .app bundle will break digital signature and make it non-portable, consider placing it in the same folder as the .app bundle instead. [b]Note:[/b] The Steam release of Godot uses self-contained mode by default. diff --git a/editor/editor_paths.cpp b/editor/editor_paths.cpp index 389c16fd66e..d5ba8418018 100644 --- a/editor/editor_paths.cpp +++ b/editor/editor_paths.cpp @@ -117,14 +117,20 @@ EditorPaths::EditorPaths() { // Self-contained mode if a `._sc_` or `_sc_` file is present in executable dir. String exe_path = OS::get_singleton()->get_executable_path().get_base_dir(); + Ref d = DirAccess::create_for_path(exe_path); + if (d->file_exists(exe_path + "/._sc_")) { + self_contained = true; + self_contained_file = exe_path + "/._sc_"; + } else if (d->file_exists(exe_path + "/_sc_")) { + self_contained = true; + self_contained_file = exe_path + "/_sc_"; + } // On macOS, look outside .app bundle, since .app bundle is read-only. + // Note: This will not work if Gatekeeper path randomization is active. if (OS::get_singleton()->has_feature("macos") && exe_path.ends_with("MacOS") && exe_path.path_join("..").simplify_path().ends_with("Contents")) { exe_path = exe_path.path_join("../../..").simplify_path(); - } - { - Ref d = DirAccess::create_for_path(exe_path); - + d = DirAccess::create_for_path(exe_path); if (d->file_exists(exe_path + "/._sc_")) { self_contained = true; self_contained_file = exe_path + "/._sc_"; diff --git a/modules/mono/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp index d08dedcfcbf..bff7d04b551 100644 --- a/modules/mono/godotsharp_dirs.cpp +++ b/modules/mono/godotsharp_dirs.cpp @@ -66,23 +66,25 @@ String _get_mono_user_dir() { if (EditorPaths::get_singleton()) { return EditorPaths::get_singleton()->get_data_dir().path_join("mono"); } else { - String settings_path; + String settings_path = OS::get_singleton()->get_data_path().path_join(OS::get_singleton()->get_godot_dir_name()); // Self-contained mode if a `._sc_` or `_sc_` file is present in executable dir. String exe_dir = OS::get_singleton()->get_executable_path().get_base_dir(); - - // On macOS, look outside .app bundle, since .app bundle is read-only. - if (OS::get_singleton()->has_feature("macos") && exe_dir.ends_with("MacOS") && exe_dir.path_join("..").simplify_path().ends_with("Contents")) { - exe_dir = exe_dir.path_join("../../..").simplify_path(); - } - Ref d = DirAccess::create_for_path(exe_dir); - if (d->file_exists("._sc_") || d->file_exists("_sc_")) { // contain yourself settings_path = exe_dir.path_join("editor_data"); - } else { - settings_path = OS::get_singleton()->get_data_path().path_join(OS::get_singleton()->get_godot_dir_name()); + } + + // On macOS, look outside .app bundle, since .app bundle is read-only. + // Note: This will not work if Gatekeeper path randomization is active. + if (OS::get_singleton()->has_feature("macos") && exe_dir.ends_with("MacOS") && exe_dir.path_join("..").simplify_path().ends_with("Contents")) { + exe_dir = exe_dir.path_join("../../..").simplify_path(); + d = DirAccess::create_for_path(exe_dir); + if (d->file_exists("._sc_") || d->file_exists("_sc_")) { + // contain yourself + settings_path = exe_dir.path_join("editor_data"); + } } return settings_path.path_join("mono"); From db3fadc560bae67b882fabf3022f8d72a3ab3561 Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Wed, 22 Feb 2023 00:08:05 +0200 Subject: [PATCH 08/73] Improve layout direction/locale automatic selection. (cherry picked from commit 82d7923c653b6328ba279bd4183b63b69e21edfc) --- core/config/project_settings.cpp | 1 + core/string/translation.cpp | 20 +++++++++++++++- doc/classes/ProjectSettings.xml | 5 +++- scene/gui/control.cpp | 41 ++++++++++++++++++++++---------- scene/main/window.cpp | 33 ++++++++++++++++++------- 5 files changed, 77 insertions(+), 23 deletions(-) diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 933b9891cc2..f3c0bc21539 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -1331,6 +1331,7 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/occlusion_culling/bvh_build_quality", PROPERTY_HINT_ENUM, "Low,Medium,High"), 2); GLOBAL_DEF(PropertyInfo(Variant::INT, "memory/limits/multithreaded_server/rid_pool_prealloc", PROPERTY_HINT_RANGE, "0,500,1"), 60); // No negative and limit to 500 due to crashes. GLOBAL_DEF_RST("internationalization/rendering/force_right_to_left_layout_direction", false); + GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "internationalization/rendering/root_node_layout_direction", PROPERTY_HINT_RANGE, "Based on Locale,Left-to-Right,Right-to-Left"), 0); GLOBAL_DEF(PropertyInfo(Variant::INT, "gui/timers/incremental_search_max_interval_msec", PROPERTY_HINT_RANGE, "0,10000,1,or_greater"), 2000); diff --git a/core/string/translation.cpp b/core/string/translation.cpp index b9d5d3b538e..160bad14ab1 100644 --- a/core/string/translation.cpp +++ b/core/string/translation.cpp @@ -712,7 +712,25 @@ String TranslationServer::get_tool_locale() { #else { #endif - return get_locale(); + // Look for best matching loaded translation. + String best_locale = "en"; + int best_score = 0; + + for (const Ref &E : translations) { + const Ref &t = E; + ERR_FAIL_COND_V(t.is_null(), best_locale); + String l = t->get_locale(); + + int score = compare_locales(locale, l); + if (score > 0 && score >= best_score) { + best_locale = l; + best_score = score; + if (score == 10) { + break; // Exact match, skip the rest. + } + } + } + return best_locale; } } diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 27bec07cba8..ed227047e5d 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -1199,7 +1199,10 @@ [b]Note:[/b] This property is only read when the project starts. To toggle pseudolocalization at run-time, use [member TranslationServer.pseudolocalization_enabled] instead. - Force layout direction and text writing direction to RTL for all locales. + Force layout direction and text writing direction to RTL for all controls. + + + Root node default layout direction. Specifies the [TextServer] to use. If left empty, the default will be used. diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index ec75fcb665b..10f9529ca96 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -2793,19 +2793,34 @@ bool Control::is_layout_rtl() const { if (data.is_rtl_dirty) { const_cast(this)->data.is_rtl_dirty = false; if (data.layout_dir == LAYOUT_DIRECTION_INHERITED) { - Window *parent_window = get_parent_window(); - Control *parent_control = get_parent_control(); - if (parent_control) { - const_cast(this)->data.is_rtl = parent_control->is_layout_rtl(); - } else if (parent_window) { - const_cast(this)->data.is_rtl = parent_window->is_layout_rtl(); - } else { - if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) { - const_cast(this)->data.is_rtl = true; - } else { - String locale = TranslationServer::get_singleton()->get_tool_locale(); - const_cast(this)->data.is_rtl = TS->is_locale_right_to_left(locale); + if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) { + const_cast(this)->data.is_rtl = true; + return data.is_rtl; + } + Node *parent_node = get_parent(); + while (parent_node) { + Control *parent_control = Object::cast_to(parent_node); + if (parent_control) { + const_cast(this)->data.is_rtl = parent_control->is_layout_rtl(); + return data.is_rtl; } + + Window *parent_window = Object::cast_to(parent_node); + if (parent_window) { + const_cast(this)->data.is_rtl = parent_window->is_layout_rtl(); + return data.is_rtl; + } + parent_node = parent_node->get_parent(); + } + + int root_dir = GLOBAL_GET(SNAME("internationalization/rendering/root_node_layout_direction")); + if (root_dir == 1) { + const_cast(this)->data.is_rtl = false; + } else if (root_dir == 2) { + const_cast(this)->data.is_rtl = true; + } else { + String locale = TranslationServer::get_singleton()->get_tool_locale(); + const_cast(this)->data.is_rtl = TS->is_locale_right_to_left(locale); } } else if (data.layout_dir == LAYOUT_DIRECTION_LOCALE) { if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) { @@ -3230,7 +3245,7 @@ void Control::_bind_methods() { ADD_GROUP("Layout", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_contents"), "set_clip_contents", "is_clipping_contents"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "custom_minimum_size", PROPERTY_HINT_NONE, "suffix:px"), "set_custom_minimum_size", "get_custom_minimum_size"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_direction", PROPERTY_HINT_ENUM, "Inherited,Locale,Left-to-Right,Right-to-Left"), "set_layout_direction", "get_layout_direction"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_direction", PROPERTY_HINT_ENUM, "Inherited,Based on Locale,Left-to-Right,Right-to-Left"), "set_layout_direction", "get_layout_direction"); ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_mode", PROPERTY_HINT_ENUM, "Position,Anchors,Container,Uncontrolled", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "_set_layout_mode", "_get_layout_mode"); ADD_PROPERTY_DEFAULT("layout_mode", LayoutMode::LAYOUT_MODE_POSITION); diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 9fb4ed458fe..5d3173a2a54 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -2116,22 +2116,39 @@ Window::LayoutDirection Window::get_layout_direction() const { bool Window::is_layout_rtl() const { if (layout_dir == LAYOUT_DIRECTION_INHERITED) { - Window *parent_w = Object::cast_to(get_parent()); - if (parent_w) { - return parent_w->is_layout_rtl(); - } else { - if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) { - return true; + if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) { + return true; + } + Node *parent_node = get_parent(); + while (parent_node) { + Control *parent_control = Object::cast_to(parent_node); + if (parent_control) { + return parent_control->is_layout_rtl(); } + + Window *parent_window = Object::cast_to(parent_node); + if (parent_window) { + return parent_window->is_layout_rtl(); + } + parent_node = parent_node->get_parent(); + } + + int root_dir = GLOBAL_GET(SNAME("internationalization/rendering/root_node_layout_direction")); + if (root_dir == 1) { + return false; + } else if (root_dir == 2) { + return true; + } else { String locale = TranslationServer::get_singleton()->get_tool_locale(); return TS->is_locale_right_to_left(locale); } } else if (layout_dir == LAYOUT_DIRECTION_LOCALE) { if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) { return true; + } else { + String locale = TranslationServer::get_singleton()->get_tool_locale(); + return TS->is_locale_right_to_left(locale); } - String locale = TranslationServer::get_singleton()->get_tool_locale(); - return TS->is_locale_right_to_left(locale); } else { return (layout_dir == LAYOUT_DIRECTION_RTL); } From 6ed9e03449097cea58189df53cd53aaf061b3f59 Mon Sep 17 00:00:00 2001 From: myaaaaaaaaa <103326468+myaaaaaaaaa@users.noreply.github.com> Date: Wed, 22 Feb 2023 16:49:48 -0500 Subject: [PATCH 09/73] Fix data races in startup/teardown (cherry picked from commit d337ed1c64de89ed410cfe208ea162e4cd4ae503) --- core/io/ip.cpp | 8 ++++---- core/os/thread.cpp | 6 +++--- core/os/thread.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/core/io/ip.cpp b/core/io/ip.cpp index 28b70371200..65728f34f6d 100644 --- a/core/io/ip.cpp +++ b/core/io/ip.cpp @@ -75,7 +75,7 @@ struct _IP_ResolverPrivate { Semaphore sem; Thread thread; - bool thread_abort = false; + SafeFlag thread_abort; void resolve_queues() { for (int i = 0; i < IP::RESOLVER_MAX_QUERIES; i++) { @@ -111,7 +111,7 @@ struct _IP_ResolverPrivate { static void _thread_function(void *self) { _IP_ResolverPrivate *ipr = static_cast<_IP_ResolverPrivate *>(self); - while (!ipr->thread_abort) { + while (!ipr->thread_abort.is_set()) { ipr->sem.wait(); ipr->resolve_queues(); } @@ -343,12 +343,12 @@ IP::IP() { singleton = this; resolver = memnew(_IP_ResolverPrivate); - resolver->thread_abort = false; + resolver->thread_abort.clear(); resolver->thread.start(_IP_ResolverPrivate::_thread_function, resolver); } IP::~IP() { - resolver->thread_abort = true; + resolver->thread_abort.set(); resolver->sem.post(); resolver->thread.wait_to_finish(); diff --git a/core/os/thread.cpp b/core/os/thread.cpp index 9d16392b2a5..92865576f3c 100644 --- a/core/os/thread.cpp +++ b/core/os/thread.cpp @@ -50,8 +50,8 @@ void Thread::_set_platform_functions(const PlatformFunctions &p_functions) { platform_functions = p_functions; } -void Thread::callback(Thread *p_self, const Settings &p_settings, Callback p_callback, void *p_userdata) { - Thread::caller_id = _thread_id_hash(p_self->thread.get_id()); +void Thread::callback(ID p_caller_id, const Settings &p_settings, Callback p_callback, void *p_userdata) { + Thread::caller_id = p_caller_id; if (platform_functions.set_priority) { platform_functions.set_priority(p_settings.priority); } @@ -79,7 +79,7 @@ void Thread::start(Thread::Callback p_callback, void *p_user, const Settings &p_ std::thread empty_thread; thread.swap(empty_thread); } - std::thread new_thread(&Thread::callback, this, p_settings, p_callback, p_user); + std::thread new_thread(&Thread::callback, _thread_id_hash(thread.get_id()), p_settings, p_callback, p_user); thread.swap(new_thread); id = _thread_id_hash(thread.get_id()); } diff --git a/core/os/thread.h b/core/os/thread.h index 3d4c48a760b..6eb21fba65b 100644 --- a/core/os/thread.h +++ b/core/os/thread.h @@ -82,7 +82,7 @@ private: static thread_local ID caller_id; std::thread thread; - static void callback(Thread *p_self, const Settings &p_settings, Thread::Callback p_callback, void *p_userdata); + static void callback(ID p_caller_id, const Settings &p_settings, Thread::Callback p_callback, void *p_userdata); static PlatformFunctions platform_functions; From bf8ab62ca3a197ebfa568b24b7c479c68bcf29af Mon Sep 17 00:00:00 2001 From: Michael Alexsander Date: Thu, 23 Feb 2023 01:40:27 -0300 Subject: [PATCH 10/73] Fix `GraphNode` resizing when its bottom border is too thin (cherry picked from commit c567a853db43c7c3ac463f775373ca65f98f0896) --- scene/gui/graph_edit.cpp | 42 ++++++++++++++++++++++++---------------- scene/gui/graph_node.cpp | 8 ++++---- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 58b820c31ff..9c0c25b1acb 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -839,6 +839,14 @@ bool GraphEdit::is_in_input_hotzone(GraphNode *p_node, int p_port, const Vector2 } bool GraphEdit::is_in_output_hotzone(GraphNode *p_node, int p_port, const Vector2 &p_mouse_pos, const Vector2i &p_port_size) { + if (p_node->is_resizable()) { + Ref resizer = p_node->get_theme_icon(SNAME("resizer")); + Rect2 resizer_rect = Rect2(p_node->get_position() / zoom + p_node->get_size() - resizer->get_size(), resizer->get_size()); + if (resizer_rect.has_point(p_mouse_pos)) { + return false; + } + } + bool success; if (GDVIRTUAL_CALL(_is_in_output_hotzone, p_node, p_port, p_mouse_pos, success)) { return success; @@ -848,10 +856,10 @@ bool GraphEdit::is_in_output_hotzone(GraphNode *p_node, int p_port, const Vector } } -bool GraphEdit::is_in_port_hotzone(const Vector2 &pos, const Vector2 &p_mouse_pos, const Vector2i &p_port_size, bool p_left) { +bool GraphEdit::is_in_port_hotzone(const Vector2 &p_pos, const Vector2 &p_mouse_pos, const Vector2i &p_port_size, bool p_left) { Rect2 hotzone = Rect2( - pos.x - (p_left ? port_hotzone_outer_extent : port_hotzone_inner_extent), - pos.y - p_port_size.height / 2.0, + p_pos.x - (p_left ? port_hotzone_outer_extent : port_hotzone_inner_extent), + p_pos.y - p_port_size.height / 2.0, port_hotzone_inner_extent + port_hotzone_outer_extent, p_port_size.height); @@ -1175,9 +1183,9 @@ void GraphEdit::gui_input(const Ref &p_ev) { minimap->queue_redraw(); } - Ref b = p_ev; - if (b.is_valid()) { - if (b->get_button_index() == MouseButton::RIGHT && b->is_pressed()) { + Ref mb = p_ev; + if (mb.is_valid()) { + if (mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed()) { if (box_selecting) { box_selecting = false; for (int i = get_child_count() - 1; i >= 0; i--) { @@ -1194,12 +1202,12 @@ void GraphEdit::gui_input(const Ref &p_ev) { if (connecting) { force_connection_drag_end(); } else { - emit_signal(SNAME("popup_request"), b->get_position()); + emit_signal(SNAME("popup_request"), mb->get_position()); } } } - if (b->get_button_index() == MouseButton::LEFT && !b->is_pressed() && dragging) { + if (mb->get_button_index() == MouseButton::LEFT && !mb->is_pressed() && dragging) { if (!just_selected && drag_accum == Vector2() && Input::get_singleton()->is_key_pressed(Key::CTRL)) { //deselect current node for (int i = get_child_count() - 1; i >= 0; i--) { @@ -1208,7 +1216,7 @@ void GraphEdit::gui_input(const Ref &p_ev) { if (gn) { Rect2 r = gn->get_rect(); r.size *= zoom; - if (r.has_point(b->get_position())) { + if (r.has_point(mb->get_position())) { gn->set_selected(false); } } @@ -1240,7 +1248,7 @@ void GraphEdit::gui_input(const Ref &p_ev) { connections_layer->queue_redraw(); } - if (b->get_button_index() == MouseButton::LEFT && b->is_pressed()) { + if (mb->get_button_index() == MouseButton::LEFT && mb->is_pressed()) { GraphNode *gn = nullptr; // Find node which was clicked on. @@ -1255,14 +1263,14 @@ void GraphEdit::gui_input(const Ref &p_ev) { continue; } - if (gn_selected->has_point((b->get_position() - gn_selected->get_position()) / zoom)) { + if (gn_selected->has_point((mb->get_position() - gn_selected->get_position()) / zoom)) { gn = gn_selected; break; } } if (gn) { - if (_filter_input(b->get_position())) { + if (_filter_input(mb->get_position())) { return; } @@ -1297,7 +1305,7 @@ void GraphEdit::gui_input(const Ref &p_ev) { } } else { - if (_filter_input(b->get_position())) { + if (_filter_input(mb->get_position())) { return; } if (panner->is_panning()) { @@ -1306,8 +1314,8 @@ void GraphEdit::gui_input(const Ref &p_ev) { // Left-clicked on empty space, start box select. box_selecting = true; - box_selecting_from = b->get_position(); - if (b->is_ctrl_pressed()) { + box_selecting_from = mb->get_position(); + if (mb->is_ctrl_pressed()) { box_selection_mode_additive = true; previous_selected.clear(); for (int i = get_child_count() - 1; i >= 0; i--) { @@ -1318,7 +1326,7 @@ void GraphEdit::gui_input(const Ref &p_ev) { previous_selected.push_back(gn2); } - } else if (b->is_shift_pressed()) { + } else if (mb->is_shift_pressed()) { box_selection_mode_additive = false; previous_selected.clear(); for (int i = get_child_count() - 1; i >= 0; i--) { @@ -1344,7 +1352,7 @@ void GraphEdit::gui_input(const Ref &p_ev) { } } - if (b->get_button_index() == MouseButton::LEFT && !b->is_pressed() && box_selecting) { + if (mb->get_button_index() == MouseButton::LEFT && !mb->is_pressed() && box_selecting) { // Box selection ended. Nodes were selected during mouse movement. box_selecting = false; box_selecting_rect = Rect2(); diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index f8d2ff0d2ca..7d9cdd62ff8 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -805,13 +805,13 @@ void GraphNode::_connpos_update() { Size2i size = c->get_rect().size; int y = sb->get_margin(SIDE_TOP) + vofs; - int h = size.y; + int h = size.height; if (slot_info.has(idx)) { if (slot_info[idx].enable_left) { PortCache cc; cc.position = Point2i(edgeofs, y + h / 2); - cc.height = size.height; + cc.height = h; cc.slot_idx = idx; cc.type = slot_info[idx].type_left; @@ -822,7 +822,7 @@ void GraphNode::_connpos_update() { if (slot_info[idx].enable_right) { PortCache cc; cc.position = Point2i(get_size().width - edgeofs, y + h / 2); - cc.height = size.height; + cc.height = h; cc.slot_idx = idx; cc.type = slot_info[idx].type_right; @@ -833,7 +833,7 @@ void GraphNode::_connpos_update() { } vofs += sep; - vofs += size.y; + vofs += h; idx++; } From 149f16b2fa2259fff81e9222f0bfcf9da7d0af32 Mon Sep 17 00:00:00 2001 From: RandomCatDude Date: Sat, 25 Feb 2023 16:28:06 +0500 Subject: [PATCH 11/73] fix spotlight shadows in volumetric fog (cherry picked from commit 59c31004f8c6feed601f2bfeedb86959563a4ef0) --- .../environment/volumetric_fog_process.glsl | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl index 28507e6c122..f961249dce0 100644 --- a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl @@ -585,23 +585,14 @@ void main() { if (spot_lights.data[light_index].shadow_opacity > 0.001) { //has shadow vec4 uv_rect = spot_lights.data[light_index].atlas_rect; - vec2 flip_offset = spot_lights.data[light_index].direction.xy; - vec3 local_vert = (spot_lights.data[light_index].shadow_matrix * vec4(view_pos, 1.0)).xyz; + vec4 v = vec4(view_pos, 1.0); - float shadow_len = length(local_vert); //need to remember shadow len from here - vec3 shadow_sample = normalize(local_vert); + vec4 splane = (spot_lights.data[light_index].shadow_matrix * v); + splane.z -= spot_lights.data[light_index].shadow_bias / (d * spot_lights.data[light_index].inv_radius); + splane /= splane.w; - if (shadow_sample.z >= 0.0) { - uv_rect.xy += flip_offset; - } - - shadow_sample.z = 1.0 + abs(shadow_sample.z); - vec3 pos = vec3(shadow_sample.xy / shadow_sample.z, shadow_len - spot_lights.data[light_index].shadow_bias); - pos.z *= spot_lights.data[light_index].inv_radius; - - pos.xy = pos.xy * 0.5 + 0.5; - pos.xy = uv_rect.xy + pos.xy * uv_rect.zw; + vec3 pos = vec3(splane.xy * spot_lights.data[light_index].atlas_rect.zw + spot_lights.data[light_index].atlas_rect.xy, splane.z); float depth = texture(sampler2D(shadow_atlas, linear_sampler), pos.xy).r; From ff125a638ad9cdeb72e1bdd889d1fc8b3a8538fd Mon Sep 17 00:00:00 2001 From: LandoUWB Date: Sat, 25 Feb 2023 23:39:43 -0800 Subject: [PATCH 12/73] Commit Fix for GLES3 point size not working (cherry picked from commit f23f0a27c11334c73b09ce86add8a6511010696f) --- drivers/gles3/rasterizer_scene_gles3.cpp | 3 +++ drivers/gles3/storage/material_storage.cpp | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index eb9ca49c5d4..b3d6b01c6cc 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -2228,6 +2228,9 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params, } RS::PrimitiveType primitive = surf->primitive; + if (shader->uses_point_size) { + primitive = RS::PRIMITIVE_POINTS; + } static const GLenum prim[5] = { GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP }; GLenum primitive_gl = prim[int(primitive)]; diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index 847ae140419..1736ad1d424 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -1510,7 +1510,7 @@ MaterialStorage::MaterialStorage() { actions.renames["LIGHT_VERTEX"] = "light_vertex"; actions.renames["SHADOW_VERTEX"] = "shadow_vertex"; actions.renames["UV"] = "uv"; - actions.renames["POINT_SIZE"] = "gl_PointSize"; + actions.renames["POINT_SIZE"] = "point_size"; actions.renames["MODEL_MATRIX"] = "model_matrix"; actions.renames["CANVAS_MATRIX"] = "canvas_transform"; @@ -1591,7 +1591,7 @@ MaterialStorage::MaterialStorage() { actions.renames["UV"] = "uv_interp"; actions.renames["UV2"] = "uv2_interp"; actions.renames["COLOR"] = "color_interp"; - actions.renames["POINT_SIZE"] = "gl_PointSize"; + actions.renames["POINT_SIZE"] = "point_size"; actions.renames["INSTANCE_ID"] = "gl_InstanceID"; actions.renames["VERTEX_ID"] = "gl_VertexID"; From 559d09c14073687da9a9373429b2f2888f8c5b6c Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Sun, 26 Feb 2023 17:55:04 +0200 Subject: [PATCH 13/73] [TextServer] Add mutex for FreeType face creation/deletion operations. (cherry picked from commit c950a1ab9479e53f8b91d457f44cea9246e24e4e) --- modules/text_server_adv/text_server_adv.cpp | 77 ++++++++++++--------- modules/text_server_adv/text_server_adv.h | 2 + modules/text_server_fb/text_server_fb.cpp | 77 ++++++++++++--------- modules/text_server_fb/text_server_fb.h | 2 + 4 files changed, 92 insertions(+), 66 deletions(-) diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index 3463cb5d9d4..3cf6288fef2 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -386,6 +386,8 @@ int64_t TextServerAdvanced::_get_features() const { void TextServerAdvanced::_free_rid(const RID &p_rid) { _THREAD_SAFE_METHOD_ if (font_owner.owns(p_rid)) { + MutexLock ftlock(ft_mutex); + FontAdvanced *fd = font_owner.get_or_null(p_rid); { MutexLock lock(fd->mutex); @@ -1321,45 +1323,48 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f // Init dynamic font. #ifdef MODULE_FREETYPE_ENABLED int error = 0; - if (!ft_library) { - error = FT_Init_FreeType(&ft_library); - if (error != 0) { - memdelete(fd); - ERR_FAIL_V_MSG(false, "FreeType: Error initializing library: '" + String(FT_Error_String(error)) + "'."); - } + { + MutexLock ftlock(ft_mutex); + if (!ft_library) { + error = FT_Init_FreeType(&ft_library); + if (error != 0) { + memdelete(fd); + ERR_FAIL_V_MSG(false, "FreeType: Error initializing library: '" + String(FT_Error_String(error)) + "'."); + } #ifdef MODULE_SVG_ENABLED - FT_Property_Set(ft_library, "ot-svg", "svg-hooks", get_tvg_svg_in_ot_hooks()); + FT_Property_Set(ft_library, "ot-svg", "svg-hooks", get_tvg_svg_in_ot_hooks()); #endif - } + } - memset(&fd->stream, 0, sizeof(FT_StreamRec)); - fd->stream.base = (unsigned char *)p_font_data->data_ptr; - fd->stream.size = p_font_data->data_size; - fd->stream.pos = 0; + memset(&fd->stream, 0, sizeof(FT_StreamRec)); + fd->stream.base = (unsigned char *)p_font_data->data_ptr; + fd->stream.size = p_font_data->data_size; + fd->stream.pos = 0; - FT_Open_Args fargs; - memset(&fargs, 0, sizeof(FT_Open_Args)); - fargs.memory_base = (unsigned char *)p_font_data->data_ptr; - fargs.memory_size = p_font_data->data_size; - fargs.flags = FT_OPEN_MEMORY; - fargs.stream = &fd->stream; + FT_Open_Args fargs; + memset(&fargs, 0, sizeof(FT_Open_Args)); + fargs.memory_base = (unsigned char *)p_font_data->data_ptr; + fargs.memory_size = p_font_data->data_size; + fargs.flags = FT_OPEN_MEMORY; + fargs.stream = &fd->stream; - int max_index = 0; - FT_Face tmp_face = nullptr; - error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face); - if (tmp_face && error == 0) { - max_index = tmp_face->num_faces - 1; - } - if (tmp_face) { - FT_Done_Face(tmp_face); - } + int max_index = 0; + FT_Face tmp_face = nullptr; + error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face); + if (tmp_face && error == 0) { + max_index = tmp_face->num_faces - 1; + } + if (tmp_face) { + FT_Done_Face(tmp_face); + } - error = FT_Open_Face(ft_library, &fargs, CLAMP(p_font_data->face_index, 0, max_index), &fd->face); - if (error) { - FT_Done_Face(fd->face); - fd->face = nullptr; - memdelete(fd); - ERR_FAIL_V_MSG(false, "FreeType: Error loading font: '" + String(FT_Error_String(error)) + "'."); + error = FT_Open_Face(ft_library, &fargs, CLAMP(p_font_data->face_index, 0, max_index), &fd->face); + if (error) { + FT_Done_Face(fd->face); + fd->face = nullptr; + memdelete(fd); + ERR_FAIL_V_MSG(false, "FreeType: Error loading font: '" + String(FT_Error_String(error)) + "'."); + } } if (p_font_data->msdf) { @@ -1788,6 +1793,8 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f } _FORCE_INLINE_ void TextServerAdvanced::_font_clear_cache(FontAdvanced *p_font_data) { + MutexLock ftlock(ft_mutex); + for (const KeyValue &E : p_font_data->cache) { memdelete(E.value); } @@ -1894,6 +1901,8 @@ int64_t TextServerAdvanced::_font_get_face_count(const RID &p_font_rid) const { fargs.flags = FT_OPEN_MEMORY; fargs.stream = &stream; + MutexLock ftlock(ft_mutex); + FT_Face tmp_face = nullptr; error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face); if (error == 0) { @@ -2285,6 +2294,7 @@ void TextServerAdvanced::_font_clear_size_cache(const RID &p_font_rid) { ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); + MutexLock ftlock(ft_mutex); for (const KeyValue &E : fd->cache) { memdelete(E.value); } @@ -2296,6 +2306,7 @@ void TextServerAdvanced::_font_remove_size_cache(const RID &p_font_rid, const Ve ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); + MutexLock ftlock(ft_mutex); if (fd->cache.has(p_size)) { memdelete(fd->cache[p_size]); fd->cache.erase(p_size); diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h index f092fa8ccab..ce08cf7694c 100644 --- a/modules/text_server_adv/text_server_adv.h +++ b/modules/text_server_adv/text_server_adv.h @@ -616,6 +616,8 @@ class TextServerAdvanced : public TextServerExtension { _FORCE_INLINE_ void _add_featuers(const Dictionary &p_source, Vector &r_ftrs); + Mutex ft_mutex; + // HarfBuzz bitmap font interface. static hb_font_funcs_t *funcs; diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp index 15124ad4884..86877262876 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -113,6 +113,8 @@ int64_t TextServerFallback::_get_features() const { void TextServerFallback::_free_rid(const RID &p_rid) { _THREAD_SAFE_METHOD_ if (font_owner.owns(p_rid)) { + MutexLock ftlock(ft_mutex); + FontFallback *fd = font_owner.get_or_null(p_rid); { MutexLock lock(fd->mutex); @@ -760,45 +762,48 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontFallback *p_f // Init dynamic font. #ifdef MODULE_FREETYPE_ENABLED int error = 0; - if (!ft_library) { - error = FT_Init_FreeType(&ft_library); - if (error != 0) { - memdelete(fd); - ERR_FAIL_V_MSG(false, "FreeType: Error initializing library: '" + String(FT_Error_String(error)) + "'."); - } + { + MutexLock ftlock(ft_mutex); + if (!ft_library) { + error = FT_Init_FreeType(&ft_library); + if (error != 0) { + memdelete(fd); + ERR_FAIL_V_MSG(false, "FreeType: Error initializing library: '" + String(FT_Error_String(error)) + "'."); + } #ifdef MODULE_SVG_ENABLED - FT_Property_Set(ft_library, "ot-svg", "svg-hooks", get_tvg_svg_in_ot_hooks()); + FT_Property_Set(ft_library, "ot-svg", "svg-hooks", get_tvg_svg_in_ot_hooks()); #endif - } + } - memset(&fd->stream, 0, sizeof(FT_StreamRec)); - fd->stream.base = (unsigned char *)p_font_data->data_ptr; - fd->stream.size = p_font_data->data_size; - fd->stream.pos = 0; + memset(&fd->stream, 0, sizeof(FT_StreamRec)); + fd->stream.base = (unsigned char *)p_font_data->data_ptr; + fd->stream.size = p_font_data->data_size; + fd->stream.pos = 0; - FT_Open_Args fargs; - memset(&fargs, 0, sizeof(FT_Open_Args)); - fargs.memory_base = (unsigned char *)p_font_data->data_ptr; - fargs.memory_size = p_font_data->data_size; - fargs.flags = FT_OPEN_MEMORY; - fargs.stream = &fd->stream; + FT_Open_Args fargs; + memset(&fargs, 0, sizeof(FT_Open_Args)); + fargs.memory_base = (unsigned char *)p_font_data->data_ptr; + fargs.memory_size = p_font_data->data_size; + fargs.flags = FT_OPEN_MEMORY; + fargs.stream = &fd->stream; - int max_index = 0; - FT_Face tmp_face = nullptr; - error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face); - if (tmp_face && error == 0) { - max_index = tmp_face->num_faces - 1; - } - if (tmp_face) { - FT_Done_Face(tmp_face); - } + int max_index = 0; + FT_Face tmp_face = nullptr; + error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face); + if (tmp_face && error == 0) { + max_index = tmp_face->num_faces - 1; + } + if (tmp_face) { + FT_Done_Face(tmp_face); + } - error = FT_Open_Face(ft_library, &fargs, CLAMP(p_font_data->face_index, 0, max_index), &fd->face); - if (error) { - FT_Done_Face(fd->face); - fd->face = nullptr; - memdelete(fd); - ERR_FAIL_V_MSG(false, "FreeType: Error loading font: '" + String(FT_Error_String(error)) + "'."); + error = FT_Open_Face(ft_library, &fargs, CLAMP(p_font_data->face_index, 0, max_index), &fd->face); + if (error) { + FT_Done_Face(fd->face); + fd->face = nullptr; + memdelete(fd); + ERR_FAIL_V_MSG(false, "FreeType: Error loading font: '" + String(FT_Error_String(error)) + "'."); + } } if (p_font_data->msdf) { @@ -909,6 +914,8 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontFallback *p_f } _FORCE_INLINE_ void TextServerFallback::_font_clear_cache(FontFallback *p_font_data) { + MutexLock ftlock(ft_mutex); + for (const KeyValue &E : p_font_data->cache) { memdelete(E.value); } @@ -1012,6 +1019,8 @@ int64_t TextServerFallback::_font_get_face_count(const RID &p_font_rid) const { fargs.flags = FT_OPEN_MEMORY; fargs.stream = &stream; + MutexLock ftlock(ft_mutex); + FT_Face tmp_face = nullptr; error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face); if (error == 0) { @@ -1393,6 +1402,7 @@ void TextServerFallback::_font_clear_size_cache(const RID &p_font_rid) { ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); + MutexLock ftlock(ft_mutex); for (const KeyValue &E : fd->cache) { memdelete(E.value); } @@ -1404,6 +1414,7 @@ void TextServerFallback::_font_remove_size_cache(const RID &p_font_rid, const Ve ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); + MutexLock ftlock(ft_mutex); if (fd->cache.has(p_size)) { memdelete(fd->cache[p_size]); fd->cache.erase(p_size); diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h index 12ed21ee950..d9e471154da 100644 --- a/modules/text_server_fb/text_server_fb.h +++ b/modules/text_server_fb/text_server_fb.h @@ -531,6 +531,8 @@ class TextServerFallback : public TextServerExtension { void _realign(ShapedTextDataFallback *p_sd) const; + Mutex ft_mutex; + protected: static void _bind_methods(){}; From 7a3f8a83da792865d717cc2dd793ec24449ef6d7 Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Mon, 27 Feb 2023 17:00:38 +0200 Subject: [PATCH 14/73] Fix GDExtensions library export when multiple architectures are set. (cherry picked from commit c2d678a924b7722b6bc846d361cb309d261c6597) --- editor/plugins/gdextension_export_plugin.h | 133 +++++++++++++-------- 1 file changed, 80 insertions(+), 53 deletions(-) diff --git a/editor/plugins/gdextension_export_plugin.h b/editor/plugins/gdextension_export_plugin.h index f3d2867030d..d1c47ab14e1 100644 --- a/editor/plugins/gdextension_export_plugin.h +++ b/editor/plugins/gdextension_export_plugin.h @@ -54,68 +54,95 @@ void GDExtensionExportPlugin::_export_file(const String &p_path, const String &p String entry_symbol = config->get_value("configuration", "entry_symbol"); - PackedStringArray tags; - String library_path = GDExtension::find_extension_library( - p_path, config, [p_features](String p_feature) { return p_features.has(p_feature); }, &tags); - if (!library_path.is_empty()) { - add_shared_object(library_path, tags); + HashSet all_archs; + all_archs.insert("x86_32"); + all_archs.insert("x86_64"); + all_archs.insert("arm32"); + all_archs.insert("arm64"); + all_archs.insert("rv64"); + all_archs.insert("ppc32"); + all_archs.insert("ppc64"); + all_archs.insert("wasm32"); + all_archs.insert("universal"); - if (p_features.has("iOS") && (library_path.ends_with(".a") || library_path.ends_with(".xcframework"))) { - String additional_code = "extern void register_dynamic_symbol(char *name, void *address);\n" - "extern void add_ios_init_callback(void (*cb)());\n" - "\n" - "extern \"C\" void $ENTRY();\n" - "void $ENTRY_init() {\n" - " if (&$ENTRY) register_dynamic_symbol((char *)\"$ENTRY\", (void *)$ENTRY);\n" - "}\n" - "struct $ENTRY_struct {\n" - " $ENTRY_struct() {\n" - " add_ios_init_callback($ENTRY_init);\n" - " }\n" - "};\n" - "$ENTRY_struct $ENTRY_struct_instance;\n\n"; - additional_code = additional_code.replace("$ENTRY", entry_symbol); - add_ios_cpp_code(additional_code); - - String linker_flags = "-Wl,-U,_" + entry_symbol; - add_ios_linker_flags(linker_flags); + HashSet archs; + HashSet features_wo_arch; + for (const String &tag : p_features) { + if (all_archs.has(tag)) { + archs.insert(tag); + } else { + features_wo_arch.insert(tag); } - } else { - Vector features_vector; - for (const String &E : p_features) { - features_vector.append(E); - } - ERR_FAIL_MSG(vformat("No suitable library found for GDExtension: %s. Possible feature flags for your platform: %s", p_path, String(", ").join(features_vector))); } - List dependencies; - if (config->has_section("dependencies")) { - config->get_section_keys("dependencies", &dependencies); + if (archs.is_empty()) { + archs.insert("unknown_arch"); // Not archs specified, still try to match. } - for (const String &E : dependencies) { - Vector dependency_tags = E.split("."); - bool all_tags_met = true; - for (int i = 0; i < dependency_tags.size(); i++) { - String tag = dependency_tags[i].strip_edges(); - if (!p_features.has(tag)) { - all_tags_met = false; + for (const String &arch_tag : archs) { + PackedStringArray tags; + String library_path = GDExtension::find_extension_library( + p_path, config, [features_wo_arch, arch_tag](String p_feature) { return features_wo_arch.has(p_feature) || (p_feature == arch_tag); }, &tags); + if (!library_path.is_empty()) { + add_shared_object(library_path, tags); + + if (p_features.has("iOS") && (library_path.ends_with(".a") || library_path.ends_with(".xcframework"))) { + String additional_code = "extern void register_dynamic_symbol(char *name, void *address);\n" + "extern void add_ios_init_callback(void (*cb)());\n" + "\n" + "extern \"C\" void $ENTRY();\n" + "void $ENTRY_init() {\n" + " if (&$ENTRY) register_dynamic_symbol((char *)\"$ENTRY\", (void *)$ENTRY);\n" + "}\n" + "struct $ENTRY_struct {\n" + " $ENTRY_struct() {\n" + " add_ios_init_callback($ENTRY_init);\n" + " }\n" + "};\n" + "$ENTRY_struct $ENTRY_struct_instance;\n\n"; + additional_code = additional_code.replace("$ENTRY", entry_symbol); + add_ios_cpp_code(additional_code); + + String linker_flags = "-Wl,-U,_" + entry_symbol; + add_ios_linker_flags(linker_flags); + } + } else { + Vector features_vector; + for (const String &E : p_features) { + features_vector.append(E); + } + ERR_FAIL_MSG(vformat("No suitable library found for GDExtension: %s. Possible feature flags for your platform: %s", p_path, String(", ").join(features_vector))); + } + + List dependencies; + if (config->has_section("dependencies")) { + config->get_section_keys("dependencies", &dependencies); + } + + for (const String &E : dependencies) { + Vector dependency_tags = E.split("."); + bool all_tags_met = true; + for (int i = 0; i < dependency_tags.size(); i++) { + String tag = dependency_tags[i].strip_edges(); + if (!p_features.has(tag)) { + all_tags_met = false; + break; + } + } + + if (all_tags_met) { + Dictionary dependency = config->get_value("dependencies", E); + for (const Variant *key = dependency.next(nullptr); key; key = dependency.next(key)) { + String dependency_path = *key; + String target_path = dependency[*key]; + if (dependency_path.is_relative_path()) { + dependency_path = p_path.get_base_dir().path_join(dependency_path); + } + add_shared_object(dependency_path, dependency_tags, target_path); + } break; } } - - if (all_tags_met) { - Dictionary dependency = config->get_value("dependencies", E); - for (const Variant *key = dependency.next(nullptr); key; key = dependency.next(key)) { - String dependency_path = *key; - String target_path = dependency[*key]; - if (dependency_path.is_relative_path()) { - dependency_path = p_path.get_base_dir().path_join(dependency_path); - } - add_shared_object(dependency_path, dependency_tags, target_path); - } - break; - } } } From a94a2062af97f634f8192208a59f1656d1af680f Mon Sep 17 00:00:00 2001 From: Bastiaan Olij Date: Wed, 1 Mar 2023 20:02:25 +1100 Subject: [PATCH 15/73] Add XRServer.world_origin property (cherry picked from commit fd8f26f26e2f8875e4e305bc22f04f0deaf9a44c) --- doc/classes/XRServer.xml | 4 ++++ servers/xr_server.cpp | 3 +++ 2 files changed, 7 insertions(+) diff --git a/doc/classes/XRServer.xml b/doc/classes/XRServer.xml index d940ea41aca..c7ba94b1b46 100644 --- a/doc/classes/XRServer.xml +++ b/doc/classes/XRServer.xml @@ -108,6 +108,10 @@ The primary [XRInterface] currently bound to the [XRServer]. + + The current origin of our tracking space in the virtual world. This is used by the renderer to properly position the camera with new tracking data. + [b]Note:[/b] This property is managed by the current [XROrigin3D] node. It is exposed for access from GDExtensions. + Allows you to adjust the scale to your game's units. Most AR/VR platforms assume a scale of 1 game world unit = 1 real world meter. diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp index 85ef684d402..bab8e9ae4b1 100644 --- a/servers/xr_server.cpp +++ b/servers/xr_server.cpp @@ -52,11 +52,14 @@ XRServer *XRServer::get_singleton() { void XRServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_world_scale"), &XRServer::get_world_scale); ClassDB::bind_method(D_METHOD("set_world_scale", "scale"), &XRServer::set_world_scale); + ClassDB::bind_method(D_METHOD("get_world_origin"), &XRServer::get_world_origin); + ClassDB::bind_method(D_METHOD("set_world_origin", "world_origin"), &XRServer::set_world_origin); ClassDB::bind_method(D_METHOD("get_reference_frame"), &XRServer::get_reference_frame); ClassDB::bind_method(D_METHOD("center_on_hmd", "rotation_mode", "keep_height"), &XRServer::center_on_hmd); ClassDB::bind_method(D_METHOD("get_hmd_transform"), &XRServer::get_hmd_transform); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "world_scale"), "set_world_scale", "get_world_scale"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "world_origin"), "set_world_origin", "get_world_origin"); ClassDB::bind_method(D_METHOD("add_interface", "interface"), &XRServer::add_interface); ClassDB::bind_method(D_METHOD("get_interface_count"), &XRServer::get_interface_count); From 46d475b067dcab6929fa76d1aad9bc6b9453e22b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20J=2E=20Est=C3=A9banez?= Date: Wed, 1 Mar 2023 11:11:40 +0100 Subject: [PATCH 16/73] Fix crash in resource load (cherry picked from commit 047671df0f6a7a300b83f36b5d6110a8165b0dfd) --- core/io/resource_loader.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index c47f297a72b..d0448e86fca 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -492,13 +492,21 @@ Ref ResourceLoader::load_threaded_get(const String &p_path, Error *r_e print_lt("GET: load count: " + itos(thread_loading_count) + " / wait count: " + itos(thread_waiting_count) + " / suspended count: " + itos(thread_suspended_count) + " / active: " + itos(thread_loading_count - thread_suspended_count)); } + bool still_valid = true; + bool was_thread = load_task.thread; do { load_task.cond_var->wait(thread_load_lock); + if (!thread_load_tasks.has(local_path)) { //may have been erased during unlock and this was always an invalid call + still_valid = false; + break; + } } while (load_task.cond_var); // In case of spurious wakeup. - thread_suspended_count--; + if (was_thread) { + thread_suspended_count--; + } - if (!thread_load_tasks.has(local_path)) { //may have been erased during unlock and this was always an invalid call + if (!still_valid) { if (r_error) { *r_error = ERR_INVALID_PARAMETER; } From 2e37c05fe6aa16625b7e09f3c30c58804405da84 Mon Sep 17 00:00:00 2001 From: VolTer Date: Wed, 1 Mar 2023 21:08:51 +0100 Subject: [PATCH 17/73] Make GDScript number highlighting stricter (cherry picked from commit 952703d92155226137fc4bb53c61c8dbc7887ed7) --- .../gdscript/editor/gdscript_highlighter.cpp | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index 5883ec863d3..bba11363d55 100644 --- a/modules/gdscript/editor/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -294,17 +294,27 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l !(str[j] == '_' && (prev_is_digit || str[j - 1] == 'b' || str[j - 1] == 'x' || str[j - 1] == '.')) && !(str[j] == 'e' && (prev_is_digit || str[j - 1] == '_')) && !(str[j] == '.' && (prev_is_digit || (!prev_is_binary_op && (j > 0 && (str[j - 1] == '-' || str[j - 1] == '+' || str[j - 1] == '~'))))) && - !((str[j] == '-' || str[j] == '+' || str[j] == '~') && !prev_is_binary_op && str[j - 1] != 'e')) { - /* This condition continues Number highlighting in special cases. - 1st row: '+' or '-' after scientific notation; + !((str[j] == '-' || str[j] == '+' || str[j] == '~') && !is_binary_op && !prev_is_binary_op && str[j - 1] != 'e')) { + /* This condition continues number highlighting in special cases. + 1st row: '+' or '-' after scientific notation (like 3e-4); 2nd row: '_' as a numeric separator; 3rd row: Scientific notation 'e' and floating points; 4th row: Floating points inside the number, or leading if after a unary mathematical operator; - 5th row: Multiple unary mathematical operators */ + 5th row: Multiple unary mathematical operators (like ~-7)*/ in_number = false; } - } else if (!is_binary_op && (str[j] == '-' || str[j] == '+' || str[j] == '~' || (str[j] == '.' && str[j + 1] != '.' && (j == 0 || (j > 0 && str[j - 1] != '.'))))) { + } else if (str[j] == '.' && !is_binary_op && is_digit(str[j + 1]) && (j == 0 || (j > 0 && str[j - 1] != '.'))) { + // Start number highlighting from leading decimal points (like .42) in_number = true; + } else if ((str[j] == '-' || str[j] == '+' || str[j] == '~') && !is_binary_op) { + // Only start number highlighting on unary operators if a digit follows them. + int non_op = j + 1; + while (str[non_op] == '-' || str[non_op] == '+' || str[non_op] == '~') { + non_op++; + } + if (is_digit(str[non_op]) || (str[non_op] == '.' && non_op < line_length && is_digit(str[non_op + 1]))) { + in_number = true; + } } if (!in_word && is_unicode_identifier_start(str[j]) && !in_number) { From a397474bd0b37ad44e75fb124683b7e28b7ce9b5 Mon Sep 17 00:00:00 2001 From: Yuri Rubinsky Date: Thu, 2 Mar 2023 12:46:25 +0300 Subject: [PATCH 18/73] Fix randfn to prevent generating of nan values (cherry picked from commit d11bb866ffb1d5e0215ffc11dd6848a11976d90e) --- core/math/random_pcg.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/core/math/random_pcg.h b/core/math/random_pcg.h index fe40e7f76a7..cc22b23b70e 100644 --- a/core/math/random_pcg.h +++ b/core/math/random_pcg.h @@ -126,10 +126,18 @@ public: } _FORCE_INLINE_ double randfn(double p_mean, double p_deviation) { - return p_mean + p_deviation * (cos(Math_TAU * randd()) * sqrt(-2.0 * log(randd()))); // Box-Muller transform + double temp = randd(); + if (temp < CMP_EPSILON) { + temp += CMP_EPSILON; // To prevent generating of INF value in log function, resulting to return NaN value from this function. + } + return p_mean + p_deviation * (cos(Math_TAU * randd()) * sqrt(-2.0 * log(temp))); // Box-Muller transform. } _FORCE_INLINE_ float randfn(float p_mean, float p_deviation) { - return p_mean + p_deviation * (cos((float)Math_TAU * randf()) * sqrt(-2.0 * log(randf()))); // Box-Muller transform + float temp = randf(); + if (temp < CMP_EPSILON) { + temp += CMP_EPSILON; // To prevent generating of INF value in log function, resulting to return NaN value from this function. + } + return p_mean + p_deviation * (cos((float)Math_TAU * randf()) * sqrt(-2.0 * log(temp))); // Box-Muller transform. } double random(double p_from, double p_to); From c4618bcc1b37d1ce7600cd5abc4bd165a94fb1aa Mon Sep 17 00:00:00 2001 From: Raul Santos Date: Fri, 3 Mar 2023 18:17:17 +0100 Subject: [PATCH 19/73] C#: Encode GodotProjectDir as Base64 to prevent issues with special characters (cherry picked from commit f949e949913205fe413377e2dc37b84552c523e0) --- .../Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props | 1 + .../Godot.SourceGenerators.Sample.csproj | 1 + .../Godot.SourceGenerators.props | 1 + .../ScriptPathAttributeGenerator.cs | 13 ++++++++++--- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props index 0d0889c4913..eea7520b05c 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props @@ -14,6 +14,7 @@ $(MSBuildProjectDirectory) $([MSBuild]::EnsureTrailingSlash('$(GodotProjectDir)')) + $([MSBuild]::ConvertToBase64('$(GodotProjectDir)')) $(GodotProjectDir).godot\mono\temp\bin\ diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj index 8e78e0385da..2df838cfb8e 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj @@ -7,6 +7,7 @@ $(MSBuildProjectDirectory) + $([MSBuild]::ConvertToBase64('$(GodotProjectDir)')) $(DefineConstants);TOOLS diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.props b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.props index 7881ed0a8ce..2a8ae7f9583 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.props +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.props @@ -2,6 +2,7 @@ + diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs index eae7e41da80..d14e3c3781c 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs @@ -22,10 +22,17 @@ namespace Godot.SourceGenerators // NOTE: NotNullWhen diagnostics don't work on projects targeting .NET Standard 2.0 // ReSharper disable once ReplaceWithStringIsNullOrEmpty - if (!context.TryGetGlobalAnalyzerProperty("GodotProjectDir", out string? godotProjectDir) - || godotProjectDir!.Length == 0) + if (!context.TryGetGlobalAnalyzerProperty("GodotProjectDirBase64", out string? godotProjectDir) || godotProjectDir!.Length == 0) { - throw new InvalidOperationException("Property 'GodotProjectDir' is null or empty."); + if (!context.TryGetGlobalAnalyzerProperty("GodotProjectDir", out godotProjectDir) || godotProjectDir!.Length == 0) + { + throw new InvalidOperationException("Property 'GodotProjectDir' is null or empty."); + } + } + else + { + // Workaround for https://github.com/dotnet/roslyn/issues/51692 + godotProjectDir = Encoding.UTF8.GetString(Convert.FromBase64String(godotProjectDir)); } Dictionary> godotClasses = context From bb5a6e29ab3c4c87c5b912dbbde2977f7f9bf6d0 Mon Sep 17 00:00:00 2001 From: RedworkDE <10944644+RedworkDE@users.noreply.github.com> Date: Mon, 6 Mar 2023 11:54:42 +0100 Subject: [PATCH 20/73] C#: Fix building projects for MSBuild before 17.3 (cherry picked from commit 6019f497b83f71a8c26a4e3831824e22b614bb75) --- .../editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props | 9 ++++++++- .../Godot.SourceGenerators.Sample.csproj | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props index eea7520b05c..894053c5de1 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props @@ -14,7 +14,7 @@ $(MSBuildProjectDirectory) $([MSBuild]::EnsureTrailingSlash('$(GodotProjectDir)')) - $([MSBuild]::ConvertToBase64('$(GodotProjectDir)')) + $([MSBuild]::ConvertToBase64('$(GodotProjectDir)')) $(GodotProjectDir).godot\mono\temp\bin\ @@ -30,6 +30,13 @@ false + + + + + + + diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj index 2df838cfb8e..3f569ebac3f 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj @@ -7,7 +7,7 @@ $(MSBuildProjectDirectory) - $([MSBuild]::ConvertToBase64('$(GodotProjectDir)')) + $([MSBuild]::ConvertToBase64('$(GodotProjectDir)')) $(DefineConstants);TOOLS From 6782cd72912453dceff55fcf5fb7b71dfaf22bd4 Mon Sep 17 00:00:00 2001 From: bitsawer Date: Sat, 4 Mar 2023 16:38:35 +0200 Subject: [PATCH 21/73] Fix several clang-tidy bool literal conversion warnings (cherry picked from commit 1736137bc9505762fd74185a839fa100b8fd3465) --- core/typedefs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/typedefs.h b/core/typedefs.h index cd1367611ad..1dcba581886 100644 --- a/core/typedefs.h +++ b/core/typedefs.h @@ -305,9 +305,9 @@ struct BuildIndexSequence<0, Is...> : IndexSequence {}; #endif // Macro GD_IS_DEFINED() allows to check if a macro is defined. It needs to be defined to anything (say 1) to work. -#define __GDARG_PLACEHOLDER_1 0, +#define __GDARG_PLACEHOLDER_1 false, #define __gd_take_second_arg(__ignored, val, ...) val -#define ____gd_is_defined(arg1_or_junk) __gd_take_second_arg(arg1_or_junk 1, 0) +#define ____gd_is_defined(arg1_or_junk) __gd_take_second_arg(arg1_or_junk true, false) #define ___gd_is_defined(val) ____gd_is_defined(__GDARG_PLACEHOLDER_##val) #define GD_IS_DEFINED(x) ___gd_is_defined(x) From 865a0b45072e5749b6082e895d94c2ee94a6e3ea Mon Sep 17 00:00:00 2001 From: necrashter Date: Sun, 5 Mar 2023 00:37:49 +0300 Subject: [PATCH 22/73] Use the new API for virtual keyboard height detection on Android, bugfix (cherry picked from commit 61549edef0c4e8cadf3bf1847c29328b598a25ff) --- .../lib/src/org/godotengine/godot/Godot.java | 70 ++++++++++++++++--- 1 file changed, 62 insertions(+), 8 deletions(-) diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java index a03da7292bf..9b65a52b70d 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java @@ -74,10 +74,14 @@ import android.util.Log; import android.view.Display; import android.view.LayoutInflater; import android.view.Surface; +import android.view.SurfaceView; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; +import android.view.ViewTreeObserver; import android.view.Window; +import android.view.WindowInsets; +import android.view.WindowInsetsAnimation; import android.view.WindowManager; import android.widget.Button; import android.widget.FrameLayout; @@ -291,14 +295,64 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC editText.setView(mRenderView); io.setEdit(editText); - view.getViewTreeObserver().addOnGlobalLayoutListener(() -> { - Point fullSize = new Point(); - activity.getWindowManager().getDefaultDisplay().getSize(fullSize); - Rect gameSize = new Rect(); - mRenderView.getView().getWindowVisibleDisplayFrame(gameSize); - final int keyboardHeight = fullSize.y - gameSize.bottom; - GodotLib.setVirtualKeyboardHeight(keyboardHeight); - }); + // Listeners for keyboard height. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + // Report the height of virtual keyboard as it changes during the animation. + final View decorView = activity.getWindow().getDecorView(); + decorView.setWindowInsetsAnimationCallback(new WindowInsetsAnimation.Callback(WindowInsetsAnimation.Callback.DISPATCH_MODE_STOP) { + int startBottom, endBottom; + @Override + public void onPrepare(@NonNull WindowInsetsAnimation animation) { + startBottom = decorView.getRootWindowInsets().getInsets(WindowInsets.Type.ime()).bottom; + } + + @NonNull + @Override + public WindowInsetsAnimation.Bounds onStart(@NonNull WindowInsetsAnimation animation, @NonNull WindowInsetsAnimation.Bounds bounds) { + endBottom = decorView.getRootWindowInsets().getInsets(WindowInsets.Type.ime()).bottom; + return bounds; + } + + @NonNull + @Override + public WindowInsets onProgress(@NonNull WindowInsets windowInsets, @NonNull List list) { + // Find the IME animation. + WindowInsetsAnimation imeAnimation = null; + for (WindowInsetsAnimation animation : list) { + if ((animation.getTypeMask() & WindowInsets.Type.ime()) != 0) { + imeAnimation = animation; + break; + } + } + // Update keyboard height based on IME animation. + if (imeAnimation != null) { + float interpolatedFraction = imeAnimation.getInterpolatedFraction(); + // Linear interpolation between start and end values. + float keyboardHeight = startBottom * (1.0f - interpolatedFraction) + endBottom * interpolatedFraction; + GodotLib.setVirtualKeyboardHeight((int)keyboardHeight); + } + return windowInsets; + } + + @Override + public void onEnd(@NonNull WindowInsetsAnimation animation) { + } + }); + } else { + // Infer the virtual keyboard height using visible area. + view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + // Don't allocate a new Rect every time the callback is called. + final Rect visibleSize = new Rect(); + + @Override + public void onGlobalLayout() { + final SurfaceView view = mRenderView.getView(); + view.getWindowVisibleDisplayFrame(visibleSize); + final int keyboardHeight = view.getHeight() - visibleSize.bottom; + GodotLib.setVirtualKeyboardHeight(keyboardHeight); + } + }); + } mRenderView.queueOnRenderThread(() -> { for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) { From 0dab32f317c4520ae2463f33d61381214a9c87c5 Mon Sep 17 00:00:00 2001 From: stmSi Date: Tue, 7 Mar 2023 02:49:14 +0630 Subject: [PATCH 23/73] Fix `Find in Files` Search Results cannot open builtin script (cherry picked from commit f1f4c5b10b934402acdfa279782a93cbe4403740) --- editor/plugins/script_editor_plugin.cpp | 65 +++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index a584d357cd3..49c815526b7 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -3586,7 +3586,72 @@ void ScriptEditor::_on_find_in_files_result_selected(String fpath, int line_numb shader_editor->get_shader_editor(res)->goto_line_selection(line_number - 1, begin, end); return; } else if (fpath.get_extension() == "tscn") { + Ref f = FileAccess::open(fpath, FileAccess::READ); + bool is_script_found = false; + + // Starting from top of the tscn file. + int scr_start_line = 1; + + String scr_header = "[sub_resource type=\"GDScript\" id=\""; + String scr_id = ""; + String line = ""; + + int l = 0; + + while (!f->eof_reached()) { + line = f->get_line(); + l++; + + if (!line.begins_with(scr_header)) { + continue; + } + + // Found the end of the script. + scr_id = line.get_slice(scr_header, 1); + scr_id = scr_id.get_slice("\"", 0); + + scr_start_line = l + 1; + int scr_line_count = 0; + + do { + line = f->get_line(); + l++; + String strline = line.strip_edges(); + + if (strline.ends_with("\"") && !strline.ends_with("\\\"")) { + // Found the end of script. + break; + } + scr_line_count++; + + } while (!f->eof_reached()); + + if (line_number > scr_start_line + scr_line_count) { + // Find in another built-in GDScript. + continue; + } + + // Real line number of the built-in script. + line_number = line_number - scr_start_line; + + is_script_found = true; + break; + } + EditorNode::get_singleton()->load_scene(fpath); + + if (is_script_found && !scr_id.is_empty()) { + Ref