From d36ab98414a4aba8c679aa8c3e9f0b6cae97db76 Mon Sep 17 00:00:00 2001 From: "Ron B. Yeh" Date: Thu, 21 Sep 2023 17:08:42 -0700 Subject: [PATCH 001/144] Remove unnecessary spaces. --- modules/mono/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/mono/README.md b/modules/mono/README.md index 74b4531dfb..e8798de149 100644 --- a/modules/mono/README.md +++ b/modules/mono/README.md @@ -20,7 +20,7 @@ MSBuild project SDK as NuGet packages. This is all transparent to the user, but it can make things complicated during development. In order to use Godot with a development of those packages, we must create -a local NuGet source where MSBuild can find them. This can be done with +a local NuGet source where MSBuild can find them. This can be done with the .NET CLI: ```sh @@ -28,7 +28,7 @@ dotnet nuget add source ~/MyLocalNugetSource --name MyLocalNugetSource ``` The Godot NuGet packages must be added to that local source. Additionally, -we must make sure there are no other versions of the package in the NuGet +we must make sure there are no other versions of the package in the NuGet cache, as MSBuild may pick one of those instead. In order to simplify this process, the `build_assemblies.py` script provides From 96a6499da269d6f71ee976df26fc3806b2b04916 Mon Sep 17 00:00:00 2001 From: aaronp64 Date: Thu, 6 Mar 2025 13:01:27 -0500 Subject: [PATCH 002/144] Link Script method documentation to details about returned dictionaries Added links for get_script_method_list(), get_script_property_list(), and get_script_signal_list() to corresponding Object method documentation that includes details about the entries in the returned dictionaries. --- doc/classes/Script.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/classes/Script.xml b/doc/classes/Script.xml index 80aad9d30d..d8d6f4fd21 100644 --- a/doc/classes/Script.xml +++ b/doc/classes/Script.xml @@ -74,18 +74,21 @@ Returns the list of methods in this [Script]. + [b]Note:[/b] The dictionaries returned by this method are formatted identically to those returned by [method Object.get_method_list]. Returns the list of properties in this [Script]. + [b]Note:[/b] The dictionaries returned by this method are formatted identically to those returned by [method Object.get_property_list]. Returns the list of user signals defined in this [Script]. + [b]Note:[/b] The dictionaries returned by this method are formatted identically to those returned by [method Object.get_signal_list]. From 044444f2e2774f397e605b20aeb00dfa42f008b4 Mon Sep 17 00:00:00 2001 From: DeeJayLSP Date: Wed, 19 Mar 2025 13:19:10 -0300 Subject: [PATCH 003/144] Reduce memory overhead of `save_to_wav` --- scene/resources/audio_stream_wav.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scene/resources/audio_stream_wav.cpp b/scene/resources/audio_stream_wav.cpp index 9e262eeaae..5b20737c0c 100644 --- a/scene/resources/audio_stream_wav.cpp +++ b/scene/resources/audio_stream_wav.cpp @@ -580,8 +580,7 @@ Error AudioStreamWAV::save_to_wav(const String &p_path) { file->store_32(sub_chunk_2_size); //Subchunk2Size // Add data - Vector stream_data = get_data(); - const uint8_t *read_data = stream_data.ptr(); + const uint8_t *read_data = data.ptr(); switch (format) { case AudioStreamWAV::FORMAT_8_BITS: for (unsigned int i = 0; i < data_bytes; i++) { From 4fd95613a4a35e67392c0afcf2be49799c7f0d6f Mon Sep 17 00:00:00 2001 From: Matt Enad Date: Thu, 3 Apr 2025 22:44:56 -0400 Subject: [PATCH 004/144] Update RichTextLabel alignment documentation --- doc/classes/RichTextLabel.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml index 8ef40f777b..7c48be5b39 100644 --- a/doc/classes/RichTextLabel.xml +++ b/doc/classes/RichTextLabel.xml @@ -9,7 +9,7 @@ [b]Note:[/b] Assignments to [member text] clear the tag stack and reconstruct it from the property's contents. Any edits made to [member text] will erase previous edits made from other manual sources such as [method append_text] and the [code]push_*[/code] / [method pop] methods. [b]Note:[/b] RichTextLabel doesn't support entangled BBCode tags. For example, instead of using [code skip-lint][b]bold[i]bold italic[/b]italic[/i][/code], use [code skip-lint][b]bold[i]bold italic[/i][/b][i]italic[/i][/code]. [b]Note:[/b] [code]push_*/pop_*[/code] functions won't affect BBCode. - [b]Note:[/b] Unlike [Label], [RichTextLabel] doesn't have a [i]property[/i] to horizontally align text to the center. Instead, enable [member bbcode_enabled] and surround the text in a [code skip-lint][center][/code] tag as follows: [code skip-lint][center]Example[/center][/code]. There is currently no built-in way to vertically align text either, but this can be emulated by relying on anchors/containers and the [member fit_content] property. + [b]Note:[/b] While [member bbcode_enabled] is enabled, alignment tags such as [code skip-lint][center][/code] will take priority over the [member horizontal_alignment] setting which determines the default text alignment. $DOCS_URL/tutorials/ui/bbcode_in_richtextlabel.html From b2bd8e4d0624a05bb6713c59be7e2417a3f2b03a Mon Sep 17 00:00:00 2001 From: Haoyu Qiu Date: Thu, 10 Apr 2025 23:50:02 +0800 Subject: [PATCH 005/144] Relax the range hint for canvas layer properties --- doc/classes/CanvasLayer.xml | 1 + doc/classes/RenderingServer.xml | 7 +++++++ scene/2d/light_2d.cpp | 4 ++-- scene/main/canvas_layer.cpp | 2 +- servers/rendering_server.cpp | 2 ++ servers/rendering_server.h | 2 ++ 6 files changed, 15 insertions(+), 3 deletions(-) diff --git a/doc/classes/CanvasLayer.xml b/doc/classes/CanvasLayer.xml index 427cabe781..66839e6327 100644 --- a/doc/classes/CanvasLayer.xml +++ b/doc/classes/CanvasLayer.xml @@ -54,6 +54,7 @@ Layer index for draw order. Lower values are drawn behind higher values. [b]Note:[/b] If multiple CanvasLayers have the same layer index, [CanvasItem] children of one CanvasLayer are drawn behind the [CanvasItem] children of the other CanvasLayer. Which CanvasLayer is drawn in front is non-deterministic. + [b]Note:[/b] The layer index should be between [constant RenderingServer.CANVAS_LAYER_MIN] and [constant RenderingServer.CANVAS_LAYER_MAX] (inclusive). Any other value will wrap around. The layer's base offset. diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 048b024e62..3c6f1668d7 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -3969,6 +3969,7 @@ Sets the stacking order for a viewport's canvas. [param layer] is the actual canvas layer, while [param sublayer] specifies the stacking order of the canvas among those in the same layer. + [b]Note:[/b] [param layer] should be between [constant CANVAS_LAYER_MIN] and [constant CANVAS_LAYER_MAX] (inclusive). Any other value will wrap around. @@ -4466,6 +4467,12 @@ The maximum Z-layer for canvas items. + + The minimum canvas layer. + + + The maximum canvas layer. + The maximum number of glow levels that can be used with the glow post-processing effect. diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index e354cd4c61..62473bfe20 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -310,8 +310,8 @@ void Light2D::_bind_methods() { ADD_GROUP("Range", "range_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "range_z_min", PROPERTY_HINT_RANGE, itos(RS::CANVAS_ITEM_Z_MIN) + "," + itos(RS::CANVAS_ITEM_Z_MAX) + ",1"), "set_z_range_min", "get_z_range_min"); ADD_PROPERTY(PropertyInfo(Variant::INT, "range_z_max", PROPERTY_HINT_RANGE, itos(RS::CANVAS_ITEM_Z_MIN) + "," + itos(RS::CANVAS_ITEM_Z_MAX) + ",1"), "set_z_range_max", "get_z_range_max"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "range_layer_min", PROPERTY_HINT_RANGE, "-512,512,1"), "set_layer_range_min", "get_layer_range_min"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "range_layer_max", PROPERTY_HINT_RANGE, "-512,512,1"), "set_layer_range_max", "get_layer_range_max"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "range_layer_min", PROPERTY_HINT_RANGE, itos(RS::CANVAS_LAYER_MIN) + "," + itos(RS::CANVAS_LAYER_MAX) + ",1"), "set_layer_range_min", "get_layer_range_min"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "range_layer_max", PROPERTY_HINT_RANGE, itos(RS::CANVAS_LAYER_MIN) + "," + itos(RS::CANVAS_LAYER_MAX) + ",1"), "set_layer_range_max", "get_layer_range_max"); ADD_PROPERTY(PropertyInfo(Variant::INT, "range_item_cull_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_item_cull_mask", "get_item_cull_mask"); ADD_GROUP("Shadow", "shadow_"); diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp index 114521e6e3..c4fd997679 100644 --- a/scene/main/canvas_layer.cpp +++ b/scene/main/canvas_layer.cpp @@ -344,7 +344,7 @@ void CanvasLayer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_canvas"), &CanvasLayer::get_canvas); ADD_GROUP("Layer", ""); - ADD_PROPERTY(PropertyInfo(Variant::INT, "layer", PROPERTY_HINT_RANGE, "-128,128,1"), "set_layer", "get_layer"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "layer", PROPERTY_HINT_RANGE, itos(RS::CANVAS_LAYER_MIN) + "," + itos(RS::CANVAS_LAYER_MAX) + ",1"), "set_layer", "get_layer"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible"); ADD_GROUP("Transform", ""); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset", PROPERTY_HINT_NONE, "suffix:px"), "set_offset", "get_offset"); diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 8fb81e59f8..8e678da6c6 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -2243,6 +2243,8 @@ void RenderingServer::_bind_methods() { BIND_CONSTANT(ARRAY_WEIGHTS_SIZE); BIND_CONSTANT(CANVAS_ITEM_Z_MIN); BIND_CONSTANT(CANVAS_ITEM_Z_MAX); + BIND_CONSTANT(CANVAS_LAYER_MIN); + BIND_CONSTANT(CANVAS_LAYER_MAX); BIND_CONSTANT(MAX_GLOW_LEVELS); BIND_CONSTANT(MAX_CURSORS); BIND_CONSTANT(MAX_2D_DIRECTIONAL_LIGHTS); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index af8be9db32..beedfc5daf 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -100,6 +100,8 @@ public: ARRAY_WEIGHTS_SIZE = 4, CANVAS_ITEM_Z_MIN = -4096, CANVAS_ITEM_Z_MAX = 4096, + CANVAS_LAYER_MIN = -2147483648, + CANVAS_LAYER_MAX = 2147483647, MAX_GLOW_LEVELS = 7, MAX_CURSORS = 8, MAX_2D_DIRECTIONAL_LIGHTS = 8, From ab36db2cfa2cb4b65b028291fef70a98909be54d Mon Sep 17 00:00:00 2001 From: Marc Gilleron Date: Sun, 13 Apr 2025 14:14:23 +0200 Subject: [PATCH 006/144] Print Godot version when an extension is found to be incompatible --- core/extension/gdextension_library_loader.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/core/extension/gdextension_library_loader.cpp b/core/extension/gdextension_library_loader.cpp index 1d6be752ce..481a5b28ad 100644 --- a/core/extension/gdextension_library_loader.cpp +++ b/core/extension/gdextension_library_loader.cpp @@ -315,7 +315,9 @@ Error GDExtensionLibraryLoader::parse_gdextension_file(const String &p_path) { compatible = GODOT_VERSION_PATCH >= compatibility_minimum[2]; } if (!compatible) { - ERR_PRINT(vformat("GDExtension only compatible with Godot version %d.%d.%d or later: %s", compatibility_minimum[0], compatibility_minimum[1], compatibility_minimum[2], p_path)); + ERR_PRINT(vformat("GDExtension only compatible with Godot version %d.%d.%d or later: %s, but your Godot version is %d.%d.%d", + compatibility_minimum[0], compatibility_minimum[1], compatibility_minimum[2], p_path, + GODOT_VERSION_MAJOR, GODOT_VERSION_MINOR, GODOT_VERSION_PATCH)); return ERR_INVALID_DATA; } @@ -347,7 +349,8 @@ Error GDExtensionLibraryLoader::parse_gdextension_file(const String &p_path) { #endif if (!compatible) { - ERR_PRINT(vformat("GDExtension only compatible with Godot version %s or earlier: %s", compat_string, p_path)); + ERR_PRINT(vformat("GDExtension only compatible with Godot version %s or earlier: %s, but your Godot version is %d.%d.%d", + compat_string, p_path, GODOT_VERSION_MAJOR, GODOT_VERSION_MINOR, GODOT_VERSION_PATCH)); return ERR_INVALID_DATA; } } From f05b22c53e9288c7f786d77277a42e4c6807e8dd Mon Sep 17 00:00:00 2001 From: Marcos Casagrande Date: Sat, 19 Apr 2025 17:45:06 +0200 Subject: [PATCH 007/144] Web: Avoid extra copy when encoding string in WebSocket _onmessage --- modules/websocket/library_godot_websocket.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/websocket/library_godot_websocket.js b/modules/websocket/library_godot_websocket.js index a6ebdeba6a..beaaf7d146 100644 --- a/modules/websocket/library_godot_websocket.js +++ b/modules/websocket/library_godot_websocket.js @@ -58,8 +58,7 @@ const GodotWebSocket = { return; } else if (typeof event.data === 'string') { is_string = 1; - const enc = new TextEncoder('utf-8'); - buffer = new Uint8Array(enc.encode(event.data)); + buffer = new TextEncoder('utf-8').encode(event.data); } else { GodotRuntime.error('Unknown message type'); return; From e9da0dfd30ec446c35a1db1c12068c53ce17294c Mon Sep 17 00:00:00 2001 From: Joyless <65855333+Joy-less@users.noreply.github.com> Date: Tue, 29 Apr 2025 23:57:26 +0100 Subject: [PATCH 008/144] Don't create unnecessary arrays in C# --- modules/mono/glue/GodotSharp/GodotSharp/Core/Aabb.cs | 6 +++--- modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Aabb.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Aabb.cs index ef550eab0d..681ab6022f 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Aabb.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Aabb.cs @@ -479,8 +479,8 @@ namespace Godot /// public readonly bool IntersectsPlane(Plane plane) { - Vector3[] points = - { + ReadOnlySpan points = + [ new Vector3(_position.X, _position.Y, _position.Z), new Vector3(_position.X, _position.Y, _position.Z + _size.Z), new Vector3(_position.X, _position.Y + _size.Y, _position.Z), @@ -489,7 +489,7 @@ namespace Godot new Vector3(_position.X + _size.X, _position.Y, _position.Z + _size.Z), new Vector3(_position.X + _size.X, _position.Y + _size.Y, _position.Z), new Vector3(_position.X + _size.X, _position.Y + _size.Y, _position.Z + _size.Z) - }; + ]; bool over = false; bool under = false; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs index 16d4616fcd..228dc55b27 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs @@ -1665,8 +1665,8 @@ namespace Godot /// The position of the first non-zero digit. public static int StepDecimals(double step) { - double[] sd = new double[] - { + ReadOnlySpan sd = + [ 0.9999, 0.09999, 0.009999, @@ -1676,7 +1676,7 @@ namespace Godot 0.0000009999, 0.00000009999, 0.000000009999, - }; + ]; double abs = Math.Abs(step); double decs = abs - (int)abs; // Strip away integer part for (int i = 0; i < sd.Length; i++) From 2b8fcca34352fff3259b573d195c84e4979c4da6 Mon Sep 17 00:00:00 2001 From: BlueCube3310 <53150244+BlueCube3310@users.noreply.github.com> Date: Sat, 3 May 2025 15:31:13 +0200 Subject: [PATCH 009/144] DDS: Load BGRA4 textures directly as RGBA4 --- modules/dds/dds_enums.h | 2 +- modules/dds/texture_loader_dds.cpp | 22 ++++++---------------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/modules/dds/dds_enums.h b/modules/dds/dds_enums.h index ea2047363e..d2454f4adc 100644 --- a/modules/dds/dds_enums.h +++ b/modules/dds/dds_enums.h @@ -196,7 +196,7 @@ static const DDSFormatInfo dds_format_info[DDS_MAX] = { { "B2GR3A8", false, 1, 2, Image::FORMAT_RGBA8 }, { "BGR10A2", false, 1, 4, Image::FORMAT_RGBA8 }, { "RGB10A2", false, 1, 4, Image::FORMAT_RGBA8 }, - { "BGRA4", false, 1, 2, Image::FORMAT_RGBA8 }, + { "BGRA4", false, 1, 2, Image::FORMAT_RGBA4444 }, { "GRAYSCALE", false, 1, 1, Image::FORMAT_L8 }, { "GRAYSCALE_ALPHA", false, 1, 2, Image::FORMAT_LA8 }, { "GRAYSCALE_ALPHA_4", false, 1, 1, Image::FORMAT_LA8 }, diff --git a/modules/dds/texture_loader_dds.cpp b/modules/dds/texture_loader_dds.cpp index fb118d411a..130052ccf7 100644 --- a/modules/dds/texture_loader_dds.cpp +++ b/modules/dds/texture_loader_dds.cpp @@ -177,7 +177,6 @@ static Ref _dds_load_layer(Ref p_file, DDSFormat p_dds_format break; case DDS_BGR5A1: - case DDS_BGRA4: case DDS_B2GR3A8: case DDS_LUMINANCE_ALPHA_4: size = size * 2; @@ -235,22 +234,13 @@ static Ref _dds_load_layer(Ref p_file, DDSFormat p_dds_format } break; case DDS_BGRA4: { - // To RGBA8. - int colcount = size / 4; + // To RGBA4. + for (uint32_t i = 0; i < size; i += 2) { + uint8_t ar = wb[i + 0]; + uint8_t gb = wb[i + 1]; - for (int i = colcount - 1; i >= 0; i--) { - int src_ofs = i * 2; - int dst_ofs = i * 4; - - uint8_t b = wb[src_ofs] & 0x0F; - uint8_t g = wb[src_ofs] & 0xF0; - uint8_t r = wb[src_ofs + 1] & 0x0F; - uint8_t a = wb[src_ofs + 1] & 0xF0; - - wb[dst_ofs] = (r << 4) | r; - wb[dst_ofs + 1] = g | (g >> 4); - wb[dst_ofs + 2] = (b << 4) | b; - wb[dst_ofs + 3] = a | (a >> 4); + wb[i + 0] = ((ar & 0x0F) << 4) | ((gb & 0xF0) >> 4); + wb[i + 1] = ((ar & 0xF0) >> 4) | ((gb & 0x0F) << 4); } } break; From 54c8d648929979d6978ffd2e60b057476240a95a Mon Sep 17 00:00:00 2001 From: Danni <34800072+KeyboardDanni@users.noreply.github.com> Date: Thu, 3 Apr 2025 20:06:19 -0400 Subject: [PATCH 010/144] Add ruler width editor setting to 2D editor --- doc/classes/EditorSettings.xml | 3 + editor/editor_settings.cpp | 1 + editor/plugins/canvas_item_editor_plugin.cpp | 80 +++++++++++--------- editor/plugins/canvas_item_editor_plugin.h | 2 + 4 files changed, 49 insertions(+), 37 deletions(-) diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml index 9a3e6087d2..642cc13737 100644 --- a/doc/classes/EditorSettings.xml +++ b/doc/classes/EditorSettings.xml @@ -283,6 +283,9 @@ The guides color to use in the 2D editor. Guides can be created by dragging the mouse cursor from the rulers. + + The thickness of the coordinate ruler in the 2D editor. Increasing this will also increase the size of the ruler font, improving readability when using a lower editor scale. The editor may force a minimum size to keep the ruler numbers legible. + The color to use when drawing smart snapping lines in the 2D editor. The smart snapping lines will automatically display when moving 2D nodes if smart snapping is enabled in the Snapping Options menu at the top of the 2D editor viewport. diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 6592ae8654..0bc8276608 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -916,6 +916,7 @@ void EditorSettings::_load_defaults(Ref p_extra_config) { _initial_set("editors/2d/viewport_border_color", Color(0.4, 0.4, 1.0, 0.4), true); _initial_set("editors/2d/use_integer_zoom_by_default", false, true); EDITOR_SETTING_BASIC(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/2d/zoom_speed_factor", 1.1, "1.01,2,0.01") + EDITOR_SETTING_BASIC(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/2d/ruler_width", 16.0, "12.0,30.0,1.0") // Bone mapper (BoneMapEditorPlugin) _initial_set("editors/bone_mapper/handle_colors/unset", Color(0.3, 0.3, 0.3)); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 00fa7d06b8..70a142e050 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -65,7 +65,6 @@ #include "scene/resources/packed_scene.h" #include "scene/resources/style_box_texture.h" -#define RULER_WIDTH (15 * EDSCALE) #define DRAG_THRESHOLD (8 * EDSCALE) constexpr real_t SCALE_HANDLE_DISTANCE = 25; constexpr real_t MOVE_HANDLE_DISTANCE = 25; @@ -1123,7 +1122,7 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref &p_eve is_hovering_h_guide = false; is_hovering_v_guide = false; - if (m.is_valid() && m->get_position().x < RULER_WIDTH) { + if (m.is_valid() && m->get_position().x < ruler_width_scaled) { // Check if we are hovering an existing horizontal guide for (int i = 0; i < hguides.size(); i++) { if (Math::abs(xform.xform(Point2(0, hguides[i])).y - m->get_position().y) < MIN(minimum, 8)) { @@ -1133,7 +1132,7 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref &p_eve } } - } else if (m.is_valid() && m->get_position().y < RULER_WIDTH) { + } else if (m.is_valid() && m->get_position().y < ruler_width_scaled) { // Check if we are hovering an existing vertical guide for (int i = 0; i < vguides.size(); i++) { if (Math::abs(xform.xform(Point2(vguides[i], 0)).x - m->get_position().x) < MIN(minimum, 8)) { @@ -1147,12 +1146,12 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref &p_eve // Start dragging a guide if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && b->is_pressed()) { // Press button - if (b->get_position().x < RULER_WIDTH && b->get_position().y < RULER_WIDTH) { + if (b->get_position().x < ruler_width_scaled && b->get_position().y < ruler_width_scaled) { // Drag a new double guide drag_type = DRAG_DOUBLE_GUIDE; dragged_guide_index = -1; return true; - } else if (b->get_position().x < RULER_WIDTH) { + } else if (b->get_position().x < ruler_width_scaled) { // Check if we drag an existing horizontal guide dragged_guide_index = -1; for (int i = 0; i < hguides.size(); i++) { @@ -1169,7 +1168,7 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref &p_eve drag_type = DRAG_V_GUIDE; } return true; - } else if (b->get_position().y < RULER_WIDTH) { + } else if (b->get_position().y < ruler_width_scaled) { // Check if we drag an existing vertical guide dragged_guide_index = -1; for (int i = 0; i < vguides.size(); i++) { @@ -1215,7 +1214,7 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref &p_eve Point2 edited = snap_point(xform.affine_inverse().xform(b->get_position()), SNAP_GRID | SNAP_PIXEL | SNAP_OTHER_NODES); if (drag_type == DRAG_V_GUIDE) { Array prev_vguides = vguides.duplicate(); - if (b->get_position().x > RULER_WIDTH) { + if (b->get_position().x > ruler_width_scaled) { // Adds a new vertical guide if (dragged_guide_index >= 0) { vguides[dragged_guide_index] = edited.x; @@ -1252,7 +1251,7 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref &p_eve } } else if (drag_type == DRAG_H_GUIDE) { Array prev_hguides = hguides.duplicate(); - if (b->get_position().y > RULER_WIDTH) { + if (b->get_position().y > ruler_width_scaled) { // Adds a new horizontal guide if (dragged_guide_index >= 0) { hguides[dragged_guide_index] = edited.y; @@ -1290,7 +1289,7 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref &p_eve } else if (drag_type == DRAG_DOUBLE_GUIDE) { Array prev_hguides = hguides.duplicate(); Array prev_vguides = vguides.duplicate(); - if (b->get_position().x > RULER_WIDTH && b->get_position().y > RULER_WIDTH) { + if (b->get_position().x > ruler_width_scaled && b->get_position().y > ruler_width_scaled) { // Adds a new horizontal guide a new vertical guide vguides.push_back(edited.x); hguides.push_back(edited.y); @@ -3010,8 +3009,8 @@ void CanvasItemEditor::_draw_guides() { Ref font = get_theme_font(SNAME("bold"), EditorStringName(EditorFonts)); int font_size = 1.3 * get_theme_font_size(SNAME("bold_size"), EditorStringName(EditorFonts)); Size2 text_size = font->get_string_size(str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size); - viewport->draw_string_outline(font, Point2(dragged_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); - viewport->draw_string(font, Point2(dragged_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, text_color); + viewport->draw_string_outline(font, Point2(dragged_guide_pos.x + 10, ruler_width_scaled + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); + viewport->draw_string(font, Point2(dragged_guide_pos.x + 10, ruler_width_scaled + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, text_color); viewport->draw_line(Point2(dragged_guide_pos.x, 0), Point2(dragged_guide_pos.x, viewport->get_size().y), guide_color, Math::round(EDSCALE)); } if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_H_GUIDE) { @@ -3019,8 +3018,8 @@ void CanvasItemEditor::_draw_guides() { Ref font = get_theme_font(SNAME("bold"), EditorStringName(EditorFonts)); int font_size = 1.3 * get_theme_font_size(SNAME("bold_size"), EditorStringName(EditorFonts)); Size2 text_size = font->get_string_size(str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size); - viewport->draw_string_outline(font, Point2(RULER_WIDTH + 10, dragged_guide_pos.y + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); - viewport->draw_string(font, Point2(RULER_WIDTH + 10, dragged_guide_pos.y + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, text_color); + viewport->draw_string_outline(font, Point2(ruler_width_scaled + 10, dragged_guide_pos.y + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); + viewport->draw_string(font, Point2(ruler_width_scaled + 10, dragged_guide_pos.y + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, text_color); viewport->draw_line(Point2(0, dragged_guide_pos.y), Point2(viewport->get_size().x, dragged_guide_pos.y), guide_color, Math::round(EDSCALE)); } } @@ -3045,7 +3044,7 @@ void CanvasItemEditor::_draw_rulers() { Color font_color = get_theme_color(SceneStringName(font_color), EditorStringName(Editor)); font_color.a = 0.8; Ref font = get_theme_font(SNAME("rulers"), EditorStringName(EditorFonts)); - int font_size = get_theme_font_size(SNAME("rulers_size"), EditorStringName(EditorFonts)); + real_t ruler_tick_scale = ruler_width_scaled / 15.0; // The rule transform Transform2D ruler_transform; @@ -3058,15 +3057,15 @@ void CanvasItemEditor::_draw_rulers() { ruler_transform.translate_local(grid_offset); ruler_transform.scale_basis(grid_step * Math::pow(2.0, grid_step_multiplier)); } - while ((transform * ruler_transform).get_scale().x < 50 || (transform * ruler_transform).get_scale().y < 50) { + while ((transform * ruler_transform).get_scale().x < 50.0 * ruler_tick_scale || (transform * ruler_transform).get_scale().y < 50.0 * ruler_tick_scale) { ruler_transform.scale_basis(Point2(2, 2)); } } else { real_t basic_rule = 100; - for (int i = 0; basic_rule * zoom > 100; i++) { + for (int i = 0; basic_rule * zoom > 100 * ruler_tick_scale; i++) { basic_rule /= (i % 2) ? 5.0 : 2.0; } - for (int i = 0; basic_rule * zoom < 100; i++) { + for (int i = 0; basic_rule * zoom < 60 * ruler_tick_scale; i++) { basic_rule *= (i % 2) ? 2.0 : 5.0; } ruler_transform.scale(Size2(basic_rule, basic_rule)); @@ -3082,50 +3081,50 @@ void CanvasItemEditor::_draw_rulers() { minor_subdivide.scale(Size2(1.0 / minor_subdivision, 1.0 / minor_subdivision)); // First and last graduations to draw (in the ruler space) - Point2 first = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(Point2(RULER_WIDTH, RULER_WIDTH)); + Point2 first = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(Point2(ruler_width_scaled, ruler_width_scaled)); Point2 last = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(viewport->get_size()); // Draw top ruler - viewport->draw_rect(Rect2(Point2(RULER_WIDTH, 0), Size2(viewport->get_size().x, RULER_WIDTH)), bg_color); + viewport->draw_rect(Rect2(Point2(ruler_width_scaled, 0), Size2(viewport->get_size().x, ruler_width_scaled)), bg_color); for (int i = Math::ceil(first.x); i < last.x; i++) { Point2 position = (transform * ruler_transform * major_subdivide * minor_subdivide).xform(Point2(i, 0)).round(); if (i % (major_subdivision * minor_subdivision) == 0) { - viewport->draw_line(Point2(position.x, 0), Point2(position.x, RULER_WIDTH), graduation_color, Math::round(EDSCALE)); + viewport->draw_line(Point2(position.x, 0), Point2(position.x, ruler_width_scaled), graduation_color, Math::round(EDSCALE)); real_t val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(i, 0)).x; - viewport->draw_string(font, Point2(position.x + 2, font->get_ascent(font_size) + Math::round(EDSCALE)), TS->format_number(vformat(((int)val == val) ? "%d" : "%.1f", val)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color); + viewport->draw_string(font, Point2(position.x + MAX(Math::round(ruler_font_size / 8.0), 2), font->get_ascent(ruler_font_size) + Math::round(EDSCALE)), TS->format_number(vformat(((int)val == val) ? "%d" : "%.1f", val)), HORIZONTAL_ALIGNMENT_LEFT, -1, ruler_font_size, font_color); } else { if (i % minor_subdivision == 0) { - viewport->draw_line(Point2(position.x, RULER_WIDTH * 0.33), Point2(position.x, RULER_WIDTH), graduation_color, Math::round(EDSCALE)); + viewport->draw_line(Point2(position.x, ruler_width_scaled * 0.33), Point2(position.x, ruler_width_scaled), graduation_color, Math::round(EDSCALE)); } else { - viewport->draw_line(Point2(position.x, RULER_WIDTH * 0.75), Point2(position.x, RULER_WIDTH), graduation_color, Math::round(EDSCALE)); + viewport->draw_line(Point2(position.x, ruler_width_scaled * 0.75), Point2(position.x, ruler_width_scaled), graduation_color, Math::round(EDSCALE)); } } } // Draw left ruler - viewport->draw_rect(Rect2(Point2(0, RULER_WIDTH), Size2(RULER_WIDTH, viewport->get_size().y)), bg_color); + viewport->draw_rect(Rect2(Point2(0, ruler_width_scaled), Size2(ruler_width_scaled, viewport->get_size().y)), bg_color); for (int i = Math::ceil(first.y); i < last.y; i++) { Point2 position = (transform * ruler_transform * major_subdivide * minor_subdivide).xform(Point2(0, i)).round(); if (i % (major_subdivision * minor_subdivision) == 0) { - viewport->draw_line(Point2(0, position.y), Point2(RULER_WIDTH, position.y), graduation_color, Math::round(EDSCALE)); + viewport->draw_line(Point2(0, position.y), Point2(ruler_width_scaled, position.y), graduation_color, Math::round(EDSCALE)); real_t val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(0, i)).y; - Transform2D text_xform = Transform2D(-Math::PI / 2.0, Point2(font->get_ascent(font_size) + Math::round(EDSCALE), position.y - 2)); + Transform2D text_xform = Transform2D(-Math::PI / 2.0, Point2(font->get_ascent(ruler_font_size) + Math::round(EDSCALE), position.y - 2)); viewport->draw_set_transform_matrix(viewport->get_transform() * text_xform); - viewport->draw_string(font, Point2(), TS->format_number(vformat(((int)val == val) ? "%d" : "%.1f", val)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color); + viewport->draw_string(font, Point2(), TS->format_number(vformat(((int)val == val) ? "%d" : "%.1f", val)), HORIZONTAL_ALIGNMENT_LEFT, -1, ruler_font_size, font_color); viewport->draw_set_transform_matrix(viewport->get_transform()); } else { if (i % minor_subdivision == 0) { - viewport->draw_line(Point2(RULER_WIDTH * 0.33, position.y), Point2(RULER_WIDTH, position.y), graduation_color, Math::round(EDSCALE)); + viewport->draw_line(Point2(ruler_width_scaled * 0.33, position.y), Point2(ruler_width_scaled, position.y), graduation_color, Math::round(EDSCALE)); } else { - viewport->draw_line(Point2(RULER_WIDTH * 0.75, position.y), Point2(RULER_WIDTH, position.y), graduation_color, Math::round(EDSCALE)); + viewport->draw_line(Point2(ruler_width_scaled * 0.75, position.y), Point2(ruler_width_scaled, position.y), graduation_color, Math::round(EDSCALE)); } } } // Draw the top left corner - viewport->draw_rect(Rect2(Point2(), Size2(RULER_WIDTH, RULER_WIDTH)), graduation_color); + viewport->draw_rect(Rect2(Point2(), Size2(ruler_width_scaled, ruler_width_scaled)), graduation_color); } void CanvasItemEditor::_draw_grid() { @@ -3985,7 +3984,7 @@ void CanvasItemEditor::_draw_message() { Ref font = get_theme_font(SceneStringName(font), SNAME("Label")); int font_size = get_theme_font_size(SceneStringName(font_size), SNAME("Label")); - Point2 msgpos = Point2(RULER_WIDTH + 10 * EDSCALE, viewport->get_size().y - 14 * EDSCALE); + Point2 msgpos = Point2(ruler_width_scaled + 10 * EDSCALE, viewport->get_size().y - 14 * EDSCALE); viewport->draw_string(font, msgpos + Point2(1, 1), message, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(0, 0, 0, 0.8)); viewport->draw_string(font, msgpos + Point2(-1, -1), message, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(0, 0, 0, 0.8)); viewport->draw_string(font, msgpos, message, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(1, 1, 1, 1)); @@ -4130,6 +4129,11 @@ void CanvasItemEditor::_update_editor_settings() { panner->set_scroll_speed(EDITOR_GET("editors/panning/2d_editor_pan_speed")); panner->setup_warped_panning(get_viewport(), EDITOR_GET("editors/panning/warped_mouse_panning")); panner->set_zoom_style((ViewPanner::ZoomStyle)EDITOR_GET("editors/panning/zoom_style").operator int()); + + // Compute the ruler width here so we can reuse the result throughout the various draw functions. + real_t ruler_width_unscaled = EDITOR_GET("editors/2d/ruler_width"); + ruler_font_size = MAX(get_theme_font_size(SNAME("rulers_size"), EditorStringName(EditorFonts)) * ruler_width_unscaled / 15.0, 8); + ruler_width_scaled = MAX(ruler_width_unscaled * EDSCALE, ruler_font_size * 2.0); } void CanvasItemEditor::_project_settings_changed() { @@ -4243,8 +4247,10 @@ void CanvasItemEditor::_notification(int p_what) { case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { if (EditorThemeManager::is_generated_theme_outdated() || - EditorSettings::get_singleton()->check_changed_settings_in_group("editors/panning")) { + EditorSettings::get_singleton()->check_changed_settings_in_group("editors/panning") || + EditorSettings::get_singleton()->check_changed_settings_in_group("editors/2d")) { _update_editor_settings(); + update_viewport(); } } break; @@ -4287,7 +4293,7 @@ void CanvasItemEditor::_update_scrollbars() { // Move the zoom buttons. Point2 controls_vb_begin = Point2(5, 5); - controls_vb_begin += (show_rulers) ? Point2(RULER_WIDTH, RULER_WIDTH) : Point2(); + controls_vb_begin += (show_rulers) ? Point2(ruler_width_scaled, ruler_width_scaled) : Point2(); controls_vb->set_begin(controls_vb_begin); Size2 hmin = h_scroll->get_minimum_size(); @@ -4332,13 +4338,13 @@ void CanvasItemEditor::_update_scrollbars() { // Move and resize the scrollbars, avoiding overlap. if (is_layout_rtl()) { - v_scroll->set_begin(Point2(0, (show_rulers) ? RULER_WIDTH : 0)); + v_scroll->set_begin(Point2(0, (show_rulers) ? ruler_width_scaled : 0)); v_scroll->set_end(Point2(vmin.width, size.height - (h_scroll->is_visible() ? hmin.height : 0))); } else { - v_scroll->set_begin(Point2(size.width - vmin.width, (show_rulers) ? RULER_WIDTH : 0)); + v_scroll->set_begin(Point2(size.width - vmin.width, (show_rulers) ? ruler_width_scaled : 0)); v_scroll->set_end(Point2(size.width, size.height - (h_scroll->is_visible() ? hmin.height : 0))); } - h_scroll->set_begin(Point2((show_rulers) ? RULER_WIDTH : 0, size.height - hmin.height)); + h_scroll->set_begin(Point2((show_rulers) ? ruler_width_scaled : 0, size.height - hmin.height)); h_scroll->set_end(Point2(size.width - (v_scroll->is_visible() ? vmin.width : 0), size.height)); // Calculate scrollable area. @@ -5193,7 +5199,7 @@ void CanvasItemEditor::clear() { zoom = 1.0 / MAX(1, EDSCALE); zoom_widget->set_zoom(zoom); - view_offset = Point2(-150 - RULER_WIDTH, -95 - RULER_WIDTH); + view_offset = Point2(-150 - ruler_width_scaled, -95 - ruler_width_scaled); previous_update_view_offset = view_offset; // Moves the view a little bit to the left so that (0,0) is visible. The values a relative to a 16/10 screen. _update_scrollbars(); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 9e1ef0083e..faec6823f4 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -256,6 +256,8 @@ private: bool ruler_tool_active = false; Point2 ruler_tool_origin; + real_t ruler_width_scaled = 16.0; + int ruler_font_size = 8; Point2 node_create_position; MenuOption last_option; From 90328e921fbf05e656e2555f986ba182f98ac8ec Mon Sep 17 00:00:00 2001 From: "Wilson E. Alvarez" Date: Mon, 12 May 2025 11:03:30 -0400 Subject: [PATCH 011/144] Improve Timer::start error message. --- scene/main/timer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scene/main/timer.cpp b/scene/main/timer.cpp index 8c36c56c42..997320b25d 100644 --- a/scene/main/timer.cpp +++ b/scene/main/timer.cpp @@ -114,7 +114,7 @@ bool Timer::has_autostart() const { } void Timer::start(double p_time) { - ERR_FAIL_COND_MSG(!is_inside_tree(), "Timer was not added to the SceneTree. Either add it or set autostart to true."); + ERR_FAIL_COND_MSG(!is_inside_tree(), "Unable to start the timer because it's not inside the scene tree. Either add it or set autostart to true."); if (p_time > 0) { set_wait_time(p_time); From 3a7425968aa878b05ad15a5b993f7a164e46ed84 Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Tue, 13 May 2025 00:29:05 +0200 Subject: [PATCH 012/144] Improve SpinBox class documentation - Describe the class's interactivity in more detail. - Clarify behavior of `apply()`. - Mention that expressions can be evaluated. - Mention caveat with `update_on_text_changed` regarding expressions. --- doc/classes/SpinBox.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/classes/SpinBox.xml b/doc/classes/SpinBox.xml index 6da6a301fe..fbcd2fa9a2 100644 --- a/doc/classes/SpinBox.xml +++ b/doc/classes/SpinBox.xml @@ -4,7 +4,8 @@ An input field for numbers. - [SpinBox] is a numerical input text field. It allows entering integers and floating-point numbers. + [SpinBox] is a numerical input text field. It allows entering integers and floating-point numbers. The [SpinBox] also has up and down buttons that can be clicked increase or decrease the value. The value can also be changed by dragging the mouse up or down over the [SpinBox]'s arrows. + Additionally, mathematical expressions can be entered. These are evaluated when the user presses [kbd]Enter[/kbd] while editing the [SpinBox]'s text field. This uses the [Expression] class to parse and evaluate the expression. The result of the expression is then set as the value of the [SpinBox]. Some examples of valid expressions are [code]5 + 2 * 3[/code], [code]pow(2, 4)[/code], and [code]PI + sin(0.5)[/code]. Expressions are case-sensitive. [b]Example:[/b] Create a [SpinBox], disable its context menu and set its text alignment to right. [codeblocks] [gdscript] @@ -33,7 +34,7 @@ - Applies the current value of this [SpinBox]. + Applies the current value of this [SpinBox]. This is equivalent to pressing [kbd]Enter[/kbd] while editing the [LineEdit] used by the [SpinBox]. This will cause [signal LineEdit.text_submitted] to be emitted and its currently contained expression to be evaluated. @@ -67,6 +68,7 @@ Sets the value of the [Range] for this [SpinBox] when the [LineEdit] text is [i]changed[/i] instead of [i]submitted[/i]. See [signal LineEdit.text_changed] and [signal LineEdit.text_submitted]. + [b]Note:[/b] If set to [code]true[/code], this will interfere with entering mathematical expressions in the [SpinBox]. The [SpinBox] will try to evaluate the expression as you type, which means symbols like a trailing [code]+[/code] are removed immediately by the expression being evaluated. From fe1322c014062ac3aa1603d8265abd82d63b32e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Wed, 14 May 2025 16:16:07 +0200 Subject: [PATCH 013/144] D3D12: Silence `-Wmaybe-uninitialized` warning in D3D12MemAlloc This was lost in #104893 when removing the warning ignores no longer relevant when including the D3D12MemAlloc _header_ as external. But we still compile the .cpp directly and it has this warning. Clarified why have a wrapper for this file. --- drivers/d3d12/d3d12ma.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/d3d12/d3d12ma.cpp b/drivers/d3d12/d3d12ma.cpp index 27f67d66e8..0cc159f350 100644 --- a/drivers/d3d12/d3d12ma.cpp +++ b/drivers/d3d12/d3d12ma.cpp @@ -28,6 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#include "rendering_context_driver_d3d12.h" +// Wrapper needed to set the required rpcndr version for MinGW compatibility. +// Since we're compiling thirdparty code in a Godot SCons environment with +// warnings enabled, we also need to silence them manually. + +#include "rendering_device_driver_d3d12.h" // For __REQUIRED_RPCNDR_H_VERSION__. + +GODOT_GCC_WARNING_PUSH_AND_IGNORE("-Wmaybe-uninitialized") #include + +GODOT_GCC_WARNING_POP From 0d4d0d44c9c820329bf2c94374e1bfa929e785d6 Mon Sep 17 00:00:00 2001 From: DeeJayLSP Date: Fri, 9 May 2025 14:55:51 -0300 Subject: [PATCH 014/144] Force weights on custom editor fonts when variable --- doc/classes/EditorSettings.xml | 2 ++ editor/themes/editor_fonts.cpp | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml index 9a3e6087d2..cbdb484a45 100644 --- a/doc/classes/EditorSettings.xml +++ b/doc/classes/EditorSettings.xml @@ -899,9 +899,11 @@ The font to use for the editor interface. Must be a resource of a [Font] type such as a [code].ttf[/code] or [code].otf[/code] font file. + [b]Note:[/b] If the provided font is variable, a weight of 400 (normal) will be used. The font to use for bold text in the editor interface. Must be a resource of a [Font] type such as a [code].ttf[/code] or [code].otf[/code] font file. + [b]Note:[/b] If the provided font is variable, a weight of 700 (bold) will be used. The size of the font in the editor interface. diff --git a/editor/themes/editor_fonts.cpp b/editor/themes/editor_fonts.cpp index e283f0342a..372393c67c 100644 --- a/editor/themes/editor_fonts.cpp +++ b/editor/themes/editor_fonts.cpp @@ -249,6 +249,9 @@ void editor_register_fonts(const Ref &p_theme) { } default_fc->set_spacing(TextServer::SPACING_TOP, -EDSCALE); default_fc->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); + Dictionary default_fc_opentype; + default_fc_opentype["weight"] = 400; + default_fc->set_variation_opentype(default_fc_opentype); Ref default_fc_msdf; default_fc_msdf.instantiate(); @@ -265,6 +268,7 @@ void editor_register_fonts(const Ref &p_theme) { } default_fc_msdf->set_spacing(TextServer::SPACING_TOP, -EDSCALE); default_fc_msdf->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); + default_fc_msdf->set_variation_opentype(default_fc_opentype); Ref bold_fc; bold_fc.instantiate(); @@ -289,6 +293,9 @@ void editor_register_fonts(const Ref &p_theme) { } bold_fc->set_spacing(TextServer::SPACING_TOP, -EDSCALE); bold_fc->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); + Dictionary bold_fc_opentype; + bold_fc_opentype["weight"] = 700; + bold_fc->set_variation_opentype(bold_fc_opentype); Ref bold_fc_msdf; bold_fc_msdf.instantiate(); @@ -313,6 +320,7 @@ void editor_register_fonts(const Ref &p_theme) { } bold_fc_msdf->set_spacing(TextServer::SPACING_TOP, -EDSCALE); bold_fc_msdf->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); + bold_fc_msdf->set_variation_opentype(bold_fc_opentype); Ref mono_fc; mono_fc.instantiate(); From a87be2c74d107b048398ec106f8da59bf65901f8 Mon Sep 17 00:00:00 2001 From: kleonc <9283098+kleonc@users.noreply.github.com> Date: Mon, 19 May 2025 20:42:07 +0200 Subject: [PATCH 015/144] Show Curve3D point tilt in degrees in inspector --- scene/resources/curve.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index 668a2a25cb..0e50c3d17d 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -2458,7 +2458,7 @@ void Curve3D::_get_property_list(List *p_list) const { p_list->push_back(pi); } - pi = PropertyInfo(Variant::FLOAT, vformat("point_%d/tilt", i)); + pi = PropertyInfo(Variant::FLOAT, vformat("point_%d/tilt", i), PROPERTY_HINT_RANGE, "-360,360,0.1,or_less,or_greater,radians_as_degrees"); pi.usage &= ~PROPERTY_USAGE_STORAGE; p_list->push_back(pi); } From f6d4bab263a1e21fc54464572a671316985e93bf Mon Sep 17 00:00:00 2001 From: DeeJayLSP Date: Mon, 19 May 2025 16:24:27 -0300 Subject: [PATCH 016/144] Update OpenXR to 1.1.47 --- COPYRIGHT.txt | 2 +- thirdparty/README.md | 2 +- thirdparty/openxr/COPYING.adoc | 2 +- thirdparty/openxr/include/openxr/openxr.h | 1163 ++++++++++++++++- .../openxr/openxr_loader_negotiation.h | 2 +- .../openxr/include/openxr/openxr_platform.h | 8 +- .../include/openxr/openxr_platform_defines.h | 2 +- .../openxr/include/openxr/openxr_reflection.h | 887 ++++++++++++- .../openxr/openxr_reflection_parent_structs.h | 20 +- .../openxr/openxr_reflection_structs.h | 67 +- .../openxr/src/common/android_logging.h | 22 + .../openxr/src/common/extra_algorithms.h | 2 +- .../openxr/src/common/filesystem_utils.cpp | 2 +- .../openxr/src/common/filesystem_utils.hpp | 2 +- .../openxr/src/common/hex_and_handles.h | 2 +- thirdparty/openxr/src/common/object_info.cpp | 2 +- thirdparty/openxr/src/common/object_info.h | 2 +- .../openxr/src/common/platform_utils.hpp | 4 +- .../openxr/src/common/stdfs_conditions.h | 2 +- thirdparty/openxr/src/common/unique_asset.h | 2 +- .../src/common/vulkan_debug_object_namer.hpp | 2 +- .../openxr/src/common/xr_dependencies.h | 2 +- thirdparty/openxr/src/common/xr_linear.h | 2 +- .../external/jsoncpp/include/json/allocator.h | 7 +- .../jsoncpp/include/json/json_features.h | 3 +- .../external/jsoncpp/include/json/reader.h | 44 +- .../src/external/jsoncpp/include/json/value.h | 46 +- .../external/jsoncpp/include/json/version.h | 9 +- .../external/jsoncpp/include/json/writer.h | 19 +- .../jsoncpp/src/lib_json/json_reader.cpp | 186 +-- .../jsoncpp/src/lib_json/json_value.cpp | 10 +- .../jsoncpp/src/lib_json/json_writer.cpp | 15 +- .../openxr/src/loader/android_utilities.cpp | 8 +- .../openxr/src/loader/android_utilities.h | 2 +- .../openxr/src/loader/api_layer_interface.cpp | 2 +- .../openxr/src/loader/api_layer_interface.hpp | 2 +- .../openxr/src/loader/exception_handling.hpp | 2 +- thirdparty/openxr/src/loader/loader_core.cpp | 2 +- .../openxr/src/loader/loader_init_data.cpp | 2 +- .../openxr/src/loader/loader_init_data.hpp | 2 +- .../openxr/src/loader/loader_instance.cpp | 2 +- .../openxr/src/loader/loader_instance.hpp | 2 +- .../openxr/src/loader/loader_logger.cpp | 2 +- .../openxr/src/loader/loader_logger.hpp | 2 +- .../src/loader/loader_logger_recorders.cpp | 2 +- .../src/loader/loader_logger_recorders.hpp | 2 +- .../openxr/src/loader/loader_platform.hpp | 2 +- .../openxr/src/loader/manifest_file.cpp | 2 +- .../openxr/src/loader/manifest_file.hpp | 2 +- .../openxr/src/loader/runtime_interface.cpp | 2 +- .../openxr/src/loader/runtime_interface.hpp | 2 +- .../openxr/src/loader/xr_generated_loader.cpp | 4 +- .../openxr/src/loader/xr_generated_loader.hpp | 4 +- .../src/xr_generated_dispatch_table_core.c | 4 +- .../src/xr_generated_dispatch_table_core.h | 4 +- 55 files changed, 2384 insertions(+), 218 deletions(-) create mode 100644 thirdparty/openxr/src/common/android_logging.h diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt index 65f84a48e8..139e77ef3d 100644 --- a/COPYRIGHT.txt +++ b/COPYRIGHT.txt @@ -504,7 +504,7 @@ License: Expat Files: thirdparty/openxr/* Comment: OpenXR Loader -Copyright: 2020-2023, The Khronos Group Inc. +Copyright: 2020-2025, The Khronos Group Inc. License: Apache-2.0 Files: thirdparty/pcre2/* diff --git a/thirdparty/README.md b/thirdparty/README.md index 53c2e6a218..50345e5468 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -836,7 +836,7 @@ Files extracted from the upstream source: ## openxr - Upstream: https://github.com/KhronosGroup/OpenXR-SDK -- Version: 1.1.41 (7d1c0961351bac61fd7bb72d402649d5ac3f2935, 2024) +- Version: 1.1.47 (858912260ca616f4c23f7fb61c89228c353eb124, 2025) - License: Apache 2.0 Files extracted from upstream source: diff --git a/thirdparty/openxr/COPYING.adoc b/thirdparty/openxr/COPYING.adoc index d700a19d7b..4dfd6e26cc 100644 --- a/thirdparty/openxr/COPYING.adoc +++ b/thirdparty/openxr/COPYING.adoc @@ -1,6 +1,6 @@ = COPYING.adoc for the Khronos Group OpenXR projects -// Copyright (c) 2020-2024, The Khronos Group Inc. +// Copyright (c) 2020-2025 The Khronos Group Inc. // // SPDX-License-Identifier: CC-BY-4.0 diff --git a/thirdparty/openxr/include/openxr/openxr.h b/thirdparty/openxr/include/openxr/openxr.h index f094b0f72b..f1d77e89a8 100644 --- a/thirdparty/openxr/include/openxr/openxr.h +++ b/thirdparty/openxr/include/openxr/openxr.h @@ -2,7 +2,7 @@ #define OPENXR_H_ 1 /* -** Copyright 2017-2024, The Khronos Group Inc. +** Copyright 2017-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 OR MIT */ @@ -26,7 +26,7 @@ extern "C" { ((((major) & 0xffffULL) << 48) | (((minor) & 0xffffULL) << 32) | ((patch) & 0xffffffffULL)) // OpenXR current version number. -#define XR_CURRENT_API_VERSION XR_MAKE_VERSION(1, 1, 41) +#define XR_CURRENT_API_VERSION XR_MAKE_VERSION(1, 1, 47) // OpenXR 1.0 version number #define XR_API_VERSION_1_0 XR_MAKE_VERSION(1, 0, XR_VERSION_PATCH(XR_CURRENT_API_VERSION)) @@ -259,6 +259,16 @@ typedef enum XrResult { XR_ENVIRONMENT_DEPTH_NOT_AVAILABLE_META = 1000291000, XR_ERROR_HINT_ALREADY_SET_QCOM = -1000306000, XR_ERROR_NOT_AN_ANCHOR_HTC = -1000319000, + XR_ERROR_SPATIAL_ENTITY_ID_INVALID_BD = -1000389000, + XR_ERROR_SPATIAL_SENSING_SERVICE_UNAVAILABLE_BD = -1000389001, + XR_ERROR_ANCHOR_NOT_SUPPORTED_FOR_ENTITY_BD = -1000389002, + XR_ERROR_SPATIAL_ANCHOR_NOT_FOUND_BD = -1000390000, + XR_ERROR_SPATIAL_ANCHOR_SHARING_NETWORK_TIMEOUT_BD = -1000391000, + XR_ERROR_SPATIAL_ANCHOR_SHARING_AUTHENTICATION_FAILURE_BD = -1000391001, + XR_ERROR_SPATIAL_ANCHOR_SHARING_NETWORK_FAILURE_BD = -1000391002, + XR_ERROR_SPATIAL_ANCHOR_SHARING_LOCALIZATION_FAIL_BD = -1000391003, + XR_ERROR_SPATIAL_ANCHOR_SHARING_MAP_INSUFFICIENT_BD = -1000391004, + XR_ERROR_SCENE_CAPTURE_FAILURE_BD = -1000392000, XR_ERROR_SPACE_NOT_LOCATABLE_EXT = -1000429000, XR_ERROR_PLANE_DETECTION_PERMISSION_DENIED_EXT = -1000429001, XR_ERROR_FUTURE_PENDING_EXT = -1000469001, @@ -267,6 +277,12 @@ typedef enum XrResult { XR_ERROR_SYSTEM_NOTIFICATION_INCOMPATIBLE_SKU_ML = -1000473001, XR_ERROR_WORLD_MESH_DETECTOR_PERMISSION_DENIED_ML = -1000474000, XR_ERROR_WORLD_MESH_DETECTOR_SPACE_NOT_LOCATABLE_ML = -1000474001, + XR_ERROR_FACIAL_EXPRESSION_PERMISSION_DENIED_ML = 1000482000, + XR_ERROR_COLOCATION_DISCOVERY_NETWORK_FAILED_META = -1000571001, + XR_ERROR_COLOCATION_DISCOVERY_NO_DISCOVERY_METHOD_META = -1000571002, + XR_COLOCATION_DISCOVERY_ALREADY_ADVERTISING_META = 1000571003, + XR_COLOCATION_DISCOVERY_ALREADY_DISCOVERING_META = 1000571004, + XR_ERROR_SPACE_GROUP_NOT_FOUND_META = -1000572002, XR_ERROR_EXTENSION_DEPENDENCY_NOT_ENABLED_KHR = XR_ERROR_EXTENSION_DEPENDENCY_NOT_ENABLED, XR_ERROR_PERMISSION_INSUFFICIENT_KHR = XR_ERROR_PERMISSION_INSUFFICIENT, XR_RESULT_MAX_ENUM = 0x7FFFFFFF @@ -571,6 +587,8 @@ typedef enum XrStructureType { XR_TYPE_COMPOSITION_LAYER_SETTINGS_FB = 1000204000, XR_TYPE_HAPTIC_PCM_VIBRATION_FB = 1000209001, XR_TYPE_DEVICE_PCM_SAMPLE_RATE_STATE_FB = 1000209002, + XR_TYPE_FRAME_SYNTHESIS_INFO_EXT = 1000211000, + XR_TYPE_FRAME_SYNTHESIS_CONFIG_VIEW_EXT = 1000211001, XR_TYPE_COMPOSITION_LAYER_DEPTH_TEST_FB = 1000212000, XR_TYPE_LOCAL_DIMMING_FRAME_END_INFO_META = 1000216000, XR_TYPE_PASSTHROUGH_PREFERENCES_META = 1000217000, @@ -606,10 +624,14 @@ typedef enum XrStructureType { XR_TYPE_PASSTHROUGH_COLOR_MAP_INTERPOLATED_LUT_META = 1000266101, XR_TYPE_SPACE_TRIANGLE_MESH_GET_INFO_META = 1000269001, XR_TYPE_SPACE_TRIANGLE_MESH_META = 1000269002, + XR_TYPE_EVENT_DATA_PASSTHROUGH_LAYER_RESUMED_META = 1000282000, XR_TYPE_SYSTEM_FACE_TRACKING_PROPERTIES2_FB = 1000287013, XR_TYPE_FACE_TRACKER_CREATE_INFO2_FB = 1000287014, XR_TYPE_FACE_EXPRESSION_INFO2_FB = 1000287015, XR_TYPE_FACE_EXPRESSION_WEIGHTS2_FB = 1000287016, + XR_TYPE_SYSTEM_SPATIAL_ENTITY_SHARING_PROPERTIES_META = 1000290000, + XR_TYPE_SHARE_SPACES_INFO_META = 1000290001, + XR_TYPE_EVENT_DATA_SHARE_SPACES_COMPLETE_META = 1000290002, XR_TYPE_ENVIRONMENT_DEPTH_PROVIDER_CREATE_INFO_META = 1000291000, XR_TYPE_ENVIRONMENT_DEPTH_SWAPCHAIN_CREATE_INFO_META = 1000291001, XR_TYPE_ENVIRONMENT_DEPTH_SWAPCHAIN_STATE_META = 1000291002, @@ -635,6 +657,44 @@ typedef enum XrStructureType { XR_TYPE_ACTIVE_ACTION_SET_PRIORITIES_EXT = 1000373000, XR_TYPE_SYSTEM_FORCE_FEEDBACK_CURL_PROPERTIES_MNDX = 1000375000, XR_TYPE_FORCE_FEEDBACK_CURL_APPLY_LOCATIONS_MNDX = 1000375001, + XR_TYPE_BODY_TRACKER_CREATE_INFO_BD = 1000385001, + XR_TYPE_BODY_JOINTS_LOCATE_INFO_BD = 1000385002, + XR_TYPE_BODY_JOINT_LOCATIONS_BD = 1000385003, + XR_TYPE_SYSTEM_BODY_TRACKING_PROPERTIES_BD = 1000385004, + XR_TYPE_SYSTEM_SPATIAL_SENSING_PROPERTIES_BD = 1000389000, + XR_TYPE_SPATIAL_ENTITY_COMPONENT_GET_INFO_BD = 1000389001, + XR_TYPE_SPATIAL_ENTITY_LOCATION_GET_INFO_BD = 1000389002, + XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_LOCATION_BD = 1000389003, + XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_SEMANTIC_BD = 1000389004, + XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_BOUNDING_BOX_2D_BD = 1000389005, + XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_POLYGON_BD = 1000389006, + XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_BOUNDING_BOX_3D_BD = 1000389007, + XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_TRIANGLE_MESH_BD = 1000389008, + XR_TYPE_SENSE_DATA_PROVIDER_CREATE_INFO_BD = 1000389009, + XR_TYPE_SENSE_DATA_PROVIDER_START_INFO_BD = 1000389010, + XR_TYPE_EVENT_DATA_SENSE_DATA_PROVIDER_STATE_CHANGED_BD = 1000389011, + XR_TYPE_EVENT_DATA_SENSE_DATA_UPDATED_BD = 1000389012, + XR_TYPE_SENSE_DATA_QUERY_INFO_BD = 1000389013, + XR_TYPE_SENSE_DATA_QUERY_COMPLETION_BD = 1000389014, + XR_TYPE_SENSE_DATA_FILTER_UUID_BD = 1000389015, + XR_TYPE_SENSE_DATA_FILTER_SEMANTIC_BD = 1000389016, + XR_TYPE_QUERIED_SENSE_DATA_GET_INFO_BD = 1000389017, + XR_TYPE_QUERIED_SENSE_DATA_BD = 1000389018, + XR_TYPE_SPATIAL_ENTITY_STATE_BD = 1000389019, + XR_TYPE_SPATIAL_ENTITY_ANCHOR_CREATE_INFO_BD = 1000389020, + XR_TYPE_ANCHOR_SPACE_CREATE_INFO_BD = 1000389021, + XR_TYPE_SYSTEM_SPATIAL_ANCHOR_PROPERTIES_BD = 1000390000, + XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_BD = 1000390001, + XR_TYPE_SPATIAL_ANCHOR_CREATE_COMPLETION_BD = 1000390002, + XR_TYPE_SPATIAL_ANCHOR_PERSIST_INFO_BD = 1000390003, + XR_TYPE_SPATIAL_ANCHOR_UNPERSIST_INFO_BD = 1000390004, + XR_TYPE_SYSTEM_SPATIAL_ANCHOR_SHARING_PROPERTIES_BD = 1000391000, + XR_TYPE_SPATIAL_ANCHOR_SHARE_INFO_BD = 1000391001, + XR_TYPE_SHARED_SPATIAL_ANCHOR_DOWNLOAD_INFO_BD = 1000391002, + XR_TYPE_SYSTEM_SPATIAL_SCENE_PROPERTIES_BD = 1000392000, + XR_TYPE_SCENE_CAPTURE_INFO_BD = 1000392001, + XR_TYPE_SYSTEM_SPATIAL_MESH_PROPERTIES_BD = 1000393000, + XR_TYPE_SENSE_DATA_PROVIDER_CREATE_INFO_SPATIAL_MESH_BD = 1000393001, XR_TYPE_HAND_TRACKING_DATA_SOURCE_INFO_EXT = 1000428000, XR_TYPE_HAND_TRACKING_DATA_SOURCE_STATE_EXT = 1000428001, XR_TYPE_PLANE_DETECTOR_CREATE_INFO_EXT = 1000429001, @@ -663,6 +723,25 @@ typedef enum XrStructureType { XR_TYPE_WORLD_MESH_BLOCK_ML = 1000474010, XR_TYPE_WORLD_MESH_REQUEST_COMPLETION_ML = 1000474011, XR_TYPE_WORLD_MESH_REQUEST_COMPLETION_INFO_ML = 1000474012, + XR_TYPE_SYSTEM_FACIAL_EXPRESSION_PROPERTIES_ML = 1000482004, + XR_TYPE_FACIAL_EXPRESSION_CLIENT_CREATE_INFO_ML = 1000482005, + XR_TYPE_FACIAL_EXPRESSION_BLEND_SHAPE_GET_INFO_ML = 1000482006, + XR_TYPE_FACIAL_EXPRESSION_BLEND_SHAPE_PROPERTIES_ML = 1000482007, + XR_TYPE_COLOCATION_DISCOVERY_START_INFO_META = 1000571010, + XR_TYPE_COLOCATION_DISCOVERY_STOP_INFO_META = 1000571011, + XR_TYPE_COLOCATION_ADVERTISEMENT_START_INFO_META = 1000571012, + XR_TYPE_COLOCATION_ADVERTISEMENT_STOP_INFO_META = 1000571013, + XR_TYPE_EVENT_DATA_START_COLOCATION_ADVERTISEMENT_COMPLETE_META = 1000571020, + XR_TYPE_EVENT_DATA_STOP_COLOCATION_ADVERTISEMENT_COMPLETE_META = 1000571021, + XR_TYPE_EVENT_DATA_COLOCATION_ADVERTISEMENT_COMPLETE_META = 1000571022, + XR_TYPE_EVENT_DATA_START_COLOCATION_DISCOVERY_COMPLETE_META = 1000571023, + XR_TYPE_EVENT_DATA_COLOCATION_DISCOVERY_RESULT_META = 1000571024, + XR_TYPE_EVENT_DATA_COLOCATION_DISCOVERY_COMPLETE_META = 1000571025, + XR_TYPE_EVENT_DATA_STOP_COLOCATION_DISCOVERY_COMPLETE_META = 1000571026, + XR_TYPE_SYSTEM_COLOCATION_DISCOVERY_PROPERTIES_META = 1000571030, + XR_TYPE_SHARE_SPACES_RECIPIENT_GROUPS_META = 1000572000, + XR_TYPE_SPACE_GROUP_UUID_FILTER_INFO_META = 1000572001, + XR_TYPE_SYSTEM_SPATIAL_ENTITY_GROUP_SHARING_PROPERTIES_META = 1000572100, XR_TYPE_GRAPHICS_BINDING_VULKAN2_KHR = XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR, XR_TYPE_SWAPCHAIN_IMAGE_VULKAN2_KHR = XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR, XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN2_KHR = XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR, @@ -771,8 +850,13 @@ typedef enum XrObjectType { XR_OBJECT_TYPE_ENVIRONMENT_DEPTH_SWAPCHAIN_META = 1000291001, XR_OBJECT_TYPE_PASSTHROUGH_HTC = 1000317000, XR_OBJECT_TYPE_BODY_TRACKER_HTC = 1000320000, + XR_OBJECT_TYPE_BODY_TRACKER_BD = 1000385000, + XR_OBJECT_TYPE_SENSE_DATA_PROVIDER_BD = 1000389000, + XR_OBJECT_TYPE_SENSE_DATA_SNAPSHOT_BD = 1000389001, + XR_OBJECT_TYPE_ANCHOR_BD = 1000389002, XR_OBJECT_TYPE_PLANE_DETECTOR_EXT = 1000429000, XR_OBJECT_TYPE_WORLD_MESH_DETECTOR_ML = 1000474000, + XR_OBJECT_TYPE_FACIAL_EXPRESSION_CLIENT_ML = 1000482000, XR_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF } XrObjectType; typedef XrFlags64 XrInstanceCreateFlags; @@ -819,6 +903,7 @@ static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_KHR = typedef XrFlags64 XrCompositionLayerFlags; // Flag bits for XrCompositionLayerFlags +// XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT is deprecated and should not be used static const XrCompositionLayerFlags XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT = 0x00000001; static const XrCompositionLayerFlags XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT = 0x00000002; static const XrCompositionLayerFlags XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT = 0x00000004; @@ -1373,7 +1458,7 @@ typedef XrResult (XRAPI_PTR *PFN_xrEnumerateReferenceSpaces)(XrSession session, typedef XrResult (XRAPI_PTR *PFN_xrCreateReferenceSpace)(XrSession session, const XrReferenceSpaceCreateInfo* createInfo, XrSpace* space); typedef XrResult (XRAPI_PTR *PFN_xrGetReferenceSpaceBoundsRect)(XrSession session, XrReferenceSpaceType referenceSpaceType, XrExtent2Df* bounds); typedef XrResult (XRAPI_PTR *PFN_xrCreateActionSpace)(XrSession session, const XrActionSpaceCreateInfo* createInfo, XrSpace* space); -typedef XrResult (XRAPI_PTR *PFN_xrLocateSpace)(XrSpace space, XrSpace baseSpace, XrTime time, XrSpaceLocation* location); +typedef XrResult (XRAPI_PTR *PFN_xrLocateSpace)(XrSpace space, XrSpace baseSpace, XrTime time, XrSpaceLocation* location); typedef XrResult (XRAPI_PTR *PFN_xrDestroySpace)(XrSpace space); typedef XrResult (XRAPI_PTR *PFN_xrEnumerateViewConfigurations)(XrInstance instance, XrSystemId systemId, uint32_t viewConfigurationTypeCapacityInput, uint32_t* viewConfigurationTypeCountOutput, XrViewConfigurationType* viewConfigurationTypes); typedef XrResult (XRAPI_PTR *PFN_xrGetViewConfigurationProperties)(XrInstance instance, XrSystemId systemId, XrViewConfigurationType viewConfigurationType, XrViewConfigurationProperties* configurationProperties); @@ -1382,9 +1467,9 @@ typedef XrResult (XRAPI_PTR *PFN_xrEnumerateSwapchainFormats)(XrSession session, typedef XrResult (XRAPI_PTR *PFN_xrCreateSwapchain)(XrSession session, const XrSwapchainCreateInfo* createInfo, XrSwapchain* swapchain); typedef XrResult (XRAPI_PTR *PFN_xrDestroySwapchain)(XrSwapchain swapchain); typedef XrResult (XRAPI_PTR *PFN_xrEnumerateSwapchainImages)(XrSwapchain swapchain, uint32_t imageCapacityInput, uint32_t* imageCountOutput, XrSwapchainImageBaseHeader* images); -typedef XrResult (XRAPI_PTR *PFN_xrAcquireSwapchainImage)(XrSwapchain swapchain, const XrSwapchainImageAcquireInfo* acquireInfo, uint32_t* index); +typedef XrResult (XRAPI_PTR *PFN_xrAcquireSwapchainImage)(XrSwapchain swapchain, const XrSwapchainImageAcquireInfo* acquireInfo, uint32_t* index); typedef XrResult (XRAPI_PTR *PFN_xrWaitSwapchainImage)(XrSwapchain swapchain, const XrSwapchainImageWaitInfo* waitInfo); -typedef XrResult (XRAPI_PTR *PFN_xrReleaseSwapchainImage)(XrSwapchain swapchain, const XrSwapchainImageReleaseInfo* releaseInfo); +typedef XrResult (XRAPI_PTR *PFN_xrReleaseSwapchainImage)(XrSwapchain swapchain, const XrSwapchainImageReleaseInfo* releaseInfo); typedef XrResult (XRAPI_PTR *PFN_xrBeginSession)(XrSession session, const XrSessionBeginInfo* beginInfo); typedef XrResult (XRAPI_PTR *PFN_xrEndSession)(XrSession session); typedef XrResult (XRAPI_PTR *PFN_xrRequestExitSession)(XrSession session); @@ -1956,6 +2041,23 @@ typedef struct XrBindingModificationsKHR { +// XR_KHR_extended_struct_name_lengths is a preprocessor guard. Do not pass it to API calls. +#define XR_KHR_extended_struct_name_lengths 1 +#define XR_KHR_extended_struct_name_lengths_SPEC_VERSION 1 +#define XR_KHR_EXTENDED_STRUCT_NAME_LENGTHS_EXTENSION_NAME "XR_KHR_extended_struct_name_lengths" +#define XR_MAX_STRUCTURE_NAME_SIZE_EXTENDED_KHR 256 +typedef XrResult (XRAPI_PTR *PFN_xrStructureTypeToString2KHR)(XrInstance instance, XrStructureType value, char buffer[XR_MAX_STRUCTURE_NAME_SIZE_EXTENDED_KHR]); + +#ifndef XR_NO_PROTOTYPES +#ifdef XR_EXTENSION_PROTOTYPES +XRAPI_ATTR XrResult XRAPI_CALL xrStructureTypeToString2KHR( + XrInstance instance, + XrStructureType value, + char buffer[XR_MAX_STRUCTURE_NAME_SIZE_EXTENDED_KHR]); +#endif /* XR_EXTENSION_PROTOTYPES */ +#endif /* !XR_NO_PROTOTYPES */ + + // XR_KHR_swapchain_usage_input_attachment_bit is a preprocessor guard. Do not pass it to API calls. #define XR_KHR_swapchain_usage_input_attachment_bit 1 #define XR_KHR_swapchain_usage_input_attachment_bit_SPEC_VERSION 3 @@ -2142,7 +2244,7 @@ typedef struct XrDebugUtilsMessengerCreateInfoEXT { typedef XrResult (XRAPI_PTR *PFN_xrSetDebugUtilsObjectNameEXT)(XrInstance instance, const XrDebugUtilsObjectNameInfoEXT* nameInfo); typedef XrResult (XRAPI_PTR *PFN_xrCreateDebugUtilsMessengerEXT)(XrInstance instance, const XrDebugUtilsMessengerCreateInfoEXT* createInfo, XrDebugUtilsMessengerEXT* messenger); typedef XrResult (XRAPI_PTR *PFN_xrDestroyDebugUtilsMessengerEXT)(XrDebugUtilsMessengerEXT messenger); -typedef XrResult (XRAPI_PTR *PFN_xrSubmitDebugUtilsMessageEXT)(XrInstance instance, XrDebugUtilsMessageSeverityFlagsEXT messageSeverity, XrDebugUtilsMessageTypeFlagsEXT messageTypes, const XrDebugUtilsMessengerCallbackDataEXT* callbackData); +typedef XrResult (XRAPI_PTR *PFN_xrSubmitDebugUtilsMessageEXT)(XrInstance instance, XrDebugUtilsMessageSeverityFlagsEXT messageSeverity, XrDebugUtilsMessageTypeFlagsEXT messageTypes, const XrDebugUtilsMessengerCallbackDataEXT* callbackData); typedef XrResult (XRAPI_PTR *PFN_xrSessionBeginDebugUtilsLabelRegionEXT)(XrSession session, const XrDebugUtilsLabelEXT* labelInfo); typedef XrResult (XRAPI_PTR *PFN_xrSessionEndDebugUtilsLabelRegionEXT)(XrSession session); typedef XrResult (XRAPI_PTR *PFN_xrSessionInsertDebugUtilsLabelEXT)(XrSession session, const XrDebugUtilsLabelEXT* labelInfo); @@ -2161,7 +2263,7 @@ XRAPI_ATTR XrResult XRAPI_CALL xrCreateDebugUtilsMessengerEXT( XRAPI_ATTR XrResult XRAPI_CALL xrDestroyDebugUtilsMessengerEXT( XrDebugUtilsMessengerEXT messenger); -XRAPI_ATTR XrResult XRAPI_CALL xrSubmitDebugUtilsMessageEXT( +XRAPI_ATTR XrResult XRAPI_CALL xrSubmitDebugUtilsMessageEXT( XrInstance instance, XrDebugUtilsMessageSeverityFlagsEXT messageSeverity, XrDebugUtilsMessageTypeFlagsEXT messageTypes, @@ -3620,7 +3722,7 @@ XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViveTrackerPathsHTCX( #define XR_FACIAL_EXPRESSION_LIP_COUNT_HTC 37 XR_DEFINE_HANDLE(XrFacialTrackerHTC) -#define XR_HTC_facial_tracking_SPEC_VERSION 2 +#define XR_HTC_facial_tracking_SPEC_VERSION 3 #define XR_HTC_FACIAL_TRACKING_EXTENSION_NAME "XR_HTC_facial_tracking" typedef enum XrEyeExpressionHTC { @@ -3654,10 +3756,10 @@ typedef enum XrLipExpressionHTC { XR_LIP_EXPRESSION_MOUTH_UPPER_OVERTURN_HTC = 9, XR_LIP_EXPRESSION_MOUTH_LOWER_OVERTURN_HTC = 10, XR_LIP_EXPRESSION_MOUTH_POUT_HTC = 11, - XR_LIP_EXPRESSION_MOUTH_SMILE_RIGHT_HTC = 12, - XR_LIP_EXPRESSION_MOUTH_SMILE_LEFT_HTC = 13, - XR_LIP_EXPRESSION_MOUTH_SAD_RIGHT_HTC = 14, - XR_LIP_EXPRESSION_MOUTH_SAD_LEFT_HTC = 15, + XR_LIP_EXPRESSION_MOUTH_RAISER_RIGHT_HTC = 12, + XR_LIP_EXPRESSION_MOUTH_RAISER_LEFT_HTC = 13, + XR_LIP_EXPRESSION_MOUTH_STRETCHER_RIGHT_HTC = 14, + XR_LIP_EXPRESSION_MOUTH_STRETCHER_LEFT_HTC = 15, XR_LIP_EXPRESSION_CHEEK_PUFF_RIGHT_HTC = 16, XR_LIP_EXPRESSION_CHEEK_PUFF_LEFT_HTC = 17, XR_LIP_EXPRESSION_CHEEK_SUCK_HTC = 18, @@ -3679,6 +3781,10 @@ typedef enum XrLipExpressionHTC { XR_LIP_EXPRESSION_TONGUE_UPLEFT_MORPH_HTC = 34, XR_LIP_EXPRESSION_TONGUE_DOWNRIGHT_MORPH_HTC = 35, XR_LIP_EXPRESSION_TONGUE_DOWNLEFT_MORPH_HTC = 36, + XR_LIP_EXPRESSION_MOUTH_SMILE_RIGHT_HTC = XR_LIP_EXPRESSION_MOUTH_RAISER_RIGHT_HTC, + XR_LIP_EXPRESSION_MOUTH_SMILE_LEFT_HTC = XR_LIP_EXPRESSION_MOUTH_RAISER_LEFT_HTC, + XR_LIP_EXPRESSION_MOUTH_SAD_RIGHT_HTC = XR_LIP_EXPRESSION_MOUTH_STRETCHER_RIGHT_HTC, + XR_LIP_EXPRESSION_MOUTH_SAD_LEFT_HTC = XR_LIP_EXPRESSION_MOUTH_STRETCHER_LEFT_HTC, XR_LIP_EXPRESSION_MAX_ENUM_HTC = 0x7FFFFFFF } XrLipExpressionHTC; @@ -4574,7 +4680,7 @@ typedef struct XrMarkerSpaceCreateInfoVARJO { XrPosef poseInMarkerSpace; } XrMarkerSpaceCreateInfoVARJO; -typedef XrResult (XRAPI_PTR *PFN_xrSetMarkerTrackingVARJO)(XrSession session, XrBool32 enabled); +typedef XrResult (XRAPI_PTR *PFN_xrSetMarkerTrackingVARJO)(XrSession session, XrBool32 enabled); typedef XrResult (XRAPI_PTR *PFN_xrSetMarkerTrackingTimeoutVARJO)(XrSession session, uint64_t markerId, XrDuration timeout); typedef XrResult (XRAPI_PTR *PFN_xrSetMarkerTrackingPredictionVARJO)(XrSession session, uint64_t markerId, XrBool32 enable); typedef XrResult (XRAPI_PTR *PFN_xrGetMarkerSizeVARJO)(XrSession session, uint64_t markerId, XrExtent2Df* size); @@ -4582,7 +4688,7 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateMarkerSpaceVARJO)(XrSession session, co #ifndef XR_NO_PROTOTYPES #ifdef XR_EXTENSION_PROTOTYPES -XRAPI_ATTR XrResult XRAPI_CALL xrSetMarkerTrackingVARJO( +XRAPI_ATTR XrResult XRAPI_CALL xrSetMarkerTrackingVARJO( XrSession session, XrBool32 enabled); @@ -4613,11 +4719,11 @@ XRAPI_ATTR XrResult XRAPI_CALL xrCreateMarkerSpaceVARJO( #define XR_VARJO_view_offset 1 #define XR_VARJO_view_offset_SPEC_VERSION 1 #define XR_VARJO_VIEW_OFFSET_EXTENSION_NAME "XR_VARJO_view_offset" -typedef XrResult (XRAPI_PTR *PFN_xrSetViewOffsetVARJO)(XrSession session, float offset); +typedef XrResult (XRAPI_PTR *PFN_xrSetViewOffsetVARJO)(XrSession session, float offset); #ifndef XR_NO_PROTOTYPES #ifdef XR_EXTENSION_PROTOTYPES -XRAPI_ATTR XrResult XRAPI_CALL xrSetViewOffsetVARJO( +XRAPI_ATTR XrResult XRAPI_CALL xrSetViewOffsetVARJO( XrSession session, float offset); #endif /* XR_EXTENSION_PROTOTYPES */ @@ -4626,7 +4732,7 @@ XRAPI_ATTR XrResult XRAPI_CALL xrSetViewOffsetVARJO( // XR_VARJO_xr4_controller_interaction is a preprocessor guard. Do not pass it to API calls. #define XR_VARJO_xr4_controller_interaction 1 -#define XR_VARJO_xr4_controller_interaction_SPEC_VERSION 1 +#define XR_VARJO_xr4_controller_interaction_SPEC_VERSION 2 #define XR_VARJO_XR4_CONTROLLER_INTERACTION_EXTENSION_NAME "XR_VARJO_xr4_controller_interaction" @@ -4990,7 +5096,7 @@ typedef XrResult (XRAPI_PTR *PFN_xrRequestMapLocalizationML)(XrSession session, typedef XrResult (XRAPI_PTR *PFN_xrImportLocalizationMapML)(XrSession session, const XrLocalizationMapImportInfoML* importInfo, XrUuidEXT* mapUuid); typedef XrResult (XRAPI_PTR *PFN_xrCreateExportedLocalizationMapML)(XrSession session, const XrUuidEXT* mapUuid, XrExportedLocalizationMapML* map); typedef XrResult (XRAPI_PTR *PFN_xrDestroyExportedLocalizationMapML)(XrExportedLocalizationMapML map); -typedef XrResult (XRAPI_PTR *PFN_xrGetExportedLocalizationMapDataML)(XrExportedLocalizationMapML map, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer); +typedef XrResult (XRAPI_PTR *PFN_xrGetExportedLocalizationMapDataML)(XrExportedLocalizationMapML map, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer); #ifndef XR_NO_PROTOTYPES #ifdef XR_EXTENSION_PROTOTYPES @@ -5299,7 +5405,7 @@ typedef XrResult (XRAPI_PTR *PFN_xrDestroySpatialAnchorStoreConnectionMSFT)(XrSp typedef XrResult (XRAPI_PTR *PFN_xrPersistSpatialAnchorMSFT)(XrSpatialAnchorStoreConnectionMSFT spatialAnchorStore, const XrSpatialAnchorPersistenceInfoMSFT* spatialAnchorPersistenceInfo); typedef XrResult (XRAPI_PTR *PFN_xrEnumeratePersistedSpatialAnchorNamesMSFT)(XrSpatialAnchorStoreConnectionMSFT spatialAnchorStore, uint32_t spatialAnchorNameCapacityInput, uint32_t* spatialAnchorNameCountOutput, XrSpatialAnchorPersistenceNameMSFT* spatialAnchorNames); typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorFromPersistedNameMSFT)(XrSession session, const XrSpatialAnchorFromPersistedAnchorCreateInfoMSFT* spatialAnchorCreateInfo, XrSpatialAnchorMSFT* spatialAnchor); -typedef XrResult (XRAPI_PTR *PFN_xrUnpersistSpatialAnchorMSFT)(XrSpatialAnchorStoreConnectionMSFT spatialAnchorStore, const XrSpatialAnchorPersistenceNameMSFT* spatialAnchorPersistenceName); +typedef XrResult (XRAPI_PTR *PFN_xrUnpersistSpatialAnchorMSFT)(XrSpatialAnchorStoreConnectionMSFT spatialAnchorStore, const XrSpatialAnchorPersistenceNameMSFT* spatialAnchorPersistenceName); typedef XrResult (XRAPI_PTR *PFN_xrClearSpatialAnchorStoreMSFT)(XrSpatialAnchorStoreConnectionMSFT spatialAnchorStore); #ifndef XR_NO_PROTOTYPES @@ -6224,6 +6330,42 @@ XRAPI_ATTR XrResult XRAPI_CALL xrGetDeviceSampleRateFB( #endif /* !XR_NO_PROTOTYPES */ +// XR_EXT_frame_synthesis is a preprocessor guard. Do not pass it to API calls. +#define XR_EXT_frame_synthesis 1 +#define XR_EXT_frame_synthesis_SPEC_VERSION 1 +#define XR_EXT_FRAME_SYNTHESIS_EXTENSION_NAME "XR_EXT_frame_synthesis" +typedef XrFlags64 XrFrameSynthesisInfoFlagsEXT; + +// Flag bits for XrFrameSynthesisInfoFlagsEXT +static const XrFrameSynthesisInfoFlagsEXT XR_FRAME_SYNTHESIS_INFO_USE_2D_MOTION_VECTOR_BIT_EXT = 0x00000001; +static const XrFrameSynthesisInfoFlagsEXT XR_FRAME_SYNTHESIS_INFO_REQUEST_RELAXED_FRAME_INTERVAL_BIT_EXT = 0x00000002; + +// XrFrameSynthesisInfoEXT extends XrCompositionLayerProjectionView +typedef struct XrFrameSynthesisInfoEXT { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrFrameSynthesisInfoFlagsEXT layerFlags; + XrSwapchainSubImage motionVectorSubImage; + XrVector4f motionVectorScale; + XrVector4f motionVectorOffset; + XrPosef appSpaceDeltaPose; + XrSwapchainSubImage depthSubImage; + float minDepth; + float maxDepth; + float nearZ; + float farZ; +} XrFrameSynthesisInfoEXT; + +// XrFrameSynthesisConfigViewEXT extends XrViewConfigurationView +typedef struct XrFrameSynthesisConfigViewEXT { + XrStructureType type; + void* XR_MAY_ALIAS next; + uint32_t recommendedMotionVectorImageRectWidth; + uint32_t recommendedMotionVectorImageRectHeight; +} XrFrameSynthesisConfigViewEXT; + + + // XR_FB_composition_layer_depth_test is a preprocessor guard. Do not pass it to API calls. #define XR_FB_composition_layer_depth_test 1 #define XR_FB_composition_layer_depth_test_SPEC_VERSION 1 @@ -6651,6 +6793,12 @@ XRAPI_ATTR XrResult XRAPI_CALL xrSaveSpaceListFB( #endif /* !XR_NO_PROTOTYPES */ +// XR_META_detached_controllers is a preprocessor guard. Do not pass it to API calls. +#define XR_META_detached_controllers 1 +#define XR_META_detached_controllers_SPEC_VERSION 1 +#define XR_META_DETACHED_CONTROLLERS_EXTENSION_NAME "XR_META_detached_controllers" + + // XR_FB_spatial_entity_user is a preprocessor guard. Do not pass it to API calls. #define XR_FB_spatial_entity_user 1 typedef uint64_t XrSpaceUserIdFB; @@ -6696,6 +6844,12 @@ typedef struct XrSystemHeadsetIdPropertiesMETA { +// XR_META_hand_tracking_microgestures is a preprocessor guard. Do not pass it to API calls. +#define XR_META_hand_tracking_microgestures 1 +#define XR_META_hand_tracking_microgestures_SPEC_VERSION 1 +#define XR_META_HAND_TRACKING_MICROGESTURES_EXTENSION_NAME "XR_META_hand_tracking_microgestures" + + // XR_META_recommended_layer_resolution is a preprocessor guard. Do not pass it to API calls. #define XR_META_recommended_layer_resolution 1 #define XR_META_recommended_layer_resolution_SPEC_VERSION 1 @@ -6845,6 +6999,18 @@ XRAPI_ATTR XrResult XRAPI_CALL xrGetSpaceTriangleMeshMETA( #define XR_META_TOUCH_CONTROLLER_PLUS_EXTENSION_NAME "XR_META_touch_controller_plus" +// XR_META_passthrough_layer_resumed_event is a preprocessor guard. Do not pass it to API calls. +#define XR_META_passthrough_layer_resumed_event 1 +#define XR_META_passthrough_layer_resumed_event_SPEC_VERSION 1 +#define XR_META_PASSTHROUGH_LAYER_RESUMED_EVENT_EXTENSION_NAME "XR_META_passthrough_layer_resumed_event" +typedef struct XrEventDataPassthroughLayerResumedMETA { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrPassthroughLayerFB layer; +} XrEventDataPassthroughLayerResumedMETA; + + + // XR_FB_face_tracking2 is a preprocessor guard. Do not pass it to API calls. #define XR_FB_face_tracking2 1 XR_DEFINE_HANDLE(XrFaceTracker2FB) @@ -7000,6 +7166,50 @@ XRAPI_ATTR XrResult XRAPI_CALL xrGetFaceExpressionWeights2FB( #endif /* !XR_NO_PROTOTYPES */ +// XR_META_spatial_entity_sharing is a preprocessor guard. Do not pass it to API calls. +#define XR_META_spatial_entity_sharing 1 +#define XR_META_spatial_entity_sharing_SPEC_VERSION 1 +#define XR_META_SPATIAL_ENTITY_SHARING_EXTENSION_NAME "XR_META_spatial_entity_sharing" +#define XR_MAX_SPACES_PER_SHARE_REQUEST_META 32 +// XrSystemSpatialEntitySharingPropertiesMETA extends XrSystemProperties +typedef struct XrSystemSpatialEntitySharingPropertiesMETA { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrBool32 supportsSpatialEntitySharing; +} XrSystemSpatialEntitySharingPropertiesMETA; + +typedef struct XR_MAY_ALIAS XrShareSpacesRecipientBaseHeaderMETA { + XrStructureType type; + const void* XR_MAY_ALIAS next; +} XrShareSpacesRecipientBaseHeaderMETA; + +typedef struct XrShareSpacesInfoMETA { + XrStructureType type; + const void* XR_MAY_ALIAS next; + uint32_t spaceCount; + XrSpace* spaces; + const XrShareSpacesRecipientBaseHeaderMETA* recipientInfo; +} XrShareSpacesInfoMETA; + +typedef struct XrEventDataShareSpacesCompleteMETA { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrAsyncRequestIdFB requestId; + XrResult result; +} XrEventDataShareSpacesCompleteMETA; + +typedef XrResult (XRAPI_PTR *PFN_xrShareSpacesMETA)(XrSession session, const XrShareSpacesInfoMETA* info, XrAsyncRequestIdFB* requestId); + +#ifndef XR_NO_PROTOTYPES +#ifdef XR_EXTENSION_PROTOTYPES +XRAPI_ATTR XrResult XRAPI_CALL xrShareSpacesMETA( + XrSession session, + const XrShareSpacesInfoMETA* info, + XrAsyncRequestIdFB* requestId); +#endif /* XR_EXTENSION_PROTOTYPES */ +#endif /* !XR_NO_PROTOTYPES */ + + // XR_META_environment_depth is a preprocessor guard. Do not pass it to API calls. #define XR_META_environment_depth 1 XR_DEFINE_HANDLE(XrEnvironmentDepthProviderMETA) @@ -7533,6 +7743,645 @@ XRAPI_ATTR XrResult XRAPI_CALL xrApplyForceFeedbackCurlMNDX( #define XR_BD_CONTROLLER_INTERACTION_EXTENSION_NAME "XR_BD_controller_interaction" +// XR_BD_body_tracking is a preprocessor guard. Do not pass it to API calls. +#define XR_BD_body_tracking 1 + +#define XR_BODY_JOINT_COUNT_BD 24 + + +#define XR_BODY_JOINT_WITHOUT_ARM_COUNT_BD 16 + +XR_DEFINE_HANDLE(XrBodyTrackerBD) +#define XR_BD_body_tracking_SPEC_VERSION 1 +#define XR_BD_BODY_TRACKING_EXTENSION_NAME "XR_BD_body_tracking" + +typedef enum XrBodyJointBD { + XR_BODY_JOINT_PELVIS_BD = 0, + XR_BODY_JOINT_LEFT_HIP_BD = 1, + XR_BODY_JOINT_RIGHT_HIP_BD = 2, + XR_BODY_JOINT_SPINE1_BD = 3, + XR_BODY_JOINT_LEFT_KNEE_BD = 4, + XR_BODY_JOINT_RIGHT_KNEE_BD = 5, + XR_BODY_JOINT_SPINE2_BD = 6, + XR_BODY_JOINT_LEFT_ANKLE_BD = 7, + XR_BODY_JOINT_RIGHT_ANKLE_BD = 8, + XR_BODY_JOINT_SPINE3_BD = 9, + XR_BODY_JOINT_LEFT_FOOT_BD = 10, + XR_BODY_JOINT_RIGHT_FOOT_BD = 11, + XR_BODY_JOINT_NECK_BD = 12, + XR_BODY_JOINT_LEFT_COLLAR_BD = 13, + XR_BODY_JOINT_RIGHT_COLLAR_BD = 14, + XR_BODY_JOINT_HEAD_BD = 15, + XR_BODY_JOINT_LEFT_SHOULDER_BD = 16, + XR_BODY_JOINT_RIGHT_SHOULDER_BD = 17, + XR_BODY_JOINT_LEFT_ELBOW_BD = 18, + XR_BODY_JOINT_RIGHT_ELBOW_BD = 19, + XR_BODY_JOINT_LEFT_WRIST_BD = 20, + XR_BODY_JOINT_RIGHT_WRIST_BD = 21, + XR_BODY_JOINT_LEFT_HAND_BD = 22, + XR_BODY_JOINT_RIGHT_HAND_BD = 23, + XR_BODY_JOINT_MAX_ENUM_BD = 0x7FFFFFFF +} XrBodyJointBD; + +typedef enum XrBodyJointSetBD { + XR_BODY_JOINT_SET_BODY_WITHOUT_ARM_BD = 1, + XR_BODY_JOINT_SET_FULL_BODY_JOINTS_BD = 2, + XR_BODY_JOINT_SET_MAX_ENUM_BD = 0x7FFFFFFF +} XrBodyJointSetBD; +// XrSystemBodyTrackingPropertiesBD extends XrSystemProperties +typedef struct XrSystemBodyTrackingPropertiesBD { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrBool32 supportsBodyTracking; +} XrSystemBodyTrackingPropertiesBD; + +typedef struct XrBodyTrackerCreateInfoBD { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrBodyJointSetBD jointSet; +} XrBodyTrackerCreateInfoBD; + +typedef struct XrBodyJointsLocateInfoBD { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrSpace baseSpace; + XrTime time; +} XrBodyJointsLocateInfoBD; + +typedef struct XrBodyJointLocationBD { + XrSpaceLocationFlags locationFlags; + XrPosef pose; +} XrBodyJointLocationBD; + +typedef struct XrBodyJointLocationsBD { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrBool32 allJointPosesTracked; + uint32_t jointLocationCount; + XrBodyJointLocationBD* jointLocations; +} XrBodyJointLocationsBD; + +typedef XrResult (XRAPI_PTR *PFN_xrCreateBodyTrackerBD)(XrSession session, const XrBodyTrackerCreateInfoBD* createInfo, XrBodyTrackerBD* bodyTracker); +typedef XrResult (XRAPI_PTR *PFN_xrDestroyBodyTrackerBD)(XrBodyTrackerBD bodyTracker); +typedef XrResult (XRAPI_PTR *PFN_xrLocateBodyJointsBD)(XrBodyTrackerBD bodyTracker, const XrBodyJointsLocateInfoBD* locateInfo, XrBodyJointLocationsBD* locations); + +#ifndef XR_NO_PROTOTYPES +#ifdef XR_EXTENSION_PROTOTYPES +XRAPI_ATTR XrResult XRAPI_CALL xrCreateBodyTrackerBD( + XrSession session, + const XrBodyTrackerCreateInfoBD* createInfo, + XrBodyTrackerBD* bodyTracker); + +XRAPI_ATTR XrResult XRAPI_CALL xrDestroyBodyTrackerBD( + XrBodyTrackerBD bodyTracker); + +XRAPI_ATTR XrResult XRAPI_CALL xrLocateBodyJointsBD( + XrBodyTrackerBD bodyTracker, + const XrBodyJointsLocateInfoBD* locateInfo, + XrBodyJointLocationsBD* locations); +#endif /* XR_EXTENSION_PROTOTYPES */ +#endif /* !XR_NO_PROTOTYPES */ + + +// XR_BD_spatial_sensing is a preprocessor guard. Do not pass it to API calls. +#define XR_BD_spatial_sensing 1 +XR_DEFINE_ATOM(XrSpatialEntityIdBD) +XR_DEFINE_HANDLE(XrSenseDataProviderBD) +XR_DEFINE_HANDLE(XrSenseDataSnapshotBD) +XR_DEFINE_HANDLE(XrAnchorBD) +#define XR_BD_spatial_sensing_SPEC_VERSION 1 +#define XR_BD_SPATIAL_SENSING_EXTENSION_NAME "XR_BD_spatial_sensing" + +typedef enum XrSpatialEntityComponentTypeBD { + XR_SPATIAL_ENTITY_COMPONENT_TYPE_LOCATION_BD = 0, + XR_SPATIAL_ENTITY_COMPONENT_TYPE_SEMANTIC_BD = 1, + XR_SPATIAL_ENTITY_COMPONENT_TYPE_BOUNDING_BOX_2D_BD = 2, + XR_SPATIAL_ENTITY_COMPONENT_TYPE_POLYGON_BD = 3, + XR_SPATIAL_ENTITY_COMPONENT_TYPE_BOUNDING_BOX_3D_BD = 4, + XR_SPATIAL_ENTITY_COMPONENT_TYPE_TRIANGLE_MESH_BD = 5, + XR_SPATIAL_ENTITY_COMPONENT_TYPE_MAX_ENUM_BD = 0x7FFFFFFF +} XrSpatialEntityComponentTypeBD; + +typedef enum XrSemanticLabelBD { + XR_SEMANTIC_LABEL_UNKNOWN_BD = 0, + XR_SEMANTIC_LABEL_FLOOR_BD = 1, + XR_SEMANTIC_LABEL_CEILING_BD = 2, + XR_SEMANTIC_LABEL_WALL_BD = 3, + XR_SEMANTIC_LABEL_DOOR_BD = 4, + XR_SEMANTIC_LABEL_WINDOW_BD = 5, + XR_SEMANTIC_LABEL_OPENING_BD = 6, + XR_SEMANTIC_LABEL_TABLE_BD = 7, + XR_SEMANTIC_LABEL_SOFA_BD = 8, + XR_SEMANTIC_LABEL_CHAIR_BD = 9, + XR_SEMANTIC_LABEL_HUMAN_BD = 10, + XR_SEMANTIC_LABEL_BEAM_BD = 11, + XR_SEMANTIC_LABEL_COLUMN_BD = 12, + XR_SEMANTIC_LABEL_CURTAIN_BD = 13, + XR_SEMANTIC_LABEL_CABINET_BD = 14, + XR_SEMANTIC_LABEL_BED_BD = 15, + XR_SEMANTIC_LABEL_PLANT_BD = 16, + XR_SEMANTIC_LABEL_SCREEN_BD = 17, + XR_SEMANTIC_LABEL_VIRTUAL_WALL_BD = 18, + XR_SEMANTIC_LABEL_REFRIGERATOR_BD = 19, + XR_SEMANTIC_LABEL_WASHING_MACHINE_BD = 20, + XR_SEMANTIC_LABEL_AIR_CONDITIONER_BD = 21, + XR_SEMANTIC_LABEL_LAMP_BD = 22, + XR_SEMANTIC_LABEL_WALL_ART_BD = 23, + XR_SEMANTIC_LABEL_STAIRWAY_BD = 24, + XR_SEMANTIC_LABEL_MAX_ENUM_BD = 0x7FFFFFFF +} XrSemanticLabelBD; + +typedef enum XrSenseDataProviderTypeBD { + XR_SENSE_DATA_PROVIDER_TYPE_ANCHOR_BD = 1000390000, + XR_SENSE_DATA_PROVIDER_TYPE_SCENE_BD = 1000392000, + XR_SENSE_DATA_PROVIDER_TYPE_MESH_BD = 1000393000, + XR_SENSE_DATA_PROVIDER_TYPE_MAX_ENUM_BD = 0x7FFFFFFF +} XrSenseDataProviderTypeBD; + +typedef enum XrSenseDataProviderStateBD { + XR_SENSE_DATA_PROVIDER_STATE_INITIALIZED_BD = 0, + XR_SENSE_DATA_PROVIDER_STATE_RUNNING_BD = 1, + XR_SENSE_DATA_PROVIDER_STATE_STOPPED_BD = 2, + XR_SENSE_DATA_PROVIDER_STATE_MAX_ENUM_BD = 0x7FFFFFFF +} XrSenseDataProviderStateBD; +// XrSystemSpatialSensingPropertiesBD extends XrSystemProperties +typedef struct XrSystemSpatialSensingPropertiesBD { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrBool32 supportsSpatialSensing; +} XrSystemSpatialSensingPropertiesBD; + +typedef struct XrSpatialEntityComponentGetInfoBD { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrSpatialEntityIdBD entityId; + XrSpatialEntityComponentTypeBD componentType; +} XrSpatialEntityComponentGetInfoBD; + +typedef struct XrSpatialEntityComponentDataBaseHeaderBD { + XrStructureType type; + void* XR_MAY_ALIAS next; +} XrSpatialEntityComponentDataBaseHeaderBD; + +typedef struct XrSpatialEntityLocationGetInfoBD { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrSpace baseSpace; +} XrSpatialEntityLocationGetInfoBD; + +// XrSpatialEntityComponentDataLocationBD extends XrSpatialEntityComponentDataBaseHeaderBD +typedef struct XrSpatialEntityComponentDataLocationBD { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrSpaceLocation location; +} XrSpatialEntityComponentDataLocationBD; + +// XrSpatialEntityComponentDataSemanticBD extends XrSpatialEntityComponentDataBaseHeaderBD +typedef struct XrSpatialEntityComponentDataSemanticBD { + XrStructureType type; + void* XR_MAY_ALIAS next; + uint32_t labelCapacityInput; + uint32_t labelCountOutput; + XrSemanticLabelBD* labels; +} XrSpatialEntityComponentDataSemanticBD; + +// XrSpatialEntityComponentDataBoundingBox2DBD extends XrSpatialEntityComponentDataBaseHeaderBD +typedef struct XrSpatialEntityComponentDataBoundingBox2DBD { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrRect2Df boundingBox2D; +} XrSpatialEntityComponentDataBoundingBox2DBD; + +// XrSpatialEntityComponentDataPolygonBD extends XrSpatialEntityComponentDataBaseHeaderBD +typedef struct XrSpatialEntityComponentDataPolygonBD { + XrStructureType type; + void* XR_MAY_ALIAS next; + uint32_t vertexCapacityInput; + uint32_t vertexCountOutput; + XrVector2f* vertices; +} XrSpatialEntityComponentDataPolygonBD; + +// XrSpatialEntityComponentDataBoundingBox3DBD extends XrSpatialEntityComponentDataBaseHeaderBD +typedef struct XrSpatialEntityComponentDataBoundingBox3DBD { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrBoxf boundingBox3D; +} XrSpatialEntityComponentDataBoundingBox3DBD; + +// XrSpatialEntityComponentDataTriangleMeshBD extends XrSpatialEntityComponentDataBaseHeaderBD +typedef struct XrSpatialEntityComponentDataTriangleMeshBD { + XrStructureType type; + void* XR_MAY_ALIAS next; + uint32_t vertexCapacityInput; + uint32_t vertexCountOutput; + XrVector3f* vertices; + uint32_t indexCapacityInput; + uint32_t indexCountOutput; + uint16_t* indices; +} XrSpatialEntityComponentDataTriangleMeshBD; + +typedef struct XrSenseDataProviderCreateInfoBD { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrSenseDataProviderTypeBD providerType; +} XrSenseDataProviderCreateInfoBD; + +typedef struct XrSenseDataProviderStartInfoBD { + XrStructureType type; + const void* XR_MAY_ALIAS next; +} XrSenseDataProviderStartInfoBD; + +typedef struct XrEventDataSenseDataProviderStateChangedBD { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrSenseDataProviderBD provider; + XrSenseDataProviderStateBD newState; +} XrEventDataSenseDataProviderStateChangedBD; + +typedef struct XrEventDataSenseDataUpdatedBD { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrSenseDataProviderBD provider; +} XrEventDataSenseDataUpdatedBD; + +typedef struct XrSenseDataQueryInfoBD { + XrStructureType type; + const void* XR_MAY_ALIAS next; +} XrSenseDataQueryInfoBD; + +typedef struct XrSenseDataQueryCompletionBD { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrResult futureResult; + XrSenseDataSnapshotBD snapshot; +} XrSenseDataQueryCompletionBD; + +typedef struct XrQueriedSenseDataGetInfoBD { + XrStructureType type; + const void* XR_MAY_ALIAS next; +} XrQueriedSenseDataGetInfoBD; + +typedef struct XrSpatialEntityStateBD { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrSpatialEntityIdBD entityId; + XrTime lastUpdateTime; + XrUuidEXT uuid; +} XrSpatialEntityStateBD; + +typedef struct XrQueriedSenseDataBD { + XrStructureType type; + void* XR_MAY_ALIAS next; + uint32_t stateCapacityInput; + uint32_t stateCountOutput; + XrSpatialEntityStateBD* states; +} XrQueriedSenseDataBD; + +// XrSenseDataFilterUuidBD extends XrSenseDataQueryInfoBD +typedef struct XrSenseDataFilterUuidBD { + XrStructureType type; + const void* XR_MAY_ALIAS next; + uint32_t uuidCount; + const XrUuidEXT* uuids; +} XrSenseDataFilterUuidBD; + +// XrSenseDataFilterSemanticBD extends XrSenseDataQueryInfoBD +typedef struct XrSenseDataFilterSemanticBD { + XrStructureType type; + const void* XR_MAY_ALIAS next; + uint32_t labelCount; + const XrSemanticLabelBD* labels; +} XrSenseDataFilterSemanticBD; + +typedef struct XrSpatialEntityAnchorCreateInfoBD { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrSenseDataSnapshotBD snapshot; + XrSpatialEntityIdBD entityId; +} XrSpatialEntityAnchorCreateInfoBD; + +typedef struct XrAnchorSpaceCreateInfoBD { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrAnchorBD anchor; + XrPosef poseInAnchorSpace; +} XrAnchorSpaceCreateInfoBD; + +typedef struct XrFutureCompletionEXT { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrResult futureResult; +} XrFutureCompletionEXT; + +typedef XrResult (XRAPI_PTR *PFN_xrEnumerateSpatialEntityComponentTypesBD)(XrSenseDataSnapshotBD snapshot, XrSpatialEntityIdBD entityId, uint32_t componentTypeCapacityInput, uint32_t* componentTypeCountOutput, XrSpatialEntityComponentTypeBD* componentTypes); +typedef XrResult (XRAPI_PTR *PFN_xrGetSpatialEntityUuidBD)(XrSenseDataSnapshotBD snapshot, XrSpatialEntityIdBD entityId, XrUuidEXT* uuid); +typedef XrResult (XRAPI_PTR *PFN_xrGetSpatialEntityComponentDataBD)(XrSenseDataSnapshotBD snapshot, const XrSpatialEntityComponentGetInfoBD* getInfo, XrSpatialEntityComponentDataBaseHeaderBD* componentData); +typedef XrResult (XRAPI_PTR *PFN_xrCreateSenseDataProviderBD)(XrSession session, const XrSenseDataProviderCreateInfoBD* createInfo, XrSenseDataProviderBD* provider); +typedef XrResult (XRAPI_PTR *PFN_xrStartSenseDataProviderAsyncBD)(XrSenseDataProviderBD provider, const XrSenseDataProviderStartInfoBD* startInfo, XrFutureEXT* future); +typedef XrResult (XRAPI_PTR *PFN_xrStartSenseDataProviderCompleteBD)(XrSession session, XrFutureEXT future, XrFutureCompletionEXT* completion); +typedef XrResult (XRAPI_PTR *PFN_xrGetSenseDataProviderStateBD)(XrSenseDataProviderBD provider, XrSenseDataProviderStateBD* state); +typedef XrResult (XRAPI_PTR *PFN_xrQuerySenseDataAsyncBD)(XrSenseDataProviderBD provider, const XrSenseDataQueryInfoBD* queryInfo, XrFutureEXT* future); +typedef XrResult (XRAPI_PTR *PFN_xrQuerySenseDataCompleteBD)(XrSenseDataProviderBD provider, XrFutureEXT future, XrSenseDataQueryCompletionBD* completion); +typedef XrResult (XRAPI_PTR *PFN_xrDestroySenseDataSnapshotBD)(XrSenseDataSnapshotBD snapshot); +typedef XrResult (XRAPI_PTR *PFN_xrGetQueriedSenseDataBD)(XrSenseDataSnapshotBD snapshot, XrQueriedSenseDataGetInfoBD* getInfo, XrQueriedSenseDataBD* queriedSenseData); +typedef XrResult (XRAPI_PTR *PFN_xrStopSenseDataProviderBD)(XrSenseDataProviderBD provider); +typedef XrResult (XRAPI_PTR *PFN_xrDestroySenseDataProviderBD)(XrSenseDataProviderBD provider); +typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialEntityAnchorBD)(XrSenseDataProviderBD provider, const XrSpatialEntityAnchorCreateInfoBD* createInfo, XrAnchorBD* anchor); +typedef XrResult (XRAPI_PTR *PFN_xrDestroyAnchorBD)(XrAnchorBD anchor); +typedef XrResult (XRAPI_PTR *PFN_xrGetAnchorUuidBD)(XrAnchorBD anchor, XrUuidEXT* uuid); +typedef XrResult (XRAPI_PTR *PFN_xrCreateAnchorSpaceBD)(XrSession session, const XrAnchorSpaceCreateInfoBD* createInfo, XrSpace* space); + +#ifndef XR_NO_PROTOTYPES +#ifdef XR_EXTENSION_PROTOTYPES +XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateSpatialEntityComponentTypesBD( + XrSenseDataSnapshotBD snapshot, + XrSpatialEntityIdBD entityId, + uint32_t componentTypeCapacityInput, + uint32_t* componentTypeCountOutput, + XrSpatialEntityComponentTypeBD* componentTypes); + +XRAPI_ATTR XrResult XRAPI_CALL xrGetSpatialEntityUuidBD( + XrSenseDataSnapshotBD snapshot, + XrSpatialEntityIdBD entityId, + XrUuidEXT* uuid); + +XRAPI_ATTR XrResult XRAPI_CALL xrGetSpatialEntityComponentDataBD( + XrSenseDataSnapshotBD snapshot, + const XrSpatialEntityComponentGetInfoBD* getInfo, + XrSpatialEntityComponentDataBaseHeaderBD* componentData); + +XRAPI_ATTR XrResult XRAPI_CALL xrCreateSenseDataProviderBD( + XrSession session, + const XrSenseDataProviderCreateInfoBD* createInfo, + XrSenseDataProviderBD* provider); + +XRAPI_ATTR XrResult XRAPI_CALL xrStartSenseDataProviderAsyncBD( + XrSenseDataProviderBD provider, + const XrSenseDataProviderStartInfoBD* startInfo, + XrFutureEXT* future); + +XRAPI_ATTR XrResult XRAPI_CALL xrStartSenseDataProviderCompleteBD( + XrSession session, + XrFutureEXT future, + XrFutureCompletionEXT* completion); + +XRAPI_ATTR XrResult XRAPI_CALL xrGetSenseDataProviderStateBD( + XrSenseDataProviderBD provider, + XrSenseDataProviderStateBD* state); + +XRAPI_ATTR XrResult XRAPI_CALL xrQuerySenseDataAsyncBD( + XrSenseDataProviderBD provider, + const XrSenseDataQueryInfoBD* queryInfo, + XrFutureEXT* future); + +XRAPI_ATTR XrResult XRAPI_CALL xrQuerySenseDataCompleteBD( + XrSenseDataProviderBD provider, + XrFutureEXT future, + XrSenseDataQueryCompletionBD* completion); + +XRAPI_ATTR XrResult XRAPI_CALL xrDestroySenseDataSnapshotBD( + XrSenseDataSnapshotBD snapshot); + +XRAPI_ATTR XrResult XRAPI_CALL xrGetQueriedSenseDataBD( + XrSenseDataSnapshotBD snapshot, + XrQueriedSenseDataGetInfoBD* getInfo, + XrQueriedSenseDataBD* queriedSenseData); + +XRAPI_ATTR XrResult XRAPI_CALL xrStopSenseDataProviderBD( + XrSenseDataProviderBD provider); + +XRAPI_ATTR XrResult XRAPI_CALL xrDestroySenseDataProviderBD( + XrSenseDataProviderBD provider); + +XRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialEntityAnchorBD( + XrSenseDataProviderBD provider, + const XrSpatialEntityAnchorCreateInfoBD* createInfo, + XrAnchorBD* anchor); + +XRAPI_ATTR XrResult XRAPI_CALL xrDestroyAnchorBD( + XrAnchorBD anchor); + +XRAPI_ATTR XrResult XRAPI_CALL xrGetAnchorUuidBD( + XrAnchorBD anchor, + XrUuidEXT* uuid); + +XRAPI_ATTR XrResult XRAPI_CALL xrCreateAnchorSpaceBD( + XrSession session, + const XrAnchorSpaceCreateInfoBD* createInfo, + XrSpace* space); +#endif /* XR_EXTENSION_PROTOTYPES */ +#endif /* !XR_NO_PROTOTYPES */ + + +// XR_BD_spatial_anchor is a preprocessor guard. Do not pass it to API calls. +#define XR_BD_spatial_anchor 1 +#define XR_BD_spatial_anchor_SPEC_VERSION 1 +#define XR_BD_SPATIAL_ANCHOR_EXTENSION_NAME "XR_BD_spatial_anchor" + +typedef enum XrPersistenceLocationBD { + XR_PERSISTENCE_LOCATION_LOCAL_BD = 0, + XR_PERSISTENCE_LOCATION_MAX_ENUM_BD = 0x7FFFFFFF +} XrPersistenceLocationBD; +// XrSystemSpatialAnchorPropertiesBD extends XrSystemProperties +typedef struct XrSystemSpatialAnchorPropertiesBD { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrBool32 supportsSpatialAnchor; +} XrSystemSpatialAnchorPropertiesBD; + +typedef struct XrSpatialAnchorCreateInfoBD { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrSpace space; + XrPosef pose; + XrTime time; +} XrSpatialAnchorCreateInfoBD; + +typedef struct XrSpatialAnchorCreateCompletionBD { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrResult futureResult; + XrAnchorBD anchor; + XrUuidEXT uuid; +} XrSpatialAnchorCreateCompletionBD; + +typedef struct XrSpatialAnchorPersistInfoBD { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrPersistenceLocationBD location; + XrAnchorBD anchor; +} XrSpatialAnchorPersistInfoBD; + +typedef struct XrSpatialAnchorUnpersistInfoBD { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrPersistenceLocationBD location; + XrAnchorBD anchor; +} XrSpatialAnchorUnpersistInfoBD; + +typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorAsyncBD)(XrSenseDataProviderBD provider, const XrSpatialAnchorCreateInfoBD* info, XrFutureEXT* future); +typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorCompleteBD)(XrSenseDataProviderBD provider, XrFutureEXT future, XrSpatialAnchorCreateCompletionBD* completion); +typedef XrResult (XRAPI_PTR *PFN_xrPersistSpatialAnchorAsyncBD)(XrSenseDataProviderBD provider, const XrSpatialAnchorPersistInfoBD* info, XrFutureEXT* future); +typedef XrResult (XRAPI_PTR *PFN_xrPersistSpatialAnchorCompleteBD)(XrSenseDataProviderBD provider, XrFutureEXT future, XrFutureCompletionEXT* completion); +typedef XrResult (XRAPI_PTR *PFN_xrUnpersistSpatialAnchorAsyncBD)(XrSenseDataProviderBD provider, const XrSpatialAnchorUnpersistInfoBD* info, XrFutureEXT* future); +typedef XrResult (XRAPI_PTR *PFN_xrUnpersistSpatialAnchorCompleteBD)(XrSenseDataProviderBD provider, XrFutureEXT future, XrFutureCompletionEXT* completion); + +#ifndef XR_NO_PROTOTYPES +#ifdef XR_EXTENSION_PROTOTYPES +XRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialAnchorAsyncBD( + XrSenseDataProviderBD provider, + const XrSpatialAnchorCreateInfoBD* info, + XrFutureEXT* future); + +XRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialAnchorCompleteBD( + XrSenseDataProviderBD provider, + XrFutureEXT future, + XrSpatialAnchorCreateCompletionBD* completion); + +XRAPI_ATTR XrResult XRAPI_CALL xrPersistSpatialAnchorAsyncBD( + XrSenseDataProviderBD provider, + const XrSpatialAnchorPersistInfoBD* info, + XrFutureEXT* future); + +XRAPI_ATTR XrResult XRAPI_CALL xrPersistSpatialAnchorCompleteBD( + XrSenseDataProviderBD provider, + XrFutureEXT future, + XrFutureCompletionEXT* completion); + +XRAPI_ATTR XrResult XRAPI_CALL xrUnpersistSpatialAnchorAsyncBD( + XrSenseDataProviderBD provider, + const XrSpatialAnchorUnpersistInfoBD* info, + XrFutureEXT* future); + +XRAPI_ATTR XrResult XRAPI_CALL xrUnpersistSpatialAnchorCompleteBD( + XrSenseDataProviderBD provider, + XrFutureEXT future, + XrFutureCompletionEXT* completion); +#endif /* XR_EXTENSION_PROTOTYPES */ +#endif /* !XR_NO_PROTOTYPES */ + + +// XR_BD_spatial_anchor_sharing is a preprocessor guard. Do not pass it to API calls. +#define XR_BD_spatial_anchor_sharing 1 +#define XR_BD_spatial_anchor_sharing_SPEC_VERSION 1 +#define XR_BD_SPATIAL_ANCHOR_SHARING_EXTENSION_NAME "XR_BD_spatial_anchor_sharing" +// XrSystemSpatialAnchorSharingPropertiesBD extends XrSystemProperties +typedef struct XrSystemSpatialAnchorSharingPropertiesBD { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrBool32 supportsSpatialAnchorSharing; +} XrSystemSpatialAnchorSharingPropertiesBD; + +typedef struct XrSpatialAnchorShareInfoBD { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrAnchorBD anchor; +} XrSpatialAnchorShareInfoBD; + +typedef struct XrSharedSpatialAnchorDownloadInfoBD { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrUuidEXT uuid; +} XrSharedSpatialAnchorDownloadInfoBD; + +typedef XrResult (XRAPI_PTR *PFN_xrShareSpatialAnchorAsyncBD)(XrSenseDataProviderBD provider, const XrSpatialAnchorShareInfoBD* info, XrFutureEXT* future); +typedef XrResult (XRAPI_PTR *PFN_xrShareSpatialAnchorCompleteBD)(XrSenseDataProviderBD provider, XrFutureEXT future, XrFutureCompletionEXT* completion); +typedef XrResult (XRAPI_PTR *PFN_xrDownloadSharedSpatialAnchorAsyncBD)(XrSenseDataProviderBD provider, const XrSharedSpatialAnchorDownloadInfoBD* info, XrFutureEXT* future); +typedef XrResult (XRAPI_PTR *PFN_xrDownloadSharedSpatialAnchorCompleteBD)(XrSenseDataProviderBD provider, XrFutureEXT future, XrFutureCompletionEXT* completion); + +#ifndef XR_NO_PROTOTYPES +#ifdef XR_EXTENSION_PROTOTYPES +XRAPI_ATTR XrResult XRAPI_CALL xrShareSpatialAnchorAsyncBD( + XrSenseDataProviderBD provider, + const XrSpatialAnchorShareInfoBD* info, + XrFutureEXT* future); + +XRAPI_ATTR XrResult XRAPI_CALL xrShareSpatialAnchorCompleteBD( + XrSenseDataProviderBD provider, + XrFutureEXT future, + XrFutureCompletionEXT* completion); + +XRAPI_ATTR XrResult XRAPI_CALL xrDownloadSharedSpatialAnchorAsyncBD( + XrSenseDataProviderBD provider, + const XrSharedSpatialAnchorDownloadInfoBD* info, + XrFutureEXT* future); + +XRAPI_ATTR XrResult XRAPI_CALL xrDownloadSharedSpatialAnchorCompleteBD( + XrSenseDataProviderBD provider, + XrFutureEXT future, + XrFutureCompletionEXT* completion); +#endif /* XR_EXTENSION_PROTOTYPES */ +#endif /* !XR_NO_PROTOTYPES */ + + +// XR_BD_spatial_scene is a preprocessor guard. Do not pass it to API calls. +#define XR_BD_spatial_scene 1 +#define XR_BD_spatial_scene_SPEC_VERSION 1 +#define XR_BD_SPATIAL_SCENE_EXTENSION_NAME "XR_BD_spatial_scene" +// XrSystemSpatialScenePropertiesBD extends XrSystemProperties +typedef struct XrSystemSpatialScenePropertiesBD { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrBool32 supportsSpatialScene; +} XrSystemSpatialScenePropertiesBD; + +typedef struct XrSceneCaptureInfoBD { + XrStructureType type; + const void* XR_MAY_ALIAS next; +} XrSceneCaptureInfoBD; + +typedef XrResult (XRAPI_PTR *PFN_xrCaptureSceneAsyncBD)(XrSenseDataProviderBD provider, const XrSceneCaptureInfoBD* info, XrFutureEXT* future); +typedef XrResult (XRAPI_PTR *PFN_xrCaptureSceneCompleteBD)(XrSenseDataProviderBD provider, XrFutureEXT future, XrFutureCompletionEXT* completion); + +#ifndef XR_NO_PROTOTYPES +#ifdef XR_EXTENSION_PROTOTYPES +XRAPI_ATTR XrResult XRAPI_CALL xrCaptureSceneAsyncBD( + XrSenseDataProviderBD provider, + const XrSceneCaptureInfoBD* info, + XrFutureEXT* future); + +XRAPI_ATTR XrResult XRAPI_CALL xrCaptureSceneCompleteBD( + XrSenseDataProviderBD provider, + XrFutureEXT future, + XrFutureCompletionEXT* completion); +#endif /* XR_EXTENSION_PROTOTYPES */ +#endif /* !XR_NO_PROTOTYPES */ + + +// XR_BD_spatial_mesh is a preprocessor guard. Do not pass it to API calls. +#define XR_BD_spatial_mesh 1 +#define XR_BD_spatial_mesh_SPEC_VERSION 1 +#define XR_BD_SPATIAL_MESH_EXTENSION_NAME "XR_BD_spatial_mesh" + +typedef enum XrSpatialMeshLodBD { + XR_SPATIAL_MESH_LOD_COARSE_BD = 0, + XR_SPATIAL_MESH_LOD_MEDIUM_BD = 1, + XR_SPATIAL_MESH_LOD_FINE_BD = 2, + XR_SPATIAL_MESH_LOD_MAX_ENUM_BD = 0x7FFFFFFF +} XrSpatialMeshLodBD; +typedef XrFlags64 XrSpatialMeshConfigFlagsBD; + +// Flag bits for XrSpatialMeshConfigFlagsBD +static const XrSpatialMeshConfigFlagsBD XR_SPATIAL_MESH_CONFIG_SEMANTIC_BIT_BD = 0x00000001; +static const XrSpatialMeshConfigFlagsBD XR_SPATIAL_MESH_CONFIG_ALIGN_SEMANTIC_WITH_VERTEX_BIT_BD = 0x00000002; + +// XrSystemSpatialMeshPropertiesBD extends XrSystemProperties +typedef struct XrSystemSpatialMeshPropertiesBD { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrBool32 supportsSpatialMesh; +} XrSystemSpatialMeshPropertiesBD; + +// XrSenseDataProviderCreateInfoSpatialMeshBD extends XrSenseDataProviderCreateInfoBD +typedef struct XrSenseDataProviderCreateInfoSpatialMeshBD { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrSpatialMeshConfigFlagsBD configFlags; + XrSpatialMeshLodBD lod; +} XrSenseDataProviderCreateInfoSpatialMeshBD; + + + // XR_EXT_local_floor is a preprocessor guard. Do not pass it to API calls. #define XR_EXT_local_floor 1 #define XR_EXT_local_floor_SPEC_VERSION 1 @@ -7679,12 +8528,12 @@ typedef struct XrPlaneDetectorPolygonBufferEXT { XrVector2f* vertices; } XrPlaneDetectorPolygonBufferEXT; -typedef XrResult (XRAPI_PTR *PFN_xrCreatePlaneDetectorEXT)(XrSession session, const XrPlaneDetectorCreateInfoEXT* createInfo, XrPlaneDetectorEXT* planeDetector); +typedef XrResult (XRAPI_PTR *PFN_xrCreatePlaneDetectorEXT)(XrSession session, const XrPlaneDetectorCreateInfoEXT* createInfo, XrPlaneDetectorEXT* planeDetector); typedef XrResult (XRAPI_PTR *PFN_xrDestroyPlaneDetectorEXT)(XrPlaneDetectorEXT planeDetector); -typedef XrResult (XRAPI_PTR *PFN_xrBeginPlaneDetectionEXT)(XrPlaneDetectorEXT planeDetector, const XrPlaneDetectorBeginInfoEXT* beginInfo); -typedef XrResult (XRAPI_PTR *PFN_xrGetPlaneDetectionStateEXT)(XrPlaneDetectorEXT planeDetector, XrPlaneDetectionStateEXT* state); -typedef XrResult (XRAPI_PTR *PFN_xrGetPlaneDetectionsEXT)(XrPlaneDetectorEXT planeDetector, const XrPlaneDetectorGetInfoEXT* info, XrPlaneDetectorLocationsEXT* locations); -typedef XrResult (XRAPI_PTR *PFN_xrGetPlanePolygonBufferEXT)(XrPlaneDetectorEXT planeDetector, uint64_t planeId, uint32_t polygonBufferIndex, XrPlaneDetectorPolygonBufferEXT* polygonBuffer); +typedef XrResult (XRAPI_PTR *PFN_xrBeginPlaneDetectionEXT)(XrPlaneDetectorEXT planeDetector, const XrPlaneDetectorBeginInfoEXT* beginInfo); +typedef XrResult (XRAPI_PTR *PFN_xrGetPlaneDetectionStateEXT)(XrPlaneDetectorEXT planeDetector, XrPlaneDetectionStateEXT* state); +typedef XrResult (XRAPI_PTR *PFN_xrGetPlaneDetectionsEXT)(XrPlaneDetectorEXT planeDetector, const XrPlaneDetectorGetInfoEXT* info, XrPlaneDetectorLocationsEXT* locations); +typedef XrResult (XRAPI_PTR *PFN_xrGetPlanePolygonBufferEXT)(XrPlaneDetectorEXT planeDetector, uint64_t planeId, uint32_t polygonBufferIndex, XrPlaneDetectorPolygonBufferEXT* polygonBuffer); #ifndef XR_NO_PROTOTYPES #ifdef XR_EXTENSION_PROTOTYPES @@ -7753,12 +8602,6 @@ typedef struct XR_MAY_ALIAS XrFutureCompletionBaseHeaderEXT { XrResult futureResult; } XrFutureCompletionBaseHeaderEXT; -typedef struct XrFutureCompletionEXT { - XrStructureType type; - void* XR_MAY_ALIAS next; - XrResult futureResult; -} XrFutureCompletionEXT; - typedef struct XrFuturePollResultEXT { XrStructureType type; void* XR_MAY_ALIAS next; @@ -8072,6 +8915,118 @@ XRAPI_ATTR XrResult XRAPI_CALL xrRequestWorldMeshCompleteML( #endif /* !XR_NO_PROTOTYPES */ +// XR_ML_facial_expression is a preprocessor guard. Do not pass it to API calls. +#define XR_ML_facial_expression 1 +XR_DEFINE_HANDLE(XrFacialExpressionClientML) +#define XR_ML_facial_expression_SPEC_VERSION 1 +#define XR_ML_FACIAL_EXPRESSION_EXTENSION_NAME "XR_ML_facial_expression" + +typedef enum XrFacialBlendShapeML { + XR_FACIAL_BLEND_SHAPE_BROW_LOWERER_L_ML = 0, + XR_FACIAL_BLEND_SHAPE_BROW_LOWERER_R_ML = 1, + XR_FACIAL_BLEND_SHAPE_CHEEK_RAISER_L_ML = 2, + XR_FACIAL_BLEND_SHAPE_CHEEK_RAISER_R_ML = 3, + XR_FACIAL_BLEND_SHAPE_CHIN_RAISER_ML = 4, + XR_FACIAL_BLEND_SHAPE_DIMPLER_L_ML = 5, + XR_FACIAL_BLEND_SHAPE_DIMPLER_R_ML = 6, + XR_FACIAL_BLEND_SHAPE_EYES_CLOSED_L_ML = 7, + XR_FACIAL_BLEND_SHAPE_EYES_CLOSED_R_ML = 8, + XR_FACIAL_BLEND_SHAPE_INNER_BROW_RAISER_L_ML = 9, + XR_FACIAL_BLEND_SHAPE_INNER_BROW_RAISER_R_ML = 10, + XR_FACIAL_BLEND_SHAPE_JAW_DROP_ML = 11, + XR_FACIAL_BLEND_SHAPE_LID_TIGHTENER_L_ML = 12, + XR_FACIAL_BLEND_SHAPE_LID_TIGHTENER_R_ML = 13, + XR_FACIAL_BLEND_SHAPE_LIP_CORNER_DEPRESSOR_L_ML = 14, + XR_FACIAL_BLEND_SHAPE_LIP_CORNER_DEPRESSOR_R_ML = 15, + XR_FACIAL_BLEND_SHAPE_LIP_CORNER_PULLER_L_ML = 16, + XR_FACIAL_BLEND_SHAPE_LIP_CORNER_PULLER_R_ML = 17, + XR_FACIAL_BLEND_SHAPE_LIP_FUNNELER_LB_ML = 18, + XR_FACIAL_BLEND_SHAPE_LIP_FUNNELER_LT_ML = 19, + XR_FACIAL_BLEND_SHAPE_LIP_FUNNELER_RB_ML = 20, + XR_FACIAL_BLEND_SHAPE_LIP_FUNNELER_RT_ML = 21, + XR_FACIAL_BLEND_SHAPE_LIP_PRESSOR_L_ML = 22, + XR_FACIAL_BLEND_SHAPE_LIP_PRESSOR_R_ML = 23, + XR_FACIAL_BLEND_SHAPE_LIP_PUCKER_L_ML = 24, + XR_FACIAL_BLEND_SHAPE_LIP_PUCKER_R_ML = 25, + XR_FACIAL_BLEND_SHAPE_LIP_STRETCHER_L_ML = 26, + XR_FACIAL_BLEND_SHAPE_LIP_STRETCHER_R_ML = 27, + XR_FACIAL_BLEND_SHAPE_LIP_SUCK_LB_ML = 28, + XR_FACIAL_BLEND_SHAPE_LIP_SUCK_LT_ML = 29, + XR_FACIAL_BLEND_SHAPE_LIP_SUCK_RB_ML = 30, + XR_FACIAL_BLEND_SHAPE_LIP_SUCK_RT_ML = 31, + XR_FACIAL_BLEND_SHAPE_LIP_TIGHTENER_L_ML = 32, + XR_FACIAL_BLEND_SHAPE_LIP_TIGHTENER_R_ML = 33, + XR_FACIAL_BLEND_SHAPE_LIPS_TOWARD_ML = 34, + XR_FACIAL_BLEND_SHAPE_LOWER_LIP_DEPRESSOR_L_ML = 35, + XR_FACIAL_BLEND_SHAPE_LOWER_LIP_DEPRESSOR_R_ML = 36, + XR_FACIAL_BLEND_SHAPE_NOSE_WRINKLER_L_ML = 37, + XR_FACIAL_BLEND_SHAPE_NOSE_WRINKLER_R_ML = 38, + XR_FACIAL_BLEND_SHAPE_OUTER_BROW_RAISER_L_ML = 39, + XR_FACIAL_BLEND_SHAPE_OUTER_BROW_RAISER_R_ML = 40, + XR_FACIAL_BLEND_SHAPE_UPPER_LID_RAISER_L_ML = 41, + XR_FACIAL_BLEND_SHAPE_UPPER_LID_RAISER_R_ML = 42, + XR_FACIAL_BLEND_SHAPE_UPPER_LIP_RAISER_L_ML = 43, + XR_FACIAL_BLEND_SHAPE_UPPER_LIP_RAISER_R_ML = 44, + XR_FACIAL_BLEND_SHAPE_TONGUE_OUT_ML = 45, + XR_FACIAL_BLEND_SHAPE_MAX_ENUM_ML = 0x7FFFFFFF +} XrFacialBlendShapeML; +typedef XrFlags64 XrFacialExpressionBlendShapePropertiesFlagsML; + +// Flag bits for XrFacialExpressionBlendShapePropertiesFlagsML +static const XrFacialExpressionBlendShapePropertiesFlagsML XR_FACIAL_EXPRESSION_BLEND_SHAPE_PROPERTIES_VALID_BIT_ML = 0x00000001; +static const XrFacialExpressionBlendShapePropertiesFlagsML XR_FACIAL_EXPRESSION_BLEND_SHAPE_PROPERTIES_TRACKED_BIT_ML = 0x00000002; + +// XrSystemFacialExpressionPropertiesML extends XrSystemProperties +typedef struct XrSystemFacialExpressionPropertiesML { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrBool32 supportsFacialExpression; +} XrSystemFacialExpressionPropertiesML; + +typedef struct XrFacialExpressionClientCreateInfoML { + XrStructureType type; + const void* XR_MAY_ALIAS next; + uint32_t requestedCount; + const XrFacialBlendShapeML* requestedFacialBlendShapes; +} XrFacialExpressionClientCreateInfoML; + +typedef struct XrFacialExpressionBlendShapeGetInfoML { + XrStructureType type; + const void* XR_MAY_ALIAS next; +} XrFacialExpressionBlendShapeGetInfoML; + +typedef struct XrFacialExpressionBlendShapePropertiesML { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrFacialBlendShapeML requestedFacialBlendShape; + float weight; + XrFacialExpressionBlendShapePropertiesFlagsML flags; + XrTime time; +} XrFacialExpressionBlendShapePropertiesML; + +typedef XrResult (XRAPI_PTR *PFN_xrCreateFacialExpressionClientML)(XrSession session, const XrFacialExpressionClientCreateInfoML* createInfo, XrFacialExpressionClientML* facialExpressionClient); +typedef XrResult (XRAPI_PTR *PFN_xrDestroyFacialExpressionClientML)(XrFacialExpressionClientML facialExpressionClient); +typedef XrResult (XRAPI_PTR *PFN_xrGetFacialExpressionBlendShapePropertiesML)(XrFacialExpressionClientML facialExpressionClient, const XrFacialExpressionBlendShapeGetInfoML* blendShapeGetInfo, uint32_t blendShapeCount, XrFacialExpressionBlendShapePropertiesML* blendShapes); + +#ifndef XR_NO_PROTOTYPES +#ifdef XR_EXTENSION_PROTOTYPES +XRAPI_ATTR XrResult XRAPI_CALL xrCreateFacialExpressionClientML( + XrSession session, + const XrFacialExpressionClientCreateInfoML* createInfo, + XrFacialExpressionClientML* facialExpressionClient); + +XRAPI_ATTR XrResult XRAPI_CALL xrDestroyFacialExpressionClientML( + XrFacialExpressionClientML facialExpressionClient); + +XRAPI_ATTR XrResult XRAPI_CALL xrGetFacialExpressionBlendShapePropertiesML( + XrFacialExpressionClientML facialExpressionClient, + const XrFacialExpressionBlendShapeGetInfoML* blendShapeGetInfo, + uint32_t blendShapeCount, + XrFacialExpressionBlendShapePropertiesML* blendShapes); +#endif /* XR_EXTENSION_PROTOTYPES */ +#endif /* !XR_NO_PROTOTYPES */ + + // XR_ML_view_configuration_depth_range_change is a preprocessor guard. Do not pass it to API calls. #define XR_ML_view_configuration_depth_range_change 1 #define XR_ML_view_configuration_depth_range_change_SPEC_VERSION 1 @@ -8089,6 +9044,154 @@ XRAPI_ATTR XrResult XRAPI_CALL xrRequestWorldMeshCompleteML( #define XR_EXT_composition_layer_inverted_alpha_SPEC_VERSION 1 #define XR_EXT_COMPOSITION_LAYER_INVERTED_ALPHA_EXTENSION_NAME "XR_EXT_composition_layer_inverted_alpha" + +// XR_META_colocation_discovery is a preprocessor guard. Do not pass it to API calls. +#define XR_META_colocation_discovery 1 +#define XR_MAX_COLOCATION_DISCOVERY_BUFFER_SIZE_META 1024 +#define XR_META_colocation_discovery_SPEC_VERSION 1 +#define XR_META_COLOCATION_DISCOVERY_EXTENSION_NAME "XR_META_colocation_discovery" +typedef struct XrColocationDiscoveryStartInfoMETA { + XrStructureType type; + const void* XR_MAY_ALIAS next; +} XrColocationDiscoveryStartInfoMETA; + +typedef struct XrColocationDiscoveryStopInfoMETA { + XrStructureType type; + const void* XR_MAY_ALIAS next; +} XrColocationDiscoveryStopInfoMETA; + +typedef struct XrColocationAdvertisementStartInfoMETA { + XrStructureType type; + const void* XR_MAY_ALIAS next; + uint32_t bufferSize; + uint8_t* buffer; +} XrColocationAdvertisementStartInfoMETA; + +typedef struct XrColocationAdvertisementStopInfoMETA { + XrStructureType type; + const void* XR_MAY_ALIAS next; +} XrColocationAdvertisementStopInfoMETA; + +typedef struct XrEventDataStartColocationAdvertisementCompleteMETA { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrAsyncRequestIdFB advertisementRequestId; + XrResult result; + XrUuid advertisementUuid; +} XrEventDataStartColocationAdvertisementCompleteMETA; + +typedef struct XrEventDataStopColocationAdvertisementCompleteMETA { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrAsyncRequestIdFB requestId; + XrResult result; +} XrEventDataStopColocationAdvertisementCompleteMETA; + +typedef struct XrEventDataColocationAdvertisementCompleteMETA { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrAsyncRequestIdFB advertisementRequestId; + XrResult result; +} XrEventDataColocationAdvertisementCompleteMETA; + +typedef struct XrEventDataStartColocationDiscoveryCompleteMETA { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrAsyncRequestIdFB discoveryRequestId; + XrResult result; +} XrEventDataStartColocationDiscoveryCompleteMETA; + +typedef struct XrEventDataColocationDiscoveryResultMETA { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrAsyncRequestIdFB discoveryRequestId; + XrUuid advertisementUuid; + uint32_t bufferSize; + uint8_t buffer[XR_MAX_COLOCATION_DISCOVERY_BUFFER_SIZE_META]; +} XrEventDataColocationDiscoveryResultMETA; + +typedef struct XrEventDataColocationDiscoveryCompleteMETA { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrAsyncRequestIdFB discoveryRequestId; + XrResult result; +} XrEventDataColocationDiscoveryCompleteMETA; + +typedef struct XrEventDataStopColocationDiscoveryCompleteMETA { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrAsyncRequestIdFB requestId; + XrResult result; +} XrEventDataStopColocationDiscoveryCompleteMETA; + +// XrSystemColocationDiscoveryPropertiesMETA extends XrSystemProperties +typedef struct XrSystemColocationDiscoveryPropertiesMETA { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrBool32 supportsColocationDiscovery; +} XrSystemColocationDiscoveryPropertiesMETA; + +typedef XrResult (XRAPI_PTR *PFN_xrStartColocationDiscoveryMETA)(XrSession session, const XrColocationDiscoveryStartInfoMETA* info, XrAsyncRequestIdFB* discoveryRequestId); +typedef XrResult (XRAPI_PTR *PFN_xrStopColocationDiscoveryMETA)(XrSession session, const XrColocationDiscoveryStopInfoMETA* info, XrAsyncRequestIdFB* requestId); +typedef XrResult (XRAPI_PTR *PFN_xrStartColocationAdvertisementMETA)(XrSession session, const XrColocationAdvertisementStartInfoMETA* info, XrAsyncRequestIdFB* advertisementRequestId); +typedef XrResult (XRAPI_PTR *PFN_xrStopColocationAdvertisementMETA)(XrSession session, const XrColocationAdvertisementStopInfoMETA* info, XrAsyncRequestIdFB* requestId); + +#ifndef XR_NO_PROTOTYPES +#ifdef XR_EXTENSION_PROTOTYPES +XRAPI_ATTR XrResult XRAPI_CALL xrStartColocationDiscoveryMETA( + XrSession session, + const XrColocationDiscoveryStartInfoMETA* info, + XrAsyncRequestIdFB* discoveryRequestId); + +XRAPI_ATTR XrResult XRAPI_CALL xrStopColocationDiscoveryMETA( + XrSession session, + const XrColocationDiscoveryStopInfoMETA* info, + XrAsyncRequestIdFB* requestId); + +XRAPI_ATTR XrResult XRAPI_CALL xrStartColocationAdvertisementMETA( + XrSession session, + const XrColocationAdvertisementStartInfoMETA* info, + XrAsyncRequestIdFB* advertisementRequestId); + +XRAPI_ATTR XrResult XRAPI_CALL xrStopColocationAdvertisementMETA( + XrSession session, + const XrColocationAdvertisementStopInfoMETA* info, + XrAsyncRequestIdFB* requestId); +#endif /* XR_EXTENSION_PROTOTYPES */ +#endif /* !XR_NO_PROTOTYPES */ + + +// XR_META_spatial_entity_group_sharing is a preprocessor guard. Do not pass it to API calls. +#define XR_META_spatial_entity_group_sharing 1 +#define XR_META_spatial_entity_group_sharing_SPEC_VERSION 1 +#define XR_META_SPATIAL_ENTITY_GROUP_SHARING_EXTENSION_NAME "XR_META_spatial_entity_group_sharing" +// XrSystemSpatialEntityGroupSharingPropertiesMETA extends XrSystemProperties +typedef struct XrSystemSpatialEntityGroupSharingPropertiesMETA { + XrStructureType type; + void* XR_MAY_ALIAS next; + XrBool32 supportsSpatialEntityGroupSharing; +} XrSystemSpatialEntityGroupSharingPropertiesMETA; + +typedef struct XrShareSpacesRecipientGroupsMETA { + XrStructureType type; + const void* XR_MAY_ALIAS next; + uint32_t groupCount; + XrUuid* groups; +} XrShareSpacesRecipientGroupsMETA; + +typedef struct XrSpaceGroupUuidFilterInfoMETA { + XrStructureType type; + const void* XR_MAY_ALIAS next; + XrUuid groupUuid; +} XrSpaceGroupUuidFilterInfoMETA; + + + +// XR_LOGITECH_mx_ink_stylus_interaction is a preprocessor guard. Do not pass it to API calls. +#define XR_LOGITECH_mx_ink_stylus_interaction 1 +#define XR_LOGITECH_mx_ink_stylus_interaction_SPEC_VERSION 1 +#define XR_LOGITECH_MX_INK_STYLUS_INTERACTION_EXTENSION_NAME "XR_LOGITECH_mx_ink_stylus_interaction" + #ifdef __cplusplus } #endif diff --git a/thirdparty/openxr/include/openxr/openxr_loader_negotiation.h b/thirdparty/openxr/include/openxr/openxr_loader_negotiation.h index 19c18cc2a3..2b58ecc82a 100644 --- a/thirdparty/openxr/include/openxr/openxr_loader_negotiation.h +++ b/thirdparty/openxr/include/openxr/openxr_loader_negotiation.h @@ -2,7 +2,7 @@ #define OPENXR_LOADER_NEGOTIATION_H_ 1 /* -** Copyright 2017-2024, The Khronos Group Inc. +** Copyright 2017-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 OR MIT */ diff --git a/thirdparty/openxr/include/openxr/openxr_platform.h b/thirdparty/openxr/include/openxr/openxr_platform.h index dfd74aa5d2..4e9048f775 100644 --- a/thirdparty/openxr/include/openxr/openxr_platform.h +++ b/thirdparty/openxr/include/openxr/openxr_platform.h @@ -2,7 +2,7 @@ #define OPENXR_PLATFORM_H_ 1 /* -** Copyright 2017-2024, The Khronos Group Inc. +** Copyright 2017-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 OR MIT */ @@ -84,7 +84,7 @@ typedef struct XrInstanceCreateInfoAndroidKHR { // XR_KHR_vulkan_swapchain_format_list is a preprocessor guard. Do not pass it to API calls. #define XR_KHR_vulkan_swapchain_format_list 1 -#define XR_KHR_vulkan_swapchain_format_list_SPEC_VERSION 4 +#define XR_KHR_vulkan_swapchain_format_list_SPEC_VERSION 5 #define XR_KHR_VULKAN_SWAPCHAIN_FORMAT_LIST_EXTENSION_NAME "XR_KHR_vulkan_swapchain_format_list" typedef struct XrVulkanSwapchainFormatListCreateInfoKHR { XrStructureType type; @@ -400,7 +400,7 @@ XRAPI_ATTR XrResult XRAPI_CALL xrGetMetalGraphicsRequirementsKHR( #define XR_KHR_win32_convert_performance_counter_time_SPEC_VERSION 1 #define XR_KHR_WIN32_CONVERT_PERFORMANCE_COUNTER_TIME_EXTENSION_NAME "XR_KHR_win32_convert_performance_counter_time" typedef XrResult (XRAPI_PTR *PFN_xrConvertWin32PerformanceCounterToTimeKHR)(XrInstance instance, const LARGE_INTEGER* performanceCounter, XrTime* time); -typedef XrResult (XRAPI_PTR *PFN_xrConvertTimeToWin32PerformanceCounterKHR)(XrInstance instance, XrTime time, LARGE_INTEGER* performanceCounter); +typedef XrResult (XRAPI_PTR *PFN_xrConvertTimeToWin32PerformanceCounterKHR)(XrInstance instance, XrTime time, LARGE_INTEGER* performanceCounter); #ifndef XR_NO_PROTOTYPES #ifdef XR_EXTENSION_PROTOTYPES @@ -424,7 +424,7 @@ XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToWin32PerformanceCounterKHR( #define XR_KHR_convert_timespec_time_SPEC_VERSION 1 #define XR_KHR_CONVERT_TIMESPEC_TIME_EXTENSION_NAME "XR_KHR_convert_timespec_time" typedef XrResult (XRAPI_PTR *PFN_xrConvertTimespecTimeToTimeKHR)(XrInstance instance, const struct timespec* timespecTime, XrTime* time); -typedef XrResult (XRAPI_PTR *PFN_xrConvertTimeToTimespecTimeKHR)(XrInstance instance, XrTime time, struct timespec* timespecTime); +typedef XrResult (XRAPI_PTR *PFN_xrConvertTimeToTimespecTimeKHR)(XrInstance instance, XrTime time, struct timespec* timespecTime); #ifndef XR_NO_PROTOTYPES #ifdef XR_EXTENSION_PROTOTYPES diff --git a/thirdparty/openxr/include/openxr/openxr_platform_defines.h b/thirdparty/openxr/include/openxr/openxr_platform_defines.h index cd07c91360..a8f7e5e06e 100644 --- a/thirdparty/openxr/include/openxr/openxr_platform_defines.h +++ b/thirdparty/openxr/include/openxr/openxr_platform_defines.h @@ -1,5 +1,5 @@ /* -** Copyright (c) 2017-2024, The Khronos Group Inc. +** Copyright (c) 2017-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 OR MIT */ diff --git a/thirdparty/openxr/include/openxr/openxr_reflection.h b/thirdparty/openxr/include/openxr/openxr_reflection.h index 4bea81c236..b39b540bd6 100644 --- a/thirdparty/openxr/include/openxr/openxr_reflection.h +++ b/thirdparty/openxr/include/openxr/openxr_reflection.h @@ -2,7 +2,7 @@ #define OPENXR_REFLECTION_H_ 1 /* -** Copyright (c) 2017-2024, The Khronos Group Inc. +** Copyright (c) 2017-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 OR MIT */ @@ -145,6 +145,16 @@ XR_ENUM_STR(XrResult); _(XR_ENVIRONMENT_DEPTH_NOT_AVAILABLE_META, 1000291000) \ _(XR_ERROR_HINT_ALREADY_SET_QCOM, -1000306000) \ _(XR_ERROR_NOT_AN_ANCHOR_HTC, -1000319000) \ + _(XR_ERROR_SPATIAL_ENTITY_ID_INVALID_BD, -1000389000) \ + _(XR_ERROR_SPATIAL_SENSING_SERVICE_UNAVAILABLE_BD, -1000389001) \ + _(XR_ERROR_ANCHOR_NOT_SUPPORTED_FOR_ENTITY_BD, -1000389002) \ + _(XR_ERROR_SPATIAL_ANCHOR_NOT_FOUND_BD, -1000390000) \ + _(XR_ERROR_SPATIAL_ANCHOR_SHARING_NETWORK_TIMEOUT_BD, -1000391000) \ + _(XR_ERROR_SPATIAL_ANCHOR_SHARING_AUTHENTICATION_FAILURE_BD, -1000391001) \ + _(XR_ERROR_SPATIAL_ANCHOR_SHARING_NETWORK_FAILURE_BD, -1000391002) \ + _(XR_ERROR_SPATIAL_ANCHOR_SHARING_LOCALIZATION_FAIL_BD, -1000391003) \ + _(XR_ERROR_SPATIAL_ANCHOR_SHARING_MAP_INSUFFICIENT_BD, -1000391004) \ + _(XR_ERROR_SCENE_CAPTURE_FAILURE_BD, -1000392000) \ _(XR_ERROR_SPACE_NOT_LOCATABLE_EXT, -1000429000) \ _(XR_ERROR_PLANE_DETECTION_PERMISSION_DENIED_EXT, -1000429001) \ _(XR_ERROR_FUTURE_PENDING_EXT, -1000469001) \ @@ -153,6 +163,12 @@ XR_ENUM_STR(XrResult); _(XR_ERROR_SYSTEM_NOTIFICATION_INCOMPATIBLE_SKU_ML, -1000473001) \ _(XR_ERROR_WORLD_MESH_DETECTOR_PERMISSION_DENIED_ML, -1000474000) \ _(XR_ERROR_WORLD_MESH_DETECTOR_SPACE_NOT_LOCATABLE_ML, -1000474001) \ + _(XR_ERROR_FACIAL_EXPRESSION_PERMISSION_DENIED_ML, 1000482000) \ + _(XR_ERROR_COLOCATION_DISCOVERY_NETWORK_FAILED_META, -1000571001) \ + _(XR_ERROR_COLOCATION_DISCOVERY_NO_DISCOVERY_METHOD_META, -1000571002) \ + _(XR_COLOCATION_DISCOVERY_ALREADY_ADVERTISING_META, 1000571003) \ + _(XR_COLOCATION_DISCOVERY_ALREADY_DISCOVERING_META, 1000571004) \ + _(XR_ERROR_SPACE_GROUP_NOT_FOUND_META, -1000572002) \ _(XR_RESULT_MAX_ENUM, 0x7FFFFFFF) #define XR_LIST_ENUM_XrStructureType(_) \ @@ -454,6 +470,8 @@ XR_ENUM_STR(XrResult); _(XR_TYPE_COMPOSITION_LAYER_SETTINGS_FB, 1000204000) \ _(XR_TYPE_HAPTIC_PCM_VIBRATION_FB, 1000209001) \ _(XR_TYPE_DEVICE_PCM_SAMPLE_RATE_STATE_FB, 1000209002) \ + _(XR_TYPE_FRAME_SYNTHESIS_INFO_EXT, 1000211000) \ + _(XR_TYPE_FRAME_SYNTHESIS_CONFIG_VIEW_EXT, 1000211001) \ _(XR_TYPE_COMPOSITION_LAYER_DEPTH_TEST_FB, 1000212000) \ _(XR_TYPE_LOCAL_DIMMING_FRAME_END_INFO_META, 1000216000) \ _(XR_TYPE_PASSTHROUGH_PREFERENCES_META, 1000217000) \ @@ -489,10 +507,14 @@ XR_ENUM_STR(XrResult); _(XR_TYPE_PASSTHROUGH_COLOR_MAP_INTERPOLATED_LUT_META, 1000266101) \ _(XR_TYPE_SPACE_TRIANGLE_MESH_GET_INFO_META, 1000269001) \ _(XR_TYPE_SPACE_TRIANGLE_MESH_META, 1000269002) \ + _(XR_TYPE_EVENT_DATA_PASSTHROUGH_LAYER_RESUMED_META, 1000282000) \ _(XR_TYPE_SYSTEM_FACE_TRACKING_PROPERTIES2_FB, 1000287013) \ _(XR_TYPE_FACE_TRACKER_CREATE_INFO2_FB, 1000287014) \ _(XR_TYPE_FACE_EXPRESSION_INFO2_FB, 1000287015) \ _(XR_TYPE_FACE_EXPRESSION_WEIGHTS2_FB, 1000287016) \ + _(XR_TYPE_SYSTEM_SPATIAL_ENTITY_SHARING_PROPERTIES_META, 1000290000) \ + _(XR_TYPE_SHARE_SPACES_INFO_META, 1000290001) \ + _(XR_TYPE_EVENT_DATA_SHARE_SPACES_COMPLETE_META, 1000290002) \ _(XR_TYPE_ENVIRONMENT_DEPTH_PROVIDER_CREATE_INFO_META, 1000291000) \ _(XR_TYPE_ENVIRONMENT_DEPTH_SWAPCHAIN_CREATE_INFO_META, 1000291001) \ _(XR_TYPE_ENVIRONMENT_DEPTH_SWAPCHAIN_STATE_META, 1000291002) \ @@ -518,6 +540,44 @@ XR_ENUM_STR(XrResult); _(XR_TYPE_ACTIVE_ACTION_SET_PRIORITIES_EXT, 1000373000) \ _(XR_TYPE_SYSTEM_FORCE_FEEDBACK_CURL_PROPERTIES_MNDX, 1000375000) \ _(XR_TYPE_FORCE_FEEDBACK_CURL_APPLY_LOCATIONS_MNDX, 1000375001) \ + _(XR_TYPE_BODY_TRACKER_CREATE_INFO_BD, 1000385001) \ + _(XR_TYPE_BODY_JOINTS_LOCATE_INFO_BD, 1000385002) \ + _(XR_TYPE_BODY_JOINT_LOCATIONS_BD, 1000385003) \ + _(XR_TYPE_SYSTEM_BODY_TRACKING_PROPERTIES_BD, 1000385004) \ + _(XR_TYPE_SYSTEM_SPATIAL_SENSING_PROPERTIES_BD, 1000389000) \ + _(XR_TYPE_SPATIAL_ENTITY_COMPONENT_GET_INFO_BD, 1000389001) \ + _(XR_TYPE_SPATIAL_ENTITY_LOCATION_GET_INFO_BD, 1000389002) \ + _(XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_LOCATION_BD, 1000389003) \ + _(XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_SEMANTIC_BD, 1000389004) \ + _(XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_BOUNDING_BOX_2D_BD, 1000389005) \ + _(XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_POLYGON_BD, 1000389006) \ + _(XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_BOUNDING_BOX_3D_BD, 1000389007) \ + _(XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_TRIANGLE_MESH_BD, 1000389008) \ + _(XR_TYPE_SENSE_DATA_PROVIDER_CREATE_INFO_BD, 1000389009) \ + _(XR_TYPE_SENSE_DATA_PROVIDER_START_INFO_BD, 1000389010) \ + _(XR_TYPE_EVENT_DATA_SENSE_DATA_PROVIDER_STATE_CHANGED_BD, 1000389011) \ + _(XR_TYPE_EVENT_DATA_SENSE_DATA_UPDATED_BD, 1000389012) \ + _(XR_TYPE_SENSE_DATA_QUERY_INFO_BD, 1000389013) \ + _(XR_TYPE_SENSE_DATA_QUERY_COMPLETION_BD, 1000389014) \ + _(XR_TYPE_SENSE_DATA_FILTER_UUID_BD, 1000389015) \ + _(XR_TYPE_SENSE_DATA_FILTER_SEMANTIC_BD, 1000389016) \ + _(XR_TYPE_QUERIED_SENSE_DATA_GET_INFO_BD, 1000389017) \ + _(XR_TYPE_QUERIED_SENSE_DATA_BD, 1000389018) \ + _(XR_TYPE_SPATIAL_ENTITY_STATE_BD, 1000389019) \ + _(XR_TYPE_SPATIAL_ENTITY_ANCHOR_CREATE_INFO_BD, 1000389020) \ + _(XR_TYPE_ANCHOR_SPACE_CREATE_INFO_BD, 1000389021) \ + _(XR_TYPE_SYSTEM_SPATIAL_ANCHOR_PROPERTIES_BD, 1000390000) \ + _(XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_BD, 1000390001) \ + _(XR_TYPE_SPATIAL_ANCHOR_CREATE_COMPLETION_BD, 1000390002) \ + _(XR_TYPE_SPATIAL_ANCHOR_PERSIST_INFO_BD, 1000390003) \ + _(XR_TYPE_SPATIAL_ANCHOR_UNPERSIST_INFO_BD, 1000390004) \ + _(XR_TYPE_SYSTEM_SPATIAL_ANCHOR_SHARING_PROPERTIES_BD, 1000391000) \ + _(XR_TYPE_SPATIAL_ANCHOR_SHARE_INFO_BD, 1000391001) \ + _(XR_TYPE_SHARED_SPATIAL_ANCHOR_DOWNLOAD_INFO_BD, 1000391002) \ + _(XR_TYPE_SYSTEM_SPATIAL_SCENE_PROPERTIES_BD, 1000392000) \ + _(XR_TYPE_SCENE_CAPTURE_INFO_BD, 1000392001) \ + _(XR_TYPE_SYSTEM_SPATIAL_MESH_PROPERTIES_BD, 1000393000) \ + _(XR_TYPE_SENSE_DATA_PROVIDER_CREATE_INFO_SPATIAL_MESH_BD, 1000393001) \ _(XR_TYPE_HAND_TRACKING_DATA_SOURCE_INFO_EXT, 1000428000) \ _(XR_TYPE_HAND_TRACKING_DATA_SOURCE_STATE_EXT, 1000428001) \ _(XR_TYPE_PLANE_DETECTOR_CREATE_INFO_EXT, 1000429001) \ @@ -546,6 +606,25 @@ XR_ENUM_STR(XrResult); _(XR_TYPE_WORLD_MESH_BLOCK_ML, 1000474010) \ _(XR_TYPE_WORLD_MESH_REQUEST_COMPLETION_ML, 1000474011) \ _(XR_TYPE_WORLD_MESH_REQUEST_COMPLETION_INFO_ML, 1000474012) \ + _(XR_TYPE_SYSTEM_FACIAL_EXPRESSION_PROPERTIES_ML, 1000482004) \ + _(XR_TYPE_FACIAL_EXPRESSION_CLIENT_CREATE_INFO_ML, 1000482005) \ + _(XR_TYPE_FACIAL_EXPRESSION_BLEND_SHAPE_GET_INFO_ML, 1000482006) \ + _(XR_TYPE_FACIAL_EXPRESSION_BLEND_SHAPE_PROPERTIES_ML, 1000482007) \ + _(XR_TYPE_COLOCATION_DISCOVERY_START_INFO_META, 1000571010) \ + _(XR_TYPE_COLOCATION_DISCOVERY_STOP_INFO_META, 1000571011) \ + _(XR_TYPE_COLOCATION_ADVERTISEMENT_START_INFO_META, 1000571012) \ + _(XR_TYPE_COLOCATION_ADVERTISEMENT_STOP_INFO_META, 1000571013) \ + _(XR_TYPE_EVENT_DATA_START_COLOCATION_ADVERTISEMENT_COMPLETE_META, 1000571020) \ + _(XR_TYPE_EVENT_DATA_STOP_COLOCATION_ADVERTISEMENT_COMPLETE_META, 1000571021) \ + _(XR_TYPE_EVENT_DATA_COLOCATION_ADVERTISEMENT_COMPLETE_META, 1000571022) \ + _(XR_TYPE_EVENT_DATA_START_COLOCATION_DISCOVERY_COMPLETE_META, 1000571023) \ + _(XR_TYPE_EVENT_DATA_COLOCATION_DISCOVERY_RESULT_META, 1000571024) \ + _(XR_TYPE_EVENT_DATA_COLOCATION_DISCOVERY_COMPLETE_META, 1000571025) \ + _(XR_TYPE_EVENT_DATA_STOP_COLOCATION_DISCOVERY_COMPLETE_META, 1000571026) \ + _(XR_TYPE_SYSTEM_COLOCATION_DISCOVERY_PROPERTIES_META, 1000571030) \ + _(XR_TYPE_SHARE_SPACES_RECIPIENT_GROUPS_META, 1000572000) \ + _(XR_TYPE_SPACE_GROUP_UUID_FILTER_INFO_META, 1000572001) \ + _(XR_TYPE_SYSTEM_SPATIAL_ENTITY_GROUP_SHARING_PROPERTIES_META, 1000572100) \ _(XR_STRUCTURE_TYPE_MAX_ENUM, 0x7FFFFFFF) #define XR_LIST_ENUM_XrFormFactor(_) \ @@ -637,8 +716,13 @@ XR_ENUM_STR(XrResult); _(XR_OBJECT_TYPE_ENVIRONMENT_DEPTH_SWAPCHAIN_META, 1000291001) \ _(XR_OBJECT_TYPE_PASSTHROUGH_HTC, 1000317000) \ _(XR_OBJECT_TYPE_BODY_TRACKER_HTC, 1000320000) \ + _(XR_OBJECT_TYPE_BODY_TRACKER_BD, 1000385000) \ + _(XR_OBJECT_TYPE_SENSE_DATA_PROVIDER_BD, 1000389000) \ + _(XR_OBJECT_TYPE_SENSE_DATA_SNAPSHOT_BD, 1000389001) \ + _(XR_OBJECT_TYPE_ANCHOR_BD, 1000389002) \ _(XR_OBJECT_TYPE_PLANE_DETECTOR_EXT, 1000429000) \ _(XR_OBJECT_TYPE_WORLD_MESH_DETECTOR_ML, 1000474000) \ + _(XR_OBJECT_TYPE_FACIAL_EXPRESSION_CLIENT_ML, 1000482000) \ _(XR_OBJECT_TYPE_MAX_ENUM, 0x7FFFFFFF) #define XR_LIST_ENUM_XrLoaderInterfaceStructs(_) \ @@ -921,10 +1005,10 @@ XR_ENUM_STR(XrResult); _(XR_LIP_EXPRESSION_MOUTH_UPPER_OVERTURN_HTC, 9) \ _(XR_LIP_EXPRESSION_MOUTH_LOWER_OVERTURN_HTC, 10) \ _(XR_LIP_EXPRESSION_MOUTH_POUT_HTC, 11) \ - _(XR_LIP_EXPRESSION_MOUTH_SMILE_RIGHT_HTC, 12) \ - _(XR_LIP_EXPRESSION_MOUTH_SMILE_LEFT_HTC, 13) \ - _(XR_LIP_EXPRESSION_MOUTH_SAD_RIGHT_HTC, 14) \ - _(XR_LIP_EXPRESSION_MOUTH_SAD_LEFT_HTC, 15) \ + _(XR_LIP_EXPRESSION_MOUTH_RAISER_RIGHT_HTC, 12) \ + _(XR_LIP_EXPRESSION_MOUTH_RAISER_LEFT_HTC, 13) \ + _(XR_LIP_EXPRESSION_MOUTH_STRETCHER_RIGHT_HTC, 14) \ + _(XR_LIP_EXPRESSION_MOUTH_STRETCHER_LEFT_HTC, 15) \ _(XR_LIP_EXPRESSION_CHEEK_PUFF_RIGHT_HTC, 16) \ _(XR_LIP_EXPRESSION_CHEEK_PUFF_LEFT_HTC, 17) \ _(XR_LIP_EXPRESSION_CHEEK_SUCK_HTC, 18) \ @@ -1465,6 +1549,97 @@ XR_ENUM_STR(XrResult); _(XR_FORCE_FEEDBACK_CURL_LOCATION_LITTLE_CURL_MNDX, 4) \ _(XR_FORCE_FEEDBACK_CURL_LOCATION_MAX_ENUM_MNDX, 0x7FFFFFFF) +#define XR_LIST_ENUM_XrBodyJointBD(_) \ + _(XR_BODY_JOINT_PELVIS_BD, 0) \ + _(XR_BODY_JOINT_LEFT_HIP_BD, 1) \ + _(XR_BODY_JOINT_RIGHT_HIP_BD, 2) \ + _(XR_BODY_JOINT_SPINE1_BD, 3) \ + _(XR_BODY_JOINT_LEFT_KNEE_BD, 4) \ + _(XR_BODY_JOINT_RIGHT_KNEE_BD, 5) \ + _(XR_BODY_JOINT_SPINE2_BD, 6) \ + _(XR_BODY_JOINT_LEFT_ANKLE_BD, 7) \ + _(XR_BODY_JOINT_RIGHT_ANKLE_BD, 8) \ + _(XR_BODY_JOINT_SPINE3_BD, 9) \ + _(XR_BODY_JOINT_LEFT_FOOT_BD, 10) \ + _(XR_BODY_JOINT_RIGHT_FOOT_BD, 11) \ + _(XR_BODY_JOINT_NECK_BD, 12) \ + _(XR_BODY_JOINT_LEFT_COLLAR_BD, 13) \ + _(XR_BODY_JOINT_RIGHT_COLLAR_BD, 14) \ + _(XR_BODY_JOINT_HEAD_BD, 15) \ + _(XR_BODY_JOINT_LEFT_SHOULDER_BD, 16) \ + _(XR_BODY_JOINT_RIGHT_SHOULDER_BD, 17) \ + _(XR_BODY_JOINT_LEFT_ELBOW_BD, 18) \ + _(XR_BODY_JOINT_RIGHT_ELBOW_BD, 19) \ + _(XR_BODY_JOINT_LEFT_WRIST_BD, 20) \ + _(XR_BODY_JOINT_RIGHT_WRIST_BD, 21) \ + _(XR_BODY_JOINT_LEFT_HAND_BD, 22) \ + _(XR_BODY_JOINT_RIGHT_HAND_BD, 23) \ + _(XR_BODY_JOINT_MAX_ENUM_BD, 0x7FFFFFFF) + +#define XR_LIST_ENUM_XrBodyJointSetBD(_) \ + _(XR_BODY_JOINT_SET_BODY_WITHOUT_ARM_BD, 1) \ + _(XR_BODY_JOINT_SET_FULL_BODY_JOINTS_BD, 2) \ + _(XR_BODY_JOINT_SET_MAX_ENUM_BD, 0x7FFFFFFF) + +#define XR_LIST_ENUM_XrSpatialEntityComponentTypeBD(_) \ + _(XR_SPATIAL_ENTITY_COMPONENT_TYPE_LOCATION_BD, 0) \ + _(XR_SPATIAL_ENTITY_COMPONENT_TYPE_SEMANTIC_BD, 1) \ + _(XR_SPATIAL_ENTITY_COMPONENT_TYPE_BOUNDING_BOX_2D_BD, 2) \ + _(XR_SPATIAL_ENTITY_COMPONENT_TYPE_POLYGON_BD, 3) \ + _(XR_SPATIAL_ENTITY_COMPONENT_TYPE_BOUNDING_BOX_3D_BD, 4) \ + _(XR_SPATIAL_ENTITY_COMPONENT_TYPE_TRIANGLE_MESH_BD, 5) \ + _(XR_SPATIAL_ENTITY_COMPONENT_TYPE_MAX_ENUM_BD, 0x7FFFFFFF) + +#define XR_LIST_ENUM_XrSemanticLabelBD(_) \ + _(XR_SEMANTIC_LABEL_UNKNOWN_BD, 0) \ + _(XR_SEMANTIC_LABEL_FLOOR_BD, 1) \ + _(XR_SEMANTIC_LABEL_CEILING_BD, 2) \ + _(XR_SEMANTIC_LABEL_WALL_BD, 3) \ + _(XR_SEMANTIC_LABEL_DOOR_BD, 4) \ + _(XR_SEMANTIC_LABEL_WINDOW_BD, 5) \ + _(XR_SEMANTIC_LABEL_OPENING_BD, 6) \ + _(XR_SEMANTIC_LABEL_TABLE_BD, 7) \ + _(XR_SEMANTIC_LABEL_SOFA_BD, 8) \ + _(XR_SEMANTIC_LABEL_CHAIR_BD, 9) \ + _(XR_SEMANTIC_LABEL_HUMAN_BD, 10) \ + _(XR_SEMANTIC_LABEL_BEAM_BD, 11) \ + _(XR_SEMANTIC_LABEL_COLUMN_BD, 12) \ + _(XR_SEMANTIC_LABEL_CURTAIN_BD, 13) \ + _(XR_SEMANTIC_LABEL_CABINET_BD, 14) \ + _(XR_SEMANTIC_LABEL_BED_BD, 15) \ + _(XR_SEMANTIC_LABEL_PLANT_BD, 16) \ + _(XR_SEMANTIC_LABEL_SCREEN_BD, 17) \ + _(XR_SEMANTIC_LABEL_VIRTUAL_WALL_BD, 18) \ + _(XR_SEMANTIC_LABEL_REFRIGERATOR_BD, 19) \ + _(XR_SEMANTIC_LABEL_WASHING_MACHINE_BD, 20) \ + _(XR_SEMANTIC_LABEL_AIR_CONDITIONER_BD, 21) \ + _(XR_SEMANTIC_LABEL_LAMP_BD, 22) \ + _(XR_SEMANTIC_LABEL_WALL_ART_BD, 23) \ + _(XR_SEMANTIC_LABEL_STAIRWAY_BD, 24) \ + _(XR_SEMANTIC_LABEL_MAX_ENUM_BD, 0x7FFFFFFF) + +#define XR_LIST_ENUM_XrSenseDataProviderTypeBD(_) \ + _(XR_SENSE_DATA_PROVIDER_TYPE_ANCHOR_BD, 1000390000) \ + _(XR_SENSE_DATA_PROVIDER_TYPE_SCENE_BD, 1000392000) \ + _(XR_SENSE_DATA_PROVIDER_TYPE_MESH_BD, 1000393000) \ + _(XR_SENSE_DATA_PROVIDER_TYPE_MAX_ENUM_BD, 0x7FFFFFFF) + +#define XR_LIST_ENUM_XrSenseDataProviderStateBD(_) \ + _(XR_SENSE_DATA_PROVIDER_STATE_INITIALIZED_BD, 0) \ + _(XR_SENSE_DATA_PROVIDER_STATE_RUNNING_BD, 1) \ + _(XR_SENSE_DATA_PROVIDER_STATE_STOPPED_BD, 2) \ + _(XR_SENSE_DATA_PROVIDER_STATE_MAX_ENUM_BD, 0x7FFFFFFF) + +#define XR_LIST_ENUM_XrPersistenceLocationBD(_) \ + _(XR_PERSISTENCE_LOCATION_LOCAL_BD, 0) \ + _(XR_PERSISTENCE_LOCATION_MAX_ENUM_BD, 0x7FFFFFFF) + +#define XR_LIST_ENUM_XrSpatialMeshLodBD(_) \ + _(XR_SPATIAL_MESH_LOD_COARSE_BD, 0) \ + _(XR_SPATIAL_MESH_LOD_MEDIUM_BD, 1) \ + _(XR_SPATIAL_MESH_LOD_FINE_BD, 2) \ + _(XR_SPATIAL_MESH_LOD_MAX_ENUM_BD, 0x7FFFFFFF) + #define XR_LIST_ENUM_XrHandTrackingDataSourceEXT(_) \ _(XR_HAND_TRACKING_DATA_SOURCE_UNOBSTRUCTED_EXT, 1) \ _(XR_HAND_TRACKING_DATA_SOURCE_CONTROLLER_EXT, 2) \ @@ -1532,6 +1707,55 @@ XR_ENUM_STR(XrResult); _(XR_WORLD_MESH_BLOCK_RESULT_PARTIAL_UPDATE_ML, 3) \ _(XR_WORLD_MESH_BLOCK_RESULT_MAX_ENUM_ML, 0x7FFFFFFF) +#define XR_LIST_ENUM_XrFacialBlendShapeML(_) \ + _(XR_FACIAL_BLEND_SHAPE_BROW_LOWERER_L_ML, 0) \ + _(XR_FACIAL_BLEND_SHAPE_BROW_LOWERER_R_ML, 1) \ + _(XR_FACIAL_BLEND_SHAPE_CHEEK_RAISER_L_ML, 2) \ + _(XR_FACIAL_BLEND_SHAPE_CHEEK_RAISER_R_ML, 3) \ + _(XR_FACIAL_BLEND_SHAPE_CHIN_RAISER_ML, 4) \ + _(XR_FACIAL_BLEND_SHAPE_DIMPLER_L_ML, 5) \ + _(XR_FACIAL_BLEND_SHAPE_DIMPLER_R_ML, 6) \ + _(XR_FACIAL_BLEND_SHAPE_EYES_CLOSED_L_ML, 7) \ + _(XR_FACIAL_BLEND_SHAPE_EYES_CLOSED_R_ML, 8) \ + _(XR_FACIAL_BLEND_SHAPE_INNER_BROW_RAISER_L_ML, 9) \ + _(XR_FACIAL_BLEND_SHAPE_INNER_BROW_RAISER_R_ML, 10) \ + _(XR_FACIAL_BLEND_SHAPE_JAW_DROP_ML, 11) \ + _(XR_FACIAL_BLEND_SHAPE_LID_TIGHTENER_L_ML, 12) \ + _(XR_FACIAL_BLEND_SHAPE_LID_TIGHTENER_R_ML, 13) \ + _(XR_FACIAL_BLEND_SHAPE_LIP_CORNER_DEPRESSOR_L_ML, 14) \ + _(XR_FACIAL_BLEND_SHAPE_LIP_CORNER_DEPRESSOR_R_ML, 15) \ + _(XR_FACIAL_BLEND_SHAPE_LIP_CORNER_PULLER_L_ML, 16) \ + _(XR_FACIAL_BLEND_SHAPE_LIP_CORNER_PULLER_R_ML, 17) \ + _(XR_FACIAL_BLEND_SHAPE_LIP_FUNNELER_LB_ML, 18) \ + _(XR_FACIAL_BLEND_SHAPE_LIP_FUNNELER_LT_ML, 19) \ + _(XR_FACIAL_BLEND_SHAPE_LIP_FUNNELER_RB_ML, 20) \ + _(XR_FACIAL_BLEND_SHAPE_LIP_FUNNELER_RT_ML, 21) \ + _(XR_FACIAL_BLEND_SHAPE_LIP_PRESSOR_L_ML, 22) \ + _(XR_FACIAL_BLEND_SHAPE_LIP_PRESSOR_R_ML, 23) \ + _(XR_FACIAL_BLEND_SHAPE_LIP_PUCKER_L_ML, 24) \ + _(XR_FACIAL_BLEND_SHAPE_LIP_PUCKER_R_ML, 25) \ + _(XR_FACIAL_BLEND_SHAPE_LIP_STRETCHER_L_ML, 26) \ + _(XR_FACIAL_BLEND_SHAPE_LIP_STRETCHER_R_ML, 27) \ + _(XR_FACIAL_BLEND_SHAPE_LIP_SUCK_LB_ML, 28) \ + _(XR_FACIAL_BLEND_SHAPE_LIP_SUCK_LT_ML, 29) \ + _(XR_FACIAL_BLEND_SHAPE_LIP_SUCK_RB_ML, 30) \ + _(XR_FACIAL_BLEND_SHAPE_LIP_SUCK_RT_ML, 31) \ + _(XR_FACIAL_BLEND_SHAPE_LIP_TIGHTENER_L_ML, 32) \ + _(XR_FACIAL_BLEND_SHAPE_LIP_TIGHTENER_R_ML, 33) \ + _(XR_FACIAL_BLEND_SHAPE_LIPS_TOWARD_ML, 34) \ + _(XR_FACIAL_BLEND_SHAPE_LOWER_LIP_DEPRESSOR_L_ML, 35) \ + _(XR_FACIAL_BLEND_SHAPE_LOWER_LIP_DEPRESSOR_R_ML, 36) \ + _(XR_FACIAL_BLEND_SHAPE_NOSE_WRINKLER_L_ML, 37) \ + _(XR_FACIAL_BLEND_SHAPE_NOSE_WRINKLER_R_ML, 38) \ + _(XR_FACIAL_BLEND_SHAPE_OUTER_BROW_RAISER_L_ML, 39) \ + _(XR_FACIAL_BLEND_SHAPE_OUTER_BROW_RAISER_R_ML, 40) \ + _(XR_FACIAL_BLEND_SHAPE_UPPER_LID_RAISER_L_ML, 41) \ + _(XR_FACIAL_BLEND_SHAPE_UPPER_LID_RAISER_R_ML, 42) \ + _(XR_FACIAL_BLEND_SHAPE_UPPER_LIP_RAISER_L_ML, 43) \ + _(XR_FACIAL_BLEND_SHAPE_UPPER_LIP_RAISER_R_ML, 44) \ + _(XR_FACIAL_BLEND_SHAPE_TONGUE_OUT_ML, 45) \ + _(XR_FACIAL_BLEND_SHAPE_MAX_ENUM_ML, 0x7FFFFFFF) + #define XR_LIST_BITS_XrInstanceCreateFlags(_) #define XR_LIST_BITS_XrSessionCreateFlags(_) @@ -1697,6 +1921,10 @@ XR_ENUM_STR(XrResult); _(XR_COMPOSITION_LAYER_SETTINGS_QUALITY_SHARPENING_BIT_FB, 0x00000008) \ _(XR_COMPOSITION_LAYER_SETTINGS_AUTO_LAYER_FILTER_BIT_META, 0x00000020) \ +#define XR_LIST_BITS_XrFrameSynthesisInfoFlagsEXT(_) \ + _(XR_FRAME_SYNTHESIS_INFO_USE_2D_MOTION_VECTOR_BIT_EXT, 0x00000001) \ + _(XR_FRAME_SYNTHESIS_INFO_REQUEST_RELAXED_FRAME_INTERVAL_BIT_EXT, 0x00000002) \ + #define XR_LIST_BITS_XrPassthroughPreferenceFlagsMETA(_) \ _(XR_PASSTHROUGH_PREFERENCE_DEFAULT_TO_ACTIVE_BIT_META, 0x00000001) \ @@ -1724,6 +1952,10 @@ XR_ENUM_STR(XrResult); _(XR_FOVEATION_DYNAMIC_CLEAR_FOV_ENABLED_BIT_HTC, 0x00000002) \ _(XR_FOVEATION_DYNAMIC_FOCAL_CENTER_OFFSET_ENABLED_BIT_HTC, 0x00000004) \ +#define XR_LIST_BITS_XrSpatialMeshConfigFlagsBD(_) \ + _(XR_SPATIAL_MESH_CONFIG_SEMANTIC_BIT_BD, 0x00000001) \ + _(XR_SPATIAL_MESH_CONFIG_ALIGN_SEMANTIC_WITH_VERTEX_BIT_BD, 0x00000002) \ + #define XR_LIST_BITS_XrPlaneDetectionCapabilityFlagsEXT(_) \ _(XR_PLANE_DETECTION_CAPABILITY_PLANE_DETECTION_BIT_EXT, 0x00000001) \ _(XR_PLANE_DETECTION_CAPABILITY_PLANE_HOLES_BIT_EXT, 0x00000002) \ @@ -1744,6 +1976,10 @@ XR_ENUM_STR(XrResult); _(XR_WORLD_MESH_DETECTOR_REMOVE_MESH_SKIRT_BIT_ML, 0x00000010) \ _(XR_WORLD_MESH_DETECTOR_INDEX_ORDER_CW_BIT_ML, 0x00000020) \ +#define XR_LIST_BITS_XrFacialExpressionBlendShapePropertiesFlagsML(_) \ + _(XR_FACIAL_EXPRESSION_BLEND_SHAPE_PROPERTIES_VALID_BIT_ML, 0x00000001) \ + _(XR_FACIAL_EXPRESSION_BLEND_SHAPE_PROPERTIES_TRACKED_BIT_ML, 0x00000002) \ + /// Calls your macro with the name of each member of XrApiLayerProperties, in order. #define XR_LIST_STRUCT_XrApiLayerProperties(_) \ _(type) \ @@ -4409,6 +4645,28 @@ XR_ENUM_STR(XrResult); _(next) \ _(sampleRate) \ +/// Calls your macro with the name of each member of XrFrameSynthesisInfoEXT, in order. +#define XR_LIST_STRUCT_XrFrameSynthesisInfoEXT(_) \ + _(type) \ + _(next) \ + _(layerFlags) \ + _(motionVectorSubImage) \ + _(motionVectorScale) \ + _(motionVectorOffset) \ + _(appSpaceDeltaPose) \ + _(depthSubImage) \ + _(minDepth) \ + _(maxDepth) \ + _(nearZ) \ + _(farZ) \ + +/// Calls your macro with the name of each member of XrFrameSynthesisConfigViewEXT, in order. +#define XR_LIST_STRUCT_XrFrameSynthesisConfigViewEXT(_) \ + _(type) \ + _(next) \ + _(recommendedMotionVectorImageRectWidth) \ + _(recommendedMotionVectorImageRectHeight) \ + /// Calls your macro with the name of each member of XrCompositionLayerDepthTestFB, in order. #define XR_LIST_STRUCT_XrCompositionLayerDepthTestFB(_) \ _(type) \ @@ -4675,6 +4933,12 @@ XR_ENUM_STR(XrResult); _(indexCountOutput) \ _(indices) \ +/// Calls your macro with the name of each member of XrEventDataPassthroughLayerResumedMETA, in order. +#define XR_LIST_STRUCT_XrEventDataPassthroughLayerResumedMETA(_) \ + _(type) \ + _(next) \ + _(layer) \ + /// Calls your macro with the name of each member of XrSystemFaceTrackingProperties2FB, in order. #define XR_LIST_STRUCT_XrSystemFaceTrackingProperties2FB(_) \ _(type) \ @@ -4709,6 +4973,32 @@ XR_ENUM_STR(XrResult); _(dataSource) \ _(time) \ +/// Calls your macro with the name of each member of XrSystemSpatialEntitySharingPropertiesMETA, in order. +#define XR_LIST_STRUCT_XrSystemSpatialEntitySharingPropertiesMETA(_) \ + _(type) \ + _(next) \ + _(supportsSpatialEntitySharing) \ + +/// Calls your macro with the name of each member of XrShareSpacesRecipientBaseHeaderMETA, in order. +#define XR_LIST_STRUCT_XrShareSpacesRecipientBaseHeaderMETA(_) \ + _(type) \ + _(next) \ + +/// Calls your macro with the name of each member of XrShareSpacesInfoMETA, in order. +#define XR_LIST_STRUCT_XrShareSpacesInfoMETA(_) \ + _(type) \ + _(next) \ + _(spaceCount) \ + _(spaces) \ + _(recipientInfo) \ + +/// Calls your macro with the name of each member of XrEventDataShareSpacesCompleteMETA, in order. +#define XR_LIST_STRUCT_XrEventDataShareSpacesCompleteMETA(_) \ + _(type) \ + _(next) \ + _(requestId) \ + _(result) \ + /// Calls your macro with the name of each member of XrEnvironmentDepthProviderCreateInfoMETA, in order. #define XR_LIST_STRUCT_XrEnvironmentDepthProviderCreateInfoMETA(_) \ _(type) \ @@ -4918,6 +5208,276 @@ XR_ENUM_STR(XrResult); _(locationCount) \ _(locations) \ +/// Calls your macro with the name of each member of XrSystemBodyTrackingPropertiesBD, in order. +#define XR_LIST_STRUCT_XrSystemBodyTrackingPropertiesBD(_) \ + _(type) \ + _(next) \ + _(supportsBodyTracking) \ + +/// Calls your macro with the name of each member of XrBodyTrackerCreateInfoBD, in order. +#define XR_LIST_STRUCT_XrBodyTrackerCreateInfoBD(_) \ + _(type) \ + _(next) \ + _(jointSet) \ + +/// Calls your macro with the name of each member of XrBodyJointsLocateInfoBD, in order. +#define XR_LIST_STRUCT_XrBodyJointsLocateInfoBD(_) \ + _(type) \ + _(next) \ + _(baseSpace) \ + _(time) \ + +/// Calls your macro with the name of each member of XrBodyJointLocationBD, in order. +#define XR_LIST_STRUCT_XrBodyJointLocationBD(_) \ + _(locationFlags) \ + _(pose) \ + +/// Calls your macro with the name of each member of XrBodyJointLocationsBD, in order. +#define XR_LIST_STRUCT_XrBodyJointLocationsBD(_) \ + _(type) \ + _(next) \ + _(allJointPosesTracked) \ + _(jointLocationCount) \ + _(jointLocations) \ + +/// Calls your macro with the name of each member of XrSystemSpatialSensingPropertiesBD, in order. +#define XR_LIST_STRUCT_XrSystemSpatialSensingPropertiesBD(_) \ + _(type) \ + _(next) \ + _(supportsSpatialSensing) \ + +/// Calls your macro with the name of each member of XrSpatialEntityComponentGetInfoBD, in order. +#define XR_LIST_STRUCT_XrSpatialEntityComponentGetInfoBD(_) \ + _(type) \ + _(next) \ + _(entityId) \ + _(componentType) \ + +/// Calls your macro with the name of each member of XrSpatialEntityComponentDataBaseHeaderBD, in order. +#define XR_LIST_STRUCT_XrSpatialEntityComponentDataBaseHeaderBD(_) \ + _(type) \ + _(next) \ + +/// Calls your macro with the name of each member of XrSpatialEntityLocationGetInfoBD, in order. +#define XR_LIST_STRUCT_XrSpatialEntityLocationGetInfoBD(_) \ + _(type) \ + _(next) \ + _(baseSpace) \ + +/// Calls your macro with the name of each member of XrSpatialEntityComponentDataLocationBD, in order. +#define XR_LIST_STRUCT_XrSpatialEntityComponentDataLocationBD(_) \ + _(type) \ + _(next) \ + _(location) \ + +/// Calls your macro with the name of each member of XrSpatialEntityComponentDataSemanticBD, in order. +#define XR_LIST_STRUCT_XrSpatialEntityComponentDataSemanticBD(_) \ + _(type) \ + _(next) \ + _(labelCapacityInput) \ + _(labelCountOutput) \ + _(labels) \ + +/// Calls your macro with the name of each member of XrSpatialEntityComponentDataBoundingBox2DBD, in order. +#define XR_LIST_STRUCT_XrSpatialEntityComponentDataBoundingBox2DBD(_) \ + _(type) \ + _(next) \ + _(boundingBox2D) \ + +/// Calls your macro with the name of each member of XrSpatialEntityComponentDataPolygonBD, in order. +#define XR_LIST_STRUCT_XrSpatialEntityComponentDataPolygonBD(_) \ + _(type) \ + _(next) \ + _(vertexCapacityInput) \ + _(vertexCountOutput) \ + _(vertices) \ + +/// Calls your macro with the name of each member of XrSpatialEntityComponentDataBoundingBox3DBD, in order. +#define XR_LIST_STRUCT_XrSpatialEntityComponentDataBoundingBox3DBD(_) \ + _(type) \ + _(next) \ + _(boundingBox3D) \ + +/// Calls your macro with the name of each member of XrSpatialEntityComponentDataTriangleMeshBD, in order. +#define XR_LIST_STRUCT_XrSpatialEntityComponentDataTriangleMeshBD(_) \ + _(type) \ + _(next) \ + _(vertexCapacityInput) \ + _(vertexCountOutput) \ + _(vertices) \ + _(indexCapacityInput) \ + _(indexCountOutput) \ + _(indices) \ + +/// Calls your macro with the name of each member of XrSenseDataProviderCreateInfoBD, in order. +#define XR_LIST_STRUCT_XrSenseDataProviderCreateInfoBD(_) \ + _(type) \ + _(next) \ + _(providerType) \ + +/// Calls your macro with the name of each member of XrSenseDataProviderStartInfoBD, in order. +#define XR_LIST_STRUCT_XrSenseDataProviderStartInfoBD(_) \ + _(type) \ + _(next) \ + +/// Calls your macro with the name of each member of XrEventDataSenseDataProviderStateChangedBD, in order. +#define XR_LIST_STRUCT_XrEventDataSenseDataProviderStateChangedBD(_) \ + _(type) \ + _(next) \ + _(provider) \ + _(newState) \ + +/// Calls your macro with the name of each member of XrEventDataSenseDataUpdatedBD, in order. +#define XR_LIST_STRUCT_XrEventDataSenseDataUpdatedBD(_) \ + _(type) \ + _(next) \ + _(provider) \ + +/// Calls your macro with the name of each member of XrSenseDataQueryInfoBD, in order. +#define XR_LIST_STRUCT_XrSenseDataQueryInfoBD(_) \ + _(type) \ + _(next) \ + +/// Calls your macro with the name of each member of XrSenseDataQueryCompletionBD, in order. +#define XR_LIST_STRUCT_XrSenseDataQueryCompletionBD(_) \ + _(type) \ + _(next) \ + _(futureResult) \ + _(snapshot) \ + +/// Calls your macro with the name of each member of XrQueriedSenseDataGetInfoBD, in order. +#define XR_LIST_STRUCT_XrQueriedSenseDataGetInfoBD(_) \ + _(type) \ + _(next) \ + +/// Calls your macro with the name of each member of XrSpatialEntityStateBD, in order. +#define XR_LIST_STRUCT_XrSpatialEntityStateBD(_) \ + _(type) \ + _(next) \ + _(entityId) \ + _(lastUpdateTime) \ + _(uuid) \ + +/// Calls your macro with the name of each member of XrQueriedSenseDataBD, in order. +#define XR_LIST_STRUCT_XrQueriedSenseDataBD(_) \ + _(type) \ + _(next) \ + _(stateCapacityInput) \ + _(stateCountOutput) \ + _(states) \ + +/// Calls your macro with the name of each member of XrSenseDataFilterUuidBD, in order. +#define XR_LIST_STRUCT_XrSenseDataFilterUuidBD(_) \ + _(type) \ + _(next) \ + _(uuidCount) \ + _(uuids) \ + +/// Calls your macro with the name of each member of XrSenseDataFilterSemanticBD, in order. +#define XR_LIST_STRUCT_XrSenseDataFilterSemanticBD(_) \ + _(type) \ + _(next) \ + _(labelCount) \ + _(labels) \ + +/// Calls your macro with the name of each member of XrSpatialEntityAnchorCreateInfoBD, in order. +#define XR_LIST_STRUCT_XrSpatialEntityAnchorCreateInfoBD(_) \ + _(type) \ + _(next) \ + _(snapshot) \ + _(entityId) \ + +/// Calls your macro with the name of each member of XrAnchorSpaceCreateInfoBD, in order. +#define XR_LIST_STRUCT_XrAnchorSpaceCreateInfoBD(_) \ + _(type) \ + _(next) \ + _(anchor) \ + _(poseInAnchorSpace) \ + +/// Calls your macro with the name of each member of XrFutureCompletionEXT, in order. +#define XR_LIST_STRUCT_XrFutureCompletionEXT(_) \ + _(type) \ + _(next) \ + _(futureResult) \ + +/// Calls your macro with the name of each member of XrSystemSpatialAnchorPropertiesBD, in order. +#define XR_LIST_STRUCT_XrSystemSpatialAnchorPropertiesBD(_) \ + _(type) \ + _(next) \ + _(supportsSpatialAnchor) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorCreateInfoBD, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorCreateInfoBD(_) \ + _(type) \ + _(next) \ + _(space) \ + _(pose) \ + _(time) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorCreateCompletionBD, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorCreateCompletionBD(_) \ + _(type) \ + _(next) \ + _(futureResult) \ + _(anchor) \ + _(uuid) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorPersistInfoBD, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorPersistInfoBD(_) \ + _(type) \ + _(next) \ + _(location) \ + _(anchor) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorUnpersistInfoBD, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorUnpersistInfoBD(_) \ + _(type) \ + _(next) \ + _(location) \ + _(anchor) \ + +/// Calls your macro with the name of each member of XrSystemSpatialAnchorSharingPropertiesBD, in order. +#define XR_LIST_STRUCT_XrSystemSpatialAnchorSharingPropertiesBD(_) \ + _(type) \ + _(next) \ + _(supportsSpatialAnchorSharing) \ + +/// Calls your macro with the name of each member of XrSpatialAnchorShareInfoBD, in order. +#define XR_LIST_STRUCT_XrSpatialAnchorShareInfoBD(_) \ + _(type) \ + _(next) \ + _(anchor) \ + +/// Calls your macro with the name of each member of XrSharedSpatialAnchorDownloadInfoBD, in order. +#define XR_LIST_STRUCT_XrSharedSpatialAnchorDownloadInfoBD(_) \ + _(type) \ + _(next) \ + _(uuid) \ + +/// Calls your macro with the name of each member of XrSystemSpatialScenePropertiesBD, in order. +#define XR_LIST_STRUCT_XrSystemSpatialScenePropertiesBD(_) \ + _(type) \ + _(next) \ + _(supportsSpatialScene) \ + +/// Calls your macro with the name of each member of XrSceneCaptureInfoBD, in order. +#define XR_LIST_STRUCT_XrSceneCaptureInfoBD(_) \ + _(type) \ + _(next) \ + +/// Calls your macro with the name of each member of XrSystemSpatialMeshPropertiesBD, in order. +#define XR_LIST_STRUCT_XrSystemSpatialMeshPropertiesBD(_) \ + _(type) \ + _(next) \ + _(supportsSpatialMesh) \ + +/// Calls your macro with the name of each member of XrSenseDataProviderCreateInfoSpatialMeshBD, in order. +#define XR_LIST_STRUCT_XrSenseDataProviderCreateInfoSpatialMeshBD(_) \ + _(type) \ + _(next) \ + _(configFlags) \ + _(lod) \ + /// Calls your macro with the name of each member of XrHandTrackingDataSourceInfoEXT, in order. #define XR_LIST_STRUCT_XrHandTrackingDataSourceInfoEXT(_) \ _(type) \ @@ -5012,12 +5572,6 @@ XR_ENUM_STR(XrResult); _(next) \ _(futureResult) \ -/// Calls your macro with the name of each member of XrFutureCompletionEXT, in order. -#define XR_LIST_STRUCT_XrFutureCompletionEXT(_) \ - _(type) \ - _(next) \ - _(futureResult) \ - /// Calls your macro with the name of each member of XrFuturePollResultEXT, in order. #define XR_LIST_STRUCT_XrFuturePollResultEXT(_) \ _(type) \ @@ -5164,6 +5718,132 @@ XR_ENUM_STR(XrResult); _(blockCount) \ _(blocks) \ +/// Calls your macro with the name of each member of XrSystemFacialExpressionPropertiesML, in order. +#define XR_LIST_STRUCT_XrSystemFacialExpressionPropertiesML(_) \ + _(type) \ + _(next) \ + _(supportsFacialExpression) \ + +/// Calls your macro with the name of each member of XrFacialExpressionClientCreateInfoML, in order. +#define XR_LIST_STRUCT_XrFacialExpressionClientCreateInfoML(_) \ + _(type) \ + _(next) \ + _(requestedCount) \ + _(requestedFacialBlendShapes) \ + +/// Calls your macro with the name of each member of XrFacialExpressionBlendShapeGetInfoML, in order. +#define XR_LIST_STRUCT_XrFacialExpressionBlendShapeGetInfoML(_) \ + _(type) \ + _(next) \ + +/// Calls your macro with the name of each member of XrFacialExpressionBlendShapePropertiesML, in order. +#define XR_LIST_STRUCT_XrFacialExpressionBlendShapePropertiesML(_) \ + _(type) \ + _(next) \ + _(requestedFacialBlendShape) \ + _(weight) \ + _(flags) \ + _(time) \ + +/// Calls your macro with the name of each member of XrColocationDiscoveryStartInfoMETA, in order. +#define XR_LIST_STRUCT_XrColocationDiscoveryStartInfoMETA(_) \ + _(type) \ + _(next) \ + +/// Calls your macro with the name of each member of XrColocationDiscoveryStopInfoMETA, in order. +#define XR_LIST_STRUCT_XrColocationDiscoveryStopInfoMETA(_) \ + _(type) \ + _(next) \ + +/// Calls your macro with the name of each member of XrColocationAdvertisementStartInfoMETA, in order. +#define XR_LIST_STRUCT_XrColocationAdvertisementStartInfoMETA(_) \ + _(type) \ + _(next) \ + _(bufferSize) \ + _(buffer) \ + +/// Calls your macro with the name of each member of XrColocationAdvertisementStopInfoMETA, in order. +#define XR_LIST_STRUCT_XrColocationAdvertisementStopInfoMETA(_) \ + _(type) \ + _(next) \ + +/// Calls your macro with the name of each member of XrEventDataStartColocationAdvertisementCompleteMETA, in order. +#define XR_LIST_STRUCT_XrEventDataStartColocationAdvertisementCompleteMETA(_) \ + _(type) \ + _(next) \ + _(advertisementRequestId) \ + _(result) \ + _(advertisementUuid) \ + +/// Calls your macro with the name of each member of XrEventDataStopColocationAdvertisementCompleteMETA, in order. +#define XR_LIST_STRUCT_XrEventDataStopColocationAdvertisementCompleteMETA(_) \ + _(type) \ + _(next) \ + _(requestId) \ + _(result) \ + +/// Calls your macro with the name of each member of XrEventDataColocationAdvertisementCompleteMETA, in order. +#define XR_LIST_STRUCT_XrEventDataColocationAdvertisementCompleteMETA(_) \ + _(type) \ + _(next) \ + _(advertisementRequestId) \ + _(result) \ + +/// Calls your macro with the name of each member of XrEventDataStartColocationDiscoveryCompleteMETA, in order. +#define XR_LIST_STRUCT_XrEventDataStartColocationDiscoveryCompleteMETA(_) \ + _(type) \ + _(next) \ + _(discoveryRequestId) \ + _(result) \ + +/// Calls your macro with the name of each member of XrEventDataColocationDiscoveryResultMETA, in order. +#define XR_LIST_STRUCT_XrEventDataColocationDiscoveryResultMETA(_) \ + _(type) \ + _(next) \ + _(discoveryRequestId) \ + _(advertisementUuid) \ + _(bufferSize) \ + _(buffer) \ + +/// Calls your macro with the name of each member of XrEventDataColocationDiscoveryCompleteMETA, in order. +#define XR_LIST_STRUCT_XrEventDataColocationDiscoveryCompleteMETA(_) \ + _(type) \ + _(next) \ + _(discoveryRequestId) \ + _(result) \ + +/// Calls your macro with the name of each member of XrEventDataStopColocationDiscoveryCompleteMETA, in order. +#define XR_LIST_STRUCT_XrEventDataStopColocationDiscoveryCompleteMETA(_) \ + _(type) \ + _(next) \ + _(requestId) \ + _(result) \ + +/// Calls your macro with the name of each member of XrSystemColocationDiscoveryPropertiesMETA, in order. +#define XR_LIST_STRUCT_XrSystemColocationDiscoveryPropertiesMETA(_) \ + _(type) \ + _(next) \ + _(supportsColocationDiscovery) \ + +/// Calls your macro with the name of each member of XrSystemSpatialEntityGroupSharingPropertiesMETA, in order. +#define XR_LIST_STRUCT_XrSystemSpatialEntityGroupSharingPropertiesMETA(_) \ + _(type) \ + _(next) \ + _(supportsSpatialEntityGroupSharing) \ + +/// Calls your macro with the name of each member of XrShareSpacesRecipientGroupsMETA, in order. +#define XR_LIST_STRUCT_XrShareSpacesRecipientGroupsMETA(_) \ + _(type) \ + _(next) \ + _(groupCount) \ + _(groups) \ + +/// Calls your macro with the name of each member of XrSpaceGroupUuidFilterInfoMETA, in order. +#define XR_LIST_STRUCT_XrSpaceGroupUuidFilterInfoMETA(_) \ + _(type) \ + _(next) \ + _(groupUuid) \ + /// Calls your macro with the structure type name and the XrStructureType constant for @@ -5448,6 +6128,8 @@ XR_ENUM_STR(XrResult); _(XrCompositionLayerSettingsFB, XR_TYPE_COMPOSITION_LAYER_SETTINGS_FB) \ _(XrHapticPcmVibrationFB, XR_TYPE_HAPTIC_PCM_VIBRATION_FB) \ _(XrDevicePcmSampleRateStateFB, XR_TYPE_DEVICE_PCM_SAMPLE_RATE_STATE_FB) \ + _(XrFrameSynthesisInfoEXT, XR_TYPE_FRAME_SYNTHESIS_INFO_EXT) \ + _(XrFrameSynthesisConfigViewEXT, XR_TYPE_FRAME_SYNTHESIS_CONFIG_VIEW_EXT) \ _(XrCompositionLayerDepthTestFB, XR_TYPE_COMPOSITION_LAYER_DEPTH_TEST_FB) \ _(XrLocalDimmingFrameEndInfoMETA, XR_TYPE_LOCAL_DIMMING_FRAME_END_INFO_META) \ _(XrPassthroughPreferencesMETA, XR_TYPE_PASSTHROUGH_PREFERENCES_META) \ @@ -5482,10 +6164,14 @@ XR_ENUM_STR(XrResult); _(XrSystemPassthroughColorLutPropertiesMETA, XR_TYPE_SYSTEM_PASSTHROUGH_COLOR_LUT_PROPERTIES_META) \ _(XrSpaceTriangleMeshGetInfoMETA, XR_TYPE_SPACE_TRIANGLE_MESH_GET_INFO_META) \ _(XrSpaceTriangleMeshMETA, XR_TYPE_SPACE_TRIANGLE_MESH_META) \ + _(XrEventDataPassthroughLayerResumedMETA, XR_TYPE_EVENT_DATA_PASSTHROUGH_LAYER_RESUMED_META) \ _(XrSystemFaceTrackingProperties2FB, XR_TYPE_SYSTEM_FACE_TRACKING_PROPERTIES2_FB) \ _(XrFaceTrackerCreateInfo2FB, XR_TYPE_FACE_TRACKER_CREATE_INFO2_FB) \ _(XrFaceExpressionInfo2FB, XR_TYPE_FACE_EXPRESSION_INFO2_FB) \ _(XrFaceExpressionWeights2FB, XR_TYPE_FACE_EXPRESSION_WEIGHTS2_FB) \ + _(XrSystemSpatialEntitySharingPropertiesMETA, XR_TYPE_SYSTEM_SPATIAL_ENTITY_SHARING_PROPERTIES_META) \ + _(XrShareSpacesInfoMETA, XR_TYPE_SHARE_SPACES_INFO_META) \ + _(XrEventDataShareSpacesCompleteMETA, XR_TYPE_EVENT_DATA_SHARE_SPACES_COMPLETE_META) \ _(XrEnvironmentDepthProviderCreateInfoMETA, XR_TYPE_ENVIRONMENT_DEPTH_PROVIDER_CREATE_INFO_META) \ _(XrEnvironmentDepthSwapchainCreateInfoMETA, XR_TYPE_ENVIRONMENT_DEPTH_SWAPCHAIN_CREATE_INFO_META) \ _(XrEnvironmentDepthSwapchainStateMETA, XR_TYPE_ENVIRONMENT_DEPTH_SWAPCHAIN_STATE_META) \ @@ -5511,6 +6197,45 @@ XR_ENUM_STR(XrResult); _(XrActiveActionSetPrioritiesEXT, XR_TYPE_ACTIVE_ACTION_SET_PRIORITIES_EXT) \ _(XrSystemForceFeedbackCurlPropertiesMNDX, XR_TYPE_SYSTEM_FORCE_FEEDBACK_CURL_PROPERTIES_MNDX) \ _(XrForceFeedbackCurlApplyLocationsMNDX, XR_TYPE_FORCE_FEEDBACK_CURL_APPLY_LOCATIONS_MNDX) \ + _(XrSystemBodyTrackingPropertiesBD, XR_TYPE_SYSTEM_BODY_TRACKING_PROPERTIES_BD) \ + _(XrBodyTrackerCreateInfoBD, XR_TYPE_BODY_TRACKER_CREATE_INFO_BD) \ + _(XrBodyJointsLocateInfoBD, XR_TYPE_BODY_JOINTS_LOCATE_INFO_BD) \ + _(XrBodyJointLocationsBD, XR_TYPE_BODY_JOINT_LOCATIONS_BD) \ + _(XrSystemSpatialSensingPropertiesBD, XR_TYPE_SYSTEM_SPATIAL_SENSING_PROPERTIES_BD) \ + _(XrSpatialEntityComponentGetInfoBD, XR_TYPE_SPATIAL_ENTITY_COMPONENT_GET_INFO_BD) \ + _(XrSpatialEntityLocationGetInfoBD, XR_TYPE_SPATIAL_ENTITY_LOCATION_GET_INFO_BD) \ + _(XrSpatialEntityComponentDataLocationBD, XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_LOCATION_BD) \ + _(XrSpatialEntityComponentDataSemanticBD, XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_SEMANTIC_BD) \ + _(XrSpatialEntityComponentDataBoundingBox2DBD, XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_BOUNDING_BOX_2D_BD) \ + _(XrSpatialEntityComponentDataPolygonBD, XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_POLYGON_BD) \ + _(XrSpatialEntityComponentDataBoundingBox3DBD, XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_BOUNDING_BOX_3D_BD) \ + _(XrSpatialEntityComponentDataTriangleMeshBD, XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_TRIANGLE_MESH_BD) \ + _(XrSenseDataProviderCreateInfoBD, XR_TYPE_SENSE_DATA_PROVIDER_CREATE_INFO_BD) \ + _(XrSenseDataProviderStartInfoBD, XR_TYPE_SENSE_DATA_PROVIDER_START_INFO_BD) \ + _(XrEventDataSenseDataProviderStateChangedBD, XR_TYPE_EVENT_DATA_SENSE_DATA_PROVIDER_STATE_CHANGED_BD) \ + _(XrEventDataSenseDataUpdatedBD, XR_TYPE_EVENT_DATA_SENSE_DATA_UPDATED_BD) \ + _(XrSenseDataQueryInfoBD, XR_TYPE_SENSE_DATA_QUERY_INFO_BD) \ + _(XrSenseDataQueryCompletionBD, XR_TYPE_SENSE_DATA_QUERY_COMPLETION_BD) \ + _(XrQueriedSenseDataGetInfoBD, XR_TYPE_QUERIED_SENSE_DATA_GET_INFO_BD) \ + _(XrSpatialEntityStateBD, XR_TYPE_SPATIAL_ENTITY_STATE_BD) \ + _(XrQueriedSenseDataBD, XR_TYPE_QUERIED_SENSE_DATA_BD) \ + _(XrSenseDataFilterUuidBD, XR_TYPE_SENSE_DATA_FILTER_UUID_BD) \ + _(XrSenseDataFilterSemanticBD, XR_TYPE_SENSE_DATA_FILTER_SEMANTIC_BD) \ + _(XrSpatialEntityAnchorCreateInfoBD, XR_TYPE_SPATIAL_ENTITY_ANCHOR_CREATE_INFO_BD) \ + _(XrAnchorSpaceCreateInfoBD, XR_TYPE_ANCHOR_SPACE_CREATE_INFO_BD) \ + _(XrFutureCompletionEXT, XR_TYPE_FUTURE_COMPLETION_EXT) \ + _(XrSystemSpatialAnchorPropertiesBD, XR_TYPE_SYSTEM_SPATIAL_ANCHOR_PROPERTIES_BD) \ + _(XrSpatialAnchorCreateInfoBD, XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_BD) \ + _(XrSpatialAnchorCreateCompletionBD, XR_TYPE_SPATIAL_ANCHOR_CREATE_COMPLETION_BD) \ + _(XrSpatialAnchorPersistInfoBD, XR_TYPE_SPATIAL_ANCHOR_PERSIST_INFO_BD) \ + _(XrSpatialAnchorUnpersistInfoBD, XR_TYPE_SPATIAL_ANCHOR_UNPERSIST_INFO_BD) \ + _(XrSystemSpatialAnchorSharingPropertiesBD, XR_TYPE_SYSTEM_SPATIAL_ANCHOR_SHARING_PROPERTIES_BD) \ + _(XrSpatialAnchorShareInfoBD, XR_TYPE_SPATIAL_ANCHOR_SHARE_INFO_BD) \ + _(XrSharedSpatialAnchorDownloadInfoBD, XR_TYPE_SHARED_SPATIAL_ANCHOR_DOWNLOAD_INFO_BD) \ + _(XrSystemSpatialScenePropertiesBD, XR_TYPE_SYSTEM_SPATIAL_SCENE_PROPERTIES_BD) \ + _(XrSceneCaptureInfoBD, XR_TYPE_SCENE_CAPTURE_INFO_BD) \ + _(XrSystemSpatialMeshPropertiesBD, XR_TYPE_SYSTEM_SPATIAL_MESH_PROPERTIES_BD) \ + _(XrSenseDataProviderCreateInfoSpatialMeshBD, XR_TYPE_SENSE_DATA_PROVIDER_CREATE_INFO_SPATIAL_MESH_BD) \ _(XrHandTrackingDataSourceInfoEXT, XR_TYPE_HAND_TRACKING_DATA_SOURCE_INFO_EXT) \ _(XrHandTrackingDataSourceStateEXT, XR_TYPE_HAND_TRACKING_DATA_SOURCE_STATE_EXT) \ _(XrSystemPlaneDetectionPropertiesEXT, XR_TYPE_SYSTEM_PLANE_DETECTION_PROPERTIES_EXT) \ @@ -5522,7 +6247,6 @@ XR_ENUM_STR(XrResult); _(XrPlaneDetectorPolygonBufferEXT, XR_TYPE_PLANE_DETECTOR_POLYGON_BUFFER_EXT) \ _(XrFutureCancelInfoEXT, XR_TYPE_FUTURE_CANCEL_INFO_EXT) \ _(XrFuturePollInfoEXT, XR_TYPE_FUTURE_POLL_INFO_EXT) \ - _(XrFutureCompletionEXT, XR_TYPE_FUTURE_COMPLETION_EXT) \ _(XrFuturePollResultEXT, XR_TYPE_FUTURE_POLL_RESULT_EXT) \ _(XrEventDataUserPresenceChangedEXT, XR_TYPE_EVENT_DATA_USER_PRESENCE_CHANGED_EXT) \ _(XrSystemUserPresencePropertiesEXT, XR_TYPE_SYSTEM_USER_PRESENCE_PROPERTIES_EXT) \ @@ -5542,6 +6266,25 @@ XR_ENUM_STR(XrResult); _(XrWorldMeshBlockML, XR_TYPE_WORLD_MESH_BLOCK_ML) \ _(XrWorldMeshRequestCompletionInfoML, XR_TYPE_WORLD_MESH_REQUEST_COMPLETION_INFO_ML) \ _(XrWorldMeshRequestCompletionML, XR_TYPE_WORLD_MESH_REQUEST_COMPLETION_ML) \ + _(XrSystemFacialExpressionPropertiesML, XR_TYPE_SYSTEM_FACIAL_EXPRESSION_PROPERTIES_ML) \ + _(XrFacialExpressionClientCreateInfoML, XR_TYPE_FACIAL_EXPRESSION_CLIENT_CREATE_INFO_ML) \ + _(XrFacialExpressionBlendShapeGetInfoML, XR_TYPE_FACIAL_EXPRESSION_BLEND_SHAPE_GET_INFO_ML) \ + _(XrFacialExpressionBlendShapePropertiesML, XR_TYPE_FACIAL_EXPRESSION_BLEND_SHAPE_PROPERTIES_ML) \ + _(XrColocationDiscoveryStartInfoMETA, XR_TYPE_COLOCATION_DISCOVERY_START_INFO_META) \ + _(XrColocationDiscoveryStopInfoMETA, XR_TYPE_COLOCATION_DISCOVERY_STOP_INFO_META) \ + _(XrColocationAdvertisementStartInfoMETA, XR_TYPE_COLOCATION_ADVERTISEMENT_START_INFO_META) \ + _(XrColocationAdvertisementStopInfoMETA, XR_TYPE_COLOCATION_ADVERTISEMENT_STOP_INFO_META) \ + _(XrEventDataStartColocationAdvertisementCompleteMETA, XR_TYPE_EVENT_DATA_START_COLOCATION_ADVERTISEMENT_COMPLETE_META) \ + _(XrEventDataStopColocationAdvertisementCompleteMETA, XR_TYPE_EVENT_DATA_STOP_COLOCATION_ADVERTISEMENT_COMPLETE_META) \ + _(XrEventDataColocationAdvertisementCompleteMETA, XR_TYPE_EVENT_DATA_COLOCATION_ADVERTISEMENT_COMPLETE_META) \ + _(XrEventDataStartColocationDiscoveryCompleteMETA, XR_TYPE_EVENT_DATA_START_COLOCATION_DISCOVERY_COMPLETE_META) \ + _(XrEventDataColocationDiscoveryResultMETA, XR_TYPE_EVENT_DATA_COLOCATION_DISCOVERY_RESULT_META) \ + _(XrEventDataColocationDiscoveryCompleteMETA, XR_TYPE_EVENT_DATA_COLOCATION_DISCOVERY_COMPLETE_META) \ + _(XrEventDataStopColocationDiscoveryCompleteMETA, XR_TYPE_EVENT_DATA_STOP_COLOCATION_DISCOVERY_COMPLETE_META) \ + _(XrSystemColocationDiscoveryPropertiesMETA, XR_TYPE_SYSTEM_COLOCATION_DISCOVERY_PROPERTIES_META) \ + _(XrSystemSpatialEntityGroupSharingPropertiesMETA, XR_TYPE_SYSTEM_SPATIAL_ENTITY_GROUP_SHARING_PROPERTIES_META) \ + _(XrShareSpacesRecipientGroupsMETA, XR_TYPE_SHARE_SPACES_RECIPIENT_GROUPS_META) \ + _(XrSpaceGroupUuidFilterInfoMETA, XR_TYPE_SPACE_GROUP_UUID_FILTER_INFO_META) \ #if defined(XR_USE_GRAPHICS_API_D3D11) @@ -5817,6 +6560,7 @@ XR_ENUM_STR(XrResult); _(XR_ML_spatial_anchors_storage, 142) \ _(XR_MSFT_spatial_anchor_persistence, 143) \ _(XR_MSFT_scene_marker, 148) \ + _(XR_KHR_extended_struct_name_lengths, 149) \ _(XR_ULTRALEAP_hand_tracking_forearm, 150) \ _(XR_FB_spatial_entity_query, 157) \ _(XR_FB_spatial_entity_storage, 159) \ @@ -5842,6 +6586,7 @@ XR_ENUM_STR(XrResult); _(XR_FB_composition_layer_settings, 205) \ _(XR_FB_touch_controller_proximity, 207) \ _(XR_FB_haptic_pcm, 210) \ + _(XR_EXT_frame_synthesis, 212) \ _(XR_FB_composition_layer_depth_test, 213) \ _(XR_META_local_dimming, 217) \ _(XR_META_passthrough_preferences, 218) \ @@ -5850,14 +6595,18 @@ XR_ENUM_STR(XrResult); _(XR_META_vulkan_swapchain_create_info, 228) \ _(XR_META_performance_metrics, 233) \ _(XR_FB_spatial_entity_storage_batch, 239) \ + _(XR_META_detached_controllers, 241) \ _(XR_FB_spatial_entity_user, 242) \ _(XR_META_headset_id, 246) \ + _(XR_META_hand_tracking_microgestures, 253) \ _(XR_META_recommended_layer_resolution, 255) \ _(XR_META_passthrough_color_lut, 267) \ _(XR_META_spatial_entity_mesh, 270) \ _(XR_META_automatic_layer_filter, 272) \ _(XR_META_touch_controller_plus, 280) \ + _(XR_META_passthrough_layer_resumed_event, 283) \ _(XR_FB_face_tracking2, 288) \ + _(XR_META_spatial_entity_sharing, 291) \ _(XR_META_environment_depth, 292) \ _(XR_EXT_uuid, 300) \ _(XR_EXT_hand_interaction, 303) \ @@ -5869,6 +6618,12 @@ XR_ENUM_STR(XrResult); _(XR_EXT_active_action_set_priority, 374) \ _(XR_MNDX_force_feedback_curl, 376) \ _(XR_BD_controller_interaction, 385) \ + _(XR_BD_body_tracking, 386) \ + _(XR_BD_spatial_sensing, 390) \ + _(XR_BD_spatial_anchor, 391) \ + _(XR_BD_spatial_anchor_sharing, 392) \ + _(XR_BD_spatial_scene, 393) \ + _(XR_BD_spatial_mesh, 394) \ _(XR_EXT_local_floor, 427) \ _(XR_EXT_hand_tracking_data_source, 429) \ _(XR_EXT_plane_detection, 430) \ @@ -5879,10 +6634,14 @@ XR_ENUM_STR(XrResult); _(XR_ML_user_calibration, 473) \ _(XR_ML_system_notifications, 474) \ _(XR_ML_world_mesh_detection, 475) \ + _(XR_ML_facial_expression, 483) \ _(XR_ML_view_configuration_depth_range_change, 484) \ _(XR_YVR_controller_interaction, 498) \ _(XR_EXT_composition_layer_inverted_alpha, 555) \ + _(XR_META_colocation_discovery, 572) \ + _(XR_META_spatial_entity_group_sharing, 573) \ _(XR_KHR_maintenance1, 711) \ + _(XR_LOGITECH_mx_ink_stylus_interaction, 746) \ @@ -6077,6 +6836,14 @@ XR_ENUM_STR(XrResult); _(GetVulkanGraphicsDevice2KHR, KHR_vulkan_enable2) \ +/// For every function defined by XR_KHR_extended_struct_name_lengths in this version of the spec, +/// calls your macro with the function name and extension name. +/// Trims the leading `xr` from the function name and the leading `XR_` from the feature name, +/// because it is easy to add back but impossible to remove with the preprocessor. +#define XR_LIST_FUNCTIONS_XR_KHR_extended_struct_name_lengths(_) \ + _(StructureTypeToString2KHR, KHR_extended_struct_name_lengths) \ + + /// For every function defined by XR_EXT_performance_settings in this version of the spec, /// calls your macro with the function name and extension name. /// Trims the leading `xr` from the function name and the leading `XR_` from the feature name, @@ -6683,6 +7450,14 @@ XR_ENUM_STR(XrResult); _(GetFaceExpressionWeights2FB, FB_face_tracking2) \ +/// For every function defined by XR_META_spatial_entity_sharing in this version of the spec, +/// calls your macro with the function name and extension name. +/// Trims the leading `xr` from the function name and the leading `XR_` from the feature name, +/// because it is easy to add back but impossible to remove with the preprocessor. +#define XR_LIST_FUNCTIONS_XR_META_spatial_entity_sharing(_) \ + _(ShareSpacesMETA, META_spatial_entity_sharing) \ + + /// For every function defined by XR_META_environment_depth in this version of the spec, /// calls your macro with the function name and extension name. /// Trims the leading `xr` from the function name and the leading `XR_` from the feature name, @@ -6753,6 +7528,73 @@ XR_ENUM_STR(XrResult); _(ApplyForceFeedbackCurlMNDX, MNDX_force_feedback_curl) \ +/// For every function defined by XR_BD_body_tracking in this version of the spec, +/// calls your macro with the function name and extension name. +/// Trims the leading `xr` from the function name and the leading `XR_` from the feature name, +/// because it is easy to add back but impossible to remove with the preprocessor. +#define XR_LIST_FUNCTIONS_XR_BD_body_tracking(_) \ + _(CreateBodyTrackerBD, BD_body_tracking) \ + _(DestroyBodyTrackerBD, BD_body_tracking) \ + _(LocateBodyJointsBD, BD_body_tracking) \ + + +/// For every function defined by XR_BD_spatial_sensing in this version of the spec, +/// calls your macro with the function name and extension name. +/// Trims the leading `xr` from the function name and the leading `XR_` from the feature name, +/// because it is easy to add back but impossible to remove with the preprocessor. +#define XR_LIST_FUNCTIONS_XR_BD_spatial_sensing(_) \ + _(EnumerateSpatialEntityComponentTypesBD, BD_spatial_sensing) \ + _(GetSpatialEntityUuidBD, BD_spatial_sensing) \ + _(GetSpatialEntityComponentDataBD, BD_spatial_sensing) \ + _(CreateSenseDataProviderBD, BD_spatial_sensing) \ + _(StartSenseDataProviderAsyncBD, BD_spatial_sensing) \ + _(StartSenseDataProviderCompleteBD, BD_spatial_sensing) \ + _(GetSenseDataProviderStateBD, BD_spatial_sensing) \ + _(QuerySenseDataAsyncBD, BD_spatial_sensing) \ + _(QuerySenseDataCompleteBD, BD_spatial_sensing) \ + _(DestroySenseDataSnapshotBD, BD_spatial_sensing) \ + _(GetQueriedSenseDataBD, BD_spatial_sensing) \ + _(StopSenseDataProviderBD, BD_spatial_sensing) \ + _(DestroySenseDataProviderBD, BD_spatial_sensing) \ + _(CreateSpatialEntityAnchorBD, BD_spatial_sensing) \ + _(DestroyAnchorBD, BD_spatial_sensing) \ + _(GetAnchorUuidBD, BD_spatial_sensing) \ + _(CreateAnchorSpaceBD, BD_spatial_sensing) \ + + +/// For every function defined by XR_BD_spatial_anchor in this version of the spec, +/// calls your macro with the function name and extension name. +/// Trims the leading `xr` from the function name and the leading `XR_` from the feature name, +/// because it is easy to add back but impossible to remove with the preprocessor. +#define XR_LIST_FUNCTIONS_XR_BD_spatial_anchor(_) \ + _(CreateSpatialAnchorAsyncBD, BD_spatial_anchor) \ + _(CreateSpatialAnchorCompleteBD, BD_spatial_anchor) \ + _(PersistSpatialAnchorAsyncBD, BD_spatial_anchor) \ + _(PersistSpatialAnchorCompleteBD, BD_spatial_anchor) \ + _(UnpersistSpatialAnchorAsyncBD, BD_spatial_anchor) \ + _(UnpersistSpatialAnchorCompleteBD, BD_spatial_anchor) \ + + +/// For every function defined by XR_BD_spatial_anchor_sharing in this version of the spec, +/// calls your macro with the function name and extension name. +/// Trims the leading `xr` from the function name and the leading `XR_` from the feature name, +/// because it is easy to add back but impossible to remove with the preprocessor. +#define XR_LIST_FUNCTIONS_XR_BD_spatial_anchor_sharing(_) \ + _(ShareSpatialAnchorAsyncBD, BD_spatial_anchor_sharing) \ + _(ShareSpatialAnchorCompleteBD, BD_spatial_anchor_sharing) \ + _(DownloadSharedSpatialAnchorAsyncBD, BD_spatial_anchor_sharing) \ + _(DownloadSharedSpatialAnchorCompleteBD, BD_spatial_anchor_sharing) \ + + +/// For every function defined by XR_BD_spatial_scene in this version of the spec, +/// calls your macro with the function name and extension name. +/// Trims the leading `xr` from the function name and the leading `XR_` from the feature name, +/// because it is easy to add back but impossible to remove with the preprocessor. +#define XR_LIST_FUNCTIONS_XR_BD_spatial_scene(_) \ + _(CaptureSceneAsyncBD, BD_spatial_scene) \ + _(CaptureSceneCompleteBD, BD_spatial_scene) \ + + /// For every function defined by XR_EXT_plane_detection in this version of the spec, /// calls your macro with the function name and extension name. /// Trims the leading `xr` from the function name and the leading `XR_` from the feature name, @@ -6807,6 +7649,27 @@ XR_ENUM_STR(XrResult); _(RequestWorldMeshCompleteML, ML_world_mesh_detection) \ +/// For every function defined by XR_ML_facial_expression in this version of the spec, +/// calls your macro with the function name and extension name. +/// Trims the leading `xr` from the function name and the leading `XR_` from the feature name, +/// because it is easy to add back but impossible to remove with the preprocessor. +#define XR_LIST_FUNCTIONS_XR_ML_facial_expression(_) \ + _(CreateFacialExpressionClientML, ML_facial_expression) \ + _(DestroyFacialExpressionClientML, ML_facial_expression) \ + _(GetFacialExpressionBlendShapePropertiesML, ML_facial_expression) \ + + +/// For every function defined by XR_META_colocation_discovery in this version of the spec, +/// calls your macro with the function name and extension name. +/// Trims the leading `xr` from the function name and the leading `XR_` from the feature name, +/// because it is easy to add back but impossible to remove with the preprocessor. +#define XR_LIST_FUNCTIONS_XR_META_colocation_discovery(_) \ + _(StartColocationDiscoveryMETA, META_colocation_discovery) \ + _(StopColocationDiscoveryMETA, META_colocation_discovery) \ + _(StartColocationAdvertisementMETA, META_colocation_discovery) \ + _(StopColocationAdvertisementMETA, META_colocation_discovery) \ + + #endif diff --git a/thirdparty/openxr/include/openxr/openxr_reflection_parent_structs.h b/thirdparty/openxr/include/openxr/openxr_reflection_parent_structs.h index bffab47cc5..043c9782a7 100644 --- a/thirdparty/openxr/include/openxr/openxr_reflection_parent_structs.h +++ b/thirdparty/openxr/include/openxr/openxr_reflection_parent_structs.h @@ -2,7 +2,7 @@ #define OPENXR_REFLECTION_PARENT_STRUCTS_H_ 1 /* -** Copyright (c) 2017-2024, The Khronos Group Inc. +** Copyright (c) 2017-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 OR MIT */ @@ -66,6 +66,9 @@ This file contains expansion macros (X Macros) for OpenXR structures that have a _avail(XrEventDataSpaceEraseCompleteFB, XR_TYPE_EVENT_DATA_SPACE_ERASE_COMPLETE_FB) \ _avail(XrEventDataSpaceShareCompleteFB, XR_TYPE_EVENT_DATA_SPACE_SHARE_COMPLETE_FB) \ _avail(XrEventDataSpaceListSaveCompleteFB, XR_TYPE_EVENT_DATA_SPACE_LIST_SAVE_COMPLETE_FB) \ + _avail(XrEventDataPassthroughLayerResumedMETA, XR_TYPE_EVENT_DATA_PASSTHROUGH_LAYER_RESUMED_META) \ + _avail(XrEventDataSenseDataProviderStateChangedBD, XR_TYPE_EVENT_DATA_SENSE_DATA_PROVIDER_STATE_CHANGED_BD) \ + _avail(XrEventDataSenseDataUpdatedBD, XR_TYPE_EVENT_DATA_SENSE_DATA_UPDATED_BD) \ _avail(XrEventDataHeadsetFitChangedML, XR_TYPE_EVENT_DATA_HEADSET_FIT_CHANGED_ML) \ _avail(XrEventDataEyeCalibrationChangedML, XR_TYPE_EVENT_DATA_EYE_CALIBRATION_CHANGED_ML) \ @@ -264,7 +267,9 @@ This file contains expansion macros (X Macros) for OpenXR structures that have a _avail(XrSpatialAnchorsPublishCompletionML, XR_TYPE_SPATIAL_ANCHORS_PUBLISH_COMPLETION_ML) \ _avail(XrSpatialAnchorsDeleteCompletionML, XR_TYPE_SPATIAL_ANCHORS_DELETE_COMPLETION_ML) \ _avail(XrSpatialAnchorsUpdateExpirationCompletionML, XR_TYPE_SPATIAL_ANCHORS_UPDATE_EXPIRATION_COMPLETION_ML) \ + _avail(XrSenseDataQueryCompletionBD, XR_TYPE_SENSE_DATA_QUERY_COMPLETION_BD) \ _avail(XrFutureCompletionEXT, XR_TYPE_FUTURE_COMPLETION_EXT) \ + _avail(XrSpatialAnchorCreateCompletionBD, XR_TYPE_SPATIAL_ANCHOR_CREATE_COMPLETION_BD) \ _avail(XrWorldMeshStateRequestCompletionML, XR_TYPE_WORLD_MESH_STATE_REQUEST_COMPLETION_ML) \ _avail(XrWorldMeshRequestCompletionML, XR_TYPE_WORLD_MESH_REQUEST_COMPLETION_ML) \ @@ -312,5 +317,18 @@ This file contains expansion macros (X Macros) for OpenXR structures that have a +/// Like XR_LIST_ALL_STRUCTURE_TYPES, but only includes types whose parent struct type is XrShareSpacesRecipientBaseHeaderMETA +#define XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrShareSpacesRecipientBaseHeaderMETA(_avail, _unavail) \ + _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrShareSpacesRecipientBaseHeaderMETA_CORE(_avail, _unavail) \ + + +// Implementation detail of XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrShareSpacesRecipientBaseHeaderMETA() +#define _impl_XR_LIST_ALL_CHILD_STRUCTURE_TYPES_XrShareSpacesRecipientBaseHeaderMETA_CORE(_avail, _unavail) \ + _avail(XrShareSpacesRecipientGroupsMETA, XR_TYPE_SHARE_SPACES_RECIPIENT_GROUPS_META) \ + + + + + #endif diff --git a/thirdparty/openxr/include/openxr/openxr_reflection_structs.h b/thirdparty/openxr/include/openxr/openxr_reflection_structs.h index b1ab8e7779..a21e421c0a 100644 --- a/thirdparty/openxr/include/openxr/openxr_reflection_structs.h +++ b/thirdparty/openxr/include/openxr/openxr_reflection_structs.h @@ -2,7 +2,7 @@ #define OPENXR_REFLECTION_STRUCTS_H_ 1 /* -** Copyright (c) 2017-2024, The Khronos Group Inc. +** Copyright (c) 2017-2025 The Khronos Group Inc. ** ** SPDX-License-Identifier: Apache-2.0 OR MIT */ @@ -303,6 +303,8 @@ This file contains expansion macros (X Macros) for OpenXR structures. _avail(XrCompositionLayerSettingsFB, XR_TYPE_COMPOSITION_LAYER_SETTINGS_FB) \ _avail(XrHapticPcmVibrationFB, XR_TYPE_HAPTIC_PCM_VIBRATION_FB) \ _avail(XrDevicePcmSampleRateStateFB, XR_TYPE_DEVICE_PCM_SAMPLE_RATE_STATE_FB) \ + _avail(XrFrameSynthesisInfoEXT, XR_TYPE_FRAME_SYNTHESIS_INFO_EXT) \ + _avail(XrFrameSynthesisConfigViewEXT, XR_TYPE_FRAME_SYNTHESIS_CONFIG_VIEW_EXT) \ _avail(XrCompositionLayerDepthTestFB, XR_TYPE_COMPOSITION_LAYER_DEPTH_TEST_FB) \ _avail(XrLocalDimmingFrameEndInfoMETA, XR_TYPE_LOCAL_DIMMING_FRAME_END_INFO_META) \ _avail(XrPassthroughPreferencesMETA, XR_TYPE_PASSTHROUGH_PREFERENCES_META) \ @@ -337,10 +339,14 @@ This file contains expansion macros (X Macros) for OpenXR structures. _avail(XrSystemPassthroughColorLutPropertiesMETA, XR_TYPE_SYSTEM_PASSTHROUGH_COLOR_LUT_PROPERTIES_META) \ _avail(XrSpaceTriangleMeshGetInfoMETA, XR_TYPE_SPACE_TRIANGLE_MESH_GET_INFO_META) \ _avail(XrSpaceTriangleMeshMETA, XR_TYPE_SPACE_TRIANGLE_MESH_META) \ + _avail(XrEventDataPassthroughLayerResumedMETA, XR_TYPE_EVENT_DATA_PASSTHROUGH_LAYER_RESUMED_META) \ _avail(XrSystemFaceTrackingProperties2FB, XR_TYPE_SYSTEM_FACE_TRACKING_PROPERTIES2_FB) \ _avail(XrFaceTrackerCreateInfo2FB, XR_TYPE_FACE_TRACKER_CREATE_INFO2_FB) \ _avail(XrFaceExpressionInfo2FB, XR_TYPE_FACE_EXPRESSION_INFO2_FB) \ _avail(XrFaceExpressionWeights2FB, XR_TYPE_FACE_EXPRESSION_WEIGHTS2_FB) \ + _avail(XrSystemSpatialEntitySharingPropertiesMETA, XR_TYPE_SYSTEM_SPATIAL_ENTITY_SHARING_PROPERTIES_META) \ + _avail(XrShareSpacesInfoMETA, XR_TYPE_SHARE_SPACES_INFO_META) \ + _avail(XrEventDataShareSpacesCompleteMETA, XR_TYPE_EVENT_DATA_SHARE_SPACES_COMPLETE_META) \ _avail(XrEnvironmentDepthProviderCreateInfoMETA, XR_TYPE_ENVIRONMENT_DEPTH_PROVIDER_CREATE_INFO_META) \ _avail(XrEnvironmentDepthSwapchainCreateInfoMETA, XR_TYPE_ENVIRONMENT_DEPTH_SWAPCHAIN_CREATE_INFO_META) \ _avail(XrEnvironmentDepthSwapchainStateMETA, XR_TYPE_ENVIRONMENT_DEPTH_SWAPCHAIN_STATE_META) \ @@ -366,6 +372,45 @@ This file contains expansion macros (X Macros) for OpenXR structures. _avail(XrActiveActionSetPrioritiesEXT, XR_TYPE_ACTIVE_ACTION_SET_PRIORITIES_EXT) \ _avail(XrSystemForceFeedbackCurlPropertiesMNDX, XR_TYPE_SYSTEM_FORCE_FEEDBACK_CURL_PROPERTIES_MNDX) \ _avail(XrForceFeedbackCurlApplyLocationsMNDX, XR_TYPE_FORCE_FEEDBACK_CURL_APPLY_LOCATIONS_MNDX) \ + _avail(XrSystemBodyTrackingPropertiesBD, XR_TYPE_SYSTEM_BODY_TRACKING_PROPERTIES_BD) \ + _avail(XrBodyTrackerCreateInfoBD, XR_TYPE_BODY_TRACKER_CREATE_INFO_BD) \ + _avail(XrBodyJointsLocateInfoBD, XR_TYPE_BODY_JOINTS_LOCATE_INFO_BD) \ + _avail(XrBodyJointLocationsBD, XR_TYPE_BODY_JOINT_LOCATIONS_BD) \ + _avail(XrSystemSpatialSensingPropertiesBD, XR_TYPE_SYSTEM_SPATIAL_SENSING_PROPERTIES_BD) \ + _avail(XrSpatialEntityComponentGetInfoBD, XR_TYPE_SPATIAL_ENTITY_COMPONENT_GET_INFO_BD) \ + _avail(XrSpatialEntityLocationGetInfoBD, XR_TYPE_SPATIAL_ENTITY_LOCATION_GET_INFO_BD) \ + _avail(XrSpatialEntityComponentDataLocationBD, XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_LOCATION_BD) \ + _avail(XrSpatialEntityComponentDataSemanticBD, XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_SEMANTIC_BD) \ + _avail(XrSpatialEntityComponentDataBoundingBox2DBD, XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_BOUNDING_BOX_2D_BD) \ + _avail(XrSpatialEntityComponentDataPolygonBD, XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_POLYGON_BD) \ + _avail(XrSpatialEntityComponentDataBoundingBox3DBD, XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_BOUNDING_BOX_3D_BD) \ + _avail(XrSpatialEntityComponentDataTriangleMeshBD, XR_TYPE_SPATIAL_ENTITY_COMPONENT_DATA_TRIANGLE_MESH_BD) \ + _avail(XrSenseDataProviderCreateInfoBD, XR_TYPE_SENSE_DATA_PROVIDER_CREATE_INFO_BD) \ + _avail(XrSenseDataProviderStartInfoBD, XR_TYPE_SENSE_DATA_PROVIDER_START_INFO_BD) \ + _avail(XrEventDataSenseDataProviderStateChangedBD, XR_TYPE_EVENT_DATA_SENSE_DATA_PROVIDER_STATE_CHANGED_BD) \ + _avail(XrEventDataSenseDataUpdatedBD, XR_TYPE_EVENT_DATA_SENSE_DATA_UPDATED_BD) \ + _avail(XrSenseDataQueryInfoBD, XR_TYPE_SENSE_DATA_QUERY_INFO_BD) \ + _avail(XrSenseDataQueryCompletionBD, XR_TYPE_SENSE_DATA_QUERY_COMPLETION_BD) \ + _avail(XrQueriedSenseDataGetInfoBD, XR_TYPE_QUERIED_SENSE_DATA_GET_INFO_BD) \ + _avail(XrSpatialEntityStateBD, XR_TYPE_SPATIAL_ENTITY_STATE_BD) \ + _avail(XrQueriedSenseDataBD, XR_TYPE_QUERIED_SENSE_DATA_BD) \ + _avail(XrSenseDataFilterUuidBD, XR_TYPE_SENSE_DATA_FILTER_UUID_BD) \ + _avail(XrSenseDataFilterSemanticBD, XR_TYPE_SENSE_DATA_FILTER_SEMANTIC_BD) \ + _avail(XrSpatialEntityAnchorCreateInfoBD, XR_TYPE_SPATIAL_ENTITY_ANCHOR_CREATE_INFO_BD) \ + _avail(XrAnchorSpaceCreateInfoBD, XR_TYPE_ANCHOR_SPACE_CREATE_INFO_BD) \ + _avail(XrFutureCompletionEXT, XR_TYPE_FUTURE_COMPLETION_EXT) \ + _avail(XrSystemSpatialAnchorPropertiesBD, XR_TYPE_SYSTEM_SPATIAL_ANCHOR_PROPERTIES_BD) \ + _avail(XrSpatialAnchorCreateInfoBD, XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_BD) \ + _avail(XrSpatialAnchorCreateCompletionBD, XR_TYPE_SPATIAL_ANCHOR_CREATE_COMPLETION_BD) \ + _avail(XrSpatialAnchorPersistInfoBD, XR_TYPE_SPATIAL_ANCHOR_PERSIST_INFO_BD) \ + _avail(XrSpatialAnchorUnpersistInfoBD, XR_TYPE_SPATIAL_ANCHOR_UNPERSIST_INFO_BD) \ + _avail(XrSystemSpatialAnchorSharingPropertiesBD, XR_TYPE_SYSTEM_SPATIAL_ANCHOR_SHARING_PROPERTIES_BD) \ + _avail(XrSpatialAnchorShareInfoBD, XR_TYPE_SPATIAL_ANCHOR_SHARE_INFO_BD) \ + _avail(XrSharedSpatialAnchorDownloadInfoBD, XR_TYPE_SHARED_SPATIAL_ANCHOR_DOWNLOAD_INFO_BD) \ + _avail(XrSystemSpatialScenePropertiesBD, XR_TYPE_SYSTEM_SPATIAL_SCENE_PROPERTIES_BD) \ + _avail(XrSceneCaptureInfoBD, XR_TYPE_SCENE_CAPTURE_INFO_BD) \ + _avail(XrSystemSpatialMeshPropertiesBD, XR_TYPE_SYSTEM_SPATIAL_MESH_PROPERTIES_BD) \ + _avail(XrSenseDataProviderCreateInfoSpatialMeshBD, XR_TYPE_SENSE_DATA_PROVIDER_CREATE_INFO_SPATIAL_MESH_BD) \ _avail(XrHandTrackingDataSourceInfoEXT, XR_TYPE_HAND_TRACKING_DATA_SOURCE_INFO_EXT) \ _avail(XrHandTrackingDataSourceStateEXT, XR_TYPE_HAND_TRACKING_DATA_SOURCE_STATE_EXT) \ _avail(XrSystemPlaneDetectionPropertiesEXT, XR_TYPE_SYSTEM_PLANE_DETECTION_PROPERTIES_EXT) \ @@ -377,7 +422,6 @@ This file contains expansion macros (X Macros) for OpenXR structures. _avail(XrPlaneDetectorPolygonBufferEXT, XR_TYPE_PLANE_DETECTOR_POLYGON_BUFFER_EXT) \ _avail(XrFutureCancelInfoEXT, XR_TYPE_FUTURE_CANCEL_INFO_EXT) \ _avail(XrFuturePollInfoEXT, XR_TYPE_FUTURE_POLL_INFO_EXT) \ - _avail(XrFutureCompletionEXT, XR_TYPE_FUTURE_COMPLETION_EXT) \ _avail(XrFuturePollResultEXT, XR_TYPE_FUTURE_POLL_RESULT_EXT) \ _avail(XrEventDataUserPresenceChangedEXT, XR_TYPE_EVENT_DATA_USER_PRESENCE_CHANGED_EXT) \ _avail(XrSystemUserPresencePropertiesEXT, XR_TYPE_SYSTEM_USER_PRESENCE_PROPERTIES_EXT) \ @@ -397,6 +441,25 @@ This file contains expansion macros (X Macros) for OpenXR structures. _avail(XrWorldMeshBlockML, XR_TYPE_WORLD_MESH_BLOCK_ML) \ _avail(XrWorldMeshRequestCompletionInfoML, XR_TYPE_WORLD_MESH_REQUEST_COMPLETION_INFO_ML) \ _avail(XrWorldMeshRequestCompletionML, XR_TYPE_WORLD_MESH_REQUEST_COMPLETION_ML) \ + _avail(XrSystemFacialExpressionPropertiesML, XR_TYPE_SYSTEM_FACIAL_EXPRESSION_PROPERTIES_ML) \ + _avail(XrFacialExpressionClientCreateInfoML, XR_TYPE_FACIAL_EXPRESSION_CLIENT_CREATE_INFO_ML) \ + _avail(XrFacialExpressionBlendShapeGetInfoML, XR_TYPE_FACIAL_EXPRESSION_BLEND_SHAPE_GET_INFO_ML) \ + _avail(XrFacialExpressionBlendShapePropertiesML, XR_TYPE_FACIAL_EXPRESSION_BLEND_SHAPE_PROPERTIES_ML) \ + _avail(XrColocationDiscoveryStartInfoMETA, XR_TYPE_COLOCATION_DISCOVERY_START_INFO_META) \ + _avail(XrColocationDiscoveryStopInfoMETA, XR_TYPE_COLOCATION_DISCOVERY_STOP_INFO_META) \ + _avail(XrColocationAdvertisementStartInfoMETA, XR_TYPE_COLOCATION_ADVERTISEMENT_START_INFO_META) \ + _avail(XrColocationAdvertisementStopInfoMETA, XR_TYPE_COLOCATION_ADVERTISEMENT_STOP_INFO_META) \ + _avail(XrEventDataStartColocationAdvertisementCompleteMETA, XR_TYPE_EVENT_DATA_START_COLOCATION_ADVERTISEMENT_COMPLETE_META) \ + _avail(XrEventDataStopColocationAdvertisementCompleteMETA, XR_TYPE_EVENT_DATA_STOP_COLOCATION_ADVERTISEMENT_COMPLETE_META) \ + _avail(XrEventDataColocationAdvertisementCompleteMETA, XR_TYPE_EVENT_DATA_COLOCATION_ADVERTISEMENT_COMPLETE_META) \ + _avail(XrEventDataStartColocationDiscoveryCompleteMETA, XR_TYPE_EVENT_DATA_START_COLOCATION_DISCOVERY_COMPLETE_META) \ + _avail(XrEventDataColocationDiscoveryResultMETA, XR_TYPE_EVENT_DATA_COLOCATION_DISCOVERY_RESULT_META) \ + _avail(XrEventDataColocationDiscoveryCompleteMETA, XR_TYPE_EVENT_DATA_COLOCATION_DISCOVERY_COMPLETE_META) \ + _avail(XrEventDataStopColocationDiscoveryCompleteMETA, XR_TYPE_EVENT_DATA_STOP_COLOCATION_DISCOVERY_COMPLETE_META) \ + _avail(XrSystemColocationDiscoveryPropertiesMETA, XR_TYPE_SYSTEM_COLOCATION_DISCOVERY_PROPERTIES_META) \ + _avail(XrSystemSpatialEntityGroupSharingPropertiesMETA, XR_TYPE_SYSTEM_SPATIAL_ENTITY_GROUP_SHARING_PROPERTIES_META) \ + _avail(XrShareSpacesRecipientGroupsMETA, XR_TYPE_SHARE_SPACES_RECIPIENT_GROUPS_META) \ + _avail(XrSpaceGroupUuidFilterInfoMETA, XR_TYPE_SPACE_GROUP_UUID_FILTER_INFO_META) \ #if defined(XR_USE_GRAPHICS_API_D3D11) diff --git a/thirdparty/openxr/src/common/android_logging.h b/thirdparty/openxr/src/common/android_logging.h new file mode 100644 index 0000000000..9e612b5d00 --- /dev/null +++ b/thirdparty/openxr/src/common/android_logging.h @@ -0,0 +1,22 @@ +// Copyright (c) 2018-2025 The Khronos Group Inc. +// +// SPDX-License-Identifier: Apache-2.0 OR MIT +// +// Utility macros for Android logging. + +#pragma once + +#ifdef XR_USE_PLATFORM_ANDROID +#include + +#if !defined(LOG_TAG) +#error "LOG_TAG must be defined before including android_logging.h" +#endif + +#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__) +#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) +#define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) +#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) +#define ALOGF(...) __android_log_print(ANDROID_LOG_FATAL, LOG_TAG, __VA_ARGS__) + +#endif // XR_USE_PLATFORM_ANDROID diff --git a/thirdparty/openxr/src/common/extra_algorithms.h b/thirdparty/openxr/src/common/extra_algorithms.h index bdaa420e9f..c373eb9ccf 100644 --- a/thirdparty/openxr/src/common/extra_algorithms.h +++ b/thirdparty/openxr/src/common/extra_algorithms.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // Copyright (c) 2019 Collabora, Ltd. diff --git a/thirdparty/openxr/src/common/filesystem_utils.cpp b/thirdparty/openxr/src/common/filesystem_utils.cpp index 063c4c4cee..8e71fad932 100644 --- a/thirdparty/openxr/src/common/filesystem_utils.cpp +++ b/thirdparty/openxr/src/common/filesystem_utils.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017 Valve Corporation // Copyright (c) 2017 LunarG, Inc. // diff --git a/thirdparty/openxr/src/common/filesystem_utils.hpp b/thirdparty/openxr/src/common/filesystem_utils.hpp index 2a923fac4c..354d1bcfad 100644 --- a/thirdparty/openxr/src/common/filesystem_utils.hpp +++ b/thirdparty/openxr/src/common/filesystem_utils.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017 Valve Corporation // Copyright (c) 2017 LunarG, Inc. // diff --git a/thirdparty/openxr/src/common/hex_and_handles.h b/thirdparty/openxr/src/common/hex_and_handles.h index 12bdb3670c..7fcad0941f 100644 --- a/thirdparty/openxr/src/common/hex_and_handles.h +++ b/thirdparty/openxr/src/common/hex_and_handles.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // Copyright (c) 2019 Collabora, Ltd. diff --git a/thirdparty/openxr/src/common/object_info.cpp b/thirdparty/openxr/src/common/object_info.cpp index d45430a609..5cc658571c 100644 --- a/thirdparty/openxr/src/common/object_info.cpp +++ b/thirdparty/openxr/src/common/object_info.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // Copyright (c) 2019 Collabora, Ltd. diff --git a/thirdparty/openxr/src/common/object_info.h b/thirdparty/openxr/src/common/object_info.h index 572f06ab15..4bb8f63646 100644 --- a/thirdparty/openxr/src/common/object_info.h +++ b/thirdparty/openxr/src/common/object_info.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // Copyright (c) 2019 Collabora, Ltd. diff --git a/thirdparty/openxr/src/common/platform_utils.hpp b/thirdparty/openxr/src/common/platform_utils.hpp index 19cd41cbb2..9715fc02cd 100644 --- a/thirdparty/openxr/src/common/platform_utils.hpp +++ b/thirdparty/openxr/src/common/platform_utils.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // @@ -71,6 +71,8 @@ #define XR_ARCH_ABI "riscv64" #elif defined(__sparc__) && defined(__arch64__) #define XR_ARCH_ABI "sparc64" +#elif defined(__loongarch64) +#define XR_ARCH_ABI "loongarch64" #else #error "No architecture string known!" #endif diff --git a/thirdparty/openxr/src/common/stdfs_conditions.h b/thirdparty/openxr/src/common/stdfs_conditions.h index 9e2ba70d42..0b68297efd 100644 --- a/thirdparty/openxr/src/common/stdfs_conditions.h +++ b/thirdparty/openxr/src/common/stdfs_conditions.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017 Valve Corporation // Copyright (c) 2017 LunarG, Inc. // diff --git a/thirdparty/openxr/src/common/unique_asset.h b/thirdparty/openxr/src/common/unique_asset.h index fd5f8868e3..8ef36421e8 100644 --- a/thirdparty/openxr/src/common/unique_asset.h +++ b/thirdparty/openxr/src/common/unique_asset.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // // SPDX-License-Identifier: Apache-2.0 OR MIT #pragma once diff --git a/thirdparty/openxr/src/common/vulkan_debug_object_namer.hpp b/thirdparty/openxr/src/common/vulkan_debug_object_namer.hpp index 885389ce8e..08675d73f7 100644 --- a/thirdparty/openxr/src/common/vulkan_debug_object_namer.hpp +++ b/thirdparty/openxr/src/common/vulkan_debug_object_namer.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // // SPDX-License-Identifier: Apache-2.0 diff --git a/thirdparty/openxr/src/common/xr_dependencies.h b/thirdparty/openxr/src/common/xr_dependencies.h index a192a2ec6d..70c3c6be83 100644 --- a/thirdparty/openxr/src/common/xr_dependencies.h +++ b/thirdparty/openxr/src/common/xr_dependencies.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018-2024, The Khronos Group Inc. +// Copyright (c) 2018-2025 The Khronos Group Inc. // // SPDX-License-Identifier: Apache-2.0 OR MIT // diff --git a/thirdparty/openxr/src/common/xr_linear.h b/thirdparty/openxr/src/common/xr_linear.h index cc525d3357..e80c61da95 100644 --- a/thirdparty/openxr/src/common/xr_linear.h +++ b/thirdparty/openxr/src/common/xr_linear.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2016, Oculus VR, LLC. // // SPDX-License-Identifier: Apache-2.0 diff --git a/thirdparty/openxr/src/external/jsoncpp/include/json/allocator.h b/thirdparty/openxr/src/external/jsoncpp/include/json/allocator.h index 95ef8a5ec4..f4fcc1c68d 100644 --- a/thirdparty/openxr/src/external/jsoncpp/include/json/allocator.h +++ b/thirdparty/openxr/src/external/jsoncpp/include/json/allocator.h @@ -9,7 +9,8 @@ #include #include -#pragma pack(push, 8) +#pragma pack(push) +#pragma pack() namespace Json { template class SecureAllocator { @@ -68,7 +69,9 @@ public: // Boilerplate SecureAllocator() {} template SecureAllocator(const SecureAllocator&) {} - template struct rebind { using other = SecureAllocator; }; + template struct rebind { + using other = SecureAllocator; + }; }; template diff --git a/thirdparty/openxr/src/external/jsoncpp/include/json/json_features.h b/thirdparty/openxr/src/external/jsoncpp/include/json/json_features.h index 7c7e9f5de1..e4a61d6f18 100644 --- a/thirdparty/openxr/src/external/jsoncpp/include/json/json_features.h +++ b/thirdparty/openxr/src/external/jsoncpp/include/json/json_features.h @@ -10,7 +10,8 @@ #include "forwards.h" #endif // if !defined(JSON_IS_AMALGAMATION) -#pragma pack(push, 8) +#pragma pack(push) +#pragma pack() namespace Json { diff --git a/thirdparty/openxr/src/external/jsoncpp/include/json/reader.h b/thirdparty/openxr/src/external/jsoncpp/include/json/reader.h index be0d7676ab..d745378fc6 100644 --- a/thirdparty/openxr/src/external/jsoncpp/include/json/reader.h +++ b/thirdparty/openxr/src/external/jsoncpp/include/json/reader.h @@ -23,7 +23,8 @@ #pragma warning(disable : 4251) #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma pack(push, 8) +#pragma pack(push) +#pragma pack() namespace Json { @@ -50,12 +51,12 @@ public: }; /** \brief Constructs a Reader allowing all features for parsing. - * \deprecated Use CharReader and CharReaderBuilder. + * \deprecated Use CharReader and CharReaderBuilder. */ Reader(); /** \brief Constructs a Reader allowing the specified feature set for parsing. - * \deprecated Use CharReader and CharReaderBuilder. + * \deprecated Use CharReader and CharReaderBuilder. */ Reader(const Features& features); @@ -189,6 +190,7 @@ private: using Errors = std::deque; bool readToken(Token& token); + bool readTokenSkippingComments(Token& token); void skipSpaces(); bool match(const Char* pattern, int patternLength); bool readComment(); @@ -220,7 +222,6 @@ private: int& column) const; String getLocationLineAndColumn(Location location) const; void addComment(Location begin, Location end, CommentPlacement placement); - void skipCommentTokens(Token& token); static bool containsNewLine(Location begin, Location end); static String normalizeEOL(Location begin, Location end); @@ -243,6 +244,12 @@ private: */ class JSON_API CharReader { public: + struct JSON_API StructuredError { + ptrdiff_t offset_start; + ptrdiff_t offset_limit; + String message; + }; + virtual ~CharReader() = default; /** \brief Read a Value from a JSON * document. The document must be a UTF-8 encoded string containing the @@ -261,7 +268,12 @@ public: * error occurred. */ virtual bool parse(char const* beginDoc, char const* endDoc, Value* root, - String* errs) = 0; + String* errs); + + /** \brief Returns a vector of structured errors encountered while parsing. + * Each parse call resets the stored list of errors. + */ + std::vector getStructuredErrors() const; class JSON_API Factory { public: @@ -271,7 +283,21 @@ public: */ virtual CharReader* newCharReader() const = 0; }; // Factory -}; // CharReader + +protected: + class Impl { + public: + virtual ~Impl() = default; + virtual bool parse(char const* beginDoc, char const* endDoc, Value* root, + String* errs) = 0; + virtual std::vector getStructuredErrors() const = 0; + }; + + explicit CharReader(std::unique_ptr impl) : _impl(std::move(impl)) {} + +private: + std::unique_ptr _impl; +}; // CharReader /** \brief Build a CharReader implementation. * @@ -359,6 +385,12 @@ public: * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode */ static void strictMode(Json::Value* settings); + /** ECMA-404 mode. + * \pre 'settings' != NULL (but Json::null is fine) + * \remark Defaults: + * \snippet src/lib_json/json_reader.cpp CharReaderBuilderECMA404Mode + */ + static void ecma404Mode(Json::Value* settings); }; /** Consume entire stream and use its begin/end. diff --git a/thirdparty/openxr/src/external/jsoncpp/include/json/value.h b/thirdparty/openxr/src/external/jsoncpp/include/json/value.h index 0edeb050ca..c8e1aae2e3 100644 --- a/thirdparty/openxr/src/external/jsoncpp/include/json/value.h +++ b/thirdparty/openxr/src/external/jsoncpp/include/json/value.h @@ -3,8 +3,8 @@ // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE -#ifndef JSON_H_INCLUDED -#define JSON_H_INCLUDED +#ifndef JSON_VALUE_H_INCLUDED +#define JSON_VALUE_H_INCLUDED #if !defined(JSON_IS_AMALGAMATION) #include "forwards.h" @@ -53,7 +53,8 @@ #pragma warning(disable : 4251 4275) #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma pack(push, 8) +#pragma pack(push) +#pragma pack() /** \brief JSON (JavaScript Object Notation). */ @@ -436,7 +437,7 @@ public: /// \post type() is arrayValue void resize(ArrayIndex newSize); - //@{ + ///@{ /// Access an array element (zero based index). If the array contains less /// than index element, then null value are inserted in the array so that /// its size is index+1. @@ -444,15 +445,15 @@ public: /// this from the operator[] which takes a string.) Value& operator[](ArrayIndex index); Value& operator[](int index); - //@} + ///@} - //@{ + ///@{ /// Access an array element (zero based index). /// (You may need to say 'value[0u]' to get your compiler to distinguish /// this from the operator[] which takes a string.) const Value& operator[](ArrayIndex index) const; const Value& operator[](int index) const; - //@} + ///@} /// If the array contains at least index+1 elements, returns the element /// value, otherwise returns defaultValue. @@ -512,6 +513,9 @@ public: /// and operator[]const /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 Value const* find(char const* begin, char const* end) const; + /// Most general and efficient version of isMember()const, get()const, + /// and operator[]const + Value const* find(const String& key) const; /// Most general and efficient version of object-mutators. /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 /// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue. @@ -584,6 +588,26 @@ public: iterator begin(); iterator end(); + /// \brief Returns a reference to the first element in the `Value`. + /// Requires that this value holds an array or json object, with at least one + /// element. + const Value& front() const; + + /// \brief Returns a reference to the first element in the `Value`. + /// Requires that this value holds an array or json object, with at least one + /// element. + Value& front(); + + /// \brief Returns a reference to the last element in the `Value`. + /// Requires that value holds an array or json object, with at least one + /// element. + const Value& back() const; + + /// \brief Returns a reference to the last element in the `Value`. + /// Requires that this value holds an array or json object, with at least one + /// element. + Value& back(); + // Accessors for the [start, limit) range of bytes within the JSON text from // which this value was parsed, if any. void setOffsetStart(ptrdiff_t start); @@ -924,6 +948,14 @@ public: inline void swap(Value& a, Value& b) { a.swap(b); } +inline const Value& Value::front() const { return *begin(); } + +inline Value& Value::front() { return *begin(); } + +inline const Value& Value::back() const { return *(--end()); } + +inline Value& Value::back() { return *(--end()); } + } // namespace Json #pragma pack(pop) diff --git a/thirdparty/openxr/src/external/jsoncpp/include/json/version.h b/thirdparty/openxr/src/external/jsoncpp/include/json/version.h index e931d0383e..38faedf11d 100644 --- a/thirdparty/openxr/src/external/jsoncpp/include/json/version.h +++ b/thirdparty/openxr/src/external/jsoncpp/include/json/version.h @@ -9,19 +9,18 @@ // 3. /CMakeLists.txt // IMPORTANT: also update the SOVERSION!! -#define JSONCPP_VERSION_STRING "1.9.5" +#define JSONCPP_VERSION_STRING "1.9.6" #define JSONCPP_VERSION_MAJOR 1 #define JSONCPP_VERSION_MINOR 9 -#define JSONCPP_VERSION_PATCH 5 +#define JSONCPP_VERSION_PATCH 6 #define JSONCPP_VERSION_QUALIFIER #define JSONCPP_VERSION_HEXA \ ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \ (JSONCPP_VERSION_PATCH << 8)) -#ifdef JSONCPP_USING_SECURE_MEMORY -#undef JSONCPP_USING_SECURE_MEMORY -#endif +#if !defined(JSONCPP_USE_SECURE_MEMORY) #define JSONCPP_USING_SECURE_MEMORY 0 +#endif // If non-zero, the library zeroes any memory that it has allocated before // it frees its memory. diff --git a/thirdparty/openxr/src/external/jsoncpp/include/json/writer.h b/thirdparty/openxr/src/external/jsoncpp/include/json/writer.h index 88a3b12e9d..7c56a21074 100644 --- a/thirdparty/openxr/src/external/jsoncpp/include/json/writer.h +++ b/thirdparty/openxr/src/external/jsoncpp/include/json/writer.h @@ -20,7 +20,8 @@ #pragma warning(disable : 4251) #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma pack(push, 8) +#pragma pack(push) +#pragma pack() namespace Json { @@ -63,7 +64,7 @@ public: */ virtual StreamWriter* newStreamWriter() const = 0; }; // Factory -}; // StreamWriter +}; // StreamWriter /** \brief Write into stringstream, then return string, for convenience. * A StreamWriter will be created from the factory, used, and then deleted. @@ -167,8 +168,7 @@ public: #pragma warning(push) #pragma warning(disable : 4996) // Deriving from deprecated class #endif -class JSON_API FastWriter - : public Writer { +class JSON_API FastWriter : public Writer { public: FastWriter(); ~FastWriter() override = default; @@ -217,7 +217,7 @@ private: * - otherwise, it the values do not fit on one line, or the array contains * object or non empty array, then print one value per line. * - * If the Value have comments then they are outputed according to their + * If the Value have comments then they are outputted according to their *#CommentPlacement. * * \sa Reader, Value, Value::setComment() @@ -227,8 +227,7 @@ private: #pragma warning(push) #pragma warning(disable : 4996) // Deriving from deprecated class #endif -class JSON_API - StyledWriter : public Writer { +class JSON_API StyledWriter : public Writer { public: StyledWriter(); ~StyledWriter() override = default; @@ -286,7 +285,7 @@ private: * - otherwise, it the values do not fit on one line, or the array contains * object or non empty array, then print one value per line. * - * If the Value have comments then they are outputed according to their + * If the Value have comments then they are outputted according to their #CommentPlacement. * * \sa Reader, Value, Value::setComment() @@ -296,8 +295,7 @@ private: #pragma warning(push) #pragma warning(disable : 4996) // Deriving from deprecated class #endif -class JSON_API - StyledStreamWriter { +class JSON_API StyledStreamWriter { public: /** * \param indentation Each level will be indented by this amount extra. @@ -353,6 +351,7 @@ String JSON_API valueToString( PrecisionType precisionType = PrecisionType::significantDigits); String JSON_API valueToString(bool value); String JSON_API valueToQuotedString(const char* value); +String JSON_API valueToQuotedString(const char* value, size_t length); /// \brief Output using the StyledStreamWriter. /// \see Json::operator>>() diff --git a/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_reader.cpp b/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_reader.cpp index a6a3f4e30d..10c97aecbe 100644 --- a/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_reader.cpp +++ b/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_reader.cpp @@ -12,6 +12,7 @@ #endif // if !defined(JSON_IS_AMALGAMATION) #include #include +#include #include #include #include @@ -128,7 +129,7 @@ bool Reader::parse(const char* beginDoc, const char* endDoc, Value& root, bool successful = readValue(); Token token; - skipCommentTokens(token); + readTokenSkippingComments(token); if (collectComments_ && !commentsBefore_.empty()) root.setComment(commentsBefore_, commentAfter); if (features_.strictRoot_) { @@ -156,7 +157,7 @@ bool Reader::readValue() { throwRuntimeError("Exceeded stackLimit in readValue()."); Token token; - skipCommentTokens(token); + readTokenSkippingComments(token); bool successful = true; if (collectComments_ && !commentsBefore_.empty()) { @@ -224,14 +225,14 @@ bool Reader::readValue() { return successful; } -void Reader::skipCommentTokens(Token& token) { +bool Reader::readTokenSkippingComments(Token& token) { + bool success = readToken(token); if (features_.allowComments_) { - do { - readToken(token); - } while (token.type_ == tokenComment); - } else { - readToken(token); + while (success && token.type_ == tokenComment) { + success = readToken(token); + } } + return success; } bool Reader::readToken(Token& token) { @@ -445,12 +446,7 @@ bool Reader::readObject(Token& token) { Value init(objectValue); currentValue().swapPayload(init); currentValue().setOffsetStart(token.start_ - begin_); - while (readToken(tokenName)) { - bool initialTokenOk = true; - while (tokenName.type_ == tokenComment && initialTokenOk) - initialTokenOk = readToken(tokenName); - if (!initialTokenOk) - break; + while (readTokenSkippingComments(tokenName)) { if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object return true; name.clear(); @@ -479,15 +475,11 @@ bool Reader::readObject(Token& token) { return recoverFromError(tokenObjectEnd); Token comma; - if (!readToken(comma) || - (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && - comma.type_ != tokenComment)) { + if (!readTokenSkippingComments(comma) || + (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator)) { return addErrorAndRecover("Missing ',' or '}' in object declaration", comma, tokenObjectEnd); } - bool finalizeTokenOk = true; - while (comma.type_ == tokenComment && finalizeTokenOk) - finalizeTokenOk = readToken(comma); if (comma.type_ == tokenObjectEnd) return true; } @@ -517,10 +509,7 @@ bool Reader::readArray(Token& token) { Token currentToken; // Accept Comment after last item in the array. - ok = readToken(currentToken); - while (currentToken.type_ == tokenComment && ok) { - ok = readToken(currentToken); - } + ok = readTokenSkippingComments(currentToken); bool badTokenType = (currentToken.type_ != tokenArraySeparator && currentToken.type_ != tokenArrayEnd); if (!ok || badTokenType) { @@ -598,11 +587,16 @@ bool Reader::decodeDouble(Token& token) { bool Reader::decodeDouble(Token& token, Value& decoded) { double value = 0; - String buffer(token.start_, token.end_); - IStringStream is(buffer); - if (!(is >> value)) - return addError( - "'" + String(token.start_, token.end_) + "' is not a number.", token); + IStringStream is(String(token.start_, token.end_)); + if (!(is >> value)) { + if (value == std::numeric_limits::max()) + value = std::numeric_limits::infinity(); + else if (value == std::numeric_limits::lowest()) + value = -std::numeric_limits::infinity(); + else if (!std::isinf(value)) + return addError( + "'" + String(token.start_, token.end_) + "' is not a number.", token); + } decoded = value; return true; } @@ -766,7 +760,7 @@ void Reader::getLocationLineAndColumn(Location location, int& line, while (current < location && current != end_) { Char c = *current++; if (c == '\r') { - if (*current == '\n') + if (current != end_ && *current == '\n') ++current; lastLineStart = current; ++line; @@ -883,17 +877,12 @@ class OurReader { public: using Char = char; using Location = const Char*; - struct StructuredError { - ptrdiff_t offset_start; - ptrdiff_t offset_limit; - String message; - }; explicit OurReader(OurFeatures const& features); bool parse(const char* beginDoc, const char* endDoc, Value& root, bool collectComments = true); String getFormattedErrorMessages() const; - std::vector getStructuredErrors() const; + std::vector getStructuredErrors() const; private: OurReader(OurReader const&); // no impl @@ -936,6 +925,7 @@ private: using Errors = std::deque; bool readToken(Token& token); + bool readTokenSkippingComments(Token& token); void skipSpaces(); void skipBom(bool skipBom); bool match(const Char* pattern, int patternLength); @@ -969,7 +959,6 @@ private: int& column) const; String getLocationLineAndColumn(Location location) const; void addComment(Location begin, Location end, CommentPlacement placement); - void skipCommentTokens(Token& token); static String normalizeEOL(Location begin, Location end); static bool containsNewLine(Location begin, Location end); @@ -1023,7 +1012,7 @@ bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root, bool successful = readValue(); nodes_.pop(); Token token; - skipCommentTokens(token); + readTokenSkippingComments(token); if (features_.failIfExtra_ && (token.type_ != tokenEndOfStream)) { addError("Extra non-whitespace after JSON value.", token); return false; @@ -1051,7 +1040,7 @@ bool OurReader::readValue() { if (nodes_.size() > features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue()."); Token token; - skipCommentTokens(token); + readTokenSkippingComments(token); bool successful = true; if (collectComments_ && !commentsBefore_.empty()) { @@ -1138,14 +1127,14 @@ bool OurReader::readValue() { return successful; } -void OurReader::skipCommentTokens(Token& token) { +bool OurReader::readTokenSkippingComments(Token& token) { + bool success = readToken(token); if (features_.allowComments_) { - do { - readToken(token); - } while (token.type_ == tokenComment); - } else { - readToken(token); + while (success && token.type_ == tokenComment) { + success = readToken(token); + } } + return success; } bool OurReader::readToken(Token& token) { @@ -1442,12 +1431,7 @@ bool OurReader::readObject(Token& token) { Value init(objectValue); currentValue().swapPayload(init); currentValue().setOffsetStart(token.start_ - begin_); - while (readToken(tokenName)) { - bool initialTokenOk = true; - while (tokenName.type_ == tokenComment && initialTokenOk) - initialTokenOk = readToken(tokenName); - if (!initialTokenOk) - break; + while (readTokenSkippingComments(tokenName)) { if (tokenName.type_ == tokenObjectEnd && (name.empty() || features_.allowTrailingCommas_)) // empty object or trailing comma @@ -1484,15 +1468,11 @@ bool OurReader::readObject(Token& token) { return recoverFromError(tokenObjectEnd); Token comma; - if (!readToken(comma) || - (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && - comma.type_ != tokenComment)) { + if (!readTokenSkippingComments(comma) || + (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator)) { return addErrorAndRecover("Missing ',' or '}' in object declaration", comma, tokenObjectEnd); } - bool finalizeTokenOk = true; - while (comma.type_ == tokenComment && finalizeTokenOk) - finalizeTokenOk = readToken(comma); if (comma.type_ == tokenObjectEnd) return true; } @@ -1526,10 +1506,7 @@ bool OurReader::readArray(Token& token) { Token currentToken; // Accept Comment after last item in the array. - ok = readToken(currentToken); - while (currentToken.type_ == tokenComment && ok) { - ok = readToken(currentToken); - } + ok = readTokenSkippingComments(currentToken); bool badTokenType = (currentToken.type_ != tokenArraySeparator && currentToken.type_ != tokenArrayEnd); if (!ok || badTokenType) { @@ -1607,7 +1584,7 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) { const auto digit(static_cast(c - '0')); if (value >= threshold) { // We've hit or exceeded the max value divided by 10 (rounded down). If - // a) we've only just touched the limit, meaing value == threshold, + // a) we've only just touched the limit, meaning value == threshold, // b) this is the last digit, or // c) it's small enough to fit in that rounding delta, we're okay. // Otherwise treat this number as a double to avoid overflow. @@ -1644,11 +1621,15 @@ bool OurReader::decodeDouble(Token& token) { bool OurReader::decodeDouble(Token& token, Value& decoded) { double value = 0; - const String buffer(token.start_, token.end_); - IStringStream is(buffer); + IStringStream is(String(token.start_, token.end_)); if (!(is >> value)) { - return addError( - "'" + String(token.start_, token.end_) + "' is not a number.", token); + if (value == std::numeric_limits::max()) + value = std::numeric_limits::infinity(); + else if (value == std::numeric_limits::lowest()) + value = -std::numeric_limits::infinity(); + else if (!std::isinf(value)) + return addError( + "'" + String(token.start_, token.end_) + "' is not a number.", token); } decoded = value; return true; @@ -1813,7 +1794,7 @@ void OurReader::getLocationLineAndColumn(Location location, int& line, while (current < location && current != end_) { Char c = *current++; if (c == '\r') { - if (*current == '\n') + if (current != end_ && *current == '\n') ++current; lastLineStart = current; ++line; @@ -1848,10 +1829,11 @@ String OurReader::getFormattedErrorMessages() const { return formattedMessage; } -std::vector OurReader::getStructuredErrors() const { - std::vector allErrors; +std::vector +OurReader::getStructuredErrors() const { + std::vector allErrors; for (const auto& error : errors_) { - OurReader::StructuredError structured; + CharReader::StructuredError structured; structured.offset_start = error.token_.start_ - begin_; structured.offset_limit = error.token_.end_ - begin_; structured.message = error.message_; @@ -1861,20 +1843,36 @@ std::vector OurReader::getStructuredErrors() const { } class OurCharReader : public CharReader { - bool const collectComments_; - OurReader reader_; public: OurCharReader(bool collectComments, OurFeatures const& features) - : collectComments_(collectComments), reader_(features) {} - bool parse(char const* beginDoc, char const* endDoc, Value* root, - String* errs) override { - bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_); - if (errs) { - *errs = reader_.getFormattedErrorMessages(); + : CharReader( + std::unique_ptr(new OurImpl(collectComments, features))) {} + +protected: + class OurImpl : public Impl { + public: + OurImpl(bool collectComments, OurFeatures const& features) + : collectComments_(collectComments), reader_(features) {} + + bool parse(char const* beginDoc, char const* endDoc, Value* root, + String* errs) override { + bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_); + if (errs) { + *errs = reader_.getFormattedErrorMessages(); + } + return ok; } - return ok; - } + + std::vector + getStructuredErrors() const override { + return reader_.getStructuredErrors(); + } + + private: + bool const collectComments_; + OurReader reader_; + }; }; CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); } @@ -1963,6 +1961,32 @@ void CharReaderBuilder::setDefaults(Json::Value* settings) { (*settings)["skipBom"] = true; //! [CharReaderBuilderDefaults] } +// static +void CharReaderBuilder::ecma404Mode(Json::Value* settings) { + //! [CharReaderBuilderECMA404Mode] + (*settings)["allowComments"] = false; + (*settings)["allowTrailingCommas"] = false; + (*settings)["strictRoot"] = false; + (*settings)["allowDroppedNullPlaceholders"] = false; + (*settings)["allowNumericKeys"] = false; + (*settings)["allowSingleQuotes"] = false; + (*settings)["stackLimit"] = 1000; + (*settings)["failIfExtra"] = true; + (*settings)["rejectDupKeys"] = false; + (*settings)["allowSpecialFloats"] = false; + (*settings)["skipBom"] = false; + //! [CharReaderBuilderECMA404Mode] +} + +std::vector +CharReader::getStructuredErrors() const { + return _impl->getStructuredErrors(); +} + +bool CharReader::parse(char const* beginDoc, char const* endDoc, Value* root, + String* errs) { + return _impl->parse(beginDoc, endDoc, root, errs); +} ////////////////////////////////// // global functions @@ -1971,7 +1995,7 @@ bool parseFromStream(CharReader::Factory const& fact, IStream& sin, Value* root, String* errs) { OStringStream ssin; ssin << sin.rdbuf(); - String doc = ssin.str(); + String doc = std::move(ssin).str(); char const* begin = doc.data(); char const* end = begin + doc.size(); // Note that we do not actually need a null-terminator. diff --git a/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_value.cpp b/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_value.cpp index aa2b744ca8..5bd8d9a272 100644 --- a/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_value.cpp +++ b/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_value.cpp @@ -1092,6 +1092,9 @@ Value const* Value::find(char const* begin, char const* end) const { return nullptr; return &(*it).second; } +Value const* Value::find(const String& key) const { + return find(key.data(), key.data() + key.length()); +} Value* Value::demand(char const* begin, char const* end) { JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue, "in Json::Value::demand(begin, end): requires " @@ -1105,7 +1108,7 @@ const Value& Value::operator[](const char* key) const { return *found; } Value const& Value::operator[](const String& key) const { - Value const* found = find(key.data(), key.data() + key.length()); + Value const* found = find(key); if (!found) return nullSingleton(); return *found; @@ -1205,7 +1208,7 @@ bool Value::removeIndex(ArrayIndex index, Value* removed) { return false; } if (removed) - *removed = it->second; + *removed = std::move(it->second); ArrayIndex oldSize = size(); // shift left all items left, into the place of the "removed" for (ArrayIndex i = index; i < (oldSize - 1); ++i) { @@ -1410,9 +1413,8 @@ void Value::setComment(String comment, CommentPlacement placement) { // Always discard trailing newline, to aid indentation. comment.pop_back(); } - JSON_ASSERT(!comment.empty()); JSON_ASSERT_MESSAGE( - comment[0] == '\0' || comment[0] == '/', + comment.empty() || comment[0] == '/', "in Json::Value::setComment(): Comments must start with /"); comments_.set(placement, std::move(comment)); } diff --git a/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_writer.cpp b/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_writer.cpp index 0dd160e452..ee45c43ba1 100644 --- a/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_writer.cpp +++ b/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_writer.cpp @@ -132,8 +132,9 @@ String valueToString(double value, bool useSpecialFloats, if (!isfinite(value)) { static const char* const reps[2][3] = {{"NaN", "-Infinity", "Infinity"}, {"null", "-1e+9999", "1e+9999"}}; - return reps[useSpecialFloats ? 0 : 1] - [isnan(value) ? 0 : (value < 0) ? 1 : 2]; + return reps[useSpecialFloats ? 0 : 1][isnan(value) ? 0 + : (value < 0) ? 1 + : 2]; } String buffer(size_t(36), '\0'); @@ -353,6 +354,10 @@ String valueToQuotedString(const char* value) { return valueToQuotedStringN(value, strlen(value)); } +String valueToQuotedString(const char* value, size_t length) { + return valueToQuotedStringN(value, length); +} + // Class Writer // ////////////////////////////////////////////////////////////////// Writer::~Writer() = default; @@ -490,7 +495,7 @@ void StyledWriter::writeValue(const Value& value) { const String& name = *it; const Value& childValue = value[name]; writeCommentBeforeValue(childValue); - writeWithIndent(valueToQuotedString(name.c_str())); + writeWithIndent(valueToQuotedString(name.c_str(), name.size())); document_ += " : "; writeValue(childValue); if (++it == members.end()) { @@ -708,7 +713,7 @@ void StyledStreamWriter::writeValue(const Value& value) { const String& name = *it; const Value& childValue = value[name]; writeCommentBeforeValue(childValue); - writeWithIndent(valueToQuotedString(name.c_str())); + writeWithIndent(valueToQuotedString(name.c_str(), name.size())); *document_ << " : "; writeValue(childValue); if (++it == members.end()) { @@ -1246,7 +1251,7 @@ String writeString(StreamWriter::Factory const& factory, Value const& root) { OStringStream sout; StreamWriterPtr const writer(factory.newStreamWriter()); writer->write(root, &sout); - return sout.str(); + return std::move(sout).str(); } OStream& operator<<(OStream& sout, Value const& root) { diff --git a/thirdparty/openxr/src/loader/android_utilities.cpp b/thirdparty/openxr/src/loader/android_utilities.cpp index 1f7424b8e6..54db54fffd 100644 --- a/thirdparty/openxr/src/loader/android_utilities.cpp +++ b/thirdparty/openxr/src/loader/android_utilities.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020-2024, The Khronos Group Inc. +// Copyright (c) 2020-2025 The Khronos Group Inc. // Copyright (c) 2020-2021, Collabora, Ltd. // // SPDX-License-Identifier: Apache-2.0 OR MIT @@ -20,10 +20,8 @@ #include #include -#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, "OpenXR-Loader", __VA_ARGS__) -#define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, "OpenXR-Loader", __VA_ARGS__) -#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, "OpenXR-Loader", __VA_ARGS__) -#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, "OpenXR-Loader", __VA_ARGS__) +#define LOG_TAG "OpenXR-Loader" +#include "android_logging.h" namespace openxr_android { using wrap::android::content::ContentUris; diff --git a/thirdparty/openxr/src/loader/android_utilities.h b/thirdparty/openxr/src/loader/android_utilities.h index 582a65056e..a1f99388fc 100644 --- a/thirdparty/openxr/src/loader/android_utilities.h +++ b/thirdparty/openxr/src/loader/android_utilities.h @@ -1,4 +1,4 @@ -// Copyright (c) 2020-2024, The Khronos Group Inc. +// Copyright (c) 2020-2025 The Khronos Group Inc. // Copyright (c) 2020-2021, Collabora, Ltd. // // SPDX-License-Identifier: Apache-2.0 OR MIT diff --git a/thirdparty/openxr/src/loader/api_layer_interface.cpp b/thirdparty/openxr/src/loader/api_layer_interface.cpp index a93d45da37..0ca99a56a8 100644 --- a/thirdparty/openxr/src/loader/api_layer_interface.cpp +++ b/thirdparty/openxr/src/loader/api_layer_interface.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/loader/api_layer_interface.hpp b/thirdparty/openxr/src/loader/api_layer_interface.hpp index 43758b31a4..9b11f48911 100644 --- a/thirdparty/openxr/src/loader/api_layer_interface.hpp +++ b/thirdparty/openxr/src/loader/api_layer_interface.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/loader/exception_handling.hpp b/thirdparty/openxr/src/loader/exception_handling.hpp index 62395fdf69..95af9efeb0 100644 --- a/thirdparty/openxr/src/loader/exception_handling.hpp +++ b/thirdparty/openxr/src/loader/exception_handling.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2024, The Khronos Group Inc. +// Copyright (c) 2019-2025 The Khronos Group Inc. // // SPDX-License-Identifier: Apache-2.0 OR MIT // diff --git a/thirdparty/openxr/src/loader/loader_core.cpp b/thirdparty/openxr/src/loader/loader_core.cpp index a0d81b28dc..3adb0ae7ae 100644 --- a/thirdparty/openxr/src/loader/loader_core.cpp +++ b/thirdparty/openxr/src/loader/loader_core.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/loader/loader_init_data.cpp b/thirdparty/openxr/src/loader/loader_init_data.cpp index 3ba6d26713..a10f8c3068 100644 --- a/thirdparty/openxr/src/loader/loader_init_data.cpp +++ b/thirdparty/openxr/src/loader/loader_init_data.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/loader/loader_init_data.hpp b/thirdparty/openxr/src/loader/loader_init_data.hpp index e3a27fc403..d8144e0dc0 100644 --- a/thirdparty/openxr/src/loader/loader_init_data.hpp +++ b/thirdparty/openxr/src/loader/loader_init_data.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/loader/loader_instance.cpp b/thirdparty/openxr/src/loader/loader_instance.cpp index 09521ecf47..163ebc17d8 100644 --- a/thirdparty/openxr/src/loader/loader_instance.cpp +++ b/thirdparty/openxr/src/loader/loader_instance.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/loader/loader_instance.hpp b/thirdparty/openxr/src/loader/loader_instance.hpp index 93cd5dc6a4..14bcdda36d 100644 --- a/thirdparty/openxr/src/loader/loader_instance.hpp +++ b/thirdparty/openxr/src/loader/loader_instance.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/loader/loader_logger.cpp b/thirdparty/openxr/src/loader/loader_logger.cpp index 593e19a3ba..140093fa77 100644 --- a/thirdparty/openxr/src/loader/loader_logger.cpp +++ b/thirdparty/openxr/src/loader/loader_logger.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/loader/loader_logger.hpp b/thirdparty/openxr/src/loader/loader_logger.hpp index 964aa47962..a864a628f3 100644 --- a/thirdparty/openxr/src/loader/loader_logger.hpp +++ b/thirdparty/openxr/src/loader/loader_logger.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/loader/loader_logger_recorders.cpp b/thirdparty/openxr/src/loader/loader_logger_recorders.cpp index 00392c27bd..4c27804eee 100644 --- a/thirdparty/openxr/src/loader/loader_logger_recorders.cpp +++ b/thirdparty/openxr/src/loader/loader_logger_recorders.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/loader/loader_logger_recorders.hpp b/thirdparty/openxr/src/loader/loader_logger_recorders.hpp index b676c37e93..dcfba5969c 100644 --- a/thirdparty/openxr/src/loader/loader_logger_recorders.hpp +++ b/thirdparty/openxr/src/loader/loader_logger_recorders.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/loader/loader_platform.hpp b/thirdparty/openxr/src/loader/loader_platform.hpp index 964116caa4..95e8a79be5 100644 --- a/thirdparty/openxr/src/loader/loader_platform.hpp +++ b/thirdparty/openxr/src/loader/loader_platform.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/loader/manifest_file.cpp b/thirdparty/openxr/src/loader/manifest_file.cpp index ca212d3435..83b468855c 100644 --- a/thirdparty/openxr/src/loader/manifest_file.cpp +++ b/thirdparty/openxr/src/loader/manifest_file.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/loader/manifest_file.hpp b/thirdparty/openxr/src/loader/manifest_file.hpp index 801614ad1e..fd9bc31059 100644 --- a/thirdparty/openxr/src/loader/manifest_file.hpp +++ b/thirdparty/openxr/src/loader/manifest_file.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017 Valve Corporation // Copyright (c) 2017 LunarG, Inc. // diff --git a/thirdparty/openxr/src/loader/runtime_interface.cpp b/thirdparty/openxr/src/loader/runtime_interface.cpp index 32feea6dde..a9091b1382 100644 --- a/thirdparty/openxr/src/loader/runtime_interface.cpp +++ b/thirdparty/openxr/src/loader/runtime_interface.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/loader/runtime_interface.hpp b/thirdparty/openxr/src/loader/runtime_interface.hpp index 3d45b12946..5ce62f7468 100644 --- a/thirdparty/openxr/src/loader/runtime_interface.hpp +++ b/thirdparty/openxr/src/loader/runtime_interface.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/loader/xr_generated_loader.cpp b/thirdparty/openxr/src/loader/xr_generated_loader.cpp index d7f1ed18c1..2dfd3fea28 100644 --- a/thirdparty/openxr/src/loader/xr_generated_loader.cpp +++ b/thirdparty/openxr/src/loader/xr_generated_loader.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // SPDX-License-Identifier: Apache-2.0 OR MIT @@ -6,7 +6,7 @@ // See loader_source_generator.py for modifications // ************************************************************ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/loader/xr_generated_loader.hpp b/thirdparty/openxr/src/loader/xr_generated_loader.hpp index 9a6c915421..9d572930ca 100644 --- a/thirdparty/openxr/src/loader/xr_generated_loader.hpp +++ b/thirdparty/openxr/src/loader/xr_generated_loader.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // SPDX-License-Identifier: Apache-2.0 OR MIT @@ -6,7 +6,7 @@ // See loader_source_generator.py for modifications // ************************************************************ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/xr_generated_dispatch_table_core.c b/thirdparty/openxr/src/xr_generated_dispatch_table_core.c index aaf854704b..64ba49f02c 100644 --- a/thirdparty/openxr/src/xr_generated_dispatch_table_core.c +++ b/thirdparty/openxr/src/xr_generated_dispatch_table_core.c @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019, Valve Corporation // Copyright (c) 2017-2019, LunarG, Inc. @@ -8,7 +8,7 @@ // See utility_source_generator.py for modifications // ************************************************************ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // diff --git a/thirdparty/openxr/src/xr_generated_dispatch_table_core.h b/thirdparty/openxr/src/xr_generated_dispatch_table_core.h index 69abf10b93..cdc4bbb1ef 100644 --- a/thirdparty/openxr/src/xr_generated_dispatch_table_core.h +++ b/thirdparty/openxr/src/xr_generated_dispatch_table_core.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019, Valve Corporation // Copyright (c) 2017-2019, LunarG, Inc. @@ -8,7 +8,7 @@ // See utility_source_generator.py for modifications // ************************************************************ -// Copyright (c) 2017-2024, The Khronos Group Inc. +// Copyright (c) 2017-2025 The Khronos Group Inc. // Copyright (c) 2017-2019 Valve Corporation // Copyright (c) 2017-2019 LunarG, Inc. // From 787d7c8b537f6313b2f16dee714d83f8754d61b1 Mon Sep 17 00:00:00 2001 From: Haoyu Qiu Date: Tue, 20 May 2025 15:10:54 +0800 Subject: [PATCH 017/144] Fix error when closing all scene tabs on the last tab --- editor/gui/editor_scene_tabs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/gui/editor_scene_tabs.h b/editor/gui/editor_scene_tabs.h index 3b23aea7e8..ee8dce75d6 100644 --- a/editor/gui/editor_scene_tabs.h +++ b/editor/gui/editor_scene_tabs.h @@ -47,7 +47,7 @@ class EditorSceneTabs : public MarginContainer { public: enum { - SCENE_SHOW_IN_FILESYSTEM = 3000, // Prevents conflicts with EditorNode options. + SCENE_SHOW_IN_FILESYSTEM = 1000, // Prevents conflicts with EditorNode options. SCENE_RUN, SCENE_CLOSE_OTHERS, SCENE_CLOSE_RIGHT, From 59a75babf88762055166f27ab1ee0d59cac74269 Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Wed, 14 May 2025 01:51:55 +0200 Subject: [PATCH 018/144] Improve documentation for `Array.get()` and `Packed*Array.get()` methods --- doc/classes/Array.xml | 3 ++- doc/classes/PackedByteArray.xml | 3 ++- doc/classes/PackedColorArray.xml | 3 ++- doc/classes/PackedFloat32Array.xml | 3 ++- doc/classes/PackedFloat64Array.xml | 3 ++- doc/classes/PackedInt32Array.xml | 3 ++- doc/classes/PackedInt64Array.xml | 3 ++- doc/classes/PackedStringArray.xml | 3 ++- doc/classes/PackedVector2Array.xml | 3 ++- doc/classes/PackedVector3Array.xml | 3 ++- doc/classes/PackedVector4Array.xml | 3 ++- 11 files changed, 22 insertions(+), 11 deletions(-) diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml index 3dbf34f5a5..edded048eb 100644 --- a/doc/classes/Array.xml +++ b/doc/classes/Array.xml @@ -426,7 +426,8 @@ - Returns the element at the given [param index] in the array. This is the same as using the [code][][/code] operator ([code]array[index][/code]). + Returns the element at the given [param index] in the array. If [param index] out-of-bounds or negative, this method fails and returns [code]null[/code]. + This method is similar (but not identical) to the [code][][/code] operator. Most notably, when this method fails, it doesn't pause project execution if run from the editor. diff --git a/doc/classes/PackedByteArray.xml b/doc/classes/PackedByteArray.xml index 712b84845b..1776577ab0 100644 --- a/doc/classes/PackedByteArray.xml +++ b/doc/classes/PackedByteArray.xml @@ -342,7 +342,8 @@ - Returns the byte at the given [param index] in the array. This is the same as using the [code][][/code] operator ([code]array[index][/code]). + Returns the byte at the given [param index] in the array. If [param index] out-of-bounds or negative, this method fails and returns [code]0[/code]. + This method is similar (but not identical) to the [code][][/code] operator. Most notably, when this method fails, it doesn't pause project execution if run from the editor. diff --git a/doc/classes/PackedColorArray.xml b/doc/classes/PackedColorArray.xml index 7f10e53d72..97a70f12fd 100644 --- a/doc/classes/PackedColorArray.xml +++ b/doc/classes/PackedColorArray.xml @@ -105,7 +105,8 @@ - Returns the [Color] at the given [param index] in the array. This is the same as using the [code][][/code] operator ([code]array[index][/code]). + Returns the [Color] at the given [param index] in the array. If [param index] out-of-bounds or negative, this method fails and returns [code]Color(0, 0, 0, 1)[/code]. + This method is similar (but not identical) to the [code][][/code] operator. Most notably, when this method fails, it doesn't pause project execution if run from the editor. diff --git a/doc/classes/PackedFloat32Array.xml b/doc/classes/PackedFloat32Array.xml index 07467762a4..1997ecf5f8 100644 --- a/doc/classes/PackedFloat32Array.xml +++ b/doc/classes/PackedFloat32Array.xml @@ -105,7 +105,8 @@ - Returns the 32-bit float at the given [param index] in the array. This is the same as using the [code][][/code] operator ([code]array[index][/code]). + Returns the 32-bit float at the given [param index] in the array. If [param index] out-of-bounds or negative, this method fails and returns [code]0.0[/code]. + This method is similar (but not identical) to the [code][][/code] operator. Most notably, when this method fails, it doesn't pause project execution if run from the editor. diff --git a/doc/classes/PackedFloat64Array.xml b/doc/classes/PackedFloat64Array.xml index 7471ee44c1..b325df4734 100644 --- a/doc/classes/PackedFloat64Array.xml +++ b/doc/classes/PackedFloat64Array.xml @@ -106,7 +106,8 @@ - Returns the 64-bit float at the given [param index] in the array. This is the same as using the [code][][/code] operator ([code]array[index][/code]). + Returns the 64-bit float at the given [param index] in the array. If [param index] out-of-bounds or negative, this method fails and returns [code]0.0[/code]. + This method is similar (but not identical) to the [code][][/code] operator. Most notably, when this method fails, it doesn't pause project execution if run from the editor. diff --git a/doc/classes/PackedInt32Array.xml b/doc/classes/PackedInt32Array.xml index 9d13b9de00..e230bd08bf 100644 --- a/doc/classes/PackedInt32Array.xml +++ b/doc/classes/PackedInt32Array.xml @@ -101,7 +101,8 @@ - Returns the 32-bit integer at the given [param index] in the array. This is the same as using the [code][][/code] operator ([code]array[index][/code]). + Returns the 32-bit integer at the given [param index] in the array. If [param index] out-of-bounds or negative, this method fails and returns [code]0[/code]. + This method is similar (but not identical) to the [code][][/code] operator. Most notably, when this method fails, it doesn't pause project execution if run from the editor. diff --git a/doc/classes/PackedInt64Array.xml b/doc/classes/PackedInt64Array.xml index 7992dff165..094dbf5419 100644 --- a/doc/classes/PackedInt64Array.xml +++ b/doc/classes/PackedInt64Array.xml @@ -102,7 +102,8 @@ - Returns the 64-bit integer at the given [param index] in the array. This is the same as using the [code][][/code] operator ([code]array[index][/code]). + Returns the 64-bit integer at the given [param index] in the array. If [param index] out-of-bounds or negative, this method fails and returns [code]0[/code]. + This method is similar (but not identical) to the [code][][/code] operator. Most notably, when this method fails, it doesn't pause project execution if run from the editor. diff --git a/doc/classes/PackedStringArray.xml b/doc/classes/PackedStringArray.xml index d583ecc80c..1bd79b33e4 100644 --- a/doc/classes/PackedStringArray.xml +++ b/doc/classes/PackedStringArray.xml @@ -108,7 +108,8 @@ - Returns the [String] at the given [param index] in the array. This is the same as using the [code][][/code] operator ([code]array[index][/code]). + Returns the [String] at the given [param index] in the array. Returns an empty string and prints an error if the access is out of bounds. Negative indices are not supported; they will always consider the value to be out of bounds and return an empty string. + This is similar to using the [code][][/code] operator ([code]array[index][/code]), except that operator supports negative indices and causes a debugger break if out-of-bounds access is performed. diff --git a/doc/classes/PackedVector2Array.xml b/doc/classes/PackedVector2Array.xml index 93adcbf930..133011ee41 100644 --- a/doc/classes/PackedVector2Array.xml +++ b/doc/classes/PackedVector2Array.xml @@ -110,7 +110,8 @@ - Returns the [Vector2] at the given [param index] in the array. This is the same as using the [code][][/code] operator ([code]array[index][/code]). + Returns the [Vector2] at the given [param index] in the array. If [param index] out-of-bounds or negative, this method fails and returns [code]Vector2(0, 0)[/code]. + This method is similar (but not identical) to the [code][][/code] operator. Most notably, when this method fails, it doesn't pause project execution if run from the editor. diff --git a/doc/classes/PackedVector3Array.xml b/doc/classes/PackedVector3Array.xml index be524078bb..87161e813f 100644 --- a/doc/classes/PackedVector3Array.xml +++ b/doc/classes/PackedVector3Array.xml @@ -109,7 +109,8 @@ - Returns the [Vector3] at the given [param index] in the array. This is the same as using the [code][][/code] operator ([code]array[index][/code]). + Returns the [Vector3] at the given [param index] in the array. If [param index] out-of-bounds or negative, this method fails and returns [code]Vector3(0, 0, 0)[/code]. + This method is similar (but not identical) to the [code][][/code] operator. Most notably, when this method fails, it doesn't pause project execution if run from the editor. diff --git a/doc/classes/PackedVector4Array.xml b/doc/classes/PackedVector4Array.xml index 8859b87bf9..30203ffe1a 100644 --- a/doc/classes/PackedVector4Array.xml +++ b/doc/classes/PackedVector4Array.xml @@ -109,7 +109,8 @@ - Returns the [Vector4] at the given [param index] in the array. This is the same as using the [code][][/code] operator ([code]array[index][/code]). + Returns the [Vector4] at the given [param index] in the array. If [param index] out-of-bounds or negative, this method fails and returns [code]Vector4(0, 0, 0, 0)[/code]. + This method is similar (but not identical) to the [code][][/code] operator. Most notably, when this method fails, it doesn't pause project execution if run from the editor. From 7aafa6ef181c29d16dc3252cddff880964cb538b Mon Sep 17 00:00:00 2001 From: Danil Alexeev Date: Wed, 21 May 2025 18:16:20 +0300 Subject: [PATCH 019/144] GDScript: Remove `leftmost_column` and `rightmost_column` fields --- core/object/script_language.h | 1 - core/object/script_language_extension.h | 4 -- modules/gdscript/gdscript_compiler.cpp | 2 +- modules/gdscript/gdscript_editor.cpp | 2 - modules/gdscript/gdscript_parser.cpp | 18 ++----- modules/gdscript/gdscript_parser.h | 14 +---- modules/gdscript/gdscript_tokenizer.cpp | 51 ------------------- modules/gdscript/gdscript_tokenizer.h | 2 - modules/gdscript/gdscript_warning.h | 1 - .../gdscript_extend_parser.cpp | 8 +-- modules/gdscript/tests/test_gdscript.cpp | 38 ++++++++++---- 11 files changed, 37 insertions(+), 104 deletions(-) diff --git a/core/object/script_language.h b/core/object/script_language.h index 4e519f405e..10b07c9c3d 100644 --- a/core/object/script_language.h +++ b/core/object/script_language.h @@ -214,7 +214,6 @@ public: /* EDITOR FUNCTIONS */ struct Warning { int start_line = -1, end_line = -1; - int leftmost_column = -1, rightmost_column = -1; int code; String string_code; String message; diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h index e605cccc7c..f9167fc307 100644 --- a/core/object/script_language_extension.h +++ b/core/object/script_language_extension.h @@ -347,8 +347,6 @@ public: Dictionary warn = warning; ERR_CONTINUE(!warn.has("start_line")); ERR_CONTINUE(!warn.has("end_line")); - ERR_CONTINUE(!warn.has("leftmost_column")); - ERR_CONTINUE(!warn.has("rightmost_column")); ERR_CONTINUE(!warn.has("code")); ERR_CONTINUE(!warn.has("string_code")); ERR_CONTINUE(!warn.has("message")); @@ -356,8 +354,6 @@ public: Warning swarn; swarn.start_line = warn["start_line"]; swarn.end_line = warn["end_line"]; - swarn.leftmost_column = warn["leftmost_column"]; - swarn.rightmost_column = warn["rightmost_column"]; swarn.code = warn["code"]; swarn.string_code = warn["string_code"]; swarn.message = warn["message"]; diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 2e6fe46f8e..327adc382a 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -79,7 +79,7 @@ void GDScriptCompiler::_set_error(const String &p_error, const GDScriptParser::N error = p_error; if (p_node) { err_line = p_node->start_line; - err_column = p_node->leftmost_column; + err_column = p_node->start_column; } else { err_line = 0; err_column = 0; diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 29885526af..c5c09c61ae 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -144,8 +144,6 @@ bool GDScriptLanguage::validate(const String &p_script, const String &p_path, Li ScriptLanguage::Warning w; w.start_line = warn.start_line; w.end_line = warn.end_line; - w.leftmost_column = warn.leftmost_column; - w.rightmost_column = warn.rightmost_column; w.code = (int)warn.code; w.string_code = GDScriptWarning::get_name_from_code(warn.code); w.message = warn.get_message(); diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index a225d2fa6f..adddc29a5e 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -184,7 +184,7 @@ void GDScriptParser::push_error(const String &p_message, const Node *p_origin) { if (p_origin == nullptr) { errors.push_back({ p_message, previous.start_line, previous.start_column }); } else { - errors.push_back({ p_message, p_origin->start_line, p_origin->leftmost_column }); + errors.push_back({ p_message, p_origin->start_line, p_origin->start_column }); } } @@ -227,8 +227,6 @@ void GDScriptParser::apply_pending_warnings() { warning.symbols = pw.symbols; warning.start_line = pw.source->start_line; warning.end_line = pw.source->end_line; - warning.leftmost_column = pw.source->leftmost_column; - warning.rightmost_column = pw.source->rightmost_column; if (pw.treated_as_error) { push_error(warning.get_message() + String(" (Warning treated as error.)"), pw.source); @@ -412,8 +410,6 @@ Error GDScriptParser::parse(const String &p_source_code, const String &p_script_ nd->start_line = 1; nd->start_column = 0; nd->end_line = 1; - nd->leftmost_column = 0; - nd->rightmost_column = 0; push_warning(nd, GDScriptWarning::EMPTY_FILE); } #endif @@ -761,8 +757,6 @@ void GDScriptParser::parse_program() { head->end_line = current.end_line; head->end_column = current.end_column; - head->leftmost_column = MIN(head->leftmost_column, current.leftmost_column); - head->rightmost_column = MAX(head->rightmost_column, current.rightmost_column); complete_extents(head); @@ -1550,8 +1544,8 @@ GDScriptParser::EnumNode *GDScriptParser::parse_enum(bool p_is_abstract, bool p_ item.identifier = identifier; item.parent_enum = enum_node; item.line = previous.start_line; - item.leftmost_column = previous.leftmost_column; - item.rightmost_column = previous.rightmost_column; + item.start_column = previous.start_column; + item.end_column = previous.end_column; if (elements.has(item.identifier->name)) { push_error(vformat(R"(Name "%s" was already in this enum (at line %d).)", item.identifier->name, elements[item.identifier->name]), item.identifier); @@ -5463,8 +5457,6 @@ void GDScriptParser::complete_extents(Node *p_node) { void GDScriptParser::update_extents(Node *p_node) { p_node->end_line = previous.end_line; p_node->end_column = previous.end_column; - p_node->leftmost_column = MIN(p_node->leftmost_column, previous.leftmost_column); - p_node->rightmost_column = MAX(p_node->rightmost_column, previous.rightmost_column); } void GDScriptParser::reset_extents(Node *p_node, GDScriptTokenizer::Token p_token) { @@ -5472,8 +5464,6 @@ void GDScriptParser::reset_extents(Node *p_node, GDScriptTokenizer::Token p_toke p_node->end_line = p_token.end_line; p_node->start_column = p_token.start_column; p_node->end_column = p_token.end_column; - p_node->leftmost_column = p_token.leftmost_column; - p_node->rightmost_column = p_token.rightmost_column; } void GDScriptParser::reset_extents(Node *p_node, Node *p_from) { @@ -5484,8 +5474,6 @@ void GDScriptParser::reset_extents(Node *p_node, Node *p_from) { p_node->end_line = p_from->end_line; p_node->start_column = p_from->start_column; p_node->end_column = p_from->end_column; - p_node->leftmost_column = p_from->leftmost_column; - p_node->rightmost_column = p_from->rightmost_column; } /*---------- PRETTY PRINT FOR DEBUG ----------*/ diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index ee246c762a..d3ffa7d27a 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -339,7 +339,6 @@ public: Type type = NONE; int start_line = 0, end_line = 0; int start_column = 0, end_column = 0; - int leftmost_column = 0, rightmost_column = 0; Node *next = nullptr; List annotations; @@ -536,8 +535,8 @@ public: bool resolved = false; int64_t value = 0; int line = 0; - int leftmost_column = 0; - int rightmost_column = 0; + int start_column = 0; + int end_column = 0; #ifdef TOOLS_ENABLED MemberDocData doc_data; #endif // TOOLS_ENABLED @@ -1105,7 +1104,6 @@ public: int start_line = 0, end_line = 0; int start_column = 0, end_column = 0; - int leftmost_column = 0, rightmost_column = 0; DataType get_datatype() const; String get_name() const; @@ -1121,8 +1119,6 @@ public: end_line = p_constant->end_line; start_column = p_constant->start_column; end_column = p_constant->end_column; - leftmost_column = p_constant->leftmost_column; - rightmost_column = p_constant->rightmost_column; } Local(VariableNode *p_variable, FunctionNode *p_source_function) { type = VARIABLE; @@ -1134,8 +1130,6 @@ public: end_line = p_variable->end_line; start_column = p_variable->start_column; end_column = p_variable->end_column; - leftmost_column = p_variable->leftmost_column; - rightmost_column = p_variable->rightmost_column; } Local(ParameterNode *p_parameter, FunctionNode *p_source_function) { type = PARAMETER; @@ -1147,8 +1141,6 @@ public: end_line = p_parameter->end_line; start_column = p_parameter->start_column; end_column = p_parameter->end_column; - leftmost_column = p_parameter->leftmost_column; - rightmost_column = p_parameter->rightmost_column; } Local(IdentifierNode *p_identifier, FunctionNode *p_source_function) { type = FOR_VARIABLE; @@ -1160,8 +1152,6 @@ public: end_line = p_identifier->end_line; start_column = p_identifier->start_column; end_column = p_identifier->end_column; - leftmost_column = p_identifier->leftmost_column; - rightmost_column = p_identifier->rightmost_column; } }; Local empty; diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index 93a06b2b76..71c6133bdc 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -329,9 +329,6 @@ char32_t GDScriptTokenizerText::_advance() { _current++; column++; position++; - if (column > rightmost_column) { - rightmost_column = column; - } if (unlikely(_is_at_end())) { // Add extra newline even if it's not there, to satisfy the parser. newline(true); @@ -367,8 +364,6 @@ GDScriptTokenizer::Token GDScriptTokenizerText::make_token(Token::Type p_type) { token.end_line = line; token.start_column = start_column; token.end_column = column; - token.leftmost_column = leftmost_column; - token.rightmost_column = rightmost_column; token.source = String::utf32(Span(_start, _current - _start)); if (p_type != Token::ERROR && cursor_line > -1) { @@ -671,8 +666,6 @@ void GDScriptTokenizerText::newline(bool p_make_token) { newline.end_line = line; newline.start_column = column - 1; newline.end_column = column; - newline.leftmost_column = newline.start_column; - newline.rightmost_column = newline.end_column; pending_newline = true; last_token = newline; last_newline = newline; @@ -681,7 +674,6 @@ void GDScriptTokenizerText::newline(bool p_make_token) { // Increment line/column counters. line++; column = 1; - leftmost_column = 1; } GDScriptTokenizer::Token GDScriptTokenizerText::number() { @@ -718,9 +710,7 @@ GDScriptTokenizer::Token GDScriptTokenizerText::number() { if (base != 10 && is_underscore(_peek())) { // Disallow `0x_` and `0b_`. Token error = make_error(vformat(R"(Unexpected underscore after "0%c".)", _peek(-1))); error.start_column = column; - error.leftmost_column = column; error.end_column = column + 1; - error.rightmost_column = column + 1; push_error(error); has_error = true; } @@ -730,9 +720,7 @@ GDScriptTokenizer::Token GDScriptTokenizerText::number() { if (previous_was_underscore) { Token error = make_error(R"(Multiple underscores cannot be adjacent in a numeric literal.)"); error.start_column = column; - error.leftmost_column = column; error.end_column = column + 1; - error.rightmost_column = column + 1; push_error(error); } previous_was_underscore = true; @@ -750,25 +738,19 @@ GDScriptTokenizer::Token GDScriptTokenizerText::number() { } else if (base == 10) { Token error = make_error("Cannot use a decimal point twice in a number."); error.start_column = column; - error.leftmost_column = column; error.end_column = column + 1; - error.rightmost_column = column + 1; push_error(error); has_error = true; } else if (base == 16) { Token error = make_error("Cannot use a decimal point in a hexadecimal number."); error.start_column = column; - error.leftmost_column = column; error.end_column = column + 1; - error.rightmost_column = column + 1; push_error(error); has_error = true; } else { Token error = make_error("Cannot use a decimal point in a binary number."); error.start_column = column; - error.leftmost_column = column; error.end_column = column + 1; - error.rightmost_column = column + 1; push_error(error); has_error = true; } @@ -779,9 +761,7 @@ GDScriptTokenizer::Token GDScriptTokenizerText::number() { if (is_underscore(_peek())) { // Disallow `10._`, but allow `10.`. Token error = make_error(R"(Unexpected underscore after decimal point.)"); error.start_column = column; - error.leftmost_column = column; error.end_column = column + 1; - error.rightmost_column = column + 1; push_error(error); has_error = true; } @@ -791,9 +771,7 @@ GDScriptTokenizer::Token GDScriptTokenizerText::number() { if (previous_was_underscore) { Token error = make_error(R"(Multiple underscores cannot be adjacent in a numeric literal.)"); error.start_column = column; - error.leftmost_column = column; error.end_column = column + 1; - error.rightmost_column = column + 1; push_error(error); } previous_was_underscore = true; @@ -816,9 +794,7 @@ GDScriptTokenizer::Token GDScriptTokenizerText::number() { if (!is_digit(_peek())) { Token error = make_error(R"(Expected exponent value after "e".)"); error.start_column = column; - error.leftmost_column = column; error.end_column = column + 1; - error.rightmost_column = column + 1; push_error(error); } previous_was_underscore = false; @@ -827,9 +803,7 @@ GDScriptTokenizer::Token GDScriptTokenizerText::number() { if (previous_was_underscore) { Token error = make_error(R"(Multiple underscores cannot be adjacent in a numeric literal.)"); error.start_column = column; - error.leftmost_column = column; error.end_column = column + 1; - error.rightmost_column = column + 1; push_error(error); } previous_was_underscore = true; @@ -845,9 +819,7 @@ GDScriptTokenizer::Token GDScriptTokenizerText::number() { // No digits in hex or bin literal. Token error = make_error(vformat(R"(Expected %s digit after "0%c".)", (base == 16 ? "hexadecimal" : "binary"), (base == 16 ? 'x' : 'b'))); error.start_column = column; - error.leftmost_column = column; error.end_column = column + 1; - error.rightmost_column = column + 1; return error; } @@ -855,9 +827,7 @@ GDScriptTokenizer::Token GDScriptTokenizerText::number() { if (!has_error && has_decimal && _peek() == '.' && _peek(1) != '.') { Token error = make_error("Cannot use a decimal point twice in a number."); error.start_column = column; - error.leftmost_column = column; error.end_column = column + 1; - error.rightmost_column = column + 1; push_error(error); has_error = true; } else if (is_unicode_identifier_start(_peek()) || is_unicode_identifier_continue(_peek())) { @@ -936,9 +906,7 @@ GDScriptTokenizer::Token GDScriptTokenizerText::string() { error = make_error("Invisible text direction control character present in the string, escape it (\"\\u" + String::num_int64(ch, 16) + "\") to avoid confusion."); } error.start_column = column; - error.leftmost_column = error.start_column; error.end_column = column + 1; - error.rightmost_column = error.end_column; push_error(error); } @@ -1032,9 +1000,7 @@ GDScriptTokenizer::Token GDScriptTokenizerText::string() { // Make error, but keep parsing the string. Token error = make_error("Invalid hexadecimal digit in unicode escape sequence."); error.start_column = column; - error.leftmost_column = error.start_column; error.end_column = column + 1; - error.rightmost_column = error.end_column; push_error(error); valid_escape = false; break; @@ -1063,7 +1029,6 @@ GDScriptTokenizer::Token GDScriptTokenizerText::string() { default: Token error = make_error("Invalid escape in string."); error.start_column = column - 2; - error.leftmost_column = error.start_column; push_error(error); valid_escape = false; break; @@ -1078,7 +1043,6 @@ GDScriptTokenizer::Token GDScriptTokenizerText::string() { } else { Token error = make_error("Invalid UTF-16 sequence in string, unpaired lead surrogate."); error.start_column = column - 2; - error.leftmost_column = error.start_column; push_error(error); valid_escape = false; prev = 0; @@ -1087,7 +1051,6 @@ GDScriptTokenizer::Token GDScriptTokenizerText::string() { if (prev == 0) { Token error = make_error("Invalid UTF-16 sequence in string, unpaired trail surrogate."); error.start_column = column - 2; - error.leftmost_column = error.start_column; push_error(error); valid_escape = false; } else { @@ -1098,7 +1061,6 @@ GDScriptTokenizer::Token GDScriptTokenizerText::string() { if (prev != 0) { Token error = make_error("Invalid UTF-16 sequence in string, unpaired lead surrogate."); error.start_column = prev_pos; - error.leftmost_column = error.start_column; push_error(error); prev = 0; } @@ -1112,7 +1074,6 @@ GDScriptTokenizer::Token GDScriptTokenizerText::string() { if (prev != 0) { Token error = make_error("Invalid UTF-16 sequence in string, unpaired lead surrogate"); error.start_column = prev_pos; - error.leftmost_column = error.start_column; push_error(error); prev = 0; } @@ -1135,7 +1096,6 @@ GDScriptTokenizer::Token GDScriptTokenizerText::string() { if (prev != 0) { Token error = make_error("Invalid UTF-16 sequence in string, unpaired lead surrogate"); error.start_column = prev_pos; - error.leftmost_column = error.start_column; push_error(error); prev = 0; } @@ -1149,7 +1109,6 @@ GDScriptTokenizer::Token GDScriptTokenizerText::string() { if (prev != 0) { Token error = make_error("Invalid UTF-16 sequence in string, unpaired lead surrogate"); error.start_column = prev_pos; - error.leftmost_column = error.start_column; push_error(error); prev = 0; } @@ -1273,8 +1232,6 @@ void GDScriptTokenizerText::check_indent() { Token error = make_error("Mixed use of tabs and spaces for indentation."); error.start_line = line; error.start_column = 1; - error.leftmost_column = 1; - error.rightmost_column = column; push_error(error); } @@ -1293,8 +1250,6 @@ void GDScriptTokenizerText::check_indent() { _get_indent_char_name(current_indent_char), _get_indent_char_name(indent_char))); error.start_line = line; error.start_column = 1; - error.leftmost_column = 1; - error.rightmost_column = column; push_error(error); } @@ -1328,9 +1283,7 @@ void GDScriptTokenizerText::check_indent() { Token error = make_error("Unindent doesn't match the previous indentation level."); error.start_line = line; error.start_column = 1; - error.leftmost_column = 1; error.end_column = column + 1; - error.rightmost_column = column + 1; push_error(error); // Still, we'll be lenient and keep going, so keep this level in the stack. indent_stack.push_back(indent_count); @@ -1431,14 +1384,11 @@ GDScriptTokenizer::Token GDScriptTokenizerText::scan() { _start = _current; start_line = line; start_column = column; - leftmost_column = column; - rightmost_column = column; if (pending_indents != 0) { // Adjust position for indent. _start -= start_column - 1; start_column = 1; - leftmost_column = 1; if (pending_indents > 0) { // Indents. pending_indents--; @@ -1448,7 +1398,6 @@ GDScriptTokenizer::Token GDScriptTokenizerText::scan() { pending_indents++; Token dedent = make_token(Token::DEDENT); dedent.end_column += 1; - dedent.rightmost_column += 1; return dedent; } } diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h index cfaa2aae05..94313edcdf 100644 --- a/modules/gdscript/gdscript_tokenizer.h +++ b/modules/gdscript/gdscript_tokenizer.h @@ -165,7 +165,6 @@ public: Type type = EMPTY; Variant literal; int start_line = 0, end_line = 0, start_column = 0, end_column = 0; - int leftmost_column = 0, rightmost_column = 0; // Column span for multiline tokens. int cursor_position = -1; CursorPlace cursor_place = CURSOR_NONE; String source; @@ -226,7 +225,6 @@ class GDScriptTokenizerText : public GDScriptTokenizer { // Keep track of multichar tokens. const char32_t *_start = nullptr; int start_line = 0, start_column = 0; - int leftmost_column = 0, rightmost_column = 0; // Info cache. bool line_continuation = false; // Whether this line is a continuation of the previous, like when using '\'. diff --git a/modules/gdscript/gdscript_warning.h b/modules/gdscript/gdscript_warning.h index e86cd3b596..5f47e120fa 100644 --- a/modules/gdscript/gdscript_warning.h +++ b/modules/gdscript/gdscript_warning.h @@ -157,7 +157,6 @@ public: Code code = WARNING_MAX; int start_line = -1, end_line = -1; - int leftmost_column = -1, rightmost_column = -1; Vector symbols; String get_name() const; diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp index f8df46b256..ed095a946b 100644 --- a/modules/gdscript/language_server/gdscript_extend_parser.cpp +++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp @@ -403,8 +403,8 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p symbol.name = m.enum_value.identifier->name; symbol.kind = LSP::SymbolKind::EnumMember; symbol.deprecated = false; - symbol.range.start = GodotPosition(m.enum_value.line, m.enum_value.leftmost_column).to_lsp(lines); - symbol.range.end = GodotPosition(m.enum_value.line, m.enum_value.rightmost_column).to_lsp(lines); + symbol.range.start = GodotPosition(m.enum_value.line, m.enum_value.start_column).to_lsp(lines); + symbol.range.end = GodotPosition(m.enum_value.line, m.enum_value.end_column).to_lsp(lines); symbol.selectionRange = range_of_node(m.enum_value.identifier); symbol.documentation = m.enum_value.doc_data.description; symbol.uri = uri; @@ -439,8 +439,8 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p child.name = value.identifier->name; child.kind = LSP::SymbolKind::EnumMember; child.deprecated = false; - child.range.start = GodotPosition(value.line, value.leftmost_column).to_lsp(lines); - child.range.end = GodotPosition(value.line, value.rightmost_column).to_lsp(lines); + child.range.start = GodotPosition(value.line, value.start_column).to_lsp(lines); + child.range.end = GodotPosition(value.line, value.end_column).to_lsp(lines); child.selectionRange = range_of_node(value.identifier); child.documentation = value.doc_data.description; child.uri = uri; diff --git a/modules/gdscript/tests/test_gdscript.cpp b/modules/gdscript/tests/test_gdscript.cpp index aca1ed5a5f..fe838919e0 100644 --- a/modules/gdscript/tests/test_gdscript.cpp +++ b/modules/gdscript/tests/test_gdscript.cpp @@ -64,25 +64,41 @@ static void test_tokenizer(const String &p_code, const Vector &p_lines) StringBuilder token; token += " --> "; // Padding for line number. + if (current.start_line != current.end_line) { + // Print "vvvvvv" to point at the token. + StringBuilder pointer; + pointer += " "; // Padding for line number. + + int line_width = 0; + if (current.start_line - 1 >= 0 && current.start_line - 1 < p_lines.size()) { + line_width = p_lines[current.start_line - 1].replace("\t", tab).length(); + } + + const int offset = MAX(0, current.start_column - 1); + const int width = MAX(0, line_width - current.start_column + 1); + pointer += String::chr(' ').repeat(offset) + String::chr('v').repeat(width); + + print_line(pointer.as_string()); + } + for (int l = current.start_line; l <= current.end_line && l <= p_lines.size(); l++) { print_line(vformat("%04d %s", l, p_lines[l - 1]).replace("\t", tab)); } { - // Print carets to point at the token. + // Print "^^^^^^" to point at the token. StringBuilder pointer; pointer += " "; // Padding for line number. - int rightmost_column = current.rightmost_column; - if (current.end_line > current.start_line) { - rightmost_column--; // Don't point to the newline as a column. - } - for (int col = 1; col < rightmost_column; col++) { - if (col < current.leftmost_column) { - pointer += " "; - } else { - pointer += "^"; - } + + if (current.start_line == current.end_line) { + const int offset = MAX(0, current.start_column - 1); + const int width = MAX(0, current.end_column - current.start_column); + pointer += String::chr(' ').repeat(offset) + String::chr('^').repeat(width); + } else { + const int width = MAX(0, current.end_column - 1); + pointer += String::chr('^').repeat(width); } + print_line(pointer.as_string()); } From 9222341575befc76c5763e7c0ce61d9329e963ae Mon Sep 17 00:00:00 2001 From: BrotherShort <129957860+BrotherShort@users.noreply.github.com> Date: Mon, 12 May 2025 01:53:45 +0800 Subject: [PATCH 020/144] Fix FileSystemTree rename TextEdit is offset --- scene/gui/tree.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index ee6001ccdf..3b6d818912 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -2358,7 +2358,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 } } - if ((select_mode == SELECT_ROW && selected_item == p_item) || p_item->cells[i].selected || !p_item->has_meta("__focus_rect")) { + if ((select_mode != SELECT_SINGLE && selected_item == p_item) || p_item->cells[i].selected || !p_item->has_meta("__focus_rect")) { Rect2i r = cell_rect; if (select_mode != SELECT_ROW) { From f6e26d01d507871752d280daf5cc2c840f696de8 Mon Sep 17 00:00:00 2001 From: HolonProduction Date: Fri, 23 May 2025 13:58:01 +0200 Subject: [PATCH 021/144] GUI: Use `TabContainer` material for internal `TabBar` --- scene/gui/tab_container.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index c93420ee40..a83a61d166 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -1167,6 +1167,7 @@ TabContainer::TabContainer() { tab_bar = memnew(TabBar); SET_DRAG_FORWARDING_GCDU(tab_bar, TabContainer); add_child(tab_bar, false, INTERNAL_MODE_FRONT); + tab_bar->set_use_parent_material(true); tab_bar->set_anchors_and_offsets_preset(Control::PRESET_TOP_WIDE); tab_bar->connect("tab_changed", callable_mp(this, &TabContainer::_on_tab_changed)); tab_bar->connect("tab_clicked", callable_mp(this, &TabContainer::_on_tab_clicked)); From d0f99ec3d3c379ea05b6e26162ebdb72d0e12cff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Sun, 25 May 2025 14:06:57 +0200 Subject: [PATCH 022/144] TileSet: Fix potential crash updating stale atlas source editor toolbar --- editor/plugins/tiles/tile_set_atlas_source_editor.cpp | 7 +++++-- editor/plugins/tiles/tile_set_atlas_source_editor.h | 1 - 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp index 419cc35d7b..c8612f15e3 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp @@ -894,10 +894,9 @@ void TileSetAtlasSourceEditor::_update_current_tile_data_editor() { // Get the correct editor for the TileData's property. if (current_tile_data_editor) { - current_tile_data_editor_toolbar = current_tile_data_editor->get_toolbar(); current_property = property; current_tile_data_editor->set_visible(tools_button_group->get_pressed_button() == tool_paint_button); - current_tile_data_editor_toolbar->set_visible(tools_button_group->get_pressed_button() == tool_paint_button); + current_tile_data_editor->get_toolbar()->set_visible(tools_button_group->get_pressed_button() == tool_paint_button); } } @@ -1031,6 +1030,10 @@ void TileSetAtlasSourceEditor::_update_atlas_view() { void TileSetAtlasSourceEditor::_update_toolbar() { // Show the tools and settings. + Control *current_tile_data_editor_toolbar = nullptr; + if (current_tile_data_editor) { + current_tile_data_editor_toolbar = current_tile_data_editor->get_toolbar(); + } if (tools_button_group->get_pressed_button() == tool_setup_atlas_source_button) { if (current_tile_data_editor_toolbar) { current_tile_data_editor_toolbar->hide(); diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.h b/editor/plugins/tiles/tile_set_atlas_source_editor.h index bb0c5e0470..2407e287b4 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.h +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.h @@ -142,7 +142,6 @@ private: // -- Tile data editors -- String current_property; - Control *current_tile_data_editor_toolbar = nullptr; HashMap tile_data_editors; TileDataEditor *current_tile_data_editor = nullptr; void _tile_data_editors_tree_selected(); From 528a0a551b9344e25a34f6718662f341fec6f6df Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Sun, 25 May 2025 12:30:42 -0700 Subject: [PATCH 023/144] GLTF: Don't export AnimationPlayer nodes as glTF nodes --- modules/gltf/gltf_document.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 8b3bf8f6af..6e6cd8ca81 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -5962,6 +5962,9 @@ void GLTFDocument::_convert_scene_node(Ref p_state, Node *p_current, } else if (Object::cast_to(p_current)) { AnimationPlayer *animation_player = Object::cast_to(p_current); p_state->animation_players.push_back(animation_player); + if (animation_player->get_child_count() == 0) { + gltf_node->set_parent(-2); // Don't export AnimationPlayer nodes as glTF nodes (unless they have children). + } } for (Ref ext : document_extensions) { ERR_CONTINUE(ext.is_null()); From 8152ecabeddf911398ba919f190ef5352316313d Mon Sep 17 00:00:00 2001 From: Lorenzo Zimmmerer Date: Tue, 30 Apr 2024 21:41:01 -0400 Subject: [PATCH 024/144] Editing SceneTree.get_frame() documentaion to reflect that it returns physics steps that have been processed, not frames rendered. fixes #90539 Add reference to physics_frame signal. Add reference to Engine.get_process_frames Update doc/classes/SceneTree.xml Co-authored-by: A Thousand Ships <96648715+AThousandShips@users.noreply.github.com> --- doc/classes/SceneTree.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml index f5d5da3d47..93aae50bba 100644 --- a/doc/classes/SceneTree.xml +++ b/doc/classes/SceneTree.xml @@ -109,7 +109,7 @@ - Returns how many frames have been processed, since the application started. This is [i]not[/i] a measurement of elapsed time. + Returns how many physics process steps have been processed, since the application started. This is [i]not[/i] a measurement of elapsed time. See also [signal physics_frame]. For the number of frames rendered, see [method Engine.get_process_frames]. From f03943f37b7d00387871ec231fefd042070669cb Mon Sep 17 00:00:00 2001 From: Marwen Azouzi Date: Thu, 22 May 2025 22:10:16 +0200 Subject: [PATCH 025/144] [Web] Keep virtual keyboard visible when `keep_editing_on_text_submit` is enabled --- scene/gui/line_edit.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 1fa6d73a20..9b87015992 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -873,13 +873,13 @@ void LineEdit::gui_input(const Ref &p_event) { // Default is ENTER and KP_ENTER. Cannot use ui_accept as default includes SPACE. if (k->is_action_pressed("ui_text_submit")) { emit_signal(SceneStringName(text_submitted), text); - if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD) && virtual_keyboard_enabled) { - DisplayServer::get_singleton()->virtual_keyboard_hide(); - } if (editing && !keep_editing_on_text_submit) { unedit(); emit_signal(SNAME("editing_toggled"), false); + if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD) && virtual_keyboard_enabled) { + DisplayServer::get_singleton()->virtual_keyboard_hide(); + } } accept_event(); From 0fd0feb77208f9cf52d60e4f9740739c04cc57fb Mon Sep 17 00:00:00 2001 From: David Snopek Date: Thu, 20 Feb 2025 15:15:19 -0600 Subject: [PATCH 026/144] Minor rendering and XR changes to allow Meta enivornment depth API to work entirely from GDExtension --- modules/openxr/openxr_api.cpp | 8 ++++---- .../renderer_rd/storage_rd/texture_storage.cpp | 16 ++++++++++++++++ servers/rendering/renderer_viewport.cpp | 3 --- servers/rendering/rendering_server_default.cpp | 10 +++++++++- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp index 0af4bbd0a9..51a12e772c 100644 --- a/modules/openxr/openxr_api.cpp +++ b/modules/openxr/openxr_api.cpp @@ -2261,10 +2261,6 @@ void OpenXRAPI::pre_render() { create_main_swapchains(swapchain_size); } - for (OpenXRExtensionWrapper *wrapper : registered_extension_wrappers) { - wrapper->on_pre_render(); - } - void *view_locate_info_next_pointer = nullptr; for (OpenXRExtensionWrapper *extension : frame_info_extensions) { void *np = extension->set_view_locate_info_and_get_next_pointer(view_locate_info_next_pointer); @@ -2335,6 +2331,10 @@ void OpenXRAPI::pre_render() { // Reset this, we haven't found a viewport for output yet render_state.has_xr_viewport = false; + + for (OpenXRExtensionWrapper *wrapper : registered_extension_wrappers) { + wrapper->on_pre_render(); + } } bool OpenXRAPI::pre_draw_viewport(RID p_render_target) { diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index f01edd2d2d..4520ec8bb9 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -2655,6 +2655,22 @@ void TextureStorage::_texture_format_from_rd(RD::DataFormat p_rd_format, Texture r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; } break; // astc 8x8 + case RD::DATA_FORMAT_D16_UNORM: { + r_format.image_format = Image::FORMAT_RH; + r_format.rd_format = RD::DATA_FORMAT_D16_UNORM; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case RD::DATA_FORMAT_D32_SFLOAT: { + r_format.image_format = Image::FORMAT_RF; + r_format.rd_format = RD::DATA_FORMAT_D32_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; default: { ERR_FAIL_MSG("Unsupported image format"); diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index d84dced9e1..f55ff85926 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -732,9 +732,6 @@ void RendererViewport::draw_viewports(bool p_swap_buffers) { Ref xr_interface; XRServer *xr_server = XRServer::get_singleton(); if (xr_server != nullptr) { - // let our XR server know we're about to render our frames so we can get our frame timing - xr_server->pre_render(); - // retrieve the interface responsible for rendering xr_interface = xr_server->get_primary_interface(); } diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp index 3a381401a2..09c532aa0b 100644 --- a/servers/rendering/rendering_server_default.cpp +++ b/servers/rendering/rendering_server_default.cpp @@ -73,6 +73,15 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) { uint64_t time_usec = OS::get_singleton()->get_ticks_usec(); RENDER_TIMESTAMP("Prepare Render Frame"); + +#ifndef XR_DISABLED + XRServer *xr_server = XRServer::get_singleton(); + if (xr_server != nullptr) { + // Let XR server know we're about to render a frame. + xr_server->pre_render(); + } +#endif // XR_DISABLED + RSG::scene->update(); //update scenes stuff before updating instances RSG::canvas->update(); @@ -88,7 +97,6 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) { RSG::rasterizer->end_frame(p_swap_buffers); #ifndef XR_DISABLED - XRServer *xr_server = XRServer::get_singleton(); if (xr_server != nullptr) { // let our XR server know we're done so we can get our frame timing xr_server->end_frame(); From c2eba05312319a48b99428f44ae9aa9b66c8bfcc Mon Sep 17 00:00:00 2001 From: 2750558108 Date: Tue, 27 May 2025 20:40:42 +0800 Subject: [PATCH 027/144] Add speed scale feature for VideoStreamPlayer node --- doc/classes/VideoStreamPlayer.xml | 3 +++ scene/gui/video_stream_player.cpp | 17 +++++++++++++++-- scene/gui/video_stream_player.h | 4 ++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/doc/classes/VideoStreamPlayer.xml b/doc/classes/VideoStreamPlayer.xml index 46bc4f491d..01bcca3590 100644 --- a/doc/classes/VideoStreamPlayer.xml +++ b/doc/classes/VideoStreamPlayer.xml @@ -73,6 +73,9 @@ If [code]true[/code], the video is paused. + + The stream's current speed scale. [code]1.0[/code] is the normal speed, while [code]2.0[/code] is double speed and [code]0.5[/code] is half speed. A speed scale of [code]0.0[/code] pauses the video, similar to setting [member paused] to [code]true[/code]. + The assigned video stream. See description for supported formats. diff --git a/scene/gui/video_stream_player.cpp b/scene/gui/video_stream_player.cpp index 2249690c6c..e4359817e3 100644 --- a/scene/gui/video_stream_player.cpp +++ b/scene/gui/video_stream_player.cpp @@ -157,9 +157,9 @@ void VideoStreamPlayer::_notification(int p_notification) { double delta = first_frame ? 0 : get_process_delta_time(); first_frame = false; - resampler.set_playback_speed(Engine::get_singleton()->get_time_scale()); + resampler.set_playback_speed(Engine::get_singleton()->get_time_scale() * speed_scale); - playback->update(delta); // playback->is_playing() returns false in the last video frame + playback->update(delta * speed_scale); // playback->is_playing() returns false in the last video frame if (!playback->is_playing()) { resampler.flush(); @@ -433,6 +433,15 @@ float VideoStreamPlayer::get_volume_db() const { } } +void VideoStreamPlayer::set_speed_scale(float p_speed_scale) { + ERR_FAIL_COND(p_speed_scale < 0.0); + speed_scale = p_speed_scale; +} + +float VideoStreamPlayer::get_speed_scale() const { + return speed_scale; +} + String VideoStreamPlayer::get_stream_name() const { if (stream.is_null()) { return ""; @@ -530,6 +539,9 @@ void VideoStreamPlayer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_volume_db", "db"), &VideoStreamPlayer::set_volume_db); ClassDB::bind_method(D_METHOD("get_volume_db"), &VideoStreamPlayer::get_volume_db); + ClassDB::bind_method(D_METHOD("set_speed_scale", "speed_scale"), &VideoStreamPlayer::set_speed_scale); + ClassDB::bind_method(D_METHOD("get_speed_scale"), &VideoStreamPlayer::get_speed_scale); + ClassDB::bind_method(D_METHOD("set_audio_track", "track"), &VideoStreamPlayer::set_audio_track); ClassDB::bind_method(D_METHOD("get_audio_track"), &VideoStreamPlayer::get_audio_track); @@ -559,6 +571,7 @@ void VideoStreamPlayer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "VideoStream"), "set_stream", "get_stream"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volume_db", PROPERTY_HINT_RANGE, "-80,24,0.01,suffix:dB"), "set_volume_db", "get_volume_db"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volume", PROPERTY_HINT_RANGE, "0,15,0.01,exp", PROPERTY_USAGE_NONE), "set_volume", "get_volume"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed_scale", PROPERTY_HINT_RANGE, "0,4,0.001,or_greater"), "set_speed_scale", "get_speed_scale"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "has_autoplay"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused"), "set_paused", "is_paused"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand"), "set_expand", "has_expand"); diff --git a/scene/gui/video_stream_player.h b/scene/gui/video_stream_player.h index 0a80d8ca3b..94c74481dc 100644 --- a/scene/gui/video_stream_player.h +++ b/scene/gui/video_stream_player.h @@ -63,6 +63,7 @@ class VideoStreamPlayer : public Control { bool paused_from_tree = false; bool autoplay = false; float volume = 1.0; + float speed_scale = 1.0; bool expand = false; bool loop = false; bool first_frame = false; @@ -107,6 +108,9 @@ public: void set_volume_db(float p_db); float get_volume_db() const; + void set_speed_scale(float p_speed_scale); + float get_speed_scale() const; + String get_stream_name() const; double get_stream_length() const; double get_stream_position() const; From 34152b3f39dbadbad90eb9c5d1f63832abff8086 Mon Sep 17 00:00:00 2001 From: kobewi Date: Wed, 28 May 2025 15:24:49 +0200 Subject: [PATCH 028/144] Remove redundant data.inside_tree --- scene/main/node.cpp | 92 ++++++++++++++++++++++----------------------- scene/main/node.h | 7 ++-- 2 files changed, 47 insertions(+), 52 deletions(-) diff --git a/scene/main/node.cpp b/scene/main/node.cpp index fc7589a176..9544d08a47 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -135,15 +135,15 @@ void Node::_notification(int p_notification) { case NOTIFICATION_ENTER_TREE: { ERR_FAIL_NULL(get_viewport()); - ERR_FAIL_NULL(get_tree()); + ERR_FAIL_NULL(data.tree); - if (get_tree()->is_accessibility_supported() && !is_part_of_edited_scene()) { - get_tree()->_accessibility_force_update(); - get_tree()->_accessibility_notify_change(this); + if (data.tree->is_accessibility_supported() && !is_part_of_edited_scene()) { + data.tree->_accessibility_force_update(); + data.tree->_accessibility_notify_change(this); if (data.parent) { - get_tree()->_accessibility_notify_change(data.parent); + data.tree->_accessibility_notify_change(data.parent); } else { - get_tree()->_accessibility_notify_change(get_window()); // Root node. + data.tree->_accessibility_notify_change(get_window()); // Root node. } } @@ -210,7 +210,7 @@ void Node::_notification(int p_notification) { add_to_group("_vp_unhandled_key_input" + itos(get_viewport()->get_instance_id())); } - get_tree()->nodes_in_tree_count++; + data.tree->nodes_in_tree_count++; orphan_node_count--; } break; @@ -223,22 +223,22 @@ void Node::_notification(int p_notification) { case NOTIFICATION_EXIT_TREE: { ERR_FAIL_NULL(get_viewport()); - ERR_FAIL_NULL(get_tree()); + ERR_FAIL_NULL(data.tree); - if (get_tree()->is_accessibility_supported() && !is_part_of_edited_scene()) { + if (data.tree->is_accessibility_supported() && !is_part_of_edited_scene()) { if (data.accessibility_element.is_valid()) { DisplayServer::get_singleton()->accessibility_free_element(data.accessibility_element); data.accessibility_element = RID(); } - get_tree()->_accessibility_notify_change(this, true); + data.tree->_accessibility_notify_change(this, true); if (data.parent) { - get_tree()->_accessibility_notify_change(data.parent); + data.tree->_accessibility_notify_change(data.parent); } else { - get_tree()->_accessibility_notify_change(get_window()); // Root node. + data.tree->_accessibility_notify_change(get_window()); // Root node. } } - get_tree()->nodes_in_tree_count--; + data.tree->nodes_in_tree_count--; orphan_node_count++; if (data.input) { @@ -313,7 +313,7 @@ void Node::_notification(int p_notification) { } break; case NOTIFICATION_PREDELETE: { - if (data.inside_tree && !Thread::is_main_thread()) { + if (data.tree && !Thread::is_main_thread()) { cancel_free(); ERR_PRINT("Attempted to free a node that is currently added to the SceneTree from a thread. This is not permitted, use queue_free() instead. Node has not been freed."); return; @@ -340,7 +340,7 @@ void Node::_notification(int p_notification) { } break; case NOTIFICATION_TRANSLATION_CHANGED: { - if (data.inside_tree) { + if (data.tree) { data.is_auto_translate_dirty = true; } } break; @@ -380,8 +380,6 @@ void Node::_propagate_enter_tree() { data.viewport = data.parent->data.viewport; } - data.inside_tree = true; - for (KeyValue &E : data.grouped) { E.value.group = data.tree->add_to_group(E.key, this); } @@ -480,7 +478,6 @@ void Node::_propagate_exit_tree() { data.tree->tree_changed(); } - data.inside_tree = false; data.ready_notified = false; data.tree = nullptr; data.depth = -1; @@ -531,7 +528,7 @@ void Node::_propagate_physics_interpolation_reset_requested(bool p_requested) { } void Node::move_child(Node *p_child, int p_index) { - ERR_FAIL_COND_MSG(data.inside_tree && !Thread::is_main_thread(), "Moving child node positions inside the SceneTree is only allowed from the main thread. Use call_deferred(\"move_child\",child,index)."); + ERR_FAIL_COND_MSG(data.tree && !Thread::is_main_thread(), "Moving child node positions inside the SceneTree is only allowed from the main thread. Use call_deferred(\"move_child\",child,index)."); ERR_FAIL_NULL(p_child); ERR_FAIL_COND_MSG(p_child->data.parent != this, "Child is not a child of this node."); @@ -747,7 +744,7 @@ void Node::set_process_mode(ProcessMode p_mode) { // This is required for the editor to update the visibility of disabled nodes // It's very expensive during runtime to change, so editor-only if (Engine::get_singleton()->is_editor_hint()) { - get_tree()->emit_signal(SNAME("tree_process_mode_changed")); + data.tree->emit_signal(SNAME("tree_process_mode_changed")); } _emit_editor_state_changed(); @@ -914,7 +911,7 @@ Ref Node::get_multiplayer() const { if (!is_inside_tree()) { return Ref(); } - return get_tree()->get_multiplayer(get_path()); + return data.tree->get_multiplayer(get_path()); } //////////// end of rpc @@ -936,7 +933,7 @@ bool Node::can_process_notification(int p_what) const { bool Node::can_process() const { ERR_FAIL_COND_V(!is_inside_tree(), false); - return !get_tree()->is_suspended() && _can_process(get_tree()->is_paused()); + return !data.tree->is_suspended() && _can_process(data.tree->is_paused()); } bool Node::_can_process(bool p_paused) const { @@ -1098,19 +1095,19 @@ void Node::set_process_internal(bool p_process_internal) { } void Node::_add_process_group() { - get_tree()->_add_process_group(this); + data.tree->_add_process_group(this); } void Node::_remove_process_group() { - get_tree()->_remove_process_group(this); + data.tree->_remove_process_group(this); } void Node::_remove_from_process_thread_group() { - get_tree()->_remove_node_from_process_group(this, data.process_thread_group_owner); + data.tree->_remove_node_from_process_group(this, data.process_thread_group_owner); } void Node::_add_to_process_thread_group() { - get_tree()->_add_node_to_process_group(this, data.process_thread_group_owner); + data.tree->_add_node_to_process_group(this, data.process_thread_group_owner); } void Node::_remove_tree_from_process_thread_group() { @@ -1168,7 +1165,7 @@ void Node::set_process_thread_group_order(int p_order) { return; } - get_tree()->process_groups_dirty = true; + data.tree->process_groups_dirty = true; } int Node::get_process_thread_group_order() const { @@ -1228,7 +1225,7 @@ int Node::get_physics_process_priority() const { } void Node::set_process_thread_group(ProcessThreadGroup p_mode) { - ERR_FAIL_COND_MSG(data.inside_tree && !Thread::is_main_thread(), "Changing the process thread group can only be done from the main thread. Use call_deferred(\"set_process_thread_group\",mode)."); + ERR_FAIL_COND_MSG(data.tree && !Thread::is_main_thread(), "Changing the process thread group can only be done from the main thread. Use call_deferred(\"set_process_thread_group\",mode)."); if (data.process_thread_group == p_mode) { return; } @@ -1370,7 +1367,7 @@ void Node::set_auto_translate_mode(AutoTranslateMode p_mode) { return; } - if (p_mode == AUTO_TRANSLATE_MODE_INHERIT && data.inside_tree && !data.parent) { + if (p_mode == AUTO_TRANSLATE_MODE_INHERIT && data.tree && !data.parent) { ERR_FAIL_MSG("The root node can't be set to Inherit auto translate mode."); } @@ -1549,7 +1546,7 @@ void Node::_set_name_nocheck(const StringName &p_name) { } void Node::set_name(const StringName &p_name) { - ERR_FAIL_COND_MSG(data.inside_tree && !Thread::is_main_thread(), "Changing the name to nodes inside the SceneTree is only allowed from the main thread. Use `set_name.call_deferred(new_name)`."); + ERR_FAIL_COND_MSG(data.tree && !Thread::is_main_thread(), "Changing the name to nodes inside the SceneTree is only allowed from the main thread. Use `set_name.call_deferred(new_name)`."); const StringName old_name = data.name; { const String input_name_str = String(p_name); @@ -1580,8 +1577,8 @@ void Node::set_name(const StringName &p_name) { if (is_inside_tree()) { emit_signal(SNAME("renamed")); - get_tree()->node_renamed(this); - get_tree()->tree_changed(); + data.tree->node_renamed(this); + data.tree->tree_changed(); } } @@ -1810,7 +1807,7 @@ void Node::_add_child_nocheck(Node *p_child, const StringName &p_name, InternalM } void Node::add_child(Node *p_child, bool p_force_readable_name, InternalMode p_internal) { - ERR_FAIL_COND_MSG(data.inside_tree && !Thread::is_main_thread(), "Adding children to a node inside the SceneTree is only allowed from the main thread. Use call_deferred(\"add_child\",node)."); + ERR_FAIL_COND_MSG(data.tree && !Thread::is_main_thread(), "Adding children to a node inside the SceneTree is only allowed from the main thread. Use call_deferred(\"add_child\",node)."); ERR_THREAD_GUARD ERR_FAIL_NULL(p_child); @@ -1834,7 +1831,7 @@ void Node::add_child(Node *p_child, bool p_force_readable_name, InternalMode p_i } void Node::add_sibling(Node *p_sibling, bool p_force_readable_name) { - ERR_FAIL_COND_MSG(data.inside_tree && !Thread::is_main_thread(), "Adding a sibling to a node inside the SceneTree is only allowed from the main thread. Use call_deferred(\"add_sibling\",node)."); + ERR_FAIL_COND_MSG(data.tree && !Thread::is_main_thread(), "Adding a sibling to a node inside the SceneTree is only allowed from the main thread. Use call_deferred(\"add_sibling\",node)."); ERR_FAIL_NULL(p_sibling); ERR_FAIL_COND_MSG(p_sibling == this, vformat("Can't add sibling '%s' to itself.", p_sibling->get_name())); // adding to itself! ERR_FAIL_NULL(data.parent); @@ -1846,7 +1843,7 @@ void Node::add_sibling(Node *p_sibling, bool p_force_readable_name) { } void Node::remove_child(Node *p_child) { - ERR_FAIL_COND_MSG(data.inside_tree && !Thread::is_main_thread(), "Removing children from a node inside the SceneTree is only allowed from the main thread. Use call_deferred(\"remove_child\",node)."); + ERR_FAIL_COND_MSG(data.tree && !Thread::is_main_thread(), "Removing children from a node inside the SceneTree is only allowed from the main thread. Use call_deferred(\"remove_child\",node)."); ERR_FAIL_NULL(p_child); ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy adding/removing children, `remove_child()` can't be called at this time. Consider using `remove_child.call_deferred(child)` instead."); ERR_FAIL_COND(p_child->data.parent != this); @@ -1879,7 +1876,7 @@ void Node::remove_child(Node *p_child) { notification(NOTIFICATION_CHILD_ORDER_CHANGED); emit_signal(SNAME("child_order_changed")); - if (data.inside_tree) { + if (data.tree) { p_child->_propagate_after_exit_tree(); } } @@ -1972,7 +1969,7 @@ Node *Node::get_node_or_null(const NodePath &p_path) const { return nullptr; } - ERR_FAIL_COND_V_MSG(!data.inside_tree && p_path.is_absolute(), nullptr, "Can't use get_node() with absolute paths from outside the active scene tree."); + ERR_FAIL_COND_V_MSG(!data.tree && p_path.is_absolute(), nullptr, "Can't use get_node() with absolute paths from outside the active scene tree."); Node *current = nullptr; Node *root = nullptr; @@ -2212,8 +2209,8 @@ bool Node::is_ancestor_of(const Node *p_node) const { bool Node::is_greater_than(const Node *p_node) const { ERR_FAIL_NULL_V(p_node, false); - ERR_FAIL_COND_V(!data.inside_tree, false); - ERR_FAIL_COND_V(!p_node->data.inside_tree, false); + ERR_FAIL_COND_V(!data.tree, false); + ERR_FAIL_COND_V(!p_node->data.tree, false); ERR_FAIL_COND_V(data.depth < 0, false); ERR_FAIL_COND_V(p_node->data.depth < 0, false); @@ -2830,8 +2827,8 @@ StringName Node::get_property_store_alias(const StringName &p_property) const { } bool Node::is_part_of_edited_scene() const { - return Engine::get_singleton()->is_editor_hint() && is_inside_tree() && get_tree()->get_edited_scene_root() && - get_tree()->get_edited_scene_root()->get_parent()->is_ancestor_of(this); + return Engine::get_singleton()->is_editor_hint() && is_inside_tree() && data.tree->get_edited_scene_root() && + data.tree->get_edited_scene_root()->get_parent()->is_ancestor_of(this); } #endif @@ -3536,8 +3533,8 @@ TypedArray Node::get_orphan_node_ids() { void Node::queue_free() { // There are users which instantiate multiple scene trees for their games. // Use the node's own tree to handle its deletion when relevant. - if (is_inside_tree()) { - get_tree()->queue_delete(this); + if (data.tree) { + data.tree->queue_delete(this); } else { SceneTree *tree = SceneTree::get_singleton(); ERR_FAIL_NULL_MSG(tree, "Can't queue free a node when no SceneTree is available."); @@ -3623,11 +3620,11 @@ PackedStringArray Node::get_configuration_warnings() const { void Node::update_configuration_warnings() { ERR_THREAD_GUARD #ifdef TOOLS_ENABLED - if (!is_inside_tree()) { + if (!data.tree) { return; } - if (get_tree()->get_edited_scene_root() && (get_tree()->get_edited_scene_root() == this || get_tree()->get_edited_scene_root()->is_ancestor_of(this))) { - get_tree()->emit_signal(SceneStringName(node_configuration_warning_changed), this); + if (data.tree->get_edited_scene_root() && (data.tree->get_edited_scene_root() == this || data.tree->get_edited_scene_root()->is_ancestor_of(this))) { + data.tree->emit_signal(SceneStringName(node_configuration_warning_changed), this); } #endif } @@ -3820,7 +3817,7 @@ String Node::get_accessibility_container_name(const Node *p_node) const { void Node::queue_accessibility_update() { if (is_inside_tree() && !is_part_of_edited_scene()) { - get_tree()->_accessibility_notify_change(this); + data.tree->_accessibility_notify_change(this); } } @@ -4226,7 +4223,6 @@ Node::Node() { data.display_folded = false; data.editable_instance = false; - data.inside_tree = false; data.ready_notified = false; // This is a small hack, so if a node is added during _ready() to the tree, it correctly gets the _ready() notification. data.ready_first = true; } diff --git a/scene/main/node.h b/scene/main/node.h index f83f7f89a2..e77b628a29 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -256,7 +256,6 @@ private: bool display_folded : 1; bool editable_instance : 1; - bool inside_tree : 1; bool ready_notified : 1; bool ready_first : 1; @@ -517,7 +516,7 @@ public: return data.tree; } - _FORCE_INLINE_ bool is_inside_tree() const { return data.inside_tree; } + _FORCE_INLINE_ bool is_inside_tree() const { return data.tree; } bool is_internal() const { return data.internal_mode != INTERNAL_MODE_DISABLED; } bool is_ancestor_of(const Node *p_node) const; @@ -655,7 +654,7 @@ public: // No thread processing. // Only accessible if node is outside the scene tree // or access will happen from a node-safe thread. - return !data.inside_tree || is_current_thread_safe_for_nodes(); + return !data.tree || is_current_thread_safe_for_nodes(); } else { // Thread processing. return current_process_thread_group == data.process_thread_group_owner; @@ -667,7 +666,7 @@ public: // No thread processing. // Only accessible if node is outside the scene tree // or access will happen from a node-safe thread. - return is_current_thread_safe_for_nodes() || unlikely(!data.inside_tree); + return is_current_thread_safe_for_nodes() || unlikely(!data.tree); } else { // Thread processing. return true; From 8cdb1768a4f78331c299a49206543958f764a2b9 Mon Sep 17 00:00:00 2001 From: KaiN Date: Thu, 17 Apr 2025 19:37:55 +0200 Subject: [PATCH 029/144] Add EditorInterface::close_scene() Co-authored-by: Tomasz Chabora --- doc/classes/EditorInterface.xml | 6 ++++++ editor/editor_interface.cpp | 5 +++++ editor/editor_interface.h | 1 + editor/editor_node.cpp | 13 +++++++++++++ editor/editor_node.h | 2 ++ 5 files changed, 27 insertions(+) diff --git a/doc/classes/EditorInterface.xml b/doc/classes/EditorInterface.xml index 26828882bf..2d547d522e 100644 --- a/doc/classes/EditorInterface.xml +++ b/doc/classes/EditorInterface.xml @@ -19,6 +19,12 @@ + + + + Closes the currently active scene, discarding any pending changes in the process. Returns [constant OK] on success or [constant ERR_DOES_NOT_EXIST] if there is no scene to close. + + diff --git a/editor/editor_interface.cpp b/editor/editor_interface.cpp index 013a59cffe..082b0ed3c9 100644 --- a/editor/editor_interface.cpp +++ b/editor/editor_interface.cpp @@ -713,6 +713,10 @@ void EditorInterface::save_all_scenes() { EditorNode::get_singleton()->save_all_scenes(); } +Error EditorInterface::close_scene() { + return EditorNode::get_singleton()->close_scene() ? OK : ERR_DOES_NOT_EXIST; +} + // Scene playback. void EditorInterface::play_main_scene() { @@ -845,6 +849,7 @@ void EditorInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("save_scene"), &EditorInterface::save_scene); ClassDB::bind_method(D_METHOD("save_scene_as", "path", "with_preview"), &EditorInterface::save_scene_as, DEFVAL(true)); ClassDB::bind_method(D_METHOD("save_all_scenes"), &EditorInterface::save_all_scenes); + ClassDB::bind_method(D_METHOD("close_scene"), &EditorInterface::close_scene); ClassDB::bind_method(D_METHOD("mark_scene_as_unsaved"), &EditorInterface::mark_scene_as_unsaved); diff --git a/editor/editor_interface.h b/editor/editor_interface.h index 5bf3ab4852..3b95eb0e7d 100644 --- a/editor/editor_interface.h +++ b/editor/editor_interface.h @@ -177,6 +177,7 @@ public: void save_scene_as(const String &p_scene, bool p_with_preview = true); void mark_scene_as_unsaved(); void save_all_scenes(); + Error close_scene(); // Scene playback. diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 8049547815..9d65bc8f18 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -4974,6 +4974,19 @@ bool EditorNode::_find_scene_in_use(Node *p_node, const String &p_path) const { return false; } +bool EditorNode::close_scene() { + int tab_index = editor_data.get_edited_scene(); + if (tab_index == 0 && get_edited_scene() == nullptr && editor_data.get_scene_path(tab_index).is_empty()) { + return false; + } + + tab_closing_idx = tab_index; + current_menu_option = SCENE_CLOSE; + _discard_changes(); + changing_scene = false; + return true; +} + bool EditorNode::is_scene_in_use(const String &p_path) { Node *es = get_edited_scene(); if (es) { diff --git a/editor/editor_node.h b/editor/editor_node.h index 163075d0d2..58571f1a66 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -943,6 +943,8 @@ public: } } + bool close_scene(); + bool is_scene_in_use(const String &p_path); void save_editor_layout_delayed(); From df70765af0b32299f9df155e485a503b9c410168 Mon Sep 17 00:00:00 2001 From: kobewi Date: Wed, 28 May 2025 23:24:27 +0200 Subject: [PATCH 030/144] Fix SCROLL_MODE_RESERVE with RTL layout --- scene/gui/scroll_container.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index aebd79cf7e..94261318c9 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -364,12 +364,13 @@ void ScrollContainer::_reposition_children() { } bool rtl = is_layout_rtl(); + bool reserve_vscroll = _is_v_scroll_visible() || vertical_scroll_mode == SCROLL_MODE_RESERVE; if (_is_h_scroll_visible() || horizontal_scroll_mode == SCROLL_MODE_RESERVE) { size.y -= h_scroll->get_minimum_size().y; } - if (_is_v_scroll_visible() || vertical_scroll_mode == SCROLL_MODE_RESERVE) { + if (reserve_vscroll) { size.x -= v_scroll->get_minimum_size().x; } @@ -391,7 +392,7 @@ void ScrollContainer::_reposition_children() { r.size.height = MAX(size.height, minsize.height); } r.position += ofs; - if (rtl && _is_v_scroll_visible()) { + if (rtl && reserve_vscroll) { r.position.x += v_scroll->get_minimum_size().x; } r.position = r.position.floor(); From 7762f70f6909d583b615e6bb92d6c8787b98abcf Mon Sep 17 00:00:00 2001 From: KOGA Mitsuhiro Date: Thu, 29 May 2025 07:24:00 +0900 Subject: [PATCH 031/144] Update CameraFeed document for Android --- doc/classes/CameraFeed.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/classes/CameraFeed.xml b/doc/classes/CameraFeed.xml index f3e5630971..00aea9a195 100644 --- a/doc/classes/CameraFeed.xml +++ b/doc/classes/CameraFeed.xml @@ -6,7 +6,7 @@ A camera feed gives you access to a single physical camera attached to your device. When enabled, Godot will start capturing frames from the camera which can then be used. See also [CameraServer]. [b]Note:[/b] Many cameras will return YCbCr images which are split into two textures and need to be combined in a shader. Godot does this automatically for you if you set the environment to show the camera image in the background. - [b]Note:[/b] This class is currently only implemented on Linux, macOS, and iOS. On other platforms no [CameraFeed]s will be available. To get a [CameraFeed] on iOS, the camera plugin from [url=https://github.com/godotengine/godot-ios-plugins]godot-ios-plugins[/url] is required. + [b]Note:[/b] This class is currently only implemented on Linux, Android, macOS, and iOS. On other platforms no [CameraFeed]s will be available. To get a [CameraFeed] on iOS, the camera plugin from [url=https://github.com/godotengine/godot-ios-plugins]godot-ios-plugins[/url] is required. From 5f2eb6de8cf7361d2b8c4d73e781b82c57caaf8a Mon Sep 17 00:00:00 2001 From: Mike Owens Date: Wed, 28 May 2025 19:37:02 -0400 Subject: [PATCH 032/144] Shader Baker: Build when `deprecated=no` Shader Baker was using the unadorned `VERSION_NUMBER` and `VERSION_HASH` symbols, which are no longer defined when `deprecated=no` is set. --- editor/plugins/shader_baker_export_plugin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/editor/plugins/shader_baker_export_plugin.cpp b/editor/plugins/shader_baker_export_plugin.cpp index d9b3e81f6a..95f9959096 100644 --- a/editor/plugins/shader_baker_export_plugin.cpp +++ b/editor/plugins/shader_baker_export_plugin.cpp @@ -111,9 +111,9 @@ bool ShaderBakerExportPlugin::_begin_customize_resources(const Ref Date: Thu, 29 May 2025 03:11:10 +0200 Subject: [PATCH 033/144] Clamp FontFile Face Index to a valid range in the inspector Previously, you could set it to an invalid value in the inspector, which caused an error to be printed by TextServerAdvanced. --- scene/resources/font.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index de460832e0..5e8cc4dc9f 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -1359,7 +1359,7 @@ void FontFile::_get_property_list(List *p_list) const { String prefix = "cache/" + itos(i) + "/"; TypedArray sizes = get_size_cache_list(i); p_list->push_back(PropertyInfo(Variant::DICTIONARY, prefix + "variation_coordinates", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); - p_list->push_back(PropertyInfo(Variant::INT, prefix + "face_index", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); + p_list->push_back(PropertyInfo(Variant::INT, prefix + "face_index", PROPERTY_HINT_RANGE, "0,32767,1", PROPERTY_USAGE_STORAGE)); p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + "embolden", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); p_list->push_back(PropertyInfo(Variant::TRANSFORM2D, prefix + "transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); p_list->push_back(PropertyInfo(Variant::INT, prefix + "spacing_top", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); @@ -2849,7 +2849,7 @@ void FontVariation::_bind_methods() { ADD_GROUP("Variation", "variation_"); ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "variation_opentype"), "set_variation_opentype", "get_variation_opentype"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "variation_face_index"), "set_variation_face_index", "get_variation_face_index"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "variation_face_index", PROPERTY_HINT_RANGE, "0,32767,1"), "set_variation_face_index", "get_variation_face_index"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "variation_embolden", PROPERTY_HINT_RANGE, "-2,2,0.01"), "set_variation_embolden", "get_variation_embolden"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "variation_transform", PROPERTY_HINT_NONE, "suffix:px"), "set_variation_transform", "get_variation_transform"); From 06ebcc911dc78eab4b7608ef4e8c7dfcbe9f7047 Mon Sep 17 00:00:00 2001 From: Stuart Carnie Date: Thu, 29 May 2025 11:30:26 +1000 Subject: [PATCH 034/144] Metal: Fix multi-view support Introduced in #102552 --- servers/rendering/rendering_device_commons.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/servers/rendering/rendering_device_commons.cpp b/servers/rendering/rendering_device_commons.cpp index 4892d14cff..7e6dcddb84 100644 --- a/servers/rendering/rendering_device_commons.cpp +++ b/servers/rendering/rendering_device_commons.cpp @@ -1210,7 +1210,7 @@ Error RenderingDeviceCommons::reflect_spirv(VectorView p_s } } - if (stage == SHADER_STAGE_VERTEX) { + if (stage == SHADER_STAGE_VERTEX || stage == SHADER_STAGE_FRAGMENT) { uint32_t iv_count = 0; result = spvReflectEnumerateInputVariables(&module, &iv_count, nullptr); ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED, @@ -1228,10 +1228,12 @@ Error RenderingDeviceCommons::reflect_spirv(VectorView p_s if (!v) { continue; } - if (v->decoration_flags == 0) { // Regular input. - r_reflection.vertex_input_mask |= (((uint64_t)1) << v->location); + if (stage == SHADER_STAGE_VERTEX) { + if (v->decoration_flags == 0) { // Regular input. + r_reflection.vertex_input_mask |= (((uint64_t)1) << v->location); + } } - if (v->built_in == SpvBuiltInViewIndex || v->built_in == SpvBuiltInViewportIndex) { + if (v->built_in == SpvBuiltInViewIndex) { r_reflection.has_multiview = true; } } @@ -1259,9 +1261,6 @@ Error RenderingDeviceCommons::reflect_spirv(VectorView p_s if (refvar->built_in != SpvBuiltInFragDepth) { r_reflection.fragment_output_mask |= 1 << refvar->location; } - if (refvar->built_in == SpvBuiltInViewIndex || refvar->built_in == SpvBuiltInViewportIndex) { - r_reflection.has_multiview = true; - } } } } From 8171720fe02094e7388c40264495e856fdee9a3f Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Tue, 11 Mar 2025 18:12:57 +0100 Subject: [PATCH 035/144] Add Paste as Unique option to the editor resource picker dropdown This is equivalent to using Paste, then immediately using Make Unique afterwards. This saves time when pasting a resource that you know will need to be unique. --- editor/editor_resource_picker.cpp | 19 ++++++++++++++----- editor/editor_resource_picker.h | 1 + 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp index 70d00b2df8..86bfab0b6d 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -290,6 +290,7 @@ void EditorResourcePicker::_update_menu_items() { if (paste_valid) { edit_menu->add_item(TTR("Paste"), OBJ_MENU_PASTE); + edit_menu->add_item(TTRC("Paste as Unique"), OBJ_MENU_PASTE_AS_UNIQUE); } } @@ -439,12 +440,20 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) { EditorSettings::get_singleton()->set_resource_clipboard(edited_resource); } break; - case OBJ_MENU_PASTE: { + case OBJ_MENU_PASTE: + case OBJ_MENU_PASTE_AS_UNIQUE: { edited_resource = EditorSettings::get_singleton()->get_resource_clipboard(); - if (edited_resource->is_built_in() && EditorNode::get_singleton()->get_edited_scene() && - edited_resource->get_path().get_slice("::", 0) != EditorNode::get_singleton()->get_edited_scene()->get_scene_file_path()) { - // Automatically make resource unique if it belongs to another scene. - _edit_menu_cbk(OBJ_MENU_MAKE_UNIQUE); + if (p_which == OBJ_MENU_PASTE_AS_UNIQUE || + (EditorNode::get_singleton()->get_edited_scene() && edited_resource->is_built_in() && edited_resource->get_path().get_slice("::", 0) != EditorNode::get_singleton()->get_edited_scene()->get_scene_file_path())) { + // Automatically make resource unique if it belongs to another scene, + // or if requested by the user with the Paste as Unique option. + if (p_which == OBJ_MENU_PASTE_AS_UNIQUE) { + // Use the recursive version when using Paste as Unique. + // This will show up a dialog to select which resources to make unique. + _edit_menu_cbk(OBJ_MENU_MAKE_UNIQUE_RECURSIVE); + } else { + _edit_menu_cbk(OBJ_MENU_MAKE_UNIQUE); + } return; } _resource_changed(); diff --git a/editor/editor_resource_picker.h b/editor/editor_resource_picker.h index 29c30f7164..856d04503c 100644 --- a/editor/editor_resource_picker.h +++ b/editor/editor_resource_picker.h @@ -75,6 +75,7 @@ class EditorResourcePicker : public HBoxContainer { OBJ_MENU_SAVE_AS, OBJ_MENU_COPY, OBJ_MENU_PASTE, + OBJ_MENU_PASTE_AS_UNIQUE, OBJ_MENU_SHOW_IN_FILE_SYSTEM, TYPE_BASE_ID = 100, From 8b2dda868b9038ddf2cee2ffb9e6d044c50e82c4 Mon Sep 17 00:00:00 2001 From: clayjohn Date: Wed, 28 May 2025 22:11:20 -0700 Subject: [PATCH 036/144] Correctly place viewport and use viewport relative rect for the final blit in Compatibility renderer --- drivers/gles3/rasterizer_gles3.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index d3bc531e1b..4bdcdd49cd 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -431,9 +431,9 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display Vector2 p2 = Vector2(flip_x ? p_screen_rect.position.x : screen_rect_end.x, flip_y ? p_screen_rect.position.y : screen_rect_end.y); Vector2 size = p2 - p1; - Rect2 screenrect = Rect2(p1 / p_screen_rect.size, (size) / p_screen_rect.size); + Rect2 screenrect = Rect2(Vector2(flip_x ? 1.0 : 0.0, flip_y ? 1.0 : 0.0), Vector2(flip_x ? -1.0 : 1.0, flip_y ? -1.0 : 1.0)); - glViewport(0, 0, Math::abs(size.x), Math::abs(size.y)); + glViewport(int(MIN(p1.x, p2.x)), int(MIN(p1.y, p2.y)), Math::abs(size.x), Math::abs(size.y)); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, rt->color); From f75c564d5883107b98366b20bf7a177afbd75603 Mon Sep 17 00:00:00 2001 From: kobewi Date: Wed, 23 Apr 2025 00:11:36 +0200 Subject: [PATCH 037/144] Add favorites and recent directories to FileDialog --- doc/classes/FileDialog.xml | 9 + scene/gui/file_dialog.cpp | 328 +++++++++++++++++++++++++++++++- scene/gui/file_dialog.h | 26 +++ scene/theme/default_theme.cpp | 3 + scene/theme/icons/favorite.svg | 1 + scene/theme/icons/move_down.svg | 1 + scene/theme/icons/move_up.svg | 1 + 7 files changed, 362 insertions(+), 7 deletions(-) create mode 100644 scene/theme/icons/favorite.svg create mode 100644 scene/theme/icons/move_down.svg create mode 100644 scene/theme/icons/move_up.svg diff --git a/doc/classes/FileDialog.xml b/doc/classes/FileDialog.xml index 4f2c61a2a1..7989b35706 100644 --- a/doc/classes/FileDialog.xml +++ b/doc/classes/FileDialog.xml @@ -240,6 +240,15 @@ Custom icon for the create folder button. + + Custom icon for favorite folder button. + + + Custom icon for button to move down a favorite entry. + + + Custom icon for button to move up a favorite entry. + Custom icon for files. diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index b887a0b0ff..e0c28206dc 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -43,6 +43,7 @@ #include "scene/gui/menu_button.h" #include "scene/gui/option_button.h" #include "scene/gui/separator.h" +#include "scene/gui/split_container.h" #include "scene/theme/theme_db.h" void FileDialog::popup_file_dialog() { @@ -249,11 +250,13 @@ void FileDialog::_notification(int p_what) { } break; case NOTIFICATION_VISIBILITY_CHANGED: { - if (!is_visible()) { + if (is_visible()) { + _update_favorite_list(); + _update_recent_list(); + invalidate(); // Put it here to preview in the editor. + } else { set_process_shortcut_input(false); } - - invalidate(); // Put it here to preview in the editor. } break; case NOTIFICATION_THEME_CHANGED: { @@ -266,10 +269,13 @@ void FileDialog::_notification(int p_what) { } _setup_button(dir_up, theme_cache.parent_folder); _setup_button(refresh_button, theme_cache.reload); + _setup_button(favorite_button, theme_cache.favorite); _setup_button(show_hidden, theme_cache.toggle_hidden); _setup_button(make_dir_button, theme_cache.create_folder); _setup_button(show_filename_filter_button, theme_cache.toggle_filename_filter); _setup_button(file_sort_button, theme_cache.sort); + _setup_button(fav_up_button, theme_cache.favorite_up); + _setup_button(fav_down_button, theme_cache.favorite_down); invalidate(); } break; @@ -400,6 +406,8 @@ void FileDialog::_file_submitted(const String &p_file) { } void FileDialog::_save_confirm_pressed() { + _save_to_recent(); + String f = dir_access->get_current_dir().path_join(filename_edit->get_text()); emit_signal(SNAME("file_selected"), f); hide(); @@ -443,6 +451,7 @@ void FileDialog::_action_pressed() { if (mode == FILE_MODE_OPEN_FILES) { const Vector files = get_selected_files(); if (!files.is_empty()) { + _save_to_recent(); emit_signal(SNAME("files_selected"), files); hide(); } @@ -453,6 +462,7 @@ void FileDialog::_action_pressed() { String f = file_text.is_absolute_path() ? file_text : dir_access->get_current_dir().path_join(file_text); if ((mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_FILE) && (dir_access->file_exists(f) || dir_access->is_bundle(f))) { + _save_to_recent(); emit_signal(SNAME("file_selected"), f); hide(); } else if (mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_DIR) { @@ -467,6 +477,7 @@ void FileDialog::_action_pressed() { } } + _save_to_recent(); emit_signal(SNAME("dir_selected"), path); hide(); } @@ -528,6 +539,7 @@ void FileDialog::_action_pressed() { confirm_save->set_text(vformat(atr(ETR("File \"%s\" already exists.\nDo you want to overwrite it?")), f)); confirm_save->popup_centered(Size2(250, 80)); } else { + _save_to_recent(); emit_signal(SNAME("file_selected"), f); hide(); } @@ -937,6 +949,21 @@ void FileDialog::update_file_list() { _file_list_select_first(); } } + + favorite_list->deselect_all(); + favorite_button->set_pressed(false); + + const int fav_count = favorite_list->get_item_count(); + for (int i = 0; i < fav_count; i++) { + const String fav_dir = favorite_list->get_item_metadata(i); + if (fav_dir != base_dir && fav_dir != base_dir + "/") { + continue; + } + favorite_list->select(i); + favorite_button->set_pressed(true); + break; + } + _update_fav_buttons(); } void FileDialog::_filter_selected(int) { @@ -1274,6 +1301,8 @@ void FileDialog::set_access(Access p_access) { invalidate(); update_filters(); update_dir(); + _update_favorite_list(); + _update_recent_list(); } void FileDialog::invalidate() { @@ -1382,6 +1411,223 @@ void FileDialog::_sort_option_selected(int p_option) { invalidate(); } +void FileDialog::_favorite_selected(int p_item) { + ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_item, global_favorites.size()); + _change_dir(favorite_list->get_item_metadata(p_item)); + _push_history(); +} + +void FileDialog::_favorite_pressed() { + String directory = get_current_dir(); + if (!directory.ends_with("/")) { + directory += "/"; + } + + bool found = false; + for (const String &name : global_favorites) { + if (!_path_matches_access(name)) { + continue; + } + + if (name == directory) { + found = true; + break; + } + } + + if (found) { + global_favorites.erase(directory); + } else { + global_favorites.push_back(directory); + } + _update_favorite_list(); +} + +void FileDialog::_favorite_move_up() { + int current = favorite_list->get_current(); + if (current <= 0) { + return; + } + + int a_idx = global_favorites.find(favorite_list->get_item_metadata(current - 1)); + int b_idx = global_favorites.find(favorite_list->get_item_metadata(current)); + + if (a_idx == -1 || b_idx == -1) { + return; + } + SWAP(global_favorites[a_idx], global_favorites[b_idx]); + _update_favorite_list(); +} + +void FileDialog::_favorite_move_down() { + int current = favorite_list->get_current(); + if (current == -1 || current >= favorite_list->get_item_count() - 1) { + return; + } + + int a_idx = global_favorites.find(favorite_list->get_item_metadata(current)); + int b_idx = global_favorites.find(favorite_list->get_item_metadata(current + 1)); + + if (a_idx == -1 || b_idx == -1) { + return; + } + SWAP(global_favorites[a_idx], global_favorites[b_idx]); + _update_favorite_list(); +} + +void FileDialog::_update_favorite_list() { + const String current = get_current_dir(); + + favorite_list->clear(); + favorite_button->set_pressed(false); + + Vector favorited_paths; + Vector favorited_names; + + int current_favorite = -1; + for (uint32_t i = 0; i < global_favorites.size(); i++) { + String name = global_favorites[i]; + if (!_path_matches_access(name)) { + continue; + } + + if (!name.ends_with("/") || !name.begins_with(root_prefix)) { + continue; + } + + if (!dir_access->dir_exists(name)) { + // Remove invalid directory from the list of favorited directories. + global_favorites.remove_at(i); + i--; + continue; + } + + if (name == current) { + current_favorite = favorited_names.size(); + } + favorited_paths.append(name); + + // Compute favorite display text. + if (name == "res://" || name == "user://") { + name = "/"; + } else { + if (current_favorite == -1 && name == current + "/") { + current_favorite = favorited_names.size(); + } + name = name.trim_suffix("/"); + name = name.get_file(); + } + favorited_names.append(name); + } + + // EditorNode::disambiguate_filenames(favorited_paths, favorited_names); // TODO Needs a non-editor method. + + const int favorites_size = favorited_paths.size(); + for (int i = 0; i < favorites_size; i++) { + favorite_list->add_item(favorited_names[i], theme_cache.folder); + favorite_list->set_item_tooltip(-1, favorited_paths[i]); + favorite_list->set_item_metadata(-1, favorited_paths[i]); + + if (i == current_favorite) { + favorite_button->set_pressed(true); + favorite_list->set_current(favorite_list->get_item_count() - 1); + recent_list->deselect_all(); + } + } + _update_fav_buttons(); +} + +void FileDialog::_update_fav_buttons() { + const int current = favorite_list->get_current(); + fav_up_button->set_disabled(current < 1); + fav_down_button->set_disabled(current == -1 || current >= favorite_list->get_item_count() - 1); +} + +void FileDialog::_recent_selected(int p_item) { + ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_item, global_recents.size()); + _change_dir(recent_list->get_item_metadata(p_item)); + _push_history(); +} + +void FileDialog::_save_to_recent() { + String directory = get_current_dir(); + if (!directory.ends_with("/")) { + directory += "/"; + } + + int count = 0; + for (uint32_t i = 0; i < global_recents.size(); i++) { + const String &dir = global_recents[i]; + if (!_path_matches_access(dir)) { + continue; + } + + if (dir == directory || count > MAX_RECENTS) { + global_recents.remove_at(i); + i--; + } else { + count++; + } + } + global_recents.insert(0, directory); + + _update_recent_list(); +} + +void FileDialog::_update_recent_list() { + recent_list->clear(); + + Vector recent_dir_paths; + Vector recent_dir_names; + + for (uint32_t i = 0; i < global_recents.size(); i++) { + String name = global_recents[i]; + if (!_path_matches_access(name)) { + continue; + } + + if (!name.begins_with(root_prefix)) { + continue; + } + + if (!dir_access->dir_exists(name)) { + // Remove invalid directory from the list of recent directories. + global_recents.remove_at(i); + i--; + continue; + } + recent_dir_paths.append(name); + + // Compute recent directory display text. + if (name == "res://" || name == "user://") { + name = "/"; + } else { + name = name.trim_suffix("/").get_file(); + } + recent_dir_names.append(name); + } + + // EditorNode::disambiguate_filenames(recent_dir_paths, recent_dir_names); // TODO Needs a non-editor method. + + const int recent_size = recent_dir_paths.size(); + for (int i = 0; i < recent_size; i++) { + recent_list->add_item(recent_dir_names[i], theme_cache.folder); + recent_list->set_item_tooltip(-1, recent_dir_paths[i]); + recent_list->set_item_metadata(-1, recent_dir_paths[i]); + } +} + +bool FileDialog::_path_matches_access(const String &p_path) const { + bool is_res = p_path.begins_with("res://"); + bool is_user = p_path.begins_with("user://"); + if (access == ACCESS_RESOURCES) { + return is_res; + } else if (access == ACCESS_USERDATA) { + return is_user; + } + return !is_res && !is_user; +} + TypedArray FileDialog::_get_options() const { TypedArray out; for (const FileDialog::Option &opt : options) { @@ -1626,12 +1872,15 @@ void FileDialog::_bind_methods() { BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, FileDialog, forward_folder); BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, FileDialog, back_folder); BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, FileDialog, reload); + BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, FileDialog, favorite); BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, FileDialog, toggle_hidden); BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, FileDialog, folder); BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, FileDialog, toggle_filename_filter); BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, FileDialog, file); BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, FileDialog, create_folder); BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, FileDialog, sort); + BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, FileDialog, favorite_up); + BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, FileDialog, favorite_down); BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, FileDialog, folder_icon_color); BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, FileDialog, file_icon_color); @@ -1775,6 +2024,13 @@ FileDialog::FileDialog() { top_toolbar->add_child(refresh_button); refresh_button->connect(SceneStringName(pressed), callable_mp(this, &FileDialog::update_file_list)); + favorite_button = memnew(Button); + favorite_button->set_theme_type_variation(SceneStringName(FlatButton)); + favorite_button->set_accessibility_name(TTRC("(Un)favorite Folder")); + favorite_button->set_tooltip_text(TTRC("(Un)favorite current folder.")); + top_toolbar->add_child(favorite_button); + favorite_button->connect(SceneStringName(pressed), callable_mp(this, &FileDialog::_favorite_pressed)); + top_toolbar->add_child(memnew(VSeparator)); make_dir_button = memnew(Button); @@ -1784,8 +2040,66 @@ FileDialog::FileDialog() { top_toolbar->add_child(make_dir_button); make_dir_button->connect(SceneStringName(pressed), callable_mp(this, &FileDialog::_make_dir)); + HSplitContainer *main_split = memnew(HSplitContainer); + main_split->set_v_size_flags(Control::SIZE_EXPAND_FILL); + main_vbox->add_child(main_split); + + { + VSplitContainer *fav_split = memnew(VSplitContainer); + main_split->add_child(fav_split); + + VBoxContainer *fav_vbox = memnew(VBoxContainer); + fav_vbox->set_v_size_flags(Control::SIZE_EXPAND_FILL); + fav_split->add_child(fav_vbox); + + HBoxContainer *fav_hbox = memnew(HBoxContainer); + fav_vbox->add_child(fav_hbox); + + { + Label *label = memnew(Label(ETR("Favorites:"))); + label->set_h_size_flags(Control::SIZE_EXPAND_FILL); + fav_hbox->add_child(label); + } + + fav_up_button = memnew(Button); + fav_up_button->set_theme_type_variation(SceneStringName(FlatButton)); + fav_hbox->add_child(fav_up_button); + fav_up_button->connect(SceneStringName(pressed), callable_mp(this, &FileDialog::_favorite_move_up)); + + fav_down_button = memnew(Button); + fav_down_button->set_theme_type_variation(SceneStringName(FlatButton)); + fav_hbox->add_child(fav_down_button); + fav_down_button->connect(SceneStringName(pressed), callable_mp(this, &FileDialog::_favorite_move_down)); + + favorite_list = memnew(ItemList); + favorite_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); + favorite_list->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); + favorite_list->set_accessibility_name(ETR("Favorites")); + fav_vbox->add_child(favorite_list); + favorite_list->connect(SceneStringName(item_selected), callable_mp(this, &FileDialog::_favorite_selected)); + + VBoxContainer *recent_vbox = memnew(VBoxContainer); + recent_vbox->set_v_size_flags(Control::SIZE_EXPAND_FILL); + fav_split->add_child(recent_vbox); + + { + Label *label = memnew(Label(ETR("Recent:"))); + recent_vbox->add_child(label); + } + + recent_list = memnew(ItemList); + recent_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); + recent_list->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); + recent_list->set_accessibility_name(ETR("Recent")); + recent_vbox->add_child(recent_list); + recent_list->connect(SceneStringName(item_selected), callable_mp(this, &FileDialog::_recent_selected)); + } + + VBoxContainer *file_vbox = memnew(VBoxContainer); + main_split->add_child(file_vbox); + HBoxContainer *lower_toolbar = memnew(HBoxContainer); - main_vbox->add_child(lower_toolbar); + file_vbox->add_child(lower_toolbar); { Label *label = memnew(Label(ETR("Directories & Files:"))); @@ -1836,7 +2150,7 @@ FileDialog::FileDialog() { file_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); file_list->set_accessibility_name(ETR("Directories and Files")); file_list->set_allow_rmb_select(true); - main_vbox->add_child(file_list); + file_vbox->add_child(file_list); file_list->connect("multi_selected", callable_mp(this, &FileDialog::_file_list_multi_selected)); file_list->connect("item_selected", callable_mp(this, &FileDialog::_file_list_selected)); file_list->connect("item_activated", callable_mp(this, &FileDialog::_file_list_item_activated)); @@ -1853,7 +2167,7 @@ FileDialog::FileDialog() { filename_filter_box = memnew(HBoxContainer); filename_filter_box->set_visible(false); - main_vbox->add_child(filename_filter_box); + file_vbox->add_child(filename_filter_box); { Label *label = memnew(Label(ETR("Filter:"))); @@ -1871,7 +2185,7 @@ FileDialog::FileDialog() { filename_filter->connect(SceneStringName(text_submitted), callable_mp(this, &FileDialog::_filename_filter_selected).unbind(1)); file_box = memnew(HBoxContainer); - main_vbox->add_child(file_box); + file_vbox->add_child(file_box); { Label *label = memnew(Label(ETR("File:"))); diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index 9374cb4f00..4b6e64c086 100644 --- a/scene/gui/file_dialog.h +++ b/scene/gui/file_dialog.h @@ -47,6 +47,8 @@ class VBoxContainer; class FileDialog : public ConfirmationDialog { GDCLASS(FileDialog, ConfirmationDialog); + inline static constexpr int MAX_RECENTS = 20; + struct Option { String name; Vector values; @@ -142,6 +144,9 @@ private: bool show_hidden_files = false; bool use_native_dialog = false; + inline static LocalVector global_favorites; + inline static LocalVector global_recents; + Access access = ACCESS_RESOURCES; FileMode mode = FILE_MODE_SAVE_FILE; FileSortOption file_sort = FileSortOption::NAME; @@ -179,11 +184,17 @@ private: HBoxContainer *shortcuts_container = nullptr; Button *refresh_button = nullptr; + Button *favorite_button = nullptr; Button *make_dir_button = nullptr; Button *show_hidden = nullptr; Button *show_filename_filter_button = nullptr; MenuButton *file_sort_button = nullptr; + Button *fav_up_button = nullptr; + Button *fav_down_button = nullptr; + ItemList *favorite_list = nullptr; + ItemList *recent_list = nullptr; + ItemList *file_list = nullptr; Label *message = nullptr; PopupMenu *item_menu = nullptr; @@ -215,6 +226,9 @@ private: Ref file; Ref create_folder; Ref sort; + Ref favorite; + Ref favorite_up; + Ref favorite_down; Color folder_icon_color; Color file_icon_color; @@ -265,6 +279,18 @@ private: void _update_drives(bool p_select = true); void _sort_option_selected(int p_option); + void _favorite_selected(int p_item); + void _favorite_pressed(); + void _favorite_move_up(); + void _favorite_move_down(); + void _update_favorite_list(); + void _update_fav_buttons(); + + void _recent_selected(int p_item); + void _save_to_recent(); + void _update_recent_list(); + bool _path_matches_access(const String &p_path) const; + void _invalidate(); void _setup_button(Button *p_button, const Ref &p_icon); diff --git a/scene/theme/default_theme.cpp b/scene/theme/default_theme.cpp index b82f2721e7..641853cf6e 100644 --- a/scene/theme/default_theme.cpp +++ b/scene/theme/default_theme.cpp @@ -690,12 +690,15 @@ void fill_default_theme(Ref &theme, const Ref &default_font, const theme->set_icon("back_folder", "FileDialog", icons["arrow_left"]); theme->set_icon("forward_folder", "FileDialog", icons["arrow_right"]); theme->set_icon("reload", "FileDialog", icons["reload"]); + theme->set_icon("favorite", "FileDialog", icons["favorite"]); theme->set_icon("toggle_hidden", "FileDialog", icons["visibility_visible"]); theme->set_icon("toggle_filename_filter", "FileDialog", icons["toggle_filename_filter"]); theme->set_icon("folder", "FileDialog", icons["folder"]); theme->set_icon("file", "FileDialog", icons["file"]); theme->set_icon("create_folder", "FileDialog", icons["folder_create"]); theme->set_icon("sort", "FileDialog", icons["sort"]); + theme->set_icon("favorite_up", "FileDialog", icons["move_up"]); + theme->set_icon("favorite_down", "FileDialog", icons["move_down"]); theme->set_color("folder_icon_color", "FileDialog", Color(1, 1, 1)); theme->set_color("file_icon_color", "FileDialog", Color(1, 1, 1)); diff --git a/scene/theme/icons/favorite.svg b/scene/theme/icons/favorite.svg new file mode 100644 index 0000000000..3595265d96 --- /dev/null +++ b/scene/theme/icons/favorite.svg @@ -0,0 +1 @@ + diff --git a/scene/theme/icons/move_down.svg b/scene/theme/icons/move_down.svg new file mode 100644 index 0000000000..3459107476 --- /dev/null +++ b/scene/theme/icons/move_down.svg @@ -0,0 +1 @@ + diff --git a/scene/theme/icons/move_up.svg b/scene/theme/icons/move_up.svg new file mode 100644 index 0000000000..e98d5832f3 --- /dev/null +++ b/scene/theme/icons/move_up.svg @@ -0,0 +1 @@ + From 873833b4a7dcbbf5c264353de4546b66f8ec9132 Mon Sep 17 00:00:00 2001 From: Marwen Azouzi Date: Wed, 28 May 2025 12:54:04 +0200 Subject: [PATCH 038/144] Remove redundant `queue_redraw()` & fix typo --- core/io/image.h | 2 +- modules/jpg/image_loader_libjpeg_turbo.cpp | 4 ++-- scene/gui/line_edit.cpp | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/core/io/image.h b/core/io/image.h index 9b2a1ff07f..fe17fb1659 100644 --- a/core/io/image.h +++ b/core/io/image.h @@ -49,7 +49,7 @@ typedef Vector (*SavePNGBufferFunc)(const Ref &p_img); typedef Error (*SaveJPGFunc)(const String &p_path, const Ref &p_img, float p_quality); typedef Vector (*SaveJPGBufferFunc)(const Ref &p_img, float p_quality); -typedef Ref (*ImageMemLoadFunc)(const uint8_t *p_png, int p_size); +typedef Ref (*ImageMemLoadFunc)(const uint8_t *p_data, int p_size); typedef Ref (*ScalableImageMemLoadFunc)(const uint8_t *p_data, int p_size, float p_scale); typedef Error (*SaveWebPFunc)(const String &p_path, const Ref &p_img, const bool p_lossy, const float p_quality); diff --git a/modules/jpg/image_loader_libjpeg_turbo.cpp b/modules/jpg/image_loader_libjpeg_turbo.cpp index d078d2f370..f5b93e9cb5 100644 --- a/modules/jpg/image_loader_libjpeg_turbo.cpp +++ b/modules/jpg/image_loader_libjpeg_turbo.cpp @@ -97,10 +97,10 @@ void ImageLoaderLibJPEGTurbo::get_recognized_extensions(List *p_extensio p_extensions->push_back("jpeg"); } -static Ref _jpeg_turbo_mem_loader_func(const uint8_t *p_png, int p_size) { +static Ref _jpeg_turbo_mem_loader_func(const uint8_t *p_data, int p_size) { Ref img; img.instantiate(); - Error err = jpeg_turbo_load_image_from_buffer(img.ptr(), p_png, p_size); + Error err = jpeg_turbo_load_image_from_buffer(img.ptr(), p_data, p_size); ERR_FAIL_COND_V(err, Ref()); return img; } diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 1fa6d73a20..7210af1bfd 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -537,7 +537,6 @@ void LineEdit::gui_input(const Ref &p_event) { emit_signal(SNAME("editing_toggled"), true); return; } - queue_redraw(); } else { if (selection.enabled && !pass && b->get_button_index() == MouseButton::LEFT && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) { From e6c9a832c191cde380d10924d9a42e5d650ebd1d Mon Sep 17 00:00:00 2001 From: Danil Alexeev Date: Fri, 2 May 2025 18:54:40 +0300 Subject: [PATCH 039/144] Editor: Add ability to rename theme types --- doc/classes/Theme.xml | 9 ++ editor/plugins/theme_editor_plugin.cpp | 203 +++++++++++++++++++++---- editor/plugins/theme_editor_plugin.h | 13 +- scene/resources/theme.cpp | 121 +++++++++++++++ scene/resources/theme.h | 8 + 5 files changed, 326 insertions(+), 28 deletions(-) diff --git a/doc/classes/Theme.xml b/doc/classes/Theme.xml index 479456ae66..6dbc671cba 100644 --- a/doc/classes/Theme.xml +++ b/doc/classes/Theme.xml @@ -462,6 +462,15 @@ [b]Note:[/b] This method is analogous to calling the corresponding data type specific method, but can be used for more generalized logic. + + + + + + Renames the theme type [param old_theme_type] to [param theme_type], if the old type exists and the new one doesn't exist. + [b]Note:[/b] Renaming a theme type to an empty name or a variation to a type associated with a built-in class removes type variation connections in a way that cannot be undone by reversing the rename alone. + + diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index 38596bb898..08a0681006 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -54,9 +54,30 @@ #include "scene/gui/tab_bar.h" #include "scene/gui/tab_container.h" #include "scene/gui/texture_rect.h" -#include "scene/resources/packed_scene.h" #include "scene/theme/theme_db.h" +static void _rename_theme_type(EditorUndoRedoManager *p_ur, Theme *p_theme, const String &p_old_theme_type, const String &p_new_theme_type) { + p_ur->add_do_method(p_theme, "rename_type", p_old_theme_type, p_new_theme_type); + p_ur->add_undo_method(p_theme, "rename_type", p_new_theme_type, p_old_theme_type); + + // Renaming a theme type to an empty name or a variation to a type associated with a built-in class + // removes type variation connections in a way that cannot be undone by reversing the rename alone. + const StringName old_base_type = p_theme->get_type_variation_base(p_old_theme_type); + if ((!p_old_theme_type.is_empty() && p_new_theme_type.is_empty()) || (old_base_type != StringName() && ClassDB::class_exists(p_new_theme_type))) { + if (old_base_type != StringName()) { + p_ur->add_undo_method(p_theme, "set_type_variation", p_old_theme_type, old_base_type); + } + + List names; + p_theme->get_type_variation_list(p_old_theme_type, &names); + for (const StringName &E : names) { + p_ur->add_undo_method(p_theme, "set_type_variation", E, p_old_theme_type); + } + } +} + +/////////////////////// + void ThemeItemImportTree::_update_items_tree() { import_items_tree->clear(); TreeItem *root = import_items_tree->create_item(); @@ -1243,8 +1264,10 @@ void ThemeItemEditorDialog::_update_edit_types() { } TreeItem *list_item = edit_type_list->create_item(list_root); list_item->set_text(0, E); + list_item->set_metadata(0, E); + list_item->set_editable(0, true); list_item->set_icon(0, item_icon); - list_item->add_button(0, get_editor_theme_icon(SNAME("Remove")), TYPES_TREE_REMOVE_ITEM, false, TTR("Remove Type")); + list_item->add_button(0, get_editor_theme_icon(SNAME("Remove")), TYPES_TREE_REMOVE_ITEM, false, TTRC("Remove Type")); if (E == edited_item_type) { list_item->select(0); @@ -1306,6 +1329,46 @@ void ThemeItemEditorDialog::_edited_type_selected() { _update_edit_item_tree(selected_type); } +void ThemeItemEditorDialog::_edited_type_edited() { + TreeItem *edited_item = edit_type_list->get_selected(); + const String old_type_name = edited_item->get_metadata(0); + + String new_type_name = edited_item->get_text(0).strip_edges(); + if (!new_type_name.is_empty()) { // The type name can be empty, unlike the item name. + new_type_name = new_type_name.validate_ascii_identifier(); + } + + if (old_type_name == new_type_name) { + edited_item->set_text(0, old_type_name); + return; + } + + List theme_types; + edited_theme->get_type_list(&theme_types); + if (theme_types.find(new_type_name) != nullptr) { + edited_item->set_text(0, old_type_name); + return; + } + + // The list will be recreated, but let's update the item just in case. + edited_item->set_metadata(0, new_type_name); + edited_item->set_text(0, new_type_name); + + EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); + ur->create_action(TTR("Rename Theme Type")); + + _rename_theme_type(ur, *edited_theme, old_type_name, new_type_name); + + // Set `edited_item_type`. + ur->add_do_method(this, "_update_edit_item_tree", new_type_name); + ur->add_undo_method(this, "_update_edit_item_tree", old_type_name); + + ur->add_do_method(this, "_update_edit_types"); + ur->add_undo_method(this, "_update_edit_types"); + + ur->commit_action(); +} + void ThemeItemEditorDialog::_edited_type_button_pressed(Object *p_item, int p_column, int p_id, MouseButton p_button) { if (p_button != MouseButton::LEFT) { return; @@ -1520,22 +1583,26 @@ void ThemeItemEditorDialog::_item_tree_button_pressed(Object *p_item, int p_colu } } -void ThemeItemEditorDialog::_add_theme_type(const String &p_new_text) { - const String new_type = edit_add_type_value->get_text().strip_edges(); +void ThemeItemEditorDialog::_add_theme_type() { + String new_type_name = edit_add_type_value->get_text().strip_edges(); + if (!new_type_name.is_empty()) { // The type name can be empty, unlike the item name. + new_type_name = new_type_name.validate_ascii_identifier(); + } edit_add_type_value->clear(); EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); ur->create_action(TTR("Add Theme Type")); - ur->add_do_method(*edited_theme, "add_type", new_type); - ur->add_undo_method(*edited_theme, "remove_type", new_type); + ur->add_do_method(*edited_theme, "add_type", new_type_name); + ur->add_undo_method(*edited_theme, "remove_type", new_type_name); + ur->add_do_method(this, "_update_edit_types"); ur->add_undo_method(this, "_update_edit_types"); ur->commit_action(); } -void ThemeItemEditorDialog::_add_theme_item(Theme::DataType p_data_type, String p_item_name, String p_item_type) { +void ThemeItemEditorDialog::_add_theme_item(Theme::DataType p_data_type, const String &p_item_name, const String &p_item_type) { EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); ur->create_action(TTR("Create Theme Item")); @@ -1617,8 +1684,8 @@ void ThemeItemEditorDialog::_remove_data_type_items(Theme::DataType p_data_type, ur->add_do_method(*edited_theme, "merge_with", new_snapshot); ur->add_undo_method(*edited_theme, "merge_with", old_snapshot); - ur->add_do_method(theme_type_editor, "_update_edit_item_tree", edited_item_type); - ur->add_undo_method(theme_type_editor, "_update_edit_item_tree", edited_item_type); + ur->add_do_method(this, "_update_edit_item_tree", edited_item_type); + ur->add_undo_method(this, "_update_edit_item_tree", edited_item_type); ur->commit_action(); } @@ -1802,14 +1869,16 @@ void ThemeItemEditorDialog::_open_rename_theme_item_dialog(Theme::DataType p_dat } void ThemeItemEditorDialog::_confirm_edit_theme_item() { + const String new_item_name = theme_item_name->get_text().strip_edges().validate_ascii_identifier(); + if (item_popup_mode == CREATE_THEME_ITEM) { - _add_theme_item(edit_item_data_type, theme_item_name->get_text(), edited_item_type); + _add_theme_item(edit_item_data_type, new_item_name, edited_item_type); } else if (item_popup_mode == RENAME_THEME_ITEM) { EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); ur->create_action(TTR("Rename Theme Item")); - ur->add_do_method(*edited_theme, "rename_theme_item", edit_item_data_type, edit_item_old_name, theme_item_name->get_text(), edited_item_type); - ur->add_undo_method(*edited_theme, "rename_theme_item", edit_item_data_type, theme_item_name->get_text(), edit_item_old_name, edited_item_type); + ur->add_do_method(*edited_theme, "rename_theme_item", edit_item_data_type, edit_item_old_name, new_item_name, edited_item_type); + ur->add_undo_method(*edited_theme, "rename_theme_item", edit_item_data_type, new_item_name, edit_item_old_name, edited_item_type); ur->add_do_method(this, "_update_edit_item_tree", edited_item_type); ur->add_undo_method(this, "_update_edit_item_tree", edited_item_type); @@ -1927,6 +1996,7 @@ ThemeItemEditorDialog::ThemeItemEditorDialog(ThemeTypeEditor *p_theme_type_edito edit_type_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); edit_dialog_side_vb->add_child(edit_type_list); edit_type_list->connect(SceneStringName(item_selected), callable_mp(this, &ThemeItemEditorDialog::_edited_type_selected)); + edit_type_list->connect("item_edited", callable_mp(this, &ThemeItemEditorDialog::_edited_type_edited)); edit_type_list->connect("button_clicked", callable_mp(this, &ThemeItemEditorDialog::_edited_type_button_pressed)); edit_type_list->set_theme_type_variation("TreeSecondary"); @@ -1938,11 +2008,11 @@ ThemeItemEditorDialog::ThemeItemEditorDialog(ThemeTypeEditor *p_theme_type_edito edit_dialog_side_vb->add_child(edit_add_type_hb); edit_add_type_value = memnew(LineEdit); edit_add_type_value->set_h_size_flags(Control::SIZE_EXPAND_FILL); - edit_add_type_value->connect(SceneStringName(text_submitted), callable_mp(this, &ThemeItemEditorDialog::_add_theme_type)); + edit_add_type_value->connect(SceneStringName(text_submitted), callable_mp(this, &ThemeItemEditorDialog::_add_theme_type).unbind(1)); edit_add_type_hb->add_child(edit_add_type_value); edit_add_type_button = memnew(Button); edit_add_type_hb->add_child(edit_add_type_button); - edit_add_type_button->connect(SceneStringName(pressed), callable_mp(this, &ThemeItemEditorDialog::_add_theme_type).bind("")); + edit_add_type_button->connect(SceneStringName(pressed), callable_mp(this, &ThemeItemEditorDialog::_add_theme_type)); VBoxContainer *edit_items_vb = memnew(VBoxContainer); edit_items_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL); @@ -2350,7 +2420,14 @@ void ThemeTypeEditor::_update_type_list() { theme_type_list->clear(); - if (theme_types.size() > 0) { + if (theme_types.is_empty()) { + theme_type_list->set_disabled(true); + theme_type_list->add_item(TTRC("None")); + theme_type_list->set_item_auto_translate_mode(-1, AUTO_TRANSLATE_MODE_ALWAYS); + + edited_type = ""; + _update_type_items(); + } else { theme_type_list->set_disabled(false); bool item_reselected = false; @@ -2371,20 +2448,17 @@ void ThemeTypeEditor::_update_type_list() { e_idx++; } - if (!item_reselected) { + if (item_reselected) { + _update_type_items(); + } else { theme_type_list->select(0); _list_type_selected(0); - } else { - _update_type_items(); } - } else { - theme_type_list->set_disabled(true); - theme_type_list->add_item(TTR("None")); - - edited_type = ""; - _update_type_items(); } + rename_type_button->set_disabled(theme_types.is_empty()); + remove_type_button->set_disabled(theme_types.is_empty()); + updating = false; } @@ -2818,6 +2892,54 @@ void ThemeTypeEditor::_add_type_button_cbk() { add_type_dialog->popup_centered(Size2(560, 420) * EDSCALE); } +void ThemeTypeEditor::_rename_type_button_cbk() { + theme_type_rename_line_edit->set_text(edited_type); + theme_type_rename_dialog->reset_size(); + theme_type_rename_dialog->popup_centered(); + theme_type_rename_line_edit->grab_focus(); +} + +void ThemeTypeEditor::_theme_type_rename_dialog_confirmed() { + String new_type_name = theme_type_rename_line_edit->get_text().strip_edges(); + if (!new_type_name.is_empty()) { // The type name can be empty, unlike the item name. + new_type_name = new_type_name.validate_ascii_identifier(); + } + + if (edited_type == new_type_name) { + return; + } + + List theme_types; + edited_theme->get_type_list(&theme_types); + if (theme_types.find(new_type_name) != nullptr) { + return; + } + + EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); + ur->create_action(TTR("Rename Theme Type")); + + _rename_theme_type(ur, *edited_theme, edited_type, new_type_name); + + ur->add_do_method(this, "select_type", new_type_name); + ur->add_undo_method(this, "select_type", edited_type); + + ur->commit_action(); +} + +void ThemeTypeEditor::_remove_type_button_cbk() { + Ref old_snapshot = edited_theme->duplicate(); + + EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); + ur->create_action(TTR("Remove Theme Type")); + + ur->add_do_method(*edited_theme, "remove_type", edited_type); + // If the type was empty, it cannot be restored with merge, but thankfully we can fake it. + ur->add_undo_method(*edited_theme, "add_type", edited_type); + ur->add_undo_method(*edited_theme, "merge_with", old_snapshot); + + ur->commit_action(); +} + void ThemeTypeEditor::_add_default_type_items() { List names; String default_type = edited_type; @@ -2911,7 +3033,8 @@ void ThemeTypeEditor::_item_add_cbk(int p_data_type, Control *p_control) { return; } - String item_name = le->get_text().strip_edges(); + const String item_name = le->get_text().strip_edges().validate_ascii_identifier(); + EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); ur->create_action(TTR("Add Theme Item")); @@ -3069,7 +3192,7 @@ void ThemeTypeEditor::_item_rename_confirmed(int p_data_type, String p_item_name return; } - String new_name = le->get_text().strip_edges(); + const String new_name = le->get_text().strip_edges().validate_ascii_identifier(); if (new_name == p_item_name) { _item_rename_canceled(p_data_type, p_item_name, p_control); return; @@ -3377,6 +3500,8 @@ void ThemeTypeEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { add_type_button->set_button_icon(get_editor_theme_icon(SNAME("Add"))); + rename_type_button->set_button_icon(get_editor_theme_icon(SNAME("Rename"))); + remove_type_button->set_button_icon(get_editor_theme_icon(SNAME("Remove"))); data_type_tabs->set_tab_icon(0, get_editor_theme_icon(SNAME("Color"))); data_type_tabs->set_tab_icon(1, get_editor_theme_icon(SNAME("MemberConstant"))); @@ -3396,6 +3521,7 @@ void ThemeTypeEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_pin_leading_stylebox"), &ThemeTypeEditor::_pin_leading_stylebox); ClassDB::bind_method(D_METHOD("_unpin_leading_stylebox"), &ThemeTypeEditor::_unpin_leading_stylebox); ClassDB::bind_method(D_METHOD("_change_pinned_stylebox"), &ThemeTypeEditor::_change_pinned_stylebox); + ClassDB::bind_method(D_METHOD("select_type", "type_name"), &ThemeTypeEditor::select_type); } void ThemeTypeEditor::set_edited_theme(const Ref &p_theme) { @@ -3468,6 +3594,31 @@ ThemeTypeEditor::ThemeTypeEditor() { type_list_hb->add_child(add_type_button); add_type_button->connect(SceneStringName(pressed), callable_mp(this, &ThemeTypeEditor::_add_type_button_cbk)); + rename_type_button = memnew(Button); + rename_type_button->set_disabled(true); + rename_type_button->set_tooltip_text(TTRC("Rename current type.")); + rename_type_button->set_accessibility_name(TTRC("Rename Current Type")); + type_list_hb->add_child(rename_type_button); + rename_type_button->connect(SceneStringName(pressed), callable_mp(this, &ThemeTypeEditor::_rename_type_button_cbk)); + + theme_type_rename_dialog = memnew(ConfirmationDialog); + theme_type_rename_dialog->set_title(TTRC("Rename Theme Type")); + theme_type_rename_dialog->set_min_size(Size2(256, 64) * EDSCALE); + add_child(theme_type_rename_dialog); + theme_type_rename_dialog->connect(SceneStringName(confirmed), callable_mp(this, &ThemeTypeEditor::_theme_type_rename_dialog_confirmed)); + + theme_type_rename_line_edit = memnew(LineEdit); + theme_type_rename_line_edit->set_select_all_on_focus(true); + theme_type_rename_dialog->add_child(theme_type_rename_line_edit); + theme_type_rename_dialog->register_text_enter(theme_type_rename_line_edit); + + remove_type_button = memnew(Button); + remove_type_button->set_disabled(true); + remove_type_button->set_tooltip_text(TTRC("Remove current type.")); + remove_type_button->set_accessibility_name(TTRC("Remove Current Type")); + type_list_hb->add_child(remove_type_button); + remove_type_button->connect(SceneStringName(pressed), callable_mp(this, &ThemeTypeEditor::_remove_type_button_cbk)); + HBoxContainer *type_controls = memnew(HBoxContainer); main_vb->add_child(type_controls); diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h index 711da63d33..7e6d933d27 100644 --- a/editor/plugins/theme_editor_plugin.h +++ b/editor/plugins/theme_editor_plugin.h @@ -42,6 +42,7 @@ class CheckButton; class EditorFileDialog; class ItemList; class Label; +class LineEdit; class OptionButton; class PanelContainer; class TabBar; @@ -253,13 +254,14 @@ class ThemeItemEditorDialog : public AcceptDialog { void _dialog_about_to_show(); void _update_edit_types(); void _edited_type_selected(); + void _edited_type_edited(); void _edited_type_button_pressed(Object *p_item, int p_column, int p_id, MouseButton p_button); void _update_edit_item_tree(String p_item_type); void _item_tree_button_pressed(Object *p_item, int p_column, int p_id, MouseButton p_button); - void _add_theme_type(const String &p_new_text); - void _add_theme_item(Theme::DataType p_data_type, String p_item_name, String p_item_type); + void _add_theme_type(); + void _add_theme_item(Theme::DataType p_data_type, const String &p_item_name, const String &p_item_type); void _remove_theme_type(const String &p_theme_type); void _remove_data_type_items(Theme::DataType p_data_type, String p_item_type); void _remove_class_items(); @@ -344,6 +346,10 @@ class ThemeTypeEditor : public MarginContainer { OptionButton *theme_type_list = nullptr; Button *add_type_button = nullptr; + Button *rename_type_button = nullptr; + ConfirmationDialog *theme_type_rename_dialog = nullptr; + LineEdit *theme_type_rename_line_edit = nullptr; + Button *remove_type_button = nullptr; CheckButton *show_default_items_button = nullptr; @@ -380,6 +386,9 @@ class ThemeTypeEditor : public MarginContainer { void _list_type_selected(int p_index); void _add_type_button_cbk(); + void _rename_type_button_cbk(); + void _theme_type_rename_dialog_confirmed(); + void _remove_type_button_cbk(); void _add_default_type_items(); void _update_add_button(const String &p_text, LineEdit *p_for_edit); diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp index d4d489cfae..fc9562c861 100644 --- a/scene/resources/theme.cpp +++ b/scene/resources/theme.cpp @@ -361,6 +361,17 @@ void Theme::remove_icon_type(const StringName &p_theme_type) { _unfreeze_and_propagate_changes(); } +void Theme::rename_icon_type(const StringName &p_old_theme_type, const StringName &p_theme_type) { + ERR_FAIL_COND_MSG(!is_valid_type_name(p_theme_type), vformat("Invalid type name: '%s'", p_theme_type)); + + if (!icon_map.has(p_old_theme_type) || icon_map.has(p_theme_type)) { + return; + } + + icon_map[p_theme_type] = icon_map[p_old_theme_type]; + icon_map.erase(p_old_theme_type); +} + void Theme::get_icon_type_list(List *p_list) const { ERR_FAIL_NULL(p_list); @@ -471,6 +482,17 @@ void Theme::remove_stylebox_type(const StringName &p_theme_type) { _unfreeze_and_propagate_changes(); } +void Theme::rename_stylebox_type(const StringName &p_old_theme_type, const StringName &p_theme_type) { + ERR_FAIL_COND_MSG(!is_valid_type_name(p_theme_type), vformat("Invalid type name: '%s'", p_theme_type)); + + if (!style_map.has(p_old_theme_type) || style_map.has(p_theme_type)) { + return; + } + + style_map[p_theme_type] = style_map[p_old_theme_type]; + style_map.erase(p_old_theme_type); +} + void Theme::get_stylebox_type_list(List *p_list) const { ERR_FAIL_NULL(p_list); @@ -587,6 +609,17 @@ void Theme::remove_font_type(const StringName &p_theme_type) { _unfreeze_and_propagate_changes(); } +void Theme::rename_font_type(const StringName &p_old_theme_type, const StringName &p_theme_type) { + ERR_FAIL_COND_MSG(!is_valid_type_name(p_theme_type), vformat("Invalid type name: '%s'", p_theme_type)); + + if (!font_map.has(p_old_theme_type) || font_map.has(p_theme_type)) { + return; + } + + font_map[p_theme_type] = font_map[p_old_theme_type]; + font_map.erase(p_old_theme_type); +} + void Theme::get_font_type_list(List *p_list) const { ERR_FAIL_NULL(p_list); @@ -679,6 +712,17 @@ void Theme::remove_font_size_type(const StringName &p_theme_type) { font_size_map.erase(p_theme_type); } +void Theme::rename_font_size_type(const StringName &p_old_theme_type, const StringName &p_theme_type) { + ERR_FAIL_COND_MSG(!is_valid_type_name(p_theme_type), vformat("Invalid type name: '%s'", p_theme_type)); + + if (!font_size_map.has(p_old_theme_type) || font_size_map.has(p_theme_type)) { + return; + } + + font_size_map[p_theme_type] = font_size_map[p_old_theme_type]; + font_size_map.erase(p_old_theme_type); +} + void Theme::get_font_size_type_list(List *p_list) const { ERR_FAIL_NULL(p_list); @@ -765,6 +809,17 @@ void Theme::remove_color_type(const StringName &p_theme_type) { color_map.erase(p_theme_type); } +void Theme::rename_color_type(const StringName &p_old_theme_type, const StringName &p_theme_type) { + ERR_FAIL_COND_MSG(!is_valid_type_name(p_theme_type), vformat("Invalid type name: '%s'", p_theme_type)); + + if (!color_map.has(p_old_theme_type) || color_map.has(p_theme_type)) { + return; + } + + color_map[p_theme_type] = color_map[p_old_theme_type]; + color_map.erase(p_old_theme_type); +} + void Theme::get_color_type_list(List *p_list) const { ERR_FAIL_NULL(p_list); @@ -851,6 +906,17 @@ void Theme::remove_constant_type(const StringName &p_theme_type) { constant_map.erase(p_theme_type); } +void Theme::rename_constant_type(const StringName &p_old_theme_type, const StringName &p_theme_type) { + ERR_FAIL_COND_MSG(!is_valid_type_name(p_theme_type), vformat("Invalid type name: '%s'", p_theme_type)); + + if (!constant_map.has(p_old_theme_type) || constant_map.has(p_theme_type)) { + return; + } + + constant_map[p_theme_type] = constant_map[p_old_theme_type]; + constant_map.erase(p_old_theme_type); +} + void Theme::get_constant_type_list(List *p_list) const { ERR_FAIL_NULL(p_list); @@ -1099,6 +1165,31 @@ void Theme::remove_theme_item_type(DataType p_data_type, const StringName &p_the } } +void Theme::rename_theme_item_type(DataType p_data_type, const StringName &p_old_theme_type, const StringName &p_theme_type) { + switch (p_data_type) { + case DATA_TYPE_COLOR: + rename_color_type(p_old_theme_type, p_theme_type); + break; + case DATA_TYPE_CONSTANT: + rename_constant_type(p_old_theme_type, p_theme_type); + break; + case DATA_TYPE_FONT: + rename_font_type(p_old_theme_type, p_theme_type); + break; + case DATA_TYPE_FONT_SIZE: + rename_font_size_type(p_old_theme_type, p_theme_type); + break; + case DATA_TYPE_ICON: + rename_icon_type(p_old_theme_type, p_theme_type); + break; + case DATA_TYPE_STYLEBOX: + rename_stylebox_type(p_old_theme_type, p_theme_type); + break; + case DATA_TYPE_MAX: + break; // Can't happen, but silences warning. + } +} + void Theme::get_theme_item_type_list(DataType p_data_type, List *p_list) const { switch (p_data_type) { case DATA_TYPE_COLOR: @@ -1217,6 +1308,35 @@ void Theme::remove_type(const StringName &p_theme_type) { _emit_theme_changed(true); } +void Theme::rename_type(const StringName &p_old_theme_type, const StringName &p_theme_type) { + // Gracefully rename the record in every data type map. + for (int i = 0; i < Theme::DATA_TYPE_MAX; i++) { + Theme::DataType dt = (Theme::DataType)i; + rename_theme_item_type(dt, p_old_theme_type, p_theme_type); + } + + // If type is a variation, replace that connection. + const StringName base_type = get_type_variation_base(p_old_theme_type); + if (base_type != StringName()) { + clear_type_variation(p_old_theme_type); + if (p_theme_type != StringName() && !ClassDB::class_exists(p_theme_type)) { + set_type_variation(p_theme_type, base_type); + } + } + + // If type is a variation base, replace all those connections. + List names; + get_type_variation_list(p_old_theme_type, &names); + for (const StringName &E : names) { + clear_type_variation(E); + if (p_theme_type != StringName()) { + set_type_variation(E, p_theme_type); + } + } + + _emit_theme_changed(true); +} + void Theme::get_type_list(List *p_list) const { ERR_FAIL_NULL(p_list); @@ -1769,6 +1889,7 @@ void Theme::_bind_methods() { ClassDB::bind_method(D_METHOD("add_type", "theme_type"), &Theme::add_type); ClassDB::bind_method(D_METHOD("remove_type", "theme_type"), &Theme::remove_type); + ClassDB::bind_method(D_METHOD("rename_type", "old_theme_type", "theme_type"), &Theme::rename_type); ClassDB::bind_method(D_METHOD("get_type_list"), &Theme::_get_type_list); ClassDB::bind_method(D_METHOD("merge_with", "other"), &Theme::merge_with); diff --git a/scene/resources/theme.h b/scene/resources/theme.h index 91575d46a4..c5c5234d26 100644 --- a/scene/resources/theme.h +++ b/scene/resources/theme.h @@ -138,6 +138,7 @@ public: void get_icon_list(const StringName &p_theme_type, List *p_list) const; void add_icon_type(const StringName &p_theme_type); void remove_icon_type(const StringName &p_theme_type); + void rename_icon_type(const StringName &p_old_theme_type, const StringName &p_theme_type); void get_icon_type_list(List *p_list) const; void set_stylebox(const StringName &p_name, const StringName &p_theme_type, const Ref &p_style); @@ -149,6 +150,7 @@ public: void get_stylebox_list(const StringName &p_theme_type, List *p_list) const; void add_stylebox_type(const StringName &p_theme_type); void remove_stylebox_type(const StringName &p_theme_type); + void rename_stylebox_type(const StringName &p_old_theme_type, const StringName &p_theme_type); void get_stylebox_type_list(List *p_list) const; void set_font(const StringName &p_name, const StringName &p_theme_type, const Ref &p_font); @@ -161,6 +163,7 @@ public: void get_font_list(const StringName &p_theme_type, List *p_list) const; void add_font_type(const StringName &p_theme_type); void remove_font_type(const StringName &p_theme_type); + void rename_font_type(const StringName &p_old_theme_type, const StringName &p_theme_type); void get_font_type_list(List *p_list) const; void set_font_size(const StringName &p_name, const StringName &p_theme_type, int p_font_size); @@ -173,6 +176,7 @@ public: void get_font_size_list(const StringName &p_theme_type, List *p_list) const; void add_font_size_type(const StringName &p_theme_type); void remove_font_size_type(const StringName &p_theme_type); + void rename_font_size_type(const StringName &p_old_theme_type, const StringName &p_theme_type); void get_font_size_type_list(List *p_list) const; void set_color(const StringName &p_name, const StringName &p_theme_type, const Color &p_color); @@ -184,6 +188,7 @@ public: void get_color_list(const StringName &p_theme_type, List *p_list) const; void add_color_type(const StringName &p_theme_type); void remove_color_type(const StringName &p_theme_type); + void rename_color_type(const StringName &p_old_theme_type, const StringName &p_theme_type); void get_color_type_list(List *p_list) const; void set_constant(const StringName &p_name, const StringName &p_theme_type, int p_constant); @@ -195,6 +200,7 @@ public: void get_constant_list(const StringName &p_theme_type, List *p_list) const; void add_constant_type(const StringName &p_theme_type); void remove_constant_type(const StringName &p_theme_type); + void rename_constant_type(const StringName &p_old_theme_type, const StringName &p_theme_type); void get_constant_type_list(List *p_list) const; void set_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type, const Variant &p_value); @@ -206,6 +212,7 @@ public: void get_theme_item_list(DataType p_data_type, const StringName &p_theme_type, List *p_list) const; void add_theme_item_type(DataType p_data_type, const StringName &p_theme_type); void remove_theme_item_type(DataType p_data_type, const StringName &p_theme_type); + void rename_theme_item_type(DataType p_data_type, const StringName &p_old_theme_type, const StringName &p_theme_type); void get_theme_item_type_list(DataType p_data_type, List *p_list) const; void set_type_variation(const StringName &p_theme_type, const StringName &p_base_type); @@ -216,6 +223,7 @@ public: void add_type(const StringName &p_theme_type); void remove_type(const StringName &p_theme_type); + void rename_type(const StringName &p_old_theme_type, const StringName &p_theme_type); void get_type_list(List *p_list) const; void get_type_dependencies(const StringName &p_base_type, const StringName &p_type_variant, Vector &r_result); From 3ec1440e809ea3795ecd908fb9e9e473fa90548f Mon Sep 17 00:00:00 2001 From: arkology <43543909+arkology@users.noreply.github.com> Date: Sun, 16 Mar 2025 12:44:41 +0300 Subject: [PATCH 040/144] Fix Run Instances window being too big --- editor/run_instances_dialog.cpp | 66 ++++++++++++++++----------------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/editor/run_instances_dialog.cpp b/editor/run_instances_dialog.cpp index 1e2d598c73..132e2c4cbd 100644 --- a/editor/run_instances_dialog.cpp +++ b/editor/run_instances_dialog.cpp @@ -38,6 +38,7 @@ #include "scene/gui/label.h" #include "scene/gui/line_edit.h" #include "scene/gui/popup_menu.h" +#include "scene/gui/separator.h" #include "scene/gui/spin_box.h" #include "scene/gui/tree.h" #include "scene/main/timer.h" @@ -194,7 +195,7 @@ void RunInstancesDialog::_instance_tree_rmb(const Vector2 &p_pos, MouseButton p_ } void RunInstancesDialog::popup_dialog() { - popup_centered(Vector2(1200, 600) * EDSCALE); + popup_centered_clamped(Size2(1200, 600) * EDSCALE, 0.8); } int RunInstancesDialog::get_instance_count() const { @@ -310,48 +311,29 @@ RunInstancesDialog::RunInstancesDialog() { VBoxContainer *main_vb = memnew(VBoxContainer); add_child(main_vb); - GridContainer *args_gc = memnew(GridContainer); - args_gc->set_columns(3); - args_gc->add_theme_constant_override("h_separation", 12 * EDSCALE); - main_vb->add_child(args_gc); - - enable_multiple_instances_checkbox = memnew(CheckBox); - enable_multiple_instances_checkbox->set_text(TTR("Enable Multiple Instances")); - enable_multiple_instances_checkbox->set_pressed(EditorSettings::get_singleton()->get_project_metadata("debug_options", "multiple_instances_enabled", false)); - args_gc->add_child(enable_multiple_instances_checkbox); - enable_multiple_instances_checkbox->connect(SceneStringName(pressed), callable_mp(this, &RunInstancesDialog::_start_main_timer)); + GridContainer *main_gc = memnew(GridContainer); + main_gc->set_columns(2); + main_vb->add_child(main_gc); { Label *l = memnew(Label); l->set_text(TTR("Main Run Args:")); - args_gc->add_child(l); + main_gc->add_child(l); } { Label *l = memnew(Label); l->set_text(TTR("Main Feature Tags:")); - args_gc->add_child(l); + main_gc->add_child(l); } stored_data = TypedArray(EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_instances_config", TypedArray())); - instance_count = memnew(SpinBox); - instance_count->set_min(1); - instance_count->set_max(20); - instance_count->set_value(EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_instance_count", stored_data.size())); - instance_count->set_accessibility_name(TTRC("Number of Instances")); - - args_gc->add_child(instance_count); - instance_count->connect(SceneStringName(value_changed), callable_mp(this, &RunInstancesDialog::_start_instance_timer).unbind(1)); - instance_count->connect(SceneStringName(value_changed), callable_mp(this, &RunInstancesDialog::_refresh_argument_count).unbind(1)); - enable_multiple_instances_checkbox->connect(SceneStringName(toggled), callable_mp(instance_count, &SpinBox::set_editable)); - instance_count->set_editable(enable_multiple_instances_checkbox->is_pressed()); - main_args_edit = memnew(LineEdit); main_args_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL); main_args_edit->set_placeholder(TTR("Space-separated arguments, example: host player1 blue")); main_args_edit->set_accessibility_name(TTRC("Launch Arguments")); - args_gc->add_child(main_args_edit); + main_gc->add_child(main_args_edit); _fetch_main_args(); ProjectSettings::get_singleton()->connect("settings_changed", callable_mp(this, &RunInstancesDialog::_fetch_main_args)); main_args_edit->connect(SceneStringName(text_changed), callable_mp(this, &RunInstancesDialog::_start_main_timer).unbind(1)); @@ -361,16 +343,32 @@ RunInstancesDialog::RunInstancesDialog() { main_features_edit->set_placeholder(TTR("Comma-separated tags, example: demo, steam, event")); main_features_edit->set_text(EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_main_feature_tags", "")); main_features_edit->set_accessibility_name(TTRC("Feature Tags")); - args_gc->add_child(main_features_edit); + main_gc->add_child(main_features_edit); main_features_edit->connect(SceneStringName(text_changed), callable_mp(this, &RunInstancesDialog::_start_main_timer).unbind(1)); - { - Label *l = memnew(Label); - l->set_text(TTR("Instance Configuration")); - l->set_h_size_flags(Control::SIZE_SHRINK_CENTER); - l->set_theme_type_variation("HeaderSmall"); - main_vb->add_child(l); - } + main_vb->add_child(memnew(HSeparator)); + + HBoxContainer *instance_hb = memnew(HBoxContainer); + instance_hb->set_alignment(BoxContainer::ALIGNMENT_CENTER); + main_vb->add_child(instance_hb); + + enable_multiple_instances_checkbox = memnew(CheckBox); + enable_multiple_instances_checkbox->set_text(TTRC("Enable Multiple Instances")); + enable_multiple_instances_checkbox->set_pressed(EditorSettings::get_singleton()->get_project_metadata("debug_options", "multiple_instances_enabled", false)); + instance_hb->add_child(enable_multiple_instances_checkbox); + enable_multiple_instances_checkbox->connect(SceneStringName(pressed), callable_mp(this, &RunInstancesDialog::_start_main_timer)); + + instance_count = memnew(SpinBox); + instance_count->set_min(1); + instance_count->set_max(20); + instance_count->set_value(EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_instance_count", stored_data.size())); + instance_count->set_accessibility_name(TTRC("Number of Instances")); + + instance_hb->add_child(instance_count); + instance_count->connect(SceneStringName(value_changed), callable_mp(this, &RunInstancesDialog::_start_instance_timer).unbind(1)); + instance_count->connect(SceneStringName(value_changed), callable_mp(this, &RunInstancesDialog::_refresh_argument_count).unbind(1)); + enable_multiple_instances_checkbox->connect(SceneStringName(toggled), callable_mp(instance_count, &SpinBox::set_editable)); + instance_count->set_editable(enable_multiple_instances_checkbox->is_pressed()); instance_tree = memnew(Tree); instance_tree->set_v_size_flags(Control::SIZE_EXPAND_FILL); From 798a644dd56257cea2803d03fb49aa7118e7df41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pa=CC=84vels=20Nadtoc=CC=8Cajevs?= <7645683+bruvzg@users.noreply.github.com> Date: Fri, 30 May 2025 00:13:53 +0300 Subject: [PATCH 041/144] [macOS] Fix borderless window maximization. --- platform/macos/display_server_macos.h | 3 ++- platform/macos/display_server_macos.mm | 19 +++++++++++++++++-- platform/macos/godot_window_delegate.mm | 10 ++++++++++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h index 72e08ceb9c..33118963e6 100644 --- a/platform/macos/display_server_macos.h +++ b/platform/macos/display_server_macos.h @@ -111,7 +111,8 @@ public: Size2i size; Vector2i wb_offset = Vector2i(14, 14); - NSRect last_frame_rect; + NSRect last_frame_rect = NSMakeRect(0, 0, 0, 0); + NSRect pre_zoom_rect = NSMakeRect(0, 0, 0, 0); bool im_active = false; Size2i im_position; diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index 9ab14ffbca..9892ee511c 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -2537,7 +2537,13 @@ void DisplayServerMacOS::window_set_mode(WindowMode p_mode, WindowID p_window) { } break; case WINDOW_MODE_MAXIMIZED: { if (NSEqualRects([wd.window_object frame], [[wd.window_object screen] visibleFrame])) { - [wd.window_object zoom:nil]; + if (wd.borderless) { + if (wd.pre_zoom_rect.size.width > 0 && wd.pre_zoom_rect.size.height > 0) { + [wd.window_object setFrame:wd.pre_zoom_rect display:NO animate:YES]; + } + } else { + [wd.window_object zoom:nil]; + } } } break; } @@ -2570,7 +2576,12 @@ void DisplayServerMacOS::window_set_mode(WindowMode p_mode, WindowID p_window) { } break; case WINDOW_MODE_MAXIMIZED: { if (!NSEqualRects([wd.window_object frame], [[wd.window_object screen] visibleFrame])) { - [wd.window_object zoom:nil]; + wd.pre_zoom_rect = [wd.window_object frame]; + if (wd.borderless) { + [wd.window_object setFrame:[[wd.window_object screen] visibleFrame] display:NO animate:YES]; + } else { + [wd.window_object zoom:nil]; + } } } break; } @@ -2770,6 +2781,7 @@ void DisplayServerMacOS::window_set_flag(WindowFlags p_flag, bool p_enabled, Win [wd.window_object orderOut:nil]; } wd.borderless = p_enabled; + bool was_maximized = (NSEqualRects([wd.window_object frame], [[wd.window_object screen] visibleFrame])); if (p_enabled) { [wd.window_object setStyleMask:NSWindowStyleMaskBorderless]; [wd.window_object setHasShadow:NO]; @@ -2800,6 +2812,9 @@ void DisplayServerMacOS::window_set_flag(WindowFlags p_flag, bool p_enabled, Win [wd.window_object makeKeyAndOrderFront:nil]; } } + if (was_maximized) { + [wd.window_object setFrame:[[wd.window_object screen] visibleFrame] display:NO]; + } } break; case WINDOW_FLAG_ALWAYS_ON_TOP: { wd.on_top = p_enabled; diff --git a/platform/macos/godot_window_delegate.mm b/platform/macos/godot_window_delegate.mm index 8c105c375d..4d7ffe9331 100644 --- a/platform/macos/godot_window_delegate.mm +++ b/platform/macos/godot_window_delegate.mm @@ -208,6 +208,16 @@ [self windowDidResize:notification]; } +- (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame { + if (ds->has_window(window_id)) { + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); + if (!wd.borderless && !(NSEqualRects([wd.window_object frame], [[wd.window_object screen] visibleFrame]))) { + wd.pre_zoom_rect = [wd.window_object frame]; + } + } + return YES; +} + - (void)windowDidChangeBackingProperties:(NSNotification *)notification { if (!ds->has_window(window_id)) { return; From 90ecdafc2716105ea3cce3507374d831f10e492c Mon Sep 17 00:00:00 2001 From: Michael Alexsander Date: Mon, 26 May 2025 13:50:40 -0300 Subject: [PATCH 042/144] Reorganize scroll and zoom elements in the audio import dialog --- .../import/audio_stream_import_settings.cpp | 48 ++++++++----------- editor/import/audio_stream_import_settings.h | 2 - 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/editor/import/audio_stream_import_settings.cpp b/editor/import/audio_stream_import_settings.cpp index 59e95b5c33..c5c60a7bcc 100644 --- a/editor/import/audio_stream_import_settings.cpp +++ b/editor/import/audio_stream_import_settings.cpp @@ -184,7 +184,6 @@ void AudioStreamImportSettingsDialog::_preview_zoom_in() { return; } float page_size = zoom_bar->get_page(); - zoom_spacer->hide(); zoom_bar->set_page(page_size * 0.5); zoom_bar->set_value(zoom_bar->get_value() + page_size * 0.25); zoom_bar->show(); @@ -202,7 +201,6 @@ void AudioStreamImportSettingsDialog::_preview_zoom_out() { zoom_bar->set_value(zoom_bar->get_value() - page_size * 0.5); if (zoom_bar->get_value() == 0) { zoom_bar->hide(); - zoom_spacer->show(); } _preview->queue_redraw(); @@ -217,7 +215,6 @@ void AudioStreamImportSettingsDialog::_preview_zoom_reset() { zoom_bar->set_page(zoom_bar->get_max()); zoom_bar->set_value(0); zoom_bar->hide(); - zoom_spacer->show(); _preview->queue_redraw(); _indicator->queue_redraw(); @@ -615,30 +612,15 @@ AudioStreamImportSettingsDialog::AudioStreamImportSettingsDialog() { _preview->set_v_size_flags(Control::SIZE_EXPAND_FILL); vbox->add_child(_preview); - HBoxContainer *zoom_hbox = memnew(HBoxContainer); zoom_bar = memnew(HScrollBar); zoom_bar->hide(); - zoom_in = memnew(Button); - zoom_in->set_accessibility_name(TTRC("Zoom In")); - zoom_in->set_flat(true); - zoom_reset = memnew(Button); - zoom_reset->set_accessibility_name(TTRC("Reset Zoom")); - zoom_reset->set_flat(true); - zoom_out = memnew(Button); - zoom_out->set_accessibility_name(TTRC("Zoom Out")); - zoom_out->set_flat(true); - zoom_hbox->add_child(zoom_bar); - zoom_spacer = zoom_hbox->add_spacer(); + vbox->add_child(zoom_bar); zoom_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL); - zoom_bar->set_v_size_flags(Control::SIZE_EXPAND_FILL); - zoom_hbox->add_child(zoom_out); - zoom_hbox->add_child(zoom_reset); - zoom_hbox->add_child(zoom_in); - zoom_in->connect(SceneStringName(pressed), callable_mp(this, &AudioStreamImportSettingsDialog::_preview_zoom_in)); - zoom_reset->connect(SceneStringName(pressed), callable_mp(this, &AudioStreamImportSettingsDialog::_preview_zoom_reset)); - zoom_out->connect(SceneStringName(pressed), callable_mp(this, &AudioStreamImportSettingsDialog::_preview_zoom_out)); zoom_bar->connect(SceneStringName(value_changed), callable_mp(this, &AudioStreamImportSettingsDialog::_preview_zoom_offset_changed)); - vbox->add_child(zoom_hbox); + + HBoxContainer *hbox = memnew(HBoxContainer); + hbox->add_theme_constant_override("separation", 0); + vbox->add_child(hbox); _indicator = memnew(Control); _indicator->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); @@ -647,10 +629,6 @@ AudioStreamImportSettingsDialog::AudioStreamImportSettingsDialog() { _indicator->connect(SceneStringName(mouse_exited), callable_mp(this, &AudioStreamImportSettingsDialog::_on_indicator_mouse_exited)); _preview->add_child(_indicator); - HBoxContainer *hbox = memnew(HBoxContainer); - hbox->add_theme_constant_override("separation", 0); - vbox->add_child(hbox); - _play_button = memnew(Button); _play_button->set_accessibility_name(TTRC("Play")); _play_button->set_flat(true); @@ -672,5 +650,21 @@ AudioStreamImportSettingsDialog::AudioStreamImportSettingsDialog() { _duration_label = memnew(Label); hbox->add_child(_duration_label); + zoom_in = memnew(Button); + zoom_in->set_accessibility_name(TTRC("Zoom In")); + zoom_in->set_flat(true); + zoom_reset = memnew(Button); + zoom_reset->set_accessibility_name(TTRC("Reset Zoom")); + zoom_reset->set_flat(true); + zoom_out = memnew(Button); + zoom_out->set_accessibility_name(TTRC("Zoom Out")); + zoom_out->set_flat(true); + hbox->add_child(zoom_out); + hbox->add_child(zoom_reset); + hbox->add_child(zoom_in); + zoom_in->connect(SceneStringName(pressed), callable_mp(this, &AudioStreamImportSettingsDialog::_preview_zoom_in)); + zoom_reset->connect(SceneStringName(pressed), callable_mp(this, &AudioStreamImportSettingsDialog::_preview_zoom_reset)); + zoom_out->connect(SceneStringName(pressed), callable_mp(this, &AudioStreamImportSettingsDialog::_preview_zoom_out)); + singleton = this; } diff --git a/editor/import/audio_stream_import_settings.h b/editor/import/audio_stream_import_settings.h index 2e32cd100e..eb6ad2d5ba 100644 --- a/editor/import/audio_stream_import_settings.h +++ b/editor/import/audio_stream_import_settings.h @@ -35,7 +35,6 @@ #include "scene/gui/color_rect.h" #include "scene/gui/dialogs.h" #include "scene/gui/spin_box.h" -#include "scene/resources/texture.h" class CheckBox; @@ -59,7 +58,6 @@ class AudioStreamImportSettingsDialog : public ConfirmationDialog { Label *_duration_label = nullptr; HScrollBar *zoom_bar = nullptr; - Control *zoom_spacer = nullptr; Button *zoom_in = nullptr; Button *zoom_reset = nullptr; Button *zoom_out = nullptr; From 879059453fc239850006c06b123c164b003fef6c Mon Sep 17 00:00:00 2001 From: Haoyu Qiu Date: Tue, 29 Apr 2025 20:59:25 +0800 Subject: [PATCH 043/144] Fix double translations in Project Manager --- editor/project_manager.cpp | 1 + editor/project_manager/project_dialog.cpp | 1 + editor/project_manager/project_list.cpp | 9 ++++++--- editor/project_manager/quick_settings_dialog.cpp | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index ed6faf060a..4702a39e02 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -1504,6 +1504,7 @@ ProjectManager::ProjectManager() { project_list_panel->add_child(empty_list_placeholder); empty_list_message = memnew(RichTextLabel); + empty_list_message->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); empty_list_message->set_use_bbcode(true); empty_list_message->set_fit_content(true); empty_list_message->set_h_size_flags(SIZE_EXPAND_FILL); diff --git a/editor/project_manager/project_dialog.cpp b/editor/project_manager/project_dialog.cpp index 42bacd97d5..20f5dcad6a 100644 --- a/editor/project_manager/project_dialog.cpp +++ b/editor/project_manager/project_dialog.cpp @@ -1092,6 +1092,7 @@ ProjectDialog::ProjectDialog() { rvb->set_h_size_flags(Control::SIZE_EXPAND_FILL); rshc->add_child(rvb); renderer_info = memnew(Label); + renderer_info->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); renderer_info->set_focus_mode(Control::FOCUS_ACCESSIBILITY); renderer_info->set_modulate(Color(1, 1, 1, 0.7)); rvb->add_child(renderer_info); diff --git a/editor/project_manager/project_list.cpp b/editor/project_manager/project_list.cpp index 2967256e1e..7b3720612a 100644 --- a/editor/project_manager/project_list.cpp +++ b/editor/project_manager/project_list.cpp @@ -323,6 +323,7 @@ void ProjectListItemControl::_bind_methods() { ProjectListItemControl::ProjectListItemControl() { set_focus_mode(FocusMode::FOCUS_ALL); + set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); VBoxContainer *favorite_box = memnew(VBoxContainer); favorite_box->set_alignment(BoxContainer::ALIGNMENT_CENTER); @@ -330,8 +331,9 @@ ProjectListItemControl::ProjectListItemControl() { favorite_button = memnew(TextureButton); favorite_button->set_name("FavoriteButton"); - favorite_button->set_tooltip_text(TTR("Add to favorites")); + favorite_button->set_tooltip_text(TTRC("Add to favorites")); favorite_button->set_accessibility_name(TTRC("Add to favorites")); + favorite_button->set_auto_translate_mode(AUTO_TRANSLATE_MODE_ALWAYS); // This makes the project's "hover" style display correctly when hovering the favorite icon. favorite_button->set_mouse_filter(MOUSE_FILTER_PASS); favorite_box->add_child(favorite_button); @@ -358,7 +360,6 @@ ProjectListItemControl::ProjectListItemControl() { project_title = memnew(Label); project_title->set_focus_mode(FOCUS_ACCESSIBILITY); - project_title->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); project_title->set_name("ProjectName"); project_title->set_h_size_flags(Control::SIZE_EXPAND_FILL); project_title->set_clip_text(true); @@ -380,7 +381,8 @@ ProjectListItemControl::ProjectListItemControl() { explore_button = memnew(Button); explore_button->set_name("ExploreButton"); - explore_button->set_tooltip_text(TTR("Open in file manager")); + explore_button->set_tooltip_auto_translate_mode(AUTO_TRANSLATE_MODE_ALWAYS); + explore_button->set_tooltip_text(TTRC("Open in file manager")); explore_button->set_accessibility_name(TTRC("Open in file manager")); explore_button->set_flat(true); path_hb->add_child(explore_button); @@ -411,6 +413,7 @@ ProjectListItemControl::ProjectListItemControl() { last_edited_info->set_focus_mode(FOCUS_ACCESSIBILITY); last_edited_info->set_name("LastEditedInfo"); last_edited_info->set_mouse_filter(Control::MOUSE_FILTER_PASS); + last_edited_info->set_tooltip_auto_translate_mode(AUTO_TRANSLATE_MODE_ALWAYS); last_edited_info->set_tooltip_text(TTRC("Last edited timestamp")); last_edited_info->set_modulate(Color(1, 1, 1, 0.5)); path_hb->add_child(last_edited_info); diff --git a/editor/project_manager/quick_settings_dialog.cpp b/editor/project_manager/quick_settings_dialog.cpp index 7dff943b2d..82c95d6d72 100644 --- a/editor/project_manager/quick_settings_dialog.cpp +++ b/editor/project_manager/quick_settings_dialog.cpp @@ -30,7 +30,6 @@ #include "quick_settings_dialog.h" -#include "core/config/project_settings.h" #include "core/string/translation_server.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" @@ -281,6 +280,7 @@ QuickSettingsDialog::QuickSettingsDialog() { // Language options. { language_option_button = memnew(OptionButton); + language_option_button->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); language_option_button->set_fit_to_longest_item(false); language_option_button->connect(SceneStringName(item_selected), callable_mp(this, &QuickSettingsDialog::_language_selected)); From 21e2bac382f7804449ca4439d29a535668ea1977 Mon Sep 17 00:00:00 2001 From: LuoZhihao Date: Fri, 30 May 2025 13:35:09 +0800 Subject: [PATCH 044/144] Add missing headers in FixedVector and Span --- core/templates/fixed_vector.h | 2 ++ core/templates/span.h | 1 + 2 files changed, 3 insertions(+) diff --git a/core/templates/fixed_vector.h b/core/templates/fixed_vector.h index e1a47449b2..a7907caaec 100644 --- a/core/templates/fixed_vector.h +++ b/core/templates/fixed_vector.h @@ -30,6 +30,8 @@ #pragma once +#include "core/templates/span.h" + /** * A high performance Vector of fixed capacity. * Especially useful if you need to create an array on the stack, to diff --git a/core/templates/span.h b/core/templates/span.h index 66f0ca2e24..7d6ed50588 100644 --- a/core/templates/span.h +++ b/core/templates/span.h @@ -30,6 +30,7 @@ #pragma once +#include "core/error/error_macros.h" #include "core/typedefs.h" // Equivalent of std::span. From 70672ef0085c5e7c448e4e687c857190e66f637b Mon Sep 17 00:00:00 2001 From: Lukas Tenbrink Date: Fri, 30 May 2025 09:25:21 +0200 Subject: [PATCH 045/144] Optimize `String::get_data`, `length` and `is_empty` by making better assumptions and inlining. --- core/string/ustring.cpp | 5 ----- core/string/ustring.h | 25 ++++++++----------------- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index 9d3fe51a2c..d893d93e7d 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -745,11 +745,6 @@ signed char String::filenocasecmp_to(const String &p_str) const { return naturalnocasecmp_to_base(this_str, that_str); } -const char32_t *String::get_data() const { - static const char32_t zero = 0; - return size() ? &operator[](0) : &zero; -} - String String::_separate_compound_words() const { if (length() == 0) { return *this; diff --git a/core/string/ustring.h b/core/string/ustring.h index 88b44578be..d19fa1b462 100644 --- a/core/string/ustring.h +++ b/core/string/ustring.h @@ -177,7 +177,11 @@ class [[nodiscard]] CharStringT { public: _FORCE_INLINE_ T *ptrw() { return _cowdata.ptrw(); } _FORCE_INLINE_ const T *ptr() const { return _cowdata.ptr(); } + _FORCE_INLINE_ const T *get_data() const { return ptr() ? ptr() : &_null; } + _FORCE_INLINE_ int size() const { return _cowdata.size(); } + _FORCE_INLINE_ int length() const { return ptr() ? size() - 1 : 0; } + _FORCE_INLINE_ bool is_empty() const { return length() == 0; } _FORCE_INLINE_ operator Span() const { return Span(ptr(), length()); } _FORCE_INLINE_ Span span() const { return Span(ptr(), length()); } @@ -226,14 +230,6 @@ public: return *this; } - _FORCE_INLINE_ int length() const { return size() ? size() - 1 : 0; } - _FORCE_INLINE_ const T *get_data() const { - if (size()) { - return &operator[](0); - } - return &_null; - } - protected: void copy_from(const T *p_cstr) { if (!p_cstr) { @@ -313,7 +309,11 @@ public: _FORCE_INLINE_ char32_t *ptrw() { return _cowdata.ptrw(); } _FORCE_INLINE_ const char32_t *ptr() const { return _cowdata.ptr(); } + _FORCE_INLINE_ const char32_t *get_data() const { return ptr() ? ptr() : &_null; } + _FORCE_INLINE_ int size() const { return _cowdata.size(); } + _FORCE_INLINE_ int length() const { return ptr() ? size() - 1 : 0; } + _FORCE_INLINE_ bool is_empty() const { return length() == 0; } _FORCE_INLINE_ operator Span() const { return Span(ptr(), length()); } _FORCE_INLINE_ Span span() const { return Span(ptr(), length()); } @@ -377,14 +377,6 @@ public: signed char filecasecmp_to(const String &p_str) const; signed char filenocasecmp_to(const String &p_str) const; - const char32_t *get_data() const; - /* standard size stuff */ - - _FORCE_INLINE_ int length() const { - int s = size(); - return s ? (s - 1) : 0; // length does not include zero - } - bool is_valid_string() const; /* debug, error messages */ @@ -587,7 +579,6 @@ public: Vector sha1_buffer() const; Vector sha256_buffer() const; - _FORCE_INLINE_ bool is_empty() const { return length() == 0; } _FORCE_INLINE_ bool contains(const char *p_str) const { return find(p_str) != -1; } _FORCE_INLINE_ bool contains(const String &p_str) const { return find(p_str) != -1; } _FORCE_INLINE_ bool contains_char(char32_t p_chr) const { return find_char(p_chr) != -1; } From b3ddb8803594191338078925bd8e1e45bdde62f3 Mon Sep 17 00:00:00 2001 From: Mikael Hermansson Date: Wed, 28 May 2025 19:48:30 +0200 Subject: [PATCH 046/144] Fix Area3D signal emissions when using Jolt Physics --- modules/jolt_physics/objects/jolt_area_3d.cpp | 28 +++++++++----- modules/jolt_physics/objects/jolt_area_3d.h | 7 ++++ .../objects/jolt_shaped_object_3d.cpp | 5 ++- .../spaces/jolt_contact_listener_3d.cpp | 38 +++++-------------- .../spaces/jolt_contact_listener_3d.h | 1 - 5 files changed, 40 insertions(+), 39 deletions(-) diff --git a/modules/jolt_physics/objects/jolt_area_3d.cpp b/modules/jolt_physics/objects/jolt_area_3d.cpp index 2a7f706ca0..1c89c93a61 100644 --- a/modules/jolt_physics/objects/jolt_area_3d.cpp +++ b/modules/jolt_physics/objects/jolt_area_3d.cpp @@ -113,12 +113,14 @@ void JoltArea3D::_add_shape_pair(Overlap &p_overlap, const JPH::BodyID &p_body_i p_overlap.rid = other_object->get_rid(); p_overlap.instance_id = other_object->get_instance_id(); - ShapeIndexPair &shape_indices = p_overlap.shape_pairs[{ p_other_shape_id, p_self_shape_id }]; + HashMap::Iterator shape_pair = p_overlap.shape_pairs.find(ShapeIDPair(p_other_shape_id, p_self_shape_id)); + if (shape_pair == p_overlap.shape_pairs.end()) { + const int other_shape_index = other_object->find_shape_index(p_other_shape_id); + const int self_shape_index = find_shape_index(p_self_shape_id); + shape_pair = p_overlap.shape_pairs.insert(ShapeIDPair(p_other_shape_id, p_self_shape_id), ShapeIndexPair(other_shape_index, self_shape_index)); + } - shape_indices.other = other_object->find_shape_index(p_other_shape_id); - shape_indices.self = find_shape_index(p_self_shape_id); - - p_overlap.pending_added.push_back(shape_indices); + p_overlap.pending_added.push_back(shape_pair->value); _events_changed(); } @@ -143,12 +145,20 @@ void JoltArea3D::_flush_events(OverlapsById &p_objects, const Callable &p_callba Overlap &overlap = E->value; if (p_callback.is_valid()) { - for (ShapeIndexPair &shape_indices : overlap.pending_removed) { - _report_event(p_callback, PhysicsServer3D::AREA_BODY_REMOVED, overlap.rid, overlap.instance_id, shape_indices.other, shape_indices.self); + for (const ShapeIndexPair &shape_indices : overlap.pending_added) { + int &ref_count = overlap.ref_counts[shape_indices]; + if (ref_count++ == 0) { + _report_event(p_callback, PhysicsServer3D::AREA_BODY_ADDED, overlap.rid, overlap.instance_id, shape_indices.other, shape_indices.self); + } } - for (ShapeIndexPair &shape_indices : overlap.pending_added) { - _report_event(p_callback, PhysicsServer3D::AREA_BODY_ADDED, overlap.rid, overlap.instance_id, shape_indices.other, shape_indices.self); + for (const ShapeIndexPair &shape_indices : overlap.pending_removed) { + int &ref_count = overlap.ref_counts[shape_indices]; + ERR_CONTINUE(ref_count <= 0); + if (--ref_count == 0) { + _report_event(p_callback, PhysicsServer3D::AREA_BODY_REMOVED, overlap.rid, overlap.instance_id, shape_indices.other, shape_indices.self); + overlap.ref_counts.erase(shape_indices); + } } } diff --git a/modules/jolt_physics/objects/jolt_area_3d.h b/modules/jolt_physics/objects/jolt_area_3d.h index d4cd5ec05c..d014105f11 100644 --- a/modules/jolt_physics/objects/jolt_area_3d.h +++ b/modules/jolt_physics/objects/jolt_area_3d.h @@ -73,6 +73,12 @@ private: ShapeIndexPair(int p_other, int p_self) : other(p_other), self(p_self) {} + static uint32_t hash(const ShapeIndexPair &p_pair) { + uint32_t hash = hash_murmur3_one_32(p_pair.other); + hash = hash_murmur3_one_32(p_pair.self, hash); + return hash_fmix32(hash); + } + friend bool operator==(const ShapeIndexPair &p_lhs, const ShapeIndexPair &p_rhs) { return (p_lhs.other == p_rhs.other) && (p_lhs.self == p_rhs.self); } @@ -80,6 +86,7 @@ private: struct Overlap { HashMap shape_pairs; + HashMap ref_counts; LocalVector pending_added; LocalVector pending_removed; RID rid; diff --git a/modules/jolt_physics/objects/jolt_shaped_object_3d.cpp b/modules/jolt_physics/objects/jolt_shaped_object_3d.cpp index 5f40c32524..9ac43699d8 100644 --- a/modules/jolt_physics/objects/jolt_shaped_object_3d.cpp +++ b/modules/jolt_physics/objects/jolt_shaped_object_3d.cpp @@ -304,7 +304,10 @@ void JoltShapedObject3D::commit_shapes(bool p_optimize_compound) { return; } - previous_jolt_shape = jolt_shape; + if (previous_jolt_shape == nullptr) { + previous_jolt_shape = jolt_shape; + } + jolt_shape = new_shape; space->get_body_iface().SetShape(jolt_body->GetID(), jolt_shape, false, JPH::EActivation::DontActivate); diff --git a/modules/jolt_physics/spaces/jolt_contact_listener_3d.cpp b/modules/jolt_physics/spaces/jolt_contact_listener_3d.cpp index 226244b984..64a4d4214c 100644 --- a/modules/jolt_physics/spaces/jolt_contact_listener_3d.cpp +++ b/modules/jolt_physics/spaces/jolt_contact_listener_3d.cpp @@ -246,13 +246,22 @@ bool JoltContactListener3D::_try_evaluate_area_overlap(const JPH::Body &p_body1, return false; } - auto evaluate = [&](const auto &p_area, const auto &p_object, const JPH::SubShapeIDPair &p_shape_pair) { + auto has_shifted = [](const JoltShapedObject3D &p_object, const JPH::SubShapeID &p_sub_shape_id) { + return p_object.get_previous_jolt_shape() != nullptr && p_object.get_jolt_shape()->GetSubShapeUserData(p_sub_shape_id) != p_object.get_previous_jolt_shape()->GetSubShapeUserData(p_sub_shape_id); + }; + + auto evaluate = [&](const JoltArea3D &p_area, const auto &p_object, const JPH::SubShapeIDPair &p_shape_pair) { const MutexLock write_lock(write_mutex); if (p_area.can_monitor(p_object)) { if (!area_overlaps.has(p_shape_pair)) { area_overlaps.insert(p_shape_pair); area_enters.insert(p_shape_pair); + } else if (has_shifted(p_area, p_shape_pair.GetSubShapeID1()) || has_shifted(p_object, p_shape_pair.GetSubShapeID2())) { + // A shape has taken on the `JPH::SubShapeID` value of another shape, likely because of the other shape having been replaced or moved + // in some way, so we force the area to refresh its internal mappings by exiting and entering this shape pair. + area_exits.insert(p_shape_pair); + area_enters.insert(p_shape_pair); } } else { if (area_overlaps.erase(p_shape_pair)) { @@ -456,32 +465,6 @@ void JoltContactListener3D::_flush_area_enters() { area_enters.clear(); } -void JoltContactListener3D::_flush_area_shifts() { - for (const JPH::SubShapeIDPair &shape_pair : area_overlaps) { - auto is_shifted = [&](const JPH::BodyID &p_body_id, const JPH::SubShapeID &p_sub_shape_id) { - const JoltShapedObject3D *object = space->try_get_shaped(p_body_id); - ERR_FAIL_NULL_V(object, false); - - if (object->get_previous_jolt_shape() == nullptr) { - return false; - } - - const JPH::Shape ¤t_shape = *object->get_jolt_shape(); - const JPH::Shape &previous_shape = *object->get_previous_jolt_shape(); - - const uint32_t current_id = (uint32_t)current_shape.GetSubShapeUserData(p_sub_shape_id); - const uint32_t previous_id = (uint32_t)previous_shape.GetSubShapeUserData(p_sub_shape_id); - - return current_id != previous_id; - }; - - if (is_shifted(shape_pair.GetBody1ID(), shape_pair.GetSubShapeID1()) || is_shifted(shape_pair.GetBody2ID(), shape_pair.GetSubShapeID2())) { - area_enters.insert(shape_pair); - area_exits.insert(shape_pair); - } - } -} - void JoltContactListener3D::_flush_area_exits() { for (const JPH::SubShapeIDPair &shape_pair : area_exits) { const JPH::BodyID &body_id1 = shape_pair.GetBody1ID(); @@ -523,7 +506,6 @@ void JoltContactListener3D::pre_step() { void JoltContactListener3D::post_step() { _flush_contacts(); - _flush_area_shifts(); _flush_area_exits(); _flush_area_enters(); } diff --git a/modules/jolt_physics/spaces/jolt_contact_listener_3d.h b/modules/jolt_physics/spaces/jolt_contact_listener_3d.h index 7a32e3a520..ad4ce475c9 100644 --- a/modules/jolt_physics/spaces/jolt_contact_listener_3d.h +++ b/modules/jolt_physics/spaces/jolt_contact_listener_3d.h @@ -120,7 +120,6 @@ class JoltContactListener3D final void _flush_contacts(); void _flush_area_enters(); - void _flush_area_shifts(); void _flush_area_exits(); public: From bc6f0d29ccf521f54b7439d02304d7cc1d852736 Mon Sep 17 00:00:00 2001 From: kobewi Date: Fri, 30 May 2025 00:10:53 +0200 Subject: [PATCH 047/144] Improve auto-translation of main screens --- editor/plugins/canvas_item_editor_plugin.cpp | 79 ++--- editor/plugins/game_view_plugin.cpp | 70 +++-- editor/plugins/node_3d_editor_plugin.cpp | 294 ++++++++++--------- 3 files changed, 241 insertions(+), 202 deletions(-) diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 33aa76fa94..6a29cf8888 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -98,7 +98,7 @@ public: VBoxContainer *container; GridContainer *child_container; - set_title(TTR("Configure Snap")); + set_title(TTRC("Configure Snap")); container = memnew(VBoxContainer); add_child(container); @@ -108,7 +108,7 @@ public: container->add_child(child_container); label = memnew(Label); - label->set_text(TTR("Grid Offset:")); + label->set_text(TTRC("Grid Offset:")); child_container->add_child(label); label->set_h_size_flags(Control::SIZE_EXPAND_FILL); @@ -135,7 +135,7 @@ public: child_container->add_child(grid_offset_y); label = memnew(Label); - label->set_text(TTR("Grid Step:")); + label->set_text(TTRC("Grid Step:")); child_container->add_child(label); label->set_h_size_flags(Control::SIZE_EXPAND_FILL); @@ -160,7 +160,7 @@ public: child_container->add_child(grid_step_y); label = memnew(Label); - label->set_text(TTR("Primary Line Every:")); + label->set_text(TTRC("Primary Line Every:")); label->set_h_size_flags(Control::SIZE_EXPAND_FILL); child_container->add_child(label); @@ -180,7 +180,7 @@ public: primary_grid_step_y->set_step(1); primary_grid_step_y->set_max(SPIN_BOX_GRID_RANGE); primary_grid_step_y->set_allow_greater(true); - primary_grid_step_y->set_suffix("steps"); + primary_grid_step_y->set_suffix(TTRC("steps")); // TODO: Add suffix auto-translation. primary_grid_step_y->set_h_size_flags(Control::SIZE_EXPAND_FILL); primary_grid_step_y->set_select_all_on_focus(true); primary_grid_step_y->set_accessibility_name(TTRC("Y Primary Step")); @@ -195,28 +195,28 @@ public: container->add_child(child_container); label = memnew(Label); - label->set_text(TTR("Rotation Offset:")); + label->set_text(TTRC("Rotation Offset:")); child_container->add_child(label); label->set_h_size_flags(Control::SIZE_EXPAND_FILL); rotation_offset = memnew(SpinBox); rotation_offset->set_min(-SPIN_BOX_ROTATION_RANGE); rotation_offset->set_max(SPIN_BOX_ROTATION_RANGE); - rotation_offset->set_suffix("deg"); + rotation_offset->set_suffix(U"°"); rotation_offset->set_h_size_flags(Control::SIZE_EXPAND_FILL); rotation_offset->set_select_all_on_focus(true); rotation_offset->set_accessibility_name(TTRC("Rotation Offset")); child_container->add_child(rotation_offset); label = memnew(Label); - label->set_text(TTR("Rotation Step:")); + label->set_text(TTRC("Rotation Step:")); child_container->add_child(label); label->set_h_size_flags(Control::SIZE_EXPAND_FILL); rotation_step = memnew(SpinBox); rotation_step->set_min(-SPIN_BOX_ROTATION_RANGE); rotation_step->set_max(SPIN_BOX_ROTATION_RANGE); - rotation_step->set_suffix("deg"); + rotation_step->set_suffix(U"°"); rotation_step->set_h_size_flags(Control::SIZE_EXPAND_FILL); rotation_step->set_select_all_on_focus(true); rotation_step->set_accessibility_name(TTRC("Rotation Step")); @@ -228,7 +228,7 @@ public: child_container->set_columns(2); container->add_child(child_container); label = memnew(Label); - label->set_text(TTR("Scale Step:")); + label->set_text(TTRC("Scale Step:")); child_container->add_child(label); label->set_h_size_flags(Control::SIZE_EXPAND_FILL); @@ -2479,17 +2479,17 @@ bool CanvasItemEditor::_gui_input_select(const Ref &p_event) { if (b.is_valid() && b->is_pressed() && b->get_button_index() == MouseButton::RIGHT) { add_node_menu->clear(); - add_node_menu->add_icon_item(get_editor_theme_icon(SNAME("Add")), TTR("Add Node Here..."), ADD_NODE); - add_node_menu->add_icon_item(get_editor_theme_icon(SNAME("Instance")), TTR("Instantiate Scene Here..."), ADD_INSTANCE); + add_node_menu->add_icon_item(get_editor_theme_icon(SNAME("Add")), TTRC("Add Node Here..."), ADD_NODE); + add_node_menu->add_icon_item(get_editor_theme_icon(SNAME("Instance")), TTRC("Instantiate Scene Here..."), ADD_INSTANCE); for (Node *node : SceneTreeDock::get_singleton()->get_node_clipboard()) { if (Object::cast_to(node)) { - add_node_menu->add_icon_item(get_editor_theme_icon(SNAME("ActionPaste")), TTR("Paste Node(s) Here"), ADD_PASTE); + add_node_menu->add_icon_item(get_editor_theme_icon(SNAME("ActionPaste")), TTRC("Paste Node(s) Here"), ADD_PASTE); break; } } for (Node *node : EditorNode::get_singleton()->get_editor_selection()->get_top_selected_node_list()) { if (Object::cast_to(node)) { - add_node_menu->add_icon_item(get_editor_theme_icon(SNAME("ToolMove")), TTR("Move Node(s) Here"), ADD_MOVE); + add_node_menu->add_icon_item(get_editor_theme_icon(SNAME("ToolMove")), TTRC("Move Node(s) Here"), ADD_MOVE); break; } } @@ -4140,6 +4140,11 @@ void CanvasItemEditor::_project_settings_changed() { void CanvasItemEditor::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_TRANSLATION_CHANGED: { + select_button->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+Drag: Move selected node.") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Alt+Drag: Scale selected node.") + "\n" + TTR("V: Set selected node's pivot position.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.") + "\n" + TTR("(Available in all modes.)") + "\n" + TTR("RMB: Add node at position clicked.")); + pivot_button->set_tooltip_text(TTR("Click to change object's pivot.") + "\n" + TTR("Shift: Set temporary pivot.") + "\n" + TTR("Click this button while holding Shift to put the temporary pivot in the center of the selected nodes.")); + } break; + case NOTIFICATION_READY: { _update_lock_and_group_button(); @@ -5430,6 +5435,7 @@ CanvasItemEditor::CanvasItemEditor() { viewport->add_child(controls_vb); select_button = memnew(Button); + select_button->set_tooltip_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); select_button->set_theme_type_variation(SceneStringName(FlatButton)); main_menu_hbox->add_child(select_button); select_button->set_toggle_mode(true); @@ -5437,7 +5443,6 @@ CanvasItemEditor::CanvasItemEditor() { select_button->set_pressed(true); select_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/select_mode", TTRC("Select Mode"), Key::Q, true)); select_button->set_shortcut_context(this); - select_button->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+Drag: Move selected node.") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Alt+Drag: Scale selected node.") + "\n" + TTR("V: Set selected node's pivot position.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.") + "\n" + TTR("(Available in all modes.)") + "\n" + TTR("RMB: Add node at position clicked.")); select_button->set_accessibility_name(TTRC("Select Mode")); main_menu_hbox->add_child(memnew(VSeparator)); @@ -5479,15 +5484,15 @@ CanvasItemEditor::CanvasItemEditor() { main_menu_hbox->add_child(list_select_button); list_select_button->set_toggle_mode(true); list_select_button->connect(SceneStringName(pressed), callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_LIST_SELECT)); - list_select_button->set_tooltip_text(TTR("Show list of selectable nodes at position clicked.")); + list_select_button->set_tooltip_text(TTRC("Show list of selectable nodes at position clicked.")); list_select_button->set_accessibility_name(TTRC("List Selectable Nodes")); pivot_button = memnew(Button); + pivot_button->set_tooltip_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); pivot_button->set_theme_type_variation(SceneStringName(FlatButton)); main_menu_hbox->add_child(pivot_button); pivot_button->set_toggle_mode(true); pivot_button->connect(SceneStringName(pressed), callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_EDIT_PIVOT)); - pivot_button->set_tooltip_text(TTR("Click to change object's pivot.") + "\n" + TTR("Shift: Set temporary pivot.") + "\n" + TTR("Click this button while holding Shift to put the temporary pivot in the center of the selected nodes.")); pivot_button->set_accessibility_name(TTRC("Change Pivot")); pan_button = memnew(Button); @@ -5538,7 +5543,7 @@ CanvasItemEditor::CanvasItemEditor() { snap_config_menu->set_shortcut_context(this); main_menu_hbox->add_child(snap_config_menu); snap_config_menu->set_h_size_flags(SIZE_SHRINK_END); - snap_config_menu->set_tooltip_text(TTR("Snapping Options")); + snap_config_menu->set_tooltip_text(TTRC("Snapping Options")); snap_config_menu->set_switch_on_hover(true); snap_config_menu->set_accessibility_name(TTRC("Snapping Options")); @@ -5559,7 +5564,7 @@ CanvasItemEditor::CanvasItemEditor() { smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_center", TTRC("Snap to Node Center")), SNAP_USE_NODE_CENTER); smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_other_nodes", TTRC("Snap to Other Nodes")), SNAP_USE_OTHER_NODES); smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_guides", TTRC("Snap to Guides")), SNAP_USE_GUIDES); - p->add_submenu_node_item(TTR("Smart Snapping"), smartsnap_config_popup); + p->add_submenu_node_item(TTRC("Smart Snapping"), smartsnap_config_popup); p->add_separator(); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/configure_snap", TTRC("Configure Snap...")), SNAP_CONFIGURE); @@ -5610,7 +5615,7 @@ CanvasItemEditor::CanvasItemEditor() { skeleton_menu->set_theme_type_variation("FlatMenuButton"); skeleton_menu->set_shortcut_context(this); main_menu_hbox->add_child(skeleton_menu); - skeleton_menu->set_tooltip_text(TTR("Skeleton Options")); + skeleton_menu->set_tooltip_text(TTRC("Skeleton Options")); skeleton_menu->set_switch_on_hover(true); skeleton_menu->set_accessibility_name(TTRC("Skeleton Options")); @@ -5627,7 +5632,7 @@ CanvasItemEditor::CanvasItemEditor() { view_menu->set_flat(false); view_menu->set_theme_type_variation("FlatMenuButton"); // TRANSLATORS: Noun, name of the 2D/3D View menus. - view_menu->set_text(TTR("View")); + view_menu->set_text(TTRC("View")); view_menu->set_switch_on_hover(true); view_menu->set_shortcut_context(this); main_menu_hbox->add_child(view_menu); @@ -5640,12 +5645,12 @@ CanvasItemEditor::CanvasItemEditor() { grid_menu = memnew(PopupMenu); grid_menu->connect("about_to_popup", callable_mp(this, &CanvasItemEditor::_prepare_grid_menu)); grid_menu->connect(SceneStringName(id_pressed), callable_mp(this, &CanvasItemEditor::_on_grid_menu_id_pressed)); - grid_menu->add_radio_check_item(TTR("Show"), GRID_VISIBILITY_SHOW); - grid_menu->add_radio_check_item(TTR("Show When Snapping"), GRID_VISIBILITY_SHOW_WHEN_SNAPPING); - grid_menu->add_radio_check_item(TTR("Hide"), GRID_VISIBILITY_HIDE); + grid_menu->add_radio_check_item(TTRC("Show"), GRID_VISIBILITY_SHOW); + grid_menu->add_radio_check_item(TTRC("Show When Snapping"), GRID_VISIBILITY_SHOW_WHEN_SNAPPING); + grid_menu->add_radio_check_item(TTRC("Hide"), GRID_VISIBILITY_HIDE); grid_menu->add_separator(); grid_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/toggle_grid", TTRC("Toggle Grid"), KeyModifierMask::CMD_OR_CTRL | Key::APOSTROPHE)); - p->add_submenu_node_item(TTR("Grid"), grid_menu); + p->add_submenu_node_item(TTRC("Grid"), grid_menu); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_helpers", TTRC("Show Helpers"), Key::H), SHOW_HELPERS); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_rulers", TTRC("Show Rulers")), SHOW_RULERS); @@ -5663,7 +5668,7 @@ CanvasItemEditor::CanvasItemEditor() { gizmos_menu->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_group_gizmos", TTRC("Group")), SHOW_GROUP_GIZMOS); gizmos_menu->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_transformation_gizmos", TTRC("Transformation")), SHOW_TRANSFORMATION_GIZMOS); p->add_child(gizmos_menu); - p->add_submenu_item(TTR("Gizmos"), "GizmosMenu"); + p->add_submenu_item(TTRC("Gizmos"), "GizmosMenu"); p->add_separator(); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/center_selection", TTRC("Center Selection"), Key::F), VIEW_CENTER_TO_SELECTION); @@ -5674,10 +5679,10 @@ CanvasItemEditor::CanvasItemEditor() { theme_menu = memnew(PopupMenu); theme_menu->connect(SceneStringName(id_pressed), callable_mp(this, &CanvasItemEditor::_switch_theme_preview)); - theme_menu->add_radio_check_item(TTR("Project theme"), THEME_PREVIEW_PROJECT); - theme_menu->add_radio_check_item(TTR("Editor theme"), THEME_PREVIEW_EDITOR); - theme_menu->add_radio_check_item(TTR("Default theme"), THEME_PREVIEW_DEFAULT); - p->add_submenu_node_item(TTR("Preview Theme"), theme_menu); + theme_menu->add_radio_check_item(TTRC("Project theme"), THEME_PREVIEW_PROJECT); + theme_menu->add_radio_check_item(TTRC("Editor theme"), THEME_PREVIEW_EDITOR); + theme_menu->add_radio_check_item(TTRC("Default theme"), THEME_PREVIEW_DEFAULT); + p->add_submenu_node_item(TTRC("Preview Theme"), theme_menu); theme_preview = (ThemePreviewMode)(int)EditorSettings::get_singleton()->get_project_metadata("2d_editor", "theme_preview", THEME_PREVIEW_PROJECT); for (int i = 0; i < THEME_PREVIEW_MAX; i++) { @@ -5705,7 +5710,7 @@ CanvasItemEditor::CanvasItemEditor() { key_loc_button->set_pressed(true); key_loc_button->set_focus_mode(FOCUS_NONE); key_loc_button->connect(SceneStringName(pressed), callable_mp(this, &CanvasItemEditor::_popup_callback).bind(ANIM_INSERT_POS)); - key_loc_button->set_tooltip_text(TTR("Translation mask for inserting keys.")); + key_loc_button->set_tooltip_text(TTRC("Translation mask for inserting keys.")); key_loc_button->set_accessibility_name(TTRC("Translation Mask")); animation_hb->add_child(key_loc_button); @@ -5715,7 +5720,7 @@ CanvasItemEditor::CanvasItemEditor() { key_rot_button->set_pressed(true); key_rot_button->set_focus_mode(FOCUS_NONE); key_rot_button->connect(SceneStringName(pressed), callable_mp(this, &CanvasItemEditor::_popup_callback).bind(ANIM_INSERT_ROT)); - key_rot_button->set_tooltip_text(TTR("Rotation mask for inserting keys.")); + key_rot_button->set_tooltip_text(TTRC("Rotation mask for inserting keys.")); key_rot_button->set_accessibility_name(TTRC("Rotation Mask")); animation_hb->add_child(key_rot_button); @@ -5724,7 +5729,7 @@ CanvasItemEditor::CanvasItemEditor() { key_scale_button->set_toggle_mode(true); key_scale_button->set_focus_mode(FOCUS_NONE); key_scale_button->connect(SceneStringName(pressed), callable_mp(this, &CanvasItemEditor::_popup_callback).bind(ANIM_INSERT_SCALE)); - key_scale_button->set_tooltip_text(TTR("Scale mask for inserting keys.")); + key_scale_button->set_tooltip_text(TTRC("Scale mask for inserting keys.")); key_scale_button->set_accessibility_name(TTRC("Scale Mask")); animation_hb->add_child(key_scale_button); @@ -5752,7 +5757,7 @@ CanvasItemEditor::CanvasItemEditor() { animation_menu->set_flat(false); animation_menu->set_theme_type_variation("FlatMenuButton"); animation_menu->set_shortcut_context(this); - animation_menu->set_tooltip_text(TTR("Animation Key and Pose Options")); + animation_menu->set_tooltip_text(TTRC("Animation Key and Pose Options")); animation_menu->set_accessibility_name(TTRC("Animation Key and Pose")); animation_hb->add_child(animation_menu); animation_menu->get_popup()->connect(SceneStringName(id_pressed), callable_mp(this, &CanvasItemEditor::_popup_callback)); @@ -6427,7 +6432,6 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(CanvasItemEditor *p_canvas_it texture_node_type_selector = memnew(AcceptDialog); EditorNode::get_singleton()->get_gui_base()->add_child(texture_node_type_selector); - texture_node_type_selector->set_title(TTR("Change Default Type")); texture_node_type_selector->connect(SceneStringName(confirmed), callable_mp(this, &CanvasItemEditorViewport::_on_change_type_confirmed)); texture_node_type_selector->connect("canceled", callable_mp(this, &CanvasItemEditorViewport::_on_change_type_closed)); @@ -6444,10 +6448,11 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(CanvasItemEditor *p_canvas_it button_group.instantiate(); for (int i = 0; i < texture_node_types.size(); i++) { CheckBox *check = memnew(CheckBox); - btn_group->add_child(check); check->set_text(texture_node_types[i]); - check->connect("button_down", callable_mp(this, &CanvasItemEditorViewport::_on_select_texture_node_type).bind(check)); + check->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); check->set_button_group(button_group); + btn_group->add_child(check); + check->connect("button_down", callable_mp(this, &CanvasItemEditorViewport::_on_select_texture_node_type).bind(check)); } label = memnew(Label); diff --git a/editor/plugins/game_view_plugin.cpp b/editor/plugins/game_view_plugin.cpp index d39139d21f..43ef9413db 100644 --- a/editor/plugins/game_view_plugin.cpp +++ b/editor/plugins/game_view_plugin.cpp @@ -386,7 +386,7 @@ void GameView::_embedding_completed() { } void GameView::_embedding_failed() { - state_label->set_text(TTR("Connection impossible to the game process.")); + state_label->set_text(TTRC("Connection impossible to the game process.")); } void GameView::_embedded_process_updated() { @@ -555,20 +555,20 @@ void GameView::_update_ui() { state_label->set_text(""); show_game_size = true; } else if (embedded_process->is_embedding_in_progress()) { - state_label->set_text(TTR("Game starting...")); + state_label->set_text(TTRC("Game starting...")); } else if (EditorRunBar::get_singleton()->is_playing()) { - state_label->set_text(TTR("Game running not embedded.")); + state_label->set_text(TTRC("Game running not embedded.")); } else if (embed_on_play) { - state_label->set_text(TTR("Press play to start the game.")); + state_label->set_text(TTRC("Press play to start the game.")); } else { - state_label->set_text(TTR("Embedding is disabled.")); + state_label->set_text(TTRC("Embedding is disabled.")); } break; case EMBED_NOT_AVAILABLE_FEATURE_NOT_SUPPORTED: if (DisplayServer::get_singleton()->get_name() == "Wayland") { - state_label->set_text(TTR("Game embedding not available on Wayland.\nWayland can be disabled in the Editor Settings (Run > Platforms > Linux/*BSD > Prefer Wayland).")); + state_label->set_text(TTRC("Game embedding not available on Wayland.\nWayland can be disabled in the Editor Settings (Run > Platforms > Linux/*BSD > Prefer Wayland).")); } else { - state_label->set_text(TTR("Game embedding not available on your OS.")); + state_label->set_text(TTRC("Game embedding not available on your OS.")); } break; case EMBED_NOT_AVAILABLE_PROJECT_DISPLAY_DRIVER: @@ -584,7 +584,7 @@ void GameView::_update_ui() { state_label->set_text(TTR("Game embedding not available when the game starts in fullscreen.") + "\n" + TTR("Consider overriding the window mode project setting with the editor feature tag to Windowed to use game embedding while leaving the exported project intact.")); break; case EMBED_NOT_AVAILABLE_SINGLE_WINDOW_MODE: - state_label->set_text(TTR("Game embedding not available in single window mode.")); + state_label->set_text(TTRC("Game embedding not available in single window mode.")); break; } @@ -692,6 +692,11 @@ void GameView::_camera_override_menu_id_pressed(int p_id) { void GameView::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_TRANSLATION_CHANGED: { + select_mode_button[RuntimeNodeSelect::SELECT_MODE_SINGLE]->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Alt+RMB: Show list of all nodes at position clicked.")); + _update_ui(); + } break; + case NOTIFICATION_THEME_CHANGED: { suspend_button->set_button_icon(get_editor_theme_icon(SNAME("Pause"))); next_frame_button->set_button_icon(get_editor_theme_icon(SNAME("NextFrame"))); @@ -976,7 +981,6 @@ GameView::GameView(Ref p_debugger, EmbeddedProcessBase *p_embe suspend_button->set_toggle_mode(true); suspend_button->set_theme_type_variation(SceneStringName(FlatButton)); suspend_button->connect(SceneStringName(toggled), callable_mp(this, &GameView::_suspend_button_toggled)); - suspend_button->set_tooltip_text(TTR("Suspend")); suspend_button->set_accessibility_name(TTRC("Suspend")); ED_SHORTCUT("editor/suspend_resume_embedded_project", TTRC("Suspend/Resume Embedded Project"), Key::F9); ED_SHORTCUT_OVERRIDE("editor/suspend_resume_embedded_project", "macos", KeyModifierMask::META | KeyModifierMask::SHIFT | Key::B); @@ -986,7 +990,6 @@ GameView::GameView(Ref p_debugger, EmbeddedProcessBase *p_embe main_menu_hbox->add_child(next_frame_button); next_frame_button->set_theme_type_variation(SceneStringName(FlatButton)); next_frame_button->connect(SceneStringName(pressed), callable_mp(*debugger, &GameViewDebugger::next_frame)); - next_frame_button->set_tooltip_text(TTR("Next Frame")); next_frame_button->set_accessibility_name(TTRC("Next Frame")); next_frame_button->set_shortcut(ED_SHORTCUT("editor/next_frame_embedded_project", TTRC("Next Frame"), Key::F10)); @@ -994,28 +997,28 @@ GameView::GameView(Ref p_debugger, EmbeddedProcessBase *p_embe node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE] = memnew(Button); main_menu_hbox->add_child(node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]); - node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]->set_text(TTR("Input")); + node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]->set_text(TTRC("Input")); node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]->set_toggle_mode(true); node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]->set_pressed(true); node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]->set_theme_type_variation(SceneStringName(FlatButton)); node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]->connect(SceneStringName(pressed), callable_mp(this, &GameView::_node_type_pressed).bind(RuntimeNodeSelect::NODE_TYPE_NONE)); - node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]->set_tooltip_text(TTR("Allow game input.")); + node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]->set_tooltip_text(TTRC("Allow game input.")); node_type_button[RuntimeNodeSelect::NODE_TYPE_2D] = memnew(Button); main_menu_hbox->add_child(node_type_button[RuntimeNodeSelect::NODE_TYPE_2D]); - node_type_button[RuntimeNodeSelect::NODE_TYPE_2D]->set_text(TTR("2D")); + node_type_button[RuntimeNodeSelect::NODE_TYPE_2D]->set_text(TTRC("2D")); node_type_button[RuntimeNodeSelect::NODE_TYPE_2D]->set_toggle_mode(true); node_type_button[RuntimeNodeSelect::NODE_TYPE_2D]->set_theme_type_variation(SceneStringName(FlatButton)); node_type_button[RuntimeNodeSelect::NODE_TYPE_2D]->connect(SceneStringName(pressed), callable_mp(this, &GameView::_node_type_pressed).bind(RuntimeNodeSelect::NODE_TYPE_2D)); - node_type_button[RuntimeNodeSelect::NODE_TYPE_2D]->set_tooltip_text(TTR("Disable game input and allow to select Node2Ds, Controls, and manipulate the 2D camera.")); + node_type_button[RuntimeNodeSelect::NODE_TYPE_2D]->set_tooltip_text(TTRC("Disable game input and allow to select Node2Ds, Controls, and manipulate the 2D camera.")); node_type_button[RuntimeNodeSelect::NODE_TYPE_3D] = memnew(Button); main_menu_hbox->add_child(node_type_button[RuntimeNodeSelect::NODE_TYPE_3D]); - node_type_button[RuntimeNodeSelect::NODE_TYPE_3D]->set_text(TTR("3D")); + node_type_button[RuntimeNodeSelect::NODE_TYPE_3D]->set_text(TTRC("3D")); node_type_button[RuntimeNodeSelect::NODE_TYPE_3D]->set_toggle_mode(true); node_type_button[RuntimeNodeSelect::NODE_TYPE_3D]->set_theme_type_variation(SceneStringName(FlatButton)); node_type_button[RuntimeNodeSelect::NODE_TYPE_3D]->connect(SceneStringName(pressed), callable_mp(this, &GameView::_node_type_pressed).bind(RuntimeNodeSelect::NODE_TYPE_3D)); - node_type_button[RuntimeNodeSelect::NODE_TYPE_3D]->set_tooltip_text(TTR("Disable game input and allow to select Node3Ds and manipulate the 3D camera.")); + node_type_button[RuntimeNodeSelect::NODE_TYPE_3D]->set_tooltip_text(TTRC("Disable game input and allow to select Node3Ds and manipulate the 3D camera.")); main_menu_hbox->add_child(memnew(VSeparator)); @@ -1024,7 +1027,7 @@ GameView::GameView(Ref p_debugger, EmbeddedProcessBase *p_embe hide_selection->set_toggle_mode(true); hide_selection->set_theme_type_variation(SceneStringName(FlatButton)); hide_selection->connect(SceneStringName(toggled), callable_mp(this, &GameView::_hide_selection_toggled)); - hide_selection->set_tooltip_text(TTR("Toggle Selection Visibility")); + hide_selection->set_tooltip_text(TTRC("Toggle Selection Visibility")); hide_selection->set_accessibility_name(TTRC("Selection Visibility")); hide_selection->set_pressed(EditorSettings::get_singleton()->get_project_metadata("game_view", "hide_selection", false)); @@ -1038,14 +1041,13 @@ GameView::GameView(Ref p_debugger, EmbeddedProcessBase *p_embe select_mode_button[RuntimeNodeSelect::SELECT_MODE_SINGLE]->connect(SceneStringName(pressed), callable_mp(this, &GameView::_select_mode_pressed).bind(RuntimeNodeSelect::SELECT_MODE_SINGLE)); select_mode_button[RuntimeNodeSelect::SELECT_MODE_SINGLE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_select", TTRC("Select Mode"), Key::Q)); select_mode_button[RuntimeNodeSelect::SELECT_MODE_SINGLE]->set_shortcut_context(this); - select_mode_button[RuntimeNodeSelect::SELECT_MODE_SINGLE]->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Alt+RMB: Show list of all nodes at position clicked.")); select_mode_button[RuntimeNodeSelect::SELECT_MODE_LIST] = memnew(Button); main_menu_hbox->add_child(select_mode_button[RuntimeNodeSelect::SELECT_MODE_LIST]); select_mode_button[RuntimeNodeSelect::SELECT_MODE_LIST]->set_toggle_mode(true); select_mode_button[RuntimeNodeSelect::SELECT_MODE_LIST]->set_theme_type_variation(SceneStringName(FlatButton)); select_mode_button[RuntimeNodeSelect::SELECT_MODE_LIST]->connect(SceneStringName(pressed), callable_mp(this, &GameView::_select_mode_pressed).bind(RuntimeNodeSelect::SELECT_MODE_LIST)); - select_mode_button[RuntimeNodeSelect::SELECT_MODE_LIST]->set_tooltip_text(TTR("Show list of selectable nodes at position clicked.")); + select_mode_button[RuntimeNodeSelect::SELECT_MODE_LIST]->set_tooltip_text(TTRC("Show list of selectable nodes at position clicked.")); _select_mode_pressed(EditorSettings::get_singleton()->get_project_metadata("game_view", "select_mode", 0)); @@ -1063,7 +1065,7 @@ GameView::GameView(Ref p_debugger, EmbeddedProcessBase *p_embe main_menu_hbox->add_child(camera_override_button); camera_override_button->set_toggle_mode(true); camera_override_button->set_theme_type_variation(SceneStringName(FlatButton)); - camera_override_button->set_tooltip_text(TTR("Override the in-game camera.")); + camera_override_button->set_tooltip_text(TTRC("Override the in-game camera.")); camera_override_button->set_accessibility_name(TTRC("Override In-game Camera")); camera_override_button->connect(SceneStringName(toggled), callable_mp(this, &GameView::_camera_override_button_toggled)); @@ -1072,17 +1074,17 @@ GameView::GameView(Ref p_debugger, EmbeddedProcessBase *p_embe camera_override_menu->set_flat(false); camera_override_menu->set_theme_type_variation("FlatMenuButton"); camera_override_menu->set_h_size_flags(SIZE_SHRINK_END); - camera_override_menu->set_tooltip_text(TTR("Camera Override Options")); + camera_override_menu->set_tooltip_text(TTRC("Camera Override Options")); camera_override_menu->set_accessibility_name(TTRC("Camera Override Options")); PopupMenu *menu = camera_override_menu->get_popup(); menu->connect(SceneStringName(id_pressed), callable_mp(this, &GameView::_camera_override_menu_id_pressed)); - menu->add_item(TTR("Reset 2D Camera"), CAMERA_RESET_2D); - menu->add_item(TTR("Reset 3D Camera"), CAMERA_RESET_3D); + menu->add_item(TTRC("Reset 2D Camera"), CAMERA_RESET_2D); + menu->add_item(TTRC("Reset 3D Camera"), CAMERA_RESET_3D); menu->add_separator(); - menu->add_radio_check_item(TTR("Manipulate In-Game"), CAMERA_MODE_INGAME); + menu->add_radio_check_item(TTRC("Manipulate In-Game"), CAMERA_MODE_INGAME); menu->set_item_checked(menu->get_item_index(CAMERA_MODE_INGAME), true); - menu->add_radio_check_item(TTR("Manipulate From Editors"), CAMERA_MODE_EDITORS); + menu->add_radio_check_item(TTRC("Manipulate From Editors"), CAMERA_MODE_EDITORS); _camera_override_menu_id_pressed(EditorSettings::get_singleton()->get_project_metadata("game_view", "camera_override_mode", 0)); embedding_separator = memnew(VSeparator); @@ -1092,7 +1094,7 @@ GameView::GameView(Ref p_debugger, EmbeddedProcessBase *p_embe main_menu_hbox->add_child(fixed_size_button); fixed_size_button->set_toggle_mode(true); fixed_size_button->set_theme_type_variation("FlatButton"); - fixed_size_button->set_tooltip_text(TTR("Embedded game size is based on project settings.\nThe 'Keep Aspect' mode is used when the Game Workspace is smaller than the desired size.")); + fixed_size_button->set_tooltip_text(TTRC("Embedded game size is based on project settings.\nThe 'Keep Aspect' mode is used when the Game Workspace is smaller than the desired size.")); fixed_size_button->set_accessibility_name(TTRC("Fixed Size")); fixed_size_button->connect(SceneStringName(pressed), callable_mp(this, &GameView::_size_mode_button_pressed).bind(SIZE_MODE_FIXED)); @@ -1100,7 +1102,7 @@ GameView::GameView(Ref p_debugger, EmbeddedProcessBase *p_embe main_menu_hbox->add_child(keep_aspect_button); keep_aspect_button->set_toggle_mode(true); keep_aspect_button->set_theme_type_variation("FlatButton"); - keep_aspect_button->set_tooltip_text(TTR("Keep the aspect ratio of the embedded game.")); + keep_aspect_button->set_tooltip_text(TTRC("Keep the aspect ratio of the embedded game.")); keep_aspect_button->set_accessibility_name(TTRC("Keep Aspect Ratio")); keep_aspect_button->connect(SceneStringName(pressed), callable_mp(this, &GameView::_size_mode_button_pressed).bind(SIZE_MODE_KEEP_ASPECT)); @@ -1108,7 +1110,7 @@ GameView::GameView(Ref p_debugger, EmbeddedProcessBase *p_embe main_menu_hbox->add_child(stretch_button); stretch_button->set_toggle_mode(true); stretch_button->set_theme_type_variation("FlatButton"); - stretch_button->set_tooltip_text(TTR("Embedded game size stretches to fit the Game Workspace.")); + stretch_button->set_tooltip_text(TTRC("Embedded game size stretches to fit the Game Workspace.")); stretch_button->set_accessibility_name(TTRC("Stretch")); stretch_button->connect(SceneStringName(pressed), callable_mp(this, &GameView::_size_mode_button_pressed).bind(SIZE_MODE_STRETCH)); @@ -1117,13 +1119,13 @@ GameView::GameView(Ref p_debugger, EmbeddedProcessBase *p_embe embed_options_menu->set_flat(false); embed_options_menu->set_theme_type_variation("FlatMenuButton"); embed_options_menu->set_h_size_flags(SIZE_SHRINK_END); - embed_options_menu->set_tooltip_text(TTR("Embedding Options")); + embed_options_menu->set_tooltip_text(TTRC("Embedding Options")); embed_options_menu->set_accessibility_name(TTRC("Embedding Options")); menu = embed_options_menu->get_popup(); menu->connect(SceneStringName(id_pressed), callable_mp(this, &GameView::_embed_options_menu_menu_id_pressed)); - menu->add_check_item(TTR("Embed Game on Next Play"), EMBED_RUN_GAME_EMBEDDED); - menu->add_check_item(TTR("Make Game Workspace Floating on Next Play"), EMBED_MAKE_FLOATING_ON_PLAY); + menu->add_check_item(TTRC("Embed Game on Next Play"), EMBED_RUN_GAME_EMBEDDED); + menu->add_check_item(TTRC("Make Game Workspace Floating on Next Play"), EMBED_MAKE_FLOATING_ON_PLAY); main_menu_hbox->add_spacer(); @@ -1213,7 +1215,6 @@ void GameViewPluginBase::setup(Ref p_debugger, EmbeddedProcess debugger = p_debugger; window_wrapper = memnew(WindowWrapper); - window_wrapper->set_window_title(vformat(TTR("%s - Godot Engine"), TTR("Game Workspace"))); window_wrapper->set_margins_enabled(true); game_view = memnew(GameView(debugger, p_embedded_process, window_wrapper)); @@ -1231,6 +1232,11 @@ void GameViewPluginBase::setup(Ref p_debugger, EmbeddedProcess void GameViewPluginBase::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_TRANSLATION_CHANGED: { +#ifndef ANDROID_ENABLED + window_wrapper->set_window_title(vformat(TTR("%s - Godot Engine"), TTR("Game Workspace"))); +#endif + } break; case NOTIFICATION_ENTER_TREE: { add_debugger_plugin(debugger); connect("main_screen_changed", callable_mp(this, &GameViewPluginBase::_save_last_editor)); diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 12afa4de4c..5ef8c5f88e 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -692,7 +692,7 @@ void Node3DEditorViewport::cancel_transform() { collision_reposition = false; finish_transform(); - set_message(TTR("Transform Aborted."), 3); + set_message(TTRC("Transform Aborted."), 3); } void Node3DEditorViewport::_update_shrink() { @@ -2929,6 +2929,51 @@ static void override_button_stylebox(Button *p_button, const Ref p_sty void Node3DEditorViewport::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_TRANSLATION_CHANGED: { + _update_name(); + message_time = MIN(message_time, 0.001); // Make it disappear. + + Key key = (OS::get_singleton()->has_feature("macos") || OS::get_singleton()->has_feature("web_macos") || OS::get_singleton()->has_feature("web_ios")) ? Key::META : Key::CTRL; + preview_material_label_desc->set_text(vformat(TTR("Drag and drop to override the material of any geometry node.\nHold %s when dropping to override a specific surface."), find_keycode_name(key))); + + const int item_count = display_submenu->get_item_count(); + for (int i = 0; i < item_count; i++) { + const Array item_data = display_submenu->get_item_metadata(i); + if (item_data.is_empty()) { + continue; + } + + SupportedRenderingMethods rendering_methods = item_data[0]; + String base_tooltip = item_data[1]; + + bool disabled = false; + String disabled_tooltip; + switch (rendering_methods) { + case SupportedRenderingMethods::ALL: + break; + case SupportedRenderingMethods::FORWARD_PLUS_MOBILE: + disabled = OS::get_singleton()->get_current_rendering_method() == "gl_compatibility"; + disabled_tooltip = TTR("This debug draw mode is not supported when using the Compatibility rendering method."); + break; + case SupportedRenderingMethods::FORWARD_PLUS: + disabled = OS::get_singleton()->get_current_rendering_method() == "gl_compatibility" || OS::get_singleton()->get_current_rendering_method() == "mobile"; + disabled_tooltip = TTR("This debug draw mode is not supported when using the Mobile or Compatibility rendering methods."); + break; + } + + display_submenu->set_item_disabled(i, disabled); + String tooltip = TTR(base_tooltip); + if (disabled) { + if (tooltip.is_empty()) { + tooltip = disabled_tooltip; + } else { + tooltip += "\n\n" + disabled_tooltip; + } + } + display_submenu->set_item_tooltip(i, tooltip); + } + } break; + case NOTIFICATION_READY: { ProjectSettings::get_singleton()->connect("settings_changed", callable_mp(this, &Node3DEditorViewport::_project_settings_changed)); } break; @@ -3577,7 +3622,6 @@ void Node3DEditorViewport::_menu_option(int p_option) { const List &selection = editor_selection->get_top_selected_node_list(); undo_redo->create_action(TTR("Align Transform with View")); - for (Node *E : selection) { Node3D *sp = Object::cast_to(E); if (!sp) { @@ -5514,32 +5558,8 @@ void Node3DEditorViewport::_set_lock_view_rotation(bool p_lock_rotation) { void Node3DEditorViewport::_add_advanced_debug_draw_mode_item(PopupMenu *p_popup, const String &p_name, int p_value, SupportedRenderingMethods p_rendering_methods, const String &p_tooltip) { display_submenu->add_radio_check_item(p_name, p_value); - - bool disabled = false; - String disabled_tooltip; - switch (p_rendering_methods) { - case SupportedRenderingMethods::ALL: - break; - case SupportedRenderingMethods::FORWARD_PLUS_MOBILE: - disabled = OS::get_singleton()->get_current_rendering_method() == "gl_compatibility"; - disabled_tooltip = TTR("This debug draw mode is not supported when using the Compatibility rendering method."); - break; - case SupportedRenderingMethods::FORWARD_PLUS: - disabled = OS::get_singleton()->get_current_rendering_method() == "gl_compatibility" || OS::get_singleton()->get_current_rendering_method() == "mobile"; - disabled_tooltip = TTR("This debug draw mode is not supported when using the Mobile or Compatibility rendering methods."); - break; - } - - display_submenu->set_item_disabled(-1, disabled); - String tooltip = p_tooltip; - if (disabled) { - if (tooltip.is_empty()) { - tooltip = disabled_tooltip; - } else { - tooltip += "\n\n" + disabled_tooltip; - } - } - display_submenu->set_item_tooltip(-1, tooltip); + Array item_data = { p_rendering_methods, p_tooltip }; + display_submenu->set_item_metadata(-1, item_data); // Tooltip is assigned in NOTIFICATION_TRANSLATION_CHANGED. } Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p_index) { @@ -5598,6 +5618,8 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p view_display_menu->set_h_size_flags(0); view_display_menu->set_shortcut_context(this); view_display_menu->set_accessibility_name(TTRC("View")); + view_display_menu->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); + view_display_menu->get_popup()->set_auto_translate_mode(AUTO_TRANSLATE_MODE_ALWAYS); hbox->add_child(view_display_menu); view_display_menu->get_popup()->set_hide_on_checkable_item_selection(false); @@ -5610,10 +5632,10 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p view_display_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/rear_view"), VIEW_REAR); view_display_menu->get_popup()->add_separator(); view_display_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/switch_perspective_orthogonal"), VIEW_SWITCH_PERSPECTIVE_ORTHOGONAL); - view_display_menu->get_popup()->add_radio_check_item(TTR("Perspective"), VIEW_PERSPECTIVE); - view_display_menu->get_popup()->add_radio_check_item(TTR("Orthogonal"), VIEW_ORTHOGONAL); + view_display_menu->get_popup()->add_radio_check_item(TTRC("Perspective"), VIEW_PERSPECTIVE); + view_display_menu->get_popup()->add_radio_check_item(TTRC("Orthogonal"), VIEW_ORTHOGONAL); view_display_menu->get_popup()->set_item_checked(view_display_menu->get_popup()->get_item_index(VIEW_PERSPECTIVE), true); - view_display_menu->get_popup()->add_check_item(TTR("Auto Orthogonal Enabled"), VIEW_AUTO_ORTHOGONAL); + view_display_menu->get_popup()->add_check_item(TTRC("Auto Orthogonal Enabled"), VIEW_AUTO_ORTHOGONAL); view_display_menu->get_popup()->set_item_checked(view_display_menu->get_popup()->get_item_index(VIEW_AUTO_ORTHOGONAL), true); view_display_menu->get_popup()->add_separator(); view_display_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_lock_rotation", TTRC("Lock View Rotation")), VIEW_LOCK_ROTATION); @@ -5628,60 +5650,60 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p display_submenu = memnew(PopupMenu); display_submenu->set_hide_on_checkable_item_selection(false); - _add_advanced_debug_draw_mode_item(display_submenu, TTR("Directional Shadow Splits"), VIEW_DISPLAY_DEBUG_PSSM_SPLITS, SupportedRenderingMethods::FORWARD_PLUS_MOBILE, - TTR("Displays directional shadow splits in different colors to make adjusting split thresholds easier. \nRed: 1st split (closest to the camera), Green: 2nd split, Blue: 3rd split, Yellow: 4th split (furthest from the camera)")); + _add_advanced_debug_draw_mode_item(display_submenu, TTRC("Directional Shadow Splits"), VIEW_DISPLAY_DEBUG_PSSM_SPLITS, SupportedRenderingMethods::FORWARD_PLUS_MOBILE, + TTRC("Displays directional shadow splits in different colors to make adjusting split thresholds easier. \nRed: 1st split (closest to the camera), Green: 2nd split, Blue: 3rd split, Yellow: 4th split (furthest from the camera)")); display_submenu->add_separator(); // TRANSLATORS: "Normal" as in "normal vector", not "normal life". - _add_advanced_debug_draw_mode_item(display_submenu, TTR("Normal Buffer"), VIEW_DISPLAY_NORMAL_BUFFER, SupportedRenderingMethods::FORWARD_PLUS); + _add_advanced_debug_draw_mode_item(display_submenu, TTRC("Normal Buffer"), VIEW_DISPLAY_NORMAL_BUFFER, SupportedRenderingMethods::FORWARD_PLUS); display_submenu->add_separator(); - _add_advanced_debug_draw_mode_item(display_submenu, TTR("Shadow Atlas"), VIEW_DISPLAY_DEBUG_SHADOW_ATLAS, SupportedRenderingMethods::ALL, - TTR("Displays the shadow atlas used for positional (omni/spot) shadow mapping.\nRequires a visible OmniLight3D or SpotLight3D node with shadows enabled to have a visible effect.")); - _add_advanced_debug_draw_mode_item(display_submenu, TTR("Directional Shadow Map"), VIEW_DISPLAY_DEBUG_DIRECTIONAL_SHADOW_ATLAS, SupportedRenderingMethods::ALL, - TTR("Displays the shadow map used for directional shadow mapping.\nRequires a visible DirectionalLight3D node with shadows enabled to have a visible effect.")); + _add_advanced_debug_draw_mode_item(display_submenu, TTRC("Shadow Atlas"), VIEW_DISPLAY_DEBUG_SHADOW_ATLAS, SupportedRenderingMethods::ALL, + TTRC("Displays the shadow atlas used for positional (omni/spot) shadow mapping.\nRequires a visible OmniLight3D or SpotLight3D node with shadows enabled to have a visible effect.")); + _add_advanced_debug_draw_mode_item(display_submenu, TTRC("Directional Shadow Map"), VIEW_DISPLAY_DEBUG_DIRECTIONAL_SHADOW_ATLAS, SupportedRenderingMethods::ALL, + TTRC("Displays the shadow map used for directional shadow mapping.\nRequires a visible DirectionalLight3D node with shadows enabled to have a visible effect.")); display_submenu->add_separator(); - _add_advanced_debug_draw_mode_item(display_submenu, TTR("Decal Atlas"), VIEW_DISPLAY_DEBUG_DECAL_ATLAS, SupportedRenderingMethods::FORWARD_PLUS_MOBILE); + _add_advanced_debug_draw_mode_item(display_submenu, TTRC("Decal Atlas"), VIEW_DISPLAY_DEBUG_DECAL_ATLAS, SupportedRenderingMethods::FORWARD_PLUS_MOBILE); display_submenu->add_separator(); - _add_advanced_debug_draw_mode_item(display_submenu, TTR("VoxelGI Lighting"), VIEW_DISPLAY_DEBUG_VOXEL_GI_LIGHTING, SupportedRenderingMethods::FORWARD_PLUS, - TTR("Requires a visible VoxelGI node that has been baked to have a visible effect.")); - _add_advanced_debug_draw_mode_item(display_submenu, TTR("VoxelGI Albedo"), VIEW_DISPLAY_DEBUG_VOXEL_GI_ALBEDO, SupportedRenderingMethods::FORWARD_PLUS, - TTR("Requires a visible VoxelGI node that has been baked to have a visible effect.")); - _add_advanced_debug_draw_mode_item(display_submenu, TTR("VoxelGI Emission"), VIEW_DISPLAY_DEBUG_VOXEL_GI_EMISSION, SupportedRenderingMethods::FORWARD_PLUS, - TTR("Requires a visible VoxelGI node that has been baked to have a visible effect.")); + _add_advanced_debug_draw_mode_item(display_submenu, TTRC("VoxelGI Lighting"), VIEW_DISPLAY_DEBUG_VOXEL_GI_LIGHTING, SupportedRenderingMethods::FORWARD_PLUS, + TTRC("Requires a visible VoxelGI node that has been baked to have a visible effect.")); + _add_advanced_debug_draw_mode_item(display_submenu, TTRC("VoxelGI Albedo"), VIEW_DISPLAY_DEBUG_VOXEL_GI_ALBEDO, SupportedRenderingMethods::FORWARD_PLUS, + TTRC("Requires a visible VoxelGI node that has been baked to have a visible effect.")); + _add_advanced_debug_draw_mode_item(display_submenu, TTRC("VoxelGI Emission"), VIEW_DISPLAY_DEBUG_VOXEL_GI_EMISSION, SupportedRenderingMethods::FORWARD_PLUS, + TTRC("Requires a visible VoxelGI node that has been baked to have a visible effect.")); display_submenu->add_separator(); - _add_advanced_debug_draw_mode_item(display_submenu, TTR("SDFGI Cascades"), VIEW_DISPLAY_DEBUG_SDFGI, SupportedRenderingMethods::FORWARD_PLUS, - TTR("Requires SDFGI to be enabled in Environment to have a visible effect.")); - _add_advanced_debug_draw_mode_item(display_submenu, TTR("SDFGI Probes"), VIEW_DISPLAY_DEBUG_SDFGI_PROBES, SupportedRenderingMethods::FORWARD_PLUS, - TTR("Requires SDFGI to be enabled in Environment to have a visible effect.")); + _add_advanced_debug_draw_mode_item(display_submenu, TTRC("SDFGI Cascades"), VIEW_DISPLAY_DEBUG_SDFGI, SupportedRenderingMethods::FORWARD_PLUS, + TTRC("Requires SDFGI to be enabled in Environment to have a visible effect.")); + _add_advanced_debug_draw_mode_item(display_submenu, TTRC("SDFGI Probes"), VIEW_DISPLAY_DEBUG_SDFGI_PROBES, SupportedRenderingMethods::FORWARD_PLUS, + TTRC("Requires SDFGI to be enabled in Environment to have a visible effect.")); display_submenu->add_separator(); - _add_advanced_debug_draw_mode_item(display_submenu, TTR("Scene Luminance"), VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE, SupportedRenderingMethods::FORWARD_PLUS_MOBILE, - TTR("Displays the scene luminance computed from the 3D buffer. This is used for Auto Exposure calculation.\nRequires Auto Exposure to be enabled in CameraAttributes to have a visible effect.")); + _add_advanced_debug_draw_mode_item(display_submenu, TTRC("Scene Luminance"), VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE, SupportedRenderingMethods::FORWARD_PLUS_MOBILE, + TTRC("Displays the scene luminance computed from the 3D buffer. This is used for Auto Exposure calculation.\nRequires Auto Exposure to be enabled in CameraAttributes to have a visible effect.")); display_submenu->add_separator(); - _add_advanced_debug_draw_mode_item(display_submenu, TTR("SSAO"), VIEW_DISPLAY_DEBUG_SSAO, SupportedRenderingMethods::FORWARD_PLUS, - TTR("Displays the screen-space ambient occlusion buffer. Requires SSAO to be enabled in Environment to have a visible effect.")); - _add_advanced_debug_draw_mode_item(display_submenu, TTR("SSIL"), VIEW_DISPLAY_DEBUG_SSIL, SupportedRenderingMethods::FORWARD_PLUS, - TTR("Displays the screen-space indirect lighting buffer. Requires SSIL to be enabled in Environment to have a visible effect.")); + _add_advanced_debug_draw_mode_item(display_submenu, TTRC("SSAO"), VIEW_DISPLAY_DEBUG_SSAO, SupportedRenderingMethods::FORWARD_PLUS, + TTRC("Displays the screen-space ambient occlusion buffer. Requires SSAO to be enabled in Environment to have a visible effect.")); + _add_advanced_debug_draw_mode_item(display_submenu, TTRC("SSIL"), VIEW_DISPLAY_DEBUG_SSIL, SupportedRenderingMethods::FORWARD_PLUS, + TTRC("Displays the screen-space indirect lighting buffer. Requires SSIL to be enabled in Environment to have a visible effect.")); display_submenu->add_separator(); - _add_advanced_debug_draw_mode_item(display_submenu, TTR("VoxelGI/SDFGI Buffer"), VIEW_DISPLAY_DEBUG_GI_BUFFER, SupportedRenderingMethods::FORWARD_PLUS, - TTR("Requires SDFGI or VoxelGI to be enabled to have a visible effect.")); + _add_advanced_debug_draw_mode_item(display_submenu, TTRC("VoxelGI/SDFGI Buffer"), VIEW_DISPLAY_DEBUG_GI_BUFFER, SupportedRenderingMethods::FORWARD_PLUS, + TTRC("Requires SDFGI or VoxelGI to be enabled to have a visible effect.")); display_submenu->add_separator(); - _add_advanced_debug_draw_mode_item(display_submenu, TTR("Disable Mesh LOD"), VIEW_DISPLAY_DEBUG_DISABLE_LOD, SupportedRenderingMethods::ALL, - TTR("Renders all meshes with their highest level of detail regardless of their distance from the camera.")); + _add_advanced_debug_draw_mode_item(display_submenu, TTRC("Disable Mesh LOD"), VIEW_DISPLAY_DEBUG_DISABLE_LOD, SupportedRenderingMethods::ALL, + TTRC("Renders all meshes with their highest level of detail regardless of their distance from the camera.")); display_submenu->add_separator(); - _add_advanced_debug_draw_mode_item(display_submenu, TTR("OmniLight3D Cluster"), VIEW_DISPLAY_DEBUG_CLUSTER_OMNI_LIGHTS, SupportedRenderingMethods::FORWARD_PLUS, - TTR("Highlights tiles of pixels that are affected by at least one OmniLight3D.")); - _add_advanced_debug_draw_mode_item(display_submenu, TTR("SpotLight3D Cluster"), VIEW_DISPLAY_DEBUG_CLUSTER_SPOT_LIGHTS, SupportedRenderingMethods::FORWARD_PLUS, - TTR("Highlights tiles of pixels that are affected by at least one SpotLight3D.")); - _add_advanced_debug_draw_mode_item(display_submenu, TTR("Decal Cluster"), VIEW_DISPLAY_DEBUG_CLUSTER_DECALS, SupportedRenderingMethods::FORWARD_PLUS, - TTR("Highlights tiles of pixels that are affected by at least one Decal.")); - _add_advanced_debug_draw_mode_item(display_submenu, TTR("ReflectionProbe Cluster"), VIEW_DISPLAY_DEBUG_CLUSTER_REFLECTION_PROBES, SupportedRenderingMethods::FORWARD_PLUS, - TTR("Highlights tiles of pixels that are affected by at least one ReflectionProbe.")); - _add_advanced_debug_draw_mode_item(display_submenu, TTR("Occlusion Culling Buffer"), VIEW_DISPLAY_DEBUG_OCCLUDERS, SupportedRenderingMethods::FORWARD_PLUS_MOBILE, - TTR("Represents occluders with black pixels. Requires occlusion culling to be enabled to have a visible effect.")); - _add_advanced_debug_draw_mode_item(display_submenu, TTR("Motion Vectors"), VIEW_DISPLAY_MOTION_VECTORS, SupportedRenderingMethods::FORWARD_PLUS, - TTR("Represents motion vectors with colored lines in the direction of motion. Gray dots represent areas with no per-pixel motion.")); - _add_advanced_debug_draw_mode_item(display_submenu, TTR("Internal Buffer"), VIEW_DISPLAY_INTERNAL_BUFFER, SupportedRenderingMethods::FORWARD_PLUS_MOBILE, - TTR("Shows the scene rendered in linear colorspace before any tonemapping or post-processing.")); - view_display_menu->get_popup()->add_submenu_node_item(TTR("Display Advanced..."), display_submenu, VIEW_DISPLAY_ADVANCED); + _add_advanced_debug_draw_mode_item(display_submenu, TTRC("OmniLight3D Cluster"), VIEW_DISPLAY_DEBUG_CLUSTER_OMNI_LIGHTS, SupportedRenderingMethods::FORWARD_PLUS, + TTRC("Highlights tiles of pixels that are affected by at least one OmniLight3D.")); + _add_advanced_debug_draw_mode_item(display_submenu, TTRC("SpotLight3D Cluster"), VIEW_DISPLAY_DEBUG_CLUSTER_SPOT_LIGHTS, SupportedRenderingMethods::FORWARD_PLUS, + TTRC("Highlights tiles of pixels that are affected by at least one SpotLight3D.")); + _add_advanced_debug_draw_mode_item(display_submenu, TTRC("Decal Cluster"), VIEW_DISPLAY_DEBUG_CLUSTER_DECALS, SupportedRenderingMethods::FORWARD_PLUS, + TTRC("Highlights tiles of pixels that are affected by at least one Decal.")); + _add_advanced_debug_draw_mode_item(display_submenu, TTRC("ReflectionProbe Cluster"), VIEW_DISPLAY_DEBUG_CLUSTER_REFLECTION_PROBES, SupportedRenderingMethods::FORWARD_PLUS, + TTRC("Highlights tiles of pixels that are affected by at least one ReflectionProbe.")); + _add_advanced_debug_draw_mode_item(display_submenu, TTRC("Occlusion Culling Buffer"), VIEW_DISPLAY_DEBUG_OCCLUDERS, SupportedRenderingMethods::FORWARD_PLUS_MOBILE, + TTRC("Represents occluders with black pixels. Requires occlusion culling to be enabled to have a visible effect.")); + _add_advanced_debug_draw_mode_item(display_submenu, TTRC("Motion Vectors"), VIEW_DISPLAY_MOTION_VECTORS, SupportedRenderingMethods::FORWARD_PLUS, + TTRC("Represents motion vectors with colored lines in the direction of motion. Gray dots represent areas with no per-pixel motion.")); + _add_advanced_debug_draw_mode_item(display_submenu, TTRC("Internal Buffer"), VIEW_DISPLAY_INTERNAL_BUFFER, SupportedRenderingMethods::FORWARD_PLUS_MOBILE, + TTRC("Shows the scene rendered in linear colorspace before any tonemapping or post-processing.")); + view_display_menu->get_popup()->add_submenu_node_item(TTRC("Display Advanced..."), display_submenu, VIEW_DISPLAY_ADVANCED); view_display_menu->get_popup()->add_separator(); view_display_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_environment", TTRC("View Environment")), VIEW_ENVIRONMENT); @@ -5745,7 +5767,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p hbox->add_child(translation_preview_button); preview_camera = memnew(CheckBox); - preview_camera->set_text(TTR("Preview")); + preview_camera->set_text(TTRC("Preview")); // Using Control even on macOS to avoid conflict with Quick Open shortcut. preview_camera->set_shortcut(ED_SHORTCUT("spatial_editor/toggle_camera_preview", TTRC("Toggle Camera Preview"), KeyModifierMask::CTRL | Key::P)); vbox->add_child(preview_camera); @@ -5786,7 +5808,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p cinema_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); cinema_label->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER); surface->add_child(cinema_label); - cinema_label->set_text(TTR("Cinematic Preview")); + cinema_label->set_text(TTRC("Cinematic Preview")); cinema_label->hide(); previewing_cinema = false; @@ -5795,11 +5817,11 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p locked_label->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER); locked_label->set_h_size_flags(SIZE_SHRINK_CENTER); bottom_center_vbox->add_child(locked_label); - locked_label->set_text(TTR("View Rotation Locked")); + locked_label->set_text(TTRC("View Rotation Locked")); locked_label->hide(); zoom_limit_label = memnew(Label); - zoom_limit_label->set_text(TTR("To zoom further, change the camera's clipping planes (View -> Settings...)")); + zoom_limit_label->set_text(TTRC("To zoom further, change the camera's clipping planes (View -> Settings...)")); zoom_limit_label->set_name("ZoomLimitMessageLabel"); zoom_limit_label->add_theme_color_override(SceneStringName(font_color), Color(1, 1, 1, 1)); zoom_limit_label->hide(); @@ -5808,7 +5830,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p preview_material_label = memnew(Label); preview_material_label->set_anchors_and_offsets_preset(LayoutPreset::PRESET_BOTTOM_LEFT); preview_material_label->set_offset(Side::SIDE_TOP, -70 * EDSCALE); - preview_material_label->set_text(TTR("Overriding material...")); + preview_material_label->set_text(TTRC("Overriding material...")); preview_material_label->add_theme_color_override(SceneStringName(font_color), Color(1, 1, 1, 1)); preview_material_label->hide(); surface->add_child(preview_material_label); @@ -5817,8 +5839,6 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p preview_material_label_desc->set_focus_mode(FOCUS_ACCESSIBILITY); preview_material_label_desc->set_anchors_and_offsets_preset(LayoutPreset::PRESET_BOTTOM_LEFT); preview_material_label_desc->set_offset(Side::SIDE_TOP, -50 * EDSCALE); - Key key = (OS::get_singleton()->has_feature("macos") || OS::get_singleton()->has_feature("web_macos") || OS::get_singleton()->has_feature("web_ios")) ? Key::META : Key::CTRL; - preview_material_label_desc->set_text(vformat(TTR("Drag and drop to override the material of any geometry node.\nHold %s when dropping to override a specific surface."), find_keycode_name(key))); preview_material_label_desc->add_theme_color_override(SceneStringName(font_color), Color(0.8, 0.8, 0.8, 1)); preview_material_label_desc->add_theme_constant_override("line_spacing", 0); preview_material_label_desc->hide(); @@ -8303,6 +8323,14 @@ void Node3DEditor::_update_theme() { void Node3DEditor::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_TRANSLATION_CHANGED: { + tool_button[TOOL_MODE_SELECT]->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.") + "\n" + TTR("(Available in all modes.)")); + tool_button[TOOL_MODE_MOVE]->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Drag: Use snap.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.")); + tool_button[TOOL_MODE_ROTATE]->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Drag: Use snap.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.")); + tool_button[TOOL_MODE_SCALE]->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Drag: Use snap.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.")); + _update_gizmos_menu(); + } break; + case NOTIFICATION_READY: { _menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT); @@ -8333,7 +8361,6 @@ void Node3DEditor::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { _update_theme(); _register_all_gizmos(); - _update_gizmos_menu(); _init_indicators(); update_all_gizmos(); } break; @@ -8874,9 +8901,9 @@ void Node3DEditor::_update_preview_environment() { } if (directional_light_count > 0) { - sun_state->set_text(TTR("Scene contains\nDirectionalLight3D.\nPreview disabled.")); + sun_state->set_text(TTRC("Scene contains\nDirectionalLight3D.\nPreview disabled.")); } else { - sun_state->set_text(TTR("Preview disabled.")); + sun_state->set_text(TTRC("Preview disabled.")); } } else { @@ -8903,9 +8930,9 @@ void Node3DEditor::_update_preview_environment() { preview_env_dangling = true; } if (world_env_count > 0) { - environ_state->set_text(TTR("Scene contains\nWorldEnvironment.\nPreview disabled.")); + environ_state->set_text(TTRC("Scene contains\nWorldEnvironment.\nPreview disabled.")); } else { - environ_state->set_text(TTR("Preview disabled.")); + environ_state->set_text(TTRC("Preview disabled.")); } } else { @@ -9116,44 +9143,44 @@ Node3DEditor::Node3DEditor() { tool_button[TOOL_MODE_SELECT] = memnew(Button); main_menu_hbox->add_child(tool_button[TOOL_MODE_SELECT]); tool_button[TOOL_MODE_SELECT]->set_toggle_mode(true); + tool_button[TOOL_MODE_SELECT]->set_tooltip_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); tool_button[TOOL_MODE_SELECT]->set_theme_type_variation(SceneStringName(FlatButton)); tool_button[TOOL_MODE_SELECT]->set_pressed(true); tool_button[TOOL_MODE_SELECT]->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_TOOL_SELECT)); tool_button[TOOL_MODE_SELECT]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_select", TTRC("Select Mode"), Key::Q, true)); tool_button[TOOL_MODE_SELECT]->set_shortcut_context(this); - tool_button[TOOL_MODE_SELECT]->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.") + "\n" + TTR("(Available in all modes.)")); tool_button[TOOL_MODE_SELECT]->set_accessibility_name(TTRC("Select Mode")); main_menu_hbox->add_child(memnew(VSeparator)); tool_button[TOOL_MODE_MOVE] = memnew(Button); main_menu_hbox->add_child(tool_button[TOOL_MODE_MOVE]); tool_button[TOOL_MODE_MOVE]->set_toggle_mode(true); + tool_button[TOOL_MODE_MOVE]->set_tooltip_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); tool_button[TOOL_MODE_MOVE]->set_theme_type_variation(SceneStringName(FlatButton)); tool_button[TOOL_MODE_MOVE]->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_TOOL_MOVE)); tool_button[TOOL_MODE_MOVE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_move", TTRC("Move Mode"), Key::W, true)); tool_button[TOOL_MODE_MOVE]->set_shortcut_context(this); - tool_button[TOOL_MODE_MOVE]->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Drag: Use snap.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.")); tool_button[TOOL_MODE_MOVE]->set_accessibility_name(TTRC("Move Mode")); tool_button[TOOL_MODE_ROTATE] = memnew(Button); main_menu_hbox->add_child(tool_button[TOOL_MODE_ROTATE]); tool_button[TOOL_MODE_ROTATE]->set_toggle_mode(true); + tool_button[TOOL_MODE_ROTATE]->set_tooltip_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); tool_button[TOOL_MODE_ROTATE]->set_theme_type_variation(SceneStringName(FlatButton)); tool_button[TOOL_MODE_ROTATE]->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_TOOL_ROTATE)); tool_button[TOOL_MODE_ROTATE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_rotate", TTRC("Rotate Mode"), Key::E, true)); tool_button[TOOL_MODE_ROTATE]->set_shortcut_context(this); - tool_button[TOOL_MODE_ROTATE]->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Drag: Use snap.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.")); tool_button[TOOL_MODE_ROTATE]->set_accessibility_name(TTRC("Rotate Mode")); tool_button[TOOL_MODE_SCALE] = memnew(Button); main_menu_hbox->add_child(tool_button[TOOL_MODE_SCALE]); tool_button[TOOL_MODE_SCALE]->set_toggle_mode(true); + tool_button[TOOL_MODE_SCALE]->set_tooltip_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); tool_button[TOOL_MODE_SCALE]->set_theme_type_variation(SceneStringName(FlatButton)); tool_button[TOOL_MODE_SCALE]->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_TOOL_SCALE)); tool_button[TOOL_MODE_SCALE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_scale", TTRC("Scale Mode"), Key::R, true)); tool_button[TOOL_MODE_SCALE]->set_shortcut_context(this); - tool_button[TOOL_MODE_SCALE]->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Drag: Use snap.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.")); tool_button[TOOL_MODE_SCALE]->set_accessibility_name(TTRC("Scale Mode")); main_menu_hbox->add_child(memnew(VSeparator)); @@ -9163,7 +9190,7 @@ Node3DEditor::Node3DEditor() { tool_button[TOOL_MODE_LIST_SELECT]->set_toggle_mode(true); tool_button[TOOL_MODE_LIST_SELECT]->set_theme_type_variation(SceneStringName(FlatButton)); tool_button[TOOL_MODE_LIST_SELECT]->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_TOOL_LIST_SELECT)); - tool_button[TOOL_MODE_LIST_SELECT]->set_tooltip_text(TTR("Show list of selectable nodes at position clicked.")); + tool_button[TOOL_MODE_LIST_SELECT]->set_tooltip_text(TTRC("Show list of selectable nodes at position clicked.")); tool_button[TOOL_MODE_LIST_SELECT]->set_accessibility_name(TTRC("Show List of Selectable Nodes")); tool_button[TOOL_LOCK_SELECTED] = memnew(Button); @@ -9234,7 +9261,7 @@ Node3DEditor::Node3DEditor() { main_menu_hbox->add_child(memnew(VSeparator)); sun_button = memnew(Button); - sun_button->set_tooltip_text(TTR("Toggle preview sunlight.\nIf a DirectionalLight3D node is added to the scene, preview sunlight is disabled.")); + sun_button->set_tooltip_text(TTRC("Toggle preview sunlight.\nIf a DirectionalLight3D node is added to the scene, preview sunlight is disabled.")); sun_button->set_toggle_mode(true); sun_button->set_accessibility_name(TTRC("Preview Sunlight")); sun_button->set_theme_type_variation(SceneStringName(FlatButton)); @@ -9245,7 +9272,7 @@ Node3DEditor::Node3DEditor() { main_menu_hbox->add_child(sun_button); environ_button = memnew(Button); - environ_button->set_tooltip_text(TTR("Toggle preview environment.\nIf a WorldEnvironment node is added to the scene, preview environment is disabled.")); + environ_button->set_tooltip_text(TTRC("Toggle preview environment.\nIf a WorldEnvironment node is added to the scene, preview environment is disabled.")); environ_button->set_toggle_mode(true); environ_button->set_accessibility_name(TTRC("Preview Environment")); environ_button->set_theme_type_variation(SceneStringName(FlatButton)); @@ -9256,7 +9283,7 @@ Node3DEditor::Node3DEditor() { main_menu_hbox->add_child(environ_button); sun_environ_settings = memnew(Button); - sun_environ_settings->set_tooltip_text(TTR("Edit Sun and Environment settings.")); + sun_environ_settings->set_tooltip_text(TTRC("Edit Sun and Environment settings.")); sun_environ_settings->set_theme_type_variation(SceneStringName(FlatButton)); sun_environ_settings->set_accessibility_name(TTRC("Edit Sun and Environment")); sun_environ_settings->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_sun_environ_settings_pressed)); @@ -9302,7 +9329,7 @@ Node3DEditor::Node3DEditor() { transform_menu = memnew(MenuButton); transform_menu->set_flat(false); transform_menu->set_theme_type_variation("FlatMenuButton"); - transform_menu->set_text(TTR("Transform")); + transform_menu->set_text(TTRC("Transform")); transform_menu->set_switch_on_hover(true); transform_menu->set_shortcut_context(this); main_menu_hbox->add_child(transform_menu); @@ -9320,7 +9347,7 @@ Node3DEditor::Node3DEditor() { view_layout_menu->set_flat(false); view_layout_menu->set_theme_type_variation("FlatMenuButton"); // TRANSLATORS: Noun, name of the 2D/3D View menus. - view_layout_menu->set_text(TTR("View")); + view_layout_menu->set_text(TTRC("View")); view_layout_menu->set_switch_on_hover(true); view_layout_menu->set_shortcut_context(this); main_menu_hbox->add_child(view_layout_menu); @@ -9348,8 +9375,9 @@ Node3DEditor::Node3DEditor() { p->add_separator(); gizmos_menu = memnew(PopupMenu); + gizmos_menu->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); gizmos_menu->set_hide_on_checkable_item_selection(false); - p->add_submenu_node_item(TTR("Gizmos"), gizmos_menu); + p->add_submenu_node_item(TTRC("Gizmos"), gizmos_menu); gizmos_menu->connect(SceneStringName(id_pressed), callable_mp(this, &Node3DEditor::_menu_gizmo_toggled)); p->add_separator(); @@ -9394,7 +9422,7 @@ Node3DEditor::Node3DEditor() { /* SNAP DIALOG */ snap_dialog = memnew(ConfirmationDialog); - snap_dialog->set_title(TTR("Snap Settings")); + snap_dialog->set_title(TTRC("Snap Settings")); add_child(snap_dialog); snap_dialog->connect(SceneStringName(confirmed), callable_mp(this, &Node3DEditor::_snap_changed)); snap_dialog->get_cancel_button()->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_snap_update)); @@ -9405,22 +9433,22 @@ Node3DEditor::Node3DEditor() { snap_translate = memnew(LineEdit); snap_translate->set_select_all_on_focus(true); snap_translate->set_accessibility_name(TTRC("Translate Snap")); - snap_dialog_vbc->add_margin_child(TTR("Translate Snap:"), snap_translate); + snap_dialog_vbc->add_margin_child(TTRC("Translate Snap:"), snap_translate); snap_rotate = memnew(LineEdit); snap_rotate->set_select_all_on_focus(true); snap_rotate->set_accessibility_name(TTRC("Rotate Snap")); - snap_dialog_vbc->add_margin_child(TTR("Rotate Snap (deg.):"), snap_rotate); + snap_dialog_vbc->add_margin_child(TTRC("Rotate Snap (deg.):"), snap_rotate); snap_scale = memnew(LineEdit); snap_scale->set_select_all_on_focus(true); snap_scale->set_accessibility_name(TTRC("Scale Snap")); - snap_dialog_vbc->add_margin_child(TTR("Scale Snap (%):"), snap_scale); + snap_dialog_vbc->add_margin_child(TTRC("Scale Snap (%):"), snap_scale); /* SETTINGS DIALOG */ settings_dialog = memnew(ConfirmationDialog); - settings_dialog->set_title(TTR("Viewport Settings")); + settings_dialog->set_title(TTRC("Viewport Settings")); add_child(settings_dialog); settings_vbc = memnew(VBoxContainer); settings_vbc->set_custom_minimum_size(Size2(200, 0) * EDSCALE); @@ -9432,9 +9460,9 @@ Node3DEditor::Node3DEditor() { settings_fov->set_step(0.1); settings_fov->set_value(EDITOR_GET("editors/3d/default_fov")); settings_fov->set_select_all_on_focus(true); - settings_fov->set_tooltip_text(TTR("FOV is defined as a vertical value, as the editor camera always uses the Keep Height aspect mode.")); + settings_fov->set_tooltip_text(TTRC("FOV is defined as a vertical value, as the editor camera always uses the Keep Height aspect mode.")); settings_fov->set_accessibility_name(TTRC("Perspective VFOV")); - settings_vbc->add_margin_child(TTR("Perspective VFOV (deg.):"), settings_fov); + settings_vbc->add_margin_child(TTRC("Perspective VFOV (deg.):"), settings_fov); settings_znear = memnew(SpinBox); settings_znear->set_max(MAX_Z); @@ -9443,7 +9471,7 @@ Node3DEditor::Node3DEditor() { settings_znear->set_accessibility_name(TTRC("View Z-Near")); settings_znear->set_value(EDITOR_GET("editors/3d/default_z_near")); settings_znear->set_select_all_on_focus(true); - settings_vbc->add_margin_child(TTR("View Z-Near:"), settings_znear); + settings_vbc->add_margin_child(TTRC("View Z-Near:"), settings_znear); settings_zfar = memnew(SpinBox); settings_zfar->set_max(MAX_Z); @@ -9452,7 +9480,7 @@ Node3DEditor::Node3DEditor() { settings_zfar->set_accessibility_name(TTRC("View Z-Far")); settings_zfar->set_value(EDITOR_GET("editors/3d/default_z_far")); settings_zfar->set_select_all_on_focus(true); - settings_vbc->add_margin_child(TTR("View Z-Far:"), settings_zfar); + settings_vbc->add_margin_child(TTRC("View Z-Far:"), settings_zfar); for (uint32_t i = 0; i < VIEWPORTS_COUNT; ++i) { settings_dialog->connect(SceneStringName(confirmed), callable_mp(viewports[i], &Node3DEditorViewport::_view_settings_confirmed).bind(0.0)); @@ -9461,14 +9489,14 @@ Node3DEditor::Node3DEditor() { /* XFORM DIALOG */ xform_dialog = memnew(ConfirmationDialog); - xform_dialog->set_title(TTR("Transform Change")); + xform_dialog->set_title(TTRC("Transform Change")); add_child(xform_dialog); VBoxContainer *xform_vbc = memnew(VBoxContainer); xform_dialog->add_child(xform_vbc); Label *l = memnew(Label); - l->set_text(TTR("Translate:")); + l->set_text(TTRC("Translate:")); xform_vbc->add_child(l); HBoxContainer *xform_hbc = memnew(HBoxContainer); @@ -9482,7 +9510,7 @@ Node3DEditor::Node3DEditor() { } l = memnew(Label); - l->set_text(TTR("Rotate (deg.):")); + l->set_text(TTRC("Rotate (deg.):")); xform_vbc->add_child(l); xform_hbc = memnew(HBoxContainer); @@ -9496,7 +9524,7 @@ Node3DEditor::Node3DEditor() { } l = memnew(Label); - l->set_text(TTR("Scale (ratio):")); + l->set_text(TTRC("Scale (ratio):")); xform_vbc->add_child(l); xform_hbc = memnew(HBoxContainer); @@ -9510,14 +9538,14 @@ Node3DEditor::Node3DEditor() { } l = memnew(Label); - l->set_text(TTR("Transform Type")); + l->set_text(TTRC("Transform Type")); xform_vbc->add_child(l); xform_type = memnew(OptionButton); xform_type->set_h_size_flags(SIZE_EXPAND_FILL); xform_type->set_accessibility_name(TTRC("Transform Type")); - xform_type->add_item(TTR("Pre")); - xform_type->add_item(TTR("Post")); + xform_type->add_item(TTRC("Pre")); + xform_type->add_item(TTRC("Post")); xform_vbc->add_child(xform_type); xform_dialog->connect(SceneStringName(confirmed), callable_mp(this, &Node3DEditor::_xform_dialog_action)); @@ -9546,14 +9574,14 @@ Node3DEditor::Node3DEditor() { sun_title = memnew(Label); sun_title->set_theme_type_variation("HeaderMedium"); sun_vb->add_child(sun_title); - sun_title->set_text(TTR("Preview Sun")); + sun_title->set_text(TTRC("Preview Sun")); sun_title->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); CenterContainer *sun_direction_center = memnew(CenterContainer); sun_direction = memnew(Control); sun_direction->set_custom_minimum_size(Size2(128, 128) * EDSCALE); sun_direction_center->add_child(sun_direction); - sun_vb->add_margin_child(TTR("Sun Direction"), sun_direction_center); + sun_vb->add_margin_child(TTRC("Sun Direction"), sun_direction_center); sun_direction->connect(SceneStringName(gui_input), callable_mp(this, &Node3DEditor::_sun_direction_input)); sun_direction->connect(SceneStringName(draw), callable_mp(this, &Node3DEditor::_sun_direction_draw)); sun_direction->set_default_cursor_shape(CURSOR_MOVE); @@ -9586,7 +9614,7 @@ void fragment() { VBoxContainer *sun_angle_altitude_vbox = memnew(VBoxContainer); sun_angle_altitude_vbox->set_h_size_flags(SIZE_EXPAND_FILL); Label *sun_angle_altitude_label = memnew(Label); - sun_angle_altitude_label->set_text(TTR("Angular Altitude")); + sun_angle_altitude_label->set_text(TTRC("Angular Altitude")); sun_angle_altitude_vbox->add_child(sun_angle_altitude_label); sun_angle_altitude = memnew(EditorSpinSlider); sun_angle_altitude->set_suffix(U"\u00B0"); @@ -9600,7 +9628,7 @@ void fragment() { sun_angle_azimuth_vbox->set_h_size_flags(SIZE_EXPAND_FILL); sun_angle_azimuth_vbox->set_custom_minimum_size(Vector2(100, 0)); Label *sun_angle_azimuth_label = memnew(Label); - sun_angle_azimuth_label->set_text(TTR("Azimuth")); + sun_angle_azimuth_label->set_text(TTRC("Azimuth")); sun_angle_azimuth_vbox->add_child(sun_angle_azimuth_label); sun_angle_azimuth = memnew(EditorSpinSlider); sun_angle_azimuth->set_suffix(U"\u00B0"); @@ -9617,7 +9645,7 @@ void fragment() { sun_color = memnew(ColorPickerButton); sun_color->set_edit_alpha(false); - sun_vb->add_margin_child(TTR("Sun Color"), sun_color); + sun_vb->add_margin_child(TTRC("Sun Color"), sun_color); sun_color->connect("color_changed", callable_mp(this, &Node3DEditor::_sun_set_color)); sun_color->get_popup()->connect("about_to_popup", callable_mp(EditorNode::get_singleton(), &EditorNode::setup_color_picker).bind(sun_color->get_picker())); @@ -9625,18 +9653,18 @@ void fragment() { sun_energy->set_max(64.0); sun_energy->set_min(0); sun_energy->set_step(0.05); - sun_vb->add_margin_child(TTR("Sun Energy"), sun_energy); + sun_vb->add_margin_child(TTRC("Sun Energy"), sun_energy); sun_energy->connect(SceneStringName(value_changed), callable_mp(this, &Node3DEditor::_sun_set_energy)); sun_shadow_max_distance = memnew(EditorSpinSlider); - sun_vb->add_margin_child(TTR("Shadow Max Distance"), sun_shadow_max_distance); + sun_vb->add_margin_child(TTRC("Shadow Max Distance"), sun_shadow_max_distance); sun_shadow_max_distance->connect(SceneStringName(value_changed), callable_mp(this, &Node3DEditor::_sun_set_shadow_max_distance)); sun_shadow_max_distance->set_min(1); sun_shadow_max_distance->set_max(4096); sun_add_to_scene = memnew(Button); - sun_add_to_scene->set_text(TTR("Add Sun to Scene")); - sun_add_to_scene->set_tooltip_text(TTR("Adds a DirectionalLight3D node matching the preview sun settings to the current scene.\nHold Shift while clicking to also add the preview environment to the current scene.")); + sun_add_to_scene->set_text(TTRC("Add Sun to Scene")); + sun_add_to_scene->set_tooltip_text(TTRC("Adds a DirectionalLight3D node matching the preview sun settings to the current scene.\nHold Shift while clicking to also add the preview environment to the current scene.")); sun_add_to_scene->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_add_sun_to_scene).bind(false)); sun_vb->add_spacer(); sun_vb->add_child(sun_add_to_scene); @@ -9661,57 +9689,57 @@ void fragment() { environ_title->set_theme_type_variation("HeaderMedium"); environ_vb->add_child(environ_title); - environ_title->set_text(TTR("Preview Environment")); + environ_title->set_text(TTRC("Preview Environment")); environ_title->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); environ_sky_color = memnew(ColorPickerButton); environ_sky_color->set_edit_alpha(false); environ_sky_color->connect("color_changed", callable_mp(this, &Node3DEditor::_environ_set_sky_color)); environ_sky_color->get_popup()->connect("about_to_popup", callable_mp(EditorNode::get_singleton(), &EditorNode::setup_color_picker).bind(environ_sky_color->get_picker())); - environ_vb->add_margin_child(TTR("Sky Color"), environ_sky_color); + environ_vb->add_margin_child(TTRC("Sky Color"), environ_sky_color); environ_ground_color = memnew(ColorPickerButton); environ_ground_color->connect("color_changed", callable_mp(this, &Node3DEditor::_environ_set_ground_color)); environ_ground_color->set_edit_alpha(false); environ_ground_color->get_popup()->connect("about_to_popup", callable_mp(EditorNode::get_singleton(), &EditorNode::setup_color_picker).bind(environ_ground_color->get_picker())); - environ_vb->add_margin_child(TTR("Ground Color"), environ_ground_color); + environ_vb->add_margin_child(TTRC("Ground Color"), environ_ground_color); environ_energy = memnew(EditorSpinSlider); environ_energy->set_max(8.0); environ_energy->set_min(0); environ_energy->set_step(0.05); environ_energy->connect(SceneStringName(value_changed), callable_mp(this, &Node3DEditor::_environ_set_sky_energy)); - environ_vb->add_margin_child(TTR("Sky Energy"), environ_energy); + environ_vb->add_margin_child(TTRC("Sky Energy"), environ_energy); HBoxContainer *fx_vb = memnew(HBoxContainer); fx_vb->set_h_size_flags(SIZE_EXPAND_FILL); environ_ao_button = memnew(Button); - environ_ao_button->set_text(TTR("AO")); + environ_ao_button->set_text(TTRC("AO")); environ_ao_button->set_h_size_flags(SIZE_EXPAND_FILL); environ_ao_button->set_toggle_mode(true); environ_ao_button->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_environ_set_ao), CONNECT_DEFERRED); fx_vb->add_child(environ_ao_button); environ_glow_button = memnew(Button); - environ_glow_button->set_text(TTR("Glow")); + environ_glow_button->set_text(TTRC("Glow")); environ_glow_button->set_h_size_flags(SIZE_EXPAND_FILL); environ_glow_button->set_toggle_mode(true); environ_glow_button->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_environ_set_glow), CONNECT_DEFERRED); fx_vb->add_child(environ_glow_button); environ_tonemap_button = memnew(Button); - environ_tonemap_button->set_text(TTR("Tonemap")); + environ_tonemap_button->set_text(TTRC("Tonemap")); environ_tonemap_button->set_h_size_flags(SIZE_EXPAND_FILL); environ_tonemap_button->set_toggle_mode(true); environ_tonemap_button->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_environ_set_tonemap), CONNECT_DEFERRED); fx_vb->add_child(environ_tonemap_button); environ_gi_button = memnew(Button); - environ_gi_button->set_text(TTR("GI")); + environ_gi_button->set_text(TTRC("GI")); environ_gi_button->set_h_size_flags(SIZE_EXPAND_FILL); environ_gi_button->set_toggle_mode(true); environ_gi_button->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_environ_set_gi), CONNECT_DEFERRED); fx_vb->add_child(environ_gi_button); - environ_vb->add_margin_child(TTR("Post Process"), fx_vb); + environ_vb->add_margin_child(TTRC("Post Process"), fx_vb); environ_add_to_scene = memnew(Button); - environ_add_to_scene->set_text(TTR("Add Environment to Scene")); - environ_add_to_scene->set_tooltip_text(TTR("Adds a WorldEnvironment node matching the preview environment settings to the current scene.\nHold Shift while clicking to also add the preview sun to the current scene.")); + environ_add_to_scene->set_text(TTRC("Add Environment to Scene")); + environ_add_to_scene->set_tooltip_text(TTRC("Adds a WorldEnvironment node matching the preview environment settings to the current scene.\nHold Shift while clicking to also add the preview sun to the current scene.")); environ_add_to_scene->connect(SceneStringName(pressed), callable_mp(this, &Node3DEditor::_add_environment_to_scene).bind(false)); environ_vb->add_spacer(); environ_vb->add_child(environ_add_to_scene); From 0138e33792e563f81e0aa64f2e308c7a17582e39 Mon Sep 17 00:00:00 2001 From: kobewi Date: Fri, 30 May 2025 14:44:14 +0200 Subject: [PATCH 048/144] Fix get_class_icon() ignoring fallback --- editor/editor_node.cpp | 6 ++++-- editor/editor_node.h | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 6188eeeecb..f1733d8f90 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -5202,9 +5202,11 @@ Ref EditorNode::get_object_icon(const Object *p_object, const String Ref EditorNode::get_class_icon(const String &p_class, const String &p_fallback) { ERR_FAIL_COND_V_MSG(p_class.is_empty(), nullptr, "Class name cannot be empty."); + const Pair key(p_class, p_fallback); + // Take from the local cache, if available. { - Ref *icon = class_icon_cache.getptr(p_class); + Ref *icon = class_icon_cache.getptr(key); if (icon) { return *icon; } @@ -5218,7 +5220,7 @@ Ref EditorNode::get_class_icon(const String &p_class, const String &p } Ref icon = _get_class_or_script_icon(p_class, script_path, p_fallback, true); - class_icon_cache[p_class] = icon; + class_icon_cache[key] = icon; return icon; } diff --git a/editor/editor_node.h b/editor/editor_node.h index 163075d0d2..e0886ce5be 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -484,7 +484,7 @@ private: PrintHandlerList print_handler; HashMap> icon_type_cache; - HashMap> class_icon_cache; + HashMap, Ref> class_icon_cache; ProjectUpgradeTool *project_upgrade_tool = nullptr; bool run_project_upgrade_tool = false; From 458850b2d9abc387f908df06d0d474dec5708c55 Mon Sep 17 00:00:00 2001 From: Anish Mishra Date: Tue, 27 May 2025 10:32:52 +0530 Subject: [PATCH 049/144] Add support for `OS.get_version_alias()` on Android --- doc/classes/OS.xml | 5 +++-- platform/android/os_android.cpp | 8 ++++++++ platform/android/os_android.h | 2 ++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index 926ce622e2..6ac50bc7c9 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -598,8 +598,9 @@ - Returns the branded version used in marketing, followed by the build number (on Windows) or the version number (on macOS). Examples include [code]11 (build 22000)[/code] and [code]Sequoia (15.0.0)[/code]. This value can then be appended to [method get_name] to get a full, human-readable operating system name and version combination for the operating system. Windows feature updates such as 24H2 are not contained in the resulting string, but Windows Server is recognized as such (e.g. [code]2025 (build 26100)[/code] for Windows Server 2025). - [b]Note:[/b] This method is only supported on Windows and macOS. On other operating systems, it returns the same value as [method get_version]. + Returns the branded version used in marketing, followed by the build number (on Windows), the version number (on macOS), or the SDK version and incremental build number (on Android). Examples include [code]11 (build 22000)[/code], [code]Sequoia (15.0.0)[/code], and [code]15 (SDK 35 build abc528-11988f)[/code]. + This value can then be appended to [method get_name] to get a full, human-readable operating system name and version combination for the operating system. Windows feature updates such as 24H2 are not contained in the resulting string, but Windows Server is recognized as such (e.g. [code]2025 (build 26100)[/code] for Windows Server 2025). + [b]Note:[/b] This method is only supported on Windows, macOS, and Android. On other operating systems, it returns the same value as [method get_version]. diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 5809c9463a..325d118fc8 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -327,6 +327,14 @@ String OS_Android::get_version() const { return ""; } +String OS_Android::get_version_alias() const { + String release = get_system_property("ro.build.version.release_or_codename"); + String sdk_version = get_system_property("ro.build.version.sdk"); + String build = get_system_property("ro.build.version.incremental"); + + return vformat("%s (SDK %s build %s)", release, sdk_version, build); +} + MainLoop *OS_Android::get_main_loop() const { return main_loop; } diff --git a/platform/android/os_android.h b/platform/android/os_android.h index 6813653504..c4a8c8f02b 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -123,6 +123,8 @@ public: virtual String get_name() const override; virtual String get_distribution_name() const override; virtual String get_version() const override; + virtual String get_version_alias() const override; + virtual MainLoop *get_main_loop() const override; void main_loop_begin(); From 617e12a6b4289d157850bf1e007d3c3e779e6be5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pa=CC=84vels=20Nadtoc=CC=8Cajevs?= <7645683+bruvzg@users.noreply.github.com> Date: Fri, 30 May 2025 11:15:06 +0300 Subject: [PATCH 050/144] [Windows] Drop support for Windows 7/8/8.1. --- doc/classes/@GlobalScope.xml | 1 - doc/classes/DisplayServer.xml | 2 +- doc/classes/OS.xml | 2 +- doc/classes/ProjectSettings.xml | 4 +- .../d3d12/rendering_context_driver_d3d12.h | 12 -- drivers/windows/thread_windows.cpp | 2 +- modules/mono/editor/hostfxr_resolver.cpp | 12 +- platform/windows/detect.py | 40 +--- platform/windows/display_server_windows.cpp | 130 +++---------- platform/windows/display_server_windows.h | 181 ------------------ platform/windows/os_windows.cpp | 35 +--- 11 files changed, 45 insertions(+), 376 deletions(-) diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index 9a0564d7a0..0c50104e80 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -876,7 +876,6 @@ [/csharp] [/codeblocks] [b]Note:[/b] Consider using [method push_error] and [method push_warning] to print error and warning messages instead of [method print] or [method print_rich]. This distinguishes them from print messages used for debugging purposes, while also displaying a stack trace when an error or warning is printed. - [b]Note:[/b] On Windows, only Windows 10 and later correctly displays ANSI escape codes in standard output. [b]Note:[/b] Output displayed in the editor supports clickable [code skip-lint][url=address]text[/url][/code] tags. The [code skip-lint][url][/code] tag's [code]address[/code] value is handled by [method OS.shell_open] when clicked. diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index d7b2c42763..460c9f39a1 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -1941,7 +1941,7 @@ Set active tablet driver name. Supported drivers: - - [code]winink[/code]: Windows Ink API, default (Windows 8.1+ required). + - [code]winink[/code]: Windows Ink API, default. - [code]wintab[/code]: Wacom Wintab API (compatible device driver required). - [code]dummy[/code]: Dummy driver, tablet input is disabled. [b]Note:[/b] This method is implemented only on Windows. diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index 926ce622e2..110d2ee243 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -588,7 +588,7 @@ Returns the exact production and build version of the operating system. This is different from the branded version used in marketing. This helps to distinguish between different releases of operating systems, including minor versions, and insider and custom builds. - - For Windows, the major and minor version are returned, as well as the build number. For example, the returned string may look like [code]10.0.9926[/code] for a build of Windows 10, and it may look like [code]6.1.7601[/code] for a build of Windows 7 SP1. + - For Windows, the major and minor version are returned, as well as the build number. For example, the returned string may look like [code]10.0.9926[/code] for a build of Windows 10. - For rolling distributions, such as Arch Linux, an empty string is returned. - For macOS and iOS, the major and minor version are returned, as well as the patch number. - For Android, the SDK version and the incremental build number are returned. If it's a custom ROM, it attempts to return its version instead. diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index fde926da72..1ffe7297ea 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -402,7 +402,7 @@ If [code]true[/code], microphone input will be allowed. This requires appropriate permissions to be set when exporting to Android or iOS. - [b]Note:[/b] If the operating system blocks access to audio input devices (due to the user's privacy settings), audio capture will only return silence. On Windows 10 and later, make sure that apps are allowed to access the microphone in the OS' privacy settings. + [b]Note:[/b] If the operating system blocks access to audio input devices (due to the user's privacy settings), audio capture will only return silence. On Windows, make sure that apps are allowed to access the microphone in the OS' privacy settings. Target mixing rate used for audio (in Hz). In general, it's better to not touch this and leave it to the host operating system. @@ -416,7 +416,7 @@ Specifies the preferred output latency in milliseconds for audio. Lower values will result in lower audio latency at the cost of increased CPU usage. Low values may result in audible crackling on slower hardware. Audio output latency may be constrained by the host operating system and audio hardware drivers. If the host can not provide the specified audio output latency then Godot will attempt to use the nearest latency allowed by the host. As such you should always use [method AudioServer.get_output_latency] to determine the actual audio output latency. Audio output latency can be overridden using the [code]--audio-output-latency <ms>[/code] command line argument. - [b]Note:[/b] This setting is ignored on Android, and on all versions of Windows prior to Windows 10. + [b]Note:[/b] This setting is ignored on Android. Safer override for [member audio/driver/output_latency] in the Web platform, to avoid audio issues especially on mobile devices. diff --git a/drivers/d3d12/rendering_context_driver_d3d12.h b/drivers/d3d12/rendering_context_driver_d3d12.h index 7ffe5afb80..20d4c7b135 100644 --- a/drivers/d3d12/rendering_context_driver_d3d12.h +++ b/drivers/d3d12/rendering_context_driver_d3d12.h @@ -42,19 +42,7 @@ #endif #ifdef DCOMP_ENABLED -#if (WINVER < _WIN32_WINNT_WIN8) && defined(_MSC_VER) -#pragma push_macro("NTDDI_VERSION") -#pragma push_macro("WINVER") -#undef NTDDI_VERSION -#undef WINVER -#define NTDDI_VERSION NTDDI_WIN8 -#define WINVER _WIN32_WINNT_WIN8 #include -#pragma pop_macro("WINVER") -#pragma pop_macro("NTDDI_VERSION") -#else -#include -#endif #endif #include diff --git a/drivers/windows/thread_windows.cpp b/drivers/windows/thread_windows.cpp index 2a734aab7c..183d104a61 100644 --- a/drivers/windows/thread_windows.cpp +++ b/drivers/windows/thread_windows.cpp @@ -45,7 +45,7 @@ static Error set_name(const String &p_name) { HANDLE hThread = GetCurrentThread(); HRESULT res = E_FAIL; if (w10_SetThreadDescription) { - res = w10_SetThreadDescription(hThread, (LPCWSTR)p_name.utf16().get_data()); + res = w10_SetThreadDescription(hThread, (LPCWSTR)p_name.utf16().get_data()); // Windows 10 Redstone (1607) only. } return SUCCEEDED(res) ? OK : ERR_INVALID_PARAMETER; } diff --git a/modules/mono/editor/hostfxr_resolver.cpp b/modules/mono/editor/hostfxr_resolver.cpp index 5766b64661..f3a0718065 100644 --- a/modules/mono/editor/hostfxr_resolver.cpp +++ b/modules/mono/editor/hostfxr_resolver.cpp @@ -130,19 +130,11 @@ bool get_latest_fxr(const String &fxr_root, String &r_fxr_path) { } #ifdef WINDOWS_ENABLED -typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL); - BOOL is_wow64() { BOOL wow64 = FALSE; - - LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)(void *)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process"); - - if (fnIsWow64Process) { - if (!fnIsWow64Process(GetCurrentProcess(), &wow64)) { - wow64 = FALSE; - } + if (!IsWow64Process(GetCurrentProcess(), &wow64)) { + wow64 = FALSE; } - return wow64; } #endif diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 1e7ca0ca03..3e808ac8a9 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -5,7 +5,7 @@ import sys from typing import TYPE_CHECKING import methods -from methods import print_error, print_info, print_warning +from methods import print_error, print_warning from platform_methods import detect_arch, validate_arch if TYPE_CHECKING: @@ -182,14 +182,6 @@ def get_opts(): return [ ("mingw_prefix", "MinGW prefix", mingw), - # Targeted Windows version: 7 (and later), minimum supported version - # XP support dropped after EOL due to missing API for IPv6 and other issues - # Vista support dropped after EOL due to GH-10243 - ( - "target_win_version", - "Targeted Windows version, >= 0x0601 (Windows 7)", - "0x0601", - ), EnumVariable("windows_subsystem", "Windows subsystem", "gui", ["gui", "console"], ignorecase=2), ("msvc_version", "MSVC version to use. Handled automatically by SCons if omitted.", ""), BoolVariable("use_mingw", "Use the Mingw compiler, even if MSVC is installed.", False), @@ -403,13 +395,6 @@ def configure_msvc(env: "SConsEnvironment"): # for notes on why this shouldn't be enabled for gcc env.AppendUnique(CCFLAGS=["/bigobj"]) - validate_win_version(env) - - if env["accesskit"]: - if int(env["target_win_version"], 16) < 0x0602: - print_info("AccessKit enabled, targeted Windows version changed to Windows 8 (0x602).") - env["target_win_version"] = "0x0602" # Accessibility API require Windows 8+ - env.AppendUnique( CPPDEFINES=[ "WINDOWS_ENABLED", @@ -417,8 +402,8 @@ def configure_msvc(env: "SConsEnvironment"): "WINMIDI_ENABLED", "TYPED_METHOD_BIND", "WIN32", - "WINVER=%s" % env["target_win_version"], - "_WIN32_WINNT=%s" % env["target_win_version"], + "WINVER=0x0A00", + "_WIN32_WINNT=0x0A00", ] ) env.AppendUnique(CPPDEFINES=["NOMINMAX"]) # disable bogus min/max WinDef.h macros @@ -447,6 +432,7 @@ def configure_msvc(env: "SConsEnvironment"): "gdi32", "IPHLPAPI", "Shlwapi", + "Shcore", "wsock32", "Ws2_32", "shell32", @@ -772,13 +758,6 @@ def configure_mingw(env: "SConsEnvironment"): ## Compile flags - validate_win_version(env) - - if env["accesskit"]: - if int(env["target_win_version"], 16) < 0x0602: - print_info("AccessKit enabled, targeted Windows version changed to Windows 8 (0x602).") - env["target_win_version"] = "0x0602" # Accessibility API require Windows 8+ - if not env["use_llvm"]: env.Append(CCFLAGS=["-mwindows"]) @@ -809,8 +788,8 @@ def configure_mingw(env: "SConsEnvironment"): env.Append(CPPDEFINES=["WINDOWS_ENABLED", "WASAPI_ENABLED", "WINMIDI_ENABLED"]) env.Append( CPPDEFINES=[ - ("WINVER", env["target_win_version"]), - ("_WIN32_WINNT", env["target_win_version"]), + "WINVER=0x0A00", + "_WIN32_WINNT=0x0A00", ] ) env.Append( @@ -824,6 +803,7 @@ def configure_mingw(env: "SConsEnvironment"): "iphlpapi", "shell32", "shlwapi", + "shcore", "wsock32", "ws2_32", "kernel32", @@ -958,9 +938,3 @@ def check_d3d12_installed(env, suffix): "https://docs.godotengine.org/en/latest/contributing/development/compiling/compiling_for_windows.html" ) sys.exit(255) - - -def validate_win_version(env): - if int(env["target_win_version"], 16) < 0x0601: - print_error("`target_win_version` should be 0x0601 or higher (Windows 7).") - sys.exit(255) diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 026ce2f092..f272c04fde 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -64,6 +64,7 @@ #include #include #include +#include #include #include #include @@ -1319,35 +1320,12 @@ typedef struct { int dpi; } EnumDpiData; -enum _MonitorDpiType { - MDT_Effective_DPI = 0, - MDT_Angular_DPI = 1, - MDT_Raw_DPI = 2, - MDT_Default = MDT_Effective_DPI -}; - -static int QueryDpiForMonitor(HMONITOR hmon, _MonitorDpiType dpiType = MDT_Default) { +static int QueryDpiForMonitor(HMONITOR hmon, MONITOR_DPI_TYPE dpiType = MDT_DEFAULT) { int dpiX = 96, dpiY = 96; - static HMODULE Shcore = nullptr; - typedef HRESULT(WINAPI * GetDPIForMonitor_t)(HMONITOR hmonitor, _MonitorDpiType dpiType, UINT * dpiX, UINT * dpiY); - static GetDPIForMonitor_t getDPIForMonitor = nullptr; - - if (Shcore == nullptr) { - Shcore = LoadLibraryW(L"Shcore.dll"); - getDPIForMonitor = Shcore ? (GetDPIForMonitor_t)(void *)GetProcAddress(Shcore, "GetDpiForMonitor") : nullptr; - - if ((Shcore == nullptr) || (getDPIForMonitor == nullptr)) { - if (Shcore) { - FreeLibrary(Shcore); - } - Shcore = (HMODULE)INVALID_HANDLE_VALUE; - } - } - UINT x = 0, y = 0; - if (hmon && (Shcore != (HMODULE)INVALID_HANDLE_VALUE)) { - HRESULT hr = getDPIForMonitor(hmon, dpiType /*MDT_Effective_DPI*/, &x, &y); + if (hmon) { + HRESULT hr = GetDpiForMonitor(hmon, dpiType, &x, &y); if (SUCCEEDED(hr) && (x > 0) && (y > 0)) { dpiX = (int)x; dpiY = (int)y; @@ -1396,9 +1374,8 @@ Color DisplayServerWindows::screen_get_pixel(const Point2i &p_position) const { POINT p; p.x = pos.x; p.y = pos.y; - if (win81p_LogicalToPhysicalPointForPerMonitorDPI) { - win81p_LogicalToPhysicalPointForPerMonitorDPI(nullptr, &p); - } + LogicalToPhysicalPointForPerMonitorDPI(nullptr, &p); + HDC dc = GetDC(nullptr); if (dc) { COLORREF col = GetPixel(dc, p.x, p.y); @@ -1436,10 +1413,8 @@ Ref DisplayServerWindows::screen_get_image(int p_screen) const { POINT p2; p2.x = pos.x + size.x; p2.y = pos.y + size.y; - if (win81p_LogicalToPhysicalPointForPerMonitorDPI) { - win81p_LogicalToPhysicalPointForPerMonitorDPI(nullptr, &p1); - win81p_LogicalToPhysicalPointForPerMonitorDPI(nullptr, &p2); - } + LogicalToPhysicalPointForPerMonitorDPI(nullptr, &p1); + LogicalToPhysicalPointForPerMonitorDPI(nullptr, &p2); Ref img; HDC dc = GetDC(nullptr); @@ -1492,10 +1467,8 @@ Ref DisplayServerWindows::screen_get_image_rect(const Rect2i &p_rect) con POINT p2; p2.x = pos.x + size.x; p2.y = pos.y + size.y; - if (win81p_LogicalToPhysicalPointForPerMonitorDPI) { - win81p_LogicalToPhysicalPointForPerMonitorDPI(0, &p1); - win81p_LogicalToPhysicalPointForPerMonitorDPI(0, &p2); - } + LogicalToPhysicalPointForPerMonitorDPI(0, &p1); + LogicalToPhysicalPointForPerMonitorDPI(0, &p2); Ref img; HDC dc = GetDC(0); @@ -1954,10 +1927,8 @@ Size2i DisplayServerWindows::window_get_title_size(const String &p_title, Window ClientToScreen(wd.hWnd, (POINT *)&rect.left); ClientToScreen(wd.hWnd, (POINT *)&rect.right); - if (win81p_PhysicalToLogicalPointForPerMonitorDPI) { - win81p_PhysicalToLogicalPointForPerMonitorDPI(nullptr, (POINT *)&rect.left); - win81p_PhysicalToLogicalPointForPerMonitorDPI(nullptr, (POINT *)&rect.right); - } + PhysicalToLogicalPointForPerMonitorDPI(nullptr, (POINT *)&rect.left); + PhysicalToLogicalPointForPerMonitorDPI(nullptr, (POINT *)&rect.right); size.x += (rect.right - rect.left); size.y = MAX(size.y, rect.bottom - rect.top); @@ -3692,10 +3663,8 @@ String DisplayServerWindows::_get_keyboard_layout_display_name(const String &p_k WCHAR buffer[MAX_PATH] = {}; DWORD buffer_size = MAX_PATH; if (RegGetValueW(key, (LPCWSTR)p_klid.utf16().get_data(), L"Layout Display Name", RRF_RT_REG_SZ, nullptr, buffer, &buffer_size) == ERROR_SUCCESS) { - if (load_indirect_string) { - if (load_indirect_string(buffer, buffer, buffer_size, nullptr) == S_OK) { - ret = String::utf16((const char16_t *)buffer, buffer_size); - } + if (SHLoadIndirectString(buffer, buffer, buffer_size, nullptr) == S_OK) { + ret = String::utf16((const char16_t *)buffer, buffer_size); } } else { if (RegGetValueW(key, (LPCWSTR)p_klid.utf16().get_data(), L"Layout Text", RRF_RT_REG_SZ, nullptr, buffer, &buffer_size) == ERROR_SUCCESS) { @@ -4307,12 +4276,6 @@ void DisplayServerWindows::set_context(Context p_context) { } bool DisplayServerWindows::is_window_transparency_available() const { - BOOL dwm_enabled = true; - if (DwmIsCompositionEnabled(&dwm_enabled) == S_OK) { // Note: Always enabled on Windows 8+, this check can be removed after Windows 7 support is dropped. - if (!dwm_enabled) { - return false; - } - } #if defined(RD_ENABLED) if (rendering_device && !rendering_device->is_composite_alpha_supported()) { return false; @@ -5089,13 +5052,13 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA break; } - if ((tablet_get_current_driver() != "winink") || !winink_available) { + if (tablet_get_current_driver() != "winink") { break; } uint32_t pointer_id = LOWORD(wParam); POINTER_INPUT_TYPE pointer_type = PT_POINTER; - if (!win8p_GetPointerType(pointer_id, &pointer_type)) { + if (!GetPointerType(pointer_id, &pointer_type)) { break; } @@ -5118,13 +5081,13 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA break; } - if ((tablet_get_current_driver() != "winink") || !winink_available) { + if (tablet_get_current_driver() != "winink") { break; } uint32_t pointer_id = LOWORD(wParam); POINTER_INPUT_TYPE pointer_type = PT_POINTER; - if (!win8p_GetPointerType(pointer_id, &pointer_type)) { + if (!GetPointerType(pointer_id, &pointer_type)) { break; } @@ -5230,13 +5193,13 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA break; } - if ((tablet_get_current_driver() != "winink") || !winink_available) { + if (tablet_get_current_driver() != "winink") { break; } uint32_t pointer_id = LOWORD(wParam); POINTER_INPUT_TYPE pointer_type = PT_POINTER; - if (!win8p_GetPointerType(pointer_id, &pointer_type)) { + if (!GetPointerType(pointer_id, &pointer_type)) { break; } @@ -5245,7 +5208,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } POINTER_PEN_INFO pen_info; - if (!win8p_GetPointerPenInfo(pointer_id, &pen_info)) { + if (!GetPointerPenInfo(pointer_id, &pen_info)) { break; } @@ -6592,16 +6555,6 @@ GetImmersiveColorFromColorSetExPtr DisplayServerWindows::GetImmersiveColorFromCo GetImmersiveColorTypeFromNamePtr DisplayServerWindows::GetImmersiveColorTypeFromName = nullptr; GetImmersiveUserColorSetPreferencePtr DisplayServerWindows::GetImmersiveUserColorSetPreference = nullptr; -// Windows Ink API. -bool DisplayServerWindows::winink_available = false; -GetPointerTypePtr DisplayServerWindows::win8p_GetPointerType = nullptr; -GetPointerPenInfoPtr DisplayServerWindows::win8p_GetPointerPenInfo = nullptr; -LogicalToPhysicalPointForPerMonitorDPIPtr DisplayServerWindows::win81p_LogicalToPhysicalPointForPerMonitorDPI = nullptr; -PhysicalToLogicalPointForPerMonitorDPIPtr DisplayServerWindows::win81p_PhysicalToLogicalPointForPerMonitorDPI = nullptr; - -// Shell API, -SHLoadIndirectStringPtr DisplayServerWindows::load_indirect_string = nullptr; - Vector2i _get_device_ids(const String &p_device_name) { if (p_device_name.is_empty()) { return Vector2i(); @@ -6717,7 +6670,7 @@ void DisplayServerWindows::tablet_set_current_driver(const String &p_driver) { String driver = p_driver; if (driver == "auto") { - if (winink_available && !winink_disabled) { + if (!winink_disabled) { driver = "winink"; } else if (wintab_available) { driver = "wintab"; @@ -6795,14 +6748,8 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win FreeLibrary(nt_lib); } - // Load Shell API. - HMODULE shellapi_lib = LoadLibraryW(L"shlwapi.dll"); - if (shellapi_lib) { - load_indirect_string = (SHLoadIndirectStringPtr)(void *)GetProcAddress(shellapi_lib, "SHLoadIndirectString"); - } - - // Load UXTheme, available on Windows 10+ only. - if (os_ver.dwBuildNumber >= 10240) { + // Load UXTheme. + if (os_ver.dwBuildNumber >= 10240) { // Not available on Wine, use only if real Windows 10/11 detected. HMODULE ux_theme_lib = LoadLibraryW(L"uxtheme.dll"); if (ux_theme_lib) { ShouldAppsUseDarkMode = (ShouldAppsUseDarkModePtr)(void *)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(132)); @@ -6847,22 +6794,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win } tablet_drivers.push_back("auto"); - - // Note: Windows Ink API for pen input, available on Windows 8+ only. - // Note: DPI conversion API, available on Windows 8.1+ only. - HMODULE user32_lib = LoadLibraryW(L"user32.dll"); - if (user32_lib) { - win8p_GetPointerType = (GetPointerTypePtr)(void *)GetProcAddress(user32_lib, "GetPointerType"); - win8p_GetPointerPenInfo = (GetPointerPenInfoPtr)(void *)GetProcAddress(user32_lib, "GetPointerPenInfo"); - win81p_LogicalToPhysicalPointForPerMonitorDPI = (LogicalToPhysicalPointForPerMonitorDPIPtr)(void *)GetProcAddress(user32_lib, "LogicalToPhysicalPointForPerMonitorDPI"); - win81p_PhysicalToLogicalPointForPerMonitorDPI = (PhysicalToLogicalPointForPerMonitorDPIPtr)(void *)GetProcAddress(user32_lib, "PhysicalToLogicalPointForPerMonitorDPI"); - - winink_available = win8p_GetPointerType && win8p_GetPointerPenInfo; - } - - if (winink_available) { - tablet_drivers.push_back("winink"); - } + tablet_drivers.push_back("winink"); // Note: Wacom WinTab driver API for pen input, for devices incompatible with Windows Ink. HMODULE wintab_lib = LoadLibraryW(L"wintab32.dll"); @@ -6904,17 +6836,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win } if (OS::get_singleton()->is_hidpi_allowed()) { - HMODULE Shcore = LoadLibraryW(L"Shcore.dll"); - - if (Shcore != nullptr) { - typedef HRESULT(WINAPI * SetProcessDpiAwareness_t)(SHC_PROCESS_DPI_AWARENESS); - - SetProcessDpiAwareness_t SetProcessDpiAwareness = (SetProcessDpiAwareness_t)(void *)GetProcAddress(Shcore, "SetProcessDpiAwareness"); - - if (SetProcessDpiAwareness) { - SetProcessDpiAwareness(SHC_PROCESS_SYSTEM_DPI_AWARE); - } - } + SetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE); } HMODULE comctl32 = LoadLibraryW(L"comctl32.dll"); diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index 94f7dcc6bf..c892bd2f58 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -172,165 +172,6 @@ typedef PreferredAppMode(WINAPI *SetPreferredAppModePtr)(PreferredAppMode appMod typedef void(WINAPI *RefreshImmersiveColorPolicyStatePtr)(); typedef void(WINAPI *FlushMenuThemesPtr)(); -// Windows Ink API -#ifndef POINTER_STRUCTURES - -#define POINTER_STRUCTURES - -typedef DWORD POINTER_INPUT_TYPE; -typedef UINT32 POINTER_FLAGS; -typedef UINT32 PEN_FLAGS; -typedef UINT32 PEN_MASK; - -#ifndef PEN_FLAG_INVERTED -#define PEN_FLAG_INVERTED 0x00000002 -#endif - -#ifndef PEN_FLAG_ERASER -#define PEN_FLAG_ERASER 0x00000004 -#endif - -#ifndef PEN_MASK_PRESSURE -#define PEN_MASK_PRESSURE 0x00000001 -#endif - -#ifndef PEN_MASK_TILT_X -#define PEN_MASK_TILT_X 0x00000004 -#endif - -#ifndef PEN_MASK_TILT_Y -#define PEN_MASK_TILT_Y 0x00000008 -#endif - -#ifndef POINTER_MESSAGE_FLAG_FIRSTBUTTON -#define POINTER_MESSAGE_FLAG_FIRSTBUTTON 0x00000010 -#endif - -#ifndef POINTER_MESSAGE_FLAG_SECONDBUTTON -#define POINTER_MESSAGE_FLAG_SECONDBUTTON 0x00000020 -#endif - -#ifndef POINTER_MESSAGE_FLAG_THIRDBUTTON -#define POINTER_MESSAGE_FLAG_THIRDBUTTON 0x00000040 -#endif - -#ifndef POINTER_MESSAGE_FLAG_FOURTHBUTTON -#define POINTER_MESSAGE_FLAG_FOURTHBUTTON 0x00000080 -#endif - -#ifndef POINTER_MESSAGE_FLAG_FIFTHBUTTON -#define POINTER_MESSAGE_FLAG_FIFTHBUTTON 0x00000100 -#endif - -#ifndef IS_POINTER_FLAG_SET_WPARAM -#define IS_POINTER_FLAG_SET_WPARAM(wParam, flag) (((DWORD)HIWORD(wParam) & (flag)) == (flag)) -#endif - -#ifndef IS_POINTER_FIRSTBUTTON_WPARAM -#define IS_POINTER_FIRSTBUTTON_WPARAM(wParam) IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_FIRSTBUTTON) -#endif - -#ifndef IS_POINTER_SECONDBUTTON_WPARAM -#define IS_POINTER_SECONDBUTTON_WPARAM(wParam) IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_SECONDBUTTON) -#endif - -#ifndef IS_POINTER_THIRDBUTTON_WPARAM -#define IS_POINTER_THIRDBUTTON_WPARAM(wParam) IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_THIRDBUTTON) -#endif - -#ifndef IS_POINTER_FOURTHBUTTON_WPARAM -#define IS_POINTER_FOURTHBUTTON_WPARAM(wParam) IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_FOURTHBUTTON) -#endif - -#ifndef IS_POINTER_FIFTHBUTTON_WPARAM -#define IS_POINTER_FIFTHBUTTON_WPARAM(wParam) IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_FIFTHBUTTON) -#endif - -#ifndef GET_POINTERID_WPARAM -#define GET_POINTERID_WPARAM(wParam) (LOWORD(wParam)) -#endif - -#if WINVER < 0x0602 -enum tagPOINTER_INPUT_TYPE { - PT_POINTER = 0x00000001, - PT_TOUCH = 0x00000002, - PT_PEN = 0x00000003, - PT_MOUSE = 0x00000004, - PT_TOUCHPAD = 0x00000005 -}; - -typedef enum tagPOINTER_BUTTON_CHANGE_TYPE { - POINTER_CHANGE_NONE, - POINTER_CHANGE_FIRSTBUTTON_DOWN, - POINTER_CHANGE_FIRSTBUTTON_UP, - POINTER_CHANGE_SECONDBUTTON_DOWN, - POINTER_CHANGE_SECONDBUTTON_UP, - POINTER_CHANGE_THIRDBUTTON_DOWN, - POINTER_CHANGE_THIRDBUTTON_UP, - POINTER_CHANGE_FOURTHBUTTON_DOWN, - POINTER_CHANGE_FOURTHBUTTON_UP, - POINTER_CHANGE_FIFTHBUTTON_DOWN, - POINTER_CHANGE_FIFTHBUTTON_UP, -} POINTER_BUTTON_CHANGE_TYPE; - -typedef struct tagPOINTER_INFO { - POINTER_INPUT_TYPE pointerType; - UINT32 pointerId; - UINT32 frameId; - POINTER_FLAGS pointerFlags; - HANDLE sourceDevice; - HWND hwndTarget; - POINT ptPixelLocation; - POINT ptHimetricLocation; - POINT ptPixelLocationRaw; - POINT ptHimetricLocationRaw; - DWORD dwTime; - UINT32 historyCount; - INT32 InputData; - DWORD dwKeyStates; - UINT64 PerformanceCount; - POINTER_BUTTON_CHANGE_TYPE ButtonChangeType; -} POINTER_INFO; - -typedef struct tagPOINTER_PEN_INFO { - POINTER_INFO pointerInfo; - PEN_FLAGS penFlags; - PEN_MASK penMask; - UINT32 pressure; - UINT32 rotation; - INT32 tiltX; - INT32 tiltY; -} POINTER_PEN_INFO; -#endif - -#endif //POINTER_STRUCTURES - -#ifndef WM_POINTERUPDATE -#define WM_POINTERUPDATE 0x0245 -#endif - -#ifndef WM_POINTERENTER -#define WM_POINTERENTER 0x0249 -#endif - -#ifndef WM_POINTERLEAVE -#define WM_POINTERLEAVE 0x024A -#endif - -#ifndef WM_POINTERDOWN -#define WM_POINTERDOWN 0x0246 -#endif - -#ifndef WM_POINTERUP -#define WM_POINTERUP 0x0247 -#endif - -typedef BOOL(WINAPI *GetPointerTypePtr)(uint32_t p_id, POINTER_INPUT_TYPE *p_type); -typedef BOOL(WINAPI *GetPointerPenInfoPtr)(uint32_t p_id, POINTER_PEN_INFO *p_pen_info); -typedef BOOL(WINAPI *LogicalToPhysicalPointForPerMonitorDPIPtr)(HWND hwnd, LPPOINT lpPoint); -typedef BOOL(WINAPI *PhysicalToLogicalPointForPerMonitorDPIPtr)(HWND hwnd, LPPOINT lpPoint); -typedef HRESULT(WINAPI *SHLoadIndirectStringPtr)(PCWSTR pszSource, PWSTR pszOutBuf, UINT cchOutBuf, void **ppvReserved); - typedef struct { BYTE bWidth; // Width, in pixels, of the image BYTE bHeight; // Height, in pixels, of the image @@ -349,16 +190,6 @@ typedef struct { ICONDIRENTRY idEntries[1]; // An entry for each image (idCount of 'em) } ICONDIR, *LPICONDIR; -typedef enum _SHC_PROCESS_DPI_AWARENESS { - SHC_PROCESS_DPI_UNAWARE = 0, - SHC_PROCESS_SYSTEM_DPI_AWARE = 1, - SHC_PROCESS_PER_MONITOR_DPI_AWARE = 2, -} SHC_PROCESS_DPI_AWARENESS; - -#ifndef WS_EX_NOREDIRECTIONBITMAP -#define WS_EX_NOREDIRECTIONBITMAP 0x00200000L -#endif - class DropTargetWindows; #ifndef WDA_EXCLUDEFROMCAPTURE @@ -389,18 +220,6 @@ class DisplayServerWindows : public DisplayServer { static WTPacketPtr wintab_WTPacket; static WTEnablePtr wintab_WTEnable; - // Windows Ink API - static bool winink_available; - static GetPointerTypePtr win8p_GetPointerType; - static GetPointerPenInfoPtr win8p_GetPointerPenInfo; - - // DPI conversion API - static LogicalToPhysicalPointForPerMonitorDPIPtr win81p_LogicalToPhysicalPointForPerMonitorDPI; - static PhysicalToLogicalPointForPerMonitorDPIPtr win81p_PhysicalToLogicalPointForPerMonitorDPI; - - // Shell API - static SHLoadIndirectStringPtr load_indirect_string; - void _update_tablet_ctx(const String &p_old_driver, const String &p_new_driver); String tablet_driver; Vector tablet_drivers; diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 19c5f67ec0..14d34fb117 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -501,22 +501,15 @@ Error OS_Windows::open_dynamic_library(const String &p_path, void *&p_library_ha } } - typedef DLL_DIRECTORY_COOKIE(WINAPI * PAddDllDirectory)(PCWSTR); - typedef BOOL(WINAPI * PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE); - - PAddDllDirectory add_dll_directory = (PAddDllDirectory)(void *)GetProcAddress(GetModuleHandle("kernel32.dll"), "AddDllDirectory"); - PRemoveDllDirectory remove_dll_directory = (PRemoveDllDirectory)(void *)GetProcAddress(GetModuleHandle("kernel32.dll"), "RemoveDllDirectory"); - - bool has_dll_directory_api = ((add_dll_directory != nullptr) && (remove_dll_directory != nullptr)); DLL_DIRECTORY_COOKIE cookie = nullptr; String dll_path = fix_path(load_path); String dll_dir = fix_path(ProjectSettings::get_singleton()->globalize_path(load_path.get_base_dir())); - if (p_data != nullptr && p_data->also_set_library_path && has_dll_directory_api) { - cookie = add_dll_directory((LPCWSTR)(dll_dir.utf16().get_data())); + if (p_data != nullptr && p_data->also_set_library_path) { + cookie = AddDllDirectory((LPCWSTR)(dll_dir.utf16().get_data())); } - p_library_handle = (void *)LoadLibraryExW((LPCWSTR)(dll_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)(dll_path.utf16().get_data()), nullptr, (p_data != nullptr && p_data->also_set_library_path) ? LOAD_LIBRARY_SEARCH_DEFAULT_DIRS : 0); if (!p_library_handle) { if (p_data != nullptr && p_data->generate_temp_files) { DirAccess::remove_absolute(load_path); @@ -548,7 +541,7 @@ Error OS_Windows::open_dynamic_library(const String &p_path, void *&p_library_ha #endif if (cookie) { - remove_dll_directory(cookie); + RemoveDllDirectory(cookie); } if (p_data != nullptr && p_data->r_resolved_path != nullptr) { @@ -644,24 +637,6 @@ String OS_Windows::get_version_alias() const { windows_string += "10"; } } - } else if (fow.dwMajorVersion == 6 && fow.dwMinorVersion == 3) { - if (fow.wProductType != VER_NT_WORKSTATION) { - windows_string = "Server 2012 R2"; - } else { - windows_string += "8.1"; - } - } else if (fow.dwMajorVersion == 6 && fow.dwMinorVersion == 2) { - if (fow.wProductType != VER_NT_WORKSTATION) { - windows_string += "Server 2012"; - } else { - windows_string += "8"; - } - } else if (fow.dwMajorVersion == 6 && fow.dwMinorVersion == 1) { - if (fow.wProductType != VER_NT_WORKSTATION) { - windows_string = "Server 2008 R2"; - } else { - windows_string += "7"; - } } else { windows_string += "Unknown"; } @@ -2713,7 +2688,7 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) { GetConsoleMode(stdoutHandle, &outMode); outMode |= ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING; if (!SetConsoleMode(stdoutHandle, outMode)) { - // Windows 8.1 or below, or Windows 10 prior to Anniversary Update. + // Windows 10 prior to Anniversary Update. print_verbose("Can't set the ENABLE_VIRTUAL_TERMINAL_PROCESSING Windows console mode. `print_rich()` will not work as expected."); } From 3198b7bea21d51d398a474fdfbada8af4d559564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pa=CC=84vels=20Nadtoc=CC=8Cajevs?= <7645683+bruvzg@users.noreply.github.com> Date: Fri, 30 May 2025 17:55:27 +0300 Subject: [PATCH 051/144] [Accessibility] Always auto-translation mode for names/descriptions. --- editor/plugins/script_editor_plugin.cpp | 6 ++---- scene/main/node.cpp | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 5774a10410..b9c84c33c8 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -1747,10 +1747,7 @@ void ScriptEditor::_notification(int p_what) { [[fallthrough]]; } - case NOTIFICATION_TRANSLATION_CHANGED: { - disk_changed_list->set_accessibility_name(TTR("The following files are newer on disk")); - [[fallthrough]]; - } + case NOTIFICATION_TRANSLATION_CHANGED: case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: case NOTIFICATION_THEME_CHANGED: { tab_container->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SNAME("ScriptEditor"), EditorStringName(EditorStyles))); @@ -4463,6 +4460,7 @@ ScriptEditor::ScriptEditor(WindowWrapper *p_wrapper) { disk_changed_list = memnew(Tree); disk_changed_list->set_hide_root(true); disk_changed_list->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); + disk_changed_list->set_accessibility_name(TTRC("The following files are newer on disk")); disk_changed_list->set_v_size_flags(SIZE_EXPAND_FILL); vbc->add_child(disk_changed_list); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index fc7589a176..c75255832d 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1465,7 +1465,7 @@ void Node::set_accessibility_name(const String &p_name) { } String Node::get_accessibility_name() const { - return atr(data.accessibility_name); + return tr(data.accessibility_name); } void Node::set_accessibility_description(const String &p_description) { @@ -1477,7 +1477,7 @@ void Node::set_accessibility_description(const String &p_description) { } String Node::get_accessibility_description() const { - return atr(data.accessibility_description); + return tr(data.accessibility_description); } void Node::set_accessibility_live(DisplayServer::AccessibilityLiveMode p_mode) { From 658d3736f42e4e393796b3c04d8543104ca67548 Mon Sep 17 00:00:00 2001 From: Fredia Huya-Kouadio Date: Fri, 30 May 2025 09:39:53 -0700 Subject: [PATCH 052/144] Update the documentation for `JavaClassWrapper` and `AndroidRuntimePlugin` Follow-up to https://github.com/godotengine/godot-docs/pull/10979 --- doc/classes/JavaClassWrapper.xml | 1 + .../godot/plugin/AndroidRuntimePlugin.kt | 38 ++----------------- 2 files changed, 5 insertions(+), 34 deletions(-) diff --git a/doc/classes/JavaClassWrapper.xml b/doc/classes/JavaClassWrapper.xml index ad99374b9c..24552e8af3 100644 --- a/doc/classes/JavaClassWrapper.xml +++ b/doc/classes/JavaClassWrapper.xml @@ -18,6 +18,7 @@ [b]Warning:[/b] When calling Java methods, be sure to check [method JavaClassWrapper.get_exception] to check if the method threw an exception. + $DOCS_URL/tutorials/platform/android/javaclasswrapper_and_androidruntimeplugin.html diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/AndroidRuntimePlugin.kt b/platform/android/java/lib/src/org/godotengine/godot/plugin/AndroidRuntimePlugin.kt index 8f0f2bdfb1..35ff7d6fa1 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/plugin/AndroidRuntimePlugin.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/AndroidRuntimePlugin.kt @@ -34,51 +34,21 @@ import org.godotengine.godot.Godot import org.godotengine.godot.variant.Callable /** - * Provides access to the Android runtime capabilities. + * Built-in Godot Android plugin used to provide access to the Android runtime capabilities. * - * For example, from gdscript, developers can use [getApplicationContext] to access system services - * and check if the device supports vibration. - * - * var android_runtime = Engine.get_singleton("AndroidRuntime") - * if android_runtime: - * print("Checking if the device supports vibration") - * var vibrator_service = android_runtime.getApplicationContext().getSystemService("vibrator") - * if vibrator_service: - * if vibrator_service.hasVibrator(): - * print("Vibration is supported on device!") - * else: - * printerr("Vibration is not supported on device") - * else: - * printerr("Unable to retrieve the vibrator service") - * else: - * printerr("Couldn't find AndroidRuntime singleton") - * - * - * Or it can be used to display an Android native toast from gdscript - * - * var android_runtime = Engine.get_singleton("AndroidRuntime") - * if android_runtime: - * var activity = android_runtime.getActivity() - * - * var toastCallable = func (): - * var ToastClass = JavaClassWrapper.wrap("android.widget.Toast") - * ToastClass.makeText(activity, "This is a test", ToastClass.LENGTH_LONG).show() - * - * activity.runOnUiThread(android_runtime.createRunnableFromGodotCallable(toastCallable)) - * else: - * printerr("Unable to access android runtime") + * @see Integrating with Android APIs */ class AndroidRuntimePlugin(godot: Godot) : GodotPlugin(godot) { override fun getPluginName() = "AndroidRuntime" /** - * Provides access to the application context to GDScript + * Provides access to the application [android.content.Context] to GDScript */ @UsedByGodot fun getApplicationContext() = activity?.applicationContext /** - * Provides access to the host activity to GDScript + * Provides access to the host [android.app.Activity] to GDScript */ @UsedByGodot override fun getActivity() = super.getActivity() From 3b70fbdc3cd0fea0e8c3de193ab6c8db2d37049b Mon Sep 17 00:00:00 2001 From: devloglogan Date: Tue, 10 Dec 2024 13:41:04 -0600 Subject: [PATCH 053/144] Implement motion vectors in mobile renderer --- .../platform/openxr_vulkan_extension.cpp | 4 + .../forward_mobile/render_forward_mobile.cpp | 111 +++++-- .../forward_mobile/render_forward_mobile.h | 14 +- .../scene_shader_forward_mobile.cpp | 7 +- .../scene_shader_forward_mobile.h | 1 + .../forward_mobile/scene_forward_mobile.glsl | 300 ++++++++++++++---- .../scene_forward_mobile_inc.glsl | 6 +- .../storage_rd/render_scene_buffers_rd.cpp | 6 + .../storage_rd/render_scene_buffers_rd.h | 2 + .../storage_rd/texture_storage.cpp | 8 + .../renderer_rd/storage_rd/texture_storage.h | 3 +- 11 files changed, 373 insertions(+), 89 deletions(-) diff --git a/modules/openxr/extensions/platform/openxr_vulkan_extension.cpp b/modules/openxr/extensions/platform/openxr_vulkan_extension.cpp index f935dde444..bec4940568 100644 --- a/modules/openxr/extensions/platform/openxr_vulkan_extension.cpp +++ b/modules/openxr/extensions/platform/openxr_vulkan_extension.cpp @@ -320,6 +320,10 @@ bool OpenXRVulkanExtension::get_swapchain_image_data(XrSwapchain p_swapchain, in format = RenderingDevice::DATA_FORMAT_B8G8R8A8_UINT; usage_flags |= RenderingDevice::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; break; + case VK_FORMAT_R16G16B16A16_SFLOAT: + format = RenderingDevice::DATA_FORMAT_R16G16B16A16_SFLOAT; + usage_flags |= RenderingDevice::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + break; case VK_FORMAT_D32_SFLOAT: format = RenderingDevice::DATA_FORMAT_D32_SFLOAT; usage_flags |= RenderingDevice::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index d3e1abc7c9..c9d0d7b63c 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -166,6 +166,34 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RenderSceneBu ERR_FAIL_NULL(render_buffers); // Huh? really? } +RID RendererSceneRenderImplementation::RenderForwardMobile::RenderBufferDataForwardMobile::get_motion_vectors_fb() { + ERR_FAIL_NULL_V(render_buffers, RID()); + + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + ERR_FAIL_NULL_V(texture_storage, RID()); + + RID velocity = render_buffers->get_velocity_buffer(false); + RID velocity_depth = render_buffers->get_velocity_depth_buffer(); + + if (velocity.is_valid() && velocity_depth.is_valid()) { + Vector textures; + textures.push_back(velocity); + textures.push_back(velocity_depth); + + Vector passes; + RD::FramebufferPass pass; + pass.color_attachments.push_back(0); + pass.depth_attachment = 1; + passes.push_back(pass); + + uint32_t view_count = render_buffers->get_view_count(); + + return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count); + } + + return RID(); +} + RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(FramebufferConfigType p_config_type) { ERR_FAIL_NULL_V(render_buffers, RID()); @@ -776,19 +804,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RENDER_TIMESTAMP("Setup 3D Scene"); - /* TODO - // check if we need motion vectors - if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) { - p_render_data->scene_data->calculate_motion_vectors = true; - } else if (_compositor_effects_has_flag(p_render_data, RS::COMPOSITOR_EFFECT_FLAG_NEEDS_MOTION_VECTORS)) { - p_render_data->scene_data->calculate_motion_vectors = true; - } else if (render target has velocity override) { // TODO - p_render_data->scene_data->calculate_motion_vectors = true; - } else { - p_render_data->scene_data->calculate_motion_vectors = false; - } - */ - p_render_data->scene_data->calculate_motion_vectors = false; // for now, not yet supported... + p_render_data->scene_data->calculate_motion_vectors = RendererRD::TextureStorage::get_singleton()->render_target_get_override_velocity(rb->get_render_target()).is_valid(); p_render_data->scene_data->directional_light_count = 0; p_render_data->scene_data->opaque_prepass_threshold = 0.0; @@ -1098,6 +1114,25 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color breadcrumb = RDD::BreadcrumbMarker::REFLECTION_PROBES; } + if (rb_data.is_valid() && p_render_data->scene_data->calculate_motion_vectors) { + RID mv_fb = rb_data->get_motion_vectors_fb(); + + if (mv_fb.is_valid()) { + RENDER_TIMESTAMP("Render Motion Vectors"); + + Vector mv_pass_clear; + mv_pass_clear.push_back(Color(0, 0, 0, 0)); + + RD::get_singleton()->draw_command_begin_label("Render Motion Vectors"); + + RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID(), samplers); + RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_MOTION_VECTORS, rp_uniform_set, base_specialization); + _render_list_with_draw_list(&render_list_params, mv_fb, RD::DRAW_CLEAR_ALL, mv_pass_clear); + + RD::get_singleton()->draw_command_end_label(); + } + } + // opaque pass RD::get_singleton()->draw_command_begin_label("Render Opaque"); @@ -1871,14 +1906,22 @@ void RenderForwardMobile::_fill_instance_data(RenderListType p_render_list, uint scene_state.instance_data[p_render_list].resize(p_offset + element_total); rl->element_info.resize(p_offset + element_total); + uint64_t frame = RSG::rasterizer->get_frame_number(); + for (uint32_t i = 0; i < element_total; i++) { GeometryInstanceSurfaceDataCache *surface = rl->elements[i + p_offset]; GeometryInstanceForwardMobile *inst = surface->owner; SceneState::InstanceData &instance_data = scene_state.instance_data[p_render_list][i + p_offset]; + if (inst->prev_transform_dirty && frame > inst->prev_transform_change_frame + 1 && inst->prev_transform_change_frame) { + inst->prev_transform = inst->transform; + inst->prev_transform_dirty = false; + } + if (inst->store_transform_cache) { RendererRD::MaterialStorage::store_transform(inst->transform, instance_data.transform); + RendererRD::MaterialStorage::store_transform(inst->prev_transform, instance_data.prev_transform); #ifdef REAL_T_IS_DOUBLE // Split the origin into two components, the float approximation and the missing precision. @@ -1889,6 +1932,7 @@ void RenderForwardMobile::_fill_instance_data(RenderListType p_render_list, uint #endif } else { RendererRD::MaterialStorage::store_transform(Transform3D(), instance_data.transform); + RendererRD::MaterialStorage::store_transform(Transform3D(), instance_data.prev_transform); } instance_data.flags = inst->flags_cache; @@ -2068,7 +2112,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const } // ADD Element - if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) { + if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT || p_pass_mode == PASS_MODE_MOTION_VECTORS) { #ifdef DEBUG_ENABLED bool force_alpha = unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW); #else @@ -2155,6 +2199,9 @@ void RenderForwardMobile::_render_list(RenderingDevice::DrawListID p_draw_list, case PASS_MODE_DEPTH_MATERIAL: { _render_list_template(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); } break; + case PASS_MODE_MOTION_VECTORS: { + _render_list_template(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); + } } } @@ -2170,6 +2217,7 @@ void RenderForwardMobile::_render_list_with_draw_list(RenderListParameters *p_pa template void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) { RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); + RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton(); RD::DrawListID draw_list = p_draw_list; RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format; @@ -2215,11 +2263,10 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr push_constant.base_index = i + p_params->element_offset; if constexpr (p_pass_mode == PASS_MODE_DEPTH_MATERIAL) { - push_constant.uv_offset[0] = p_params->uv_offset.x; - push_constant.uv_offset[1] = p_params->uv_offset.y; + push_constant.uv_offset = Math::make_half_float(p_params->uv_offset.y) << 16; + push_constant.uv_offset |= Math::make_half_float(p_params->uv_offset.x); } else { - push_constant.uv_offset[0] = 0.0; - push_constant.uv_offset[1] = 0.0; + push_constant.uv_offset = 0; } if (shadow_pass) { @@ -2301,6 +2348,9 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for material pass"); pipeline_key.version = SceneShaderForwardMobile::SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL; } break; + case PASS_MODE_MOTION_VECTORS: { + pipeline_key.version = SceneShaderForwardMobile::SHADER_VERSION_MOTION_VECTORS_MULTIVIEW; + } } pipeline_key.framebuffer_format_id = framebuffer_format; @@ -2319,9 +2369,9 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr // Skeleton and blend shape. uint64_t input_mask = shader->get_vertex_input_mask(pipeline_key.version, pipeline_key.ubershader); if (surf->owner->mesh_instance.is_valid()) { - mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, input_mask, false, vertex_array_rd, vertex_format); + mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, input_mask, p_pass_mode == PASS_MODE_MOTION_VECTORS, vertex_array_rd, vertex_format); } else { - mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, input_mask, false, vertex_array_rd, vertex_format); + mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, input_mask, p_pass_mode == PASS_MODE_MOTION_VECTORS, vertex_array_rd, vertex_format); } pipeline_key.vertex_format_id = vertex_format; @@ -2388,6 +2438,15 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr prev_material_uniform_set = material_uniform_set; } + if (surf->owner->base_flags & INSTANCE_DATA_FLAG_PARTICLES) { + particles_storage->particles_get_instance_buffer_motion_vectors_offsets(surf->owner->data->base, push_constant.multimesh_motion_vectors_current_offset, push_constant.multimesh_motion_vectors_previous_offset); + } else if (surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH) { + mesh_storage->_multimesh_get_motion_vectors_offsets(surf->owner->data->base, push_constant.multimesh_motion_vectors_current_offset, push_constant.multimesh_motion_vectors_previous_offset); + } else { + push_constant.multimesh_motion_vectors_current_offset = 0; + push_constant.multimesh_motion_vectors_previous_offset = 0; + } + size_t push_constant_size = 0; if (pipeline_key.ubershader) { push_constant_size = sizeof(SceneState::PushConstant); @@ -2439,6 +2498,17 @@ RenderGeometryInstance *RenderForwardMobile::geometry_instance_create(RID p_base return ginstance; } +void RendererSceneRenderImplementation::RenderForwardMobile::GeometryInstanceForwardMobile::set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) { + uint64_t frame = RSG::rasterizer->get_frame_number(); + if (frame != prev_transform_change_frame) { + prev_transform = transform; + prev_transform_change_frame = frame; + prev_transform_dirty = true; + } + + RenderGeometryInstanceBase::set_transform(p_transform, p_aabb, p_transformed_aabb); +} + void RenderForwardMobile::GeometryInstanceForwardMobile::set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) { lightmap_instance = p_lightmap_instance; lightmap_uv_scale = p_lightmap_uv_scale; @@ -2847,6 +2917,7 @@ void RenderForwardMobile::_geometry_instance_update(RenderGeometryInstance *p_ge ginstance->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); } else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) { + ginstance->base_flags |= INSTANCE_DATA_FLAG_PARTICLES; ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH; if (false) { // 2D particles ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D; diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index a3bfb86ccd..5aa536c7df 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -89,6 +89,8 @@ private: virtual void free_data() override; virtual void configure(RenderSceneBuffersRD *p_render_buffers) override; + RID get_motion_vectors_fb(); + private: RenderSceneBuffersRD *render_buffers = nullptr; }; @@ -108,6 +110,7 @@ private: // PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI, PASS_MODE_DEPTH_MATERIAL, // PASS_MODE_SDF, + PASS_MODE_MOTION_VECTORS, }; struct RenderElementInfo; @@ -198,14 +201,16 @@ private: }; struct PushConstant { - float uv_offset[2]; + uint32_t uv_offset; uint32_t base_index; - uint32_t pad; + uint32_t multimesh_motion_vectors_current_offset; + uint32_t multimesh_motion_vectors_previous_offset; PushConstantUbershader ubershader; }; struct InstanceData { float transform[16]; + float prev_transform[16]; uint32_t flags; uint32_t instance_uniforms_ofs; // Base offset in global buffer for instance variables. uint32_t gi_offset; // GI information when using lightmapping (VCT or lightmap index). @@ -497,6 +502,10 @@ protected: uint32_t instance_count = 0; uint32_t trail_steps = 1; + uint64_t prev_transform_change_frame = UINT_MAX; + bool prev_transform_dirty = true; + Transform3D prev_transform; + // lightmap uint32_t gi_offset_cache = 0; // !BAS! Should rename this to lightmap_offset_cache, in forward clustered this was shared between gi and lightmap RID lightmap_instance; @@ -524,6 +533,7 @@ protected: virtual void _mark_dirty() override; + virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override; virtual void set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override; virtual void set_lightmap_capture(const Color *p_sh9) override; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index b32e00bfad..732d430531 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -307,7 +307,7 @@ void SceneShaderForwardMobile::ShaderData::_create_pipeline(PipelineKey p_pipeli multisample_state.enable_alpha_to_one = true; } - if (p_pipeline_key.version == SHADER_VERSION_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) { + if (p_pipeline_key.version == SHADER_VERSION_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_MOTION_VECTORS_MULTIVIEW) { blend_state = blend_state_blend; if (depth_draw == DEPTH_DRAW_OPAQUE && !uses_alpha_clip) { // Alpha does not write to depth. @@ -322,7 +322,7 @@ void SceneShaderForwardMobile::ShaderData::_create_pipeline(PipelineKey p_pipeli // Do not use this version (error case). } } else { - if (p_pipeline_key.version == SHADER_VERSION_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) { + if (p_pipeline_key.version == SHADER_VERSION_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_MOTION_VECTORS_MULTIVIEW) { blend_state = blend_state_opaque; } else if (p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS || p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS_DP) { // Contains nothing. @@ -502,6 +502,7 @@ void SceneShaderForwardMobile::init(const String p_defines) { shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n", false)); // SHADER_VERSION_COLOR_PASS_MULTIVIEW shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n#define USE_LIGHTMAP\n", false)); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n#define SHADOW_PASS\n", false)); // SHADER_VERSION_SHADOW_PASS_MULTIVIEW + shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_MOTION_VECTORS\n", false)); // SHADER_VERSION_MOTION_VECTORS_MULTIVIEW } Vector immutable_samplers; @@ -711,7 +712,7 @@ void SceneShaderForwardMobile::init(const String p_defines) { actions.base_texture_binding_index = 1; actions.texture_layout_set = RenderForwardMobile::MATERIAL_UNIFORM_SET; actions.base_uniform_string = "material."; - actions.base_varying_index = 10; + actions.base_varying_index = 14; actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h index 51ca5628ea..29fc5bb2a5 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h @@ -52,6 +52,7 @@ public: SHADER_VERSION_COLOR_PASS_MULTIVIEW, SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW, SHADER_VERSION_SHADOW_PASS_MULTIVIEW, + SHADER_VERSION_MOTION_VECTORS_MULTIVIEW, SHADER_VERSION_MAX }; 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 5842d054cd..be37e837ab 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 @@ -66,6 +66,15 @@ layout(location = 10) in uvec4 bone_attrib; layout(location = 11) in vec4 weight_attrib; #endif +#if defined(MODE_RENDER_MOTION_VECTORS) +layout(location = 12) in vec4 previous_vertex_attrib; + +#if defined(NORMAL_USED) || defined(TANGENT_USED) +layout(location = 13) in vec4 previous_normal_attrib; +#endif + +#endif // MODE_RENDER_MOTION_VECTORS + vec3 oct_to_vec3(vec2 e) { vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y)); float t = max(-v.z, 0.0); @@ -127,6 +136,11 @@ layout(location = 9) out highp float dp_clip; #endif +#if defined(MODE_RENDER_MOTION_VECTORS) +layout(location = 12) out highp vec4 screen_position; +layout(location = 13) out highp vec4 prev_screen_position; +#endif + #ifdef USE_MULTIVIEW #extension GL_EXT_multiview : enable #define ViewIndex gl_ViewIndex @@ -185,15 +199,77 @@ uint multimesh_stride() { return stride; } -void main() { +void _unpack_vertex_attributes(vec4 p_vertex_in, vec3 p_compressed_aabb_position, vec3 p_compressed_aabb_size, +#if defined(NORMAL_USED) || defined(TANGENT_USED) + vec4 p_normal_in, +#ifdef NORMAL_USED + out vec3 r_normal, +#endif + out vec3 r_tangent, + out vec3 r_binormal, +#endif + out vec3 r_vertex) { + + r_vertex = p_vertex_in.xyz * p_compressed_aabb_size + p_compressed_aabb_position; +#ifdef NORMAL_USED + r_normal = oct_to_vec3(p_normal_in.xy * 2.0 - 1.0); +#endif + +#if defined(NORMAL_USED) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(BENT_NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) + + float binormal_sign; + + // This works because the oct value (0, 1) maps onto (0, 0, -1) which encodes to (1, 1). + // Accordingly, if p_normal_in.z contains octahedral values, it won't equal (0, 1). + if (p_normal_in.z > 0.0 || p_normal_in.w < 1.0) { + // Uncompressed format. + vec2 signed_tangent_attrib = p_normal_in.zw * 2.0 - 1.0; + r_tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0)); + binormal_sign = sign(signed_tangent_attrib.y); + r_binormal = normalize(cross(r_normal, r_tangent) * binormal_sign); + } else { + // Compressed format. + float angle = p_vertex_in.w; + binormal_sign = angle > 0.5 ? 1.0 : -1.0; // 0.5 does not exist in UNORM16, so values are either greater or smaller. + angle = abs(angle * 2.0 - 1.0) * M_PI; // 0.5 is basically zero, allowing to encode both signs reliably. + vec3 axis = r_normal; + axis_angle_to_tbn(axis, angle, r_tangent, r_binormal, r_normal); + r_binormal *= binormal_sign; + } +#endif +} + +void vertex_shader(in vec3 vertex, +#ifdef NORMAL_USED + in vec3 normal, +#endif +#if defined(NORMAL_USED) || defined(TANGENT_USED) + in vec3 tangent, + in vec3 binormal, +#endif + in uint instance_index, in uint multimesh_offset, in mat4 model_matrix, +#ifdef MODE_DUAL_PARABOLOID + in float dual_paraboloid_side, + in float z_far, +#endif +#if defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL) + in uint scene_flags, +#endif + in mat4 projection_matrix, + in mat4 inv_projection_matrix, +#ifdef USE_MULTIVIEW + in vec4 scene_eye_offset, +#endif + in mat4 view_matrix, + in mat4 inv_view_matrix, + in vec2 viewport_size, + in uint scene_directional_light_count, + out vec4 screen_position_output) { vec4 instance_custom = vec4(0.0); #if defined(COLOR_USED) color_interp = color_attrib; #endif - mat4 model_matrix = instances.data[draw_call.instance_index].transform; - mat4 inv_view_matrix = scene_data.inv_view_matrix; - #ifdef USE_DOUBLE_PRECISION vec3 model_precision = vec3(model_matrix[0][3], model_matrix[1][3], model_matrix[2][3]); model_matrix[0][3] = 0.0; @@ -206,7 +282,7 @@ void main() { #endif mat3 model_normal_matrix; - if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) { + if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) { model_normal_matrix = transpose(inverse(mat3(model_matrix))); } else { model_normal_matrix = mat3(model_matrix); @@ -219,7 +295,7 @@ void main() { //multimesh, instances are for it #ifdef USE_PARTICLE_TRAILS - uint trail_size = (instances.data[draw_call.instance_index].flags >> INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT) & INSTANCE_FLAGS_PARTICLE_TRAIL_MASK; + uint trail_size = (instances.data[instance_index].flags >> INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT) & INSTANCE_FLAGS_PARTICLE_TRAIL_MASK; uint stride = 3 + 1 + 1; //particles always uses this format uint offset = trail_size * stride * gl_InstanceIndex; @@ -264,7 +340,7 @@ void main() { #else uint stride = multimesh_stride(); - uint offset = stride * gl_InstanceIndex; + uint offset = stride * (gl_InstanceIndex + multimesh_offset); if (sc_multimesh_format_2d()) { matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)); @@ -300,33 +376,6 @@ void main() { model_normal_matrix = model_normal_matrix * mat3(matrix); } - vec3 vertex = vertex_angle_attrib.xyz * instances.data[draw_call.instance_index].compressed_aabb_size_pad.xyz + instances.data[draw_call.instance_index].compressed_aabb_position_pad.xyz; -#ifdef NORMAL_USED - vec3 normal = oct_to_vec3(axis_tangent_attrib.xy * 2.0 - 1.0); -#endif - -#if defined(NORMAL_USED) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(BENT_NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) - - vec3 binormal; - float binormal_sign; - vec3 tangent; - if (axis_tangent_attrib.z > 0.0 || axis_tangent_attrib.w < 1.0) { - // Uncompressed format. - vec2 signed_tangent_attrib = axis_tangent_attrib.zw * 2.0 - 1.0; - tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0)); - binormal_sign = sign(signed_tangent_attrib.y); - binormal = normalize(cross(normal, tangent) * binormal_sign); - } else { - // Compressed format. - float angle = vertex_angle_attrib.w; - binormal_sign = angle > 0.5 ? 1.0 : -1.0; // 0.5 does not exist in UNORM16, so values are either greater or smaller. - angle = abs(angle * 2.0 - 1.0) * M_PI; // 0.5 is basically zero, allowing to encode both signs reliably. - vec3 axis = normal; - axis_angle_to_tbn(axis, angle, tangent, binormal, normal); - binormal *= binormal_sign; - } -#endif - #ifdef UV_USED uv_interp = uv_attrib; #endif @@ -335,7 +384,7 @@ void main() { uv2_interp = uv2_attrib; #endif - vec4 uv_scale = instances.data[draw_call.instance_index].uv_scale; + vec4 uv_scale = instances.data[instance_index].uv_scale; if (uv_scale != vec4(0.0)) { // Compression enabled #ifdef UV_USED @@ -351,14 +400,10 @@ void main() { #endif #ifdef USE_MULTIVIEW - mat4 projection_matrix = scene_data.projection_matrix_view[ViewIndex]; - mat4 inv_projection_matrix = scene_data.inv_projection_matrix_view[ViewIndex]; - vec3 eye_offset = scene_data.eye_offset[ViewIndex].xyz; + vec3 eye_offset = scene_eye_offset.xyz; #else - mat4 projection_matrix = scene_data.projection_matrix; - mat4 inv_projection_matrix = scene_data.inv_projection_matrix; vec3 eye_offset = vec3(0.0, 0.0, 0.0); -#endif //USE_MULTIVIEW +#endif // USE_MULTIVIEW //using world coordinates #if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) @@ -383,10 +428,10 @@ void main() { float roughness = 1.0; - mat4 modelview = scene_data.view_matrix * model_matrix; - mat3 modelview_normal = mat3(scene_data.view_matrix) * model_normal_matrix; - mat4 read_view_matrix = scene_data.view_matrix; - vec2 read_viewport_size = scene_data.viewport_size; + mat4 modelview = view_matrix * model_matrix; + mat3 modelview_normal = mat3(view_matrix) * model_normal_matrix; + mat4 read_view_matrix = view_matrix; + vec2 read_viewport_size = viewport_size; { #CODE : VERTEX @@ -406,8 +451,8 @@ void main() { } vertex = mat3(inv_view_matrix * modelview) * vertex; vec3 temp_precision; - vertex += double_add_vec3(model_origin, model_precision, scene_data.inv_view_matrix[3].xyz, view_precision, temp_precision); - vertex = mat3(scene_data.view_matrix) * vertex; + vertex += double_add_vec3(model_origin, model_precision, inv_view_matrix[3].xyz, view_precision, temp_precision); + vertex = mat3(view_matrix) * vertex; #else vertex = (modelview * vec4(vertex, 1.0)).xyz; #endif @@ -425,14 +470,14 @@ void main() { //using world coordinates #if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) - vertex = (scene_data.view_matrix * vec4(vertex, 1.0)).xyz; + vertex = (view_matrix * vec4(vertex, 1.0)).xyz; #ifdef NORMAL_USED - normal = (scene_data.view_matrix * vec4(normal, 0.0)).xyz; + normal = (view_matrix * vec4(normal, 0.0)).xyz; #endif #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(BENT_NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) - binormal = (scene_data.view_matrix * vec4(binormal, 0.0)).xyz; - tangent = (scene_data.view_matrix * vec4(tangent, 0.0)).xyz; + binormal = (view_matrix * vec4(binormal, 0.0)).xyz; + tangent = (view_matrix * vec4(tangent, 0.0)).xyz; #endif #endif @@ -461,7 +506,7 @@ void main() { specular_light_interp = vec4(0.0); uint omni_light_count = sc_omni_lights(8); - uvec2 omni_light_indices = instances.data[draw_call.instance_index].omni_lights; + uvec2 omni_light_indices = instances.data[instance_index].omni_lights; for (uint i = 0; i < omni_light_count; i++) { uint light_index = (i > 3) ? ((omni_light_indices.y >> ((i - 4) * 8)) & 0xFF) : ((omni_light_indices.x >> (i * 8)) & 0xFF); if (i > 0 && light_index == 0xFF) { @@ -472,7 +517,7 @@ void main() { } uint spot_light_count = sc_spot_lights(8); - uvec2 spot_light_indices = instances.data[draw_call.instance_index].spot_lights; + uvec2 spot_light_indices = instances.data[instance_index].spot_lights; for (uint i = 0; i < spot_light_count; i++) { uint light_index = (i > 3) ? ((spot_light_indices.y >> ((i - 4) * 8)) & 0xFF) : ((spot_light_indices.x >> (i * 8)) & 0xFF); if (i > 0 && light_index == 0xFF) { @@ -482,18 +527,18 @@ void main() { light_process_spot_vertex(light_index, vertex, view, normal_interp, roughness, diffuse_light_interp.rgb, specular_light_interp.rgb); } - uint directional_lights_count = sc_directional_lights(scene_data.directional_light_count); + uint directional_lights_count = sc_directional_lights(scene_directional_light_count); if (directional_lights_count > 0) { // We process the first directional light separately as it may have shadows. vec3 directional_diffuse = vec3(0.0); vec3 directional_specular = vec3(0.0); for (uint i = 0; i < directional_lights_count; i++) { - if (!bool(directional_lights.data[i].mask & instances.data[draw_call.instance_index].layer_mask)) { + if (!bool(directional_lights.data[i].mask & instances.data[instance_index].layer_mask)) { continue; // Not masked, skip. } - if (directional_lights.data[i].bake_mode == LIGHT_BAKE_STATIC && bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { + if (directional_lights.data[i].bake_mode == LIGHT_BAKE_STATIC && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { continue; // Statically baked light and object uses lightmap, skip. } if (i == 0) { @@ -539,7 +584,7 @@ void main() { #ifdef MODE_DUAL_PARABOLOID - vertex_interp.z *= scene_data.dual_paraboloid_side; + vertex_interp.z *= dual_paraboloid_side; dp_clip = vertex_interp.z; //this attempts to avoid noise caused by objects sent to the other parabolloid side due to bias @@ -549,7 +594,7 @@ void main() { float distance = length(vtx); vtx = normalize(vtx); vtx.xy /= 1.0 - vtx.z; - vtx.z = (distance / scene_data.z_far); + vtx.z = (distance / z_far); vtx.z = vtx.z * 2.0 - 1.0; vertex_interp = vtx; @@ -568,14 +613,14 @@ void main() { #endif #ifdef MODE_RENDER_DEPTH - if (bool(scene_data.flags & SCENE_DATA_FLAGS_USE_PANCAKE_SHADOWS)) { + if (bool(scene_flags & SCENE_DATA_FLAGS_USE_PANCAKE_SHADOWS)) { if (gl_Position.z >= 0.9999) { gl_Position.z = 0.9999; } } #endif // MODE_RENDER_DEPTH #ifdef MODE_RENDER_MATERIAL - if (bool(scene_data.flags & SCENE_DATA_FLAGS_USE_UV2_MATERIAL)) { + if (bool(scene_flags & SCENE_DATA_FLAGS_USE_UV2_MATERIAL)) { vec2 uv_dest_attrib; if (uv_scale != vec4(0.0)) { uv_dest_attrib = (uv2_attrib.xy - 0.5) * uv_scale.zw; @@ -583,11 +628,128 @@ void main() { uv_dest_attrib = uv2_attrib.xy; } - gl_Position.xy = (uv_dest_attrib + draw_call.uv_offset) * 2.0 - 1.0; + vec2 uv_offset = unpackHalf2x16(draw_call.uv_offset); + gl_Position.xy = (uv_dest_attrib + uv_offset) * 2.0 - 1.0; gl_Position.z = 0.00001; gl_Position.w = 1.0; } #endif // MODE_RENDER_MATERIAL +#ifdef MODE_RENDER_MOTION_VECTORS + screen_position_output = gl_Position; +#endif // MODE_RENDER_MOTION_VECTORS +} + +void main() { +#if defined(MODE_RENDER_MOTION_VECTORS) + vec3 prev_vertex; +#ifdef NORMAL_USED + vec3 prev_normal; +#endif +#if defined(NORMAL_USED) || defined(TANGENT_USED) + vec3 prev_tangent; + vec3 prev_binormal; +#endif + + _unpack_vertex_attributes( + previous_vertex_attrib, + instances.data[draw_call.instance_index].compressed_aabb_position_pad.xyz, + instances.data[draw_call.instance_index].compressed_aabb_size_pad.xyz, +#if defined(NORMAL_USED) || defined(TANGENT_USED) + previous_normal_attrib, +#ifdef NORMAL_USED + prev_normal, +#endif + prev_tangent, + prev_binormal, +#endif + prev_vertex); + + vertex_shader(prev_vertex, +#ifdef NORMAL_USED + prev_normal, +#endif +#if defined(NORMAL_USED) || defined(TANGENT_USED) + prev_tangent, + prev_binormal, +#endif + draw_call.instance_index, draw_call.multimesh_motion_vectors_previous_offset, instances.data[draw_call.instance_index].prev_transform, +#ifdef MODE_DUAL_PARABOLOID + scene_data_block.prev_data.dual_paraboloid_side, + scene_data_block.prev_data.z_far, +#endif +#if defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL) + scene_data_block.prev_data.flags, +#endif +#ifdef USE_MULTIVIEW + scene_data_block.prev_data.projection_matrix_view[ViewIndex], + scene_data_block.prev_data.inv_projection_matrix_view[ViewIndex], + scene_data_block.prev_data.eye_offset[ViewIndex], +#else + scene_data_block.prev_data.projection_matrix, + scene_data_block.prev_data.inv_projection_matrix, +#endif + scene_data_block.prev_data.view_matrix, + scene_data_block.prev_data.inv_view_matrix, + scene_data_block.prev_data.viewport_size, + scene_data_block.prev_data.directional_light_count, + prev_screen_position); +#else + // Unused output. + vec4 screen_position; +#endif // MODE_RENDER_MOTION_VECTORS + + vec3 vertex; +#ifdef NORMAL_USED + vec3 normal; +#endif +#if defined(NORMAL_USED) || defined(TANGENT_USED) + vec3 tangent; + vec3 binormal; +#endif + + _unpack_vertex_attributes( + vertex_angle_attrib, + instances.data[draw_call.instance_index].compressed_aabb_position_pad.xyz, + instances.data[draw_call.instance_index].compressed_aabb_size_pad.xyz, +#if defined(NORMAL_USED) || defined(TANGENT_USED) + axis_tangent_attrib, +#ifdef NORMAL_USED + normal, +#endif + tangent, + binormal, +#endif + vertex); + + vertex_shader(vertex, +#ifdef NORMAL_USED + normal, +#endif +#if defined(NORMAL_USED) || defined(TANGENT_USED) + tangent, + binormal, +#endif + draw_call.instance_index, draw_call.multimesh_motion_vectors_current_offset, instances.data[draw_call.instance_index].transform, +#ifdef MODE_DUAL_PARABOLOID + scene_data_block.data.dual_paraboloid_side, + scene_data_block.data.z_far, +#endif +#if defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL) + scene_data_block.data.flags, +#endif +#ifdef USE_MULTIVIEW + scene_data_block.data.projection_matrix_view[ViewIndex], + scene_data_block.data.inv_projection_matrix_view[ViewIndex], + scene_data_block.data.eye_offset[ViewIndex], +#else + scene_data_block.data.projection_matrix, + scene_data_block.data.inv_projection_matrix, +#endif + scene_data_block.data.view_matrix, + scene_data_block.data.inv_view_matrix, + scene_data_block.data.viewport_size, + scene_data_block.data.directional_light_count, + screen_position); } #[fragment] @@ -644,6 +806,11 @@ layout(location = 9) highp in float dp_clip; #endif +#if defined(MODE_RENDER_MOTION_VECTORS) +layout(location = 12) in highp vec4 screen_position; +layout(location = 13) in highp vec4 prev_screen_position; +#endif + #ifdef USE_LIGHTMAP // w0, w1, w2, and w3 are the four cubic B-spline basis functions float w0(float a) { @@ -1970,4 +2137,15 @@ void main() { #endif //MODE_MULTIPLE_RENDER_TARGETS #endif //MODE_RENDER_DEPTH + +#ifdef MODE_RENDER_MOTION_VECTORS + // These motion vectors are in NDC space (as opposed to screen space) to fit the OpenXR XR_FB_space_warp specification. + // https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XR_FB_space_warp + + vec3 ndc = screen_position.xyz / screen_position.w; + ndc.y = -ndc.y; + vec3 prev_ndc = prev_screen_position.xyz / prev_screen_position.w; + prev_ndc.y = -prev_ndc.y; + frag_color = vec4(ndc - prev_ndc, 0.0); +#endif } diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl index 86bca89a6c..8c7cd0fd54 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl @@ -13,9 +13,10 @@ #define USING_MOBILE_RENDERER layout(push_constant, std430) uniform DrawCall { - vec2 uv_offset; + uint uv_offset; uint instance_index; - uint pad; + uint multimesh_motion_vectors_current_offset; + uint multimesh_motion_vectors_previous_offset; #ifdef UBERSHADER uint sc_packed_0; uint sc_packed_1; @@ -303,6 +304,7 @@ scene_data_block; struct InstanceData { highp mat4 transform; // 64 - 64 + highp mat4 prev_transform; uint flags; // 04 - 68 uint instance_uniforms_ofs; // Base offset in global buffer for instance variables. // 04 - 72 uint gi_offset; // GI information when using lightmapping (VCT or lightmap index). // 04 - 76 diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp index a06df3a79e..63aa4760e1 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp @@ -702,6 +702,12 @@ RID RenderSceneBuffersRD::get_velocity_buffer(bool p_get_msaa, uint32_t p_layer) } } +RID RenderSceneBuffersRD::get_velocity_depth_buffer() { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + RID velocity_depth = texture_storage->render_target_get_override_velocity_depth(render_target); + return velocity_depth; +} + uint32_t RenderSceneBuffersRD::get_color_usage_bits(bool p_resolve, bool p_msaa, bool p_storage) { DEV_ASSERT((!p_resolve && !p_msaa) || (p_resolve != p_msaa)); diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h index ba42970a5d..11c593001d 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h @@ -312,6 +312,8 @@ public: RID get_velocity_buffer(bool p_get_msaa); RID get_velocity_buffer(bool p_get_msaa, uint32_t p_layer); + RID get_velocity_depth_buffer(); + // Samplers adjusted with the mipmap bias that is best fit for the configuration of these render buffers. _FORCE_INLINE_ RendererRD::MaterialStorage::Samplers get_samplers() const { diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index f01edd2d2d..1cc192cfe0 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -3526,6 +3526,7 @@ void TextureStorage::render_target_set_override(RID p_render_target, RID p_color rt->overridden.color = p_color_texture; rt->overridden.depth = p_depth_texture; rt->overridden.velocity = p_velocity_texture; + rt->overridden.velocity_depth = p_velocity_depth_texture; } RID TextureStorage::render_target_get_override_color(RID p_render_target) const { @@ -3587,6 +3588,13 @@ RID TextureStorage::render_target_get_override_velocity_slice(RID p_render_targe } } +RID TextureStorage::render_target_get_override_velocity_depth(RID p_render_target) const { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_NULL_V(rt, RID()); + + return rt->overridden.velocity_depth; +} + void RendererRD::TextureStorage::render_target_set_render_region(RID p_render_target, const Rect2i &p_render_region) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_NULL(rt); diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h index 89690498d4..8db9a565ab 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -399,6 +399,7 @@ private: RID color; RID depth; RID velocity; + RID velocity_depth; // In a multiview scenario, which is the most likely where we // override our destination textures, we need to obtain slices @@ -791,7 +792,7 @@ public: RID render_target_get_override_depth_slice(RID p_render_target, const uint32_t p_layer) const; virtual RID render_target_get_override_velocity(RID p_render_target) const override; RID render_target_get_override_velocity_slice(RID p_render_target, const uint32_t p_layer) const; - virtual RID render_target_get_override_velocity_depth(RID p_render_target) const override { return RID(); } + virtual RID render_target_get_override_velocity_depth(RID p_render_target) const override; virtual void render_target_set_render_region(RID p_render_target, const Rect2i &p_render_region) override; virtual Rect2i render_target_get_render_region(RID p_render_target) const override; From a7d18f51a2806734858f238a0d101b8f8ac1db1b Mon Sep 17 00:00:00 2001 From: Marcos Casagrande Date: Fri, 21 Mar 2025 20:01:48 +0100 Subject: [PATCH 054/144] Web: Add godot_pool_size/emscripten_pool_size config --- platform/web/detect.py | 2 +- .../web/doc_classes/EditorExportPlatformWeb.xml | 8 ++++++++ platform/web/export/export_plugin.cpp | 4 ++++ platform/web/godot_js.h | 1 + platform/web/js/engine/config.js | 14 ++++++++++++++ platform/web/js/libs/library_godot_os.js | 13 +++++++++++++ platform/web/os_web.cpp | 8 ++++++++ platform/web/os_web.h | 2 +- 8 files changed, 50 insertions(+), 2 deletions(-) diff --git a/platform/web/detect.py b/platform/web/detect.py index 27556926ff..c281e4292b 100644 --- a/platform/web/detect.py +++ b/platform/web/detect.py @@ -240,7 +240,7 @@ def configure(env: "SConsEnvironment"): env.Append(CCFLAGS=["-sUSE_PTHREADS=1"]) env.Append(LINKFLAGS=["-sUSE_PTHREADS=1"]) env.Append(LINKFLAGS=["-sDEFAULT_PTHREAD_STACK_SIZE=%sKB" % env["default_pthread_stack_size"]]) - env.Append(LINKFLAGS=["-sPTHREAD_POOL_SIZE=8"]) + env.Append(LINKFLAGS=["-sPTHREAD_POOL_SIZE='Module[\"emscriptenPoolSize\"]||8'"]) env.Append(LINKFLAGS=["-sWASM_MEM_MAX=2048MB"]) if not env["dlink_enabled"]: # Workaround https://github.com/emscripten-core/emscripten/issues/21844#issuecomment-2116936414. diff --git a/platform/web/doc_classes/EditorExportPlatformWeb.xml b/platform/web/doc_classes/EditorExportPlatformWeb.xml index 08632392be..c994465741 100644 --- a/platform/web/doc_classes/EditorExportPlatformWeb.xml +++ b/platform/web/doc_classes/EditorExportPlatformWeb.xml @@ -79,9 +79,17 @@ - [b]Landscape:[/b] Forces a horizontal layout (wider than it is taller). - [b]Portrait:[/b] Forces a vertical layout (taller than it is wider). + + The number of threads that emscripten will allocate at startup. A smaller value will allocate fewer threads and consume fewer system resources, but you may run the risk of running out of threads in the pool and needing to allocate more threads at run time which may cause a deadlock. + [b]Note:[/b] Some browsers have a hard cap on the number of threads that can be allocated, so it is best to be cautious and keep this number low. + If [code]true[/code] enables [GDExtension] support for this web build. + + Override for the default size of the [WorkerThreadPool]. This setting is used when [member ProjectSettings.threading/worker_pool/max_threads] size is set to -1 (which it is by default). This size must be smaller than [member variant/emscripten_pool_size] otherwise deadlocks may occur. + When using threads this size needs to be large enough to accommodate features that rely on having a dedicated thread like [member ProjectSettings.physics/2d/run_on_separate_thread] or [member ProjectSettings.rendering/driver/threads/thread_model]. In general, it is best to ensure that this is at least 4 and is at least 2 or 3 less than [member variant/emscripten_pool_size]. + If [code]true[/code], the exported game will support threads. It requires [url=https://web.dev/articles/coop-coep]a "cross-origin isolated" website[/url], which may be difficult to set up and is limited for security reasons (such as not being able to communicate with third-party websites). If [code]false[/code], the exported game will not support threads. As a result, it is more prone to performance and audio issues, but will only require to be run on an HTTPS website. diff --git a/platform/web/export/export_plugin.cpp b/platform/web/export/export_plugin.cpp index 6614a9210d..ad73125a2a 100644 --- a/platform/web/export/export_plugin.cpp +++ b/platform/web/export/export_plugin.cpp @@ -143,11 +143,13 @@ void EditorExportPlatformWeb::_fix_html(Vector &p_html, const Refget("html/canvas_resize_policy"); config["experimentalVK"] = p_preset->get("html/experimental_virtual_keyboard"); config["focusCanvas"] = p_preset->get("html/focus_canvas_on_start"); + config["godotPoolSize"] = p_preset->get("variant/godot_pool_size"); config["gdextensionLibs"] = libs; config["executable"] = p_name; config["args"] = args; config["fileSizes"] = p_file_sizes; config["ensureCrossOriginIsolationHeaders"] = (bool)p_preset->get("progressive_web_app/ensure_cross_origin_isolation_headers"); + config["emscriptenPoolSize"] = p_preset->get("variant/emscripten_pool_size"); String head_include; if (p_preset->get("html/export_icon")) { @@ -360,6 +362,8 @@ void EditorExportPlatformWeb::get_export_options(List *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "variant/extensions_support"), false)); // GDExtension support. r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "variant/thread_support"), false)); // Thread support (i.e. run with or without COEP/COOP headers). + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "variant/emscripten_pool_size"), 8)); + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "variant/godot_pool_size"), 4)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "vram_texture_compression/for_desktop"), true)); // S3TC r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "vram_texture_compression/for_mobile"), false)); // ETC or ETC2, depending on renderer diff --git a/platform/web/godot_js.h b/platform/web/godot_js.h index c29ccccd2b..a0d9523ec0 100644 --- a/platform/web/godot_js.h +++ b/platform/web/godot_js.h @@ -50,6 +50,7 @@ extern void godot_js_os_fs_sync(void (*p_callback)()); extern int godot_js_os_execute(const char *p_json); extern void godot_js_os_shell_open(const char *p_uri); extern int godot_js_os_hw_concurrency_get(); +extern int godot_js_os_thread_pool_size_get(); extern int godot_js_os_has_feature(const char *p_ftr); extern int godot_js_pwa_cb(void (*p_callback)()); extern int godot_js_pwa_update(); diff --git a/platform/web/js/engine/config.js b/platform/web/js/engine/config.js index 3947195fa1..d867376e41 100644 --- a/platform/web/js/engine/config.js +++ b/platform/web/js/engine/config.js @@ -133,6 +133,16 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused- * @type {Array.} */ fileSizes: [], + /** + * @ignore + * @type {number} + */ + emscriptenPoolSize: 8, + /** + * @ignore + * @type {number} + */ + godotPoolSize: 4, /** * A callback function for handling Godot's ``OS.execute`` calls. * @@ -259,6 +269,8 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused- this.serviceWorker = parse('serviceWorker', this.serviceWorker); this.gdextensionLibs = parse('gdextensionLibs', this.gdextensionLibs); this.fileSizes = parse('fileSizes', this.fileSizes); + this.emscriptenPoolSize = parse('emscriptenPoolSize', this.emscriptenPoolSize); + this.godotPoolSize = parse('godotPoolSize', this.godotPoolSize); this.args = parse('args', this.args); this.onExecute = parse('onExecute', this.onExecute); this.onExit = parse('onExit', this.onExit); @@ -278,6 +290,7 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused- 'thisProgram': this.executable, 'noExitRuntime': false, 'dynamicLibraries': [`${loadPath}.side.wasm`].concat(this.gdextensionLibs), + 'emscriptenPoolSize': this.emscriptenPoolSize, 'instantiateWasm': function (imports, onSuccess) { function done(result) { onSuccess(result['instance'], result['module']); @@ -350,6 +363,7 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused- 'locale': locale, 'persistentDrops': this.persistentDrops, 'virtualKeyboard': this.experimentalVK, + 'godotPoolSize': this.godotPoolSize, 'focusCanvas': this.focusCanvas, 'onExecute': this.onExecute, 'onExit': function (p_code) { diff --git a/platform/web/js/libs/library_godot_os.js b/platform/web/js/libs/library_godot_os.js index 2899d7e45f..0e931b794e 100644 --- a/platform/web/js/libs/library_godot_os.js +++ b/platform/web/js/libs/library_godot_os.js @@ -61,6 +61,7 @@ const GodotConfig = { canvas_resize_policy: 2, // Adaptive virtual_keyboard: false, persistent_drops: false, + godot_pool_size: 4, on_execute: null, on_exit: null, @@ -70,6 +71,7 @@ const GodotConfig = { GodotConfig.locale = p_opts['locale'] || GodotConfig.locale; GodotConfig.virtual_keyboard = p_opts['virtualKeyboard']; GodotConfig.persistent_drops = !!p_opts['persistentDrops']; + GodotConfig.godot_pool_size = p_opts['godotPoolSize']; GodotConfig.on_execute = p_opts['onExecute']; GodotConfig.on_exit = p_opts['onExit']; if (p_opts['focusCanvas']) { @@ -346,6 +348,17 @@ const GodotOS = { return concurrency < 2 ? concurrency : 2; }, + godot_js_os_thread_pool_size_get__proxy: 'sync', + godot_js_os_thread_pool_size_get__sig: 'i', + godot_js_os_thread_pool_size_get: function () { + if (typeof PThread === 'undefined') { + // Threads aren't supported, so default to `1`. + return 1; + } + + return GodotConfig.godot_pool_size; + }, + godot_js_os_download_buffer__proxy: 'sync', godot_js_os_download_buffer__sig: 'viiii', godot_js_os_download_buffer: function (p_ptr, p_size, p_name, p_mime) { diff --git a/platform/web/os_web.cpp b/platform/web/os_web.cpp index a56a808060..fa284f3c2f 100644 --- a/platform/web/os_web.cpp +++ b/platform/web/os_web.cpp @@ -148,6 +148,14 @@ String OS_Web::get_unique_id() const { ERR_FAIL_V_MSG("", "OS::get_unique_id() is not available on the Web platform."); } +int OS_Web::get_default_thread_pool_size() const { +#ifdef THREADS_ENABLED + return godot_js_os_thread_pool_size_get(); +#else // No threads. + return 1; +#endif +} + bool OS_Web::_check_internal_feature_support(const String &p_feature) { if (p_feature == "web") { return true; diff --git a/platform/web/os_web.h b/platform/web/os_web.h index e29301f1e8..725eda3621 100644 --- a/platform/web/os_web.h +++ b/platform/web/os_web.h @@ -91,7 +91,7 @@ public: int get_process_exit_code(const ProcessID &p_pid) const override; int get_processor_count() const override; String get_unique_id() const override; - int get_default_thread_pool_size() const override { return 1; } + int get_default_thread_pool_size() const override; String get_executable_path() const override; Error shell_open(const String &p_uri) override; From a6664af0d632120a643dc97fd0342c1f80c6b2c5 Mon Sep 17 00:00:00 2001 From: Lukas Tenbrink Date: Fri, 30 May 2025 21:33:35 +0200 Subject: [PATCH 055/144] Fix infinite recursion on `GDScriptTests` if a script cannot be reloaded. --- modules/gdscript/tests/gdscript_test_runner.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp index 59585b9a06..045aa308d0 100644 --- a/modules/gdscript/tests/gdscript_test_runner.cpp +++ b/modules/gdscript/tests/gdscript_test_runner.cpp @@ -655,6 +655,8 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) { result.status = GDTEST_LOAD_ERROR; result.output = ""; result.passed = false; + remove_print_handler(&_print_handler); + remove_error_handler(&_error_handler); ERR_FAIL_V_MSG(result, "\nCould not reload script: '" + source_file + "'"); } From be1f9a878b733a9655b18767b8825baf67b4c8d8 Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Thu, 10 Mar 2022 01:40:31 +0100 Subject: [PATCH 056/144] Use SSE 4.2 as a baseline when compiling Godot This lets the compiler do more optimizations, leading to increased performance for demanding CPU tasks. --- SConstruct | 20 +++++++++++++++++--- modules/raycast/SCsub | 11 +++++++++-- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/SConstruct b/SConstruct index 1e76c431b7..fb6a7e6ffb 100644 --- a/SConstruct +++ b/SConstruct @@ -731,11 +731,25 @@ elif env.msvc: ) Exit(255) -# Default architecture flags. -if env["arch"] == "x86_32": - if env.msvc: +# Set x86 CPU instruction sets to use by the compiler's autovectorization. +if env["arch"] == "x86_64": + # On 64-bit x86, enable SSE 4.2 and prior instruction sets (SSE3/SSSE3/SSE4/SSE4.1) to improve performance. + # This is supported on most CPUs released after 2009-2011 (Intel Nehalem, AMD Bulldozer). + # AVX and AVX2 aren't enabled because they aren't available on more recent low-end Intel CPUs. + if env.msvc and not methods.using_clang(env): + # https://stackoverflow.com/questions/64053597/how-do-i-enable-sse4-1-and-sse3-but-not-avx-in-msvc/69328426 + env.Append(CCFLAGS=["/d2archSSE42"]) + else: + # `-msse2` is implied when compiling for x86_64. + env.Append(CCFLAGS=["-msse4.2"]) +elif env["arch"] == "x86_32": + # Be more conservative with instruction sets on 32-bit x86 to improve compatibility. + # SSE and SSE2 are present on all CPUs that support 64-bit, even if running a 32-bit OS. + if env.msvc and not methods.using_clang(env): env.Append(CCFLAGS=["/arch:SSE2"]) else: + # Use `-mfpmath=sse` to use SSE for floating-point math, which is more stable than x87. + # `-mstackrealign` is needed for it to work. env.Append(CCFLAGS=["-msse2", "-mfpmath=sse", "-mstackrealign"]) # Explicitly specify colored output. diff --git a/modules/raycast/SCsub b/modules/raycast/SCsub index 64a5100c77..28a81e3e5d 100644 --- a/modules/raycast/SCsub +++ b/modules/raycast/SCsub @@ -80,9 +80,16 @@ if env["builtin_embree"]: env_thirdparty.disable_warnings() env_thirdparty.add_source_files(thirdparty_obj, thirdparty_sources) + # Set x86 CPU instruction sets to use when building Embree's own intrinsics. + # Keep this in sync with Godot's main SConstruct file. + # This is only needed on MSVC, as GCC/Clang will set those defines automatically + # according to compiler instruction set flags. if env["arch"] != "x86_64" or env.msvc: - # Embree needs those, it will automatically use SSE2NEON in ARM - env_thirdparty.Append(CPPDEFINES=["__SSE2__", "__SSE__"]) + # Embree needs those; it will automatically use SSE2NEON in ARM. + env_thirdparty.Append(CPPDEFINES=["__SSE__", "__SSE2__"]) + + if env["arch"] == "x86_64" and env.msvc: + env_thirdparty.Append(CPPDEFINES=["__SSE3__", "__SSSE3__", "__SSE4_1__", "__SSE4_2__"]) if env["platform"] == "web": env_thirdparty.Append(CXXFLAGS=["-msimd128"]) From 08343189dc89678bfbb108c78ae923b66d5949af Mon Sep 17 00:00:00 2001 From: daniel080400 Date: Sat, 31 May 2025 16:57:51 +0800 Subject: [PATCH 057/144] Rework scene preview thumbnails --- doc/classes/EditorInterface.xml | 1 + editor/editor_interface.cpp | 155 ---- editor/editor_interface.h | 3 - editor/editor_node.cpp | 118 +-- editor/editor_node.h | 8 +- editor/editor_resource_preview.cpp | 105 ++- editor/editor_resource_preview.h | 9 +- editor/import/3d/resource_importer_scene.cpp | 11 - editor/import/3d/resource_importer_scene.h | 1 - editor/plugins/editor_preview_plugins.cpp | 732 ++++++++++++++++++- editor/plugins/editor_preview_plugins.h | 17 + 11 files changed, 851 insertions(+), 309 deletions(-) diff --git a/doc/classes/EditorInterface.xml b/doc/classes/EditorInterface.xml index 26828882bf..e422eca5cd 100644 --- a/doc/classes/EditorInterface.xml +++ b/doc/classes/EditorInterface.xml @@ -422,6 +422,7 @@ Saves the currently active scene as a file at [param path]. + [b]Note:[/b] The [param with_preview] parameter has no effect. diff --git a/editor/editor_interface.cpp b/editor/editor_interface.cpp index 013a59cffe..63cabe3243 100644 --- a/editor/editor_interface.cpp +++ b/editor/editor_interface.cpp @@ -52,9 +52,6 @@ #include "editor/property_selector.h" #include "editor/themes/editor_scale.h" #include "main/main.h" -#include "plugins/editor_preview_plugins.h" -#include "scene/3d/light_3d.h" -#include "scene/3d/mesh_instance_3d.h" #include "scene/gui/box_container.h" #include "scene/gui/control.h" #include "scene/main/window.h" @@ -103,27 +100,6 @@ EditorUndoRedoManager *EditorInterface::get_editor_undo_redo() const { return EditorUndoRedoManager::get_singleton(); } -AABB EditorInterface::_calculate_aabb_for_scene(Node *p_node, AABB &p_scene_aabb) { - MeshInstance3D *mesh_node = Object::cast_to(p_node); - if (mesh_node && mesh_node->get_mesh().is_valid()) { - Transform3D accum_xform; - Node3D *base = mesh_node; - while (base) { - accum_xform = base->get_transform() * accum_xform; - base = Object::cast_to(base->get_parent()); - } - - AABB aabb = accum_xform.xform(mesh_node->get_mesh()->get_aabb()); - p_scene_aabb.merge_with(aabb); - } - - for (int i = 0; i < p_node->get_child_count(); i++) { - p_scene_aabb = _calculate_aabb_for_scene(p_node->get_child(i), p_scene_aabb); - } - - return p_scene_aabb; -} - TypedArray EditorInterface::_make_mesh_previews(const TypedArray &p_meshes, int p_preview_size) { Vector> meshes; @@ -229,137 +205,6 @@ Vector> EditorInterface::make_mesh_previews(const Vectoris_inside_tree(), "The scene must not be inside the tree."); - ERR_FAIL_COND_MSG(!Engine::get_singleton()->is_editor_hint(), "This function can only be called from the editor."); - ERR_FAIL_NULL_MSG(EditorNode::get_singleton(), "EditorNode doesn't exist."); - - SubViewport *sub_viewport_node = memnew(SubViewport); - AABB scene_aabb; - scene_aabb = _calculate_aabb_for_scene(p_scene, scene_aabb); - - sub_viewport_node->set_update_mode(SubViewport::UPDATE_ALWAYS); - sub_viewport_node->set_size(Vector2i(p_preview_size, p_preview_size)); - sub_viewport_node->set_transparent_background(false); - Ref world; - world.instantiate(); - sub_viewport_node->set_world_3d(world); - - EditorNode::get_singleton()->add_child(sub_viewport_node); - Ref env; - env.instantiate(); - env->set_background(Environment::BG_CLEAR_COLOR); - - Ref camera_attributes; - camera_attributes.instantiate(); - - Node3D *root = memnew(Node3D); - root->set_name("Root"); - sub_viewport_node->add_child(root); - - Camera3D *camera = memnew(Camera3D); - camera->set_environment(env); - camera->set_attributes(camera_attributes); - camera->set_name("Camera3D"); - root->add_child(camera); - camera->set_current(true); - - camera->set_position(Vector3(0.0, 0.0, 3.0)); - - DirectionalLight3D *light = memnew(DirectionalLight3D); - light->set_name("Light"); - DirectionalLight3D *light2 = memnew(DirectionalLight3D); - light2->set_name("Light2"); - light2->set_color(Color(0.7, 0.7, 0.7, 1.0)); - - root->add_child(light); - root->add_child(light2); - - sub_viewport_node->add_child(p_scene); - - // Calculate the camera and lighting position based on the size of the scene. - Vector3 center = scene_aabb.get_center(); - float camera_size = scene_aabb.get_longest_axis_size(); - - const float cam_rot_x = -Math::PI / 4; - const float cam_rot_y = -Math::PI / 4; - - camera->set_orthogonal(camera_size * 2.0, 0.0001, camera_size * 2.0); - - Transform3D xf; - xf.basis = Basis(Vector3(0, 1, 0), cam_rot_y) * Basis(Vector3(1, 0, 0), cam_rot_x); - xf.origin = center; - xf.translate_local(0, 0, camera_size); - - camera->set_transform(xf); - - Transform3D xform; - xform.basis = Basis().rotated(Vector3(0, 1, 0), -Math::PI / 6); - xform.basis = Basis().rotated(Vector3(1, 0, 0), Math::PI / 6) * xform.basis; - - light->set_transform(xform * Transform3D().looking_at(Vector3(-2, -1, -1), Vector3(0, 1, 0))); - light2->set_transform(xform * Transform3D().looking_at(Vector3(+1, -1, -2), Vector3(0, 1, 0))); - - // Update the renderer to get the screenshot. - DisplayServer::get_singleton()->process_events(); - Main::iteration(); - Main::iteration(); - - // Get the texture. - Ref texture = sub_viewport_node->get_texture(); - ERR_FAIL_COND_MSG(texture.is_null(), "Failed to get texture from sub_viewport_node."); - - // Remove the initial scene node. - sub_viewport_node->remove_child(p_scene); - - // Cleanup the viewport. - if (sub_viewport_node) { - if (sub_viewport_node->get_parent()) { - sub_viewport_node->get_parent()->remove_child(sub_viewport_node); - } - sub_viewport_node->queue_free(); - sub_viewport_node = nullptr; - } - - // Now generate the cache image. - Ref img = texture->get_image(); - if (img.is_valid() && img->get_width() > 0 && img->get_height() > 0) { - img = img->duplicate(); - - int preview_size = EDITOR_GET("filesystem/file_dialog/thumbnail_size"); - preview_size *= EDSCALE; - - int vp_size = MIN(img->get_width(), img->get_height()); - int x = (img->get_width() - vp_size) / 2; - int y = (img->get_height() - vp_size) / 2; - - if (vp_size < preview_size) { - img->crop_from_point(x, y, vp_size, vp_size); - } else { - int ratio = vp_size / preview_size; - int size = preview_size * MAX(1, ratio / 2); - - x = (img->get_width() - size) / 2; - y = (img->get_height() - size) / 2; - - img->crop_from_point(x, y, size, size); - img->resize(preview_size, preview_size, Image::INTERPOLATE_LANCZOS); - } - img->convert(Image::FORMAT_RGB8); - - String temp_path = EditorPaths::get_singleton()->get_cache_dir(); - String cache_base = ProjectSettings::get_singleton()->globalize_path(p_path).md5_text(); - cache_base = temp_path.path_join("resthumb-" + cache_base); - - post_process_preview(img); - img->save_png(cache_base + ".png"); - } - - EditorResourcePreview::get_singleton()->check_for_invalidation(p_path); - EditorFileSystem::get_singleton()->emit_signal(SNAME("filesystem_changed")); -} - void EditorInterface::set_plugin_enabled(const String &p_plugin, bool p_enabled) { EditorNode::get_singleton()->set_addon_plugin_enabled(p_plugin, p_enabled, true); } diff --git a/editor/editor_interface.h b/editor/editor_interface.h index 5bf3ab4852..d0ce9db5a5 100644 --- a/editor/editor_interface.h +++ b/editor/editor_interface.h @@ -79,9 +79,7 @@ class EditorInterface : public Object { void _call_dialog_callback(const Callable &p_callback, const Variant &p_selected, const String &p_context); // Editor tools. - TypedArray _make_mesh_previews(const TypedArray &p_meshes, int p_preview_size); - AABB _calculate_aabb_for_scene(Node *p_node, AABB &p_scene_aabb); protected: static void _bind_methods(); @@ -110,7 +108,6 @@ public: EditorUndoRedoManager *get_editor_undo_redo() const; Vector> make_mesh_previews(const Vector> &p_meshes, Vector *p_transforms, int p_preview_size); - void make_scene_preview(const String &p_path, Node *p_scene, int p_preview_size); void set_plugin_enabled(const String &p_plugin, bool p_enabled); bool is_plugin_enabled(const String &p_plugin) const; diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 330bc9d50f..48901e9170 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -1840,91 +1840,6 @@ 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) { - save_scene_progress = memnew(EditorProgress("save", TTR("Saving Scene"), 4)); - - if (editor_data.get_edited_scene_root() != nullptr) { - 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_scene_progress->step(TTR("Creating Thumbnail"), 1); - // Current view? - - Ref img; - // If neither 3D or 2D nodes are present, make a 1x1 black texture. - // We cannot fallback on the 2D editor, because it may not have been used yet, - // which would result in an invalid texture. - if (c3d == 0 && c2d == 0) { - img.instantiate(); - img->initialize_data(1, 1, false, Image::FORMAT_RGB8); - } else if (c3d < c2d) { - Ref viewport_texture = scene_root->get_texture(); - if (viewport_texture->get_width() > 0 && viewport_texture->get_height() > 0) { - img = viewport_texture->get_image(); - } - } else { - // The 3D editor may be disabled as a feature, but scenes can still be opened. - // This check prevents the preview from regenerating in case those scenes are then saved. - // The preview will be generated if no feature profile is set (as the 3D editor is enabled by default). - Ref profile = feature_profile_manager->get_current_profile(); - if (profile.is_null() || !profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D)) { - img = Node3DEditor::get_singleton()->get_editor_viewport(0)->get_viewport_node()->get_texture()->get_image(); - } - } - - if (img.is_valid() && img->get_width() > 0 && img->get_height() > 0) { - img = img->duplicate(); - - save_scene_progress->step(TTR("Creating Thumbnail"), 3); - - int preview_size = EDITOR_GET("filesystem/file_dialog/thumbnail_size"); - preview_size *= EDSCALE; - - // Consider a square region. - int vp_size = MIN(img->get_width(), img->get_height()); - int x = (img->get_width() - vp_size) / 2; - int y = (img->get_height() - vp_size) / 2; - - if (vp_size < preview_size) { - // Just square it. - img->crop_from_point(x, y, vp_size, vp_size); - } else { - int ratio = vp_size / preview_size; - int size = preview_size * MAX(1, ratio / 2); - - x = (img->get_width() - size) / 2; - y = (img->get_height() - size) / 2; - - img->crop_from_point(x, y, size, size); - img->resize(preview_size, preview_size, Image::INTERPOLATE_LANCZOS); - } - img->convert(Image::FORMAT_RGB8); - - // Save thumbnail directly, as thumbnailer may not update due to actual scene not changing md5. - String temp_path = EditorPaths::get_singleton()->get_cache_dir(); - String cache_base = ProjectSettings::get_singleton()->globalize_path(p_file).md5_text(); - cache_base = temp_path.path_join("resthumb-" + cache_base); - - // Does not have it, try to load a cached thumbnail. - post_process_preview(img); - img->save_png(cache_base + ".png"); - } - } - - save_scene_progress->step(TTR("Saving Scene"), 4); - _save_scene(p_file, p_idx); - - if (!singleton->cmdline_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; @@ -2055,13 +1970,18 @@ void EditorNode::_save_scene(String p_file, int idx) { Node *scene = editor_data.get_edited_scene_root(idx); + save_scene_progress = memnew(EditorProgress("save", TTR("Saving Scene"), 3)); + save_scene_progress->step(TTR("Analyzing"), 0); + if (!scene) { show_accept(TTR("This operation can't be done without a tree root."), TTR("OK")); + _close_save_scene_progress(); return; } if (!scene->get_scene_file_path().is_empty() && _validate_scene_recursive(scene->get_scene_file_path(), scene)) { show_accept(TTR("This scene can't be saved because there is a cyclic instance inclusion.\nPlease resolve it and then attempt to save again."), TTR("OK")); + _close_save_scene_progress(); return; } @@ -2073,6 +1993,8 @@ void EditorNode::_save_scene(String p_file, int idx) { _reset_animation_mixers(scene, &anim_backups); _save_editor_states(p_file, idx); + save_scene_progress->step(TTR("Packing Scene"), 1); + Ref sdata; if (ResourceCache::has(p_file)) { @@ -2093,9 +2015,12 @@ void EditorNode::_save_scene(String p_file, int idx) { if (err != OK) { show_accept(TTR("Couldn't save scene. Likely dependencies (instances or inheritance) couldn't be satisfied."), TTR("OK")); + _close_save_scene_progress(); return; } + save_scene_progress->step(TTR("Saving scene"), 2); + int flg = 0; if (EDITOR_GET("filesystem/on_save/compress_binary_resources")) { flg |= ResourceSaver::FLAG_COMPRESS; @@ -2108,6 +2033,8 @@ void EditorNode::_save_scene(String p_file, int idx) { emit_signal(SNAME("scene_saved"), p_file); editor_data.notify_scene_saved(p_file); + save_scene_progress->step(TTR("Saving external resources"), 3); + _save_external_resources(); saving_scene = p_file; // Some editors may save scenes of built-in resources as external data, so avoid saving this scene again. editor_data.save_editor_external_data(); @@ -2132,6 +2059,7 @@ void EditorNode::_save_scene(String p_file, int idx) { scene->propagate_notification(NOTIFICATION_EDITOR_POST_SAVE); _update_unsaved_cache(); + _close_save_scene_progress(); } void EditorNode::save_all_scenes() { @@ -2171,7 +2099,7 @@ void EditorNode::try_autosave() { Node *scene = editor_data.get_edited_scene_root(); if (scene && !scene->get_scene_file_path().is_empty()) { // Only autosave if there is a scene and if it has a path. - _save_scene_with_preview(scene->get_scene_file_path()); + _save_scene(scene->get_scene_file_path()); } } _menu_option(SCENE_SAVE_ALL_SCENES); @@ -2199,7 +2127,7 @@ void EditorNode::_save_all_scenes() { } if (i == editor_data.get_edited_scene()) { - _save_scene_with_preview(scene_path); + _save_scene(scene_path); } else { _save_scene(scene_path, i); } @@ -2293,7 +2221,7 @@ void EditorNode::_dialog_action(String p_file) { } save_default_environment(); - _save_scene_with_preview(p_file, scene_idx); + _save_scene(p_file, scene_idx); _add_to_recent_scenes(p_file); save_editor_layout_delayed(); @@ -2314,7 +2242,7 @@ void EditorNode::_dialog_action(String p_file) { case SAVE_AND_RUN: { if (file->get_file_mode() == EditorFileDialog::FILE_MODE_SAVE_FILE) { save_default_environment(); - _save_scene_with_preview(p_file); + _save_scene(p_file); project_run_bar->play_custom_scene(p_file); } } break; @@ -2325,7 +2253,7 @@ void EditorNode::_dialog_action(String p_file) { if (file->get_file_mode() == EditorFileDialog::FILE_MODE_SAVE_FILE) { save_default_environment(); - _save_scene_with_preview(p_file); + _save_scene(p_file); project_run_bar->play_main_scene((bool)pick_main_scene->get_meta("from_native", false)); } } break; @@ -2439,7 +2367,7 @@ void EditorNode::_dialog_action(String p_file) { default: { // Save scene? if (file->get_file_mode() == EditorFileDialog::FILE_MODE_SAVE_FILE) { - _save_scene_with_preview(p_file); + _save_scene(p_file); } } break; @@ -2989,9 +2917,9 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { if (scene && !scene->get_scene_file_path().is_empty()) { if (DirAccess::exists(scene->get_scene_file_path().get_base_dir())) { if (scene_idx != editor_data.get_edited_scene()) { - _save_scene_with_preview(scene->get_scene_file_path(), scene_idx); + _save_scene(scene->get_scene_file_path(), scene_idx); } else { - _save_scene_with_preview(scene->get_scene_file_path()); + _save_scene(scene->get_scene_file_path()); } if (scene_idx != -1) { @@ -3161,7 +3089,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { confirmation_button->grab_focus(); break; } else { - _save_scene_with_preview(scene_filename); + _save_scene(scene_filename); } } @@ -7491,7 +7419,7 @@ EditorNode::EditorNode() { ResourceLoader::set_dependency_error_notify_func(&EditorNode::_dependency_error_report); SceneState::set_instantiation_warning_notify_func([](const String &p_warning) { - add_io_warning(p_warning); + callable_mp_static(EditorNode::add_io_warning).call_deferred(p_warning); callable_mp(EditorInterface::get_singleton(), &EditorInterface::mark_scene_as_unsaved).call_deferred(); }); diff --git a/editor/editor_node.h b/editor/editor_node.h index 904f3c1a3a..731e961653 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -638,7 +638,6 @@ private: bool _is_scene_unsaved(int p_idx); 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; @@ -935,11 +934,8 @@ public: Control *get_gui_base() { return gui_base; } void save_scene_to_path(String p_file, bool p_with_preview = true) { - if (p_with_preview) { - _save_scene_with_preview(p_file); - } else { - _save_scene(p_file); - } + // p_with_preview has no effect, now generates preview at EditorPackedScenePreviewPlugin + _save_scene(p_file); } bool is_scene_in_use(const String &p_path); diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp index bfb304fe8d..8c6f3292c5 100644 --- a/editor/editor_resource_preview.cpp +++ b/editor/editor_resource_preview.cpp @@ -97,7 +97,9 @@ void EditorResourcePreviewGenerator::DrawRequester::request_and_wait(RID p_viewp Callable request_vp_update_once = callable_mp(RS::get_singleton(), &RS::viewport_set_update_mode).bind(p_viewport, RS::VIEWPORT_UPDATE_ONCE); if (EditorResourcePreview::get_singleton()->is_threaded()) { - RS::get_singleton()->connect(SNAME("frame_pre_draw"), request_vp_update_once, Object::CONNECT_ONE_SHOT); + if (!RS::get_singleton()->is_connected(SNAME("frame_pre_draw"), request_vp_update_once)) { + RS::get_singleton()->connect(SNAME("frame_pre_draw"), request_vp_update_once, Object::CONNECT_ONE_SHOT); + } RS::get_singleton()->request_frame_drawn_callback(callable_mp(this, &EditorResourcePreviewGenerator::DrawRequester::_post_semaphore)); semaphore.wait(); @@ -127,10 +129,14 @@ Variant EditorResourcePreviewGenerator::DrawRequester::_post_semaphore() { return Variant(); // Needed because of how the callback is used. } -bool EditorResourcePreview::is_threaded() const { +bool EditorResourcePreview::can_run_on_thread() const { return RSG::rasterizer->can_create_resources_async(); } +bool EditorResourcePreview::is_threaded() const { + return thread.is_started(); +} + void EditorResourcePreview::_thread_func(void *ud) { EditorResourcePreview *erp = (EditorResourcePreview *)ud; erp->_thread(); @@ -269,11 +275,14 @@ void EditorResourcePreview::_iterate() { QueueItem item = queue.front()->get(); queue.pop_front(); + singleton->processing_item = item; + singleton->last_process_msec = OS::get_singleton()->get_ticks_msec(); if (cache.has(item.path)) { Item cached_item = cache[item.path]; // Already has it because someone loaded it, just let it know it's ready. _preview_ready(item.path, cached_item.last_hash, cached_item.preview, cached_item.small_preview, item.id, item.function, item.userdata, cached_item.preview_metadata); + singleton->processing_item = QueueItem(); preview_mutex.unlock(); return; } @@ -289,6 +298,9 @@ void EditorResourcePreview::_iterate() { Dictionary preview_metadata; _generate_preview(texture, small_texture, item, String(), preview_metadata); _preview_ready(item.path, item.resource->hash_edited_version_for_preview(), texture, small_texture, item.id, item.function, item.userdata, preview_metadata); + preview_mutex.lock(); + singleton->processing_item = QueueItem(); + preview_mutex.unlock(); return; } @@ -327,7 +339,7 @@ void EditorResourcePreview::_iterate() { cache_valid = false; f.unref(); } else if (last_modtime != modtime) { - String last_md5 = f->get_line(); + String last_md5 = hash; String md5 = FileAccess::get_md5(item.path); f.unref(); @@ -377,6 +389,9 @@ void EditorResourcePreview::_iterate() { } } _preview_ready(item.path, 0, texture, small_texture, item.id, item.function, item.userdata, preview_metadata); + preview_mutex.lock(); + singleton->processing_item = QueueItem(); + preview_mutex.unlock(); } void EditorResourcePreview::_write_preview_cache(Ref p_file, int p_thumbnail_size, bool p_has_small_texture, uint64_t p_modified_time, const String &p_hash, const Dictionary &p_metadata) { @@ -413,11 +428,57 @@ void EditorResourcePreview::_idle_callback() { return; } - // Process preview tasks, trying to leave a little bit of responsiveness worst case. - uint64_t start = OS::get_singleton()->get_ticks_msec(); - while (!singleton->queue.is_empty() && OS::get_singleton()->get_ticks_msec() - start < 100) { - singleton->_iterate(); + singleton->_update_progress_bar(); + + // Ensure to process one item at a time + singleton->preview_mutex.lock(); + bool processing = singleton->processing_item.path != ""; + singleton->preview_mutex.unlock(); + if (processing) { + return; } + + singleton->_iterate(); +} + +EditorProgress *EditorResourcePreview::thumbnail_progress = nullptr; // it's static + +void EditorResourcePreview::_update_progress_bar() { + DEV_ASSERT(Thread::get_caller_id() == Thread::get_main_id()); // Progress bar can only be updated in main thread + + // Return if nothing is happening + if (singleton->queue.is_empty() && thumbnail_progress == nullptr) { + singleton->progress_total_steps = -1; + return; + } + + // Create progress bar if not present + if (!singleton->queue.is_empty() && thumbnail_progress == nullptr && singleton->progress_total_steps == -1) { + singleton->progress_total_steps = singleton->queue.size(); + thumbnail_progress = memnew(EditorProgress("generate_thumbnails", "Generate Thumbnails", singleton->progress_total_steps)); + } + + // Update progress bar + if (!singleton->queue.is_empty() && thumbnail_progress != nullptr) { + // The full path could be too long to display, show only the file name + String queue_file; + if (singleton->queue.front()->get().path.count("/") > 1) { + queue_file = singleton->queue.front()->get().path.rsplit("/", true, 1)[1]; + } + int queue_steps = singleton->progress_total_steps - singleton->queue.size(); + int queue_total = singleton->progress_total_steps; + String msg = vformat("%s (%d/%d)", queue_file, queue_steps, queue_total); + + // Don't force update or will stuck in infinite loop at _idle_callback(), since ProgressDialog::task_step() iterates the main loop + thumbnail_progress->step(msg, queue_steps, false); + } + + // Destroy progress bar when queue empty + if (singleton->queue.is_empty() && thumbnail_progress != nullptr) { + memdelete(thumbnail_progress); + thumbnail_progress = nullptr; + } + return; } void EditorResourcePreview::_update_thumbnail_sizes() { @@ -556,7 +617,7 @@ void EditorResourcePreview::start() { return; } - if (is_threaded()) { + if (can_run_on_thread()) { ERR_FAIL_COND_MSG(thread.is_started(), "Thread already started."); thread.start(_thread_func, this); } else { @@ -568,23 +629,21 @@ void EditorResourcePreview::start() { void EditorResourcePreview::stop() { if (is_threaded()) { - if (thread.is_started()) { - exiting.set(); - preview_sem.post(); + exiting.set(); + preview_sem.post(); - for (int i = 0; i < preview_generators.size(); i++) { - preview_generators.write[i]->abort(); - } - - while (!exited.is_set()) { - // Sync pending work. - OS::get_singleton()->delay_usec(10000); - RenderingServer::get_singleton()->sync(); - MessageQueue::get_singleton()->flush(); - } - - thread.wait_to_finish(); + for (int i = 0; i < preview_generators.size(); i++) { + preview_generators.write[i]->abort(); } + + while (!exited.is_set()) { + // Sync pending work. + OS::get_singleton()->delay_usec(10000); + RenderingServer::get_singleton()->sync(); + MessageQueue::get_singleton()->flush(); + } + + thread.wait_to_finish(); } } diff --git a/editor/editor_resource_preview.h b/editor/editor_resource_preview.h index 5b25b5c611..2b7ebeae45 100644 --- a/editor/editor_resource_preview.h +++ b/editor/editor_resource_preview.h @@ -33,6 +33,7 @@ #include "core/os/semaphore.h" #include "core/os/thread.h" #include "core/templates/safe_refcount.h" +#include "editor/editor_node.h" #include "scene/main/node.h" class ImageTexture; @@ -73,7 +74,7 @@ public: class EditorResourcePreview : public Node { GDCLASS(EditorResourcePreview, Node); - static constexpr int CURRENT_METADATA_VERSION = 1; // Increment this number to invalidate all previews. + inline static constexpr int CURRENT_METADATA_VERSION = 2; // Increment this number to invalidate all previews. inline static EditorResourcePreview *singleton = nullptr; struct QueueItem { @@ -91,6 +92,10 @@ class EditorResourcePreview : public Node { Thread thread; SafeFlag exiting; SafeFlag exited; + QueueItem processing_item; + int last_process_msec = -1; + int progress_total_steps = -1; + static EditorProgress *thumbnail_progress; struct Item { Ref preview; @@ -111,6 +116,7 @@ class EditorResourcePreview : public Node { void _thread(); // For rendering drivers supporting async texture creation. static void _idle_callback(); // For other rendering drivers (i.e., OpenGL). void _iterate(); + void _update_progress_bar(); void _write_preview_cache(Ref p_file, int p_thumbnail_size, bool p_has_small_texture, uint64_t p_modified_time, const String &p_hash, const Dictionary &p_metadata); void _read_preview_cache(Ref p_file, int *r_thumbnail_size, bool *r_has_small_texture, uint64_t *r_modified_time, String *r_hash, Dictionary *r_metadata, bool *r_outdated); @@ -145,6 +151,7 @@ public: void start(); void stop(); + bool can_run_on_thread() const; bool is_threaded() const; EditorResourcePreview(); diff --git a/editor/import/3d/resource_importer_scene.cpp b/editor/import/3d/resource_importer_scene.cpp index f0da6d2460..45bcd1930e 100644 --- a/editor/import/3d/resource_importer_scene.cpp +++ b/editor/import/3d/resource_importer_scene.cpp @@ -34,7 +34,6 @@ #include "core/io/dir_access.h" #include "core/io/resource_saver.h" #include "core/object/script_language.h" -#include "editor/editor_interface.h" #include "editor/editor_node.h" #include "editor/editor_settings.h" #include "editor/import/3d/scene_import_settings.h" @@ -2864,15 +2863,6 @@ void ResourceImporterScene::_optimize_track_usage(AnimationPlayer *p_player, Ani } } -void ResourceImporterScene::_generate_editor_preview_for_scene(const String &p_path, Node *p_scene) { - if (!Engine::get_singleton()->is_editor_hint()) { - return; - } - ERR_FAIL_COND_MSG(p_path.is_empty(), "Path is empty, cannot generate preview."); - ERR_FAIL_NULL_MSG(p_scene, "Scene is null, cannot generate preview."); - EditorInterface::get_singleton()->make_scene_preview(p_path, p_scene, 1024); -} - Node *ResourceImporterScene::pre_import(const String &p_source_file, const HashMap &p_options) { Ref importer; String ext = p_source_file.get_extension().to_lower(); @@ -3280,7 +3270,6 @@ Error ResourceImporterScene::import(ResourceUID::ID p_source_id, const String &p print_verbose("Saving scene to: " + p_save_path + ".scn"); err = ResourceSaver::save(packer, p_save_path + ".scn", flags); //do not take over, let the changed files reload themselves ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save scene to file '" + p_save_path + ".scn'."); - _generate_editor_preview_for_scene(p_source_file, scene); } else { ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "Unknown scene import type: " + _scene_import_type); } diff --git a/editor/import/3d/resource_importer_scene.h b/editor/import/3d/resource_importer_scene.h index 224ad97e3d..775c69c816 100644 --- a/editor/import/3d/resource_importer_scene.h +++ b/editor/import/3d/resource_importer_scene.h @@ -231,7 +231,6 @@ class ResourceImporterScene : public ResourceImporter { }; void _optimize_track_usage(AnimationPlayer *p_player, AnimationImportTracks *p_track_actions); - void _generate_editor_preview_for_scene(const String &p_path, Node *p_scene); String _scene_import_type = "PackedScene"; diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index 5927f9d736..f203c6b21d 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -34,9 +34,28 @@ #include "core/io/image.h" #include "core/io/resource_loader.h" #include "core/object/script_language.h" +#include "editor/editor_node.h" #include "editor/editor_paths.h" #include "editor/editor_settings.h" #include "editor/themes/editor_scale.h" +#include "main/main.h" +#include "modules/gridmap/grid_map.h" +#include "scene/2d/animated_sprite_2d.h" +#include "scene/2d/camera_2d.h" +#include "scene/2d/line_2d.h" +#include "scene/2d/mesh_instance_2d.h" +#include "scene/2d/multimesh_instance_2d.h" +#include "scene/2d/physics/touch_screen_button.h" +#include "scene/2d/polygon_2d.h" +#include "scene/2d/sprite_2d.h" +#include "scene/2d/tile_map_layer.h" +#include "scene/3d/cpu_particles_3d.h" +#include "scene/3d/gpu_particles_3d.h" +#include "scene/3d/light_3d.h" +#include "scene/3d/mesh_instance_3d.h" +#include "scene/gui/option_button.h" +#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "scene/resources/atlas_texture.h" #include "scene/resources/bit_map.h" #include "scene/resources/font.h" @@ -44,6 +63,7 @@ #include "scene/resources/image_texture.h" #include "scene/resources/material.h" #include "scene/resources/mesh.h" +#include "scene/resources/world_2d.h" #include "servers/audio/audio_stream.h" void post_process_preview(Ref p_image) { @@ -283,6 +303,11 @@ bool EditorBitmapPreviewPlugin::generate_small_preview_automatically() const { /////////////////////////////////////////////////////////////////////////// +void EditorPackedScenePreviewPlugin::abort() { + draw_requester.abort(); + aborted = true; +} + bool EditorPackedScenePreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "PackedScene"); } @@ -292,28 +317,701 @@ Ref EditorPackedScenePreviewPlugin::generate(const Ref &p_f } Ref EditorPackedScenePreviewPlugin::generate_from_path(const String &p_path, const Size2 &p_size, Dictionary &p_metadata) const { - String temp_path = EditorPaths::get_singleton()->get_cache_dir(); - String cache_base = ProjectSettings::get_singleton()->globalize_path(p_path).md5_text(); - cache_base = temp_path.path_join("resthumb-" + cache_base); + ERR_FAIL_COND_V_MSG(!Engine::get_singleton()->is_editor_hint(), Ref(), "This function can only be called from the editor."); + ERR_FAIL_NULL_V_MSG(EditorNode::get_singleton(), Ref(), "EditorNode doesn't exist."); - //does not have it, try to load a cached thumbnail + // Lower abort flag + aborted = false; - String path = cache_base + ".png"; - - if (!FileAccess::exists(path)) { + Error load_error; + Ref pack = ResourceLoader::load(p_path, "PackedScene", ResourceFormatLoader::CACHE_MODE_IGNORE, &load_error); // no more cache issues? + if (load_error != OK) { + print_error(vformat("Failed to generate scene thumbnail for %s : Loaded with error code %d", p_path, int(load_error))); + return Ref(); + } + if (pack.is_null()) { + print_error(vformat("Failed to generate scene thumbnail for %s : Invalid scene file", p_path)); return Ref(); } - Ref img; - img.instantiate(); - Error err = img->load(path); - if (err == OK) { - post_process_preview(img); - return ImageTexture::create_from_image(img); + bool _scene_setup_success = _setup_packed_scene(pack); // We don't want tool scripts to fire off when generating previews + if (!_scene_setup_success) { + print_error(vformat("Failed to generate scene thumbnail for %s : error in setting up preview scene, thus not safe to create thumbnail image", p_path)); + return Ref(); + } + Node *p_scene = pack->instantiate(); // The instantiated preview scene + + // Prohibit Viewport class as root when generating thumbnails + if (Object::cast_to(p_scene)) { + p_scene->queue_free(); + return Ref(); + } + + int count_2d = 0; + int count_3d = 0; + int count_light_3d = 0; + _count_node_types(p_scene, count_2d, count_3d, count_light_3d); + + if (count_3d > 0) { // Is 3d scene + // Setup preview viewport + SubViewport *sub_viewport = memnew(SubViewport); + sub_viewport->set_update_mode(SubViewport::UpdateMode::UPDATE_DISABLED); + + sub_viewport->set_size(Size2i(Math::round(p_size.x), Math::round(p_size.y))); + sub_viewport->set_transparent_background(false); + sub_viewport->set_disable_3d(false); + + if (p_size.x < 2048 && p_size.y < 2048) { // Universal baseline for textures in Godot 4 is 4K + sub_viewport->set_scaling_3d_scale(2.0); // Supersampling x2 + } + + if (RS::get_singleton()->get_current_rendering_method() != "gl_compatibility") { + sub_viewport->set_msaa_3d(Viewport::MSAA::MSAA_8X); + } + + Ref environment; + Color default_clear_color = GLOBAL_GET("rendering/environment/defaults/default_clear_color"); + environment.instantiate(); + environment->set_background(Environment::BGMode::BG_CLEAR_COLOR); + environment->set_bg_color(default_clear_color); + Ref world_3d; + sub_viewport->set_world_3d(world_3d); + sub_viewport->set_use_own_world_3d(true); + + Camera3D *camera_3d = memnew(Camera3D); + + sub_viewport->add_child(camera_3d); + camera_3d->set_perspective(preview_3d_fov, 0.05, 10000.0); + + // Add scene to viewport + _setup_scene_3d(p_scene); + sub_viewport->add_child(p_scene); + + // Setup preview light + DirectionalLight3D *light_1 = nullptr; + DirectionalLight3D *light_2 = nullptr; + + if (count_light_3d == 0) { + light_1 = memnew(DirectionalLight3D); + light_2 = memnew(DirectionalLight3D); + sub_viewport->add_child(light_1); + sub_viewport->add_child(light_2); + light_1->set_color(Color(1.0, 1.0, 1.0, 1.0)); + light_2->set_color(Color(0.7, 0.7, 0.7, 1.0)); + light_1->set_transform(Transform3D(Basis().rotated(Vector3(0, 1, 0), -Math::PI / 6), Vector3(0.0, 0.0, 0.0))); + light_2->set_transform(Transform3D(Basis().rotated(Vector3(1, 0, 0), -Math::PI / 6), Vector3(0.0, 0.0, 0.0))); + } + + // Setup preview camera + AABB scene_aabb; + _calculate_scene_aabb(p_scene, scene_aabb); + float bound_sphere_radius = (scene_aabb.get_end() - scene_aabb.get_position()).length() / 2.0f; + if (bound_sphere_radius <= 0.0f) { + // The scene has zero volume, so just it give a literal + bound_sphere_radius = 1.0f; + } + + float cam_distance = bound_sphere_radius / Math::tan(Math::deg_to_rad(preview_3d_fov) / 2.0f); + Transform3D thumbnail_cam_trans_3d; + thumbnail_cam_trans_3d.set_origin(scene_aabb.get_center() + Vector3(1.0f, 0.25f, 1.0f).normalized() * cam_distance); + thumbnail_cam_trans_3d.set_look_at(thumbnail_cam_trans_3d.origin, scene_aabb.get_center()); + + // Set camera to orthogonal if distance exceeds camera default far (large scene) + if (thumbnail_cam_trans_3d.origin.length() > camera_3d->get_far()) { + real_t distance = thumbnail_cam_trans_3d.origin.length(); + camera_3d->set_orthogonal(distance / 2.0, distance / 1000.0, distance); // Approximately contains the whole scene + } + + camera_3d->set_transform(thumbnail_cam_trans_3d); + + // Attach the preview viewport to MainTree + sub_viewport->set_update_mode(SubViewport::UpdateMode::UPDATE_ONCE); + if (EditorResourcePreview::get_singleton()->is_threaded()) { + callable_mp((Node *)EditorNode::get_singleton(), &Node::add_child).call_deferred(sub_viewport, false, Node::InternalMode::INTERNAL_MODE_DISABLED); + callable_mp(camera_3d, &Camera3D::set_current).call_deferred(true); + } else { + EditorNode::get_singleton()->add_child(sub_viewport); + camera_3d->set_current(true); + } + _wait_frame(); + draw_requester.request_and_wait(sub_viewport->get_viewport_rid()); + + if (aborted) { + sub_viewport->queue_free(); + return Ref(); + } + + // Retrieve thumbnail image + Ref thumbnail; + thumbnail = ImageTexture::create_from_image(sub_viewport->get_texture()->get_image()); + + // Clean up + sub_viewport->queue_free(); + + return thumbnail; + } + + if (count_2d > 0) { // Is 2d scene + // If anyone want to rewrite this part to call RenderingServer directly, note that at the time of writing, + // there's a limitation where CanvasItem cannot be rendered outside of the tree. + // See CanvasItem::queue_redraw() and RenderingServer::draw() + int texture_filter = GLOBAL_GET("rendering/textures/canvas_textures/default_texture_filter"); + int texture_repeat = GLOBAL_GET("rendering/textures/canvas_textures/default_texture_repeat"); + + SubViewport *sub_viewport = memnew(SubViewport); + sub_viewport->set_update_mode(SubViewport::UpdateMode::UPDATE_DISABLED); + sub_viewport->set_disable_3d(true); + sub_viewport->set_transparent_background(false); + if (RS::get_singleton()->get_current_rendering_method() != "gl_compatibility") { + sub_viewport->set_msaa_2d(Viewport::MSAA::MSAA_8X); + } + sub_viewport->set_default_canvas_item_texture_filter(Viewport::DefaultCanvasItemTextureFilter(texture_filter)); + sub_viewport->set_default_canvas_item_texture_repeat(Viewport::DefaultCanvasItemTextureRepeat(texture_repeat)); + Ref world; + world.instantiate(); + sub_viewport->set_world_2d(world); + sub_viewport->add_child(p_scene); + + _setup_scene_2d(p_scene); + _hide_gui_in_scene(p_scene); + + // Preview camera + Camera2D *camera = memnew(Camera2D); + sub_viewport->add_child(camera); + camera->set_enabled(true); + + // Attach subviewport (following process needs scene to be in tree) + if (EditorResourcePreview::get_singleton()->is_threaded()) { + callable_mp((Node *)EditorNode::get_singleton(), &Node::add_child).call_deferred(sub_viewport, false, Node::InternalMode::INTERNAL_MODE_DISABLED); + callable_mp((Camera2D *)camera, &Camera2D::make_current).call_deferred(); + } else { + EditorNode::get_singleton()->add_child(sub_viewport); + camera->make_current(); + } + _wait_frame(); + + if (aborted) { + sub_viewport->queue_free(); + return Ref(); + } + + // Calculate scene rect + Rect2 scene_rect; + _calculate_scene_rect(p_scene, scene_rect); + Vector2 scene_true_center = scene_rect.get_center(); + + // Place camera 2D + camera->set_position(Point2(scene_true_center)); + + // Render viewport + uint16_t scene_rect_long = MAX(scene_rect.get_size().x, scene_rect.get_size().y); + if (scene_rect_long == 0) { + scene_rect_long = MAX(p_size.x, p_size.y); // Prevent 0 size rect (which causes error) and defaults to thumbnail size. + } + sub_viewport->set_size(p_size); + camera->set_zoom(Vector2(p_size.x / float(scene_rect_long), p_size.y / float(scene_rect_long))); + sub_viewport->set_update_mode(SubViewport::UpdateMode::UPDATE_ONCE); + _wait_frame(); + draw_requester.request_and_wait(sub_viewport->get_viewport_rid()); + + if (aborted) { + sub_viewport->queue_free(); + return Ref(); + } + + // Retrieve thumbnail of 2D (No GUI) + Ref capture_2d = ImageTexture::create_from_image(sub_viewport->get_texture()->get_image()); + capture_2d->get_image()->resize(p_size.x, p_size.y); + capture_2d->get_image()->convert(Image::Format::FORMAT_RGBA8); // ALPHA channel is required for image blending + + // Prepare for gui render + callable_mp((Node *)sub_viewport, &Node::remove_child).call_deferred(p_scene); + p_scene->queue_free(); + p_scene = pack->instantiate(); + _setup_scene_2d(p_scene); + _hide_node_2d_in_scene(p_scene); + SubViewport *sub_viewport_gui = memnew(SubViewport); + sub_viewport_gui->set_size(Size2i(GLOBAL_GET("display/window/size/viewport_width"), GLOBAL_GET("display/window/size/viewport_height"))); + sub_viewport_gui->set_update_mode(SubViewport::UpdateMode::UPDATE_DISABLED); + sub_viewport_gui->set_transparent_background(true); + if (RS::get_singleton()->get_current_rendering_method() != "gl_compatibility") { + sub_viewport_gui->set_msaa_2d(Viewport::MSAA::MSAA_8X); + } + sub_viewport_gui->set_default_canvas_item_texture_filter(Viewport::DefaultCanvasItemTextureFilter(texture_filter)); + sub_viewport_gui->set_default_canvas_item_texture_repeat(Viewport::DefaultCanvasItemTextureRepeat(texture_repeat)); + sub_viewport_gui->set_disable_3d(true); + sub_viewport_gui->add_child(p_scene); + + // Render GUI + sub_viewport_gui->set_update_mode(SubViewport::UpdateMode::UPDATE_ONCE); + if (EditorResourcePreview::get_singleton()->is_threaded()) { + callable_mp((Node *)EditorNode::get_singleton(), &Node::add_child).call_deferred(sub_viewport_gui, false, Node::InternalMode::INTERNAL_MODE_DISABLED); + } else { + EditorNode::get_singleton()->add_child(sub_viewport_gui); + } + _wait_frame(); + draw_requester.request_and_wait(sub_viewport_gui->get_viewport_rid()); + + if (aborted) { + sub_viewport->queue_free(); + sub_viewport_gui->queue_free(); + return Ref(); + } + + // Retrieve thumbnail of gui + Ref capture_gui = ImageTexture::create_from_image(sub_viewport_gui->get_texture()->get_image()); + capture_gui->get_image()->resize(p_size.x, p_size.y); + + // Mix 2D, GUI thumbnail images into one + Ref thumbnail; + thumbnail.instantiate(); + Ref thumbnail_image = Image::create_empty(p_size.x, p_size.y, false, Image::Format::FORMAT_RGBA8); // blend_rect needs ALPHA channel to work + thumbnail_image->blend_rect(capture_2d->get_image(), capture_2d->get_image()->get_used_rect(), Point2i(0, 0)); + thumbnail_image->blend_rect(capture_gui->get_image(), capture_gui->get_image()->get_used_rect(), Point2i(0, 0)); + thumbnail->set_image(thumbnail_image); + + // Clean up + sub_viewport->queue_free(); + sub_viewport_gui->queue_free(); + + return thumbnail; + } + + // Is scene without any visuals (No Node2D, Node3D, Control found) + return Ref(); +} + +void EditorPackedScenePreviewPlugin::_setup_scene_3d(Node *p_node) const { + // Do not account any SubViewport at preview scene, as it would not render correctly + if (Object::cast_to(p_node) && p_node->get_parent()) { + p_node->get_parent()->remove_child(p_node); + callable_mp(p_node, &Node::queue_free).call_deferred(); + return; + } + + // Don't let window to popup + Window *window = Object::cast_to(p_node); + if (window) { + window->set_visible(false); + } + + // Make sure no Node2D, Control node is visible (Might occupy large proportion of the thumbnail) + Node2D *n2d = Object::cast_to(p_node); + if (n2d) { + n2d->set_visible(false); + } + + Control *ctrl = Object::cast_to(p_node); + if (ctrl) { + ctrl->set_visible(false); + } + + // Disable skinning for skeleton meshes (animations and skeleton scaling might disturb aabb calculation) + MeshInstance3D *mesh = Object::cast_to(p_node); + if (mesh && mesh->is_visible_in_tree()) { + mesh->set_skeleton_path(NodePath()); + } + + CPUParticles3D *cpu_particles = Object::cast_to(p_node); + if (cpu_particles && cpu_particles->is_visible_in_tree()) { + cpu_particles->set_pre_process_time(cpu_particles->get_lifetime() * 0.5); // Fast forward the particle emission to make it render something + cpu_particles->set_use_local_coordinates(true); // HACK - Now constructs scene outside of tree, using global coords will cause error, this may introduce visual bugs, but is the best solution now + cpu_particles->restart(true); // Keep seed to make simulation persistent + } + + GPUParticles3D *gpu_particles = Object::cast_to(p_node); + if (gpu_particles && gpu_particles->is_visible_in_tree()) { + // Convert to CPUParticles (As GPUParticles can't be rendered correctly in thumbnails, don't know why) + CPUParticles3D *gtc_particles = memnew(CPUParticles3D); // GPU to CPU particles + gtc_particles->convert_from_particles(gpu_particles); + gpu_particles->add_child(gtc_particles); // So the created CPUParticles instance will be freed later we call queue_free() on the preview scene + + // Setup CPUParticles + gtc_particles->set_pre_process_time(gtc_particles->get_lifetime() * 0.5); + gtc_particles->set_use_local_coordinates(true); + gtc_particles->restart(true); + } + + for (int i = 0; i < p_node->get_child_count(); i++) { + _setup_scene_3d(p_node->get_child(i)); + } +} + +void EditorPackedScenePreviewPlugin::_setup_scene_2d(Node *p_node) const { + // Do not account any SubViewport at preview scene, as it would not render correctly + if (Object::cast_to(p_node) && p_node->get_parent()) { + p_node->get_parent()->remove_child(p_node); + callable_mp(p_node, &Node::queue_free).call_deferred(); + return; + } + + // Don't let window to popup + Window *window = Object::cast_to(p_node); + if (window) { + window->set_visible(false); + } + + for (int i = 0; i < p_node->get_child_count(); i++) { + _setup_scene_2d(p_node->get_child(i)); + } +} + +void EditorPackedScenePreviewPlugin::_count_node_types(Node *p_node, int &r_c2d, int &r_c3d, int &r_clight3d) const { + if (p_node->is_class("Control") || p_node->is_class("Node2D")) { + r_c2d++; + } + if (p_node->is_class("Node3D")) { + r_c3d++; + } + if (p_node->is_class("Light3D")) { + r_clight3d++; + } + for (int i = 0; i < p_node->get_child_count(); i++) { + // Do not count anything under SubViewport node, those children are irrelevant for determining if the scene is 2D or 3D. + if (p_node->get_child(i)->is_class("SubViewport")) { + continue; + } + _count_node_types(p_node->get_child(i), r_c2d, r_c3d, r_clight3d); + } +} + +void EditorPackedScenePreviewPlugin::_calculate_scene_rect(Node *p_node, Rect2 &r_rect) const { + // NOTE: There's no universal way to get the exact global rect as a Node2D, so we dig into subclasses one by one + + // NOTE: + // 1. Sprite2D::position by default is at the **center** of the sprite. (with offset == (0,0) AND centered == true) + // 2. Rect2::position is at the **up-left** of the rect + // 3. AABB::position is at the **bottom-left-forward** of the bounding box + // + // calculation below is done with these in mind. + + Rect2 n2d_rect; // The rect of the current iterating Node2D + + Sprite2D *sprite = Object::cast_to(p_node); + if (sprite && sprite->is_visible_in_tree()) { + n2d_rect.size = sprite->get_global_scale() * sprite->get_rect().size; + n2d_rect.position = sprite->get_global_position() + sprite->get_offset() * sprite->get_global_scale(); + if (sprite->is_centered()) { + n2d_rect.position -= n2d_rect.size / 2.0f; + } + } + + AnimatedSprite2D *anim_sprite = Object::cast_to(p_node); + if (anim_sprite && anim_sprite->is_visible_in_tree()) { + if (anim_sprite->get_sprite_frames().is_valid()) { + Ref current_frame_tex = anim_sprite->get_sprite_frames()->get_frame_texture(anim_sprite->get_animation(), anim_sprite->get_frame()); + + if (current_frame_tex.is_valid()) { + n2d_rect.size = current_frame_tex->get_size() * anim_sprite->get_global_scale(); + n2d_rect.position = anim_sprite->get_global_position() + anim_sprite->get_offset() * anim_sprite->get_global_scale(); + if (anim_sprite->is_centered()) { + n2d_rect.position -= n2d_rect.size / 2.0f; + } + } + } + } + + MeshInstance2D *mesh2d = Object::cast_to(p_node); + if (mesh2d && mesh2d->is_visible_in_tree()) { + // NOTE: Conversion is 1m = 1px (before 2d scale) + Ref mesh = mesh2d->get_mesh(); + + if (mesh.is_valid()) { + // Discard z axis (depth) and only get length of mesh in x,y axis + n2d_rect.size.x = (mesh->get_aabb().get_end() - mesh->get_aabb().position).x; + n2d_rect.size.y = (mesh->get_aabb().get_end() - mesh->get_aabb().position).y; + n2d_rect.size *= mesh2d->get_global_scale(); + + // Account for mesh offset in 3d space when calculating rect2 + n2d_rect.position.x = mesh2d->get_global_position().x + mesh->get_aabb().position.x * mesh2d->get_global_scale().x; // AABB::position is bottom-left + n2d_rect.position.y = mesh2d->get_global_position().y + mesh->get_aabb().position.y * mesh2d->get_global_scale().y; + } + } + + MultiMeshInstance2D *mmesh2d = Object::cast_to(p_node); + if (mmesh2d && mmesh2d->is_visible_in_tree()) { + // Basically the same procedure as MeshInstance2D. + Ref mmesh = mmesh2d->get_multimesh(); + + if (mmesh.is_valid()) { + n2d_rect.size.x = (mmesh->get_aabb().get_end() - mmesh->get_aabb().position).x; + n2d_rect.size.y = (mmesh->get_aabb().get_end() - mmesh->get_aabb().position).y; + n2d_rect.size *= mmesh2d->get_global_scale(); + + n2d_rect.position.x = mmesh2d->get_global_position().x + mmesh->get_aabb().position.x * mmesh2d->get_global_scale().x; + n2d_rect.position.y = mmesh2d->get_global_position().y + mmesh->get_aabb().position.y * mmesh2d->get_global_scale().y; + } + } + + TileMapLayer *tile_map = Object::cast_to(p_node); + if (tile_map && tile_map->is_visible_in_tree()) { + // NOTE: TileMapLayer::get_used_rect() only count cells, not their actual pixel size + + if (tile_map->get_tile_set().is_valid()) { + Size2 tile_size = tile_map->get_tile_set()->get_tile_size(); // Tile map cell pixel size (x,y). + Rect2 tile_rect = tile_map->get_used_rect(); // Unit is in cells, not pixels! + + n2d_rect.position = tile_map->get_global_position() + tile_rect.position * tile_size * tile_map->get_global_scale(); // Accounts tilemap offset + n2d_rect.size = tile_rect.size * tile_size * tile_map->get_global_scale(); + } + } + + Polygon2D *poly2d = Object::cast_to(p_node); + if (poly2d && poly2d->is_visible_in_tree()) { + PackedVector2Array polygon = poly2d->get_polygon(); + + if (polygon.size() > 2) { // Abort if there's no surface (min = 3 verts) + // Calculate bounds + float max_x = polygon[0].x; + float min_x = polygon[0].x; + float max_y = polygon[0].y; + float min_y = polygon[0].y; + for (int i = 0; i < polygon.size(); i++) { + if (polygon[i].x > max_x) { + max_x = polygon[i].x; + } + if (polygon[i].x < min_x) { + min_x = polygon[i].x; + } + + if (polygon[i].y > max_y) { + max_y = polygon[i].y; + } + if (polygon[i].y < min_y) { + min_y = polygon[i].y; + } + } + + Rect2 poly_rect = Rect2(min_x, min_y, max_x - min_x, max_y - min_y); + + n2d_rect.position = poly2d->get_global_position() + poly2d->get_offset() * poly2d->get_global_scale(); + n2d_rect.position += poly_rect.position * poly2d->get_global_scale(); + n2d_rect.size = poly_rect.size * poly2d->get_global_scale(); + } + } + + Line2D *line2d = Object::cast_to(p_node); + if (line2d && line2d->is_visible_in_tree()) { + // The same procedure as Polygon2D + PackedVector2Array points = line2d->get_points(); + + if (line2d->get_point_count() > 1) { // Abort if there's no line drawn + // Calculate bounds + float max_x = points[0].x; + float min_x = points[0].x; + float max_y = points[0].y; + float min_y = points[0].y; + for (int i = 0; i < points.size(); i++) { + if (points[i].x > max_x) { + max_x = points[i].x; + } + if (points[i].x < min_x) { + min_x = points[i].x; + } + + if (points[i].y > max_y) { + max_y = points[i].y; + } + if (points[i].y < min_y) { + min_y = points[i].y; + } + } + + Rect2 line2d_rect = Rect2(min_x, min_y, max_x - min_x, max_y - min_y); + + n2d_rect.position = line2d->get_global_position(); + n2d_rect.position += line2d_rect.position * line2d->get_global_scale(); + n2d_rect.size = line2d_rect.size * line2d->get_global_scale(); + n2d_rect.size += Size2(line2d->get_width(), line2d->get_width()) / 2.0f; // account for line width + } + } + + TouchScreenButton *btn = Object::cast_to(p_node); + if (btn && btn->is_visible_in_tree()) { + Ref btn_tex = btn->get_texture_normal(); + + if (btn_tex.is_valid()) { // Abort if there's no normal texture for this button (won't display anything) + n2d_rect.position = btn->get_global_position(); // It's not possible to offset image in this node + n2d_rect.size = btn_tex->get_size() * btn->get_global_scale(); + } + } + + // Merge the calculated node 2d rect + if (r_rect.get_size().length_squared() == 0.0f) { // Avoid accounting scene origin (0,0) into scene rect. + r_rect = n2d_rect.abs(); } else { - return Ref(); + r_rect = r_rect.merge(n2d_rect.abs()); } + + for (int i = 0; i < p_node->get_child_count(); i++) { + _calculate_scene_rect(p_node->get_child(i), r_rect); + } +} + +void EditorPackedScenePreviewPlugin::_hide_node_2d_in_scene(Node *p_node) const { + // NOTE: Irreversible (cannot unhide nodes after this) + // We cannot simple hide() since it will affect all its children (may contain Control nodes) + + if (p_node->is_class("Node2D")) { + Node2D *n2d = Object::cast_to(p_node); + n2d->set_self_modulate(Color(0.0f, 0.0f, 0.0f, 0.0f)); + } + + for (int i = 0; i < p_node->get_child_count(); i++) { + _hide_node_2d_in_scene(p_node->get_child(i)); + } +} + +void EditorPackedScenePreviewPlugin::_hide_gui_in_scene(Node *p_node) const { + // NOTE: Irreversible (cannot unhide nodes after this) + // We cannot simply hide() since it will affect all its children (may contain Node2D nodes) + + if (p_node->is_class("Control")) { + Control *ctrl = Object::cast_to(p_node); + ctrl->set_self_modulate(Color(0.0f, 0.0f, 0.0f, 0.0f)); + } + + for (int i = 0; i < p_node->get_child_count(); i++) { + _hide_gui_in_scene(p_node->get_child(i)); + } +} + +// Hacky implementation, remove this when draw_requester.request_and_wait() is sufficient to render previews properly. +// Is needed for 2 reason: +// 1. Scene preview requires adding scene to tree and wait for RenderingServer to redraw. +// 2. To resolve some rendering bugs by waiting extra frames. +void EditorPackedScenePreviewPlugin::_wait_frame() const { + const uint64_t prev_frame = Engine::get_singleton()->get_frames_drawn(); + while (Engine::get_singleton()->get_frames_drawn() - prev_frame < 1) { + if (!EditorResourcePreview::get_singleton()->is_threaded()) { + // Is running this on main thread, iterate main loop (or will get stuck here forever) + DisplayServer::get_singleton()->process_events(); + Main::iteration(); + } + if (aborted) { + break; + } + continue; + } +} + +void EditorPackedScenePreviewPlugin::_calculate_scene_aabb(Node *p_node, AABB &r_aabb) const { + GeometryInstance3D *g3d = Object::cast_to(p_node); + if (g3d && g3d->is_visible_in_tree()) { // Use this because VisualInstance3D may have derived classes that are non-graphical (probes, volumes) + AABB node_aabb = _get_global_transform_3d(g3d).xform(g3d->get_aabb()); + r_aabb.merge_with(node_aabb); + } + + CPUParticles3D *cpu_particles = Object::cast_to(p_node); + if (cpu_particles && cpu_particles->is_visible_in_tree()) { // CPUParticles3D does not calculate particle bounds, so do it here + // Account the furthest position where particles can go + Vector3 particle_destination = _get_global_transform_3d(cpu_particles).origin; + particle_destination += cpu_particles->get_direction() * cpu_particles->get_param_max(CPUParticles3D::PARAM_INITIAL_LINEAR_VELOCITY); + r_aabb.expand_to(particle_destination * 0.5); + r_aabb.expand_to(particle_destination * -0.5); + } + + GPUParticles3D *gpu_particles = Object::cast_to(p_node); + if (gpu_particles && gpu_particles->is_visible_in_tree()) { + r_aabb.merge_with(_get_global_transform_3d(gpu_particles).xform(gpu_particles->get_visibility_aabb())); + } + + for (int i = 0; i < p_node->get_child_count(); i++) { + _calculate_scene_aabb(p_node->get_child(i), r_aabb); + } +} + +Transform3D EditorPackedScenePreviewPlugin::_get_global_transform_3d(Node *p_n3d) const { + // Designed to work even if node is outside the tree (is_inside_tree() != true) + Transform3D global_transform; + Array parents; + + if (!p_n3d->is_class("Node3D")) { + ERR_PRINT("Expected a Node3D node as argument"); + return global_transform; + } + + Node *p_loop_node = p_n3d; + while (p_loop_node != nullptr) { + if (p_loop_node->is_class("Node3D")) { + parents.append(p_loop_node); + } + p_loop_node = p_loop_node->get_parent(); + } + + parents.reverse(); + + for (int i = 0; i < parents.size(); i++) { + Node3D *p_parent = Object::cast_to(parents[i]); + if (i == 0) { + global_transform = p_parent->get_transform(); + continue; + } + global_transform *= p_parent->get_transform(); + } + + return global_transform; +} + +bool EditorPackedScenePreviewPlugin::_setup_packed_scene(Ref p_pack) const { + // Refer to SceneState in packed_scene.cpp to see how PackedScene is managed underhood. + + // Sanitize + Dictionary bundle = p_pack->get_state()->get_bundled_scene(); + ERR_FAIL_COND_V(!bundle.has("names"), false); + ERR_FAIL_COND_V(!bundle.has("variants"), false); + ERR_FAIL_COND_V(!bundle.has("node_count"), false); + ERR_FAIL_COND_V(!bundle.has("nodes"), false); + ERR_FAIL_COND_V(!bundle.has("conn_count"), false); + ERR_FAIL_COND_V(!bundle.has("conns"), false); + + const uint8_t supported_version = 3; + uint8_t current_version = bundle.get("version", 1); + + if (current_version > supported_version) { + WARN_PRINT_ONCE(vformat("Scene thumbnail creation was built upon PackedScene with version %d, but the version has changed to %d now.", supported_version, current_version)); + // And assume it's safe to continue, there should have no reason to change the main structure of PackedScene + } + + // Find and remove variants in scene + const Ref