diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 748d787b86ea..68bd4bc4ceae 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 95e3d4a553d1..384284b6047e 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/godot.windows.editor.x86_64.exe - artifact: true + compiler: msvc - name: Editor w/ clang-cl (target=editor, tests=yes, use_llvm=yes) cache-name: windows-editor-clang @@ -38,6 +38,7 @@ jobs: tests: true sconsflags: debug_symbols=no windows_subsystem=console use_llvm=yes bin: ./bin/godot.windows.editor.x86_64.llvm.exe + compiler: clang - name: Template (target=template_release, tests=yes) cache-name: windows-template @@ -45,7 +46,16 @@ jobs: tests: true sconsflags: debug_symbols=no bin: ./bin/godot.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/godot.windows.template_release.x86_64.console.exe + compiler: gcc steps: - name: Checkout @@ -69,16 +79,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: @@ -94,12 +109,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 9fe54e57a7a7..01f15f9c8e4d 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -1167,22 +1167,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::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 d60619b27ff9..a49826958ae7 100644 --- a/core/math/geometry_2d.cpp +++ b/core/math/geometry_2d.cpp @@ -35,7 +35,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> Geometry2D::decompose_polygon_in_convex(const Vector &polygon) { Vector> decomp; @@ -224,7 +225,7 @@ Vector> 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 }); @@ -298,9 +299,10 @@ Vector> Geometry2D::_polypath_offset(const Vector &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> polypaths; for (PathsD::size_type i = 0; i < paths.size(); ++i) { diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml index de3295fbe041..1779408a4d67 100644 --- a/doc/classes/Environment.xml +++ b/doc/classes/Environment.xml @@ -81,8 +81,9 @@ The background mode. See [enum BGMode] for possible values. - 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]. 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 da41812e0be0..4d487b6dc29b 100644 --- a/doc/classes/PackedVector2Array.xml +++ b/doc/classes/PackedVector2Array.xml @@ -5,7 +5,7 @@ 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. diff --git a/drivers/d3d12/SCsub b/drivers/d3d12/SCsub index b6ceed23ac83..beeb13398e37 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 f94a4a30df3c..e08492c9ea9f 100644 --- a/drivers/d3d12/dxil_hash.cpp +++ b/drivers/d3d12/dxil_hash.cpp @@ -96,7 +96,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 8271d4b7e38d..0ef88e7d5285 100644 --- a/drivers/d3d12/rendering_device_driver_d3d12.cpp +++ b/drivers/d3d12/rendering_device_driver_d3d12.cpp @@ -1348,7 +1348,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; @@ -6578,8 +6585,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 4477ba7752cb..603dfadd4b95 100644 --- a/drivers/egl/egl_manager.cpp +++ b/drivers/egl/egl_manager.cpp @@ -30,6 +30,8 @@ #include "egl_manager.h" +#include "drivers/gles3/rasterizer_gles3.h" + #ifdef EGL_ENABLED #if defined(EGL_STATIC) @@ -51,6 +53,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. @@ -115,6 +127,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 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. @@ -237,8 +261,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 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); @@ -250,6 +295,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; @@ -316,6 +375,10 @@ void EGLManager::window_make_current(DisplayServer::WindowID p_window_id) { GLDisplay ¤t_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 a4502c06871d..f1b3dc99b78f 100644 --- a/drivers/egl/egl_manager.h +++ b/drivers/egl/egl_manager.h @@ -53,11 +53,18 @@ class EGLManager { 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 e79f1db08de8..6e508c6ebf0a 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -86,6 +86,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) { @@ -389,6 +393,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); @@ -485,9 +495,14 @@ void RasterizerGLES3::set_boot_image(const Ref &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 92454e014edb..6765d8b4d5ad 100644 --- a/drivers/gles3/rasterizer_gles3.h +++ b/drivers/gles3/rasterizer_gles3.h @@ -58,6 +58,10 @@ class RasterizerGLES3 : public RendererCompositor { 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: @@ -118,6 +122,12 @@ class RasterizerGLES3 : public RendererCompositor { 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/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp index 505855465907..73d95d75baf6 100644 --- a/drivers/gles3/storage/mesh_storage.cpp +++ b/drivers/gles3/storage/mesh_storage.cpp @@ -2201,7 +2201,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); } @@ -2232,7 +2232,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]; @@ -2284,7 +2284,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 31858cd372c6..8615b89a30d3 100644 --- a/drivers/gles3/storage/mesh_storage.h +++ b/drivers/gles3/storage/mesh_storage.h @@ -214,7 +214,7 @@ struct Skeleton { bool use_2d = false; int size = 0; int height = 0; - Vector data; + LocalVector data; bool dirty = false; Skeleton *dirty_list = nullptr; diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index c02efc445f83..f8d35f2112a2 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -4279,7 +4279,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 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(p_node) && p_property == "current_animation") { if (p_node == AnimationPlayerEditor::get_singleton()->get_player()) { diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index ee06f08a2d7b..12a7c3a2ff80 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -1424,24 +1424,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 5360b6fb60c7..230931937606 100644 --- a/editor/export/export_template_manager.cpp +++ b/editor/export/export_template_manager.cpp @@ -34,6 +34,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" @@ -876,7 +877,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 45786c0ab5e2..ef6a9c9a88b2 100644 --- a/editor/multi_node_edit.cpp +++ b/editor/multi_node_edit.cpp @@ -186,25 +186,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 a2c36b1f3ce6..9a53f07a3fc8 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -112,9 +112,13 @@ Ref EditorTexturePreviewPlugin::generate(const Ref &p_from, return Ref(); } - const int mid_depth = (tex_3d->get_depth() - 1) / 2; - Vector> data = tex_3d->get_data(); + if (data.size() != tex_3d->get_depth()) { + return Ref(); + } + + // 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(); } @@ -124,6 +128,7 @@ Ref EditorTexturePreviewPlugin::generate(const Ref &p_from, return Ref(); } + // Use the middle slice for the thumbnail. const int mid_layer = (tex_lyr->get_layers() - 1) / 2; Ref 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 ec9513363d16..6366d205399a 100644 --- a/editor/plugins/font_config_plugin.cpp +++ b/editor/plugins/font_config_plugin.cpp @@ -121,13 +121,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; } @@ -142,7 +137,6 @@ bool EditorPropertyFontOTObject::_property_get_revert(const StringName &p_name, return true; } } - return false; } diff --git a/modules/bcdec/image_decompress_bcdec.cpp b/modules/bcdec/image_decompress_bcdec.cpp index 30ca1fccb3df..c76470e3cc6f 100644 --- a/modules/bcdec/image_decompress_bcdec.cpp +++ b/modules/bcdec/image_decompress_bcdec.cpp @@ -92,8 +92,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; @@ -148,30 +160,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 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 7f0d5005cb0f..4a3a3a4b6152 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -148,6 +148,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; @@ -1101,7 +1110,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; @@ -1194,7 +1203,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); @@ -4249,7 +4258,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 0fd891aa8013..3de1decc1800 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -3782,7 +3782,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/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 89655e0b5610..946e997c1b5b 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -2348,9 +2348,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 @@ -2776,7 +2784,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."); @@ -2789,6 +2797,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; @@ -2835,6 +2872,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 { @@ -2846,7 +2885,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 += "> "; @@ -2856,7 +2899,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 { @@ -2867,7 +2910,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 : ; String arg_or_defval_local = iarg.name; @@ -2927,6 +2970,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"; @@ -2934,7 +2981,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 << " = "; @@ -4734,13 +4781,14 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype = TypeInterface(); itype.name = "VarArg"; itype.cname = itype.name; - itype.proxy_name = "Variant[]"; + itype.proxy_name = "ReadOnlySpan"; itype.cs_type = "params Variant[]"; - itype.cs_in_expr = "%0 ?? Array.Empty()"; + 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"; + 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) \ @@ -4754,9 +4802,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 556d287af4ef..1670aca4b3e9 100644 --- a/modules/mono/editor/bindings_generator.h +++ b/modules/mono/editor/bindings_generator.h @@ -265,6 +265,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 @@ -840,7 +841,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/NativeInterop/Marshaling.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs index 15b7ce7c73f4..fc68b119322b 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 @@ public static unsafe byte[] ConvertNativePackedByteArrayToSystemArray(in godot_p return array; } - public static unsafe godot_packed_byte_array ConvertSystemArrayToNativePackedByteArray(Span p_array) + public static godot_packed_byte_array ConvertSystemArrayToNativePackedByteArray(Span p_array) + { + return ConvertSystemArrayToNativePackedByteArray((ReadOnlySpan)p_array); + } + + public static unsafe godot_packed_byte_array ConvertSystemArrayToNativePackedByteArray(ReadOnlySpan p_array) { if (p_array.IsEmpty) return new godot_packed_byte_array(); @@ -417,7 +422,12 @@ public static unsafe int[] ConvertNativePackedInt32ArrayToSystemArray(godot_pack return array; } - public static unsafe godot_packed_int32_array ConvertSystemArrayToNativePackedInt32Array(Span p_array) + public static godot_packed_int32_array ConvertSystemArrayToNativePackedInt32Array(Span p_array) + { + return ConvertSystemArrayToNativePackedInt32Array((ReadOnlySpan)p_array); + } + + public static unsafe godot_packed_int32_array ConvertSystemArrayToNativePackedInt32Array(ReadOnlySpan p_array) { if (p_array.IsEmpty) return new godot_packed_int32_array(); @@ -440,7 +450,12 @@ public static unsafe long[] ConvertNativePackedInt64ArrayToSystemArray(godot_pac return array; } - public static unsafe godot_packed_int64_array ConvertSystemArrayToNativePackedInt64Array(Span p_array) + public static godot_packed_int64_array ConvertSystemArrayToNativePackedInt64Array(Span p_array) + { + return ConvertSystemArrayToNativePackedInt64Array((ReadOnlySpan)p_array); + } + + public static unsafe godot_packed_int64_array ConvertSystemArrayToNativePackedInt64Array(ReadOnlySpan p_array) { if (p_array.IsEmpty) return new godot_packed_int64_array(); @@ -463,8 +478,13 @@ public static unsafe float[] ConvertNativePackedFloat32ArrayToSystemArray(godot_ return array; } + public static godot_packed_float32_array ConvertSystemArrayToNativePackedFloat32Array(Span p_array) + { + return ConvertSystemArrayToNativePackedFloat32Array((ReadOnlySpan)p_array); + } + public static unsafe godot_packed_float32_array ConvertSystemArrayToNativePackedFloat32Array( - Span p_array) + ReadOnlySpan p_array) { if (p_array.IsEmpty) return new godot_packed_float32_array(); @@ -487,8 +507,13 @@ public static unsafe double[] ConvertNativePackedFloat64ArrayToSystemArray(godot return array; } + public static godot_packed_float64_array ConvertSystemArrayToNativePackedFloat64Array(Span p_array) + { + return ConvertSystemArrayToNativePackedFloat64Array((ReadOnlySpan)p_array); + } + public static unsafe godot_packed_float64_array ConvertSystemArrayToNativePackedFloat64Array( - Span p_array) + ReadOnlySpan p_array) { if (p_array.IsEmpty) return new godot_packed_float64_array(); @@ -511,6 +536,11 @@ public static unsafe string[] ConvertNativePackedStringArrayToSystemArray(godot_ } public static godot_packed_string_array ConvertSystemArrayToNativePackedStringArray(Span p_array) + { + return ConvertSystemArrayToNativePackedStringArray((ReadOnlySpan)p_array); + } + + public static godot_packed_string_array ConvertSystemArrayToNativePackedStringArray(ReadOnlySpan p_array) { godot_packed_string_array dest = new godot_packed_string_array(); @@ -544,8 +574,13 @@ public static unsafe Vector2[] ConvertNativePackedVector2ArrayToSystemArray(godo return array; } + public static godot_packed_vector2_array ConvertSystemArrayToNativePackedVector2Array(Span p_array) + { + return ConvertSystemArrayToNativePackedVector2Array((ReadOnlySpan)p_array); + } + public static unsafe godot_packed_vector2_array ConvertSystemArrayToNativePackedVector2Array( - Span p_array) + ReadOnlySpan p_array) { if (p_array.IsEmpty) return new godot_packed_vector2_array(); @@ -568,8 +603,13 @@ public static unsafe Vector3[] ConvertNativePackedVector3ArrayToSystemArray(godo return array; } + public static godot_packed_vector3_array ConvertSystemArrayToNativePackedVector3Array(Span p_array) + { + return ConvertSystemArrayToNativePackedVector3Array((ReadOnlySpan)p_array); + } + public static unsafe godot_packed_vector3_array ConvertSystemArrayToNativePackedVector3Array( - Span p_array) + ReadOnlySpan p_array) { if (p_array.IsEmpty) return new godot_packed_vector3_array(); @@ -592,8 +632,13 @@ public static unsafe Vector4[] ConvertNativePackedVector4ArrayToSystemArray(godo return array; } + public static godot_packed_vector4_array ConvertSystemArrayToNativePackedVector4Array(Span p_array) + { + return ConvertSystemArrayToNativePackedVector4Array((ReadOnlySpan)p_array); + } + public static unsafe godot_packed_vector4_array ConvertSystemArrayToNativePackedVector4Array( - Span p_array) + ReadOnlySpan p_array) { if (p_array.IsEmpty) return new godot_packed_vector4_array(); @@ -616,7 +661,12 @@ public static unsafe Color[] ConvertNativePackedColorArrayToSystemArray(godot_pa return array; } - public static unsafe godot_packed_color_array ConvertSystemArrayToNativePackedColorArray(Span p_array) + public static godot_packed_color_array ConvertSystemArrayToNativePackedColorArray(Span p_array) + { + return ConvertSystemArrayToNativePackedColorArray((ReadOnlySpan)p_array); + } + + public static unsafe godot_packed_color_array ConvertSystemArrayToNativePackedColorArray(ReadOnlySpan p_array) { if (p_array.IsEmpty) return new godot_packed_color_array(); diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 4043f3a8c282..0ee52a09a7fe 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 90bfb4c84c87..39cfccf983f9 100644 --- a/scene/2d/skeleton_2d.cpp +++ b/scene/2d/skeleton_2d.cpp @@ -159,7 +159,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; @@ -555,17 +555,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(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; @@ -594,16 +594,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); } @@ -621,7 +621,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; } @@ -733,14 +733,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; } @@ -771,7 +771,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; } @@ -783,7 +783,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); @@ -793,7 +793,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. @@ -804,7 +804,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 033bdff41d6a..16bd6fd34bc3 100644 --- a/scene/2d/skeleton_2d.h +++ b/scene/2d/skeleton_2d.h @@ -123,7 +123,7 @@ class Skeleton2D : public Node2D { bool local_pose_override_persistent = false; }; - Vector bones; + LocalVector 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 86ce8a881a2f..85de85a9a679 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -1181,15 +1181,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; @@ -1198,35 +1199,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 db9c4db30d06..f778fccf0957 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -81,7 +81,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") { @@ -89,7 +89,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); @@ -153,10 +153,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); @@ -182,7 +182,7 @@ bool Skeleton3D::_get(const StringName &p_path, Variant &r_ret) const { } void Skeleton3D::_get_property_list(List *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)); @@ -241,7 +241,7 @@ void Skeleton3D::_update_process_order() { return; } - Bone *bonesptr = bones.ptrw(); + Bone *bonesptr = bones.ptr(); int len = bones.size(); parentless_bones.clear(); @@ -283,7 +283,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 += ","; } @@ -331,14 +331,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(); @@ -412,8 +412,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]); } } @@ -534,7 +534,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++; @@ -582,13 +582,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 { @@ -615,7 +615,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(); @@ -629,11 +629,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; @@ -669,7 +669,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(); } @@ -692,7 +692,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(); } @@ -727,10 +727,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(); } @@ -740,8 +740,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(); } @@ -750,8 +750,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(); } @@ -760,8 +760,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(); } @@ -794,7 +794,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); } } @@ -802,7 +802,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(this)->bones.write[p_bone].update_pose_cache(); + const_cast(this)->bones[p_bone].update_pose_cache(); return bones[p_bone].pose_cache; } @@ -853,7 +853,7 @@ Ref 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 bones_to_process; @@ -877,7 +877,7 @@ Ref 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()); @@ -937,7 +937,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 bones_to_process; bones_to_process.clear(); bones_to_process.push_back(p_bone_idx); @@ -1171,9 +1171,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(); } @@ -1181,9 +1181,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 07bdeccf2f76..7213dc580cb6 100644 --- a/scene/3d/skeleton_3d.h +++ b/scene/3d/skeleton_3d.h @@ -153,7 +153,7 @@ class Skeleton3D : public Node3D { HashSet skin_bindings; void _skin_changed(); - Vector bones; + LocalVector bones; bool process_order_dirty = false; Vector parentless_bones; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 9df009ec28c3..ecc1982aa5ef 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -382,14 +382,11 @@ void ShaderMaterial::_get_property_list(List *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 18975320f7dc..0d468ad1e322 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -2185,7 +2185,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); @@ -2219,7 +2219,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]; @@ -2270,8 +2270,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 6784520d17e3..322f3cc6f4b1 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h @@ -312,7 +312,7 @@ class MeshStorage : public RendererMeshStorage { struct Skeleton { bool use_2d = false; int size = 0; - Vector data; + LocalVector data; RID buffer; bool dirty = false;