Compare commits

..

95 commits

Author SHA1 Message Date
Rémi Verschelde
f62fdbde15 Bump version to 4.5.1-stable 2025-10-13 21:05:40 +02:00
Rémi Verschelde
8522dfd066 Add changelog for 4.5.1 2025-10-13 21:04:59 +02:00
Pāvels Nadtočajevs
41acf6a75d Fix iOS/visionOS export plugin crash on exit.
(cherry picked from commit 906aff5331)
2025-10-13 21:02:39 +02:00
Rémi Verschelde
d3b052df8f
Merge pull request #111472 from akien-mga/4.5-cherrypicks
[4.5] Cherry-picks for the 4.5 branch (future 4.5.1) - 4th batch
2025-10-10 13:01:22 +02:00
Anish Mishra
d632731ba8
Android: Only validate keystore relevant to current export mode
- Debug builds skip release keystore validation.
- Release builds skip debug keystore validation.

(cherry picked from commit 097ccbc5cd)
2025-10-10 11:07:41 +02:00
Pāvels Nadtočajevs
eb7c869f84
[macOS] Remove old embedded window joystick init code.
(cherry picked from commit 77dd83efbf)
2025-10-10 11:06:47 +02:00
Artemy Fedotov
183f6cdd63
Fix favorite folders that are outside of the project being displayed in FileSystemDock's file list
(cherry picked from commit 8d137bcd29)
2025-10-10 11:04:56 +02:00
Artemy Fedotov
83a78186ca
Fix crash due to null pointer dereference when moving/renaming folders in FileSystemDock
(cherry picked from commit 4e3a39a2e8)
2025-10-10 11:04:36 +02:00
Rémi Verschelde
1c078fee01
SCons: Don't activate fast_unsafe automatically on dev_build
We experienced first hand why it's called unsafe, and so we should leave it
as an explicit choice for contributors, informing themselves of the caveats.

See #111408.

(cherry picked from commit fa57282a1e)
2025-10-10 11:03:16 +02:00
kobewi
07596299e6
Enable script templates by default
(cherry picked from commit a299004622)
2025-10-10 11:02:15 +02:00
Fredia Huya-Kouadio
ce8f9dfea8
Fix the bug causing java.lang.StringIndexOutOfBoundsException crashes when showing the virtual keyboard
(cherry picked from commit ff3eee7df6)
2025-10-10 11:00:26 +02:00
Rémi Verschelde
e146c46214
Merge pull request #111438 from Kaleb-Reid/fix-screen-texture-4.5
[4.5] Fix uniform name for luminance multiplier in shader compiler
2025-10-09 10:38:22 +02:00
Kaleb Reid
d18aaaa5d3 Fix uniform name for luminance multiplier in shader compiler 2025-10-08 22:20:41 -07:00
Thaddeus Crews
69796bf7d6
Merge pull request #111388 from akien-mga/4.5-cherrypicks
[4.5] Cherry-picks for the 4.5 branch (future 4.5.1) - 3rd batch
2025-10-07 20:38:07 -05:00
Stuart Carnie
7f9232c84e
MacOS: Move includes inside #ifdef so OpenGL can be disabled
(cherry picked from commit 94c7c2b780)
2025-10-08 02:27:36 +02:00
Nintorch
1d50fc26b4
Fix invalid reported joypad presses
(cherry picked from commit 4a3bf069a6)
2025-10-08 02:27:22 +02:00
Kaleb Reid
b891558050
Fix compiling SDL without DBus under Linux
(cherry picked from commit 03eb42642c)
2025-10-08 02:26:37 +02:00
Hugo Locurcio
bcd06b478a
Tweak macOS notarization export message in the editor
One message had a typo and was missing `--team-id` for one of the
`xcrun notarytool` commands.

(cherry picked from commit 020cdd0f73)
2025-10-08 02:26:24 +02:00
Allen Pestaluky
29f8d9f504
Fix glow intensity not showing in compatibility renderer when blend mode is set to mix.
(cherry picked from commit 3101d75634)
2025-10-08 02:25:40 +02:00
Anish Mishra
d92413782b
Fix bottom panel being unintentionally draggable
(cherry picked from commit f7e052a456)
2025-10-08 02:22:53 +02:00
Jorrit Rouwe
a3b924766d
Fix Generic6DOFJoint3D not respecting angular limits
A 6DOF constraint that constrains all rotation axis in combination with a body that has some of its rotation axis locked would not constrain the rotation in the unlocked axis.

Fixes #109018

(cherry picked from commit 9bb8d12c1b)
2025-10-08 02:22:53 +02:00
kobewi
0234028f7c
Fix Quick Open history
(cherry picked from commit be53dd3d04)
2025-10-08 02:22:53 +02:00
Pāvels Nadtočajevs
a5fa61bcfe
Fix text servers build with disabled FreeType.
(cherry picked from commit e59a55e645)
2025-10-08 02:22:53 +02:00
Silc Lizard (Tokage) Renew
670c0707a7
Make extended SkeletonModifiers retrieve interpolated global transform
(cherry picked from commit f3db297fd1)
2025-10-08 02:22:53 +02:00
Paeniche
368f0c75c3
Fix /tutorial added twice
Some links in the offlince documentation for lights and shadows had /tutorials/tutorials in their links leading to 'page not found' error

(cherry picked from commit 0b7b52a1f1)
2025-10-08 02:22:53 +02:00
Hugo Locurcio
33b6898494
Fix and improve Node2D.move_local_{x,y}() description
The `delta` parameter name refers to a generic distance parameter here,
rather than the process or physics process time.

(cherry picked from commit f277add285)
2025-10-08 02:16:14 +02:00
Ricardo Buring
25415a831e
OBJ importer: Support bump multiplier (normal scale)
This improves compatibility with OBJ/MTL files found in the wild.

(cherry picked from commit 2f3eaa965c)
2025-10-08 02:15:32 +02:00
Mikael Hermansson
ccf3976dc5
Fix crash when calling move_and_collide with a null jolt_body
(cherry picked from commit a285ab6bcf)
2025-10-08 02:15:10 +02:00
Pāvels Nadtočajevs
48466413c1
Change macos.permission.RECORD_SCREEN version check from 10.15 to 11.0.
(cherry picked from commit 1c59038555)
2025-10-08 02:14:36 +02:00
Mara Huldra
b0a2063d8f
wayland: Inhibit idle in DisplayServerWayland::screen_set_keep_on
Without this, the screen does go into idle after a few minutes on a RPi5 with default install (wayland w/ labwc), even
though `screen_keep_on` is set. DBUS is enabled but apparently, the screensaver call is not enough.

(cherry picked from commit c64ff4b069)
2025-10-08 02:14:12 +02:00
Ruw
24bc49d557
SCons: Fix Windows silence_msvc logfile encoding
Fix UnicodeEncodeError on cp932 environments by adding errors="replace" to log file open.

(cherry picked from commit b23b0dde9a)
2025-10-08 02:12:47 +02:00
Hugo Locurcio
e788127654
Fix DPITexture editor icon name
It was still using its previous name from 4.5 development.

(cherry picked from commit d824e79fc0)
2025-10-08 02:11:17 +02:00
Silc Lizard (Tokage) Renew
9058a406ea
Fix Reset on Save corrupt poses if scene has multiple Skeletons
(cherry picked from commit 8df06279c6)
2025-10-08 02:10:41 +02:00
Kaleb Reid
d841779578
Divide screen texture by luminance multiplier in compatibility
(cherry picked from commit 8ad335eae0)
2025-10-08 02:09:29 +02:00
Pāvels Nadtočajevs
5bd344b259
Add column boundary check in the autocompletion.
(cherry picked from commit 1c50f8660a)
2025-10-08 02:08:43 +02:00
Pāvels Nadtočajevs
2d7f6f32ce
Enforce zero width spaces and joiners with missing font. Do not warn about missing non-visual characters.
(cherry picked from commit fda161f976)
2025-10-08 02:06:26 +02:00
Thaddeus Crews
3ac14dfe01
Revert "SCons: Add CPPEXTPATH for external includes"
(cherry picked from commit b17aa3343a)
2025-10-08 02:04:05 +02:00
Haoyu Qiu
0e179c0e5c
Editor: Generate translation data in separate cpp files
(cherry picked from commit c93f55533d)
2025-10-08 02:01:04 +02:00
Rémi Verschelde
42ef49fa99
Linux: Allow unbundling libjpeg-turbo to use system package
(cherry picked from commit 6d8aa8582f)
2025-10-08 01:56:58 +02:00
Pāvels Nadtočajevs
9d08253661
[Windows] Fix application manifest in exported projects with modified resources.
(cherry picked from commit 91fc0c3756)
2025-10-08 01:48:56 +02:00
Michael Alexsander
632d29232b
Fix selection of remote tree using the keyboard
(cherry picked from commit 53231879b3)
2025-10-08 01:48:46 +02:00
kobewi
90d1d9e957
Set correct saved history after clearing
(cherry picked from commit ea452f2de5)
2025-10-08 01:48:35 +02:00
Silc Lizard (Tokage) Renew
f12cc7a014
Fix backward root motion in AnimationTree
(cherry picked from commit 749d9b95b9)
2025-10-08 01:48:25 +02:00
Pāvels Nadtočajevs
95d452fad9
[macOS] Always use "Regular" activation policy for GUI, and headless main loop for command line only tools.
(cherry picked from commit 6e76a9467f)
2025-10-08 01:48:12 +02:00
Riteo
c4a375ca55
Wayland: Emulate frame event for old wl_seat versions
Multiwindow support simplified input handling by processing all data
only during a `wl_seat::frame` event, which got introduced in wl_seat
version 5. If the compositor reports an older version, we manually call
the frame event handler.

(cherry picked from commit 2e41412ee4)
2025-10-08 01:47:54 +02:00
Rémi Verschelde
452332621f
Revert "Initialize Quaternion variant with identity"
This reverts commit a52de93373.

This may be correct, but it breaks compatibility so it shouldn't be
cherry-picked to stable branches.
2025-10-08 01:47:13 +02:00
Yufeng Ying
a156af98c3
Remove dependency of variant.h in print_string.h
(cherry picked from commit 05dae23f18)
Co-Authored-By: Lukas Tenbrink <lukas.tenbrink@gmail.com>
Co-Authored-By: A Thousand Ships <96648715+AThousandShips@users.noreply.github.com>
2025-10-06 12:17:32 -05:00
Lukas Tenbrink
28f4d5d6a7
Change "reserve called with a capacity smaller than the current size" error message to a verbose message.
(cherry picked from commit c6f57c7a55)
2025-10-06 10:40:25 -05:00
Artemy Fedotov
fb9d73438d
Fix LineEdit's placeholder text being selected when double clicking
(cherry picked from commit 40d56c98bc)
2025-10-06 10:36:29 -05:00
Mounir Tohami
b70ddd29a0
Fix Redundant calls of CIE _update_lock_and_group_button on SceneTree selection.
(cherry picked from commit 320ff6bc75)
2025-10-06 10:36:25 -05:00
Haoyu Qiu
8a9ef4a891
Unix: Fix retrieval of PID exit code
(cherry picked from commit d5738b5cdd)
2025-10-06 10:36:21 -05:00
Nintorch
d72311f6ae
Fix weak and strong joy vibration being swapped
(cherry picked from commit e5ecc392c9)
2025-10-06 10:36:18 -05:00
BlueCube3310
dd92108759
Fix LightmapGI not being correctly applied to objects
(cherry picked from commit 24ed12d4a3)
2025-10-06 10:36:14 -05:00
DeeJayLSP
0990896d91
Editor font: do not embolden the Main Font if it's variable
(cherry picked from commit d719fc74f5)
2025-10-06 10:36:10 -05:00
Pāvels Nadtočajevs
f5b146cc61
[TextServer] Enforce zero width spaces and joiners to actually be zero width and not fallback to regular space.
(cherry picked from commit 3f84820711)
2025-10-06 10:36:07 -05:00
风青山
3f97c33dac
Fix the project file was not updated when some files were removed
(cherry picked from commit 54dff9228c)
2025-10-06 10:36:04 -05:00
Artemy Fedotov
e6cf63cb88
GridMap: fix cell scale not applying to the cursor mesh
(cherry picked from commit d1f11b2b28)
2025-10-06 10:35:58 -05:00
HolonProduction
1aed7cefdd
LSP: Fix repeated restart attempts
(cherry picked from commit 400c77f170)
2025-10-06 09:51:41 -05:00
David Snopek
2cb6d30dd1
GDExtension: Prevent breaking compatibility for unexposed classes that can only be created once
(cherry picked from commit 2c707a911f)
2025-10-06 09:51:30 -05:00
Stuart Carnie
c834443ef1
Metal: Fix Metal compiler version inspection
(cherry picked from commit d93fe9038d)
2025-09-30 11:36:49 -05:00
Kaleb Reid
899ef8df88
Sort render list correctly in RD renderers
(cherry picked from commit 5021b3e6e5)
2025-09-30 11:36:45 -05:00
Jonas Seidl
eed94508f0
Fix d3d12 stencil buffer not clearing
(cherry picked from commit d1246b099e)
2025-09-30 11:36:41 -05:00
Mikael Hermansson
da0c3122f1
Fix CCD bodies adding multiple contact manifolds when using Jolt
(cherry picked from commit 0590c974c1)
2025-09-30 11:36:37 -05:00
Bryce Hutchings
757dbe621f
Remove static lifetime object to avoid late destruction
(cherry picked from commit cd198f7517)
2025-09-30 11:36:33 -05:00
Bryce Hutchings
6c180272b4
Fix D3D12 using the wrong clip space projection matrix. Remove error-prone/unnecessary graphicsApi parameter.
(cherry picked from commit 58ecb8ade5)
2025-09-30 11:36:30 -05:00
smix8
354b02f92d
Make navmesh rasterization errors more lenient
Make navmesh rasterization on the navigation regions and map more lenient by starting out with a lower internal cell scale by default and changing the merge error to just warning that can be toggled.

(cherry picked from commit 19df15f1dc)
2025-09-30 11:36:26 -05:00
A Thousand Ships
b963cf15ef
[Navigation 2D] Fix sign of cross product
Regression from splitting the servers. Also replaces the method for
getting the triangle area.

(cherry picked from commit f8d72ba783)
2025-09-30 11:36:23 -05:00
vaner-org
0f17c184e4
Fix accessibility name errors in BlendSpace2D editor
(cherry picked from commit 22e67735f1)
2025-09-30 11:36:19 -05:00
Hugo Locurcio
50aad8e62b
Disable unsupported SSR, SSS, DoF on transparent viewports
For technical reasons, transparent viewports cannot support
screen-space reflections, subsurface scattering and depth of field.
Previously, enabling any of these would turn transparent viewports
invisible.

(cherry picked from commit 1c62ba40b7)
2025-09-30 11:36:16 -05:00
ydeltastar
25ed1b3811
Android: Ensure proper cleanup of the fragment
(cherry picked from commit 6a3d37ef1c)
2025-09-30 11:36:12 -05:00
João Pedro Xavier
9166e4d5a7
Fix bug where material with double-sided shadows ignores backface culling on compatibility renderer
(cherry picked from commit d6aca93c1a)
2025-09-30 11:36:08 -05:00
detomon
a52de93373
Initialize Quaternion variant with identity
(cherry picked from commit c0e36dc493)
2025-09-30 11:36:02 -05:00
Thaddeus Crews
1e743ad0ab
Windows: Migrate godot.manifest to platform/windows
• Ensure file is included as proper dependency

(cherry picked from commit d48f255074)
2025-09-30 11:35:57 -05:00
Rémi Verschelde
eca3785100
makerst: Skip generated header for translations
This reduces diff size on branch updates for godot-docs-l10n.
2025-09-30 13:27:18 +02:00
Rémi Verschelde
d488e962df
i18n: Sync translations with Weblate 2025-09-30 13:08:27 +02:00
Quentin Quaadgras
928ee70231
add codeblock indentation back to --dump-extension-api-with-docs
xml codeblock indentation was changed from spaces to tabs but the tabs
were being replaced with empty strings when exported with
--dump-extension-api-with-docs, this is small change so that tab
characters are no longer replaced.

(cherry picked from commit e9131550b1)
2025-09-22 08:31:16 -05:00
Lukas Tenbrink
777649d574
Check for NUL characters in string parsing functions.
(cherry picked from commit 0d700e53f3)
2025-09-22 08:31:13 -05:00
clayjohn
79dd13f6fb
Move check for sky cubemap array back into the SkyRD initializer so it is set before being used.
Previously it was moved out of this function becuase we relied on RenderingServer::get_video_adapter_name which wasn't available yet.

However, that was unnecessary since it is just a wrapper around RenderingDevice::get_device_name() which is available.

(cherry picked from commit fc951855ed)
2025-09-22 08:31:06 -05:00
Mounir Tohami
cb878d90a2
X11 input: prevent non-printable keys from producing empty Strings
(cherry picked from commit 1b697aff38)
2025-09-22 08:31:02 -05:00
Roman Goldman
6bf74272f9
Fix Basis.determinant() doc: uniform scale determinant is scale^3, not scale^2
Corrected a documentation mistake in Basis.determinant(). For a uniform scale basis, the determinant is scale^3, not scale^2.

(cherry picked from commit 6379874180)
2025-09-22 08:30:59 -05:00
Roland Marchand
6f121b29b9
Specified delta interaction in CharacterBody docs
(cherry picked from commit bee392fcd2)
2025-09-22 08:30:55 -05:00
Hugo Locurcio
4aedc06168
Document typed dictionaries and arrays in the class reference
(cherry picked from commit b6dcb111d2)
2025-09-22 08:30:50 -05:00
Hugo Locurcio
49d2dbc027
Document the interaction between Light3D cull mask and GI/volumetric fog
(cherry picked from commit 9317c8eb23)
2025-09-22 08:30:39 -05:00
Arti Chhabra
68ea3d8aad
Corrected the order of DiagonalMode in Add Property
(cherry picked from commit 6a288c9275)
2025-09-16 09:57:28 -05:00
Giganzo
168f401db6
Fix LineEdit icon positon in right-to-left layout
(cherry picked from commit fbf27dbfc6)
2025-09-16 09:57:24 -05:00
Pāvels Nadtočajevs
9abec0666e
[Windows] Try reading GPU driver information directly from registry.
(cherry picked from commit 9f8626ccaa)
2025-09-16 09:57:20 -05:00
Colin O'Rourke
0f760c7c97
Material Conversion Error Handling
Material Conversion Plugins now ERR_FAIL if called on an unitialized material.

FileSystemDock no longer crashes if Conversion Plugin fails and returns a null ref.

(cherry picked from commit 05fd79af7c)
2025-09-16 09:57:16 -05:00
Patrick Gelvin
35833f8dbf
Workaround X11 crash issue
(cherry picked from commit 6842a5861b)
2025-09-16 09:57:11 -05:00
Bastiaan Olij
fcd2ab70e0
OpenXR: Fix ViewportTextures not displaying correct texture (Compatibility)
(cherry picked from commit a38256c19e)
2025-09-16 09:57:07 -05:00
Lukas Rahmann
acab46d09e
Add descriptor heap pooling to D3D12.
(cherry picked from commit f7fd65923a)
2025-09-16 09:57:04 -05:00
Jorrit Rouwe
11e6e4afef
Fixed bug in ManifoldBetweenTwoFaces
Fixed bug in ManifoldBetweenTwoFaces which would not find the correct manifold in case face 1 had 3 or more vertices and face 2 only 2. E.g. for a box resting the long edge of a cylinder this would mean that only a single contact point was found instead of 2 (the other way around would work fine).

Fixes godotengine/godot#110479

(cherry picked from commit 1daf9893ec)
2025-09-16 09:57:00 -05:00
aaronp64
4e62b91749
Avoid repeated _copy_on_write() calls in Array::resize()
Updated Array::resize() to call ptrw() once before looping to initialize typed array elements, instead of accessing each through .write[].

(cherry picked from commit 4c3f2be16d)
2025-09-16 09:56:56 -05:00
DeeJayLSP
63b1d72795
Add one padding frame to QOA buffer for short streams
(cherry picked from commit af5a81faf8)
2025-09-16 09:56:52 -05:00
clayjohn
e13771d562
Increase precision of SpotLight attenuation calculation to avoid driver bug on Intel devices
(cherry picked from commit 0576b12699)
2025-09-16 09:56:48 -05:00
Thaddeus Crews
7176fc231f
Bump version to 4.5.1-rc 2025-09-15 15:56:44 -05:00
1954 changed files with 24137 additions and 51894 deletions

24
.github/CODEOWNERS vendored
View file

@ -45,6 +45,8 @@
# Editor
/editor/ @godotengine/docks
/editor/script/ @godotengine/script-editor
/editor/shader/ @godotengine/script-editor @godotengine/shaders
/editor/animation/ @godotengine/animation
/editor/audio/ @godotengine/audio
/editor/debugger/ @godotengine/debugger
@ -55,12 +57,10 @@
/editor/import/ @godotengine/import
/editor/inspector/ @godotengine/docks
/editor/scene/2d/ @godotengine/2d-editor
/editor/scene/2d/physics/ @godotengine/2d-editor @godotengine/physics
/editor/scene/2d/physics @godotengine/2d-editor @godotengine/physics
/editor/scene/3d/ @godotengine/3d-editor
/editor/scene/3d/physics/ @godotengine/3d-editor @godotengine/physics
/editor/scene/3d/physics @godotengine/3d-editor @godotengine/physics
/editor/scene/gui/ @godotengine/gui-nodes
/editor/script/ @godotengine/script-editor
/editor/shader/ @godotengine/script-editor @godotengine/shaders
/editor/themes/ @godotengine/usability @godotengine/gui-nodes
/editor/translations/ @godotengine/usability
@ -205,12 +205,9 @@
# Scene
/scene/2d/ @godotengine/2d-nodes
/scene/2d/navigation/ @godotengine/2d-nodes @godotengine/navigation
/scene/2d/physics/ @godotengine/2d-nodes @godotengine/physics
/scene/3d/ @godotengine/3d-nodes
/scene/3d/navigation/ @godotengine/3d-nodes @godotengine/navigation
/scene/3d/physics/ @godotengine/3d-nodes @godotengine/physics
/scene/3d/xr/ @godotengine/3d-nodes @godotengine/xr
/scene/animation/ @godotengine/animation
/scene/audio/ @godotengine/audio
/scene/debugger/ @godotengine/debugger
@ -230,13 +227,18 @@
# Servers
/servers/**/audio_* @godotengine/audio
/servers/**/camera_* @godotengine/xr
/servers/**/debugger_* @godotengine/debugger
/servers/**/navigation_* @godotengine/navigation
/servers/**/physics_* @godotengine/physics
/servers/**/rendering_* @godotengine/rendering
/servers/**/text_* @godotengine/gui-nodes
/servers/**/xr_* @godotengine/xr
/servers/audio/ @godotengine/audio
/servers/camera/ @godotengine/xr
/servers/debugger/ @godotengine/debugger
/servers/navigation_2d/ @godotengine/navigation
/servers/navigation_3d/ @godotengine/navigation
/servers/physics_2d/ @godotengine/physics
/servers/physics_3d/ @godotengine/physics
/servers/navigation/ @godotengine/navigation
/servers/rendering/ @godotengine/rendering
/servers/text/ @godotengine/gui-nodes
/servers/xr/ @godotengine/xr

View file

@ -10,7 +10,7 @@ inputs:
default: x64
scons-version:
description: The SCons version to use.
default: 4.10.0
default: 4.9.0
runs:
using: composite

View file

@ -26,14 +26,14 @@ jobs:
arch=arm64
production=yes
- name: Template arm32 (target=template_debug, arch=arm32)
- name: Template arm32 (target=template_release, arch=arm32)
cache-name: android-template-arm32
target: template_debug
target: template_release
scons-flags: arch=arm32
- name: Template arm64 (target=template_debug, arch=arm64)
- name: Template arm64 (target=template_release, arch=arm64)
cache-name: android-template-arm64
target: template_debug
target: template_release
scons-flags: arch=arm64
steps:
@ -82,7 +82,7 @@ jobs:
continue-on-error: true
- name: Generate Godot templates
if: matrix.target == 'template_debug'
if: matrix.target == 'template_release'
run: |
cd platform/android/java
./gradlew generateGodotTemplates

View file

@ -8,7 +8,7 @@ env:
dev_mode=yes
module_text_server_fb_enabled=yes
"accesskit_sdk_path=${{ github.workspace }}/accesskit-c-0.17.0/"
GODOT_CPP_BRANCH: 4.5
GODOT_CPP_BRANCH: 4.4
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: true
ASAN_OPTIONS: color=always:print_suppressions=1:suppressions=${{ github.workspace }}/misc/error_suppressions/asan.txt

2
.gitignore vendored
View file

@ -217,7 +217,7 @@ xcuserdata/
*.xcscmblueprint
*.xccheckout
*.xcodeproj/*
!misc/misc/dist/apple_embedded_xcode/godot.xcodeproj/project.pbxproj
!misc/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
# Zed
.zed/

View file

@ -34,9 +34,9 @@ repos:
stages: [manual] # Not automatically triggered, invoked via `pre-commit run --hook-stage manual clang-tidy`
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.13.1
rev: v0.12.0
hooks:
- id: ruff-check
- id: ruff
args: [--fix]
files: (\.py|SConstruct|SCsub)$
types_or: [text]

View file

@ -7,6 +7,157 @@ previous feature release. It is equivalent to the listings on our
Changelogs for earlier feature releases are available in their respective Git
branches, and linked at the [end of this file](#Past-releases).
## 4.5 - 2025-10-13
- [Release announcement](https://godotengine.org/article/maintenance-release-godot-4-5-1)
- [Interactive changelog](https://godotengine.github.io/godot-interactive-changelog/#4.5.1)
#### 2D
- Fix redundant calls of `CanvasItemEditor::_update_lock_and_group_button` on `SceneTreeEditor` node selection ([GH-110320](https://github.com/godotengine/godot/pull/110320)).
#### 3D
- GridMap: fix cell scale not applying to the cursor mesh ([GH-104510](https://github.com/godotengine/godot/pull/104510)).
#### Animation
- Fix Reset on Save corrupt poses if scene has multiple Skeletons ([GH-110506](https://github.com/godotengine/godot/pull/110506)).
- Fix backward/pingpong root motion in AnimationTree ([GH-110982](https://github.com/godotengine/godot/pull/110982)).
- Make extended SkeletonModifiers retrieve interpolated global transform ([GH-110987](https://github.com/godotengine/godot/pull/110987)).
#### Audio
- Add one padding frame to QOA buffer for short streams ([GH-110515](https://github.com/godotengine/godot/pull/110515)).
#### Buildsystem
- Linux: Allow unbundling libjpeg-turbo to use system package ([GH-110540](https://github.com/godotengine/godot/pull/110540)).
- Editor: Generate translation data in separate cpp files ([GH-110618](https://github.com/godotengine/godot/pull/110618)).
- SCons: Fix Windows `silence_msvc` logfile encoding ([GH-110691](https://github.com/godotengine/godot/pull/110691)).
- Windows: Migrate `godot.manifest` to `platform/windows`, include as dependency ([GH-110897](https://github.com/godotengine/godot/pull/110897)).
- Fix compiling SDL without DBus under Linux ([GH-111146](https://github.com/godotengine/godot/pull/111146)).
- macOS: Move includes inside `#ifdef` so OpenGL can be disabled ([GH-111301](https://github.com/godotengine/godot/pull/111301)).
- SCons: Don't activate `fast_unsafe` automatically on `dev_build` ([GH-111411](https://github.com/godotengine/godot/pull/111411)).
#### Codestyle
- Remove dependency of `variant.h` in `print_string.h` ([GH-107721](https://github.com/godotengine/godot/pull/107721)).
#### Core
- Initialize `Quaternion` variant with identity ([GH-84658](https://github.com/godotengine/godot/pull/84658)).
- Avoid repeated `_copy_on_write()` calls in `Array::resize()` ([GH-110535](https://github.com/godotengine/godot/pull/110535)).
- Check for `NUL` characters in string parsing functions ([GH-110556](https://github.com/godotengine/godot/pull/110556)).
- X11 input: prevent non-printable keys from producing empty strings ([GH-110635](https://github.com/godotengine/godot/pull/110635)).
- Change "reserve called with a capacity smaller than the current size" error message to a verbose message ([GH-110826](https://github.com/godotengine/godot/pull/110826)).
#### Documentation
- Document typed dictionaries and arrays in the class reference ([GH-107071](https://github.com/godotengine/godot/pull/107071)).
- Clarify that velocity doesn't need delta multiplication in CharacterBody documentation ([GH-109925](https://github.com/godotengine/godot/pull/109925)).
- Document the interaction between Light3D cull mask and GI/volumetric fog ([GH-110423](https://github.com/godotengine/godot/pull/110423)).
- Fix Basis.determinant() doc: uniform scale determinant is scale^3 ([GH-110424](https://github.com/godotengine/godot/pull/110424)).
- Fix and improve `Node2D.move_local_{x,y}()` description ([GH-110878](https://github.com/godotengine/godot/pull/110878)).
- Fix /tutorial added twice in offline docs ([GH-110881](https://github.com/godotengine/godot/pull/110881)).
#### Editor
- Correct the order of Diagonal Mode in Add Property ([GH-109214](https://github.com/godotengine/godot/pull/109214)).
- Fix typos in BlendSpace2D editor's axis labels' accessibility names ([GH-109847](https://github.com/godotengine/godot/pull/109847)).
- Add column boundary check in the autocompletion ([GH-110017](https://github.com/godotengine/godot/pull/110017)).
- Fix favorite folders that are outside of the project being displayed in `FileSystemDock`'s file list ([GH-110415](https://github.com/godotengine/godot/pull/110415)).
- Fix crash due to null pointer dereference when moving/renaming folders in `FileSystemDock` ([GH-110420](https://github.com/godotengine/godot/pull/110420)).
- Fix the project file was not updated when some files were removed ([GH-110576](https://github.com/godotengine/godot/pull/110576)).
- Fix DPITexture editor icon name ([GH-110661](https://github.com/godotengine/godot/pull/110661)).
- Fix selection of remote tree using the keyboard ([GH-110738](https://github.com/godotengine/godot/pull/110738)).
- Tweak macOS notarization export message in the editor ([GH-110793](https://github.com/godotengine/godot/pull/110793)).
- Fix Quick Open history ([GH-111068](https://github.com/godotengine/godot/pull/111068)).
- Set correct saved history after clearing ([GH-111136](https://github.com/godotengine/godot/pull/111136)).
- Cherry-picks for the 4.5 branch (future 4.5.1) - 3rd batch ([GH-111388](https://github.com/godotengine/godot/pull/111388)).
- Enable script templates by default ([GH-111454](https://github.com/godotengine/godot/pull/111454)).
#### Export
- Android: Only validate keystore relevant to current export mode ([GH-109568](https://github.com/godotengine/godot/pull/109568)).
- Android: Ensure proper cleanup of the fragment ([GH-109764](https://github.com/godotengine/godot/pull/109764)).
- iOS/visionOS: Fix export plugin crash on exit ([GH-110485](https://github.com/godotengine/godot/pull/110485)).
- Metal: Fix Metal compiler version inspection ([GH-110873](https://github.com/godotengine/godot/pull/110873)).
- Windows: Fix application manifest in exported projects with modified resources ([GH-111316](https://github.com/godotengine/godot/pull/111316)).
#### GDExtension
- Fix `--dump-extension-api-with-docs` indentation ([GH-110557](https://github.com/godotengine/godot/pull/110557)).
- Prevent breaking compatibility for unexposed classes that can only be created once ([GH-111090](https://github.com/godotengine/godot/pull/111090)).
#### GDScript
- LSP: Fix repeated restart attempts ([GH-111290](https://github.com/godotengine/godot/pull/111290)).
#### GUI
- Fix LineEdit icon position in right-to-left layout ([GH-109363](https://github.com/godotengine/godot/pull/109363)).
- Editor font: do not embolden the Main Font if it's variable ([GH-110737](https://github.com/godotengine/godot/pull/110737)).
- Fix LineEdit's placeholder text being selected when double clicking ([GH-110886](https://github.com/godotengine/godot/pull/110886)).
- Fix text servers build with disabled FreeType ([GH-111001](https://github.com/godotengine/godot/pull/111001)).
- TextServer: Enforce zero width spaces and joiners to actually be zero width and not fallback to regular space ([GH-111014](https://github.com/godotengine/godot/pull/111014)).
- Fix bottom panel being unintentionally draggable ([GH-111121](https://github.com/godotengine/godot/pull/111121)).
- Enforce zero width spaces and joiners with missing font. Do not warn about missing non-visual characters ([GH-111355](https://github.com/godotengine/godot/pull/111355)).
#### Import
- Material Conversion Error Handling ([GH-109369](https://github.com/godotengine/godot/pull/109369)).
- OBJ importer: Support bump multiplier (normal scale) ([GH-110925](https://github.com/godotengine/godot/pull/110925)).
#### Input
- macOS: Remove old embedded window joystick init code ([GH-110491](https://github.com/godotengine/godot/pull/110491)).
- Fix the bug causing `java.lang.StringIndexOutOfBoundsException` crashes when showing the virtual keyboard ([GH-110611](https://github.com/godotengine/godot/pull/110611)).
- Fix weak and strong joypad vibration being swapped ([GH-111191](https://github.com/godotengine/godot/pull/111191)).
- Fix invalid reported joypad presses ([GH-111192](https://github.com/godotengine/godot/pull/111192)).
#### Navigation
- [Navigation 2D] Fix sign of cross product ([GH-110815](https://github.com/godotengine/godot/pull/110815)).
- Make navmesh rasterization errors more lenient ([GH-110841](https://github.com/godotengine/godot/pull/110841)).
#### Physics
- Fix bug in ManifoldBetweenTwoFaces ([GH-110507](https://github.com/godotengine/godot/pull/110507)).
- Fix CCD bodies adding multiple contact manifolds when using Jolt ([GH-110914](https://github.com/godotengine/godot/pull/110914)).
- Fix crash when calling `move_and_collide` with a null `jolt_body` ([GH-110964](https://github.com/godotengine/godot/pull/110964)).
- JoltPhysics: Fix Generic6DOFJoint3D not respecting angular limits ([GH-111087](https://github.com/godotengine/godot/pull/111087)).
#### Porting
- Wayland: Emulate frame event for old `wl_seat` versions ([GH-105587](https://github.com/godotengine/godot/pull/105587)).
- Workaround X11 crash issue ([GH-106798](https://github.com/godotengine/godot/pull/106798)).
- macOS: Always use "Regular" activation policy for GUI, and headless main loop for command line only tools ([GH-109795](https://github.com/godotengine/godot/pull/109795)).
- Wayland: Inhibit idle in DisplayServerWayland::screen_set_keep_on ([GH-110875](https://github.com/godotengine/godot/pull/110875)).
- Change `macos.permission.RECORD_SCREEN` version check from 10.15 to 11.0 ([GH-110936](https://github.com/godotengine/godot/pull/110936)).
- Unix: Fix retrieval of PID exit code ([GH-111058](https://github.com/godotengine/godot/pull/111058)).
#### Rendering
- DirectX DescriptorsHeap pooling on CPU ([GH-106809](https://github.com/godotengine/godot/pull/106809)).
- Disable unsupported SSR, SSS, DoF on transparent viewports ([GH-108206](https://github.com/godotengine/godot/pull/108206)).
- Windows: Try reading GPU driver information directly from registry ([GH-109346](https://github.com/godotengine/godot/pull/109346)).
- Compatibility: Fix backface culling gets ignored when double-sided shadows are used ([GH-109793](https://github.com/godotengine/godot/pull/109793)).
- OpenXR: Fix ViewportTextures not displaying correct texture (OpenGL) ([GH-110002](https://github.com/godotengine/godot/pull/110002)).
- Divide screen texture by luminance multiplier in compatibility ([GH-110004](https://github.com/godotengine/godot/pull/110004)).
- Increase precision of SpotLight attenuation calculation to avoid driver bug on Intel devices ([GH-110363](https://github.com/godotengine/godot/pull/110363)).
- Move check for sky cubemap array back into the SkyRD initializer ([GH-110627](https://github.com/godotengine/godot/pull/110627)).
- Fix glow intensity not showing in compatibility renderer ([GH-110843](https://github.com/godotengine/godot/pull/110843)).
- Fix OpenXR with D3D12 using the wrong clip space projection matrix ([GH-110865](https://github.com/godotengine/godot/pull/110865)).
- Fix d3d12 stencil buffer not clearing ([GH-111032](https://github.com/godotengine/godot/pull/111032)).
- Sort render list correctly in RD renderers ([GH-111054](https://github.com/godotengine/godot/pull/111054)).
- Fix LightmapGI not being correctly applied to objects ([GH-111125](https://github.com/godotengine/godot/pull/111125)).
- Fix uniform name for luminance multiplier in shader compiler ([GH-111438](https://github.com/godotengine/godot/pull/111438)).
#### XR
- Fix late destruction access violation with OpenXRAPIExtension object ([GH-110868](https://github.com/godotengine/godot/pull/110868)).
## 4.5 - 2025-09-15
- [Release announcement](https://godotengine.org/releases/4.5/)
@ -207,7 +358,7 @@ Table of contents:
- Implement `ModifierBoneTarget3D` which can be target of the other `SkeletonModifier3D`s ([GH-106846](https://github.com/godotengine/godot/pull/106846)).
- Fix ambiguous AnimationNode's parameter type in default value and make `validate_type_match()` static function ([GH-107005](https://github.com/godotengine/godot/pull/107005)).
- Fix animation track filter size bug ([GH-107084](https://github.com/godotengine/godot/pull/107084)).
- Add default paramater for AnimationNode as super class ([GH-107171](https://github.com/godotengine/godot/pull/107171)).
- Add default parameter for AnimationNode as super class ([GH-107171](https://github.com/godotengine/godot/pull/107171)).
- Fix animation track inserted path and key type ([GH-107241](https://github.com/godotengine/godot/pull/107241)).
- Fix AnimationPlayer finished state in the editor ([GH-107244](https://github.com/godotengine/godot/pull/107244)).
- Fix editing/removal of bone meta ([GH-107546](https://github.com/godotengine/godot/pull/107546)).
@ -308,12 +459,10 @@ Table of contents:
- Android: Replace the deprecated version macro ([GH-104797](https://github.com/godotengine/godot/pull/104797)).
- CI: Validate `scons-cache` via action output ([GH-104803](https://github.com/godotengine/godot/pull/104803)).
- SCons: Only set GCC `-Wvirtual-inheritance` for C++ and `warnings=extra` ([GH-104841](https://github.com/godotengine/godot/pull/104841)).
- SCons: Add `CPPEXTPATH` for external includes ([GH-104893](https://github.com/godotengine/godot/pull/104893)).
- mbedtls: Disable ASM when compiling with LLVM MemorySanitizer (MSAN) ([GH-104912](https://github.com/godotengine/godot/pull/104912)).
- Organize ifdefs for disabling navigation, physics, and XR ([GH-104915](https://github.com/godotengine/godot/pull/104915)).
- Fix compiling with `disable_xr=yes` when 3d enabled ([GH-104978](https://github.com/godotengine/godot/pull/104978)).
- SCons: Integrate `WARNLEVEL` & `OPTIMIZELEVEL` ([GH-104982](https://github.com/godotengine/godot/pull/104982)).
- CI: Remove "Free disk space on runner" job (REVERTED) ([GH-105025](https://github.com/godotengine/godot/pull/105025)).
- Fix issue where vsproj=yes vsproj_gen_only=no sometimes fails to build ([GH-105238](https://github.com/godotengine/godot/pull/105238)).
- Web: Add the equivalent of `-Werror` for `wasm-ld` ([GH-105242](https://github.com/godotengine/godot/pull/105242)).
- Fix missing `gdb.printing` import for the pretty print script ([GH-105494](https://github.com/godotengine/godot/pull/105494)).
@ -395,7 +544,6 @@ Table of contents:
- macOS: Regenerate editor `icns` file to include all resolutions ([GH-109292](https://github.com/godotengine/godot/pull/109292)).
- Meta: Move /editor/scene folder from `core` to `docks` codeowner ([GH-109424](https://github.com/godotengine/godot/pull/109424)).
- CI: Update dependency setup on Linux actions ([GH-109573](https://github.com/godotengine/godot/pull/109573)).
- SCons: Temporarily revert Mesa includes to `CPPPATH` ([GH-109749](https://github.com/godotengine/godot/pull/109749)).
- SCons: Fix `dlltool` on Windows MinGW builds ([GH-109758](https://github.com/godotengine/godot/pull/109758)).
- CI: Fix detection of Windows D3D12 dependencies ([GH-109912](https://github.com/godotengine/godot/pull/109912)).
- CI: Ensure prettier/clearer sanitizer output ([GH-109960](https://github.com/godotengine/godot/pull/109960)).
@ -409,7 +557,7 @@ Table of contents:
- Resolve the hostfxr path using dotnet CLI ([GH-96146](https://github.com/godotengine/godot/pull/96146)).
- Add `linux-bionic` RID export option to support NativeAOT on Android ([GH-97908](https://github.com/godotengine/godot/pull/97908)).
- Use `ObjectID` when converting `Variant` to `GodotObject` ([GH-98034](https://github.com/godotengine/godot/pull/98034)).
- Editor: Prevent `TOOLS` .NET `DefineConstants` being overriden by the user ([GH-98153](https://github.com/godotengine/godot/pull/98153)).
- Editor: Prevent `TOOLS` .NET `DefineConstants` being overridden by the user ([GH-98153](https://github.com/godotengine/godot/pull/98153)).
- Fix thread deadlock when using a worker thread to load a script with a generic base class ([GH-99798](https://github.com/godotengine/godot/pull/99798)).
- Update Dotnet iOS Export Process ([GH-100187](https://github.com/godotengine/godot/pull/100187)).
- Fix `RefCounted` not disposed correctly in certain case ([GH-101006](https://github.com/godotengine/godot/pull/101006)).
@ -680,7 +828,7 @@ Table of contents:
- Smoke test: Log an error if `reserve()` is called with fewer elements than `size()` ([GH-105278](https://github.com/godotengine/godot/pull/105278)).
- Fix custom scene argument if it's referenced as UID ([GH-105288](https://github.com/godotengine/godot/pull/105288)).
- Add `--scene` command line argument ([GH-105302](https://github.com/godotengine/godot/pull/105302)).
- Supress unused paramater warning conflicting with if constexpr ([GH-105326](https://github.com/godotengine/godot/pull/105326)).
- Suppress unused parameter warning conflicting with if constexpr ([GH-105326](https://github.com/godotengine/godot/pull/105326)).
- Allow inserting at end of array again ([GH-105334](https://github.com/godotengine/godot/pull/105334)).
- Optimize `Array` `min`/`max` methods ([GH-105392](https://github.com/godotengine/godot/pull/105392)).
- Add thread safety to Object signals ([GH-105453](https://github.com/godotengine/godot/pull/105453)).
@ -727,7 +875,7 @@ Table of contents:
- Remove redundant `data.inside_tree` ([GH-106903](https://github.com/godotengine/godot/pull/106903)).
- JavaClassWrapper: Don't discard overloaded methods that differ by object type ([GH-106908](https://github.com/godotengine/godot/pull/106908)).
- Add missing headers in `FixedVector` and `Span` ([GH-106954](https://github.com/godotengine/godot/pull/106954)).
- Remove `OAHashMap`, in favour of `AHashMap` ([GH-106996](https://github.com/godotengine/godot/pull/106996)).
- Remove `OAHashMap`, in favor of `AHashMap` ([GH-106996](https://github.com/godotengine/godot/pull/106996)).
- Expose `WorkerThreadPool.get_caller_task_id()` ([GH-107029](https://github.com/godotengine/godot/pull/107029)).
- Add `WorkerThreadPool.get_caller_group_id` ([GH-107040](https://github.com/godotengine/godot/pull/107040)).
- Fix `ResourceSaver` saving default value of `Resource` ([GH-107049](https://github.com/godotengine/godot/pull/107049)).
@ -909,7 +1057,7 @@ Table of contents:
- C#: Fix Shortcut example ([GH-107609](https://github.com/godotengine/godot/pull/107609)).
- Clarify `_set`/`_get` description ([GH-107823](https://github.com/godotengine/godot/pull/107823)).
- Docs: Various grammar and spelling fixes ([GH-107895](https://github.com/godotengine/godot/pull/107895)).
- Specifiy return value in several store methods in `FileAccess` ([GH-107938](https://github.com/godotengine/godot/pull/107938)).
- Specify return value in several store methods in `FileAccess` ([GH-107938](https://github.com/godotengine/godot/pull/107938)).
- Fix OptionButton ID value range documentation ([GH-107940](https://github.com/godotengine/godot/pull/107940)).
- Document `Gradient.sample()` clamping behavior ([GH-107976](https://github.com/godotengine/godot/pull/107976)).
- Clarify `visible_characters` ([GH-108029](https://github.com/godotengine/godot/pull/108029)).
@ -1294,7 +1442,7 @@ Table of contents:
- Add single-object inspect command backwards compatible API for potential regression ([GH-110043](https://github.com/godotengine/godot/pull/110043)).
- Add missing range hint to `Viewport.oversampling_override` in the editor ([GH-110094](https://github.com/godotengine/godot/pull/110094)).
- Fix Range scale overflow ([GH-110107](https://github.com/godotengine/godot/pull/110107)).
- Fix "SpriteFrames" editor not fully hidding the bottom panel ([GH-110280](https://github.com/godotengine/godot/pull/110280)).
- Fix "SpriteFrames" editor not fully hiding the bottom panel ([GH-110280](https://github.com/godotengine/godot/pull/110280)).
#### Export
@ -1330,7 +1478,7 @@ Table of contents:
- [Windows export] Use project version as fallback ([GH-108472](https://github.com/godotengine/godot/pull/108472)).
- Remove selective shader baking ([GH-108914](https://github.com/godotengine/godot/pull/108914)).
- Reduce log spam during headless import/export ([GH-109334](https://github.com/godotengine/godot/pull/109334)).
- Android: Thread Syncronization for FileAccessHandler ([GH-109340](https://github.com/godotengine/godot/pull/109340)).
- Android: Thread Synchronization for FileAccessHandler ([GH-109340](https://github.com/godotengine/godot/pull/109340)).
- Fix headless import/export reporting progress greater than 100% ([GH-109391](https://github.com/godotengine/godot/pull/109391)).
- Android: Fix build command for AAB export ([GH-109608](https://github.com/godotengine/godot/pull/109608)).
- Add default param value to `EditorExportPlatform::get_forced_export_files` ([GH-109662](https://github.com/godotengine/godot/pull/109662)).
@ -1402,7 +1550,7 @@ Table of contents:
- Fix a few GDScript warning messages for grammar and consistency ([GH-104729](https://github.com/godotengine/godot/pull/104729)).
- Fix invalid DAP responses when content has non-ASCII content ([GH-104936](https://github.com/godotengine/godot/pull/104936)).
- LSP: Fix relative path handling for document links ([GH-105059](https://github.com/godotengine/godot/pull/105059)).
- LSP: Don't advertize support for workspace symbols ([GH-105061](https://github.com/godotengine/godot/pull/105061)).
- LSP: Don't advertise support for workspace symbols ([GH-105061](https://github.com/godotengine/godot/pull/105061)).
- Add autocompletion for `@export_tool_button` ([GH-105081](https://github.com/godotengine/godot/pull/105081)).
- LSP: Extract annotations from `EditorHelp` ([GH-105087](https://github.com/godotengine/godot/pull/105087)).
- Fix LSP not returning expected localization for API docs ([GH-105344](https://github.com/godotengine/godot/pull/105344)).
@ -1552,7 +1700,7 @@ Table of contents:
- Remove macros from FontFile test case ([GH-104709](https://github.com/godotengine/godot/pull/104709)).
- Implement Stackable Text Outline on `Label` ([GH-104731](https://github.com/godotengine/godot/pull/104731)).
- Fix TextEdit VScroll max tolerance ([GH-104776](https://github.com/godotengine/godot/pull/104776)).
- Replace global oversampling with overrideable per-viewport oversampling ([GH-104872](https://github.com/godotengine/godot/pull/104872)).
- Replace global oversampling with overridable per-viewport oversampling ([GH-104872](https://github.com/godotengine/godot/pull/104872)).
- Add font import flag to toggle modulation of colored glyphs ([GH-104878](https://github.com/godotengine/godot/pull/104878)).
- Make `swap_cancel_ok` setting 3-state instead of boolean ([GH-104958](https://github.com/godotengine/godot/pull/104958)).
- Linux: Detect KDE/LXQt and swap OK/Cancel buttons to Windows style ([GH-104959](https://github.com/godotengine/godot/pull/104959)).
@ -1961,7 +2109,7 @@ Table of contents:
- Fix CapsuleShape2D outline for navmesh baking ([GH-107263](https://github.com/godotengine/godot/pull/107263)).
- Change 2D navigation region and link updates to an async process ([GH-107381](https://github.com/godotengine/godot/pull/107381)).
- Only repath a NavigationAgent with a target position ([GH-107513](https://github.com/godotengine/godot/pull/107513)).
- Remove `get_used_cells` to avoid unecessary allocations in navigation baking ([GH-107559](https://github.com/godotengine/godot/pull/107559)).
- Remove `get_used_cells` to avoid unnecessary allocations in navigation baking ([GH-107559](https://github.com/godotengine/godot/pull/107559)).
- NavigationServer2D: Bind missing `merge_rasterizer_cell_scale` setting and functions ([GH-107802](https://github.com/godotengine/godot/pull/107802)).
- NavMap3D: check if obstacles have avoidance enabled ([GH-108281](https://github.com/godotengine/godot/pull/108281)).
- NavMap2D: check if obstacles have avoidance enabled ([GH-108284](https://github.com/godotengine/godot/pull/108284)).
@ -2172,7 +2320,7 @@ Table of contents:
- Fix wrong default texture for global uniforms of type `sampler2DArray` ([GH-101941](https://github.com/godotengine/godot/pull/101941)).
- Pass angular diameter into light size constants for sky shaders ([GH-101971](https://github.com/godotengine/godot/pull/101971)).
- Optimize ProceduralSkyMaterial by removing uses of acos and simplifying logic ([GH-101973](https://github.com/godotengine/godot/pull/101973)).
- Rendering compositor identifies `is_opengl` API; minor optimisation ([GH-102302](https://github.com/godotengine/godot/pull/102302)).
- Rendering compositor identifies `is_opengl` API; minor optimization ([GH-102302](https://github.com/godotengine/godot/pull/102302)).
- Add SMAA 1x to screenspace AA options ([GH-102330](https://github.com/godotengine/godot/pull/102330)).
- Add ASTC HDR format variants ([GH-102777](https://github.com/godotengine/godot/pull/102777)).
- GLES3: Fix errors baking light map with compatibility renderer ([GH-102783](https://github.com/godotengine/godot/pull/102783)).
@ -2235,7 +2383,7 @@ Table of contents:
- Fix reflection probe dark borders ([GH-105899](https://github.com/godotengine/godot/pull/105899)).
- Fix error spam to due wrong use of `reserve()` in D3D12 driver ([GH-105906](https://github.com/godotengine/godot/pull/105906)).
- FTI - Add custom interpolation for wheels ([GH-105915](https://github.com/godotengine/godot/pull/105915)).
- FTI - Fix `SceneTreeFTI` behaviour on exit tree ([GH-105973](https://github.com/godotengine/godot/pull/105973)).
- FTI - Fix `SceneTreeFTI` behavior on exit tree ([GH-105973](https://github.com/godotengine/godot/pull/105973)).
- Avoid crash when allocating specular and normal-roughness buffers when render buffers aren't available ([GH-106079](https://github.com/godotengine/godot/pull/106079)).
- Check for GL ES version of BPTC extension when using the OpenGL renderer ([GH-106086](https://github.com/godotengine/godot/pull/106086)).
- Add specular occlusion from ambient light ([GH-106145](https://github.com/godotengine/godot/pull/106145)).
@ -2263,7 +2411,7 @@ Table of contents:
- Mobile: Move `_setup_lightmaps` before `_fill_render_list` ([GH-106748](https://github.com/godotengine/godot/pull/106748)).
- D3D12: Fix inconsistent value for `DCOMP_ENABLED` in platform code ([GH-106827](https://github.com/godotengine/godot/pull/106827)).
- Fix missing ibl reconstruction from DFG multiscattering ([GH-106844](https://github.com/godotengine/godot/pull/106844)).
- Minor rendering and XR changes to allow Meta enivornment depth API to work entirely from GDExtension ([GH-106880](https://github.com/godotengine/godot/pull/106880)).
- Minor rendering and XR changes to allow Meta environment depth API to work entirely from GDExtension ([GH-106880](https://github.com/godotengine/godot/pull/106880)).
- Vulkan Mobile: Fix lightmap instances count ([GH-106907](https://github.com/godotengine/godot/pull/106907)).
- Correctly place viewport and use viewport relative rect for the final blit in Compatibility renderer ([GH-106924](https://github.com/godotengine/godot/pull/106924)).
- Metal: Fix multi-view support ([GH-106925](https://github.com/godotengine/godot/pull/106925)).
@ -2309,13 +2457,13 @@ Table of contents:
- Fix VVL errors by changing `frag_color` to FP32 and dFdx/y ([GH-108015](https://github.com/godotengine/godot/pull/108015)).
- Metal: Use image atomic operations on supported Apple hardware ([GH-108028](https://github.com/godotengine/godot/pull/108028)).
- Fix opaque stencil rendering ([GH-108044](https://github.com/godotengine/godot/pull/108044)).
- FTI: - Fix `MultiMesh` init and stable behaviour ([GH-108109](https://github.com/godotengine/godot/pull/108109)).
- FTI: - Fix `MultiMesh` init and stable behavior ([GH-108109](https://github.com/godotengine/godot/pull/108109)).
- FTI: - Add reset on setting `top_level` ([GH-108112](https://github.com/godotengine/godot/pull/108112)).
- Metal: Use correct environment variable to generate labels ([GH-108123](https://github.com/godotengine/godot/pull/108123)).
- FTI: - Clear `SceneTreeFTI` completely on enabling / disabling ([GH-108131](https://github.com/godotengine/godot/pull/108131)).
- Web: Restrict rendering method selection ([GH-108276](https://github.com/godotengine/godot/pull/108276)).
- Fix `surface_get_arrays` returns wrong index array when using empty vertex array ([GH-108308](https://github.com/godotengine/godot/pull/108308)).
- Fix underculling of occulusion culling ([GH-108347](https://github.com/godotengine/godot/pull/108347)).
- Fix underculling of occlusion culling ([GH-108347](https://github.com/godotengine/godot/pull/108347)).
- Fix division by zero in clearcoat specular BRDF ([GH-108378](https://github.com/godotengine/godot/pull/108378)).
- Fix crash when creating voxel GI data ([GH-108397](https://github.com/godotengine/godot/pull/108397)).
- Metal: Remove invalid assumption for image atomic operations ([GH-108452](https://github.com/godotengine/godot/pull/108452)).

View file

@ -214,7 +214,7 @@ License: Apache-2.0
Files: thirdparty/basis_universal/*
Comment: Basis Universal
Copyright: 2019-2025, Binomial LLC.
Copyright: 2019-2024, Binomial LLC.
License: Apache-2.0
Files: thirdparty/brotli/*
@ -555,7 +555,7 @@ License: Zlib
Files: thirdparty/sdl/hidapi/*
Comment: hidapi
Copyright: 2010, Alan Ott, Signal 11 Software
License: BSD-3-clause
License: BSD-3-Clause
Files: thirdparty/spirv-cross/*
Comment: SPIRV-Cross

View file

@ -239,7 +239,6 @@ opts.Add(BoolVariable("disable_physics_3d", "Disable 3D physics nodes and server
opts.Add(BoolVariable("disable_navigation_2d", "Disable 2D navigation features", False))
opts.Add(BoolVariable("disable_navigation_3d", "Disable 3D navigation features", False))
opts.Add(BoolVariable("disable_xr", "Disable XR nodes and server", False))
opts.Add(BoolVariable("disable_overrides", "Disable project settings overrides and related CLI arguments", False))
opts.Add("build_profile", "Path to a file containing a feature build profile", "")
opts.Add("custom_modules", "A list of comma-separated directory paths containing custom modules to build.", "")
opts.Add(BoolVariable("custom_modules_recursive", "Detect custom modules recursively for each specified path.", True))
@ -265,14 +264,6 @@ opts.Add(
True,
)
)
opts.Add(
EnumVariable(
"library_type",
"Build library type",
"executable",
("executable", "static_library", "shared_library"),
)
)
# Thirdparty libraries
opts.Add(BoolVariable("builtin_brotli", "Use the built-in Brotli library", True))
@ -555,13 +546,6 @@ if not env["deprecated"]:
if env["precision"] == "double":
env.Append(CPPDEFINES=["REAL_T_IS_DOUBLE"])
# Library Support
if env["library_type"] != "executable":
if "library" not in env.get("supported", []):
print_error(f"Library builds unsupported for {env['platform']}")
Exit(255)
env.Append(CPPDEFINES=["LIBGODOT_ENABLED"])
# Default num_jobs to local cpu count if not user specified.
# SCons has a peculiarity where user-specified options won't be overridden
# by SetOption, so we can rely on this to know if we should use our default.
@ -640,7 +624,6 @@ if env["strict_checks"]:
# Run SCU file generation script if in a SCU build.
if env["scu_build"]:
env.Append(CPPDEFINES=["SCU_BUILD_ENABLED"])
max_includes_per_scu = 8
if env.dev_build:
max_includes_per_scu = 1024
@ -1036,9 +1019,6 @@ if env["minizip"]:
if env["brotli"]:
env.Append(CPPDEFINES=["BROTLI_ENABLED"])
if not env["disable_overrides"]:
env.Append(CPPDEFINES=["OVERRIDE_ENABLED"])
if not env["verbose"]:
methods.no_verbose(env)

View file

@ -38,40 +38,24 @@
#include "core/version.h"
#include "servers/rendering/rendering_device.h"
void Engine::_update_time_scale() {
_time_scale = _user_time_scale * _game_time_scale;
user_ips = MAX(1, ips * _user_time_scale);
max_user_physics_steps_per_frame = MAX(max_physics_steps_per_frame, max_physics_steps_per_frame * _user_time_scale);
}
void Engine::set_physics_ticks_per_second(int p_ips) {
ERR_FAIL_COND_MSG(p_ips <= 0, "Engine iterations per second must be greater than 0.");
ips = p_ips;
_update_time_scale();
}
int Engine::get_physics_ticks_per_second() const {
return ips;
}
int Engine::get_user_physics_ticks_per_second() const {
return user_ips;
}
void Engine::set_max_physics_steps_per_frame(int p_max_physics_steps) {
ERR_FAIL_COND_MSG(p_max_physics_steps <= 0, "Maximum number of physics steps per frame must be greater than 0.");
max_physics_steps_per_frame = p_max_physics_steps;
_update_time_scale();
}
int Engine::get_max_physics_steps_per_frame() const {
return max_physics_steps_per_frame;
}
int Engine::get_user_max_physics_steps_per_frame() const {
return max_user_physics_steps_per_frame;
}
void Engine::set_physics_jitter_fix(double p_threshold) {
if (p_threshold < 0) {
p_threshold = 0;
@ -128,21 +112,11 @@ uint32_t Engine::get_frame_delay() const {
}
void Engine::set_time_scale(double p_scale) {
_game_time_scale = p_scale;
_update_time_scale();
_time_scale = p_scale;
}
double Engine::get_time_scale() const {
return freeze_time_scale ? 0.0 : _game_time_scale;
}
void Engine::set_user_time_scale(double p_scale) {
_user_time_scale = p_scale;
_update_time_scale();
}
double Engine::get_effective_time_scale() const {
return freeze_time_scale ? 0.0 : _time_scale;
return freeze_time_scale ? 0 : _time_scale;
}
double Engine::get_unfrozen_time_scale() const {

View file

@ -30,13 +30,10 @@
#pragma once
#include "core/string/string_name.h"
#include "core/templates/hash_map.h"
#include "core/os/main_loop.h"
#include "core/string/ustring.h"
#include "core/templates/list.h"
class Object;
class Dictionary;
template <typename T>
class TypedArray;
@ -62,17 +59,13 @@ private:
double _process_step = 0;
int ips = 60;
int user_ips = 60;
double physics_jitter_fix = 0.5;
double _fps = 1;
int _max_fps = 0;
int _audio_output_latency = 0;
double _time_scale = 1.0;
double _game_time_scale = 1.0;
double _user_time_scale = 1.0;
uint64_t _physics_frames = 0;
int max_physics_steps_per_frame = 8;
int max_user_physics_steps_per_frame = 8;
double _physics_interpolation_fraction = 0.0f;
bool abort_on_gpu_errors = false;
bool use_validation_layers = false;
@ -108,19 +101,14 @@ private:
bool freeze_time_scale = false;
protected:
void _update_time_scale();
public:
static Engine *get_singleton();
virtual void set_physics_ticks_per_second(int p_ips);
virtual int get_physics_ticks_per_second() const;
virtual int get_user_physics_ticks_per_second() const;
virtual void set_max_physics_steps_per_frame(int p_max_physics_steps);
virtual int get_max_physics_steps_per_frame() const;
virtual int get_user_max_physics_steps_per_frame() const;
void set_physics_jitter_fix(double p_threshold);
double get_physics_jitter_fix() const;
@ -144,8 +132,6 @@ public:
void set_time_scale(double p_scale);
double get_time_scale() const;
void set_user_time_scale(double p_scale);
double get_effective_time_scale() const;
double get_unfrozen_time_scale() const;
void set_print_to_stdout(bool p_enabled);

View file

@ -83,11 +83,6 @@ const PackedStringArray ProjectSettings::get_required_features() {
// Returns the features supported by this build of Godot. Includes all required features.
const PackedStringArray ProjectSettings::_get_supported_features() {
PackedStringArray features = get_required_features();
#ifdef LIBGODOT_ENABLED
features.append("LibGodot");
#endif
#ifdef MODULE_MONO_ENABLED
features.append("C#");
#endif
@ -285,7 +280,7 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
if (p_value.get_type() == Variant::NIL) {
props.erase(p_name);
if (p_name.operator String().begins_with("autoload/")) {
String node_name = p_name.operator String().get_slicec('/', 1);
String node_name = p_name.operator String().split("/")[1];
if (autoloads.has(node_name)) {
remove_autoload(node_name);
}
@ -331,7 +326,7 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
props[p_name] = VariantContainer(p_value, last_order++);
}
if (p_name.operator String().begins_with("autoload/")) {
String node_name = p_name.operator String().get_slicec('/', 1);
String node_name = p_name.operator String().split("/")[1];
AutoloadInfo autoload;
autoload.name = node_name;
String path = p_value;
@ -648,16 +643,11 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
ERR_FAIL_COND_V_MSG(!ok, ERR_CANT_OPEN, vformat("Cannot open resource pack '%s'.", p_main_pack));
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
#ifdef OVERRIDE_ENABLED
if (err == OK && !p_ignore_override) {
// Load override from location of the main pack
// Optional, we don't mind if it fails
bool disable_override = GLOBAL_GET("application/config/disable_project_settings_override");
if (!disable_override) {
_load_settings_text(p_main_pack.get_base_dir().path_join("override.cfg"));
}
_load_settings_text(p_main_pack.get_base_dir().path_join("override.cfg"));
}
#endif // OVERRIDE_ENABLED
return err;
}
@ -703,17 +693,12 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
// If we opened our package, try and load our project.
if (found) {
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
#ifdef OVERRIDE_ENABLED
if (err == OK && !p_ignore_override) {
// Load overrides from the PCK and the executable location.
// Optional, we don't mind if either fails.
bool disable_override = GLOBAL_GET("application/config/disable_project_settings_override");
if (!disable_override) {
_load_settings_text("res://override.cfg");
_load_settings_text(exec_path.get_base_dir().path_join("override.cfg"));
}
_load_settings_text("res://override.cfg");
_load_settings_text(exec_path.get_base_dir().path_join("override.cfg"));
}
#endif // OVERRIDE_ENABLED
return err;
}
}
@ -728,15 +713,10 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
if (!OS::get_singleton()->get_resource_dir().is_empty()) {
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
#ifdef OVERRIDE_ENABLED
if (err == OK && !p_ignore_override) {
// Optional, we don't mind if it fails.
bool disable_override = GLOBAL_GET("application/config/disable_project_settings_override");
if (!disable_override) {
_load_settings_text("res://override.cfg");
}
_load_settings_text("res://override.cfg");
}
#endif // OVERRIDE_ENABLED
return err;
}
@ -756,16 +736,11 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
err = _load_settings_text_or_binary(resource_path.path_join("project.godot"), resource_path.path_join("project.binary"));
if (err == OK && !p_ignore_override) {
// Optional, we don't mind if it fails.
#ifdef OVERRIDE_ENABLED
bool disable_override = GLOBAL_GET("application/config/disable_project_settings_override");
if (!disable_override) {
_load_settings_text(resource_path.path_join("override.cfg"));
}
#endif // OVERRIDE_ENABLED
_load_settings_text(resource_path.path_join("override.cfg"));
return err;
}
}
#endif // MACOS_ENABLED
#endif
// Nothing was found, try to find a project file in provided path (`p_path`)
// or, if requested (`p_upwards`) in parent directories.
@ -785,12 +760,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
err = _load_settings_text_or_binary(current_dir.path_join("project.godot"), current_dir.path_join("project.binary"));
if (err == OK && !p_ignore_override) {
// Optional, we don't mind if it fails.
#ifdef OVERRIDE_ENABLED
bool disable_override = GLOBAL_GET("application/config/disable_project_settings_override");
if (!disable_override) {
_load_settings_text(current_dir.path_join("override.cfg"));
}
#endif // OVERRIDE_ENABLED
_load_settings_text(current_dir.path_join("override.cfg"));
found = true;
break;
}
@ -1599,7 +1569,6 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("application/config/use_custom_user_dir", false);
GLOBAL_DEF("application/config/custom_user_dir_name", "");
GLOBAL_DEF("application/config/project_settings_override", "");
GLOBAL_DEF("application/config/disable_project_settings_override", false);
GLOBAL_DEF("application/run/main_loop_type", "SceneTree");
GLOBAL_DEF("application/config/auto_accept_quit", true);
@ -1706,7 +1675,6 @@ ProjectSettings::ProjectSettings() {
#endif
GLOBAL_DEF_BASIC("gui/common/snap_controls_to_pixels", true);
GLOBAL_DEF("gui/common/always_show_focus_state", false);
GLOBAL_DEF_BASIC("gui/fonts/dynamic_fonts/use_oversampling", true);
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/rendering_device/vsync/frame_queue_size", PROPERTY_HINT_RANGE, "2,3,1"), 2);
@ -1730,7 +1698,7 @@ ProjectSettings::ProjectSettings() {
// installed by the scripts provided in the repository
// (check `misc/scripts/install_d3d12_sdk_windows.py`).
// For example, if the script installs 1.613.3, the default value must be 613.
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/rendering_device/d3d12/agility_sdk_version", PROPERTY_HINT_RANGE, "0,10000,1,or_greater,hide_control"), 613);
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/rendering_device/d3d12/agility_sdk_version", PROPERTY_HINT_RANGE, "0,10000,1,or_greater,hide_slider"), 613);
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/textures/canvas_textures/default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Linear Mipmap,Nearest Mipmap"), 1);
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/textures/canvas_textures/default_texture_repeat", PROPERTY_HINT_ENUM, "Disable,Enable,Mirror"), 0);

View file

@ -30,8 +30,7 @@
#pragma once
#include "core/object/object.h"
#include "core/templates/rb_map.h"
#include "core/object/class_db.h"
template <typename T>
class TypedArray;
@ -50,7 +49,7 @@ class ProjectSettings : public Object {
public:
typedef HashMap<String, Variant> CustomMap;
static inline const String PROJECT_DATA_DIR_NAME_SUFFIX = "godot";
static inline const String EDITOR_SETTING_OVERRIDE_PREFIX = PNAME("editor_overrides") + String("/");
static inline const String EDITOR_SETTING_OVERRIDE_PREFIX = "editor_overrides/";
// Properties that are not for built in values begin from this value, so builtin ones are displayed first.
constexpr static const int32_t NO_BUILTIN_ORDER_BASE = 1 << 16;

View file

@ -35,12 +35,10 @@
#include "core/crypto/crypto_core.h"
#include "core/debugger/engine_debugger.h"
#include "core/debugger/script_debugger.h"
#include "core/io/file_access.h"
#include "core/io/marshalls.h"
#include "core/math/geometry_2d.h"
#include "core/math/geometry_3d.h"
#include "core/os/keyboard.h"
#include "core/os/main_loop.h"
#include "core/os/thread_safe.h"
#include "core/variant/typed_array.h"
@ -1528,10 +1526,6 @@ void Thread::set_thread_safety_checks_enabled(bool p_enabled) {
set_current_thread_safe_for_nodes(!p_enabled);
}
bool Thread::is_main_thread() {
return ::Thread::is_main_thread();
}
void Thread::_bind_methods() {
ClassDB::bind_method(D_METHOD("start", "callable", "priority"), &Thread::start, DEFVAL(PRIORITY_NORMAL));
ClassDB::bind_method(D_METHOD("get_id"), &Thread::get_id);
@ -1540,7 +1534,6 @@ void Thread::_bind_methods() {
ClassDB::bind_method(D_METHOD("wait_to_finish"), &Thread::wait_to_finish);
ClassDB::bind_static_method("Thread", D_METHOD("set_thread_safety_checks_enabled", "enabled"), &Thread::set_thread_safety_checks_enabled);
ClassDB::bind_static_method("Thread", D_METHOD("is_main_thread"), &Thread::is_main_thread);
BIND_ENUM_CONSTANT(PRIORITY_LOW);
BIND_ENUM_CONSTANT(PRIORITY_NORMAL);
@ -1552,16 +1545,14 @@ namespace Special {
////// ClassDB //////
PackedStringArray ClassDB::get_class_list() const {
LocalVector<StringName> classes;
::ClassDB::get_class_list(classes);
List<StringName> classes;
::ClassDB::get_class_list(&classes);
PackedStringArray ret;
ret.resize(classes.size());
String *ptrw = ret.ptrw();
int idx = 0;
for (const StringName &cls : classes) {
ptrw[idx] = cls;
idx++;
for (const StringName &E : classes) {
ret.set(idx++, E);
}
return ret;
@ -1815,12 +1806,8 @@ void ClassDB::get_argument_options(const StringName &p_function, int p_idx, List
pf == "is_class_enabled" || pf == "is_class_enum_bitfield" || pf == "class_get_api_type");
}
if (first_argument_is_class || pf == "is_parent_class") {
LocalVector<StringName> classes;
::ClassDB::get_class_list(classes);
for (const StringName &E : classes) {
if (::ClassDB::is_class_exposed(E)) {
r_options->push_back(E.operator String().quote());
}
for (const String &E : get_class_list()) {
r_options->push_back(E.quote());
}
}

View file

@ -495,7 +495,6 @@ public:
Variant wait_to_finish();
static void set_thread_safety_checks_enabled(bool p_enabled);
static bool is_main_thread();
};
namespace Special {

View file

@ -11,7 +11,7 @@ def disabled_class_builder(target, source, env):
with methods.generated_wrapper(str(target[0])) as file:
for c in source[0].read():
if cs := c.strip():
file.write(f"class {cs}; template <> struct is_class_enabled<{cs}> : std::false_type {{}};\n")
file.write(f"#define ClassDB_Disable_{cs} 1\n")
# Generate version info

View file

@ -75,7 +75,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CONSTANT(m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -83,7 +83,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_BITFIELD_FLAG(m_constant) \
{ \
StringName enum_name = __constant_get_bitfield_name(m_constant); \
StringName enum_name = __constant_get_bitfield_name(m_constant, #m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant, false, true)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -92,7 +92,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
// This just binds enum classes as if they were regular enum constants.
#define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \
{ \
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member); \
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -100,7 +100,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_BITFIELD_CLASS_FLAG(m_enum, m_prefix, m_member) \
{ \
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member); \
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member, #m_prefix "_" #m_member); \
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member, false, true)); \
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -108,7 +108,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \
{ \
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_name); \
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member)); \
_global_constants_map[#m_name] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -116,7 +116,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(m_enum, m_name, m_member) \
{ \
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member); \
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member, #m_name); \
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member, false, true)); \
_global_constants_map[#m_name] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -124,7 +124,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CLASS_CONSTANT_NO_VAL(m_enum, m_prefix, m_member) \
{ \
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member); \
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member, true)); \
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -132,7 +132,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant)); \
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -144,7 +144,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CONSTANT_NO_VAL(m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant, true)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -152,7 +152,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CONSTANT_CUSTOM_NO_VAL(m_custom_name, m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant, true)); \
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -166,7 +166,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CONSTANT(m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -174,7 +174,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_BITFIELD_FLAG(m_constant) \
{ \
StringName enum_name = __constant_get_bitfield_name(m_constant); \
StringName enum_name = __constant_get_bitfield_name(m_constant, #m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -183,7 +183,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
// This just binds enum classes as if they were regular enum constants.
#define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \
{ \
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member); \
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -191,7 +191,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_BITFIELD_CLASS_FLAG(m_enum, m_prefix, m_member) \
{ \
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member); \
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member, #m_prefix "_" #m_member); \
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -199,7 +199,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \
{ \
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_name); \
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member)); \
_global_constants_map[#m_name] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -207,7 +207,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(m_enum, m_name, m_member) \
{ \
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member); \
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member, #m_name); \
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member)); \
_global_constants_map[#m_name] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -215,7 +215,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CLASS_CONSTANT_NO_VAL(m_enum, m_prefix, m_member) \
{ \
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member); \
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -223,7 +223,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant)); \
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -235,7 +235,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CONSTANT_NO_VAL(m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -243,7 +243,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CONSTANT_CUSTOM_NO_VAL(m_custom_name, m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant)); \
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \

View file

@ -149,8 +149,6 @@ public:
};
class ResourceFormatLoaderCrypto : public ResourceFormatLoader {
GDSOFTCLASS(ResourceFormatLoaderCrypto, ResourceFormatLoader);
public:
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
@ -163,8 +161,6 @@ public:
};
class ResourceFormatSaverCrypto : public ResourceFormatSaver {
GDSOFTCLASS(ResourceFormatSaverCrypto, ResourceFormatSaver);
public:
virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0) override;
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const override;

View file

@ -121,10 +121,7 @@ void EngineDebugger::iteration(uint64_t p_frame_ticks, uint64_t p_process_ticks,
}
void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, bool p_ignore_error_breaks, const Vector<String> &p_breakpoints, void (*p_allow_focus_steal_fn)()) {
register_uri_handler("tcp://", RemoteDebuggerPeerTCP::create_tcp); // TCP is the default protocol. Platforms/modules can add more.
#ifdef UNIX_ENABLED
register_uri_handler("unix://", RemoteDebuggerPeerTCP::create_unix);
#endif
register_uri_handler("tcp://", RemoteDebuggerPeerTCP::create); // TCP is the default protocol. Platforms/modules can add more.
if (p_uri.is_empty()) {
return;
}
@ -135,10 +132,10 @@ void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, bo
OS::get_singleton()->initialize_debugging();
} else if (p_uri.contains("://")) {
const String proto = p_uri.substr(0, p_uri.find("://") + 3);
CreatePeerFunc *create_fn = protocols.getptr(proto);
ERR_FAIL_NULL_MSG(create_fn, vformat("Invalid protocol: %s.", proto));
RemoteDebuggerPeer *peer = (*create_fn)(p_uri);
if (!protocols.has(proto)) {
return;
}
RemoteDebuggerPeer *peer = protocols[proto](p_uri);
if (!peer) {
return;
}

View file

@ -31,7 +31,6 @@
#include "local_debugger.h"
#include "core/debugger/script_debugger.h"
#include "core/os/main_loop.h"
#include "core/os/os.h"
struct LocalDebugger::ScriptsProfiler {

View file

@ -40,7 +40,7 @@
#include "core/math/expression.h"
#include "core/object/script_language.h"
#include "core/os/os.h"
#include "servers/display/display_server.h"
#include "servers/display_server.h"
class RemoteDebugger::PerformanceProfiler : public EngineProfiler {
Object *performance = nullptr;
@ -48,9 +48,9 @@ class RemoteDebugger::PerformanceProfiler : public EngineProfiler {
uint64_t last_monitor_modification_time = 0;
public:
void toggle(bool p_enable, const Array &p_opts) override {}
void add(const Array &p_data) override {}
void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) override {
void toggle(bool p_enable, const Array &p_opts) {}
void add(const Array &p_data) {}
void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) {
if (!performance) {
return;
}
@ -566,25 +566,25 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
input_vals.append(V);
}
LocalVector<StringName> native_types;
ClassDB::get_class_list(native_types);
for (const StringName &class_name : native_types) {
if (!ClassDB::is_class_exposed(class_name) || !Engine::get_singleton()->has_singleton(class_name) || Engine::get_singleton()->is_singleton_editor_only(class_name)) {
List<StringName> native_types;
ClassDB::get_class_list(&native_types);
for (const StringName &E : native_types) {
if (!ClassDB::is_class_exposed(E) || !Engine::get_singleton()->has_singleton(E) || Engine::get_singleton()->is_singleton_editor_only(E)) {
continue;
}
input_names.append(class_name);
input_vals.append(Engine::get_singleton()->get_singleton_object(class_name));
input_names.append(E);
input_vals.append(Engine::get_singleton()->get_singleton_object(E));
}
LocalVector<StringName> user_types;
ScriptServer::get_global_class_list(user_types);
for (const StringName &class_name : user_types) {
String scr_path = ScriptServer::get_global_class_path(class_name);
List<StringName> user_types;
ScriptServer::get_global_class_list(&user_types);
for (const StringName &S : user_types) {
String scr_path = ScriptServer::get_global_class_path(S);
Ref<Script> scr = ResourceLoader::load(scr_path, "Script");
ERR_CONTINUE_MSG(scr.is_null(), vformat(R"(Could not load the global class %s from resource path: "%s".)", class_name, scr_path));
ERR_CONTINUE_MSG(scr.is_null(), vformat(R"(Could not load the global class %s from resource path: "%s".)", S, scr_path));
input_names.append(class_name);
input_names.append(S);
input_vals.append(scr);
}

View file

@ -76,19 +76,18 @@ void RemoteDebuggerPeerTCP::close() {
in_buf.clear();
}
RemoteDebuggerPeerTCP::RemoteDebuggerPeerTCP() {
RemoteDebuggerPeerTCP::RemoteDebuggerPeerTCP(Ref<StreamPeerTCP> p_tcp) {
// This means remote debugger takes 16 MiB just because it exists...
in_buf.resize((8 << 20) + 4); // 8 MiB should be way more than enough (need 4 extra bytes for encoding packet size).
out_buf.resize(8 << 20); // 8 MiB should be way more than enough
}
RemoteDebuggerPeerTCP::RemoteDebuggerPeerTCP(Ref<StreamPeerSocket> p_stream) :
RemoteDebuggerPeerTCP() {
DEV_ASSERT(p_stream.is_valid());
tcp_client = p_stream;
connected = true;
running = true;
thread.start(_thread_func, this);
tcp_client = p_tcp;
if (tcp_client.is_valid()) { // Attaching to an already connected stream.
connected = true;
running = true;
thread.start(_thread_func, this);
} else {
tcp_client.instantiate();
}
}
RemoteDebuggerPeerTCP::~RemoteDebuggerPeerTCP() {
@ -155,10 +154,22 @@ void RemoteDebuggerPeerTCP::_read_in() {
}
}
Error RemoteDebuggerPeerTCP::_try_connect(Ref<StreamPeerSocket> tcp_client) {
Error RemoteDebuggerPeerTCP::connect_to_host(const String &p_host, uint16_t p_port) {
IPAddress ip;
if (p_host.is_valid_ip_address()) {
ip = p_host;
} else {
ip = IP::get_singleton()->resolve_hostname(p_host);
}
int port = p_port;
const int tries = 6;
const int waits[tries] = { 1, 10, 100, 1000, 1000, 1000 };
Error err = tcp_client->connect_to_host(ip, port);
ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Remote Debugger: Unable to connect to host '%s:%d'.", p_host, port));
for (int i = 0; i < tries; i++) {
tcp_client->poll();
if (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED) {
@ -175,6 +186,9 @@ Error RemoteDebuggerPeerTCP::_try_connect(Ref<StreamPeerSocket> tcp_client) {
ERR_PRINT(vformat("Remote Debugger: Unable to connect. Status: %s.", String::num_int64(tcp_client->get_status())));
return FAILED;
}
connected = true;
running = true;
thread.start(_thread_func, this);
return OK;
}
@ -208,7 +222,7 @@ void RemoteDebuggerPeerTCP::_poll() {
}
}
RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create_tcp(const String &p_uri) {
RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create(const String &p_uri) {
ERR_FAIL_COND_V(!p_uri.begins_with("tcp://"), nullptr);
String debug_host = p_uri.replace("tcp://", "");
@ -220,30 +234,13 @@ RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create_tcp(const String &p_uri) {
debug_host = debug_host.substr(0, sep_pos);
}
IPAddress ip;
if (debug_host.is_valid_ip_address()) {
ip = debug_host;
} else {
ip = IP::get_singleton()->resolve_hostname(debug_host);
RemoteDebuggerPeerTCP *peer = memnew(RemoteDebuggerPeerTCP);
Error err = peer->connect_to_host(debug_host, debug_port);
if (err != OK) {
memdelete(peer);
return nullptr;
}
Ref<StreamPeerTCP> stream;
stream.instantiate();
ERR_FAIL_COND_V_MSG(stream->connect_to_host(ip, debug_port) != OK, nullptr, vformat("Remote Debugger: Unable to connect to host '%s:%d'.", debug_host, debug_port));
ERR_FAIL_COND_V(_try_connect(stream), nullptr);
return memnew(RemoteDebuggerPeerTCP(stream));
}
RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create_unix(const String &p_uri) {
ERR_FAIL_COND_V(!p_uri.begins_with("unix://"), nullptr);
String debug_path = p_uri.replace("unix://", "");
Ref<StreamPeerUDS> stream;
stream.instantiate();
Error err = stream->connect_to_host(debug_path);
ERR_FAIL_COND_V_MSG(err != OK && err != ERR_BUSY, nullptr, vformat("Remote Debugger: Unable to connect to socket path '%s'.", debug_path));
ERR_FAIL_COND_V(_try_connect(stream), nullptr);
return memnew(RemoteDebuggerPeerTCP(stream));
return peer;
}
RemoteDebuggerPeer::RemoteDebuggerPeer() {

View file

@ -31,15 +31,12 @@
#pragma once
#include "core/io/stream_peer_tcp.h"
#include "core/io/stream_peer_uds.h"
#include "core/object/ref_counted.h"
#include "core/os/mutex.h"
#include "core/os/thread.h"
#include "core/string/ustring.h"
class RemoteDebuggerPeer : public RefCounted {
GDSOFTCLASS(RemoteDebuggerPeer, RefCounted);
protected:
int max_queued_messages = 4096;
@ -57,10 +54,8 @@ public:
};
class RemoteDebuggerPeerTCP : public RemoteDebuggerPeer {
GDSOFTCLASS(RemoteDebuggerPeerTCP, RemoteDebuggerPeer);
private:
Ref<StreamPeerSocket> tcp_client;
Ref<StreamPeerTCP> tcp_client;
Mutex mutex;
Thread thread;
List<Array> in_queue;
@ -79,11 +74,11 @@ private:
void _poll();
void _write_out();
void _read_in();
static Error _try_connect(Ref<StreamPeerSocket> p_stream);
public:
static RemoteDebuggerPeer *create_tcp(const String &p_uri);
static RemoteDebuggerPeer *create_unix(const String &p_uri);
static RemoteDebuggerPeer *create(const String &p_uri);
Error connect_to_host(const String &p_host, uint16_t p_port);
bool is_peer_connected() override;
int get_max_message_size() const override;
@ -93,7 +88,6 @@ public:
void poll() override;
void close() override;
RemoteDebuggerPeerTCP(Ref<StreamPeerSocket> p_stream);
RemoteDebuggerPeerTCP();
RemoteDebuggerPeerTCP(Ref<StreamPeerTCP> p_stream = Ref<StreamPeerTCP>());
~RemoteDebuggerPeerTCP();
};

View file

@ -30,7 +30,7 @@
#include "error_list.h"
#include "core/typedefs.h"
#include <iterator>
const char *error_names[] = {
"OK", // OK
@ -84,4 +84,4 @@ const char *error_names[] = {
"Printer on fire", // ERR_PRINTER_ON_FIRE
};
static_assert(std_size(error_names) == ERR_MAX);
static_assert(std::size(error_names) == ERR_MAX);

View file

@ -900,9 +900,11 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
// classes
Array classes;
LocalVector<StringName> class_list;
List<StringName> class_list;
ClassDB::get_class_list(class_list);
ClassDB::get_class_list(&class_list);
class_list.sort_custom<StringName::AlphCompare>();
for (const StringName &class_name : class_list) {
if (!ClassDB::is_class_exposed(class_name)) {

View file

@ -184,8 +184,6 @@ public:
VARIANT_ENUM_CAST(GDExtension::InitializationLevel)
class GDExtensionResourceLoader : public ResourceFormatLoader {
GDSOFTCLASS(GDExtensionResourceLoader, ResourceFormatLoader);
public:
static Error load_gdextension_resource(const String &p_path, Ref<GDExtension> &p_extension);

View file

@ -1,74 +0,0 @@
/**************************************************************************/
/* gdextension_function_loader.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "gdextension_function_loader.h"
#include "gdextension.h"
Error GDExtensionFunctionLoader::open_library(const String &p_path) {
ERR_FAIL_COND_V_MSG(!p_path.begins_with("libgodot://"), ERR_FILE_NOT_FOUND, "Function based GDExtensions should have a path starting with libgodot://");
ERR_FAIL_COND_V_MSG(!initialization_function, ERR_DOES_NOT_EXIST, "Initialization function is required for function based GDExtensions.");
library_path = p_path;
return OK;
}
Error GDExtensionFunctionLoader::initialize(GDExtensionInterfaceGetProcAddress p_get_proc_address, const Ref<GDExtension> &p_extension, GDExtensionInitialization *r_initialization) {
ERR_FAIL_COND_V_MSG(!initialization_function, ERR_DOES_NOT_EXIST, "Initialization function is required for function based GDExtensions.");
GDExtensionBool ret = initialization_function(p_get_proc_address, p_extension.ptr(), r_initialization);
if (ret) {
return OK;
} else {
ERR_FAIL_V_MSG(FAILED, "GDExtension initialization function for '" + library_path + "' returned an error.");
}
}
void GDExtensionFunctionLoader::close_library() {
initialization_function = nullptr;
library_path.clear();
}
bool GDExtensionFunctionLoader::is_library_open() const {
return !library_path.is_empty();
}
bool GDExtensionFunctionLoader::has_library_changed() const {
return false;
}
bool GDExtensionFunctionLoader::library_exists() const {
return true;
}
void GDExtensionFunctionLoader::set_initialization_function(GDExtensionInitializationFunction p_initialization_function) {
initialization_function = p_initialization_function;
}

View file

@ -1,54 +0,0 @@
/**************************************************************************/
/* gdextension_function_loader.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "core/extension/gdextension_loader.h"
#include "core/os/shared_object.h"
class GDExtension;
class GDExtensionFunctionLoader : public GDExtensionLoader {
friend class GDExtensionManager;
friend class GDExtension;
String library_path;
GDExtensionInitializationFunction initialization_function = nullptr;
public:
virtual Error open_library(const String &p_path) override;
virtual Error initialize(GDExtensionInterfaceGetProcAddress p_get_proc_address, const Ref<GDExtension> &p_extension, GDExtensionInitialization *r_initialization) override;
virtual void close_library() override;
virtual bool is_library_open() const override;
virtual bool has_library_changed() const override;
virtual bool library_exists() const override;
void set_initialization_function(GDExtensionInitializationFunction p_initialization_function);
};

View file

@ -261,7 +261,6 @@ static void gdextension_get_godot_version2(GDExtensionGodotVersion2 *r_godot_ver
}
// Memory Functions
#ifndef DISABLE_DEPRECATED
static void *gdextension_mem_alloc(size_t p_size) {
return memalloc(p_size);
}
@ -273,19 +272,6 @@ static void *gdextension_mem_realloc(void *p_mem, size_t p_size) {
static void gdextension_mem_free(void *p_mem) {
memfree(p_mem);
}
#endif
static void *gdextension_mem_alloc2(size_t p_size, GDExtensionBool p_prepad_align) {
return Memory::alloc_static(p_size, p_prepad_align);
}
static void *gdextension_mem_realloc2(void *p_mem, size_t p_size, GDExtensionBool p_prepad_align) {
return Memory::realloc_static(p_mem, p_size, p_prepad_align);
}
static void gdextension_mem_free2(void *p_mem, GDExtensionBool p_prepad_align) {
Memory::free_static(p_mem, p_prepad_align);
}
// Helper print functions.
static void gdextension_print_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify) {
@ -1701,14 +1687,9 @@ void gdextension_setup_interface() {
REGISTER_INTERFACE_FUNC(get_godot_version);
#endif // DISABLE_DEPRECATED
REGISTER_INTERFACE_FUNC(get_godot_version2);
#ifndef DISABLE_DEPRECATED
REGISTER_INTERFACE_FUNC(mem_alloc);
REGISTER_INTERFACE_FUNC(mem_realloc);
REGISTER_INTERFACE_FUNC(mem_free);
#endif // DISABLE_DEPRECATED
REGISTER_INTERFACE_FUNC(mem_alloc2);
REGISTER_INTERFACE_FUNC(mem_realloc2);
REGISTER_INTERFACE_FUNC(mem_free2);
REGISTER_INTERFACE_FUNC(print_error);
REGISTER_INTERFACE_FUNC(print_error_with_message);
REGISTER_INTERFACE_FUNC(print_warning);

View file

@ -858,7 +858,6 @@ typedef void (*GDExtensionInterfaceGetGodotVersion2)(GDExtensionGodotVersion2 *r
/**
* @name mem_alloc
* @since 4.1
* @deprecated in Godot 4.6. Use `mem_alloc2` instead.
*
* Allocates memory.
*
@ -871,7 +870,6 @@ typedef void *(*GDExtensionInterfaceMemAlloc)(size_t p_bytes);
/**
* @name mem_realloc
* @since 4.1
* @deprecated in Godot 4.6. Use `mem_realloc2` instead.
*
* Reallocates memory.
*
@ -885,7 +883,6 @@ typedef void *(*GDExtensionInterfaceMemRealloc)(void *p_ptr, size_t p_bytes);
/**
* @name mem_free
* @since 4.1
* @deprecated in Godot 4.6. Use `mem_free2` instead.
*
* Frees memory.
*
@ -893,45 +890,7 @@ typedef void *(*GDExtensionInterfaceMemRealloc)(void *p_ptr, size_t p_bytes);
*/
typedef void (*GDExtensionInterfaceMemFree)(void *p_ptr);
/**
* @name mem_alloc2
* @since 4.6
*
* Allocates memory.
*
* @param p_bytes The amount of memory to allocate in bytes.
* @param p_pad_align If true, the returned memory will have prepadding of at least 8 bytes.
*
* @return A pointer to the allocated memory, or NULL if unsuccessful.
*/
typedef void *(*GDExtensionInterfaceMemAlloc2)(size_t p_bytes, GDExtensionBool p_pad_align);
/**
* @name mem_realloc2
* @since 4.6
*
* Reallocates memory.
*
* @param p_ptr A pointer to the previously allocated memory.
* @param p_bytes The number of bytes to resize the memory block to.
* @param p_pad_align If true, the returned memory will have prepadding of at least 8 bytes.
*
* @return A pointer to the allocated memory, or NULL if unsuccessful.
*/
typedef void *(*GDExtensionInterfaceMemRealloc2)(void *p_ptr, size_t p_bytes, GDExtensionBool p_pad_align);
/**
* @name mem_free2
* @since 4.6
*
* Frees memory.
*
* @param p_ptr A pointer to the previously allocated memory.
* @param p_pad_align If true, the given memory was allocated with prepadding.
*/
typedef void (*GDExtensionInterfaceMemFree2)(void *p_ptr, GDExtensionBool p_pad_align);
//* INTERFACE: Godot Core */
/* INTERFACE: Godot Core */
/**
* @name print_error

View file

@ -30,7 +30,6 @@
#include "gdextension_manager.h"
#include "core/extension/gdextension_function_loader.h"
#include "core/extension/gdextension_library_loader.h"
#include "core/extension/gdextension_special_compat_hashes.h"
#include "core/io/dir_access.h"
@ -115,14 +114,7 @@ GDExtensionManager::LoadStatus GDExtensionManager::load_extension(const String &
Ref<GDExtensionLibraryLoader> loader;
loader.instantiate();
return load_extension_with_loader(p_path, loader);
}
GDExtensionManager::LoadStatus GDExtensionManager::load_extension_from_function(const String &p_path, GDExtensionConstPtr<const GDExtensionInitializationFunction> p_init_func) {
Ref<GDExtensionFunctionLoader> func_loader;
func_loader.instantiate();
func_loader->set_initialization_function((GDExtensionInitializationFunction)*p_init_func.data);
return load_extension_with_loader(p_path, func_loader);
return GDExtensionManager::get_singleton()->load_extension_with_loader(p_path, loader);
}
GDExtensionManager::LoadStatus GDExtensionManager::load_extension_with_loader(const String &p_path, const Ref<GDExtensionLoader> &p_loader) {
@ -462,7 +454,6 @@ GDExtensionManager *GDExtensionManager::get_singleton() {
void GDExtensionManager::_bind_methods() {
ClassDB::bind_method(D_METHOD("load_extension", "path"), &GDExtensionManager::load_extension);
ClassDB::bind_method(D_METHOD("load_extension_from_function", "path", "init_func"), &GDExtensionManager::load_extension_from_function);
ClassDB::bind_method(D_METHOD("reload_extension", "path"), &GDExtensionManager::reload_extension);
ClassDB::bind_method(D_METHOD("unload_extension", "path"), &GDExtensionManager::unload_extension);
ClassDB::bind_method(D_METHOD("is_extension_loaded", "path"), &GDExtensionManager::is_extension_loaded);

View file

@ -31,9 +31,6 @@
#pragma once
#include "core/extension/gdextension.h"
#include "core/variant/native_ptr.h"
GDVIRTUAL_NATIVE_PTR(GDExtensionInitializationFunction)
class GDExtensionManager : public Object {
GDCLASS(GDExtensionManager, Object);
@ -69,7 +66,6 @@ private:
public:
LoadStatus load_extension(const String &p_path);
LoadStatus load_extension_from_function(const String &p_path, GDExtensionConstPtr<const GDExtensionInitializationFunction> p_init_func);
LoadStatus load_extension_with_loader(const String &p_path, const Ref<GDExtensionLoader> &p_loader);
LoadStatus reload_extension(const String &p_path);
LoadStatus unload_extension(const String &p_path);

View file

@ -63,7 +63,7 @@ bool GDExtensionSpecialCompatHashes::get_legacy_hashes(const StringName &p_class
if (p_check_valid) {
MethodBind *mb = ClassDB::get_method_with_compatibility(p_class, p_method, mapping.current_hash);
if (!mb) {
WARN_PRINT(vformat("Compatibility hash %d for %s::%s() mapped to non-existent hash %d in gdextension_special_compat_hashes.cpp.", mapping.legacy_hash, p_class, p_method, mapping.current_hash));
WARN_PRINT(vformat("Compatibility hash %d for %s::%s() mapped to non-existent hash %d. Please update gdextension_special_compat_hashes.cpp.", mapping.legacy_hash, p_class, p_method, mapping.current_hash));
continue;
}
}

View file

@ -36,8 +36,6 @@
#include "core/templates/hash_map.h"
#include "core/templates/local_vector.h"
class Array;
// Note: In most situations, compatibility methods should be registered via ClassDB::bind_compatibility_method().
// This class is only meant to be used in exceptional circumstances, for example, when Godot's hashing
// algorithm changes and registering compatibility methods for all affect methods would be onerous.

View file

@ -1,126 +0,0 @@
/**************************************************************************/
/* godot_instance.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "godot_instance.h"
#include "core/extension/gdextension_manager.h"
#include "core/os/main_loop.h"
#include "main/main.h"
#include "servers/display/display_server.h"
void GodotInstance::_bind_methods() {
ClassDB::bind_method(D_METHOD("start"), &GodotInstance::start);
ClassDB::bind_method(D_METHOD("is_started"), &GodotInstance::is_started);
ClassDB::bind_method(D_METHOD("iteration"), &GodotInstance::iteration);
ClassDB::bind_method(D_METHOD("focus_in"), &GodotInstance::focus_in);
ClassDB::bind_method(D_METHOD("focus_out"), &GodotInstance::focus_out);
ClassDB::bind_method(D_METHOD("pause"), &GodotInstance::pause);
ClassDB::bind_method(D_METHOD("resume"), &GodotInstance::resume);
}
GodotInstance::GodotInstance() {
}
GodotInstance::~GodotInstance() {
}
bool GodotInstance::initialize(GDExtensionInitializationFunction p_init_func) {
print_verbose("Godot Instance initialization");
GDExtensionManager *gdextension_manager = GDExtensionManager::get_singleton();
GDExtensionConstPtr<const GDExtensionInitializationFunction> ptr((const GDExtensionInitializationFunction *)&p_init_func);
GDExtensionManager::LoadStatus status = gdextension_manager->load_extension_from_function("libgodot://main", ptr);
return status == GDExtensionManager::LoadStatus::LOAD_STATUS_OK;
}
bool GodotInstance::start() {
print_verbose("GodotInstance::start()");
Error err = Main::setup2();
if (err != OK) {
return false;
}
started = Main::start() == EXIT_SUCCESS;
if (started) {
OS::get_singleton()->get_main_loop()->initialize();
}
return started;
}
bool GodotInstance::is_started() {
return started;
}
bool GodotInstance::iteration() {
DisplayServer::get_singleton()->process_events();
return Main::iteration();
}
void GodotInstance::stop() {
print_verbose("GodotInstance::stop()");
if (started) {
OS::get_singleton()->get_main_loop()->finalize();
}
started = false;
}
void GodotInstance::focus_out() {
print_verbose("GodotInstance::focus_out()");
if (started) {
if (OS::get_singleton()->get_main_loop()) {
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT);
}
}
}
void GodotInstance::focus_in() {
print_verbose("GodotInstance::focus_in()");
if (started) {
if (OS::get_singleton()->get_main_loop()) {
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN);
}
}
}
void GodotInstance::pause() {
print_verbose("GodotInstance::pause()");
if (started) {
if (OS::get_singleton()->get_main_loop()) {
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_PAUSED);
}
}
}
void GodotInstance::resume() {
print_verbose("GodotInstance::resume()");
if (started) {
if (OS::get_singleton()->get_main_loop()) {
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_RESUMED);
}
}
}

View file

@ -1,59 +0,0 @@
/**************************************************************************/
/* godot_instance.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "core/extension/gdextension_interface.h"
#include "core/object/class_db.h"
class GodotInstance : public Object {
GDCLASS(GodotInstance, Object);
bool started = false;
protected:
static void _bind_methods();
public:
GodotInstance();
~GodotInstance();
bool initialize(GDExtensionInitializationFunction p_init_func);
bool start();
bool is_started();
bool iteration();
void stop();
void focus_out();
void focus_in();
void pause();
void resume();
};

View file

@ -1,73 +0,0 @@
/**************************************************************************/
/* libgodot.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "gdextension_interface.h"
#ifdef __cplusplus
extern "C" {
#endif
// Export macros for DLL visibility
#if defined(_MSC_VER) || defined(__MINGW32__)
#define LIBGODOT_API __declspec(dllexport)
#elif defined(__GNUC__) || defined(__clang__)
#define LIBGODOT_API __attribute__((visibility("default")))
#endif // if defined(_MSC_VER)
/**
* @name libgodot_create_godot_instance
* @since 4.6
*
* Creates a new Godot instance.
*
* @param p_argc The number of command line arguments.
* @param p_argv The C-style array of command line arguments.
* @param p_init_func GDExtension initialization function of the host application.
*
* @return A pointer to created \ref GodotInstance GDExtension object or nullptr if there was an error.
*/
LIBGODOT_API GDExtensionObjectPtr libgodot_create_godot_instance(int p_argc, char *p_argv[], GDExtensionInitializationFunction p_init_func);
/**
* @name libgodot_destroy_godot_instance
* @since 4.6
*
* Destroys an existing Godot instance.
*
* @param p_godot_instance The reference to the GodotInstance object to destroy.
*
*/
LIBGODOT_API void libgodot_destroy_godot_instance(GDExtensionObjectPtr p_godot_instance);
#ifdef __cplusplus
}
#endif

View file

@ -1756,7 +1756,8 @@ void Input::parse_mapping(const String &p_mapping) {
void Input::add_joy_mapping(const String &p_mapping, bool p_update_existing) {
parse_mapping(p_mapping);
if (p_update_existing) {
const String uid = p_mapping.get_slicec(',', 0);
Vector<String> entry = p_mapping.split(",");
const String &uid = entry[0];
for (KeyValue<int, Joypad> &E : joy_names) {
Joypad &joy = E.value;
if (joy.uid == uid) {

View file

@ -34,7 +34,6 @@
#include "core/object/object.h"
#include "core/os/keyboard.h"
#include "core/os/thread_safe.h"
#include "core/templates/rb_map.h"
#include "core/templates/rb_set.h"
#include "core/variant/typed_array.h"

View file

@ -260,12 +260,12 @@ String InputEventWithModifiers::as_text() const {
if (is_ctrl_pressed()) {
mod_names.push_back(find_keycode_name(Key::CTRL));
}
if (is_alt_pressed()) {
mod_names.push_back(find_keycode_name(Key::ALT));
}
if (is_shift_pressed()) {
mod_names.push_back(find_keycode_name(Key::SHIFT));
}
if (is_alt_pressed()) {
mod_names.push_back(find_keycode_name(Key::ALT));
}
if (is_meta_pressed()) {
mod_names.push_back(find_keycode_name(Key::META));
}
@ -277,7 +277,7 @@ String InputEventWithModifiers::as_text() const {
}
}
String InputEventWithModifiers::_to_string() {
String InputEventWithModifiers::to_string() {
return as_text();
}
@ -488,7 +488,7 @@ String InputEventKey::as_text() const {
return mods_text.is_empty() ? kc : mods_text + "+" + kc;
}
String InputEventKey::_to_string() {
String InputEventKey::to_string() {
String p = is_pressed() ? "true" : "false";
String e = is_echo() ? "true" : "false";
@ -848,7 +848,7 @@ String InputEventMouseButton::as_text() const {
return full_string;
}
String InputEventMouseButton::_to_string() {
String InputEventMouseButton::to_string() {
String p = is_pressed() ? "true" : "false";
String canceled_state = is_canceled() ? "true" : "false";
String d = double_click ? "true" : "false";
@ -988,7 +988,7 @@ String InputEventMouseMotion::as_text() const {
return vformat(RTR("Mouse motion at position (%s) with velocity (%s)"), String(get_position()), String(get_velocity()));
}
String InputEventMouseMotion::_to_string() {
String InputEventMouseMotion::to_string() {
BitField<MouseButtonMask> mouse_button_mask = get_button_mask();
String button_mask_string = itos((int64_t)mouse_button_mask);
@ -1184,16 +1184,15 @@ String InputEventJoypadMotion::as_text() const {
return vformat(RTR("Joypad Motion on Axis %d (%s) with Value %.2f"), axis, desc, axis_value);
}
String InputEventJoypadMotion::_to_string() {
String InputEventJoypadMotion::to_string() {
return vformat("InputEventJoypadMotion: axis=%d, axis_value=%.2f", axis, axis_value);
}
Ref<InputEventJoypadMotion> InputEventJoypadMotion::create_reference(JoyAxis p_axis, float p_value, int p_device) {
Ref<InputEventJoypadMotion> InputEventJoypadMotion::create_reference(JoyAxis p_axis, float p_value) {
Ref<InputEventJoypadMotion> ie;
ie.instantiate();
ie->set_axis(p_axis);
ie->set_axis_value(p_value);
ie->set_device(p_device);
return ie;
}
@ -1303,16 +1302,15 @@ String InputEventJoypadButton::as_text() const {
return text;
}
String InputEventJoypadButton::_to_string() {
String InputEventJoypadButton::to_string() {
String p = is_pressed() ? "true" : "false";
return vformat("InputEventJoypadButton: button_index=%d, pressed=%s, pressure=%.2f", button_index, p, pressure);
}
Ref<InputEventJoypadButton> InputEventJoypadButton::create_reference(JoyButton p_btn_index, int p_device) {
Ref<InputEventJoypadButton> InputEventJoypadButton::create_reference(JoyButton p_btn_index) {
Ref<InputEventJoypadButton> ie;
ie.instantiate();
ie->set_button_index(p_btn_index);
ie->set_device(p_device);
return ie;
}
@ -1386,7 +1384,7 @@ String InputEventScreenTouch::as_text() const {
return vformat(RTR("Screen %s at (%s) with %s touch points"), status, String(get_position()), itos(index));
}
String InputEventScreenTouch::_to_string() {
String InputEventScreenTouch::to_string() {
String p = pressed ? "true" : "false";
String canceled_state = canceled ? "true" : "false";
String double_tap_string = double_tap ? "true" : "false";
@ -1514,7 +1512,7 @@ String InputEventScreenDrag::as_text() const {
return vformat(RTR("Screen dragged with %s touch points at position (%s) with velocity of (%s)"), itos(index), String(get_position()), String(get_velocity()));
}
String InputEventScreenDrag::_to_string() {
String InputEventScreenDrag::to_string() {
return vformat("InputEventScreenDrag: index=%d, position=(%s), relative=(%s), velocity=(%s), pressure=%.2f, tilt=(%s), pen_inverted=(%s)", index, String(get_position()), String(get_relative()), String(get_velocity()), get_pressure(), String(get_tilt()), get_pen_inverted());
}
@ -1656,7 +1654,7 @@ String InputEventAction::as_text() const {
return String();
}
String InputEventAction::_to_string() {
String InputEventAction::to_string() {
String p = is_pressed() ? "true" : "false";
return vformat("InputEventAction: action=\"%s\", pressed=%s", action, p);
}
@ -1727,7 +1725,7 @@ String InputEventMagnifyGesture::as_text() const {
return vformat(RTR("Magnify Gesture at (%s) with factor %s"), String(get_position()), rtos(get_factor()));
}
String InputEventMagnifyGesture::_to_string() {
String InputEventMagnifyGesture::to_string() {
return vformat("InputEventMagnifyGesture: factor=%.2f, position=(%s)", factor, String(get_position()));
}
@ -1769,7 +1767,7 @@ String InputEventPanGesture::as_text() const {
return vformat(RTR("Pan Gesture at (%s) with delta (%s)"), String(get_position()), String(get_delta()));
}
String InputEventPanGesture::_to_string() {
String InputEventPanGesture::to_string() {
return vformat("InputEventPanGesture: delta=(%s), position=(%s)", String(get_delta()), String(get_position()));
}
@ -1850,7 +1848,7 @@ String InputEventMIDI::as_text() const {
return vformat(RTR("MIDI Input on Channel=%s Message=%s"), itos(channel), itos((int64_t)message));
}
String InputEventMIDI::_to_string() {
String InputEventMIDI::to_string() {
String ret;
switch (message) {
case MIDIMessage::NOTE_ON:
@ -1926,7 +1924,7 @@ String InputEventShortcut::as_text() const {
return vformat(RTR("Input Event with Shortcut=%s"), shortcut->get_as_text());
}
String InputEventShortcut::_to_string() {
String InputEventShortcut::to_string() {
ERR_FAIL_COND_V(shortcut.is_null(), "None");
return vformat("InputEventShortcut: shortcut=%s", shortcut->get_as_text());

View file

@ -146,7 +146,7 @@ public:
BitField<KeyModifierMask> get_modifiers_mask() const;
virtual String as_text() const override;
virtual String _to_string() override;
virtual String to_string() override;
InputEventWithModifiers() {}
};
@ -200,7 +200,7 @@ public:
virtual String as_text_key_label() const;
virtual String as_text_location() const;
virtual String as_text() const override;
virtual String _to_string() override;
virtual String to_string() override;
static Ref<InputEventKey> create_reference(Key p_keycode_with_modifier_masks, bool p_physical = false);
@ -263,7 +263,7 @@ public:
virtual bool is_action_type() const override { return true; }
virtual String as_text() const override;
virtual String _to_string() override;
virtual String to_string() override;
InputEventType get_type() const final override { return InputEventType::MOUSE_BUTTON; }
@ -308,7 +308,7 @@ public:
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
virtual String as_text() const override;
virtual String _to_string() override;
virtual String to_string() override;
virtual bool accumulate(const Ref<InputEvent> &p_event) override;
@ -337,10 +337,9 @@ public:
virtual bool is_action_type() const override { return true; }
virtual String as_text() const override;
virtual String _to_string() override;
virtual String to_string() override;
// The default device ID is `InputMap::ALL_DEVICES`.
static Ref<InputEventJoypadMotion> create_reference(JoyAxis p_axis, float p_value, int p_device = -1);
static Ref<InputEventJoypadMotion> create_reference(JoyAxis p_axis, float p_value);
InputEventType get_type() const final override { return InputEventType::JOY_MOTION; }
@ -370,10 +369,9 @@ public:
virtual bool is_action_type() const override { return true; }
virtual String as_text() const override;
virtual String _to_string() override;
virtual String to_string() override;
// The default device ID is `InputMap::ALL_DEVICES`.
static Ref<InputEventJoypadButton> create_reference(JoyButton p_btn_index, int p_device = -1);
static Ref<InputEventJoypadButton> create_reference(JoyButton p_btn_index);
InputEventType get_type() const final override { return InputEventType::JOY_BUTTON; }
@ -404,7 +402,7 @@ public:
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
virtual String as_text() const override;
virtual String _to_string() override;
virtual String to_string() override;
InputEventType get_type() const final override { return InputEventType::SCREEN_TOUCH; }
@ -456,7 +454,7 @@ public:
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
virtual String as_text() const override;
virtual String _to_string() override;
virtual String to_string() override;
virtual bool accumulate(const Ref<InputEvent> &p_event) override;
@ -495,7 +493,7 @@ public:
virtual bool is_action_type() const override { return true; }
virtual String as_text() const override;
virtual String _to_string() override;
virtual String to_string() override;
InputEventType get_type() const final override { return InputEventType::ACTION; }
@ -528,7 +526,7 @@ public:
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
virtual String as_text() const override;
virtual String _to_string() override;
virtual String to_string() override;
InputEventType get_type() const final override { return InputEventType::MAGNIFY_GESTURE; }
@ -548,7 +546,7 @@ public:
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
virtual String as_text() const override;
virtual String _to_string() override;
virtual String to_string() override;
InputEventType get_type() const final override { return InputEventType::PAN_GESTURE; }
@ -596,7 +594,7 @@ public:
int get_controller_value() const;
virtual String as_text() const override;
virtual String _to_string() override;
virtual String to_string() override;
InputEventType get_type() const final override { return InputEventType::MIDI; }
@ -616,7 +614,7 @@ public:
Ref<Shortcut> get_shortcut();
virtual String as_text() const override;
virtual String _to_string() override;
virtual String to_string() override;
InputEventType get_type() const final override { return InputEventType::SHORTCUT; }

View file

@ -403,12 +403,9 @@ static const _BuiltinActionDisplayName _builtin_action_display_names[] = {
{ "ui_graph_delete", TTRC("Delete Nodes") },
{ "ui_graph_follow_left", TTRC("Follow Input Port Connection") },
{ "ui_graph_follow_right", TTRC("Follow Output Port Connection") },
{ "ui_filedialog_delete", TTRC("Delete") },
{ "ui_filedialog_up_one_level", TTRC("Go Up One Level") },
{ "ui_filedialog_refresh", TTRC("Refresh") },
{ "ui_filedialog_show_hidden", TTRC("Show Hidden") },
{ "ui_filedialog_find", TTRC("Find") },
{ "ui_filedialog_focus_path", TTRC("Focus Path") },
{ "ui_swap_input_direction ", TTRC("Swap Input Direction") },
{ "ui_unicode_start", TTRC("Start Unicode Character Input") },
{ "ui_colorpicker_delete_preset", TTRC("ColorPicker: Delete Preset") },
@ -418,7 +415,7 @@ static const _BuiltinActionDisplayName _builtin_action_display_names[] = {
};
String InputMap::get_builtin_display_name(const String &p_name) const {
constexpr int len = std_size(_builtin_action_display_names);
constexpr int len = std::size(_builtin_action_display_names);
for (int i = 0; i < len; i++) {
if (_builtin_action_display_names[i].name == p_name) {
@ -807,10 +804,6 @@ const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
default_builtin_cache.insert("ui_graph_follow_right.macos", inputs);
// ///// UI File Dialog Shortcuts /////
inputs = List<Ref<InputEvent>>();
inputs.push_back(InputEventKey::create_reference(Key::KEY_DELETE));
default_builtin_cache.insert("ui_filedialog_delete", inputs);
inputs = List<Ref<InputEvent>>();
inputs.push_back(InputEventKey::create_reference(Key::BACKSPACE));
default_builtin_cache.insert("ui_filedialog_up_one_level", inputs);
@ -823,22 +816,6 @@ const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
inputs.push_back(InputEventKey::create_reference(Key::H));
default_builtin_cache.insert("ui_filedialog_show_hidden", inputs);
inputs = List<Ref<InputEvent>>();
inputs.push_back(InputEventKey::create_reference(Key::F | KeyModifierMask::CMD_OR_CTRL));
default_builtin_cache.insert("ui_filedialog_find", inputs);
inputs = List<Ref<InputEvent>>();
// Ctrl + L (matches most Windows/Linux file managers' "focus on path bar" shortcut,
// plus macOS Safari's "focus on address bar" shortcut).
inputs.push_back(InputEventKey::create_reference(Key::L | KeyModifierMask::CMD_OR_CTRL));
default_builtin_cache.insert("ui_filedialog_focus_path", inputs);
inputs = List<Ref<InputEvent>>();
// Cmd + Shift + G (matches Finder's "Go To" shortcut).
inputs.push_back(InputEventKey::create_reference(Key::G | KeyModifierMask::CMD_OR_CTRL));
inputs.push_back(InputEventKey::create_reference(Key::L | KeyModifierMask::CMD_OR_CTRL));
default_builtin_cache.insert("ui_filedialog_focus_path.macos", inputs);
inputs = List<Ref<InputEvent>>();
inputs.push_back(InputEventKey::create_reference(Key::QUOTELEFT | KeyModifierMask::CMD_OR_CTRL));
default_builtin_cache.insert("ui_swap_input_direction", inputs);
@ -866,8 +843,9 @@ const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins_with_featur
for (const KeyValue<String, List<Ref<InputEvent>>> &E : builtins) {
String fullname = E.key;
const String &name = fullname.get_slicec('.', 0);
String override_for = fullname.get_slice_count(".") > 1 ? fullname.get_slicec('.', 1) : String();
Vector<String> split = fullname.split(".");
const String &name = split[0];
String override_for = split.size() > 1 ? split[1] : String();
if (!override_for.is_empty() && OS::get_singleton()->has_feature(override_for)) {
builtins_with_overrides[name].push_back(override_for);
@ -877,8 +855,9 @@ const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins_with_featur
for (const KeyValue<String, List<Ref<InputEvent>>> &E : builtins) {
String fullname = E.key;
const String &name = fullname.get_slicec('.', 0);
String override_for = fullname.get_slice_count(".") > 1 ? fullname.get_slicec('.', 1) : String();
Vector<String> split = fullname.split(".");
const String &name = split[0];
String override_for = split.size() > 1 ? split[1] : String();
if (builtins_with_overrides.has(name) && override_for.is_empty()) {
// Builtin has an override but this particular one is not an override, so skip.

View file

@ -85,17 +85,6 @@ String Shortcut::get_as_text() const {
return "None";
}
Ref<Shortcut> Shortcut::make_from_action(const StringName &p_action) {
Ref<InputEventAction> event;
event.instantiate();
event->set_action(p_action);
Ref<Shortcut> shortcut;
shortcut.instantiate();
shortcut->set_events({ event });
return shortcut;
}
bool Shortcut::has_valid_event() const {
// Tests if there is ANY input event which is valid.
for (int i = 0; i < events.size(); i++) {

View file

@ -52,7 +52,5 @@ public:
String get_as_text() const;
static Ref<Shortcut> make_from_action(const StringName &p_action);
static bool is_event_array_equal(const Array &p_event_array1, const Array &p_event_array2);
};

View file

@ -90,14 +90,6 @@ void FileAccess::store_pascal_string_bind_compat_78289(const String &p_string) {
store_pascal_string(p_string);
}
String FileAccess::get_as_text_bind_compat_110867(bool p_skip_cr) const {
String text = get_as_text();
if (unlikely(p_skip_cr)) {
text = text.remove_char('\r');
}
return text;
}
void FileAccess::_bind_compatibility_methods() {
ClassDB::bind_compatibility_static_method("FileAccess", D_METHOD("open_encrypted", "path", "mode_flags", "key"), &FileAccess::_open_encrypted_bind_compat_98918);
@ -115,7 +107,6 @@ void FileAccess::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("store_string", "string"), &FileAccess::store_string_bind_compat_78289);
ClassDB::bind_compatibility_method(D_METHOD("store_var", "value", "full_objects"), &FileAccess::store_var_bind_compat_78289, DEFVAL(false));
ClassDB::bind_compatibility_method(D_METHOD("store_pascal_string", "string"), &FileAccess::store_pascal_string_bind_compat_78289);
ClassDB::bind_compatibility_method(D_METHOD("get_as_text", "skip_cr"), &FileAccess::get_as_text_bind_compat_110867, DEFVAL(false));
}
#endif

View file

@ -37,7 +37,6 @@
#include "core/io/file_access_encrypted.h"
#include "core/io/file_access_pack.h"
#include "core/io/marshalls.h"
#include "core/io/resource_uid.h"
#include "core/os/os.h"
#include "core/os/time.h"
@ -82,12 +81,12 @@ Ref<FileAccess> FileAccess::create_for_path(const String &p_path) {
Ref<FileAccess> FileAccess::create_temp(int p_mode_flags, const String &p_prefix, const String &p_extension, bool p_keep, Error *r_error) {
const String ERROR_COMMON_PREFIX = "Error while creating temporary file";
if (!p_prefix.is_empty() && !p_prefix.is_valid_filename()) {
if (!p_prefix.is_valid_filename()) {
*r_error = ERR_FILE_BAD_PATH;
ERR_FAIL_V_MSG(Ref<FileAccess>(), vformat(R"(%s: "%s" is not a valid prefix.)", ERROR_COMMON_PREFIX, p_prefix));
}
if (!p_extension.is_empty() && !p_extension.is_valid_filename()) {
if (!p_extension.is_valid_filename()) {
*r_error = ERR_FILE_BAD_PATH;
ERR_FAIL_V_MSG(Ref<FileAccess>(), vformat(R"(%s: "%s" is not a valid extension.)", ERROR_COMMON_PREFIX, p_extension));
}
@ -446,7 +445,7 @@ class CharBuffer {
public:
_FORCE_INLINE_ CharBuffer() :
buffer(stack_buffer),
capacity(std_size(stack_buffer)) {
capacity(std::size(stack_buffer)) {
}
_FORCE_INLINE_ void push_back(char c) {
@ -468,22 +467,10 @@ String FileAccess::get_line() const {
uint8_t c = get_8();
while (!eof_reached()) {
if (c == '\r' || c == '\n' || c == '\0' || get_error() != OK) {
if (c == '\r') {
// Check for Windows-style EOL.
const uint64_t prev_pos = get_position() - 1;
if (unlikely(get_8() != '\n')) {
// HACK: We can't simply check the next value in a vacuum, so we risk triggering
// an EOL false-positive in the unlikely event that this `\r` was the final
// value of the file. Unilaterally work around by re-reading the *previous*
// byte (the starting `\r`) to ensure `get_error()` returns `OK`.
const_cast<FileAccess *>(this)->seek(prev_pos);
get_8();
}
}
if (c == '\n' || c == '\0' || get_error() != OK) {
line.push_back(0);
return String::utf8(line.get_data());
} else {
} else if (c != '\r') {
line.push_back(char(c));
}
@ -551,11 +538,11 @@ Vector<String> FileAccess::get_csv_line(const String &p_delim) const {
return strings;
}
String FileAccess::get_as_text() const {
String FileAccess::get_as_text(bool p_skip_cr) const {
uint64_t original_pos = get_position();
const_cast<FileAccess *>(this)->seek(0);
String text = get_as_utf8_string();
String text = get_as_utf8_string(p_skip_cr);
const_cast<FileAccess *>(this)->seek(original_pos);
@ -570,7 +557,6 @@ Vector<uint8_t> FileAccess::get_buffer(int64_t p_length) const {
return data;
}
data.reserve_exact(p_length);
Error err = data.resize(p_length);
ERR_FAIL_COND_V_MSG(err != OK, data, vformat("Can't resize data to %d elements.", p_length));
@ -584,7 +570,7 @@ Vector<uint8_t> FileAccess::get_buffer(int64_t p_length) const {
return data;
}
String FileAccess::get_as_utf8_string() const {
String FileAccess::get_as_utf8_string(bool p_skip_cr) const {
Vector<uint8_t> sourcef;
uint64_t len = get_length();
sourcef.resize(len + 1);
@ -595,7 +581,7 @@ String FileAccess::get_as_utf8_string() const {
w[len] = 0;
String s;
s.append_utf8((const char *)w, len);
s.append_utf8((const char *)w, len, p_skip_cr);
return s;
}
@ -865,7 +851,6 @@ Vector<uint8_t> FileAccess::get_file_as_bytes(const String &p_path, Error *r_err
ERR_FAIL_V_MSG(Vector<uint8_t>(), vformat("Can't open file from path '%s'.", String(p_path)));
}
Vector<uint8_t> data;
data.reserve_exact(f->get_length());
data.resize(f->get_length());
f->get_buffer(data.ptrw(), data.size());
return data;
@ -1002,7 +987,7 @@ void FileAccess::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_buffer", "length"), (Vector<uint8_t> (FileAccess::*)(int64_t) const) & FileAccess::get_buffer);
ClassDB::bind_method(D_METHOD("get_line"), &FileAccess::get_line);
ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &FileAccess::get_csv_line, DEFVAL(","));
ClassDB::bind_method(D_METHOD("get_as_text"), &FileAccess::get_as_text);
ClassDB::bind_method(D_METHOD("get_as_text", "skip_cr"), &FileAccess::get_as_text, DEFVAL(false));
ClassDB::bind_static_method("FileAccess", D_METHOD("get_md5", "path"), &FileAccess::get_md5);
ClassDB::bind_static_method("FileAccess", D_METHOD("get_sha256", "path"), &FileAccess::get_sha256);
ClassDB::bind_method(D_METHOD("is_big_endian"), &FileAccess::is_big_endian);

View file

@ -132,7 +132,6 @@ protected:
void store_line_bind_compat_78289(const String &p_line);
void store_csv_line_bind_compat_78289(const Vector<String> &p_values, const String &p_delim = ",");
void store_pascal_string_bind_compat_78289(const String &p_string);
String get_as_text_bind_compat_110867(bool p_skip_cr) const;
static void _bind_compatibility_methods();
#endif
@ -189,8 +188,8 @@ public:
virtual String get_line() const;
virtual String get_token() const;
virtual Vector<String> get_csv_line(const String &p_delim = ",") const;
String get_as_text() const;
virtual String get_as_utf8_string() const;
String get_as_text(bool p_skip_cr = false) const;
virtual String get_as_utf8_string(bool p_skip_cr = false) const;
/**

View file

@ -130,37 +130,34 @@ void FileAccessCompressed::_close() {
f->store_32(0); //compressed sizes, will update later
}
uint32_t last_block_size = write_max % block_size;
// Temporary buffer for compressed data blocks.
LocalVector<uint8_t> temp_cblock;
temp_cblock.resize(Compression::get_max_compressed_buffer_size(bc == 1 ? last_block_size : block_size, cmode));
uint8_t *temp_cblock_ptr = temp_cblock.ptr();
// Compress and store the blocks.
LocalVector<uint32_t> block_sizes;
Vector<int> block_sizes;
for (uint32_t i = 0; i < bc; i++) {
uint32_t bl = i == (bc - 1) ? last_block_size : block_size;
uint32_t bl = i == (bc - 1) ? write_max % block_size : block_size;
uint8_t *bp = &write_ptr[i * block_size];
const int64_t compressed_size = Compression::compress(temp_cblock_ptr, bp, bl, cmode);
Vector<uint8_t> cblock;
cblock.resize(Compression::get_max_compressed_buffer_size(bl, cmode));
const int64_t compressed_size = Compression::compress(cblock.ptrw(), bp, bl, cmode);
ERR_FAIL_COND_MSG(compressed_size < 0, "FileAccessCompressed: Error compressing data.");
f->store_buffer(temp_cblock_ptr, (uint64_t)compressed_size);
f->store_buffer(cblock.ptr(), (uint64_t)compressed_size);
block_sizes.push_back(compressed_size);
}
f->seek(16); //ok write block sizes
for (uint32_t i = 0; i < bc; i++) {
f->store_32(block_sizes[i]);
f->store_32(uint32_t(block_sizes[i]));
}
f->seek_end();
f->store_buffer((const uint8_t *)mgc.get_data(), mgc.length()); //magic at the end too
buffer.clear();
} else {
comp_buffer.clear();
buffer.clear();
read_blocks.clear();
}
buffer.clear();
f.unref();
}

View file

@ -140,7 +140,7 @@ void FileAccessEncrypted::_close() {
}
if (writing) {
LocalVector<uint8_t> compressed;
Vector<uint8_t> compressed;
uint64_t len = data.size();
if (len % 16) {
len += 16 - (len % 16);
@ -150,8 +150,10 @@ void FileAccessEncrypted::_close() {
ERR_FAIL_COND(CryptoCore::md5(data.ptr(), data.size(), hash) != OK); // Bug?
compressed.resize(len);
memcpy(compressed.ptr(), data.ptr(), data.size());
memset(compressed.ptr() + data.size(), 0, len - data.size());
memset(compressed.ptrw(), 0, len);
for (int i = 0; i < data.size(); i++) {
compressed.write[i] = data[i];
}
CryptoCore::AESContext ctx;
ctx.set_encode_key(key.ptrw(), 256);
@ -164,7 +166,7 @@ void FileAccessEncrypted::_close() {
file->store_64(data.size());
file->store_buffer(iv.ptr(), 16);
ctx.encrypt_cfb(len, iv.ptrw(), compressed.ptr(), compressed.ptr());
ctx.encrypt_cfb(len, iv.ptrw(), compressed.ptrw(), compressed.ptrw());
file->store_buffer(compressed.ptr(), compressed.size());
data.clear();

View file

@ -35,8 +35,6 @@
#include "core/crypto/crypto.h"
class HTTPClientTCP : public HTTPClient {
GDSOFTCLASS(HTTPClientTCP, HTTPClient);
private:
Status status = STATUS_DISCONNECTED;
IP::ResolverID resolving = IP::RESOLVER_INVALID_ID;

View file

@ -78,14 +78,6 @@ const char *Image::format_names[Image::FORMAT_MAX] = {
"ASTC_4x4_HDR",
"ASTC_8x8",
"ASTC_8x8_HDR",
"R16",
"RG16",
"RGB16",
"RGBA16",
"R16Int",
"RG16Int",
"RGB16Int",
"RGBA16Int",
};
// External VRAM compression function pointers.
@ -209,22 +201,6 @@ int Image::get_format_pixel_size(Format p_format) {
return 1;
case FORMAT_ASTC_8x8_HDR:
return 1;
case FORMAT_R16:
return 2;
case FORMAT_RG16:
return 4;
case FORMAT_RGB16:
return 6;
case FORMAT_RGBA16:
return 8;
case FORMAT_R16I:
return 2;
case FORMAT_RG16I:
return 4;
case FORMAT_RGB16I:
return 6;
case FORMAT_RGBA16I:
return 8;
case FORMAT_MAX: {
}
}
@ -783,78 +759,6 @@ void Image::convert(Format p_new_format) {
case FORMAT_RGBAF | (FORMAT_RGBF << 8):
_convert_fast<uint32_t, 4, 3, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
break;
case FORMAT_R16 | (FORMAT_RG16 << 8):
_convert_fast<uint16_t, 1, 2, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_R16 | (FORMAT_RGB16 << 8):
_convert_fast<uint16_t, 1, 3, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_R16 | (FORMAT_RGBA16 << 8):
_convert_fast<uint16_t, 1, 4, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RG16 | (FORMAT_R16 << 8):
_convert_fast<uint16_t, 2, 1, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RG16 | (FORMAT_RGB16 << 8):
_convert_fast<uint16_t, 2, 3, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RG16 | (FORMAT_RGBA16 << 8):
_convert_fast<uint16_t, 2, 4, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RGB16 | (FORMAT_R16 << 8):
_convert_fast<uint16_t, 3, 1, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RGB16 | (FORMAT_RG16 << 8):
_convert_fast<uint16_t, 3, 2, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RGB16 | (FORMAT_RGBA16 << 8):
_convert_fast<uint16_t, 3, 4, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RGBA16 | (FORMAT_R16 << 8):
_convert_fast<uint16_t, 4, 1, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RGBA16 | (FORMAT_RG16 << 8):
_convert_fast<uint16_t, 4, 2, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RGBA16 | (FORMAT_RGB16 << 8):
_convert_fast<uint16_t, 4, 3, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_R16I | (FORMAT_RG16I << 8):
_convert_fast<uint16_t, 1, 2, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_R16I | (FORMAT_RGB16I << 8):
_convert_fast<uint16_t, 1, 3, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_R16I | (FORMAT_RGBA16I << 8):
_convert_fast<uint16_t, 1, 4, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RG16I | (FORMAT_R16I << 8):
_convert_fast<uint16_t, 2, 1, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RG16I | (FORMAT_RGB16I << 8):
_convert_fast<uint16_t, 2, 3, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RG16I | (FORMAT_RGBA16I << 8):
_convert_fast<uint16_t, 2, 4, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RGB16I | (FORMAT_R16I << 8):
_convert_fast<uint16_t, 3, 1, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RGB16I | (FORMAT_RG16I << 8):
_convert_fast<uint16_t, 3, 2, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RGB16I | (FORMAT_RGBA16I << 8):
_convert_fast<uint16_t, 3, 4, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RGBA16I | (FORMAT_R16I << 8):
_convert_fast<uint16_t, 4, 1, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RGBA16I | (FORMAT_RG16I << 8):
_convert_fast<uint16_t, 4, 2, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RGBA16I | (FORMAT_RGB16I << 8):
_convert_fast<uint16_t, 4, 3, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
}
}
@ -865,11 +769,6 @@ Image::Format Image::get_format() const {
return format;
}
enum ImageScaleType {
IMAGE_SCALING_INT,
IMAGE_SCALING_FLOAT,
};
static double _bicubic_interp_kernel(double x) {
x = Math::abs(x);
@ -884,7 +783,7 @@ static double _bicubic_interp_kernel(double x) {
return bc;
}
template <int CC, typename T, ImageScaleType TYPE>
template <int CC, typename T>
static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
// get source image size
int width = p_src_width;
@ -946,7 +845,7 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_
const T *__restrict p = ((T *)p_src) + (oy2 * p_src_width + ox2) * CC;
for (int i = 0; i < CC; i++) {
if constexpr (sizeof(T) == 2 && TYPE == IMAGE_SCALING_FLOAT) { //half float
if constexpr (sizeof(T) == 2) { //half float
color[i] = Math::half_to_float(p[i]);
} else {
color[i] += p[i] * k2;
@ -958,12 +857,8 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_
for (int i = 0; i < CC; i++) {
if constexpr (sizeof(T) == 1) { //byte
dst[i] = CLAMP(Math::fast_ftoi(color[i]), 0, 255);
} else if constexpr (sizeof(T) == 2) {
if constexpr (TYPE == IMAGE_SCALING_FLOAT) {
dst[i] = Math::make_half_float(color[i]); //half float
} else {
dst[i] = CLAMP(Math::fast_ftoi(color[i]), 0, 65535); // uint16
}
} else if constexpr (sizeof(T) == 2) { //half float
dst[i] = Math::make_half_float(color[i]);
} else {
dst[i] = color[i];
}
@ -972,7 +867,7 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_
}
}
template <int CC, typename T, ImageScaleType TYPE>
template <int CC, typename T>
static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
constexpr uint32_t FRAC_BITS = 8;
constexpr uint32_t FRAC_LEN = (1 << FRAC_BITS);
@ -1020,40 +915,23 @@ static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict
uint32_t interp = interp_up + (((interp_down - interp_up) * src_yofs_frac) >> FRAC_BITS);
interp >>= FRAC_BITS;
p_dst[i * p_dst_width * CC + j * CC + l] = uint8_t(interp);
} else if constexpr (sizeof(T) == 2) {
if constexpr (TYPE == IMAGE_SCALING_FLOAT) { //half float
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
float yofs_frac = float(src_yofs_frac) / (1 << FRAC_BITS);
const T *src = ((const T *)p_src);
T *dst = ((T *)p_dst);
} else if constexpr (sizeof(T) == 2) { //half float
float p00 = Math::half_to_float(src[y_ofs_up + src_xofs_left + l]);
float p10 = Math::half_to_float(src[y_ofs_up + src_xofs_right + l]);
float p01 = Math::half_to_float(src[y_ofs_down + src_xofs_left + l]);
float p11 = Math::half_to_float(src[y_ofs_down + src_xofs_right + l]);
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
float yofs_frac = float(src_yofs_frac) / (1 << FRAC_BITS);
const T *src = ((const T *)p_src);
T *dst = ((T *)p_dst);
float interp_up = p00 + (p10 - p00) * xofs_frac;
float interp_down = p01 + (p11 - p01) * xofs_frac;
float interp = interp_up + ((interp_down - interp_up) * yofs_frac);
float p00 = Math::half_to_float(src[y_ofs_up + src_xofs_left + l]);
float p10 = Math::half_to_float(src[y_ofs_up + src_xofs_right + l]);
float p01 = Math::half_to_float(src[y_ofs_down + src_xofs_left + l]);
float p11 = Math::half_to_float(src[y_ofs_down + src_xofs_right + l]);
dst[i * p_dst_width * CC + j * CC + l] = Math::make_half_float(interp);
} else { //uint16
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
float yofs_frac = float(src_yofs_frac) / (1 << FRAC_BITS);
const T *src = ((const T *)p_src);
T *dst = ((T *)p_dst);
float interp_up = p00 + (p10 - p00) * xofs_frac;
float interp_down = p01 + (p11 - p01) * xofs_frac;
float interp = interp_up + ((interp_down - interp_up) * yofs_frac);
float p00 = src[y_ofs_up + src_xofs_left + l];
float p10 = src[y_ofs_up + src_xofs_right + l];
float p01 = src[y_ofs_down + src_xofs_left + l];
float p11 = src[y_ofs_down + src_xofs_right + l];
float interp_up = p00 + (p10 - p00) * xofs_frac;
float interp_down = p01 + (p11 - p01) * xofs_frac;
float interp = interp_up + ((interp_down - interp_up) * yofs_frac);
dst[i * p_dst_width * CC + j * CC + l] = uint16_t(interp);
}
dst[i * p_dst_width * CC + j * CC + l] = Math::make_half_float(interp);
} else if constexpr (sizeof(T) == 4) { //float
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
@ -1104,7 +982,7 @@ static float _lanczos(float p_x) {
return Math::abs(p_x) >= LANCZOS_TYPE ? 0 : Math::sincn(p_x) * Math::sincn(p_x / LANCZOS_TYPE);
}
template <int CC, typename T, ImageScaleType TYPE>
template <int CC, typename T>
static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
int32_t src_width = p_src_width;
int32_t src_height = p_src_height;
@ -1145,7 +1023,7 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict
const T *__restrict src_data = ((const T *)p_src) + (buffer_y * src_width + target_x) * CC;
for (uint32_t i = 0; i < CC; i++) {
if constexpr (sizeof(T) == 2 && TYPE == IMAGE_SCALING_FLOAT) { //half float
if constexpr (sizeof(T) == 2) { //half float
pixel[i] += Math::half_to_float(src_data[i]) * lanczos_val;
} else {
pixel[i] += src_data[i] * lanczos_val;
@ -1204,13 +1082,8 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict
if constexpr (sizeof(T) == 1) { //byte
dst_data[i] = CLAMP(Math::fast_ftoi(pixel[i]), 0, 255);
} else if constexpr (sizeof(T) == 2) {
if constexpr (TYPE == IMAGE_SCALING_FLOAT) { //half float
dst_data[i] = Math::make_half_float(pixel[i]);
} else { //uint16
dst_data[i] = CLAMP(Math::fast_ftoi(pixel[i]), 0, 65535);
}
} else if constexpr (sizeof(T) == 2) { //half float
dst_data[i] = Math::make_half_float(pixel[i]);
} else { // float
dst_data[i] = pixel[i];
}
@ -1353,21 +1226,6 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
_scale_nearest<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
}
} else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
switch (get_format_pixel_size(format)) {
case 2:
_scale_nearest<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 4:
_scale_nearest<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 6:
_scale_nearest<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 8:
_scale_nearest<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
}
}
} break;
@ -1412,61 +1270,46 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
switch (get_format_pixel_size(format)) {
case 1:
_scale_bilinear<1, uint8_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
_scale_bilinear<1, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
break;
case 2:
_scale_bilinear<2, uint8_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
_scale_bilinear<2, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
break;
case 3:
_scale_bilinear<3, uint8_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
_scale_bilinear<3, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
break;
case 4:
_scale_bilinear<4, uint8_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
_scale_bilinear<4, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
break;
}
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
switch (get_format_pixel_size(format)) {
case 4:
_scale_bilinear<1, float, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
_scale_bilinear<1, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
break;
case 8:
_scale_bilinear<2, float, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
_scale_bilinear<2, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
break;
case 12:
_scale_bilinear<3, float, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
_scale_bilinear<3, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
break;
case 16:
_scale_bilinear<4, float, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
_scale_bilinear<4, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
break;
}
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
switch (get_format_pixel_size(format)) {
case 2:
_scale_bilinear<1, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
_scale_bilinear<1, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
break;
case 4:
_scale_bilinear<2, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
_scale_bilinear<2, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
break;
case 6:
_scale_bilinear<3, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
_scale_bilinear<3, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
break;
case 8:
_scale_bilinear<4, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
break;
}
} else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
switch (get_format_pixel_size(format)) {
case 2:
_scale_bilinear<1, uint16_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
break;
case 4:
_scale_bilinear<2, uint16_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
break;
case 6:
_scale_bilinear<3, uint16_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
break;
case 8:
_scale_bilinear<4, uint16_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
_scale_bilinear<4, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
break;
}
}
@ -1483,61 +1326,46 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
switch (get_format_pixel_size(format)) {
case 1:
_scale_cubic<1, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_cubic<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 2:
_scale_cubic<2, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_cubic<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 3:
_scale_cubic<3, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_cubic<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 4:
_scale_cubic<4, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_cubic<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
}
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
switch (get_format_pixel_size(format)) {
case 4:
_scale_cubic<1, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_cubic<1, float>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 8:
_scale_cubic<2, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_cubic<2, float>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 12:
_scale_cubic<3, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_cubic<3, float>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 16:
_scale_cubic<4, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_cubic<4, float>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
}
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
switch (get_format_pixel_size(format)) {
case 2:
_scale_cubic<1, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_cubic<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 4:
_scale_cubic<2, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_cubic<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 6:
_scale_cubic<3, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_cubic<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 8:
_scale_cubic<4, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
}
} else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
switch (get_format_pixel_size(format)) {
case 2:
_scale_cubic<1, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 4:
_scale_cubic<2, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 6:
_scale_cubic<3, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 8:
_scale_cubic<4, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_cubic<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
}
}
@ -1546,61 +1374,46 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
switch (get_format_pixel_size(format)) {
case 1:
_scale_lanczos<1, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_lanczos<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 2:
_scale_lanczos<2, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_lanczos<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 3:
_scale_lanczos<3, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_lanczos<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 4:
_scale_lanczos<4, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_lanczos<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
}
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
switch (get_format_pixel_size(format)) {
case 4:
_scale_lanczos<1, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_lanczos<1, float>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 8:
_scale_lanczos<2, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_lanczos<2, float>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 12:
_scale_lanczos<3, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_lanczos<3, float>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 16:
_scale_lanczos<4, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_lanczos<4, float>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
}
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
switch (get_format_pixel_size(format)) {
case 2:
_scale_lanczos<1, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_lanczos<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 4:
_scale_lanczos<2, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_lanczos<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 6:
_scale_lanczos<3, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_lanczos<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 8:
_scale_lanczos<4, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
}
} else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
switch (get_format_pixel_size(format)) {
case 2:
_scale_lanczos<1, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 4:
_scale_lanczos<2, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 6:
_scale_lanczos<3, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
case 8:
_scale_lanczos<4, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
_scale_lanczos<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
break;
}
}
@ -1969,7 +1782,7 @@ static void _generate_po2_mipmap(const Component *p_src, Component *p_dst, uint3
average_func(dst_ptr[j], rup_ptr[j], rup_ptr[j + right_step], rdown_ptr[j], rdown_ptr[j + right_step]);
}
if constexpr (renormalize) {
if (renormalize) {
renormalize_func(dst_ptr);
}
@ -2015,12 +1828,6 @@ void Image::_generate_mipmap_from_format(Image::Format p_format, const uint8_t *
_generate_po2_mipmap<uint8_t, 4, false, Image::average_4_uint8, Image::renormalize_uint8>(p_src, p_dst, p_width, p_height);
}
} break;
case Image::FORMAT_RGBA4444: {
_generate_po2_mipmap<uint16_t, 1, false, Image::average_4_rgba4444, nullptr>(src_u16, dst_u16, p_width, p_height);
} break;
case Image::FORMAT_RGB565: {
_generate_po2_mipmap<uint16_t, 1, false, Image::average_4_rgb565, nullptr>(src_u16, dst_u16, p_width, p_height);
} break;
case Image::FORMAT_RF:
_generate_po2_mipmap<float, 1, false, Image::average_4_float, Image::renormalize_float>(src_float, dst_float, p_width, p_height);
break;
@ -2062,32 +1869,8 @@ void Image::_generate_mipmap_from_format(Image::Format p_format, const uint8_t *
}
} break;
case Image::FORMAT_RGBE9995:
_generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, nullptr>(src_u32, dst_u32, p_width, p_height);
_generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(src_u32, dst_u32, p_width, p_height);
break;
case Image::FORMAT_R16:
case Image::FORMAT_R16I:
_generate_po2_mipmap<uint16_t, 1, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
break;
case Image::FORMAT_RG16:
case Image::FORMAT_RG16I:
_generate_po2_mipmap<uint16_t, 2, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
break;
case Image::FORMAT_RGB16:
case Image::FORMAT_RGB16I: {
if (p_renormalize) {
_generate_po2_mipmap<uint16_t, 3, true, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
} else {
_generate_po2_mipmap<uint16_t, 3, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
}
} break;
case Image::FORMAT_RGBA16:
case Image::FORMAT_RGBA16I: {
if (p_renormalize) {
_generate_po2_mipmap<uint16_t, 4, true, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
} else {
_generate_po2_mipmap<uint16_t, 4, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
}
} break;
default:
return;
@ -2147,6 +1930,7 @@ void Image::normalize() {
Error Image::generate_mipmaps(bool p_renormalize) {
ERR_FAIL_COND_V_MSG(is_compressed(), ERR_UNAVAILABLE, "Cannot generate mipmaps from compressed image formats.");
ERR_FAIL_COND_V_MSG(format == FORMAT_RGBA4444, ERR_UNAVAILABLE, "Cannot generate mipmaps from RGBA4444 format.");
ERR_FAIL_COND_V_MSG(width == 0 || height == 0, ERR_UNCONFIGURED, "Cannot generate mipmaps with width or height equal to 0.");
int gen_mipmap_count;
@ -2684,17 +2468,6 @@ bool Image::is_invisible() const {
}
}
} break;
case FORMAT_RGBA16:
case FORMAT_RGBA16I: {
const int pixel_count = len / 8;
const uint16_t *pixeldata = reinterpret_cast<const uint16_t *>(data.ptr());
for (int i = 0; i < pixel_count; i++) {
if (pixeldata[i * 4 + 3] != 0) {
return false;
}
}
} break;
default: {
// Formats that are compressed or don't support alpha channels are presumed to be visible.
return false;
@ -2898,7 +2671,7 @@ bool Image::is_compressed() const {
}
bool Image::is_format_compressed(Format p_format) {
return p_format > FORMAT_RGBE9995 && p_format < FORMAT_R16;
return p_format > FORMAT_RGBE9995;
}
Error Image::decompress() {
@ -3129,17 +2902,20 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const P
int pixel_size = get_format_pixel_size(format);
// If the rect width is equivalent for both src and dst and the x offset is 0, we can blit in a single memcpy.
// Else, we do a per-line copy.
if ((dest_rect.size.x == p_src->width) && (p_src->width == width) && (dest_rect.position.x == 0) && (src_rect.position.x == 0)) {
const uint8_t *src = &src_data_ptr[(src_rect.position.y * p_src->width) * pixel_size];
uint8_t *dst = &dst_data_ptr[(dest_rect.position.y * width) * pixel_size];
memcpy(dst, src, width * dest_rect.size.y * pixel_size);
} else {
for (int i = 0; i < dest_rect.size.y; i++) {
const uint8_t *src = &src_data_ptr[((src_rect.position.y + i) * p_src->width + src_rect.position.x) * pixel_size];
uint8_t *dst = &dst_data_ptr[((dest_rect.position.y + i) * width + dest_rect.position.x) * pixel_size];
memcpy(dst, src, pixel_size * dest_rect.size.x);
for (int i = 0; i < dest_rect.size.y; i++) {
for (int j = 0; j < dest_rect.size.x; j++) {
int src_x = src_rect.position.x + j;
int src_y = src_rect.position.y + i;
int dst_x = dest_rect.position.x + j;
int dst_y = dest_rect.position.y + i;
const uint8_t *src = &src_data_ptr[(src_y * p_src->width + src_x) * pixel_size];
uint8_t *dst = &dst_data_ptr[(dst_y * width + dst_x) * pixel_size];
for (int k = 0; k < pixel_size; k++) {
dst[k] = src[k];
}
}
}
}
@ -3295,13 +3071,13 @@ void Image::fill(const Color &p_color) {
ERR_FAIL_COND_MSG(is_compressed(), "Cannot fill in compressed image formats.");
uint8_t *dst_data_ptr = data.ptrw();
int pixel_size = get_format_pixel_size(format);
int64_t pixel_count = data.size() / pixel_size;
// Put first pixel with the format-aware API.
_set_color_at_ofs(dst_data_ptr, 0, p_color);
_repeat_pixel_over_subsequent_memory(dst_data_ptr, pixel_size, pixel_count);
_repeat_pixel_over_subsequent_memory(dst_data_ptr, pixel_size, width * height);
}
void Image::fill_rect(const Rect2i &p_rect, const Color &p_color) {
@ -3381,42 +3157,6 @@ void Image::_copy_internals_from(const Image &p_image) {
data = p_image.data;
}
_FORCE_INLINE_ Color color_from_rgba4444(uint16_t p_col) {
float r = ((p_col >> 12) & 0xF) / 15.0;
float g = ((p_col >> 8) & 0xF) / 15.0;
float b = ((p_col >> 4) & 0xF) / 15.0;
float a = (p_col & 0xF) / 15.0;
return Color(r, g, b, a);
}
_FORCE_INLINE_ uint16_t color_to_rgba4444(Color p_col) {
uint16_t rgba = 0;
rgba = uint16_t(CLAMP(p_col.r * 15.0, 0, 15)) << 12;
rgba |= uint16_t(CLAMP(p_col.g * 15.0, 0, 15)) << 8;
rgba |= uint16_t(CLAMP(p_col.b * 15.0, 0, 15)) << 4;
rgba |= uint16_t(CLAMP(p_col.a * 15.0, 0, 15));
return rgba;
}
_FORCE_INLINE_ Color color_from_rgb565(uint16_t p_col) {
float r = ((p_col >> 11) & 0x1F) / 31.0;
float g = ((p_col >> 5) & 0x3F) / 63.0;
float b = (p_col & 0x1F) / 31.0;
return Color(r, g, b, 1.0);
}
_FORCE_INLINE_ uint16_t color_to_rgb565(Color p_col) {
uint16_t rgba = 0;
rgba = uint16_t(CLAMP(p_col.r * 31.0, 0, 31)) << 11;
rgba |= uint16_t(CLAMP(p_col.g * 63.0, 0, 63)) << 5;
rgba |= uint16_t(CLAMP(p_col.b * 31.0, 0, 31));
return rgba;
}
Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const {
switch (format) {
case FORMAT_L8: {
@ -3451,10 +3191,19 @@ Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const {
return Color(r, g, b, a);
}
case FORMAT_RGBA4444: {
return color_from_rgba4444(((uint16_t *)ptr)[ofs]);
uint16_t u = ((uint16_t *)ptr)[ofs];
float r = ((u >> 12) & 0xF) / 15.0;
float g = ((u >> 8) & 0xF) / 15.0;
float b = ((u >> 4) & 0xF) / 15.0;
float a = (u & 0xF) / 15.0;
return Color(r, g, b, a);
}
case FORMAT_RGB565: {
return color_from_rgb565(((uint16_t *)ptr)[ofs]);
uint16_t u = ((uint16_t *)ptr)[ofs];
float r = ((u >> 11) & 0x1F) / 31.0;
float g = ((u >> 5) & 0x3F) / 63.0;
float b = (u & 0x1F) / 31.0;
return Color(r, g, b, 1.0);
}
case FORMAT_RF: {
float r = ((float *)ptr)[ofs];
@ -3503,50 +3252,6 @@ Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const {
case FORMAT_RGBE9995: {
return Color::from_rgbe9995(((uint32_t *)ptr)[ofs]);
}
case FORMAT_R16: {
float r = ((uint16_t *)ptr)[ofs] / 65535.0f;
return Color(r, 0, 0, 1);
}
case FORMAT_RG16: {
float r = ((uint16_t *)ptr)[ofs * 2 + 0] / 65535.0f;
float g = ((uint16_t *)ptr)[ofs * 2 + 1] / 65535.0f;
return Color(r, g, 0, 1);
}
case FORMAT_RGB16: {
float r = ((uint16_t *)ptr)[ofs * 3 + 0] / 65535.0f;
float g = ((uint16_t *)ptr)[ofs * 3 + 1] / 65535.0f;
float b = ((uint16_t *)ptr)[ofs * 3 + 2] / 65535.0f;
return Color(r, g, b, 1);
}
case FORMAT_RGBA16: {
float r = ((uint16_t *)ptr)[ofs * 4 + 0] / 65535.0f;
float g = ((uint16_t *)ptr)[ofs * 4 + 1] / 65535.0f;
float b = ((uint16_t *)ptr)[ofs * 4 + 2] / 65535.0f;
float a = ((uint16_t *)ptr)[ofs * 4 + 3] / 65535.0f;
return Color(r, g, b, a);
}
case FORMAT_R16I: {
uint16_t r = ((uint16_t *)ptr)[ofs];
return Color(r, 0, 0, 1);
}
case FORMAT_RG16I: {
uint16_t r = ((uint16_t *)ptr)[ofs * 2 + 0];
uint16_t g = ((uint16_t *)ptr)[ofs * 2 + 1];
return Color(r, g, 0, 1);
}
case FORMAT_RGB16I: {
uint16_t r = ((uint16_t *)ptr)[ofs * 3 + 0];
uint16_t g = ((uint16_t *)ptr)[ofs * 3 + 1];
uint16_t b = ((uint16_t *)ptr)[ofs * 3 + 2];
return Color(r, g, b, 1);
}
case FORMAT_RGBA16I: {
uint16_t r = ((uint16_t *)ptr)[ofs * 4 + 0];
uint16_t g = ((uint16_t *)ptr)[ofs * 4 + 1];
uint16_t b = ((uint16_t *)ptr)[ofs * 4 + 2];
uint16_t a = ((uint16_t *)ptr)[ofs * 4 + 3];
return Color(r, g, b, a);
}
default: {
ERR_FAIL_V_MSG(Color(), "Can't get_pixel() on compressed image, sorry.");
@ -3582,10 +3287,23 @@ void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color)
ptr[ofs * 4 + 3] = uint8_t(CLAMP(p_color.a * 255.0, 0, 255));
} break;
case FORMAT_RGBA4444: {
((uint16_t *)ptr)[ofs] = color_to_rgba4444(p_color);
uint16_t rgba = 0;
rgba = uint16_t(CLAMP(p_color.r * 15.0, 0, 15)) << 12;
rgba |= uint16_t(CLAMP(p_color.g * 15.0, 0, 15)) << 8;
rgba |= uint16_t(CLAMP(p_color.b * 15.0, 0, 15)) << 4;
rgba |= uint16_t(CLAMP(p_color.a * 15.0, 0, 15));
((uint16_t *)ptr)[ofs] = rgba;
} break;
case FORMAT_RGB565: {
((uint16_t *)ptr)[ofs] = color_to_rgb565(p_color);
uint16_t rgba = 0;
rgba = uint16_t(CLAMP(p_color.r * 31.0, 0, 31)) << 11;
rgba |= uint16_t(CLAMP(p_color.g * 63.0, 0, 63)) << 5;
rgba |= uint16_t(CLAMP(p_color.b * 31.0, 0, 31));
((uint16_t *)ptr)[ofs] = rgba;
} break;
case FORMAT_RF: {
((float *)ptr)[ofs] = p_color.r;
@ -3626,42 +3344,6 @@ void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color)
case FORMAT_RGBE9995: {
((uint32_t *)ptr)[ofs] = p_color.to_rgbe9995();
} break;
case FORMAT_R16: {
((uint16_t *)ptr)[ofs] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
} break;
case FORMAT_RG16: {
((uint16_t *)ptr)[ofs * 2 + 0] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
((uint16_t *)ptr)[ofs * 2 + 1] = uint16_t(CLAMP(p_color.g * 65535.0, 0, 65535));
} break;
case FORMAT_RGB16: {
((uint16_t *)ptr)[ofs * 3 + 0] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
((uint16_t *)ptr)[ofs * 3 + 1] = uint16_t(CLAMP(p_color.g * 65535.0, 0, 65535));
((uint16_t *)ptr)[ofs * 3 + 2] = uint16_t(CLAMP(p_color.b * 65535.0, 0, 65535));
} break;
case FORMAT_RGBA16: {
((uint16_t *)ptr)[ofs * 4 + 0] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
((uint16_t *)ptr)[ofs * 4 + 1] = uint16_t(CLAMP(p_color.g * 65535.0, 0, 65535));
((uint16_t *)ptr)[ofs * 4 + 2] = uint16_t(CLAMP(p_color.b * 65535.0, 0, 65535));
((uint16_t *)ptr)[ofs * 4 + 3] = uint16_t(CLAMP(p_color.a * 65535.0, 0, 65535));
} break;
case FORMAT_R16I: {
((uint16_t *)ptr)[ofs] = uint16_t(CLAMP(p_color.r, 0, 65535));
} break;
case FORMAT_RG16I: {
((uint16_t *)ptr)[ofs * 2 + 0] = uint16_t(CLAMP(p_color.r, 0, 65535));
((uint16_t *)ptr)[ofs * 2 + 1] = uint16_t(CLAMP(p_color.g, 0, 65535));
} break;
case FORMAT_RGB16I: {
((uint16_t *)ptr)[ofs * 3 + 0] = uint16_t(CLAMP(p_color.r, 0, 65535));
((uint16_t *)ptr)[ofs * 3 + 1] = uint16_t(CLAMP(p_color.g, 0, 65535));
((uint16_t *)ptr)[ofs * 3 + 2] = uint16_t(CLAMP(p_color.b, 0, 65535));
} break;
case FORMAT_RGBA16I: {
((uint16_t *)ptr)[ofs * 4 + 0] = uint16_t(CLAMP(p_color.r, 0, 65535));
((uint16_t *)ptr)[ofs * 4 + 1] = uint16_t(CLAMP(p_color.g, 0, 65535));
((uint16_t *)ptr)[ofs * 4 + 2] = uint16_t(CLAMP(p_color.b, 0, 65535));
((uint16_t *)ptr)[ofs * 4 + 3] = uint16_t(CLAMP(p_color.a, 0, 65535));
} break;
default: {
ERR_FAIL_MSG("Can't set_pixel() on compressed image, sorry.");
@ -3737,11 +3419,11 @@ Image::UsedChannels Image::detect_used_channels(CompressSource p_source) const {
if (format == FORMAT_L8) {
return USED_CHANNELS_L; // Grayscale only cannot have any channel less.
} else if (format == FORMAT_R8 || format == FORMAT_RH || format == FORMAT_RF || format == FORMAT_R16 || format == FORMAT_R16I) {
} else if (format == FORMAT_R8 || format == FORMAT_RH || format == FORMAT_RF) {
return USED_CHANNELS_R; // Red only cannot have any channel less.
}
const bool supports_alpha = format == FORMAT_RGBA8 || format == FORMAT_RGBA4444 || format == FORMAT_RGBAH || format == FORMAT_RGBAF || format == FORMAT_RGBA16 || format == FORMAT_RGBA16I;
const bool supports_alpha = format == FORMAT_RGBA8 || format == FORMAT_RGBA4444 || format == FORMAT_RGBAH || format == FORMAT_RGBAF;
bool r = false, g = false, b = false, a = false, c = false;
const uint8_t *data_ptr = data.ptr();
@ -3975,14 +3657,6 @@ void Image::_bind_methods() {
BIND_ENUM_CONSTANT(FORMAT_ASTC_4x4_HDR);
BIND_ENUM_CONSTANT(FORMAT_ASTC_8x8);
BIND_ENUM_CONSTANT(FORMAT_ASTC_8x8_HDR);
BIND_ENUM_CONSTANT(FORMAT_R16);
BIND_ENUM_CONSTANT(FORMAT_RG16);
BIND_ENUM_CONSTANT(FORMAT_RGB16);
BIND_ENUM_CONSTANT(FORMAT_RGBA16);
BIND_ENUM_CONSTANT(FORMAT_R16I);
BIND_ENUM_CONSTANT(FORMAT_RG16I);
BIND_ENUM_CONSTANT(FORMAT_RGB16I);
BIND_ENUM_CONSTANT(FORMAT_RGBA16I);
BIND_ENUM_CONSTANT(FORMAT_MAX);
BIND_ENUM_CONSTANT(INTERPOLATE_NEAREST);
@ -4396,22 +4070,6 @@ uint32_t Image::get_format_component_mask(Format p_format) {
return rgba;
case FORMAT_ASTC_8x8_HDR:
return rgba;
case FORMAT_R16:
return r;
case FORMAT_RG16:
return rg;
case FORMAT_RGB16:
return rgb;
case FORMAT_RGBA16:
return rgba;
case FORMAT_R16I:
return r;
case FORMAT_RG16I:
return rg;
case FORMAT_RGB16I:
return rgb;
case FORMAT_RGBA16I:
return rgba;
default:
ERR_PRINT("Unhandled format.");
return rgba;
@ -4555,18 +4213,6 @@ void Image::average_4_rgbe9995(uint32_t &p_out, const uint32_t &p_a, const uint3
p_out = ((Color::from_rgbe9995(p_a) + Color::from_rgbe9995(p_b) + Color::from_rgbe9995(p_c) + Color::from_rgbe9995(p_d)) * 0.25f).to_rgbe9995();
}
void Image::average_4_uint16(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d) {
p_out = static_cast<uint16_t>((p_a + p_b + p_c + p_d + 2) >> 2);
}
void Image::average_4_rgba4444(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d) {
p_out = color_to_rgba4444((color_from_rgba4444(p_a) + color_from_rgba4444(p_b) + color_from_rgba4444(p_c) + color_from_rgba4444(p_d)) * 0.25f);
}
void Image::average_4_rgb565(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d) {
p_out = color_to_rgb565((color_from_rgb565(p_a) + color_from_rgb565(p_b) + color_from_rgb565(p_c) + color_from_rgb565(p_d)) * 0.25f);
}
void Image::renormalize_uint8(uint8_t *p_rgb) {
Vector3 n(p_rgb[0] / 255.0, p_rgb[1] / 255.0, p_rgb[2] / 255.0);
n *= 2.0;
@ -4596,17 +4242,8 @@ void Image::renormalize_half(uint16_t *p_rgb) {
p_rgb[2] = Math::make_half_float(n.z);
}
void Image::renormalize_uint16(uint16_t *p_rgb) {
Vector3 n(p_rgb[0] / 65535.0, p_rgb[1] / 65535.0, p_rgb[2] / 65535.0);
n *= 2.0;
n -= Vector3(1, 1, 1);
n.normalize();
n += Vector3(1, 1, 1);
n *= 0.5;
n *= 65535;
p_rgb[0] = CLAMP(int(n.x), 0, 65535);
p_rgb[1] = CLAMP(int(n.y), 0, 65535);
p_rgb[2] = CLAMP(int(n.z), 0, 65535);
void Image::renormalize_rgbe9995(uint32_t *p_rgb) {
// Never used.
}
Image::Image(const uint8_t *p_mem_png_jpg, int p_len) {

View file

@ -111,14 +111,6 @@ public:
FORMAT_ASTC_4x4_HDR,
FORMAT_ASTC_8x8,
FORMAT_ASTC_8x8_HDR,
FORMAT_R16,
FORMAT_RG16,
FORMAT_RGB16,
FORMAT_RGBA16,
FORMAT_R16I,
FORMAT_RG16I,
FORMAT_RGB16I,
FORMAT_RGBA16I,
FORMAT_MAX
};
@ -290,14 +282,10 @@ private:
static void average_4_float(float &p_out, const float &p_a, const float &p_b, const float &p_c, const float &p_d);
static void average_4_half(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d);
static void average_4_rgbe9995(uint32_t &p_out, const uint32_t &p_a, const uint32_t &p_b, const uint32_t &p_c, const uint32_t &p_d);
static void average_4_uint16(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d);
static void average_4_rgba4444(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d);
static void average_4_rgb565(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d);
static void renormalize_uint8(uint8_t *p_rgb);
static void renormalize_float(float *p_rgb);
static void renormalize_half(uint16_t *p_rgb);
static void renormalize_uint16(uint16_t *p_rgb);
static void renormalize_rgbe9995(uint32_t *p_rgb);
public:
int get_width() const;

View file

@ -101,8 +101,6 @@ public:
};
class ResourceFormatLoaderImage : public ResourceFormatLoader {
GDSOFTCLASS(ResourceFormatLoaderImage, ResourceFormatLoader);
public:
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
virtual void get_recognized_extensions(List<String> *p_extensions) const override;

View file

@ -31,7 +31,6 @@
#include "json.h"
#include "core/config/engine.h"
#include "core/io/file_access.h"
#include "core/object/script_language.h"
#include "core/variant/container_type_validate.h"
@ -83,18 +82,11 @@ void JSON::_stringify(String &r_result, const Variant &p_var, const String &p_in
return;
}
if (p_full_precision) {
const String num_sci = String::num_scientific(num);
if (num_sci.contains_char('.') || num_sci.contains_char('e')) {
r_result += num_sci;
} else {
r_result += num_sci + ".0";
}
} else {
const double magnitude = std::log10(Math::abs(num));
const int precision = MAX(1, 14 - (int)Math::floor(magnitude));
r_result += String::num(num, precision);
}
const double magnitude = std::log10(Math::abs(num));
const int total_digits = p_full_precision ? 17 : 14;
const int precision = MAX(1, total_digits - (int)Math::floor(magnitude));
r_result += String::num(num, precision);
return;
}
case Variant::PACKED_INT32_ARRAY:

View file

@ -107,8 +107,6 @@ public:
};
class ResourceFormatLoaderJSON : public ResourceFormatLoader {
GDSOFTCLASS(ResourceFormatLoaderJSON, ResourceFormatLoader);
public:
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
@ -121,8 +119,6 @@ public:
};
class ResourceFormatSaverJSON : public ResourceFormatSaver {
GDSOFTCLASS(ResourceFormatSaverJSON, ResourceFormatSaver);
public:
virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0) override;
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const override;

View file

@ -32,8 +32,6 @@
#include "core/core_globals.h"
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
#include "core/object/script_backtrace.h"
#include "core/os/time.h"
#include "core/templates/rb_set.h"

View file

@ -30,15 +30,14 @@
#pragma once
#include "core/object/ref_counted.h"
#include "core/io/file_access.h"
#include "core/object/script_backtrace.h"
#include "core/string/ustring.h"
#include "core/templates/vector.h"
#include <cstdarg>
class FileAccess;
class RegEx;
class ScriptBacktrace;
class Logger {
protected:

View file

@ -34,8 +34,6 @@
#include "core/object/ref_counted.h"
class NetSocket : public RefCounted {
GDSOFTCLASS(NetSocket, RefCounted);
protected:
static NetSocket *(*_create)();
@ -54,61 +52,21 @@ public:
TYPE_UDP,
};
enum class Family {
NONE,
INET,
UNIX,
};
class Address {
Family _family = Family::NONE;
CharString _path;
IPAddress _ip;
uint16_t _port = 0;
public:
_FORCE_INLINE_ Family get_family() const { return _family; }
_FORCE_INLINE_ bool is_inet() const { return _family == Family::INET; }
_FORCE_INLINE_ bool is_unix() const { return _family == Family::UNIX; }
_FORCE_INLINE_ bool is_valid() const { return is_inet() || is_unix(); }
_FORCE_INLINE_ const IPAddress &ip() const { return _ip; }
_FORCE_INLINE_ const uint16_t &port() const { return _port; }
_FORCE_INLINE_ const CharString &get_path() const { return _path; }
Address() {}
Address(const IPAddress &p_addr, uint16_t p_port) :
_family(Family::INET) {
_ip = p_addr;
_port = p_port;
}
Address(const String &p_path) :
_family(Family::UNIX), _path(p_path.utf8()) {
}
Address(const CharString &p_path) :
_family(Family::UNIX), _path(p_path) {
}
};
virtual Error open(Family p_family, Type p_type, IP::Type &r_ip_type) = 0;
virtual Error open(Type p_type, IP::Type &ip_type) = 0;
virtual void close() = 0;
virtual Error bind(Address p_addr) = 0;
virtual Error bind(IPAddress p_addr, uint16_t p_port) = 0;
virtual Error listen(int p_max_pending) = 0;
virtual Error connect_to_host(Address p_addr) = 0;
virtual Error connect_to_host(IPAddress p_addr, uint16_t p_port) = 0;
virtual Error poll(PollType p_type, int timeout) const = 0;
virtual Error recv(uint8_t *p_buffer, int p_len, int &r_read) = 0;
virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port, bool p_peek = false) = 0;
virtual Error send(const uint8_t *p_buffer, int p_len, int &r_sent) = 0;
virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) = 0;
virtual Ref<NetSocket> accept(Address &r_addr) = 0;
virtual Ref<NetSocket> accept(IPAddress &r_ip, uint16_t &r_port) = 0;
virtual bool is_open() const = 0;
virtual int get_available_bytes() const = 0;
virtual Error get_socket_address(Address *r_addr) const = 0;
virtual Error get_socket_address(IPAddress *r_ip, uint16_t *r_port) const = 0;
virtual Error set_broadcasting_enabled(bool p_enabled) = 0; // Returns OK if the socket option has been set successfully.
virtual void set_blocking_enabled(bool p_enabled) = 0;

View file

@ -52,7 +52,7 @@ Error PacketPeerUDP::join_multicast_group(IPAddress p_multi_address, const Strin
if (!_sock->is_open()) {
IP::Type ip_type = p_multi_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
Error err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_UDP, ip_type);
Error err = _sock->open(NetSocket::TYPE_UDP, ip_type);
ERR_FAIL_COND_V(err != OK, err);
_sock->set_blocking_enabled(false);
_sock->set_broadcasting_enabled(broadcast);
@ -141,7 +141,7 @@ Error PacketPeerUDP::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
if (!_sock->is_open()) {
IP::Type ip_type = peer_addr.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_UDP, ip_type);
err = _sock->open(NetSocket::TYPE_UDP, ip_type);
ERR_FAIL_COND_V(err != OK, err);
_sock->set_blocking_enabled(false);
_sock->set_broadcasting_enabled(broadcast);
@ -186,7 +186,7 @@ Error PacketPeerUDP::bind(int p_port, const IPAddress &p_bind_address, int p_rec
ip_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
}
err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_UDP, ip_type);
err = _sock->open(NetSocket::TYPE_UDP, ip_type);
if (err != OK) {
return ERR_CANT_CREATE;
@ -194,8 +194,7 @@ Error PacketPeerUDP::bind(int p_port, const IPAddress &p_bind_address, int p_rec
_sock->set_blocking_enabled(false);
_sock->set_broadcasting_enabled(broadcast);
NetSocket::Address addr(p_bind_address, p_port);
err = _sock->bind(addr);
err = _sock->bind(p_bind_address, p_port);
if (err != OK) {
_sock->close();
@ -232,13 +231,12 @@ Error PacketPeerUDP::connect_to_host(const IPAddress &p_host, int p_port) {
if (!_sock->is_open()) {
IP::Type ip_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_UDP, ip_type);
err = _sock->open(NetSocket::TYPE_UDP, ip_type);
ERR_FAIL_COND_V(err != OK, ERR_CANT_OPEN);
_sock->set_blocking_enabled(false);
}
NetSocket::Address addr(p_host, p_port);
err = _sock->connect_to_host(addr);
err = _sock->connect_to_host(p_host, p_port);
// I see no reason why we should get ERR_BUSY (wouldblock/eagain) here.
// This is UDP, so connect is only used to tell the OS to which socket
@ -347,9 +345,9 @@ int PacketPeerUDP::get_packet_port() const {
}
int PacketPeerUDP::get_local_port() const {
NetSocket::Address addr;
_sock->get_socket_address(&addr);
return addr.port();
uint16_t local_port;
_sock->get_socket_address(nullptr, &local_port);
return local_port;
}
void PacketPeerUDP::set_dest_address(const IPAddress &p_address, int p_port) {

View file

@ -37,8 +37,6 @@
class PListNode;
class PList : public RefCounted {
GDSOFTCLASS(PList, RefCounted);
friend class PListNode;
public:

View file

@ -660,10 +660,6 @@ void Resource::reset_local_to_scene() {
// Restores the state as if setup_local_to_scene() hadn't been called.
}
String Resource::_to_string() {
return (name.is_empty() ? "" : String(name) + " ") + "(" + path_cache + "):" + Object::_to_string();
}
Node *(*Resource::_get_local_scene_func)() = nullptr;
void (*Resource::_update_configuration_warning)() = nullptr;
@ -762,9 +758,7 @@ void Resource::_bind_methods() {
}
Resource::Resource() :
remapped_list(this) {
_define_ancestry(AncestralClass::RESOURCE);
}
remapped_list(this) {}
Resource::~Resource() {
if (unlikely(path_cache.is_empty())) {

View file

@ -54,8 +54,6 @@ class Resource : public RefCounted {
GDCLASS(Resource, RefCounted);
public:
static constexpr AncestralClass static_ancestral_class = AncestralClass::RESOURCE;
static void register_custom_data_to_otdb() { ClassDB::add_resource_base_extension("res", get_class_static()); }
virtual String get_base_extension() const { return "res"; }
@ -122,7 +120,6 @@ protected:
GDVIRTUAL0(_reset_state);
virtual Ref<Resource> _duplicate(const DuplicateParams &p_params) const;
virtual String _to_string() override;
public:
static Node *(*_get_local_scene_func)(); // Used by the editor.

View file

@ -33,7 +33,6 @@
#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
#include "core/templates/rb_map.h"
class ResourceLoaderBinary {
bool translation_remapped = false;
@ -109,8 +108,6 @@ public:
};
class ResourceFormatLoaderBinary : public ResourceFormatLoader {
GDSOFTCLASS(ResourceFormatLoaderBinary, ResourceFormatLoader);
public:
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const override;
@ -182,8 +179,6 @@ public:
};
class ResourceFormatSaverBinary : public ResourceFormatSaver {
GDSOFTCLASS(ResourceFormatSaverBinary, ResourceFormatSaver);
public:
static inline ResourceFormatSaverBinary *singleton = nullptr;
virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0) override;

View file

@ -39,8 +39,6 @@ class ResourceFormatImporter;
typedef Ref<Resource> (*ResourceFormatImporterLoadOnStartup)(ResourceFormatImporter *p_importer, const String &p_path, Error *r_error, bool p_use_sub_threads, float *r_progress, ResourceFormatLoader::CacheMode p_cache_mode);
class ResourceFormatImporter : public ResourceFormatLoader {
GDSOFTCLASS(ResourceFormatImporter, ResourceFormatLoader);
struct PathAndType {
String path;
String type;

View file

@ -43,7 +43,7 @@
#include "core/string/translation_server.h"
#include "core/templates/rb_set.h"
#include "core/variant/variant_parser.h"
#include "servers/rendering/rendering_server.h"
#include "servers/rendering_server.h"
#ifdef DEBUG_LOAD_THREADED
#define print_lt(m_text) print_line(m_text)
@ -174,7 +174,7 @@ Ref<Resource> ResourceFormatLoader::load(const String &p_path, const String &p_o
}
}
return Ref<Resource>();
ERR_FAIL_V_MSG(Ref<Resource>(), vformat("Failed to load resource '%s'. ResourceFormatLoader::load was not implemented for this resource type.", p_path));
}
void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
@ -1465,8 +1465,8 @@ void ResourceLoader::add_custom_loaders() {
String custom_loader_base_class = ResourceFormatLoader::get_class_static();
LocalVector<StringName> global_classes;
ScriptServer::get_global_class_list(global_classes);
List<StringName> global_classes;
ScriptServer::get_global_class_list(&global_classes);
for (const StringName &class_name : global_classes) {
StringName base_class = ScriptServer::get_global_class_native_base(class_name);

View file

@ -70,7 +70,7 @@ protected:
GDVIRTUAL2RC(Error, _rename_dependencies, String, Dictionary)
GDVIRTUAL1RC(bool, _exists, String)
GDVIRTUAL4RC_REQUIRED(Variant, _load, String, String, bool, int)
GDVIRTUAL4RC(Variant, _load, String, String, bool, int)
public:
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);

View file

@ -255,8 +255,8 @@ void ResourceSaver::add_custom_savers() {
String custom_saver_base_class = ResourceFormatSaver::get_class_static();
LocalVector<StringName> global_classes;
ScriptServer::get_global_class_list(global_classes);
List<StringName> global_classes;
ScriptServer::get_global_class_list(&global_classes);
for (const StringName &class_name : global_classes) {
StringName base_class = ScriptServer::get_global_class_native_base(class_name);

View file

@ -47,7 +47,7 @@ String ResourceUID::get_cache_file() {
}
static constexpr uint8_t uuid_characters[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', '0', '1', '2', '3', '4', '5', '6', '7', '8' };
static constexpr uint32_t uuid_characters_element_count = std_size(uuid_characters);
static constexpr uint32_t uuid_characters_element_count = std::size(uuid_characters);
static constexpr uint8_t max_uuid_number_length = 13; // Max 0x7FFFFFFFFFFFFFFF (uid://d4n4ub6itg400) size is 13 characters.
String ResourceUID::id_to_text(ID p_id) const {
@ -351,7 +351,6 @@ void ResourceUID::clear() {
unique_ids.clear();
changed = false;
}
void ResourceUID::_bind_methods() {
ClassDB::bind_method(D_METHOD("id_to_text", "id"), &ResourceUID::id_to_text);
ClassDB::bind_method(D_METHOD("text_to_id", "text_id"), &ResourceUID::text_to_id);

View file

@ -1,90 +0,0 @@
/**************************************************************************/
/* socket_server.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "socket_server.h"
void SocketServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_connection_available"), &SocketServer::is_connection_available);
ClassDB::bind_method(D_METHOD("is_listening"), &SocketServer::is_listening);
ClassDB::bind_method(D_METHOD("stop"), &SocketServer::stop);
ClassDB::bind_method(D_METHOD("take_socket_connection"), &SocketServer::take_socket_connection);
}
Error SocketServer::_listen(const NetSocket::Address &p_addr) {
DEV_ASSERT(_sock.is_valid());
DEV_ASSERT(_sock->is_open());
_sock->set_blocking_enabled(false);
Error err = _sock->bind(p_addr);
if (err != OK) {
_sock->close();
return ERR_ALREADY_IN_USE;
}
err = _sock->listen(MAX_PENDING_CONNECTIONS);
if (err != OK) {
_sock->close();
return FAILED;
}
return OK;
}
bool SocketServer::is_listening() const {
ERR_FAIL_COND_V(_sock.is_null(), false);
return _sock->is_open();
}
bool SocketServer::is_connection_available() const {
ERR_FAIL_COND_V(_sock.is_null(), false);
if (!_sock->is_open()) {
return false;
}
Error err = _sock->poll(NetSocket::POLL_TYPE_IN, 0);
return (err == OK);
}
void SocketServer::stop() {
if (_sock.is_valid()) {
_sock->close();
}
}
SocketServer::SocketServer() :
_sock(NetSocket::create()) {
}
SocketServer::~SocketServer() {
stop();
}

View file

@ -1,77 +0,0 @@
/**************************************************************************/
/* socket_server.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "core/io/net_socket.h"
#include "core/io/stream_peer_socket.h"
class SocketServer : public RefCounted {
GDCLASS(SocketServer, RefCounted);
protected:
enum {
MAX_PENDING_CONNECTIONS = 8,
};
Ref<NetSocket> _sock;
static void _bind_methods();
Error _listen(const NetSocket::Address &p_addr);
template <typename T>
Ref<T> _take_connection() {
Ref<T> conn;
if (!is_connection_available()) {
return conn;
}
Ref<NetSocket> ns;
NetSocket::Address addr;
ns = _sock->accept(addr);
if (ns.is_null()) {
return conn;
}
conn.instantiate();
conn->accept_socket(ns, addr);
return conn;
}
public:
bool is_listening() const;
bool is_connection_available() const;
virtual Ref<StreamPeerSocket> take_socket_connection() = 0;
void stop(); // Stop listening
SocketServer();
~SocketServer();
};

View file

@ -1,52 +0,0 @@
/**************************************************************************/
/* stream_peer_socket.compat.inc */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef DISABLE_DEPRECATED
namespace compat::StreamPeerTCP {
enum class Status {
STATUS_NONE = StreamPeerSocket::STATUS_NONE,
STATUS_CONNECTING = StreamPeerSocket::STATUS_CONNECTING,
STATUS_CONNECTED = StreamPeerSocket::STATUS_CONNECTED,
STATUS_ERROR = StreamPeerSocket::STATUS_ERROR,
};
}
VARIANT_ENUM_CAST(compat::StreamPeerTCP::Status);
compat::StreamPeerTCP::Status StreamPeerSocket::_get_status_compat_107954() const {
return (compat::StreamPeerTCP::Status)get_status();
}
void StreamPeerSocket::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("get_status"), &StreamPeerSocket::_get_status_compat_107954);
}
#endif

View file

@ -1,236 +0,0 @@
/**************************************************************************/
/* stream_peer_socket.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "stream_peer_socket.h"
#include "stream_peer_socket.compat.inc"
Error StreamPeerSocket::poll() {
if (status == STATUS_CONNECTED) {
Error err;
err = _sock->poll(NetSocket::POLL_TYPE_IN, 0);
if (err == OK) {
// FIN received
if (_sock->get_available_bytes() == 0) {
disconnect_from_host();
return OK;
}
}
// Also poll write
err = _sock->poll(NetSocket::POLL_TYPE_IN_OUT, 0);
if (err != OK && err != ERR_BUSY) {
// Got an error
disconnect_from_host();
status = STATUS_ERROR;
return err;
}
return OK;
} else if (status != STATUS_CONNECTING) {
return OK;
}
Error err = _sock->connect_to_host(peer_address);
if (err == OK) {
status = STATUS_CONNECTED;
return OK;
} else if (err == ERR_BUSY) {
// Check for connect timeout
if (OS::get_singleton()->get_ticks_msec() > timeout) {
disconnect_from_host();
status = STATUS_ERROR;
return ERR_CONNECTION_ERROR;
}
// Still trying to connect
return OK;
}
disconnect_from_host();
status = STATUS_ERROR;
return ERR_CONNECTION_ERROR;
}
Error StreamPeerSocket::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block) {
ERR_FAIL_COND_V(_sock.is_null(), ERR_UNAVAILABLE);
if (status != STATUS_CONNECTED) {
return FAILED;
}
Error err;
int data_to_send = p_bytes;
const uint8_t *offset = p_data;
int total_sent = 0;
while (data_to_send) {
int sent_amount = 0;
err = _sock->send(offset, data_to_send, sent_amount);
if (err != OK) {
if (err != ERR_BUSY) {
disconnect_from_host();
return FAILED;
}
if (!p_block) {
r_sent = total_sent;
return OK;
}
// Block and wait for the socket to accept more data
err = _sock->poll(NetSocket::POLL_TYPE_OUT, -1);
if (err != OK) {
disconnect_from_host();
return FAILED;
}
} else {
data_to_send -= sent_amount;
offset += sent_amount;
total_sent += sent_amount;
}
}
r_sent = total_sent;
return OK;
}
Error StreamPeerSocket::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block) {
if (status != STATUS_CONNECTED) {
return FAILED;
}
Error err;
int to_read = p_bytes;
int total_read = 0;
r_received = 0;
while (to_read) {
int read = 0;
err = _sock->recv(p_buffer + total_read, to_read, read);
if (err != OK) {
if (err != ERR_BUSY) {
disconnect_from_host();
return FAILED;
}
if (!p_block) {
r_received = total_read;
return OK;
}
err = _sock->poll(NetSocket::POLL_TYPE_IN, -1);
if (err != OK) {
disconnect_from_host();
return FAILED;
}
} else if (read == 0) {
disconnect_from_host();
r_received = total_read;
return ERR_FILE_EOF;
} else {
to_read -= read;
total_read += read;
if (!p_block) {
r_received = total_read;
return OK;
}
}
}
r_received = total_read;
return OK;
}
StreamPeerSocket::Status StreamPeerSocket::get_status() const {
return status;
}
void StreamPeerSocket::disconnect_from_host() {
if (_sock.is_valid() && _sock->is_open()) {
_sock->close();
}
timeout = 0;
status = STATUS_NONE;
peer_address = NetSocket::Address();
}
Error StreamPeerSocket::wait(NetSocket::PollType p_type, int p_timeout) {
ERR_FAIL_COND_V(_sock.is_null() || !_sock->is_open(), ERR_UNAVAILABLE);
return _sock->poll(p_type, p_timeout);
}
Error StreamPeerSocket::put_data(const uint8_t *p_data, int p_bytes) {
int total;
return write(p_data, p_bytes, total, true);
}
Error StreamPeerSocket::put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) {
return write(p_data, p_bytes, r_sent, false);
}
Error StreamPeerSocket::get_data(uint8_t *p_buffer, int p_bytes) {
int total;
return read(p_buffer, p_bytes, total, true);
}
Error StreamPeerSocket::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) {
return read(p_buffer, p_bytes, r_received, false);
}
int StreamPeerSocket::get_available_bytes() const {
ERR_FAIL_COND_V(_sock.is_null(), -1);
return _sock->get_available_bytes();
}
void StreamPeerSocket::_bind_methods() {
ClassDB::bind_method(D_METHOD("poll"), &StreamPeerSocket::poll);
ClassDB::bind_method(D_METHOD("get_status"), &StreamPeerSocket::get_status);
ClassDB::bind_method(D_METHOD("disconnect_from_host"), &StreamPeerSocket::disconnect_from_host);
BIND_ENUM_CONSTANT(STATUS_NONE);
BIND_ENUM_CONSTANT(STATUS_CONNECTING);
BIND_ENUM_CONSTANT(STATUS_CONNECTED);
BIND_ENUM_CONSTANT(STATUS_ERROR);
}
StreamPeerSocket::StreamPeerSocket() :
_sock(NetSocket::create()) {
}
StreamPeerSocket::~StreamPeerSocket() {
disconnect_from_host();
}

View file

@ -1,93 +0,0 @@
/**************************************************************************/
/* stream_peer_socket.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "core/io/net_socket.h"
#include "core/io/stream_peer.h"
#ifndef DISABLE_DEPRECATED
namespace compat::StreamPeerTCP {
enum class Status;
} //namespace compat::StreamPeerTCP
#endif
class StreamPeerSocket : public StreamPeer {
GDCLASS(StreamPeerSocket, StreamPeer);
public:
enum Status {
STATUS_NONE,
STATUS_CONNECTING,
STATUS_CONNECTED,
STATUS_ERROR,
};
protected:
#ifndef DISABLE_DEPRECATED
compat::StreamPeerTCP::Status _get_status_compat_107954() const;
static void _bind_compatibility_methods();
#endif
Ref<NetSocket> _sock;
uint64_t timeout = 0;
Status status = STATUS_NONE;
NetSocket::Address peer_address;
Error write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block);
Error read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block);
static void _bind_methods();
public:
virtual void accept_socket(Ref<NetSocket> p_sock, const NetSocket::Address &p_addr) = 0;
void disconnect_from_host();
int get_available_bytes() const override;
Status get_status() const;
// Poll socket updating its state.
Error poll();
// Wait or check for writable, readable.
Error wait(NetSocket::PollType p_type, int p_timeout = 0);
// Read/Write from StreamPeer
Error put_data(const uint8_t *p_data, int p_bytes) override;
Error put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) override;
Error get_data(uint8_t *p_buffer, int p_bytes) override;
Error get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) override;
StreamPeerSocket();
virtual ~StreamPeerSocket();
};
VARIANT_ENUM_CAST(StreamPeerSocket::Status);

View file

@ -32,14 +32,60 @@
#include "core/config/project_settings.h"
void StreamPeerTCP::accept_socket(Ref<NetSocket> p_sock, const NetSocket::Address &p_addr) {
Error StreamPeerTCP::poll() {
if (status == STATUS_CONNECTED) {
Error err;
err = _sock->poll(NetSocket::POLL_TYPE_IN, 0);
if (err == OK) {
// FIN received
if (_sock->get_available_bytes() == 0) {
disconnect_from_host();
return OK;
}
}
// Also poll write
err = _sock->poll(NetSocket::POLL_TYPE_IN_OUT, 0);
if (err != OK && err != ERR_BUSY) {
// Got an error
disconnect_from_host();
status = STATUS_ERROR;
return err;
}
return OK;
} else if (status != STATUS_CONNECTING) {
return OK;
}
Error err = _sock->connect_to_host(peer_host, peer_port);
if (err == OK) {
status = STATUS_CONNECTED;
return OK;
} else if (err == ERR_BUSY) {
// Check for connect timeout
if (OS::get_singleton()->get_ticks_msec() > timeout) {
disconnect_from_host();
status = STATUS_ERROR;
return ERR_CONNECTION_ERROR;
}
// Still trying to connect
return OK;
}
disconnect_from_host();
status = STATUS_ERROR;
return ERR_CONNECTION_ERROR;
}
void StreamPeerTCP::accept_socket(Ref<NetSocket> p_sock, IPAddress p_host, uint16_t p_port) {
_sock = p_sock;
_sock->set_blocking_enabled(false);
timeout = OS::get_singleton()->get_ticks_msec() + (((uint64_t)GLOBAL_GET("network/limits/tcp/connect_timeout_seconds")) * 1000);
status = STATUS_CONNECTED;
peer_address = p_addr;
peer_host = p_host;
peer_port = p_port;
}
Error StreamPeerTCP::bind(int p_port, const IPAddress &p_host) {
@ -51,13 +97,12 @@ Error StreamPeerTCP::bind(int p_port, const IPAddress &p_host) {
if (p_host.is_wildcard()) {
ip_type = IP::TYPE_ANY;
}
Error err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_TCP, ip_type);
Error err = _sock->open(NetSocket::TYPE_TCP, ip_type);
if (err != OK) {
return err;
}
_sock->set_blocking_enabled(false);
NetSocket::Address addr(p_host, p_port);
return _sock->bind(addr);
return _sock->bind(p_host, p_port);
}
Error StreamPeerTCP::connect_to_host(const IPAddress &p_host, int p_port) {
@ -68,7 +113,7 @@ Error StreamPeerTCP::connect_to_host(const IPAddress &p_host, int p_port) {
if (!_sock->is_open()) {
IP::Type ip_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
Error err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_TCP, ip_type);
Error err = _sock->open(NetSocket::TYPE_TCP, ip_type);
if (err != OK) {
return err;
}
@ -76,9 +121,7 @@ Error StreamPeerTCP::connect_to_host(const IPAddress &p_host, int p_port) {
}
timeout = OS::get_singleton()->get_ticks_msec() + (((uint64_t)GLOBAL_GET("network/limits/tcp/connect_timeout_seconds")) * 1000);
NetSocket::Address addr(p_host, p_port);
Error err = _sock->connect_to_host(addr);
Error err = _sock->connect_to_host(p_host, p_port);
if (err == OK) {
status = STATUS_CONNECTED;
@ -90,7 +133,106 @@ Error StreamPeerTCP::connect_to_host(const IPAddress &p_host, int p_port) {
return FAILED;
}
peer_address = addr;
peer_host = p_host;
peer_port = p_port;
return OK;
}
Error StreamPeerTCP::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block) {
ERR_FAIL_COND_V(_sock.is_null(), ERR_UNAVAILABLE);
if (status != STATUS_CONNECTED) {
return FAILED;
}
Error err;
int data_to_send = p_bytes;
const uint8_t *offset = p_data;
int total_sent = 0;
while (data_to_send) {
int sent_amount = 0;
err = _sock->send(offset, data_to_send, sent_amount);
if (err != OK) {
if (err != ERR_BUSY) {
disconnect_from_host();
return FAILED;
}
if (!p_block) {
r_sent = total_sent;
return OK;
}
// Block and wait for the socket to accept more data
err = _sock->poll(NetSocket::POLL_TYPE_OUT, -1);
if (err != OK) {
disconnect_from_host();
return FAILED;
}
} else {
data_to_send -= sent_amount;
offset += sent_amount;
total_sent += sent_amount;
}
}
r_sent = total_sent;
return OK;
}
Error StreamPeerTCP::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block) {
if (status != STATUS_CONNECTED) {
return FAILED;
}
Error err;
int to_read = p_bytes;
int total_read = 0;
r_received = 0;
while (to_read) {
int read = 0;
err = _sock->recv(p_buffer + total_read, to_read, read);
if (err != OK) {
if (err != ERR_BUSY) {
disconnect_from_host();
return FAILED;
}
if (!p_block) {
r_received = total_read;
return OK;
}
err = _sock->poll(NetSocket::POLL_TYPE_IN, -1);
if (err != OK) {
disconnect_from_host();
return FAILED;
}
} else if (read == 0) {
disconnect_from_host();
r_received = total_read;
return ERR_FILE_EOF;
} else {
to_read -= read;
total_read += read;
if (!p_block) {
r_received = total_read;
return OK;
}
}
}
r_received = total_read;
return OK;
}
@ -100,18 +242,61 @@ void StreamPeerTCP::set_no_delay(bool p_enabled) {
_sock->set_tcp_no_delay_enabled(p_enabled);
}
StreamPeerTCP::Status StreamPeerTCP::get_status() const {
return status;
}
void StreamPeerTCP::disconnect_from_host() {
if (_sock.is_valid() && _sock->is_open()) {
_sock->close();
}
timeout = 0;
status = STATUS_NONE;
peer_host = IPAddress();
peer_port = 0;
}
Error StreamPeerTCP::wait(NetSocket::PollType p_type, int p_timeout) {
ERR_FAIL_COND_V(_sock.is_null() || !_sock->is_open(), ERR_UNAVAILABLE);
return _sock->poll(p_type, p_timeout);
}
Error StreamPeerTCP::put_data(const uint8_t *p_data, int p_bytes) {
int total;
return write(p_data, p_bytes, total, true);
}
Error StreamPeerTCP::put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) {
return write(p_data, p_bytes, r_sent, false);
}
Error StreamPeerTCP::get_data(uint8_t *p_buffer, int p_bytes) {
int total;
return read(p_buffer, p_bytes, total, true);
}
Error StreamPeerTCP::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) {
return read(p_buffer, p_bytes, r_received, false);
}
int StreamPeerTCP::get_available_bytes() const {
ERR_FAIL_COND_V(_sock.is_null(), -1);
return _sock->get_available_bytes();
}
IPAddress StreamPeerTCP::get_connected_host() const {
return peer_address.ip();
return peer_host;
}
int StreamPeerTCP::get_connected_port() const {
return peer_address.port();
return peer_port;
}
int StreamPeerTCP::get_local_port() const {
NetSocket::Address addr;
_sock->get_socket_address(&addr);
return addr.port();
uint16_t local_port;
_sock->get_socket_address(nullptr, &local_port);
return local_port;
}
Error StreamPeerTCP::_connect(const String &p_address, int p_port) {
@ -131,8 +316,24 @@ Error StreamPeerTCP::_connect(const String &p_address, int p_port) {
void StreamPeerTCP::_bind_methods() {
ClassDB::bind_method(D_METHOD("bind", "port", "host"), &StreamPeerTCP::bind, DEFVAL("*"));
ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port"), &StreamPeerTCP::_connect);
ClassDB::bind_method(D_METHOD("poll"), &StreamPeerTCP::poll);
ClassDB::bind_method(D_METHOD("get_status"), &StreamPeerTCP::get_status);
ClassDB::bind_method(D_METHOD("get_connected_host"), &StreamPeerTCP::get_connected_host);
ClassDB::bind_method(D_METHOD("get_connected_port"), &StreamPeerTCP::get_connected_port);
ClassDB::bind_method(D_METHOD("get_local_port"), &StreamPeerTCP::get_local_port);
ClassDB::bind_method(D_METHOD("disconnect_from_host"), &StreamPeerTCP::disconnect_from_host);
ClassDB::bind_method(D_METHOD("set_no_delay", "enabled"), &StreamPeerTCP::set_no_delay);
BIND_ENUM_CONSTANT(STATUS_NONE);
BIND_ENUM_CONSTANT(STATUS_CONNECTING);
BIND_ENUM_CONSTANT(STATUS_CONNECTED);
BIND_ENUM_CONSTANT(STATUS_ERROR);
}
StreamPeerTCP::StreamPeerTCP() :
_sock(Ref<NetSocket>(NetSocket::create())) {
}
StreamPeerTCP::~StreamPeerTCP() {
disconnect_from_host();
}

View file

@ -32,24 +32,62 @@
#include "core/io/ip.h"
#include "core/io/ip_address.h"
#include "core/io/stream_peer_socket.h"
#include "core/io/net_socket.h"
#include "core/io/stream_peer.h"
class StreamPeerTCP : public StreamPeerSocket {
GDCLASS(StreamPeerTCP, StreamPeerSocket);
class StreamPeerTCP : public StreamPeer {
GDCLASS(StreamPeerTCP, StreamPeer);
public:
enum Status {
STATUS_NONE,
STATUS_CONNECTING,
STATUS_CONNECTED,
STATUS_ERROR,
};
protected:
Ref<NetSocket> _sock;
uint64_t timeout = 0;
Status status = STATUS_NONE;
IPAddress peer_host;
uint16_t peer_port = 0;
Error _connect(const String &p_address, int p_port);
Error write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block);
Error read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block);
static void _bind_methods();
public:
void accept_socket(Ref<NetSocket> p_sock, const NetSocket::Address &p_addr) override;
void accept_socket(Ref<NetSocket> p_sock, IPAddress p_host, uint16_t p_port);
Error bind(int p_port, const IPAddress &p_host);
Error connect_to_host(const IPAddress &p_host, int p_port);
IPAddress get_connected_host() const;
int get_connected_port() const;
int get_local_port() const;
void disconnect_from_host();
int get_available_bytes() const override;
Status get_status() const;
void set_no_delay(bool p_enabled);
// Poll socket updating its state.
Error poll();
// Wait or check for writable, readable.
Error wait(NetSocket::PollType p_type, int p_timeout = 0);
// Read/Write from StreamPeer
Error put_data(const uint8_t *p_data, int p_bytes) override;
Error put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) override;
Error get_data(uint8_t *p_buffer, int p_bytes) override;
Error get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) override;
StreamPeerTCP();
~StreamPeerTCP();
};
VARIANT_ENUM_CAST(StreamPeerTCP::Status);

View file

@ -1,99 +0,0 @@
/**************************************************************************/
/* stream_peer_uds.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "stream_peer_uds.h"
#include "core/config/project_settings.h"
void StreamPeerUDS::_bind_methods() {
ClassDB::bind_method(D_METHOD("bind", "path"), &StreamPeerUDS::bind);
ClassDB::bind_method(D_METHOD("connect_to_host", "path"), &StreamPeerUDS::connect_to_host);
ClassDB::bind_method(D_METHOD("get_connected_path"), &StreamPeerUDS::get_connected_path);
}
void StreamPeerUDS::accept_socket(Ref<NetSocket> p_sock, const NetSocket::Address &p_addr) {
_sock = p_sock;
_sock->set_blocking_enabled(false);
timeout = OS::get_singleton()->get_ticks_msec() + (((uint64_t)GLOBAL_GET("network/limits/unix/connect_timeout_seconds")) * 1000);
status = STATUS_CONNECTED;
}
Error StreamPeerUDS::bind(const String &p_path) {
ERR_FAIL_COND_V(_sock.is_null(), ERR_UNAVAILABLE);
ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE);
IP::Type ip_type = IP::TYPE_NONE;
Error err = _sock->open(NetSocket::Family::UNIX, NetSocket::TYPE_NONE, ip_type);
if (err != OK) {
return err;
}
_sock->set_blocking_enabled(false);
NetSocket::Address addr(p_path);
return _sock->bind(addr);
}
Error StreamPeerUDS::connect_to_host(const String &p_path) {
ERR_FAIL_COND_V(_sock.is_null(), ERR_UNAVAILABLE);
ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE);
ERR_FAIL_COND_V(p_path.is_empty(), ERR_INVALID_PARAMETER);
if (!_sock->is_open()) {
IP::Type ip_type = IP::TYPE_NONE;
Error err = _sock->open(NetSocket::Family::UNIX, NetSocket::TYPE_NONE, ip_type);
if (err != OK) {
return err;
}
_sock->set_blocking_enabled(false);
}
timeout = OS::get_singleton()->get_ticks_msec() + (((uint64_t)GLOBAL_GET("network/limits/unix/connect_timeout_seconds")) * 1000);
NetSocket::Address addr(p_path);
Error err = _sock->connect_to_host(addr);
if (err == OK) {
status = STATUS_CONNECTED;
} else if (err == ERR_BUSY) {
status = STATUS_CONNECTING;
} else {
ERR_PRINT("Connection to remote host failed!");
disconnect_from_host();
return FAILED;
}
peer_address = addr;
peer_path = p_path;
return OK;
}
const String StreamPeerUDS::get_connected_path() const {
return String(peer_address.get_path().get_data());
}

View file

@ -1,48 +0,0 @@
/**************************************************************************/
/* stream_peer_uds.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "core/io/stream_peer_socket.h"
class StreamPeerUDS : public StreamPeerSocket {
GDCLASS(StreamPeerUDS, StreamPeerSocket);
protected:
String peer_path;
static void _bind_methods();
public:
void accept_socket(Ref<NetSocket> p_sock, const NetSocket::Address &p_addr) override;
Error bind(const String &p_path);
Error connect_to_host(const String &p_path);
const String get_connected_path() const;
};

View file

@ -32,8 +32,11 @@
void TCPServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("listen", "port", "bind_address"), &TCPServer::listen, DEFVAL("*"));
ClassDB::bind_method(D_METHOD("is_connection_available"), &TCPServer::is_connection_available);
ClassDB::bind_method(D_METHOD("is_listening"), &TCPServer::is_listening);
ClassDB::bind_method(D_METHOD("get_local_port"), &TCPServer::get_local_port);
ClassDB::bind_method(D_METHOD("take_connection"), &TCPServer::take_connection);
ClassDB::bind_method(D_METHOD("stop"), &TCPServer::stop);
}
Error TCPServer::listen(uint16_t p_port, const IPAddress &p_bind_address) {
@ -49,21 +52,81 @@ Error TCPServer::listen(uint16_t p_port, const IPAddress &p_bind_address) {
ip_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
}
err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_TCP, ip_type);
err = _sock->open(NetSocket::TYPE_TCP, ip_type);
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
_sock->set_blocking_enabled(false);
_sock->set_reuse_address_enabled(true);
return _listen(NetSocket::Address(p_bind_address, p_port));
err = _sock->bind(p_bind_address, p_port);
if (err != OK) {
_sock->close();
return ERR_ALREADY_IN_USE;
}
err = _sock->listen(MAX_PENDING_CONNECTIONS);
if (err != OK) {
_sock->close();
return FAILED;
}
return OK;
}
int TCPServer::get_local_port() const {
NetSocket::Address addr;
_sock->get_socket_address(&addr);
return addr.port();
uint16_t local_port;
_sock->get_socket_address(nullptr, &local_port);
return local_port;
}
bool TCPServer::is_listening() const {
ERR_FAIL_COND_V(_sock.is_null(), false);
return _sock->is_open();
}
bool TCPServer::is_connection_available() const {
ERR_FAIL_COND_V(_sock.is_null(), false);
if (!_sock->is_open()) {
return false;
}
Error err = _sock->poll(NetSocket::POLL_TYPE_IN, 0);
return (err == OK);
}
Ref<StreamPeerTCP> TCPServer::take_connection() {
return _take_connection<StreamPeerTCP>();
Ref<StreamPeerTCP> conn;
if (!is_connection_available()) {
return conn;
}
Ref<NetSocket> ns;
IPAddress ip;
uint16_t port = 0;
ns = _sock->accept(ip, port);
if (ns.is_null()) {
return conn;
}
conn.instantiate();
conn->accept_socket(ns, ip, port);
return conn;
}
void TCPServer::stop() {
if (_sock.is_valid()) {
_sock->close();
}
}
TCPServer::TCPServer() :
_sock(Ref<NetSocket>(NetSocket::create())) {
}
TCPServer::~TCPServer() {
stop();
}

View file

@ -31,18 +31,30 @@
#pragma once
#include "core/io/ip.h"
#include "core/io/socket_server.h"
#include "core/io/net_socket.h"
#include "core/io/stream_peer.h"
#include "core/io/stream_peer_tcp.h"
class TCPServer : public SocketServer {
GDCLASS(TCPServer, SocketServer);
class TCPServer : public RefCounted {
GDCLASS(TCPServer, RefCounted);
protected:
enum {
MAX_PENDING_CONNECTIONS = 8
};
Ref<NetSocket> _sock;
static void _bind_methods();
public:
Error listen(uint16_t p_port, const IPAddress &p_bind_address = IPAddress("*"));
int get_local_port() const;
bool is_listening() const;
bool is_connection_available() const;
Ref<StreamPeerTCP> take_connection();
Ref<StreamPeerSocket> take_socket_connection() override { return take_connection(); }
void stop(); // Stop listening
TCPServer();
~TCPServer();
};

View file

@ -31,7 +31,7 @@
#include "translation_loader_po.h"
#include "core/io/file_access.h"
#include "core/string/translation.h"
#include "core/string/translation_po.h"
Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_error) {
if (r_error) {
@ -39,8 +39,7 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
}
const String path = f->get_path();
Ref<Translation> translation;
translation.instantiate();
Ref<TranslationPO> translation = Ref<TranslationPO>(memnew(TranslationPO));
String config;
uint32_t magic = f->get_32();
@ -113,7 +112,7 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
int p_start = config.find("Plural-Forms");
if (p_start != -1) {
int p_end = config.find_char('\n', p_start);
translation->set_plural_rules_override(config.substr(p_start, p_end - p_start));
translation->set_plural_rule(config.substr(p_start, p_end - p_start));
}
} else {
uint32_t str_start = 0;
@ -229,8 +228,8 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
int p_start = config.find("Plural-Forms");
if (p_start != -1) {
int p_end = config.find_char('\n', p_start);
translation->set_plural_rules_override(config.substr(p_start, p_end - p_start));
plural_forms = translation->get_nplurals();
translation->set_plural_rule(config.substr(p_start, p_end - p_start));
plural_forms = translation->get_plural_forms();
}
}

View file

@ -32,10 +32,9 @@
#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
#include "core/string/translation.h"
class TranslationLoaderPO : public ResourceFormatLoader {
GDSOFTCLASS(TranslationLoaderPO, ResourceFormatLoader);
public:
static Ref<Resource> load_translation(Ref<FileAccess> f, Error *r_error = nullptr);
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;

View file

@ -99,7 +99,7 @@ Error UDPServer::listen(uint16_t p_port, const IPAddress &p_bind_address) {
ip_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
}
err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_UDP, ip_type);
err = _sock->open(NetSocket::TYPE_UDP, ip_type);
if (err != OK) {
return ERR_CANT_CREATE;
@ -107,8 +107,7 @@ Error UDPServer::listen(uint16_t p_port, const IPAddress &p_bind_address) {
_sock->set_blocking_enabled(false);
_sock->set_reuse_address_enabled(true);
NetSocket::Address addr(p_bind_address, p_port);
err = _sock->bind(addr);
err = _sock->bind(p_bind_address, p_port);
if (err != OK) {
stop();
@ -118,9 +117,9 @@ Error UDPServer::listen(uint16_t p_port, const IPAddress &p_bind_address) {
}
int UDPServer::get_local_port() const {
NetSocket::Address addr;
_sock->get_socket_address(&addr);
return addr.port();
uint16_t local_port;
_sock->get_socket_address(nullptr, &local_port);
return local_port;
}
bool UDPServer::is_listening() const {

View file

@ -1,52 +0,0 @@
/**************************************************************************/
/* uds_server.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "uds_server.h"
void UDSServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("listen", "path"), &UDSServer::listen);
ClassDB::bind_method(D_METHOD("take_connection"), &UDSServer::take_connection);
}
Error UDSServer::listen(const String &p_path) {
ERR_FAIL_COND_V(_sock.is_null(), ERR_UNAVAILABLE);
ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE);
ERR_FAIL_COND_V(p_path.is_empty(), ERR_INVALID_PARAMETER);
IP::Type ip_type = IP::TYPE_NONE;
Error err = _sock->open(NetSocket::Family::UNIX, NetSocket::TYPE_NONE, ip_type);
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
return _listen(p_path);
}
Ref<StreamPeerUDS> UDSServer::take_connection() {
return _take_connection<StreamPeerUDS>();
}

View file

@ -1,46 +0,0 @@
/**************************************************************************/
/* uds_server.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "core/io/socket_server.h"
#include "core/io/stream_peer_uds.h"
class UDSServer : public SocketServer {
GDCLASS(UDSServer, SocketServer);
protected:
static void _bind_methods();
public:
Error listen(const String &p_path);
Ref<StreamPeerUDS> take_connection();
Ref<StreamPeerSocket> take_socket_connection() override { return take_connection(); }
};

View file

@ -32,7 +32,6 @@
#include "core/math/plane.h"
#include "core/math/vector3.h"
#include "core/templates/hashfuncs.h"
/**
* AABB (Axis Aligned Bounding Box)
@ -132,16 +131,6 @@ struct [[nodiscard]] AABB {
return position + (size * 0.5f);
}
uint32_t hash() const {
uint32_t h = hash_murmur3_one_real(position.x);
h = hash_murmur3_one_real(position.y, h);
h = hash_murmur3_one_real(position.z, h);
h = hash_murmur3_one_real(size.x, h);
h = hash_murmur3_one_real(size.y, h);
h = hash_murmur3_one_real(size.z, h);
return hash_fmix32(h);
}
explicit operator String() const;
AABB() = default;

View file

@ -34,10 +34,6 @@
#include "core/math/vector3.h"
struct [[nodiscard]] Basis {
static const Basis FLIP_X;
static const Basis FLIP_Y;
static const Basis FLIP_Z;
Vector3 rows[3] = {
Vector3(1, 0, 0),
Vector3(0, 1, 0),
@ -228,7 +224,7 @@ struct [[nodiscard]] Basis {
operator Quaternion() const { return get_quaternion(); }
static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3::UP, bool p_use_model_front = false);
static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false);
Basis(const Quaternion &p_quaternion) { set_quaternion(p_quaternion); }
Basis(const Quaternion &p_quaternion, const Vector3 &p_scale) { set_quaternion_scale(p_quaternion, p_scale); }
@ -251,10 +247,6 @@ private:
void _set_diagonal(const Vector3 &p_diag);
};
inline constexpr Basis Basis::FLIP_X = { { -1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
inline constexpr Basis Basis::FLIP_Y = { { 1, 0, 0 }, { 0, -1, 0 }, { 0, 0, 1 } };
inline constexpr Basis Basis::FLIP_Z = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, -1 } };
constexpr bool Basis::operator==(const Basis &p_matrix) const {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {

View file

@ -432,7 +432,7 @@ int Color::find_named_color(const String &p_name) {
}
int Color::get_named_color_count() {
return std_size(named_colors);
return std::size(named_colors);
}
String Color::get_named_color_name(int p_idx) {

View file

@ -31,7 +31,6 @@
#pragma once
#include "core/math/math_funcs.h"
#include "core/templates/hashfuncs.h"
class String;
@ -240,14 +239,6 @@ struct [[nodiscard]] Color {
_FORCE_INLINE_ void set_ok_hsl_s(float p_s) { set_ok_hsl(get_ok_hsl_h(), p_s, get_ok_hsl_l(), a); }
_FORCE_INLINE_ void set_ok_hsl_l(float p_l) { set_ok_hsl(get_ok_hsl_h(), get_ok_hsl_s(), p_l, a); }
uint32_t hash() const {
uint32_t h = hash_murmur3_one_float(r);
h = hash_murmur3_one_float(r, h);
h = hash_murmur3_one_float(b, h);
h = hash_murmur3_one_float(a, h);
return hash_fmix32(h);
}
constexpr Color() :
r(0), g(0), b(0), a(1) {}

View file

@ -33,7 +33,6 @@
#include "core/math/aabb.h"
#include "core/math/projection.h"
#include "core/math/vector3.h"
#include "core/math/vector3i.h"
#include "core/templates/a_hash_map.h"
#include "core/templates/list.h"
#include "core/templates/local_vector.h"

View file

@ -30,9 +30,7 @@
#include "geometry_2d.h"
GODOT_GCC_WARNING_PUSH_AND_IGNORE("-Walloc-zero")
#include "thirdparty/clipper2/include/clipper2/clipper.h"
GODOT_GCC_WARNING_POP
#include "thirdparty/misc/polypartition.h"
#define STB_RECT_PACK_IMPLEMENTATION
#include "thirdparty/misc/stb_rect_pack.h"
@ -294,16 +292,14 @@ Vector<Vector<Point2>> Geometry2D::_polypaths_do_operation(PolyBooleanOperation
}
Vector<Vector<Point2>> polypaths;
polypaths.resize(paths.size());
for (PathsD::size_type i = 0; i < paths.size(); i++) {
for (PathsD::size_type i = 0; i < paths.size(); ++i) {
const PathD &path = paths[i];
Vector<Vector2> polypath;
polypath.resize(path.size());
for (PathsD::size_type j = 0; j < path.size(); ++j) {
polypath.set(j, Point2(static_cast<real_t>(path[j].x), static_cast<real_t>(path[j].y)));
polypath.push_back(Point2(static_cast<real_t>(path[j].x), static_cast<real_t>(path[j].y)));
}
polypaths.set(i, polypath);
polypaths.push_back(polypath);
}
return polypaths;
}
@ -357,16 +353,14 @@ Vector<Vector<Point2>> Geometry2D::_polypath_offset(const Vector<Point2> &p_poly
// to attain the desired precision.
Vector<Vector<Point2>> polypaths;
polypaths.resize(paths.size());
for (PathsD::size_type i = 0; i < paths.size(); ++i) {
const PathD &path = paths[i];
Vector<Vector2> polypath2;
polypath2.resize(path.size());
for (PathsD::size_type j = 0; j < path.size(); ++j) {
polypath2.set(j, Point2(static_cast<real_t>(path[j].x), static_cast<real_t>(path[j].y)));
polypath2.push_back(Point2(static_cast<real_t>(path[j].x), static_cast<real_t>(path[j].y)));
}
polypaths.set(i, polypath2);
polypaths.push_back(polypath2);
}
return polypaths;
}

View file

@ -30,10 +30,8 @@
#pragma once
#include "core/math/color.h"
#include "core/math/delaunay_3d.h"
#include "core/math/face3.h"
#include "core/math/vector2.h"
#include "core/templates/local_vector.h"
#include "core/templates/vector.h"
@ -294,10 +292,6 @@ public:
real_t den = p.normal.dot(dir);
if (Math::abs(den) <= (real_t)CMP_EPSILON) {
if (p.is_point_over(p_from)) {
// Separating plane.
return false;
}
continue; // Ignore parallel plane.
}

View file

@ -35,10 +35,6 @@
class Variant;
struct [[nodiscard]] Plane {
static const Plane PLANE_YZ;
static const Plane PLANE_XZ;
static const Plane PLANE_XY;
Vector3 normal;
real_t d = 0;
@ -94,10 +90,6 @@ struct [[nodiscard]] Plane {
_FORCE_INLINE_ Plane(const Vector3 &p_point1, const Vector3 &p_point2, const Vector3 &p_point3, ClockDirection p_dir = CLOCKWISE);
};
inline constexpr Plane Plane::PLANE_YZ = { 1, 0, 0, 0 };
inline constexpr Plane Plane::PLANE_XZ = { 0, 1, 0, 0 };
inline constexpr Plane Plane::PLANE_XY = { 0, 0, 1, 0 };
bool Plane::is_point_over(const Vector3 &p_point) const {
return (normal.dot(p_point) > d);
}

View file

@ -32,7 +32,6 @@
#include "core/error/error_macros.h"
#include "core/math/vector2.h"
#include "core/templates/hashfuncs.h"
class String;
struct Rect2i;
@ -362,14 +361,6 @@ struct [[nodiscard]] Rect2 {
explicit operator String() const;
operator Rect2i() const;
uint32_t hash() const {
uint32_t h = hash_murmur3_one_real(position.x);
h = hash_murmur3_one_real(position.y, h);
h = hash_murmur3_one_real(size.x, h);
h = hash_murmur3_one_real(size.y, h);
return hash_fmix32(h);
}
Rect2() = default;
constexpr Rect2(real_t p_x, real_t p_y, real_t p_width, real_t p_height) :
position(Point2(p_x, p_y)),

View file

@ -32,7 +32,6 @@
#include "core/error/error_macros.h"
#include "core/math/vector2i.h"
#include "core/templates/hashfuncs.h"
class String;
struct Rect2;
@ -227,14 +226,6 @@ struct [[nodiscard]] Rect2i {
explicit operator String() const;
operator Rect2() const;
uint32_t hash() const {
uint32_t h = hash_murmur3_one_32(uint32_t(position.x));
h = hash_murmur3_one_32(uint32_t(position.y), h);
h = hash_murmur3_one_32(uint32_t(size.x), h);
h = hash_murmur3_one_32(uint32_t(size.y), h);
return hash_fmix32(h);
}
Rect2i() = default;
constexpr Rect2i(int p_x, int p_y, int p_width, int p_height) :
position(Point2i(p_x, p_y)),

View file

@ -52,9 +52,6 @@ struct [[nodiscard]] Transform2D {
// WARNING: Be aware that unlike 3D code, 2D code uses a left-handed coordinate system:
// Y-axis points down, and angle is measure from +X to +Y in a clockwise-fashion.
static const Transform2D FLIP_X;
static const Transform2D FLIP_Y;
Vector2 columns[3] = {
{ 1, 0 },
{ 0, 1 },
@ -152,9 +149,6 @@ struct [[nodiscard]] Transform2D {
Transform2D() = default;
};
inline constexpr Transform2D Transform2D::FLIP_X = { { -1, 0 }, { 0, 1 }, { 0, 0 } };
inline constexpr Transform2D Transform2D::FLIP_Y = { { 1, 0 }, { 0, -1 }, { 0, 0 } };
constexpr bool Transform2D::operator==(const Transform2D &p_transform) const {
for (int i = 0; i < 3; i++) {
if (columns[i] != p_transform.columns[i]) {

View file

@ -36,10 +36,6 @@
#include "core/templates/vector.h"
struct [[nodiscard]] Transform3D {
static const Transform3D FLIP_X;
static const Transform3D FLIP_Y;
static const Transform3D FLIP_Z;
Basis basis;
Vector3 origin;
@ -55,8 +51,8 @@ struct [[nodiscard]] Transform3D {
void rotate(const Vector3 &p_axis, real_t p_angle);
void rotate_basis(const Vector3 &p_axis, real_t p_angle);
void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up = Vector3::UP, bool p_use_model_front = false);
Transform3D looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3::UP, bool p_use_model_front = false) const;
void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false);
Transform3D looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false) const;
void scale(const Vector3 &p_scale);
Transform3D scaled(const Vector3 &p_scale) const;
@ -140,10 +136,6 @@ struct [[nodiscard]] Transform3D {
origin(p_ox, p_oy, p_oz) {}
};
inline constexpr Transform3D Transform3D::FLIP_X = { Basis::FLIP_X };
inline constexpr Transform3D Transform3D::FLIP_Y = { Basis::FLIP_Y };
inline constexpr Transform3D Transform3D::FLIP_Z = { Basis::FLIP_Z };
constexpr bool Transform3D::operator==(const Transform3D &p_transform) const {
return (basis == p_transform.basis && origin == p_transform.origin);
}

View file

@ -32,18 +32,12 @@
#include "core/error/error_macros.h"
#include "core/math/math_funcs.h"
#include "core/templates/hashfuncs.h"
class String;
struct Vector2i;
struct [[nodiscard]] Vector2 {
static const Vector2 LEFT;
static const Vector2 RIGHT;
static const Vector2 UP;
static const Vector2 DOWN;
static constexpr int AXIS_COUNT = 2;
static const int AXIS_COUNT = 2;
enum Axis {
AXIS_X,
@ -191,12 +185,6 @@ struct [[nodiscard]] Vector2 {
explicit operator String() const;
operator Vector2i() const;
uint32_t hash() const {
uint32_t h = hash_murmur3_one_real(x);
h = hash_murmur3_one_real(y, h);
return hash_fmix32(h);
}
// NOLINTBEGIN(cppcoreguidelines-pro-type-member-init)
constexpr Vector2() :
x(0), y(0) {}
@ -205,11 +193,6 @@ struct [[nodiscard]] Vector2 {
// NOLINTEND(cppcoreguidelines-pro-type-member-init)
};
inline constexpr Vector2 Vector2::LEFT = { -1, 0 };
inline constexpr Vector2 Vector2::RIGHT = { 1, 0 };
inline constexpr Vector2 Vector2::UP = { 0, -1 };
inline constexpr Vector2 Vector2::DOWN = { 0, 1 };
_FORCE_INLINE_ Vector2 Vector2::plane_project(real_t p_d, const Vector2 &p_vec) const {
return p_vec - *this * (dot(p_vec) - p_d);
}

View file

@ -32,18 +32,12 @@
#include "core/error/error_macros.h"
#include "core/math/math_funcs.h"
#include "core/templates/hashfuncs.h"
class String;
struct Vector2;
struct [[nodiscard]] Vector2i {
static const Vector2i LEFT;
static const Vector2i RIGHT;
static const Vector2i UP;
static const Vector2i DOWN;
static constexpr int AXIS_COUNT = 2;
static const int AXIS_COUNT = 2;
enum Axis {
AXIS_X,
@ -148,12 +142,6 @@ struct [[nodiscard]] Vector2i {
explicit operator String() const;
operator Vector2() const;
uint32_t hash() const {
uint32_t h = hash_murmur3_one_32(uint32_t(x));
h = hash_murmur3_one_32(uint32_t(y), h);
return hash_fmix32(h);
}
// NOLINTBEGIN(cppcoreguidelines-pro-type-member-init)
constexpr Vector2i() :
x(0), y(0) {}
@ -162,11 +150,6 @@ struct [[nodiscard]] Vector2i {
// NOLINTEND(cppcoreguidelines-pro-type-member-init)
};
inline constexpr Vector2i Vector2i::LEFT = { -1, 0 };
inline constexpr Vector2i Vector2i::RIGHT = { 1, 0 };
inline constexpr Vector2i Vector2i::UP = { 0, -1 };
inline constexpr Vector2i Vector2i::DOWN = { 0, 1 };
constexpr Vector2i Vector2i::operator+(const Vector2i &p_v) const {
return Vector2i(x + p_v.x, y + p_v.y);
}

View file

@ -45,6 +45,20 @@ Vector3 Vector3::rotated(const Vector3 &p_axis, real_t p_angle) const {
return r;
}
Vector3 Vector3::clamp(const Vector3 &p_min, const Vector3 &p_max) const {
return Vector3(
CLAMP(x, p_min.x, p_max.x),
CLAMP(y, p_min.y, p_max.y),
CLAMP(z, p_min.z, p_max.z));
}
Vector3 Vector3::clampf(real_t p_min, real_t p_max) const {
return Vector3(
CLAMP(x, p_min, p_max),
CLAMP(y, p_min, p_max),
CLAMP(z, p_min, p_max));
}
void Vector3::snap(const Vector3 &p_step) {
x = Math::snapped(x, p_step.x);
y = Math::snapped(y, p_step.y);

View file

@ -39,20 +39,7 @@ struct Vector2;
struct Vector3i;
struct [[nodiscard]] Vector3 {
static const Vector3 LEFT;
static const Vector3 RIGHT;
static const Vector3 UP;
static const Vector3 DOWN;
static const Vector3 FORWARD;
static const Vector3 BACK;
static const Vector3 MODEL_LEFT;
static const Vector3 MODEL_RIGHT;
static const Vector3 MODEL_TOP;
static const Vector3 MODEL_BOTTOM;
static const Vector3 MODEL_FRONT;
static const Vector3 MODEL_REAR;
static constexpr int AXIS_COUNT = 3;
static const int AXIS_COUNT = 3;
enum Axis {
AXIS_X,
@ -106,20 +93,6 @@ struct [[nodiscard]] Vector3 {
return Vector3(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar));
}
Vector3 clamp(const Vector3 &p_min, const Vector3 &p_max) const {
return Vector3(
CLAMP(x, p_min.x, p_max.x),
CLAMP(y, p_min.y, p_max.y),
CLAMP(z, p_min.z, p_max.z));
}
Vector3 clampf(real_t p_min, real_t p_max) const {
return Vector3(
CLAMP(x, p_min, p_max),
CLAMP(y, p_min, p_max),
CLAMP(z, p_min, p_max));
}
_FORCE_INLINE_ real_t length() const;
_FORCE_INLINE_ real_t length_squared() const;
@ -165,6 +138,8 @@ struct [[nodiscard]] Vector3 {
_FORCE_INLINE_ Vector3 sign() const;
_FORCE_INLINE_ Vector3 ceil() const;
_FORCE_INLINE_ Vector3 round() const;
Vector3 clamp(const Vector3 &p_min, const Vector3 &p_max) const;
Vector3 clampf(real_t p_min, real_t p_max) const;
_FORCE_INLINE_ real_t distance_to(const Vector3 &p_to) const;
_FORCE_INLINE_ real_t distance_squared_to(const Vector3 &p_to) const;
@ -214,32 +189,12 @@ struct [[nodiscard]] Vector3 {
explicit operator String() const;
operator Vector3i() const;
uint32_t hash() const {
uint32_t h = hash_murmur3_one_real(x);
h = hash_murmur3_one_real(y, h);
h = hash_murmur3_one_real(z, h);
return hash_fmix32(h);
}
constexpr Vector3() :
x(0), y(0), z(0) {}
constexpr Vector3(real_t p_x, real_t p_y, real_t p_z) :
x(p_x), y(p_y), z(p_z) {}
};
inline constexpr Vector3 Vector3::LEFT = { -1, 0, 0 };
inline constexpr Vector3 Vector3::RIGHT = { 1, 0, 0 };
inline constexpr Vector3 Vector3::UP = { 0, 1, 0 };
inline constexpr Vector3 Vector3::DOWN = { 0, -1, 0 };
inline constexpr Vector3 Vector3::FORWARD = { 0, 0, -1 };
inline constexpr Vector3 Vector3::BACK = { 0, 0, 1 };
inline constexpr Vector3 Vector3::MODEL_LEFT = { 1, 0, 0 };
inline constexpr Vector3 Vector3::MODEL_RIGHT = { -1, 0, 0 };
inline constexpr Vector3 Vector3::MODEL_TOP = { 0, 1, 0 };
inline constexpr Vector3 Vector3::MODEL_BOTTOM = { 0, -1, 0 };
inline constexpr Vector3 Vector3::MODEL_FRONT = { 0, 0, 1 };
inline constexpr Vector3 Vector3::MODEL_REAR = { 0, 0, -1 };
Vector3 Vector3::cross(const Vector3 &p_with) const {
Vector3 ret(
(y * p_with.z) - (z * p_with.y),
@ -379,7 +334,7 @@ Vector3 Vector3::get_any_perpendicular() const {
// since it could be a different vector depending on the prior branching code Math::abs(x) <= Math::abs(y) && Math::abs(x) <= Math::abs(z).
// However, it would be reasonable to use any of the axes of the basis, as it is simpler to calculate.
ERR_FAIL_COND_V_MSG(is_zero_approx(), Vector3(0, 0, 0), "The Vector3 must not be zero.");
return cross((Math::abs(x) <= Math::abs(y) && Math::abs(x) <= Math::abs(z)) ? Vector3::RIGHT : Vector3::UP).normalized();
return cross((Math::abs(x) <= Math::abs(y) && Math::abs(x) <= Math::abs(z)) ? Vector3(1, 0, 0) : Vector3(0, 1, 0)).normalized();
}
/* Operators */

Some files were not shown because too many files have changed in this diff Show more