summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSpartan322 <Megacake1234@gmail.com>2024-10-14 02:57:59 -0400
committerSpartan322 <Megacake1234@gmail.com>2024-10-14 02:57:59 -0400
commit22d604c80d9ffd7ad72b06458a2e8e72ee5737e3 (patch)
tree176614fa17d6a68691b5f27f8e5f7d9b4dd17729
parent83d65738b06986e5aa0943cae01e357133e04a75 (diff)
parent92e51fca7247c932f95a1662aefc28aca96e8de6 (diff)
downloadredot-engine-22d604c80d9ffd7ad72b06458a2e8e72ee5737e3.tar.gz
Merge commit godotengine@92e51fca7247c932f95a1662aefc28aca96e8de6
-rw-r--r--.github/CODEOWNERS64
-rw-r--r--.github/workflows/windows_builds.yml29
-rw-r--r--core/config/project_settings.cpp18
-rw-r--r--core/math/geometry_2d.cpp12
-rw-r--r--doc/classes/Environment.xml3
-rw-r--r--doc/classes/PackedVector2Array.xml2
-rw-r--r--drivers/d3d12/SCsub6
-rw-r--r--drivers/d3d12/dxil_hash.cpp2
-rw-r--r--drivers/d3d12/rendering_device_driver_d3d12.cpp9
-rw-r--r--drivers/egl/egl_manager.cpp65
-rw-r--r--drivers/egl/egl_manager.h7
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp21
-rw-r--r--drivers/gles3/rasterizer_gles3.h10
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp1
-rw-r--r--drivers/gles3/shaders/scene.glsl2
-rw-r--r--drivers/gles3/storage/material_storage.cpp1
-rw-r--r--drivers/gles3/storage/mesh_storage.cpp6
-rw-r--r--drivers/gles3/storage/mesh_storage.h2
-rw-r--r--drivers/metal/rendering_device_driver_metal.mm3
-rw-r--r--editor/animation_track_editor.cpp13
-rw-r--r--editor/editor_paths.cpp16
-rw-r--r--editor/editor_settings.cpp22
-rw-r--r--editor/export/export_template_manager.cpp3
-rw-r--r--editor/multi_node_edit.cpp18
-rw-r--r--editor/plugins/editor_preview_plugins.cpp9
-rw-r--r--editor/plugins/font_config_plugin.cpp8
-rw-r--r--editor/project_manager/project_dialog.cpp15
-rw-r--r--modules/bcdec/image_decompress_bcdec.cpp35
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp15
-rw-r--r--modules/gdscript/gdscript_editor.cpp14
-rw-r--r--modules/gdscript/tests/scripts/.editorconfig2
-rw-r--r--modules/mono/editor/bindings_generator.cpp69
-rw-r--r--modules/mono/editor/bindings_generator.h3
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs68
-rw-r--r--modules/noise/doc_classes/FastNoiseLite.xml4
-rw-r--r--platform/windows/detect.py7
-rw-r--r--scene/2d/skeleton_2d.cpp44
-rw-r--r--scene/2d/skeleton_2d.h2
-rw-r--r--scene/3d/node_3d.cpp22
-rw-r--r--scene/3d/skeleton_3d.cpp82
-rw-r--r--scene/3d/skeleton_3d.h2
-rw-r--r--scene/resources/material.cpp9
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp7
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.h2
-rw-r--r--servers/rendering/shader_compiler.cpp4
-rw-r--r--servers/rendering/shader_language.cpp4
47 files changed, 513 insertions, 251 deletions
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 748d787b86..68bd4bc4ce 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -2,7 +2,7 @@
# Each line is a file pattern followed by one or more owners.
# Owners can be @users, @org/teams or emails
-# Buildsystem
+# Buildsystem (Before everything to be overwritten)
* @godotengine/buildsystem
@@ -17,10 +17,11 @@
# Doc
/doc/ @godotengine/documentation
-**/doc_classes/ @godotengine/documentation
# Drivers
+/drivers/ @godotengine/_systems
+
## Audio
/drivers/alsa/ @godotengine/audio
/drivers/alsamidi/ @godotengine/audio
@@ -34,7 +35,9 @@
## Rendering
/drivers/d3d12/ @godotengine/rendering
/drivers/dummy/ @godotengine/rendering
+/drivers/egl/ @godotengine/rendering
/drivers/gles3/ @godotengine/rendering
+/drivers/metal/ @godotengine/rendering
/drivers/spirv-reflect/ @godotengine/rendering
/drivers/vulkan/ @godotengine/rendering
@@ -47,18 +50,19 @@
# Editor
-/editor/*debugger* @godotengine/debugger
+/editor/ @godotengine/_editor
+/editor/**/*2d* @godotengine/2d-editor
+/editor/**/*3d* @godotengine/3d-editor
+/editor/**/*code* @godotengine/script-editor
+/editor/**/*debugger* @godotengine/debugger
+/editor/**/*dock* @godotengine/docks
+/editor/**/*script* @godotengine/script-editor
+/editor/**/*shader* @godotengine/shaders
+/editor/debugger/ @godotengine/debugger
/editor/gui/ @godotengine/usability @godotengine/gui-nodes
/editor/icons/ @godotengine/usability
/editor/import/ @godotengine/import
-/editor/plugins/*2d_*.* @godotengine/2d-editor
-/editor/plugins/*3d_*.* @godotengine/3d-editor
-/editor/plugins/script_*.* @godotengine/script-editor
-/editor/plugins/*shader*.* @godotengine/shaders
/editor/themes/ @godotengine/usability @godotengine/gui-nodes
-/editor/code_editor.* @godotengine/script-editor
-/editor/*dock*.* @godotengine/docks
-/editor/*shader*.* @godotengine/shaders
# Main
@@ -71,9 +75,16 @@
# Modules
+/modules/ @godotengine/_engine
+/modules/**/doc_classes/ @godotengine/_engine @godotengine/documentation
+/modules/**/editor/ @godotengine/_engine @godotengine/_editor
+/modules/**/icons/ @godotengine/_engine @godotengine/usability
+/modules/**/tests/ @godotengine/_engine @godotengine/tests
+
## Audio (+ video)
/modules/interactive_music/ @godotengine/audio
/modules/interactive_music/doc_classes/ @godotengine/audio @godotengine/documentation
+/modules/interactive_music/editor/ @godotengine/audio @godotengine/_editor
/modules/minimp3/ @godotengine/audio
/modules/minimp3/doc_classes/ @godotengine/audio @godotengine/documentation
/modules/ogg/ @godotengine/audio
@@ -93,8 +104,10 @@
/modules/etcpak/ @godotengine/import
/modules/fbx/ @godotengine/import
/modules/fbx/doc_classes/ @godotengine/import @godotengine/documentation
+/modules/fbx/editor/ @godotengine/import @godotengine/_editor
/modules/gltf/ @godotengine/import
/modules/gltf/doc_classes/ @godotengine/import @godotengine/documentation
+/modules/gltf/editor/ @godotengine/import @godotengine/_editor
/modules/gltf/tests/ @godotengine/import @godotengine/tests
/modules/hdr/ @godotengine/import
/modules/jpg/ @godotengine/import
@@ -112,12 +125,14 @@
/modules/mbedtls/tests/ @godotengine/network @godotengine/tests
/modules/multiplayer/ @godotengine/network
/modules/multiplayer/doc_classes/ @godotengine/network @godotengine/documentation
+/modules/multiplayer/editor/ @godotengine/network @godotengine/_editor
/modules/upnp/ @godotengine/network
/modules/upnp/doc_classes/ @godotengine/network @godotengine/documentation
/modules/webrtc/ @godotengine/network
/modules/webrtc/doc_classes/ @godotengine/network @godotengine/documentation
/modules/websocket/ @godotengine/network
/modules/websocket/doc_classes/ @godotengine/network @godotengine/documentation
+/modules/websocket/editor/ @godotengine/network @godotengine/_editor
## Physics
/modules/godot_physics_2d/ @godotengine/physics
@@ -134,12 +149,14 @@
## Scripting
/modules/gdscript/ @godotengine/gdscript
/modules/gdscript/doc_classes/ @godotengine/gdscript @godotengine/documentation
+/modules/gdscript/editor/ @godotengine/gdscript @godotengine/_editor
/modules/gdscript/icons/ @godotengine/gdscript @godotengine/usability
/modules/gdscript/tests/ @godotengine/gdscript @godotengine/tests
/modules/jsonrpc/ @godotengine/gdscript @godotengine/network
/modules/jsonrpc/tests @godotengine/gdscript @godotengine/network @godotengine/tests
/modules/mono/ @godotengine/dotnet
/modules/mono/doc_classes/ @godotengine/dotnet @godotengine/documentation
+/modules/mono/editor/ @godotengine/dotnet @godotengine/_editor
/modules/mono/icons/ @godotengine/dotnet @godotengine/usability
## Text
@@ -156,19 +173,24 @@
/modules/mobile_vr/doc_classes/ @godotengine/xr @godotengine/documentation
/modules/openxr/ @godotengine/xr
/modules/openxr/doc_classes/ @godotengine/xr @godotengine/documentation
+/modules/openxr/editor/ @godotengine/xr @godotengine/_editor
/modules/webxr/ @godotengine/xr
/modules/webxr/doc_classes/ @godotengine/xr @godotengine/documentation
## Misc
/modules/csg/ @godotengine/3d-nodes
/modules/csg/doc_classes/ @godotengine/3d-nodes @godotengine/documentation
+/modules/csg/editor/ @godotengine/3d-nodes @godotengine/_editor
/modules/csg/icons/ @godotengine/3d-nodes @godotengine/usability
-/modules/navigation/ @godotengine/navigation
/modules/gridmap/ @godotengine/3d-nodes
/modules/gridmap/doc_classes/ @godotengine/3d-nodes @godotengine/documentation
+/modules/gridmap/editor/ @godotengine/3d-nodes @godotengine/_editor
/modules/gridmap/icons/ @godotengine/3d-nodes @godotengine/usability
+/modules/navigation/ @godotengine/navigation
+/modules/navigation/editor/ @godotengine/navigation @godotengine/_editor
/modules/noise/ @godotengine/core
/modules/noise/doc_classes/ @godotengine/core @godotengine/documentation
+/modules/noise/editor/ @godotengine/core @godotengine/_editor
/modules/noise/icons/ @godotengine/core @godotengine/usability
/modules/noise/tests/ @godotengine/core @godotengine/tests
/modules/regex/ @godotengine/core
@@ -180,6 +202,7 @@
# Platform
+/platform/ @godotengine/_platforms
/platform/android/ @godotengine/android
/platform/android/doc_classes/ @godotengine/android @godotengine/documentation
/platform/ios/ @godotengine/ios
@@ -195,6 +218,7 @@
# Scene
+/scene/ @godotengine/_systems @godotengine/core
/scene/2d/ @godotengine/2d-nodes
/scene/2d/physics/ @godotengine/2d-nodes @godotengine/physics
/scene/3d/ @godotengine/3d-nodes
@@ -213,14 +237,16 @@
# Servers
-/servers/audio* @godotengine/audio
-/servers/camera* @godotengine/xr
-/servers/display_server.* @godotengine/_platforms
-/servers/navigation_server*.* @godotengine/navigation
-/servers/physics* @godotengine/physics
-/servers/rendering* @godotengine/rendering
-/servers/text_server.* @godotengine/gui-nodes
-/servers/xr* @godotengine/xr
+/servers/ @godotengine/_systems
+/servers/**/audio* @godotengine/audio
+/servers/**/camera* @godotengine/xr
+/servers/**/debugger* @godotengine/debugger
+/servers/**/display* @godotengine/_platforms
+/servers/**/navigation* @godotengine/navigation
+/servers/**/physics* @godotengine/physics
+/servers/**/rendering* @godotengine/rendering
+/servers/**/text* @godotengine/gui-nodes
+/servers/**/xr* @godotengine/xr
# Tests
diff --git a/.github/workflows/windows_builds.yml b/.github/workflows/windows_builds.yml
index 697b37f36f..f55827bd6f 100644
--- a/.github/workflows/windows_builds.yml
+++ b/.github/workflows/windows_builds.yml
@@ -30,7 +30,7 @@ jobs:
# Skip debug symbols, they're way too big with MSVC.
sconsflags: debug_symbols=no vsproj=yes vsproj_gen_only=no windows_subsystem=console
bin: ./bin/redot.windows.editor.x86_64.exe
- artifact: true
+ compiler: msvc
- name: Editor w/ Mono (target=editor)
cache-name: windows-editor-mono
@@ -42,7 +42,7 @@ jobs:
doc-test: true
proj-conv: true
api-compat: true
- artifact: true
+ compiler: msvc
- name: Editor w/ clang-cl (target=editor, tests=yes, use_llvm=yes)
cache-name: windows-editor-clang
@@ -50,6 +50,7 @@ jobs:
tests: true
sconsflags: debug_symbols=no windows_subsystem=console use_llvm=yes
bin: ./bin/redot.windows.editor.x86_64.llvm.exe
+ compiler: clang
- name: Template (target=template_release, tests=yes)
cache-name: windows-template
@@ -57,7 +58,16 @@ jobs:
tests: true
sconsflags: debug_symbols=no
bin: ./bin/redot.windows.template_release.x86_64.console.exe
- artifact: true
+ compiler: msvc
+
+ - name: Template w/ GCC (target=template_release, tests=yes, use_mingw=yes)
+ cache-name: windows-template-gcc
+ # MinGW takes MUCH longer to compile; save time by only targeting Template.
+ target: template_release
+ tests: true
+ sconsflags: debug_symbols=no use_mingw=yes
+ bin: ./bin/redot.windows.template_release.x86_64.console.exe
+ compiler: gcc
steps:
- name: Checkout
@@ -81,16 +91,21 @@ jobs:
uses: dsaltares/fetch-gh-release-asset@1.1.2
with:
repo: godotengine/godot-angle-static
- version: tags/chromium/6029
- file: Windows.6029-1.MSVC_17.x86_64.x86_32.zip
+ version: tags/chromium/6601.2
+ file: godot-angle-static-x86_64-${{ matrix.compiler == 'gcc' && 'gcc' || 'msvc' }}-release.zip
target: angle/angle.zip
- name: Extract pre-built ANGLE static libraries
run: Expand-Archive -Force angle/angle.zip ${{ github.workspace }}/
- name: Setup MSVC problem matcher
+ if: matrix.compiler == 'msvc'
uses: ammaraskar/msvc-problem-matcher@master
+ - name: Setup GCC problem matcher
+ if: matrix.compiler != 'msvc'
+ uses: ammaraskar/gcc-problem-matcher@master
+
- name: Compilation
uses: ./.github/actions/godot-build
with:
@@ -114,12 +129,12 @@ jobs:
continue-on-error: true
- name: Prepare artifact
- if: ${{ matrix.artifact }}
+ if: matrix.compiler == 'msvc'
run: |
Remove-Item bin/* -Include *.exp,*.lib,*.pdb -Force
- name: Upload artifact
- if: ${{ matrix.artifact }}
+ if: matrix.compiler == 'msvc'
uses: ./.github/actions/upload-artifact
with:
name: ${{ matrix.cache-name }}
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index 876f5ae515..26ec56c8b0 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -1169,22 +1169,16 @@ bool ProjectSettings::is_project_loaded() const {
}
bool ProjectSettings::_property_can_revert(const StringName &p_name) const {
- if (!props.has(p_name)) {
- return false;
- }
-
- return props[p_name].initial != props[p_name].variant;
+ return props.has(p_name);
}
bool ProjectSettings::_property_get_revert(const StringName &p_name, Variant &r_property) const {
- if (!props.has(p_name)) {
- return false;
+ const RBMap<StringName, ProjectSettings::VariantContainer>::Element *value = props.find(p_name);
+ if (value) {
+ r_property = value->value().initial.duplicate();
+ return true;
}
-
- // Duplicate so that if value is array or dictionary, changing the setting will not change the stored initial value.
- r_property = props[p_name].initial.duplicate();
-
- return true;
+ return false;
}
void ProjectSettings::set_setting(const String &p_setting, const Variant &p_value) {
diff --git a/core/math/geometry_2d.cpp b/core/math/geometry_2d.cpp
index 68e236df3d..2812ebbe51 100644
--- a/core/math/geometry_2d.cpp
+++ b/core/math/geometry_2d.cpp
@@ -37,7 +37,8 @@
#define STB_RECT_PACK_IMPLEMENTATION
#include "thirdparty/misc/stb_rect_pack.h"
-#define PRECISION 5 // Based on CMP_EPSILON.
+const int clipper_precision = 5; // Based on CMP_EPSILON.
+const double clipper_scale = Math::pow(10.0, clipper_precision);
Vector<Vector<Vector2>> Geometry2D::decompose_polygon_in_convex(const Vector<Point2> &polygon) {
Vector<Vector<Vector2>> decomp;
@@ -226,7 +227,7 @@ Vector<Vector<Point2>> Geometry2D::_polypaths_do_operation(PolyBooleanOperation
path_b[i] = PointD(p_polypath_b[i].x, p_polypath_b[i].y);
}
- ClipperD clp(PRECISION); // Scale points up internally to attain the desired precision.
+ ClipperD clp(clipper_precision); // Scale points up internally to attain the desired precision.
clp.PreserveCollinear(false); // Remove redundant vertices.
if (is_a_open) {
clp.AddOpenSubject({ path_a });
@@ -300,9 +301,10 @@ Vector<Vector<Point2>> Geometry2D::_polypath_offset(const Vector<Point2> &p_poly
}
// Inflate/deflate.
- PathsD paths = InflatePaths({ polypath }, p_delta, jt, et, 2.0, PRECISION, 0.0);
- // Here the miter_limit = 2.0 and arc_tolerance = 0.0 are Clipper2 defaults,
- // and the PRECISION is used to scale points up internally, to attain the desired precision.
+ PathsD paths = InflatePaths({ polypath }, p_delta, jt, et, 2.0, clipper_precision, 0.25 * clipper_scale);
+ // Here the points are scaled up internally and
+ // the arc_tolerance is scaled accordingly
+ // to attain the desired precision.
Vector<Vector<Point2>> polypaths;
for (PathsD::size_type i = 0; i < paths.size(); ++i) {
diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml
index de3295fbe0..1779408a4d 100644
--- a/doc/classes/Environment.xml
+++ b/doc/classes/Environment.xml
@@ -81,8 +81,9 @@
The background mode. See [enum BGMode] for possible values.
</member>
<member name="fog_aerial_perspective" type="float" setter="set_fog_aerial_perspective" getter="get_fog_aerial_perspective" default="0.0">
- If set above [code]0.0[/code] (exclusive), blends between the fog's color and the color of the background [Sky]. This has a small performance cost when set above [code]0.0[/code]. Must have [member background_mode] set to [constant BG_SKY].
+ If set above [code]0.0[/code] (exclusive), blends between the fog's color and the color of the background [Sky], as read from the radiance cubemap. This has a small performance cost when set above [code]0.0[/code]. Must have [member background_mode] set to [constant BG_SKY].
This is useful to simulate [url=https://en.wikipedia.org/wiki/Aerial_perspective]aerial perspective[/url] in large scenes with low density fog. However, it is not very useful for high-density fog, as the sky will shine through. When set to [code]1.0[/code], the fog color comes completely from the [Sky]. If set to [code]0.0[/code], aerial perspective is disabled.
+ Notice that this does not sample the [Sky] directly, but rather the radiance cubemap. The cubemap is sampled at a mipmap level depending on the depth of the rendered pixel; the farther away, the higher the resolution of the sampled mipmap. This results in the actual color being a blurred version of the sky, with more blur closer to the camera. The highest mipmap resolution is used at a depth of [member Camera3D.far].
</member>
<member name="fog_density" type="float" setter="set_fog_density" getter="get_fog_density" default="0.01">
The fog density to be used. This is demonstrated in different ways depending on the [member fog_mode] mode chosen:
diff --git a/doc/classes/PackedVector2Array.xml b/doc/classes/PackedVector2Array.xml
index da41812e0b..4d487b6dc2 100644
--- a/doc/classes/PackedVector2Array.xml
+++ b/doc/classes/PackedVector2Array.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
An array specifically designed to hold [Vector2]. Packs data tightly, so it saves memory for large array sizes.
- [b]Differences between packed arrays, typed arrays, and untyped arrays:[/b] Packed arrays are generally faster to iterate on and modify compared to a typed array of the same type (e.g. [PackedVector3Array] versus [code]Array[Vector2][/code]). Also, packed arrays consume less memory. As a downside, packed arrays are less flexible as they don't offer as many convenience methods such as [method Array.map]. Typed arrays are in turn faster to iterate on and modify than untyped arrays.
+ [b]Differences between packed arrays, typed arrays, and untyped arrays:[/b] Packed arrays are generally faster to iterate on and modify compared to a typed array of the same type (e.g. [PackedVector2Array] versus [code]Array[Vector2][/code]). Also, packed arrays consume less memory. As a downside, packed arrays are less flexible as they don't offer as many convenience methods such as [method Array.map]. Typed arrays are in turn faster to iterate on and modify than untyped arrays.
[b]Note:[/b] Packed arrays are always passed by reference. To get a copy of an array that can be modified independently of the original array, use [method duplicate]. This is [i]not[/i] the case for built-in properties and methods. The returned packed array of these are a copies, and changing it will [i]not[/i] affect the original value. To update a built-in property you need to modify the returned array, and then assign it to the property again.
</description>
<tutorials>
diff --git a/drivers/d3d12/SCsub b/drivers/d3d12/SCsub
index eeb899006d..1c9675e4ad 100644
--- a/drivers/d3d12/SCsub
+++ b/drivers/d3d12/SCsub
@@ -4,6 +4,8 @@ from misc.utility.scons_hints import *
import os
from pathlib import Path
+import methods
+
Import("env")
env_d3d12_rdd = env.Clone()
@@ -139,6 +141,10 @@ else:
extra_defines += [
"HAVE_STRUCT_TIMESPEC",
]
+ if methods.using_gcc(env) and methods.get_compiler_version(env)["major"] < 13:
+ # `region` & `endregion` not recognized as valid pragmas.
+ env_d3d12_rdd.Append(CCFLAGS=["-Wno-unknown-pragmas"])
+ env.Append(CCFLAGS=["-Wno-unknown-pragmas"])
# This is needed since rendering_device_d3d12.cpp needs to include some Mesa internals.
env_d3d12_rdd.Prepend(CPPPATH=mesa_private_inc_paths)
diff --git a/drivers/d3d12/dxil_hash.cpp b/drivers/d3d12/dxil_hash.cpp
index d7a6f8e992..51c8ee71fa 100644
--- a/drivers/d3d12/dxil_hash.cpp
+++ b/drivers/d3d12/dxil_hash.cpp
@@ -98,7 +98,7 @@ void compute_dxil_hash(const BYTE *pData, UINT byteCount, BYTE *pOutHash) {
UINT NextEndState = bTwoRowsPadding ? N - 2 : N - 1;
const BYTE *pCurrData = pData;
for (UINT i = 0; i < N; i++, offset += 64, pCurrData += 64) {
- UINT x[16];
+ UINT x[16] = {};
const UINT *pX;
if (i == NextEndState) {
if (!bTwoRowsPadding && i == N - 1) {
diff --git a/drivers/d3d12/rendering_device_driver_d3d12.cpp b/drivers/d3d12/rendering_device_driver_d3d12.cpp
index 269765f3fc..8f4079c2d9 100644
--- a/drivers/d3d12/rendering_device_driver_d3d12.cpp
+++ b/drivers/d3d12/rendering_device_driver_d3d12.cpp
@@ -1350,7 +1350,14 @@ RDD::TextureID RenderingDeviceDriverD3D12::texture_create(const TextureFormat &p
}
tex_info->states_ptr = &tex_info->owner_info.states;
tex_info->format = p_format.format;
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif
tex_info->desc = *(CD3DX12_RESOURCE_DESC *)&resource_desc;
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
tex_info->base_layer = 0;
tex_info->layers = resource_desc.ArraySize();
tex_info->base_mip = 0;
@@ -6580,8 +6587,6 @@ static Error create_command_signature(ID3D12Device *device, D3D12_INDIRECT_ARGUM
Error RenderingDeviceDriverD3D12::_initialize_frames(uint32_t p_frame_count) {
Error err;
- D3D12MA::ALLOCATION_DESC allocation_desc = {};
- allocation_desc.HeapType = D3D12_HEAP_TYPE_DEFAULT;
//CD3DX12_RESOURCE_DESC resource_desc = CD3DX12_RESOURCE_DESC::Buffer(D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT);
uint32_t resource_descriptors_per_frame = GLOBAL_GET("rendering/rendering_device/d3d12/max_resource_descriptors_per_frame");
diff --git a/drivers/egl/egl_manager.cpp b/drivers/egl/egl_manager.cpp
index f9f420f0a8..7dd01e6d55 100644
--- a/drivers/egl/egl_manager.cpp
+++ b/drivers/egl/egl_manager.cpp
@@ -32,6 +32,8 @@
#include "egl_manager.h"
+#include "drivers/gles3/rasterizer_gles3.h"
+
#ifdef EGL_ENABLED
#if defined(EGL_STATIC)
@@ -53,6 +55,16 @@ extern "C" EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT(EGLenum platfo
#define GLAD_EGL_EXT_platform_base 0
#endif
+#ifdef WINDOWS_ENABLED
+// Unofficial ANGLE extension: EGL_ANGLE_surface_orientation
+#ifndef EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE
+#define EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE 0x33A7
+#define EGL_SURFACE_ORIENTATION_ANGLE 0x33A8
+#define EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE 0x0001
+#define EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE 0x0002
+#endif
+#endif
+
// Creates and caches a GLDisplay. Returns -1 on error.
int EGLManager::_get_gldisplay_id(void *p_display) {
// Look for a cached GLDisplay.
@@ -117,6 +129,18 @@ int EGLManager::_get_gldisplay_id(void *p_display) {
}
#endif
+#ifdef WINDOWS_ENABLED
+ String client_extensions_string = eglQueryString(new_gldisplay.egl_display, EGL_EXTENSIONS);
+ if (eglGetError() == EGL_SUCCESS) {
+ Vector<String> egl_extensions = client_extensions_string.split(" ");
+
+ if (egl_extensions.has("EGL_ANGLE_surface_orientation")) {
+ new_gldisplay.has_EGL_ANGLE_surface_orientation = true;
+ print_verbose("EGL: EGL_ANGLE_surface_orientation is supported.");
+ }
+ }
+#endif
+
displays.push_back(new_gldisplay);
// Return the new GLDisplay's ID.
@@ -239,8 +263,29 @@ Error EGLManager::window_create(DisplayServer::WindowID p_window_id, void *p_dis
GLWindow &glwindow = windows[p_window_id];
glwindow.gldisplay_id = gldisplay_id;
+ Vector<EGLAttrib> egl_attribs;
+
+#ifdef WINDOWS_ENABLED
+ if (gldisplay.has_EGL_ANGLE_surface_orientation) {
+ EGLint optimal_orientation;
+ if (eglGetConfigAttrib(gldisplay.egl_display, gldisplay.egl_config, EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE, &optimal_orientation)) {
+ // We only need to support inverting Y for optimizing ANGLE on D3D11.
+ if (optimal_orientation & EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE && !(optimal_orientation & EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE)) {
+ egl_attribs.push_back(EGL_SURFACE_ORIENTATION_ANGLE);
+ egl_attribs.push_back(EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE);
+ }
+ } else {
+ ERR_PRINT(vformat("Failed to get EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE, error: 0x%08X", eglGetError()));
+ }
+ }
+
+ if (!egl_attribs.is_empty()) {
+ egl_attribs.push_back(EGL_NONE);
+ }
+#endif
+
if (GLAD_EGL_VERSION_1_5) {
- glwindow.egl_surface = eglCreatePlatformWindowSurface(gldisplay.egl_display, gldisplay.egl_config, p_native_window, nullptr);
+ glwindow.egl_surface = eglCreatePlatformWindowSurface(gldisplay.egl_display, gldisplay.egl_config, p_native_window, egl_attribs.ptr());
} else {
EGLNativeWindowType *native_window_type = (EGLNativeWindowType *)p_native_window;
glwindow.egl_surface = eglCreateWindowSurface(gldisplay.egl_display, gldisplay.egl_config, *native_window_type, nullptr);
@@ -252,6 +297,20 @@ Error EGLManager::window_create(DisplayServer::WindowID p_window_id, void *p_dis
glwindow.initialized = true;
+#ifdef WINDOWS_ENABLED
+ if (gldisplay.has_EGL_ANGLE_surface_orientation) {
+ EGLint orientation;
+ if (eglQuerySurface(gldisplay.egl_display, glwindow.egl_surface, EGL_SURFACE_ORIENTATION_ANGLE, &orientation)) {
+ if (orientation & EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE && !(orientation & EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE)) {
+ glwindow.flipped_y = true;
+ print_verbose("EGL: Using optimal surface orientation: Invert Y");
+ }
+ } else {
+ ERR_PRINT(vformat("Failed to get EGL_SURFACE_ORIENTATION_ANGLE, error: 0x%08X", eglGetError()));
+ }
+ }
+#endif
+
window_make_current(p_window_id);
return OK;
@@ -318,6 +377,10 @@ void EGLManager::window_make_current(DisplayServer::WindowID p_window_id) {
GLDisplay &current_display = displays[current_window->gldisplay_id];
eglMakeCurrent(current_display.egl_display, current_window->egl_surface, current_window->egl_surface, current_display.egl_context);
+
+#ifdef WINDOWS_ENABLED
+ RasterizerGLES3::set_screen_flipped_y(glwindow.flipped_y);
+#endif
}
void EGLManager::set_use_vsync(bool p_use) {
diff --git a/drivers/egl/egl_manager.h b/drivers/egl/egl_manager.h
index 3cf0563843..386fb1daab 100644
--- a/drivers/egl/egl_manager.h
+++ b/drivers/egl/egl_manager.h
@@ -55,11 +55,18 @@ private:
EGLDisplay egl_display = EGL_NO_DISPLAY;
EGLContext egl_context = EGL_NO_CONTEXT;
EGLConfig egl_config = nullptr;
+
+#ifdef WINDOWS_ENABLED
+ bool has_EGL_ANGLE_surface_orientation = false;
+#endif
};
// EGL specific window data.
struct GLWindow {
bool initialized = false;
+#ifdef WINDOWS_ENABLED
+ bool flipped_y = false;
+#endif
// An handle to the GLDisplay associated with this window.
int gldisplay_id = -1;
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index 24ca3419fc..9cd9b7b18c 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -88,6 +88,10 @@
#define strcpy strcpy_s
#endif
+#ifdef WINDOWS_ENABLED
+bool RasterizerGLES3::screen_flipped_y = false;
+#endif
+
bool RasterizerGLES3::gles_over_gl = true;
void RasterizerGLES3::begin_frame(double frame_step) {
@@ -391,6 +395,12 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display
flip_y = false;
}
+#ifdef WINDOWS_ENABLED
+ if (screen_flipped_y) {
+ flip_y = !flip_y;
+ }
+#endif
+
GLuint read_fbo = 0;
glGenFramebuffers(1, &read_fbo);
glBindFramebuffer(GL_READ_FRAMEBUFFER, read_fbo);
@@ -487,9 +497,14 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c
screenrect.position += ((Size2(win_size.width, win_size.height) - screenrect.size) / 2.0).floor();
}
- // Flip Y.
- screenrect.position.y = win_size.y - screenrect.position.y;
- screenrect.size.y = -screenrect.size.y;
+#ifdef WINDOWS_ENABLED
+ if (!screen_flipped_y)
+#endif
+ {
+ // Flip Y.
+ screenrect.position.y = win_size.y - screenrect.position.y;
+ screenrect.size.y = -screenrect.size.y;
+ }
// Normalize texture coordinates to window size.
screenrect.position /= win_size;
diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h
index 8fa9d5b23d..feb70c31da 100644
--- a/drivers/gles3/rasterizer_gles3.h
+++ b/drivers/gles3/rasterizer_gles3.h
@@ -60,6 +60,10 @@ private:
double time_total = 0.0;
bool flip_xy_workaround = false;
+#ifdef WINDOWS_ENABLED
+ static bool screen_flipped_y;
+#endif
+
static bool gles_over_gl;
protected:
@@ -120,6 +124,12 @@ public:
low_end = true;
}
+#ifdef WINDOWS_ENABLED
+ static void set_screen_flipped_y(bool p_flipped) {
+ screen_flipped_y = p_flipped;
+ }
+#endif
+
_ALWAYS_INLINE_ uint64_t get_frame_number() const { return frame; }
_ALWAYS_INLINE_ double get_frame_delta_time() const { return delta; }
_ALWAYS_INLINE_ double get_total_time() const { return time_total; }
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 2d62833c75..3af9ecfeca 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -3445,6 +3445,7 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
}
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::MODEL_FLAGS, inst->flags_cache, shader->version, instance_variant, spec_constants);
+ material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::INSTANCE_OFFSET, uint32_t(inst->shader_uniforms_offset), shader->version, instance_variant, spec_constants);
if (p_pass_mode == PASS_MODE_MATERIAL) {
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::UV_OFFSET, p_params->uv_offset, shader->version, instance_variant, spec_constants);
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 9ce10a4488..fcfbeddb9e 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -430,6 +430,7 @@ uniform highp mat4 world_transform;
uniform highp vec3 compressed_aabb_position;
uniform highp vec3 compressed_aabb_size;
uniform highp vec4 uv_scale;
+uniform highp uint instance_offset;
uniform highp uint model_flags;
@@ -1201,6 +1202,7 @@ ivec2 multiview_uv(ivec2 uv) {
uniform highp mat4 world_transform;
uniform mediump float opaque_prepass_threshold;
uniform highp uint model_flags;
+uniform highp uint instance_offset;
#if defined(RENDER_MATERIAL)
layout(location = 0) out vec4 albedo_output_buffer;
diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp
index 54d1feb4f1..89ac1fa8be 100644
--- a/drivers/gles3/storage/material_storage.cpp
+++ b/drivers/gles3/storage/material_storage.cpp
@@ -1381,6 +1381,7 @@ MaterialStorage::MaterialStorage() {
actions.check_multiview_samplers = RasterizerGLES3::get_singleton()->is_xr_enabled();
actions.global_buffer_array_variable = "global_shader_uniforms";
+ actions.instance_uniform_index_variable = "instance_offset";
shaders.compiler_scene.initialize(actions);
}
diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp
index f8f9550484..9699020a71 100644
--- a/drivers/gles3/storage/mesh_storage.cpp
+++ b/drivers/gles3/storage/mesh_storage.cpp
@@ -2203,7 +2203,7 @@ void MeshStorage::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_
glBindTexture(GL_TEXTURE_2D, 0);
GLES3::Utilities::get_singleton()->texture_allocated_data(skeleton->transforms_texture, skeleton->data.size() * sizeof(float), "Skeleton transforms texture");
- memset(skeleton->data.ptrw(), 0, skeleton->data.size() * sizeof(float));
+ memset(skeleton->data.ptr(), 0, skeleton->data.size() * sizeof(float));
_skeleton_make_dirty(skeleton);
}
@@ -2234,7 +2234,7 @@ void MeshStorage::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const
ERR_FAIL_INDEX(p_bone, skeleton->size);
ERR_FAIL_COND(skeleton->use_2d);
- float *dataptr = skeleton->data.ptrw() + p_bone * 12;
+ float *dataptr = skeleton->data.ptr() + p_bone * 12;
dataptr[0] = p_transform.basis.rows[0][0];
dataptr[1] = p_transform.basis.rows[0][1];
@@ -2286,7 +2286,7 @@ void MeshStorage::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, con
ERR_FAIL_INDEX(p_bone, skeleton->size);
ERR_FAIL_COND(!skeleton->use_2d);
- float *dataptr = skeleton->data.ptrw() + p_bone * 8;
+ float *dataptr = skeleton->data.ptr() + p_bone * 8;
dataptr[0] = p_transform.columns[0][0];
dataptr[1] = p_transform.columns[1][0];
diff --git a/drivers/gles3/storage/mesh_storage.h b/drivers/gles3/storage/mesh_storage.h
index 7a41eac816..2f1617a884 100644
--- a/drivers/gles3/storage/mesh_storage.h
+++ b/drivers/gles3/storage/mesh_storage.h
@@ -216,7 +216,7 @@ struct Skeleton {
bool use_2d = false;
int size = 0;
int height = 0;
- Vector<float> data;
+ LocalVector<float> data;
bool dirty = false;
Skeleton *dirty_list = nullptr;
diff --git a/drivers/metal/rendering_device_driver_metal.mm b/drivers/metal/rendering_device_driver_metal.mm
index d73e6e767a..090f700134 100644
--- a/drivers/metal/rendering_device_driver_metal.mm
+++ b/drivers/metal/rendering_device_driver_metal.mm
@@ -3673,7 +3673,8 @@ void RenderingDeviceDriverMetal::set_object_name(ObjectType p_type, ID p_driver_
uint64_t RenderingDeviceDriverMetal::get_resource_native_handle(DriverResource p_type, ID p_driver_id) {
switch (p_type) {
case DRIVER_RESOURCE_LOGICAL_DEVICE: {
- return 0;
+ uintptr_t devicePtr = (uintptr_t)(__bridge void *)device;
+ return (uint64_t)devicePtr;
}
case DRIVER_RESOURCE_PHYSICAL_DEVICE: {
return 0;
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 2dfd9191c6..622810eab3 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -4281,7 +4281,18 @@ void AnimationTrackEditor::insert_node_value_key(Node *p_node, const String &p_p
// Let's build a node path.
String path = root->get_path_to(p_node, true);
- Variant value = p_node->get(p_property);
+ // Get the value from the subpath.
+ Variant value = p_node;
+ Vector<String> property_path = p_property.split(":");
+ for (const String &E : property_path) {
+ if (value.get_type() == Variant::OBJECT) {
+ Object *obj = value;
+ value = obj->get(E);
+ } else {
+ value = Variant();
+ break;
+ }
+ }
if (Object::cast_to<AnimationPlayer>(p_node) && p_property == "current_animation") {
if (p_node == AnimationPlayerEditor::get_singleton()->get_player()) {
diff --git a/editor/editor_paths.cpp b/editor/editor_paths.cpp
index 372114e44d..b3ca9039be 100644
--- a/editor/editor_paths.cpp
+++ b/editor/editor_paths.cpp
@@ -259,22 +259,6 @@ EditorPaths::EditorPaths() {
}
}
- // Check that `.editorconfig` file exists.
- String project_editorconfig_path = "res://.editorconfig";
- if (!FileAccess::exists(project_editorconfig_path)) {
- Ref<FileAccess> f = FileAccess::open(project_editorconfig_path, FileAccess::WRITE);
- if (f.is_valid()) {
- f->store_line("root = true");
- f->store_line("");
- f->store_line("[*]");
- f->store_line("charset = utf-8");
- f->close();
- } else {
- ERR_PRINT("Failed to create file " + project_editorconfig_path.quote() + ".");
- }
- FileAccess::set_hidden_attribute(project_editorconfig_path, true);
- }
-
Engine::get_singleton()->set_shader_cache_path(project_data_dir);
// Editor metadata dir.
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index acd7c90a3f..3bfd66a821 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -1426,24 +1426,20 @@ Variant _EDITOR_GET(const String &p_setting) {
}
bool EditorSettings::_property_can_revert(const StringName &p_name) const {
- if (!props.has(p_name)) {
- return false;
- }
-
- if (!props[p_name].has_default_value) {
- return false;
+ const VariantContainer *property = props.getptr(p_name);
+ if (property) {
+ return property->has_default_value;
}
-
- return props[p_name].initial != props[p_name].variant;
+ return false;
}
bool EditorSettings::_property_get_revert(const StringName &p_name, Variant &r_property) const {
- if (!props.has(p_name) || !props[p_name].has_default_value) {
- return false;
+ const VariantContainer *value = props.getptr(p_name);
+ if (value && value->has_default_value) {
+ r_property = value->initial;
+ return true;
}
-
- r_property = props[p_name].initial;
- return true;
+ return false;
}
void EditorSettings::add_property_hint(const PropertyInfo &p_hint) {
diff --git a/editor/export/export_template_manager.cpp b/editor/export/export_template_manager.cpp
index dc966c9018..2430c6fc80 100644
--- a/editor/export/export_template_manager.cpp
+++ b/editor/export/export_template_manager.cpp
@@ -36,6 +36,7 @@
#include "core/io/json.h"
#include "core/io/zip_io.h"
#include "core/version.h"
+#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
#include "editor/editor_settings.h"
@@ -878,7 +879,7 @@ Error ExportTemplateManager::install_android_template_from_file(const String &p_
ProgressDialog::get_singleton()->end_task("uncompress_src");
unzClose(pkg);
-
+ EditorFileSystem::get_singleton()->scan_changes();
return OK;
}
diff --git a/editor/multi_node_edit.cpp b/editor/multi_node_edit.cpp
index fd5b575941..55ac861488 100644
--- a/editor/multi_node_edit.cpp
+++ b/editor/multi_node_edit.cpp
@@ -188,25 +188,9 @@ bool MultiNodeEdit::_property_can_revert(const StringName &p_name) const {
}
if (ClassDB::has_property(get_edited_class_name(), p_name)) {
- StringName class_name;
for (const NodePath &E : nodes) {
Node *node = es->get_node_or_null(E);
- if (!node) {
- continue;
- }
-
- class_name = node->get_class_name();
- }
-
- Variant default_value = ClassDB::class_get_default_property_value(class_name, p_name);
- for (const NodePath &E : nodes) {
- Node *node = es->get_node_or_null(E);
- if (!node) {
- continue;
- }
-
- if (node->get(p_name) != default_value) {
- // A node that doesn't have the default value has been found, so show the revert button.
+ if (node) {
return true;
}
}
diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp
index de3dc2d40a..608a0cdfb1 100644
--- a/editor/plugins/editor_preview_plugins.cpp
+++ b/editor/plugins/editor_preview_plugins.cpp
@@ -114,9 +114,13 @@ Ref<Texture2D> EditorTexturePreviewPlugin::generate(const Ref<Resource> &p_from,
return Ref<Texture2D>();
}
- const int mid_depth = (tex_3d->get_depth() - 1) / 2;
-
Vector<Ref<Image>> data = tex_3d->get_data();
+ if (data.size() != tex_3d->get_depth()) {
+ return Ref<Texture2D>();
+ }
+
+ // Use the middle slice for the thumbnail.
+ const int mid_depth = (tex_3d->get_depth() - 1) / 2;
if (!data.is_empty() && data[mid_depth].is_valid()) {
img = data[mid_depth]->duplicate();
}
@@ -126,6 +130,7 @@ Ref<Texture2D> EditorTexturePreviewPlugin::generate(const Ref<Resource> &p_from,
return Ref<Texture2D>();
}
+ // Use the middle slice for the thumbnail.
const int mid_layer = (tex_lyr->get_layers() - 1) / 2;
Ref<Image> data = tex_lyr->get_layer_data(mid_layer);
diff --git a/editor/plugins/font_config_plugin.cpp b/editor/plugins/font_config_plugin.cpp
index 66cc183c82..e78ae89293 100644
--- a/editor/plugins/font_config_plugin.cpp
+++ b/editor/plugins/font_config_plugin.cpp
@@ -123,13 +123,8 @@ bool EditorPropertyFontOTObject::_property_can_revert(const StringName &p_name)
if (name.begins_with("keys")) {
int key = name.get_slicec('/', 1).to_int();
- if (defaults_dict.has(key) && dict.has(key)) {
- int value = dict[key];
- Vector3i range = defaults_dict[key];
- return range.z != value;
- }
+ return defaults_dict.has(key) && dict.has(key);
}
-
return false;
}
@@ -144,7 +139,6 @@ bool EditorPropertyFontOTObject::_property_get_revert(const StringName &p_name,
return true;
}
}
-
return false;
}
diff --git a/editor/project_manager/project_dialog.cpp b/editor/project_manager/project_dialog.cpp
index 3a288f1c07..3aa58803a2 100644
--- a/editor/project_manager/project_dialog.cpp
+++ b/editor/project_manager/project_dialog.cpp
@@ -554,6 +554,21 @@ void ProjectDialog::ok_pressed() {
fa_icon->store_string(get_default_project_icon());
EditorVCSInterface::create_vcs_metadata_files(EditorVCSInterface::VCSMetadata(vcs_metadata_selection->get_selected()), path);
+
+ // Ensures external editors and IDEs use UTF-8 encoding.
+ const String editor_config_path = path.path_join(".editorconfig");
+ Ref<FileAccess> f = FileAccess::open(editor_config_path, FileAccess::WRITE);
+ if (f.is_null()) {
+ // .editorconfig isn't so critical.
+ ERR_PRINT("Couldn't create .editorconfig in project path.");
+ } else {
+ f->store_line("root = true");
+ f->store_line("");
+ f->store_line("[*]");
+ f->store_line("charset = utf-8");
+ f->close();
+ FileAccess::set_hidden_attribute(editor_config_path, true);
+ }
}
// Two cases for importing a ZIP.
diff --git a/modules/bcdec/image_decompress_bcdec.cpp b/modules/bcdec/image_decompress_bcdec.cpp
index d7cf6d7e4f..8f2a6150f2 100644
--- a/modules/bcdec/image_decompress_bcdec.cpp
+++ b/modules/bcdec/image_decompress_bcdec.cpp
@@ -94,8 +94,20 @@ static void decompress_image(BCdecFormat format, const void *src, void *dst, con
void image_decompress_bcdec(Image *p_image) {
uint64_t start_time = OS::get_singleton()->get_ticks_msec();
- int w = p_image->get_width();
- int h = p_image->get_height();
+ int width = p_image->get_width();
+ int height = p_image->get_height();
+
+ // Compressed images' dimensions should be padded to the upper multiple of 4.
+ // If they aren't, they need to be realigned (the actual data is correctly padded though).
+ if (width % 4 != 0 || height % 4 != 0) {
+ int new_width = width + (4 - (width % 4));
+ int new_height = height + (4 - (height % 4));
+
+ print_verbose(vformat("Compressed image's dimensions are not multiples of 4 (%dx%d), aligning to (%dx%d)", width, height, new_width, new_height));
+
+ width = new_width;
+ height = new_height;
+ }
Image::Format source_format = p_image->get_format();
Image::Format target_format = Image::FORMAT_MAX;
@@ -150,30 +162,27 @@ void image_decompress_bcdec(Image *p_image) {
}
int mm_count = p_image->get_mipmap_count();
- int64_t target_size = Image::get_image_data_size(w, h, target_format, p_image->has_mipmaps());
+ int64_t target_size = Image::get_image_data_size(width, height, target_format, p_image->has_mipmaps());
+ // Decompressed data.
Vector<uint8_t> data;
data.resize(target_size);
+ uint8_t *wb = data.ptrw();
+ // Source data.
const uint8_t *rb = p_image->get_data().ptr();
- uint8_t *wb = data.ptrw();
// Decompress mipmaps.
for (int i = 0; i <= mm_count; i++) {
- int64_t src_ofs = 0, mipmap_size = 0;
int mipmap_w = 0, mipmap_h = 0;
- p_image->get_mipmap_offset_size_and_dimensions(i, src_ofs, mipmap_size, mipmap_w, mipmap_h);
-
- int64_t dst_ofs = Image::get_image_mipmap_offset(p_image->get_width(), p_image->get_height(), target_format, i);
+ int64_t src_ofs = Image::get_image_mipmap_offset_and_dimensions(width, height, source_format, i, mipmap_w, mipmap_h);
+ int64_t dst_ofs = Image::get_image_mipmap_offset(width, height, target_format, i);
decompress_image(bcdec_format, rb + src_ofs, wb + dst_ofs, mipmap_w, mipmap_h);
-
- w >>= 1;
- h >>= 1;
}
- p_image->set_data(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data);
+ p_image->set_data(width, height, p_image->has_mipmaps(), target_format, data);
- // Swap channels if necessary.
+ // Swap channels if the format is using a channel swizzle.
if (source_format == Image::FORMAT_DXT5_RA_AS_RG) {
p_image->convert_ra_rgba8_to_rg();
}
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index b9646dee71..cd950662fd 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -150,6 +150,15 @@ static GDScriptParser::DataType make_enum_type(const StringName &p_enum_name, co
return type;
}
+static GDScriptParser::DataType make_class_enum_type(const StringName &p_enum_name, GDScriptParser::ClassNode *p_class, const String &p_script_path, bool p_meta = true) {
+ GDScriptParser::DataType type = make_enum_type(p_enum_name, p_class->fqcn, p_meta);
+
+ type.class_type = p_class;
+ type.script_path = p_script_path;
+
+ return type;
+}
+
static GDScriptParser::DataType make_native_enum_type(const StringName &p_enum_name, const StringName &p_native_class, bool p_meta = true) {
// Find out which base class declared the enum, so the name is always the same even when coming from other contexts.
StringName native_base = p_native_class;
@@ -1103,7 +1112,7 @@ void GDScriptAnalyzer::resolve_class_member(GDScriptParser::ClassNode *p_class,
check_class_member_name_conflict(p_class, member.m_enum->identifier->name, member.m_enum);
member.m_enum->set_datatype(resolving_datatype);
- GDScriptParser::DataType enum_type = make_enum_type(member.m_enum->identifier->name, p_class->fqcn, true);
+ GDScriptParser::DataType enum_type = make_class_enum_type(member.m_enum->identifier->name, p_class, parser->script_path, true);
const GDScriptParser::EnumNode *prev_enum = current_enum;
current_enum = member.m_enum;
@@ -1196,7 +1205,7 @@ void GDScriptAnalyzer::resolve_class_member(GDScriptParser::ClassNode *p_class,
// Also update the original references.
member.enum_value.parent_enum->values.set(member.enum_value.index, member.enum_value);
- member.enum_value.identifier->set_datatype(make_enum_type(UNNAMED_ENUM, p_class->fqcn, false));
+ member.enum_value.identifier->set_datatype(make_class_enum_type(UNNAMED_ENUM, p_class, parser->script_path, false));
} break;
case GDScriptParser::ClassNode::Member::CLASS:
check_class_member_name_conflict(p_class, member.m_class->identifier->name, member.m_class);
@@ -4251,7 +4260,7 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
const GDScriptParser::EnumNode::Value &element = current_enum->values[i];
if (element.identifier->name == p_identifier->name) {
StringName enum_name = current_enum->identifier ? current_enum->identifier->name : UNNAMED_ENUM;
- GDScriptParser::DataType type = make_enum_type(enum_name, parser->current_class->fqcn, false);
+ GDScriptParser::DataType type = make_class_enum_type(enum_name, parser->current_class, parser->script_path, false);
if (element.parent_enum->identifier) {
type.enum_type = element.parent_enum->identifier->name;
}
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index 940a138637..b82fedf180 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -3784,7 +3784,19 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co
}
} break;
case GDScriptParser::DataType::ENUM: {
- if (base_type.enum_values.has(p_symbol)) {
+ if (base_type.class_type && base_type.class_type->has_member(base_type.enum_type)) {
+ GDScriptParser::EnumNode *base_enum = base_type.class_type->get_member(base_type.enum_type).m_enum;
+ for (const GDScriptParser::EnumNode::Value &value : base_enum->values) {
+ if (value.identifier && value.identifier->name == p_symbol) {
+ r_result.type = ScriptLanguage::LOOKUP_RESULT_SCRIPT_LOCATION;
+ r_result.class_path = base_type.script_path;
+ r_result.location = value.line;
+ Error err = OK;
+ r_result.script = GDScriptCache::get_shallow_script(r_result.class_path, err);
+ return err;
+ }
+ }
+ } else if (base_type.enum_values.has(p_symbol)) {
r_result.type = ScriptLanguage::LOOKUP_RESULT_CLASS_CONSTANT;
r_result.class_name = String(base_type.native_type).get_slicec('.', 0);
r_result.class_member = p_symbol;
diff --git a/modules/gdscript/tests/scripts/.editorconfig b/modules/gdscript/tests/scripts/.editorconfig
index da1efefe3c..34fff8d1de 100644
--- a/modules/gdscript/tests/scripts/.editorconfig
+++ b/modules/gdscript/tests/scripts/.editorconfig
@@ -1,5 +1,3 @@
-# This file is required to workaround `.editorconfig` autogeneration (see #96845).
-
# Some tests handle invalid syntax deliberately; exclude relevant attributes.
[parser/features/mixed_indentation_on_blank_lines.gd]
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index dae61af07d..d4af45da81 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -2350,9 +2350,17 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
int method_bind_count = 0;
for (const MethodInterface &imethod : itype.methods) {
- Error method_err = _generate_cs_method(itype, imethod, method_bind_count, output);
+ Error method_err = _generate_cs_method(itype, imethod, method_bind_count, output, false);
ERR_FAIL_COND_V_MSG(method_err != OK, method_err,
"Failed to generate method '" + imethod.name + "' for class '" + itype.name + "'.");
+ if (imethod.is_internal) {
+ // No need to generate span overloads for internal methods.
+ continue;
+ }
+
+ method_err = _generate_cs_method(itype, imethod, method_bind_count, output, true);
+ ERR_FAIL_COND_V_MSG(method_err != OK, method_err,
+ "Failed to generate span overload method '" + imethod.name + "' for class '" + itype.name + "'.");
}
// Signals
@@ -2778,7 +2786,7 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
return OK;
}
-Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output) {
+Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output, bool p_use_span) {
const TypeInterface *return_type = _get_type_or_singleton_or_null(p_imethod.return_type);
ERR_FAIL_NULL_V_MSG(return_type, ERR_BUG, "Return type '" + p_imethod.return_type.cname + "' was not found.");
@@ -2791,6 +2799,35 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
"' from the editor API. Core API cannot have dependencies on the editor API.");
}
+ if (p_imethod.is_virtual && p_use_span) {
+ return OK;
+ }
+
+ bool has_span_argument = false;
+
+ if (p_use_span) {
+ if (p_imethod.is_vararg) {
+ has_span_argument = true;
+ } else {
+ for (const ArgumentInterface &iarg : p_imethod.arguments) {
+ const TypeInterface *arg_type = _get_type_or_singleton_or_null(iarg.type);
+ ERR_FAIL_NULL_V_MSG(arg_type, ERR_BUG, "Argument type '" + iarg.type.cname + "' was not found.");
+
+ if (arg_type->is_span_compatible) {
+ has_span_argument = true;
+ break;
+ }
+ }
+ }
+
+ if (has_span_argument) {
+ // Span overloads use the same method bind as the array overloads.
+ // Since both overloads are generated one after the other, we can decrease the count here
+ // to ensure the span overload uses the same method bind.
+ p_method_bind_count--;
+ }
+ }
+
String method_bind_field = CS_STATIC_FIELD_METHOD_BIND_PREFIX + itos(p_method_bind_count);
String arguments_sig;
@@ -2837,6 +2874,8 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
String arg_cs_type = arg_type->cs_type + _get_generic_type_parameters(*arg_type, iarg.type.generic_type_parameters);
+ bool use_span_for_arg = p_use_span && arg_type->is_span_compatible;
+
// Add the current arguments to the signature
// If the argument has a default value which is not a constant, we will make it Nullable
{
@@ -2848,7 +2887,11 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
arguments_sig += "Nullable<";
}
- arguments_sig += arg_cs_type;
+ if (use_span_for_arg) {
+ arguments_sig += arg_type->c_type_in;
+ } else {
+ arguments_sig += arg_cs_type;
+ }
if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL) {
arguments_sig += "> ";
@@ -2858,7 +2901,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
arguments_sig += iarg.name;
- if (!p_imethod.is_compat && iarg.default_argument.size()) {
+ if (!p_use_span && !p_imethod.is_compat && iarg.default_argument.size()) {
if (iarg.def_param_mode != ArgumentInterface::CONSTANT) {
arguments_sig += " = null";
} else {
@@ -2869,7 +2912,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
icall_params += ", ";
- if (iarg.default_argument.size() && iarg.def_param_mode != ArgumentInterface::CONSTANT) {
+ if (iarg.default_argument.size() && iarg.def_param_mode != ArgumentInterface::CONSTANT && !use_span_for_arg) {
// The default value of an argument must be constant. Otherwise we make it Nullable and do the following:
// Type arg_in = arg.HasValue ? arg.Value : <non-const default value>;
String arg_or_defval_local = iarg.name;
@@ -2929,6 +2972,10 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
cs_in_expr_is_unsafe |= arg_type->cs_in_expr_is_unsafe;
}
+ if (p_use_span && !has_span_argument) {
+ return OK;
+ }
+
// Collect caller name for MethodBind
if (p_imethod.is_vararg) {
icall_params += ", (godot_string_name)MethodName." + p_imethod.proxy_name + ".NativeValue";
@@ -2936,7 +2983,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
// Generate method
{
- if (!p_imethod.is_virtual && !p_imethod.requires_object_call) {
+ if (!p_imethod.is_virtual && !p_imethod.requires_object_call && !p_use_span) {
p_output << MEMBER_BEGIN "[DebuggerBrowsable(DebuggerBrowsableState.Never)]\n"
<< INDENT1 "private static readonly IntPtr " << method_bind_field << " = ";
@@ -4736,13 +4783,14 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype = TypeInterface();
itype.name = "VarArg";
itype.cname = itype.name;
- itype.proxy_name = "Variant[]";
+ itype.proxy_name = "ReadOnlySpan<Variant>";
itype.cs_type = "params Variant[]";
- itype.cs_in_expr = "%0 ?? Array.Empty<Variant>()";
+ itype.cs_in_expr = "%0";
// c_type, c_in and c_arg_in are hard-coded in the generator.
// c_out and c_type_out are not applicable to VarArg.
itype.c_arg_in = "&%s_in";
- itype.c_type_in = "Variant[]";
+ itype.c_type_in = "ReadOnlySpan<Variant>";
+ itype.is_span_compatible = true;
builtin_types.insert(itype.cname, itype);
#define INSERT_ARRAY_FULL(m_name, m_type, m_managed_type, m_proxy_t) \
@@ -4756,9 +4804,10 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_out = "%5return " C_METHOD_MONOARRAY_FROM(m_type) "(%1);\n"; \
itype.c_arg_in = "&%s_in"; \
itype.c_type = #m_managed_type; \
- itype.c_type_in = itype.proxy_name; \
+ itype.c_type_in = "ReadOnlySpan<" #m_proxy_t ">"; \
itype.c_type_out = itype.proxy_name; \
itype.c_type_is_disposable_struct = true; \
+ itype.is_span_compatible = true; \
builtin_types.insert(itype.name, itype); \
}
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index 0193ef8287..f6b1a53a45 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -267,6 +267,7 @@ class BindingsGenerator {
bool is_singleton = false;
bool is_singleton_instance = false;
bool is_ref_counted = false;
+ bool is_span_compatible = false;
/**
* Class is a singleton, but can't be declared as a static class as that would
@@ -842,7 +843,7 @@ class BindingsGenerator {
Error _generate_cs_type(const TypeInterface &itype, const String &p_output_file);
Error _generate_cs_property(const TypeInterface &p_itype, const PropertyInterface &p_iprop, StringBuilder &p_output);
- Error _generate_cs_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output);
+ Error _generate_cs_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output, bool p_use_span);
Error _generate_cs_signal(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::SignalInterface &p_isignal, StringBuilder &p_output);
Error _generate_cs_native_calls(const InternalCall &p_icall, StringBuilder &r_output);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
index 864815866a..db6961fd12 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
@@ -174,7 +174,7 @@ namespace Godot.Collections
var keys = Array.CreateTakingOwnershipOfDisposableValue(keysArray);
godot_array valuesArray;
- NativeFuncs.godotsharp_dictionary_keys(ref self, out valuesArray);
+ NativeFuncs.godotsharp_dictionary_values(ref self, out valuesArray);
var values = Array.CreateTakingOwnershipOfDisposableValue(valuesArray);
int count = NativeFuncs.godotsharp_dictionary_count(ref self);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
index 15b7ce7c73..fc68b11932 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
@@ -394,7 +394,12 @@ namespace Godot.NativeInterop
return array;
}
- public static unsafe godot_packed_byte_array ConvertSystemArrayToNativePackedByteArray(Span<byte> p_array)
+ public static godot_packed_byte_array ConvertSystemArrayToNativePackedByteArray(Span<byte> p_array)
+ {
+ return ConvertSystemArrayToNativePackedByteArray((ReadOnlySpan<byte>)p_array);
+ }
+
+ public static unsafe godot_packed_byte_array ConvertSystemArrayToNativePackedByteArray(ReadOnlySpan<byte> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_byte_array();
@@ -417,7 +422,12 @@ namespace Godot.NativeInterop
return array;
}
- public static unsafe godot_packed_int32_array ConvertSystemArrayToNativePackedInt32Array(Span<int> p_array)
+ public static godot_packed_int32_array ConvertSystemArrayToNativePackedInt32Array(Span<int> p_array)
+ {
+ return ConvertSystemArrayToNativePackedInt32Array((ReadOnlySpan<int>)p_array);
+ }
+
+ public static unsafe godot_packed_int32_array ConvertSystemArrayToNativePackedInt32Array(ReadOnlySpan<int> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_int32_array();
@@ -440,7 +450,12 @@ namespace Godot.NativeInterop
return array;
}
- public static unsafe godot_packed_int64_array ConvertSystemArrayToNativePackedInt64Array(Span<long> p_array)
+ public static godot_packed_int64_array ConvertSystemArrayToNativePackedInt64Array(Span<long> p_array)
+ {
+ return ConvertSystemArrayToNativePackedInt64Array((ReadOnlySpan<long>)p_array);
+ }
+
+ public static unsafe godot_packed_int64_array ConvertSystemArrayToNativePackedInt64Array(ReadOnlySpan<long> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_int64_array();
@@ -463,8 +478,13 @@ namespace Godot.NativeInterop
return array;
}
+ public static godot_packed_float32_array ConvertSystemArrayToNativePackedFloat32Array(Span<float> p_array)
+ {
+ return ConvertSystemArrayToNativePackedFloat32Array((ReadOnlySpan<float>)p_array);
+ }
+
public static unsafe godot_packed_float32_array ConvertSystemArrayToNativePackedFloat32Array(
- Span<float> p_array)
+ ReadOnlySpan<float> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_float32_array();
@@ -487,8 +507,13 @@ namespace Godot.NativeInterop
return array;
}
+ public static godot_packed_float64_array ConvertSystemArrayToNativePackedFloat64Array(Span<double> p_array)
+ {
+ return ConvertSystemArrayToNativePackedFloat64Array((ReadOnlySpan<double>)p_array);
+ }
+
public static unsafe godot_packed_float64_array ConvertSystemArrayToNativePackedFloat64Array(
- Span<double> p_array)
+ ReadOnlySpan<double> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_float64_array();
@@ -512,6 +537,11 @@ namespace Godot.NativeInterop
public static godot_packed_string_array ConvertSystemArrayToNativePackedStringArray(Span<string> p_array)
{
+ return ConvertSystemArrayToNativePackedStringArray((ReadOnlySpan<string>)p_array);
+ }
+
+ public static godot_packed_string_array ConvertSystemArrayToNativePackedStringArray(ReadOnlySpan<string> p_array)
+ {
godot_packed_string_array dest = new godot_packed_string_array();
if (p_array.IsEmpty)
@@ -544,8 +574,13 @@ namespace Godot.NativeInterop
return array;
}
+ public static godot_packed_vector2_array ConvertSystemArrayToNativePackedVector2Array(Span<Vector2> p_array)
+ {
+ return ConvertSystemArrayToNativePackedVector2Array((ReadOnlySpan<Vector2>)p_array);
+ }
+
public static unsafe godot_packed_vector2_array ConvertSystemArrayToNativePackedVector2Array(
- Span<Vector2> p_array)
+ ReadOnlySpan<Vector2> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_vector2_array();
@@ -568,8 +603,13 @@ namespace Godot.NativeInterop
return array;
}
+ public static godot_packed_vector3_array ConvertSystemArrayToNativePackedVector3Array(Span<Vector3> p_array)
+ {
+ return ConvertSystemArrayToNativePackedVector3Array((ReadOnlySpan<Vector3>)p_array);
+ }
+
public static unsafe godot_packed_vector3_array ConvertSystemArrayToNativePackedVector3Array(
- Span<Vector3> p_array)
+ ReadOnlySpan<Vector3> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_vector3_array();
@@ -592,8 +632,13 @@ namespace Godot.NativeInterop
return array;
}
+ public static godot_packed_vector4_array ConvertSystemArrayToNativePackedVector4Array(Span<Vector4> p_array)
+ {
+ return ConvertSystemArrayToNativePackedVector4Array((ReadOnlySpan<Vector4>)p_array);
+ }
+
public static unsafe godot_packed_vector4_array ConvertSystemArrayToNativePackedVector4Array(
- Span<Vector4> p_array)
+ ReadOnlySpan<Vector4> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_vector4_array();
@@ -616,7 +661,12 @@ namespace Godot.NativeInterop
return array;
}
- public static unsafe godot_packed_color_array ConvertSystemArrayToNativePackedColorArray(Span<Color> p_array)
+ public static godot_packed_color_array ConvertSystemArrayToNativePackedColorArray(Span<Color> p_array)
+ {
+ return ConvertSystemArrayToNativePackedColorArray((ReadOnlySpan<Color>)p_array);
+ }
+
+ public static unsafe godot_packed_color_array ConvertSystemArrayToNativePackedColorArray(ReadOnlySpan<Color> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_color_array();
diff --git a/modules/noise/doc_classes/FastNoiseLite.xml b/modules/noise/doc_classes/FastNoiseLite.xml
index f2a6c60376..6f6a637893 100644
--- a/modules/noise/doc_classes/FastNoiseLite.xml
+++ b/modules/noise/doc_classes/FastNoiseLite.xml
@@ -91,10 +91,10 @@
Cellular includes both Worley noise and Voronoi diagrams which creates various regions of the same value.
</constant>
<constant name="TYPE_SIMPLEX" value="0" enum="NoiseType">
- As opposed to [constant TYPE_PERLIN], gradients exist in a simplex lattice rather than a grid lattice, avoiding directional artifacts.
+ As opposed to [constant TYPE_PERLIN], gradients exist in a simplex lattice rather than a grid lattice, avoiding directional artifacts. Internally uses FastNoiseLite's OpenSimplex2 noise type.
</constant>
<constant name="TYPE_SIMPLEX_SMOOTH" value="1" enum="NoiseType">
- Modified, higher quality version of [constant TYPE_SIMPLEX], but slower.
+ Modified, higher quality version of [constant TYPE_SIMPLEX], but slower. Internally uses FastNoiseLite's OpenSimplex2S noise type.
</constant>
<constant name="FRACTAL_NONE" value="0" enum="FractalType">
No fractal noise.
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index 4043f3a8c2..0ee52a09a7 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -662,7 +662,7 @@ def get_ar_version(env):
print_warning("Couldn't check version of `ar`.")
return ret
- match = re.search(r"GNU ar \(GNU Binutils\) (\d+)\.(\d+)(?:\.(\d+))?", output)
+ match = re.search(r"GNU ar(?: \(GNU Binutils\)| version) (\d+)\.(\d+)(?:\.(\d+))?", output)
if match:
ret["major"] = int(match[1])
ret["minor"] = int(match[2])
@@ -788,8 +788,9 @@ def configure_mingw(env: "SConsEnvironment"):
env["CXX"] = mingw_bin_prefix + "g++"
if try_cmd("as --version", env["mingw_prefix"], env["arch"]):
env["AS"] = mingw_bin_prefix + "as"
- if try_cmd("gcc-ar --version", env["mingw_prefix"], env["arch"]):
- env["AR"] = mingw_bin_prefix + "gcc-ar"
+ ar = "ar" if os.name == "nt" else "gcc-ar"
+ if try_cmd(f"{ar} --version", env["mingw_prefix"], env["arch"]):
+ env["AR"] = mingw_bin_prefix + ar
if try_cmd("gcc-ranlib --version", env["mingw_prefix"], env["arch"]):
env["RANLIB"] = mingw_bin_prefix + "gcc-ranlib"
diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp
index b74e91e97c..dea7b09807 100644
--- a/scene/2d/skeleton_2d.cpp
+++ b/scene/2d/skeleton_2d.cpp
@@ -161,7 +161,7 @@ void Bone2D::_notification(int p_what) {
case NOTIFICATION_EXIT_TREE: {
if (skeleton) {
- for (int i = 0; i < skeleton->bones.size(); i++) {
+ for (uint32_t i = 0; i < skeleton->bones.size(); i++) {
if (skeleton->bones[i].bone == this) {
skeleton->bones.remove_at(i);
break;
@@ -557,17 +557,17 @@ void Skeleton2D::_update_bone_setup() {
bones.sort(); //sorting so that they are always in the same order/index
- for (int i = 0; i < bones.size(); i++) {
- bones.write[i].rest_inverse = bones[i].bone->get_skeleton_rest().affine_inverse(); //bind pose
- bones.write[i].bone->skeleton_index = i;
+ for (uint32_t i = 0; i < bones.size(); i++) {
+ bones[i].rest_inverse = bones[i].bone->get_skeleton_rest().affine_inverse(); //bind pose
+ bones[i].bone->skeleton_index = i;
Bone2D *parent_bone = Object::cast_to<Bone2D>(bones[i].bone->get_parent());
if (parent_bone) {
- bones.write[i].parent_index = parent_bone->skeleton_index;
+ bones[i].parent_index = parent_bone->skeleton_index;
} else {
- bones.write[i].parent_index = -1;
+ bones[i].parent_index = -1;
}
- bones.write[i].local_pose_override = bones[i].bone->get_skeleton_rest();
+ bones[i].local_pose_override = bones[i].bone->get_skeleton_rest();
}
transform_dirty = true;
@@ -596,16 +596,16 @@ void Skeleton2D::_update_transform() {
transform_dirty = false;
- for (int i = 0; i < bones.size(); i++) {
- ERR_CONTINUE(bones[i].parent_index >= i);
+ for (uint32_t i = 0; i < bones.size(); i++) {
+ ERR_CONTINUE(bones[i].parent_index >= (int)i);
if (bones[i].parent_index >= 0) {
- bones.write[i].accum_transform = bones[bones[i].parent_index].accum_transform * bones[i].bone->get_transform();
+ bones[i].accum_transform = bones[bones[i].parent_index].accum_transform * bones[i].bone->get_transform();
} else {
- bones.write[i].accum_transform = bones[i].bone->get_transform();
+ bones[i].accum_transform = bones[i].bone->get_transform();
}
}
- for (int i = 0; i < bones.size(); i++) {
+ for (uint32_t i = 0; i < bones.size(); i++) {
Transform2D final_xform = bones[i].accum_transform * bones[i].rest_inverse;
RS::get_singleton()->skeleton_bone_set_transform_2d(skeleton, i, final_xform);
}
@@ -623,7 +623,7 @@ int Skeleton2D::get_bone_count() const {
Bone2D *Skeleton2D::get_bone(int p_idx) {
ERR_FAIL_COND_V(!is_inside_tree(), nullptr);
- ERR_FAIL_INDEX_V(p_idx, bones.size(), nullptr);
+ ERR_FAIL_INDEX_V(p_idx, (int)bones.size(), nullptr);
return bones[p_idx].bone;
}
@@ -735,14 +735,14 @@ RID Skeleton2D::get_skeleton() const {
}
void Skeleton2D::set_bone_local_pose_override(int p_bone_idx, Transform2D p_override, real_t p_amount, bool p_persistent) {
- ERR_FAIL_INDEX_MSG(p_bone_idx, bones.size(), "Bone index is out of range!");
- bones.write[p_bone_idx].local_pose_override = p_override;
- bones.write[p_bone_idx].local_pose_override_amount = p_amount;
- bones.write[p_bone_idx].local_pose_override_persistent = p_persistent;
+ ERR_FAIL_INDEX_MSG(p_bone_idx, (int)bones.size(), "Bone index is out of range!");
+ bones[p_bone_idx].local_pose_override = p_override;
+ bones[p_bone_idx].local_pose_override_amount = p_amount;
+ bones[p_bone_idx].local_pose_override_persistent = p_persistent;
}
Transform2D Skeleton2D::get_bone_local_pose_override(int p_bone_idx) {
- ERR_FAIL_INDEX_V_MSG(p_bone_idx, bones.size(), Transform2D(), "Bone index is out of range!");
+ ERR_FAIL_INDEX_V_MSG(p_bone_idx, (int)bones.size(), Transform2D(), "Bone index is out of range!");
return bones[p_bone_idx].local_pose_override;
}
@@ -773,7 +773,7 @@ void Skeleton2D::execute_modifications(real_t p_delta, int p_execution_mode) {
}
// Do not cache the transform changes caused by the modifications!
- for (int i = 0; i < bones.size(); i++) {
+ for (uint32_t i = 0; i < bones.size(); i++) {
bones[i].bone->copy_transform_to_cache = false;
}
@@ -785,7 +785,7 @@ void Skeleton2D::execute_modifications(real_t p_delta, int p_execution_mode) {
// Only apply the local pose override on _process. Otherwise, just calculate the local_pose_override and reset the transform.
if (p_execution_mode == SkeletonModificationStack2D::EXECUTION_MODE::execution_mode_process) {
- for (int i = 0; i < bones.size(); i++) {
+ for (uint32_t i = 0; i < bones.size(); i++) {
if (bones[i].local_pose_override_amount > 0) {
bones[i].bone->set_meta("_local_pose_override_enabled_", true);
@@ -795,7 +795,7 @@ void Skeleton2D::execute_modifications(real_t p_delta, int p_execution_mode) {
bones[i].bone->propagate_call("force_update_transform");
if (bones[i].local_pose_override_persistent) {
- bones.write[i].local_pose_override_amount = 0.0;
+ bones[i].local_pose_override_amount = 0.0;
}
} else {
// TODO: see if there is a way to undo the override without having to resort to setting every bone's transform.
@@ -806,7 +806,7 @@ void Skeleton2D::execute_modifications(real_t p_delta, int p_execution_mode) {
}
// Cache any future transform changes
- for (int i = 0; i < bones.size(); i++) {
+ for (uint32_t i = 0; i < bones.size(); i++) {
bones[i].bone->copy_transform_to_cache = true;
}
diff --git a/scene/2d/skeleton_2d.h b/scene/2d/skeleton_2d.h
index 07ec13f191..cc9030aa54 100644
--- a/scene/2d/skeleton_2d.h
+++ b/scene/2d/skeleton_2d.h
@@ -125,7 +125,7 @@ class Skeleton2D : public Node2D {
bool local_pose_override_persistent = false;
};
- Vector<Bone> bones;
+ LocalVector<Bone> bones;
bool bone_setup_dirty = true;
void _make_bone_setup_dirty();
diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp
index 8acd92828f..b4ac5efc2a 100644
--- a/scene/3d/node_3d.cpp
+++ b/scene/3d/node_3d.cpp
@@ -1183,15 +1183,16 @@ void Node3D::_validate_property(PropertyInfo &p_property) const {
}
bool Node3D::_property_can_revert(const StringName &p_name) const {
- if (p_name == "basis") {
+ const String sname = p_name;
+ if (sname == "basis") {
return true;
- } else if (p_name == "scale") {
+ } else if (sname == "scale") {
return true;
- } else if (p_name == "quaternion") {
+ } else if (sname == "quaternion") {
return true;
- } else if (p_name == "rotation") {
+ } else if (sname == "rotation") {
return true;
- } else if (p_name == "position") {
+ } else if (sname == "position") {
return true;
}
return false;
@@ -1200,35 +1201,36 @@ bool Node3D::_property_can_revert(const StringName &p_name) const {
bool Node3D::_property_get_revert(const StringName &p_name, Variant &r_property) const {
bool valid = false;
- if (p_name == "basis") {
+ const String sname = p_name;
+ if (sname == "basis") {
Variant variant = PropertyUtils::get_property_default_value(this, "transform", &valid);
if (valid && variant.get_type() == Variant::Type::TRANSFORM3D) {
r_property = Transform3D(variant).get_basis();
} else {
r_property = Basis();
}
- } else if (p_name == "scale") {
+ } else if (sname == "scale") {
Variant variant = PropertyUtils::get_property_default_value(this, "transform", &valid);
if (valid && variant.get_type() == Variant::Type::TRANSFORM3D) {
r_property = Transform3D(variant).get_basis().get_scale();
} else {
r_property = Vector3(1.0, 1.0, 1.0);
}
- } else if (p_name == "quaternion") {
+ } else if (sname == "quaternion") {
Variant variant = PropertyUtils::get_property_default_value(this, "transform", &valid);
if (valid && variant.get_type() == Variant::Type::TRANSFORM3D) {
r_property = Quaternion(Transform3D(variant).get_basis().get_rotation_quaternion());
} else {
r_property = Quaternion();
}
- } else if (p_name == "rotation") {
+ } else if (sname == "rotation") {
Variant variant = PropertyUtils::get_property_default_value(this, "transform", &valid);
if (valid && variant.get_type() == Variant::Type::TRANSFORM3D) {
r_property = Transform3D(variant).get_basis().get_euler_normalized(data.euler_rotation_order);
} else {
r_property = Vector3();
}
- } else if (p_name == "position") {
+ } else if (sname == "position") {
Variant variant = PropertyUtils::get_property_default_value(this, "transform", &valid);
if (valid) {
r_property = Transform3D(variant).get_origin();
diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp
index 923a7a85eb..25a29e0823 100644
--- a/scene/3d/skeleton_3d.cpp
+++ b/scene/3d/skeleton_3d.cpp
@@ -83,7 +83,7 @@ bool Skeleton3D::_set(const StringName &p_path, const Variant &p_value) {
return false;
}
- int which = path.get_slicec('/', 1).to_int();
+ uint32_t which = path.get_slicec('/', 1).to_int();
String what = path.get_slicec('/', 2);
if (which == bones.size() && what == "name") {
@@ -91,7 +91,7 @@ bool Skeleton3D::_set(const StringName &p_path, const Variant &p_value) {
return true;
}
- ERR_FAIL_INDEX_V(which, bones.size(), false);
+ ERR_FAIL_UNSIGNED_INDEX_V(which, bones.size(), false);
if (what == "parent") {
set_bone_parent(which, p_value);
@@ -155,10 +155,10 @@ bool Skeleton3D::_get(const StringName &p_path, Variant &r_ret) const {
return false;
}
- int which = path.get_slicec('/', 1).to_int();
+ uint32_t which = path.get_slicec('/', 1).to_int();
String what = path.get_slicec('/', 2);
- ERR_FAIL_INDEX_V(which, bones.size(), false);
+ ERR_FAIL_UNSIGNED_INDEX_V(which, bones.size(), false);
if (what == "name") {
r_ret = get_bone_name(which);
@@ -184,7 +184,7 @@ bool Skeleton3D::_get(const StringName &p_path, Variant &r_ret) const {
}
void Skeleton3D::_get_property_list(List<PropertyInfo> *p_list) const {
- for (int i = 0; i < bones.size(); i++) {
+ for (uint32_t i = 0; i < bones.size(); i++) {
const String prep = vformat("%s/%d/", PNAME("bones"), i);
p_list->push_back(PropertyInfo(Variant::STRING, prep + PNAME("name"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
p_list->push_back(PropertyInfo(Variant::INT, prep + PNAME("parent"), PROPERTY_HINT_RANGE, "-1," + itos(bones.size() - 1) + ",1", PROPERTY_USAGE_NO_EDITOR));
@@ -243,7 +243,7 @@ void Skeleton3D::_update_process_order() {
return;
}
- Bone *bonesptr = bones.ptrw();
+ Bone *bonesptr = bones.ptr();
int len = bones.size();
parentless_bones.clear();
@@ -285,7 +285,7 @@ void Skeleton3D::_update_process_order() {
void Skeleton3D::_update_bone_names() const {
String names;
- for (int i = 0; i < bones.size(); i++) {
+ for (uint32_t i = 0; i < bones.size(); i++) {
if (i > 0) {
names += ",";
}
@@ -333,14 +333,14 @@ void Skeleton3D::_notification(int p_what) {
updating = true;
- Bone *bonesptr = bones.ptrw();
+ Bone *bonesptr = bones.ptr();
int len = bones.size();
// Process modifiers.
_find_modifiers();
if (!modifiers.is_empty()) {
// Store unmodified bone poses.
- for (int i = 0; i < bones.size(); i++) {
+ for (uint32_t i = 0; i < bones.size(); i++) {
bones_backup[i].save(bones[i]);
}
_process_modifiers();
@@ -414,8 +414,8 @@ void Skeleton3D::_notification(int p_what) {
if (!modifiers.is_empty()) {
// Restore unmodified bone poses.
- for (int i = 0; i < bones.size(); i++) {
- bones_backup[i].restore(bones.write[i]);
+ for (uint32_t i = 0; i < bones.size(); i++) {
+ bones_backup[i].restore(bones[i]);
}
}
@@ -536,7 +536,7 @@ void Skeleton3D::set_bone_name(int p_bone, const String &p_name) {
}
name_to_bone_index.erase(bones[p_bone].name);
- bones.write[p_bone].name = p_name;
+ bones[p_bone].name = p_name;
name_to_bone_index.insert(p_name, p_bone);
version++;
@@ -584,13 +584,13 @@ void Skeleton3D::set_bone_meta(int p_bone, const StringName &p_key, const Varian
ERR_FAIL_INDEX(p_bone, bone_size);
if (p_value.get_type() == Variant::NIL) {
- if (bones.write[p_bone].metadata.has(p_key)) {
- bones.write[p_bone].metadata.erase(p_key);
+ if (bones[p_bone].metadata.has(p_key)) {
+ bones[p_bone].metadata.erase(p_key);
}
return;
}
- bones.write[p_bone].metadata.insert(p_key, p_value, false);
+ bones[p_bone].metadata.insert(p_key, p_value, false);
}
bool Skeleton3D::is_bone_parent_of(int p_bone, int p_parent_bone_id) const {
@@ -617,7 +617,7 @@ void Skeleton3D::set_bone_parent(int p_bone, int p_parent) {
ERR_FAIL_COND(p_parent != -1 && (p_parent < 0));
ERR_FAIL_COND(p_bone == p_parent);
- bones.write[p_bone].parent = p_parent;
+ bones[p_bone].parent = p_parent;
process_order_dirty = true;
rest_dirty = true;
_make_dirty();
@@ -631,11 +631,11 @@ void Skeleton3D::unparent_bone_and_rest(int p_bone) {
int parent = bones[p_bone].parent;
while (parent >= 0) {
- bones.write[p_bone].rest = bones[parent].rest * bones[p_bone].rest;
+ bones[p_bone].rest = bones[parent].rest * bones[p_bone].rest;
parent = bones[parent].parent;
}
- bones.write[p_bone].parent = -1;
+ bones[p_bone].parent = -1;
process_order_dirty = true;
rest_dirty = true;
@@ -671,7 +671,7 @@ void Skeleton3D::set_bone_rest(int p_bone, const Transform3D &p_rest) {
const int bone_size = bones.size();
ERR_FAIL_INDEX(p_bone, bone_size);
- bones.write[p_bone].rest = p_rest;
+ bones[p_bone].rest = p_rest;
rest_dirty = true;
_make_dirty();
}
@@ -694,7 +694,7 @@ void Skeleton3D::set_bone_enabled(int p_bone, bool p_enabled) {
const int bone_size = bones.size();
ERR_FAIL_INDEX(p_bone, bone_size);
- bones.write[p_bone].enabled = p_enabled;
+ bones[p_bone].enabled = p_enabled;
emit_signal(SceneStringName(bone_enabled_changed), p_bone);
_make_dirty();
}
@@ -729,10 +729,10 @@ void Skeleton3D::set_bone_pose(int p_bone, const Transform3D &p_pose) {
const int bone_size = bones.size();
ERR_FAIL_INDEX(p_bone, bone_size);
- bones.write[p_bone].pose_position = p_pose.origin;
- bones.write[p_bone].pose_rotation = p_pose.basis.get_rotation_quaternion();
- bones.write[p_bone].pose_scale = p_pose.basis.get_scale();
- bones.write[p_bone].pose_cache_dirty = true;
+ bones[p_bone].pose_position = p_pose.origin;
+ bones[p_bone].pose_rotation = p_pose.basis.get_rotation_quaternion();
+ bones[p_bone].pose_scale = p_pose.basis.get_scale();
+ bones[p_bone].pose_cache_dirty = true;
if (is_inside_tree()) {
_make_dirty();
}
@@ -742,8 +742,8 @@ void Skeleton3D::set_bone_pose_position(int p_bone, const Vector3 &p_position) {
const int bone_size = bones.size();
ERR_FAIL_INDEX(p_bone, bone_size);
- bones.write[p_bone].pose_position = p_position;
- bones.write[p_bone].pose_cache_dirty = true;
+ bones[p_bone].pose_position = p_position;
+ bones[p_bone].pose_cache_dirty = true;
if (is_inside_tree()) {
_make_dirty();
}
@@ -752,8 +752,8 @@ void Skeleton3D::set_bone_pose_rotation(int p_bone, const Quaternion &p_rotation
const int bone_size = bones.size();
ERR_FAIL_INDEX(p_bone, bone_size);
- bones.write[p_bone].pose_rotation = p_rotation;
- bones.write[p_bone].pose_cache_dirty = true;
+ bones[p_bone].pose_rotation = p_rotation;
+ bones[p_bone].pose_cache_dirty = true;
if (is_inside_tree()) {
_make_dirty();
}
@@ -762,8 +762,8 @@ void Skeleton3D::set_bone_pose_scale(int p_bone, const Vector3 &p_scale) {
const int bone_size = bones.size();
ERR_FAIL_INDEX(p_bone, bone_size);
- bones.write[p_bone].pose_scale = p_scale;
- bones.write[p_bone].pose_cache_dirty = true;
+ bones[p_bone].pose_scale = p_scale;
+ bones[p_bone].pose_cache_dirty = true;
if (is_inside_tree()) {
_make_dirty();
}
@@ -796,7 +796,7 @@ void Skeleton3D::reset_bone_pose(int p_bone) {
}
void Skeleton3D::reset_bone_poses() {
- for (int i = 0; i < bones.size(); i++) {
+ for (uint32_t i = 0; i < bones.size(); i++) {
reset_bone_pose(i);
}
}
@@ -804,7 +804,7 @@ void Skeleton3D::reset_bone_poses() {
Transform3D Skeleton3D::get_bone_pose(int p_bone) const {
const int bone_size = bones.size();
ERR_FAIL_INDEX_V(p_bone, bone_size, Transform3D());
- const_cast<Skeleton3D *>(this)->bones.write[p_bone].update_pose_cache();
+ const_cast<Skeleton3D *>(this)->bones[p_bone].update_pose_cache();
return bones[p_bone].pose_cache;
}
@@ -855,7 +855,7 @@ Ref<Skin> Skeleton3D::create_skin_from_rest_transforms() {
// Pose changed, rebuild cache of inverses.
const Bone *bonesptr = bones.ptr();
- int len = bones.size();
+ uint32_t len = bones.size();
// Calculate global rests and invert them.
LocalVector<int> bones_to_process;
@@ -879,7 +879,7 @@ Ref<Skin> Skeleton3D::create_skin_from_rest_transforms() {
}
}
- for (int i = 0; i < len; i++) {
+ for (uint32_t i = 0; i < len; i++) {
// The inverse is what is actually required.
skin->set_bind_bone(i, i);
skin->set_bind_pose(i, skin->get_bind_pose(i).affine_inverse());
@@ -939,7 +939,7 @@ void Skeleton3D::force_update_bone_children_transforms(int p_bone_idx) {
const int bone_size = bones.size();
ERR_FAIL_INDEX(p_bone_idx, bone_size);
- Bone *bonesptr = bones.ptrw();
+ Bone *bonesptr = bones.ptr();
thread_local LocalVector<int> bones_to_process;
bones_to_process.clear();
bones_to_process.push_back(p_bone_idx);
@@ -1173,9 +1173,9 @@ void Skeleton3D::_bind_methods() {
#ifndef DISABLE_DEPRECATED
void Skeleton3D::clear_bones_global_pose_override() {
- for (int i = 0; i < bones.size(); i += 1) {
- bones.write[i].global_pose_override_amount = 0;
- bones.write[i].global_pose_override_reset = true;
+ for (uint32_t i = 0; i < bones.size(); i += 1) {
+ bones[i].global_pose_override_amount = 0;
+ bones[i].global_pose_override_reset = true;
}
_make_dirty();
}
@@ -1183,9 +1183,9 @@ void Skeleton3D::clear_bones_global_pose_override() {
void Skeleton3D::set_bone_global_pose_override(int p_bone, const Transform3D &p_pose, real_t p_amount, bool p_persistent) {
const int bone_size = bones.size();
ERR_FAIL_INDEX(p_bone, bone_size);
- bones.write[p_bone].global_pose_override_amount = p_amount;
- bones.write[p_bone].global_pose_override = p_pose;
- bones.write[p_bone].global_pose_override_reset = !p_persistent;
+ bones[p_bone].global_pose_override_amount = p_amount;
+ bones[p_bone].global_pose_override = p_pose;
+ bones[p_bone].global_pose_override_reset = !p_persistent;
_make_dirty();
}
diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h
index f890470769..0dd10f177e 100644
--- a/scene/3d/skeleton_3d.h
+++ b/scene/3d/skeleton_3d.h
@@ -155,7 +155,7 @@ private:
HashSet<SkinReference *> skin_bindings;
void _skin_changed();
- Vector<Bone> bones;
+ LocalVector<Bone> bones;
bool process_order_dirty = false;
Vector<int> parentless_bones;
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 9efdffd983..fc32e6883c 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -384,14 +384,11 @@ void ShaderMaterial::_get_property_list(List<PropertyInfo> *p_list) const {
bool ShaderMaterial::_property_can_revert(const StringName &p_name) const {
if (shader.is_valid()) {
- const StringName *pr = remap_cache.getptr(p_name);
- if (pr) {
- Variant default_value = RenderingServer::get_singleton()->shader_get_parameter_default(shader->get_rid(), *pr);
- Variant current_value = get_shader_parameter(*pr);
- return default_value.get_type() != Variant::NIL && default_value != current_value;
- } else if (p_name == "render_priority" || p_name == "next_pass") {
+ if (remap_cache.has(p_name)) {
return true;
}
+ const String sname = p_name;
+ return sname == "render_priority" || sname == "next_pass";
}
return false;
}
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
index 3df9ef9858..26bfac1aed 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
@@ -2187,7 +2187,7 @@ void MeshStorage::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_
if (skeleton->size) {
skeleton->data.resize(skeleton->size * (skeleton->use_2d ? 8 : 12));
skeleton->buffer = RD::get_singleton()->storage_buffer_create(skeleton->data.size() * sizeof(float));
- memset(skeleton->data.ptrw(), 0, skeleton->data.size() * sizeof(float));
+ memset(skeleton->data.ptr(), 0, skeleton->data.size() * sizeof(float));
_skeleton_make_dirty(skeleton);
@@ -2221,7 +2221,7 @@ void MeshStorage::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const
ERR_FAIL_INDEX(p_bone, skeleton->size);
ERR_FAIL_COND(skeleton->use_2d);
- float *dataptr = skeleton->data.ptrw() + p_bone * 12;
+ float *dataptr = skeleton->data.ptr() + p_bone * 12;
dataptr[0] = p_transform.basis.rows[0][0];
dataptr[1] = p_transform.basis.rows[0][1];
@@ -2272,8 +2272,7 @@ void MeshStorage::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, con
ERR_FAIL_NULL(skeleton);
ERR_FAIL_INDEX(p_bone, skeleton->size);
ERR_FAIL_COND(!skeleton->use_2d);
-
- float *dataptr = skeleton->data.ptrw() + p_bone * 8;
+ float *dataptr = skeleton->data.ptr() + p_bone * 8;
dataptr[0] = p_transform.columns[0][0];
dataptr[1] = p_transform.columns[1][0];
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
index 46d685eb18..a9ac1b7e14 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
@@ -314,7 +314,7 @@ private:
struct Skeleton {
bool use_2d = false;
int size = 0;
- Vector<float> data;
+ LocalVector<float> data;
RID buffer;
bool dirty = false;
diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp
index 599cd0aeb2..7f13e91aa1 100644
--- a/servers/rendering/shader_compiler.cpp
+++ b/servers/rendering/shader_compiler.cpp
@@ -953,7 +953,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
} else if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
//instance variable, index it as such
- code = "(" + p_default_actions.instance_uniform_index_variable + "+" + itos(u.instance_index) + ")";
+ code = "(" + p_default_actions.instance_uniform_index_variable + "+" + itos(u.instance_index) + "u)";
code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
} else {
//regular uniform, index from UBO
@@ -1053,7 +1053,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
} else if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
//instance variable, index it as such
- code = "(" + p_default_actions.instance_uniform_index_variable + "+" + itos(u.instance_index) + ")";
+ code = "(" + p_default_actions.instance_uniform_index_variable + "+" + itos(u.instance_index) + "u)";
code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
} else {
//regular uniform, index from UBO
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 0ac805acca..23c97be953 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -9091,10 +9091,6 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
_set_error(vformat(RTR("Uniform instances are not yet implemented for '%s' shaders."), shader_type_identifier));
return ERR_PARSE_ERROR;
}
- if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") {
- _set_error(RTR("Uniform instances are not supported in gl_compatibility shaders."));
- return ERR_PARSE_ERROR;
- }
if (uniform_scope == ShaderNode::Uniform::SCOPE_LOCAL) {
tk = _get_token();
if (tk.type != TK_UNIFORM) {