Compare commits

..

196 Commits
master ... 4.3

Author SHA1 Message Date
Rémi Verschelde
6699ae7897
Update AUTHORS and DONORS list
(cherry picked from commit a1b081f45c)
2024-09-17 20:47:01 +02:00
Rémi Verschelde
53cde2eb85
i18n: Sync translations with Weblate
Adds Irish (ga) doc translations, and Bengali (bg) editor translations.
2024-09-17 20:46:20 +02:00
Rémi Verschelde
6225d39826
Merge pull request #97082 from akien-mga/4.3-cherrypicks
[4.3] Cherry-picks for the 4.3 branch (future 4.3.1) - 1st batch
2024-09-17 12:39:29 +02:00
patwork
3a2804a7e7
Fix for GLES3 radiance cubemap update
(cherry picked from commit 3038de4245)
2024-09-17 10:00:12 +02:00
Silc Lizard (Tokage) Renew
7b32e96f3d
Fix syncing PhysicalBone internal poses individually
(cherry picked from commit 2b3cf2451f)
2024-09-17 09:59:53 +02:00
Hilderin
15129c044e
Fix error reopening non existing scene on startup
(cherry picked from commit d06c7ad6f0)
2024-09-17 09:59:30 +02:00
Raffaele Picca
56a1d07421
Added a more detailed error message when instatiating a scene with missing export properties.
(cherry picked from commit 1df0159b36)
2024-09-17 09:59:13 +02:00
Pedro J. Estébanez
2c612abdd1
WorkerThreadPool: Fix end-of-yield logic potentially leading to deadlocks
(cherry picked from commit 5dade0e08b)
2024-09-17 09:55:10 +02:00
Rémi Verschelde
f273c7c773
thorvg: Update to 0.14.10
More fixes to rendering of SVG files with broken text tags.

Also backports upstream patch to fix #97078.

(cherry picked from commit 0c0336f704)
2024-09-17 08:57:46 +02:00
Rémi Verschelde
99a8821a71
thorvg: Update to 0.14.9
Fixes #96491.

Update fix for #96262 to a simple revert of the problematic commit,
as the upstream fix is still being debated and caused other issues.

Also include fix for upstream regression 2715 added in 0.14.9.

(cherry picked from commit a6ab039f2b)
2024-09-17 08:57:46 +02:00
Rémi Verschelde
7a7e4129bd
thorvg: Update to 0.14.8, and workaround Bezier precision regression
Fixes #96262 by backporting https://github.com/thorvg/thorvg/pull/2702.

(cherry picked from commit 7375f9b923)
2024-09-17 08:57:46 +02:00
Rémi Verschelde
4abc358952
thorvg: Update to 0.14.7
Fixes #95861.

(cherry picked from commit f16d4af342)
2024-09-17 08:57:46 +02:00
Robert Cadena
f7ad4dca8c
Remove debug print from Android DisplayServer.screen_get_scale implementation
(cherry picked from commit 42b0e91ee4)
2024-09-17 08:57:46 +02:00
bruvzg
35b4a1f374
[Windows] Emit native file dialog callback from event loop, fix selected options not saved.
(cherry picked from commit ea252675aa)
2024-09-17 08:57:46 +02:00
bruvzg
4944d59198
[Windows] Run native file dialogs in thread to make it non-blocking.
(cherry picked from commit 66832e9968)
2024-09-17 08:57:46 +02:00
Mounir Tohami
0a83f06608
Fix VSlider grabber area.
(cherry picked from commit 701188fd1e)
2024-09-17 08:57:46 +02:00
HolonProduction
03168cc9d1
LSP: Don't use smart resolve for completion
(cherry picked from commit 8155c1f836)
2024-09-17 08:57:46 +02:00
Silc Lizard (Tokage) Renew
47f34e8436
Add missing "Quad" capture TransitionType enum hint
(cherry picked from commit 8d30ccd067)
2024-09-17 08:57:46 +02:00
Daylily-Zeleen
abe68d397e
Fix description of Array.sort_custom()
(cherry picked from commit c6f7c89149)
2024-09-17 08:57:46 +02:00
Hilderin
7246e1488e
Fix editor_doc_cache locked on editor startup
(cherry picked from commit e064efccbc)
2024-09-17 08:57:45 +02:00
HolonProduction
a2e3c13451
LSP: Omit some values based on specification version 3.17
(cherry picked from commit 4d713d91b5)
2024-09-17 08:57:45 +02:00
Pedro J. Estébanez
3030d4b806
Object: Add tests about the safety of tail destruction
(cherry picked from commit bb77520599)
2024-09-17 08:57:45 +02:00
Pedro J. Estébanez
018f8be3d5
Object: Let debug lock handle callee destruction within call chain gracefully
Co-authored-by: lawnjelly <lawnjelly@gmail.com>
(cherry picked from commit 10e2318bde)
2024-09-17 08:57:45 +02:00
Lisandro Lorea
d92f9017c6
Fix gamepad triggers not working on web exports
Fixes #81758

DisplayServerWeb::process_joypads handles buttons 6 and 7 of the
HTML5 Standard Gamepad as a special case by doing:
`input->joy_axis(idx, (JoyAxis)b, s_btns[b]);`

This doesn't work because there is no JoyAxis 6 or 7 in the enum

To fix this we use JoyAxis::TRIGGER_LEFT and TRIGGER_RIGHT for button 6
and 7

However since we are now lying to input->joy_axis we also need to lie in
the mappings for the standard gamepad in godotcontrollersdb.txt,
otherwise input->joy_axis will try to find a mapping to axis 4(LT) and
axis 5(RT) that's not defined.

Therefore we set lefttrigger to +a4 and righttrigger to +a5 in the
mapping, to match what we are actually sending.

A cleaner, and more involved fix to this would be modifying
input->joy_button so that it can handle analog buttons and map them to
axes preserving their value instead of converting to boolean

(cherry picked from commit 9dd372f316)
2024-09-17 08:57:45 +02:00
A Thousand Ships
34251cf5b3
[Windows] Use GetFileTime for FileAccess
Prevents DST from rearranging file times.

(cherry picked from commit 7139f46c9a)
2024-09-17 08:57:45 +02:00
Giganzo
d00e4fbb16
Fix double lock/group buttons when starting editor with empty scene
(cherry picked from commit 96aa2f285c)
2024-09-17 08:57:45 +02:00
Giganzo
927d7a9250
Fix below what value is invalid in default_font_size doc
(cherry picked from commit 575a0b4dfb)
2024-09-17 08:57:45 +02:00
Giganzo
13701384ab
Fix slider size in compact mode
(cherry picked from commit f21a969bb9)
2024-09-17 08:57:45 +02:00
Hristo Iliev
f4b71b5325
Fix polygon node losing its UV toolbar by adding a call to the show method when assinging a node.
Fixes #96238

(cherry picked from commit dabeaa6a4b)
2024-09-17 08:57:45 +02:00
DeeJayLSP
51c86eb085
WAV: Fix one frame overflow at the end
(cherry picked from commit 147accdf74)
2024-09-17 08:57:45 +02:00
BlueCube3310
4addddd8df
Compatibility: Fix alignment of compressed textures when retrieving
(cherry picked from commit 0182294b37)
2024-09-17 08:57:45 +02:00
Dowsley
6dd8e7fece
Update AnimationPlayer in real-time when bezier curve properties or bezier editor changes
(cherry picked from commit 9d0944b673)
2024-09-17 08:57:45 +02:00
bruvzg
69713dadf0
[RTL] Fix font not updated for some spans.
(cherry picked from commit e517eaf053)
2024-09-17 08:57:45 +02:00
Mikael Hermansson
90f1c3e7bd
Fix issue with GDScript binary tokens being non-deterministic
(cherry picked from commit e120792760)
2024-09-17 08:57:45 +02:00
A Thousand Ships
d51be1f68d
[Buildsystem] Improve cache handling
Prevents cache issues by not purging cache before starting a build.
Splits cache purge related code from progress code and delays the purge
until after final build is done.

(cherry picked from commit acffc53e01)
2024-09-17 08:57:45 +02:00
Rudolph Bester
3fac9e43af
Fixed OpenGL shadow textures not honoring texture type when reusing textures
(cherry picked from commit 359aaa48ee)
2024-09-17 08:57:44 +02:00
Haoyu Qiu
1d790deedb
Fix parsing of 4. in Expression
(cherry picked from commit ee9cea521d)
2024-09-17 08:57:44 +02:00
kleonc
88370e44d8
Fix undoing "Move tiles" TileMapLayer action when drag/drop areas overlap
(cherry picked from commit ab504b3139)
2024-09-17 08:57:44 +02:00
shahriarlabib000
c7a173aa60
Fix directory empty bug on Android
(cherry picked from commit 8f66513bad)
2024-09-17 08:57:44 +02:00
Yaohua Xiong
e7e723b3e3
Do not defer PathFollow3D transform updates
Co-authored-by: Yaohua Xiong <xiongyaohua@gmail.com>
(cherry picked from commit 51b8b74d4b)
2024-09-17 08:57:44 +02:00
Praytic
281642831c
Enable MSAA support for all non-web platforms
MSAA support is built into GLES3 core, eliminating the need to check for GL_EXT_framebuffer_multisample, which was necessary only in GLES2 due to the lack of inherent multisample framebuffer support. This commit corrects an oversight from GLES2-based code, ensuring compatibility with GLES3 where multisampling is natively supported without extensions.

(cherry picked from commit fc955fa89f)
2024-09-17 08:57:44 +02:00
bruvzg
6b7f36e2a9
[Windows] Fix broken apksigner detection.
(cherry picked from commit 2c991a727b)
2024-09-17 08:57:44 +02:00
Pedro J. Estébanez
f757cc9a70
RenderingDevice: Fix uncapped mipmap sizes causing div-by-zero
(cherry picked from commit 7f1989bac1)
2024-09-17 08:57:44 +02:00
ajreckof
cab91cf8fb
fix clear button on Array[Node]
(cherry picked from commit dee0453b57)
2024-09-17 08:57:44 +02:00
Adam Scott
0b815cbb99
Fix leak when using audio samples instead of streams
(cherry picked from commit d3ddce6b88)
2024-09-17 08:57:44 +02:00
Pedro J. Estébanez
f11f9e3b7f
AudioServer: Fix code style issues
- Drop STL copy in favor of old-school for loops.
- Be explicit about loads and stores to atomic value. (This also fixes an error in certain compiler toolchains.)

(cherry picked from commit 1cc485ba1f)
2024-09-17 08:57:44 +02:00
A Thousand Ships
b2b882cc1d
Fix super call in various get_configuration_warnings methods
(cherry picked from commit 9dc231366d)
2024-09-17 08:57:44 +02:00
Gustavo Jaruga Cruz
f5b5b6cbfe
Fix interactive audio transitions fade in for clips with auto_advance
(cherry picked from commit 4fa6287de1)
2024-09-17 08:57:44 +02:00
RedMser
02c45088ea
Fix "reparent to new node" when node has internal children
(cherry picked from commit 8da49ab947)
2024-09-17 08:57:44 +02:00
RedMser
7f0cc1aa35
Fix "reparent to new node" not remembering index
(cherry picked from commit b11ccf3c77)
2024-09-17 08:57:44 +02:00
kleonc
21a0a84c6f
Fix StyleBoxFlat rectangles skewing independently
(cherry picked from commit 86c773d208)
2024-09-17 08:57:44 +02:00
jsjtxietian
fb1758ce23
Fixes godot crash or give unclear message when exporting with invalid args
(cherry picked from commit 1d09970404)
2024-09-17 08:57:44 +02:00
Danil Alexeev
c4525f24e3
GDScript: Do not produce UNUSED_SIGNAL warning for common implicit uses
(cherry picked from commit d1e2afaae3)
2024-09-17 08:57:43 +02:00
Giganzo
61b2ad9242
Fix Set Frame Title popup position
(cherry picked from commit 7d78d753b5)
2024-09-17 08:57:43 +02:00
smix8
d7a8654edd
Fix 2D debug navigation flickering with tile maps
Both the tile map layers and the debug navigation canvas items did fight for the same z order causing a lot of flickering in certain situations.

(cherry picked from commit 5bedaf77f7)
2024-09-17 08:57:43 +02:00
Giganzo
1629e9b1fa
Fix shift clicking on Add Sun/Environment to Scene buttons
(cherry picked from commit 1b6af3acd3)
2024-09-17 08:57:43 +02:00
A Thousand Ships
3783527410
[Editor] Fix handle ID being passed for 3D Gizmo plugins
(cherry picked from commit 62d98c6f02)
2024-09-17 08:57:43 +02:00
A Thousand Ships
00866dc80a
[Editor] Prevent duplicate Open in Editor buttons in scene tree dock
Duplicate buttons were added when editor description changed

(cherry picked from commit ab04d76e0e)
2024-09-17 08:57:43 +02:00
Hilderin
d842870331
Fix selection stuck after saving scene
(cherry picked from commit 613d4d10cb)
2024-09-17 08:57:43 +02:00
detomon
2635ff777e
Prevent editing value on focus when EditorSpinSlider is read-only
(cherry picked from commit 88f1b679f3)
2024-09-17 08:57:43 +02:00
ev13bird
cbcc5f8d19
Fix instant transformations not being committed when used in succession
Also:
- Fix holding down keys repeatedly committing instant transformations, and disallow starting instant during non-instant
- Fix echoed inputs starting new instant transformations after clicking to confirm, and disallow left mouse release committing instant transformations

(cherry picked from commit 060a1a0899)
2024-09-17 08:57:43 +02:00
A Thousand Ships
64cbde426f
[Editor] Don't show popup when clicking empty in Favorites
(cherry picked from commit d2a8b330d8)
2024-09-17 08:57:43 +02:00
bruvzg
b1c1c40250
[Windows] Use the same API for all OS_Windows::*_environment functions.
(cherry picked from commit 319bfa9965)
2024-09-17 08:57:43 +02:00
clayjohn
e09cada53f
Only use backbuffer mipmaps in SCREEN_TEXTURE when generated.
(cherry picked from commit d2f5c1a552)
2024-09-17 08:57:43 +02:00
Alexis Breust
2b05cf154a
Sky: No more auto-selecting REALTIME mode if radiance is not 256
(cherry picked from commit 44e526d3d5)
2024-09-17 08:57:43 +02:00
Arsh Panesar
26cc13705a
Fix AnimationPlayer crash when it's made the scene root
When an AnimationPlayer is made root of a scene,
the track links may become broken and clicking on
them will crash.

Current master branch also breaks node links when
AnimationPlayer is made scene root, and can also
crash the engine if another node was made scene
root prior to the AnimationPlayer.

This happens because when made root, the editor
loses track of AnimPlayer's root node. By keeping
a copy of the AnimPlayer's root_node, the track
links remain functional.

Fixes #91043.

(cherry picked from commit e905be8249)
2024-09-17 08:57:43 +02:00
Radiant
af8caffd0e
Fix shadow mesh recursion.
(cherry picked from commit 70860aafd8)
2024-09-17 08:57:43 +02:00
aaronp64
ec20c3ff76
Fix Array.sort_custom example code
Array.sort_custom descending sort example was comparing index 0, but had expected result based on comparing index 1.  Updated to use index 1 consistently.

(cherry picked from commit 39ca8b4e23)
2024-09-17 08:57:43 +02:00
aaronp64
a2f64b3c10
Fix SubViewport/AudioStreamPlayer2D crash
Updated Viewport destructor to remove itself from World2D, to avoid World2D keeping invalid pointers.

(cherry picked from commit 7a9acd5aca)
2024-09-17 08:57:42 +02:00
kobewi
fc5e7c7411
Fix Path2D splitting
(cherry picked from commit 7e7a4f238b)
2024-09-17 08:57:42 +02:00
Giganzo
1e5d7a0907
Fix floating window corner radius
(cherry picked from commit 308186a89e)
2024-09-17 08:57:42 +02:00
Hilderin
4d0f10a543
Fix missing material override after two glb reimports
(cherry picked from commit 79d0254a2d)
2024-09-17 08:57:42 +02:00
kerstop
f8c9ec3f37
fix deadzone slider not working correctly
(cherry picked from commit 2fd39eca30)
2024-09-17 08:57:42 +02:00
bruvzg
fd17fae4bd
[RTL] Do not add final newline to the paragraph context.
(cherry picked from commit 02113dff83)
2024-09-17 08:57:42 +02:00
clayjohn
b1fda8f5c4
Avoid indexing instances without a base in scene cull phase
(cherry picked from commit b5fd29e7bc)
2024-09-17 08:57:42 +02:00
clayjohn
1250b4568a
Various fixes for transmittance effect
Use correct shadow sampling for omni and spot lights

Disable transmittance if shadows are disabled

Correct DirectionalLight transmittance bias to match shadow bias (its still pretty sensitive though)

(cherry picked from commit d61fae36f3)
2024-09-17 08:57:42 +02:00
ComycSans
430a69baed
Fix SkyRD::Sky::free() freeing material
(cherry picked from commit 09e59fbec5)
2024-09-17 08:57:42 +02:00
Silc Lizard (Tokage) Renew
b60bf28a2f
Fix physical bone update without simulating
(cherry picked from commit f2186eeac0)
2024-09-17 08:57:42 +02:00
NotWearingPants
5567fedd04
NoiseTexture2D/3D: Don't use a thread to regenerate when the build doesn't support threads
(cherry picked from commit b47b98db34)
2024-09-17 08:57:42 +02:00
Fabio Alessandrelli
1a5ac1fd59
[MP] Fix division by zero in network profiler
The debugger reports synchronizers with empty state to the editor
even if no data is being sent to other peers.

The editor conditional to avoid division by zero was checking the wrong
variable.

(cherry picked from commit 042b264c55)
2024-09-17 08:57:42 +02:00
Haoyu Qiu
e72e42fe9b
Fix collapsing TreeItem not updating horizontal scrollbar
(cherry picked from commit d16dcbb3ac)
2024-09-17 08:57:42 +02:00
Lars Pettersson
f783cf7b81
Fix Polygon2D UV editor error when opening grid settings
(cherry picked from commit 5a0a0257e1)
2024-09-17 08:57:42 +02:00
viksl
f3848b75cb
Fixes alpha materials being rendered with a reverse cull which is visible in reflections from reflection probes.
(cherry picked from commit 929c69bad8)
2024-09-17 08:57:42 +02:00
David Snopek
19843328d9
GDExtension: Show warning on missing PDB file, rather than error
(cherry picked from commit 760099ca6f)
2024-09-17 08:57:42 +02:00
Hilderin
1e9f578740
Fix no unsaved indicator Save As resource
(cherry picked from commit b97c128b34)
2024-09-17 08:57:42 +02:00
clayjohn
0a1724f713
Use correct lightmap coefficients to ensure that the directional lightmap mode looks correct
Also remove the metallic option from directional lightmap as it is guaranteed to return negative numbers in many cases

(cherry picked from commit f4ccba7508)
2024-09-17 08:57:41 +02:00
Leonardo Demartino
e79157af72
Only main binaries require entitlements. This fixes signing issues on macOS.
(cherry picked from commit 0a57dd4682)
2024-09-17 08:57:41 +02:00
Hristo Iliev
6ab9ec33f2
Add modf function and fix snap behavior
Fixes #96159

(cherry picked from commit fcc8518bce)
2024-09-17 08:57:41 +02:00
MBCX
4acc73dbfa
Make sure huf_decompress is only applied to 64-bit x86.
(cherry picked from commit 6b13236956)
2024-09-17 08:57:41 +02:00
kleonc
e549ab35fa
Fix SceneTreeDock invalid state after trying to remove internal Node
(cherry picked from commit 5ae85a4fb9)
2024-09-17 08:57:41 +02:00
RedOrbweaver
43fa723659
Fix build logger unable to handle an event without an associated file
(cherry picked from commit 81799b8fa3)
2024-09-17 08:57:41 +02:00
passivestar
1c9ba616d5
Fix missing project date showing the unix epoch
(cherry picked from commit 6ed54ab9ba)
2024-09-17 08:57:41 +02:00
DeeJayLSP
682ee73f64
Fix memory leak on QOA import
(cherry picked from commit e67cc73463)
2024-09-16 17:25:14 +02:00
David Snopek
9946eba398
Windows: Call AddDllDirectory() with an absolute path
(cherry picked from commit e8bd385f53)
2024-09-16 17:24:05 +02:00
Saracen
30bba8745c
Fix crash when selecting ownerless 3D node.
(cherry picked from commit 279ccd6d32)
2024-09-16 17:23:54 +02:00
Togira
c4351c8d98
Fix RandomPCG::rand_weighted incorrectly returning -1
(cherry picked from commit ab13513403)
2024-09-16 17:23:44 +02:00
jsjtxietian
e2184c5da0
Support opening custom class documentation with "Open Documentation" menu entry
(cherry picked from commit b5fa2a3d3a)
2024-09-16 17:23:31 +02:00
kit
4fabc1ba58
Fix script overwriting with external editor
(cherry picked from commit 23927c3d9b)
2024-09-16 17:23:16 +02:00
kleonc
4d7feff723
Fix snapping when zoomed in Polygon2D UV editor
(cherry picked from commit 1b7626f391)
2024-09-16 17:22:50 +02:00
Fabio Alessandrelli
1d775b5b97
[mbedTLS] Fix incorrect cert pinning with client_unsafe
(cherry picked from commit ccae47ab66)
2024-09-16 17:22:33 +02:00
bruvzg
b6055941b9
[Windows] Hide cursor before moving.
(cherry picked from commit 9a2977fef1)
2024-09-16 17:20:22 +02:00
Sen
e5be133032
Fix for multimesh motion vector corruption by resetting motion vector state and filling both halves of buffer
(cherry picked from commit 52cd5acdda)
2024-09-16 17:19:58 +02:00
Fredia Huya-Kouadio
0f33a4b97e
Fix invalid Skeleton3D bone pose updates
The issue would cause log spams when trying to update the bone pose position or rotation with an invalid bone index.

(cherry picked from commit 039722a341)
2024-09-16 17:19:17 +02:00
Rakka Rage
f9bcd4f0ca
Enable revert button for ShaderMaterial::next_pass and ShaderMaterial::render_priority.
(cherry picked from commit ba23b22153)
2024-09-16 17:19:07 +02:00
Jason Wodicka
169b568e65
Fix C# code example for Object._get_property_list
There were two small errors in this code example that kept it from working when copied to a new node locally. These are the fixes I used locally to test the example.

(cherry picked from commit 97cf2c147e)
2024-09-16 17:18:54 +02:00
Mikael Hermansson
95a0525361
Fix animation library copy-paste not preserving resource reference
(cherry picked from commit 08ef14a037)
2024-09-16 17:18:40 +02:00
BlueCube3310
8e1d1a54fe
Compatibility: Fix crash when initializing certain compressed layered textures
(cherry picked from commit e8b4568900)
2024-09-16 17:18:24 +02:00
Paul Joannon
99dde70ad3
Fix relative paths for global class icons in C#
(cherry picked from commit 3c0eaec39f)
2024-09-16 17:18:14 +02:00
bruvzg
e59f59a439
[Editor] Prevent unnecessary editor theme regeneration on unrelated system setting update.
(cherry picked from commit 97085358ce)
2024-09-16 17:18:03 +02:00
Joel Winarske
afc330e33f
Use wayland-egl-core.h instead of wayland-egl.h
-avoid use of transitive wayland include

-resolves https://github.com/godotengine/godot/issues/95830

Signed-off-by: Joel Winarske <joel.winarske@gmail.com>
(cherry picked from commit 6ce71f0fb0)
2024-09-16 17:17:49 +02:00
Adam Scott
219ddde30c
Honor pitch_scale value before playing audio sample
(cherry picked from commit aaafd163b2)
2024-09-16 17:15:29 +02:00
kobewi
2dd696867f
Always store ID of PopupMenu items
(cherry picked from commit 5279fec60f)
2024-09-16 17:15:19 +02:00
Dungeon Master
9cf21b4b03
Fix some C# variable types In AStar2D/3D Class Reference
(cherry picked from commit 1928a84f6e)
2024-09-16 17:15:07 +02:00
Tallivm
497570b1cf
Fix typo in Array code example
(cherry picked from commit b516742358)
2024-09-16 17:14:51 +02:00
David Snopek
70a8761deb
Fix crash when calling OpenXRAPI::get_hand_tracker() and hand-tracking is disabled
(cherry picked from commit 11dd1f52ae)
2024-09-16 17:14:35 +02:00
Z0rb14n
19bed8fee7
Fix Vector3 Slerp Normalizing Zero Vectors
Ported the existing zero length check in C++ into C#.

(cherry picked from commit 0d6e9de0b9)
2024-09-16 17:14:24 +02:00
aaronp64
7874dad279
Minor AnimationNodeBlendSpace2D documentation fixes
Updated a couple parts that seemed to be copied over from AnimationNodeBlendSpace1D

(cherry picked from commit 05bcfda784)
2024-09-16 17:12:52 +02:00
jsjtxietian
05860062a5
Fix curve2d incorrect sample range description
(cherry picked from commit 5183588499)
2024-09-16 17:12:40 +02:00
Hilderin
8496e0738f
Fix drag&drop between window on Windows
(cherry picked from commit 0987a9dc06)
2024-09-16 17:12:26 +02:00
tetrapod00
20ce427a6c
Remember "View Grid" (per-viewport) setting between editor sessions
(cherry picked from commit 080acd7246)
2024-09-16 17:11:42 +02:00
Arseny Kapoulkine
40dcdcbe79
Fix double free in FSR2 destructor
Before this change, using FSR2 resulted in the following error when the
effect was destroyed:

	ERROR: Attempted to free invalid ID: 662734928609453
	   at: _free_internal (servers/rendering/rendering_device.cpp:4957)

This happened because ACCUMULATE and ACCUMULATE_SHARPEN passes shared
the same shader_version object but had different pipeline IDs. When
version_free was called for ACCUMULATE pass, it destroyed pipelines
created from that version, including the pipeline for the
ACCUMULATE_SHARPEN pass.

Using a unique version could work around this problem, but it's easier
to rely on version_free destroying the created pipelines through the
dependency mechanism.

(cherry picked from commit 0024cface5)
2024-09-16 17:10:59 +02:00
Arseny Kapoulkine
b2c83b42f6
Relax motion vector updates to allow skipped frames for skeletons
Before this change, a skeleton that was not updated every frame would
result in a difference of 2+ between last_change and frame index every
frame, which would disable the buffer rotation and set motion vectors to
zero. This results in significant visual artifacts for FSR2 that are
especially prominent on the characters that move together with the view
such as the main character in third person mode.

This is a significant problem for high refresh rate displays: at 120 Hz,
we are effectively guaranteed to skip skeleton updates every other frame
with skeleton update happening during physics processing, and the lack
of physics interpolation for skeletons. This happens by default in TPS
demo when FSR2 is enabled.

In other places where motion vectors are disabled, such as multi-mesh
and mesh rendering (where previous transform is updated), the logic
effectively allows for a single-frame gap in updates, because it
compares the frame where the update happened (which is the current frame
if updates are consistent) with the current frame, so the latency of 0
means "update just happened", but both multi-mesh and mesh transform
updates permit a latency of 1 as well.

Here, however, last_change is updated *after* the frame processing has
concluded, so a zero-latency update has a distance of 1. Allowing a
distance of 2 (latency 1) reduces the severity of the problem and aligns
the logic with transform updates.

Note that the problem will still happen when refresh rate is noticeably
higher than physics rate times 2. For example, it still happens at 240
Hz. However, a longer latency allowance is inconsistent with other
transforms and could lead to issues, so ideally long term physical
interpolation of skeleton transforms would completely solve this.

(cherry picked from commit 92f2bc70dd)
2024-09-16 17:10:47 +02:00
Giganzo
cf40a5bc5a
Fix huge tscn icon in FileSystem split mode using list view
(cherry picked from commit 36c9d31a9e)
2024-09-16 17:10:34 +02:00
Mikael Hermansson
1ecf20c783
Fix errors about UndoRedo history mismatch when deleting bezier track
(cherry picked from commit 4db3e6e6cd)
2024-09-16 17:10:19 +02:00
Hilderin
b05470efd0
Fix display dialog while saving scene
(cherry picked from commit da31679d12)
2024-09-16 17:10:04 +02:00
aryan-11825114
433509b489
Fix small graph editor pins at higher display scales
(cherry picked from commit 3f7efd2291)
2024-09-16 17:09:50 +02:00
jsjtxietian
139f5ee15e
Add model_normal_matrix for fragment shader
(cherry picked from commit e698351db2)
2024-09-16 17:09:36 +02:00
matheusmdx
bd552ff609
Fallback to theme icon when no custom icon is set in autocompletion
(cherry picked from commit e8254dc3f4)
2024-09-16 17:09:23 +02:00
Orion Lawlor
ecbb9a9c6a
Fix GLES3 crash with Mesh surface with exactly 65536 vertices
Fixes #95837.

(cherry picked from commit bde165ccb3)
2024-09-16 17:09:12 +02:00
Juan Pablo Arce
d0c4f19dd2
Fix gizmos without visible geometry not being selectable
The issue was that Node3DEditorViewport was using the render server's BVH to filter out nodes,
which is not correct for gizmos that have no renderable components,
or have collision triangles that exceed the bounds of their renderable components.

(cherry picked from commit 45f6110e26)
2024-09-16 17:08:59 +02:00
kleonc
df6bbb2538
Fix MenuBar popup placement assuming it's in viewport default canvas
(cherry picked from commit 8228d647a9)
2024-09-16 17:08:44 +02:00
Aaron Franke
1d0bcae019
GLTF: Propagate owner for root node children
(cherry picked from commit 246cc7e86d)
2024-09-16 17:08:33 +02:00
voidedWarranties
df522db6f0
Fix virtual binding for ScriptLanguageExtension::_reload_scripts
(cherry picked from commit d65ea6fb9c)
2024-09-16 17:06:44 +02:00
clayjohn
c684d65c64
Use transformed roughness instead of raw roughness to calculate roughness fade in SSR
(cherry picked from commit b99d0d778a)
2024-09-16 17:06:30 +02:00
Pedro J. Estébanez
5676d398e0
Avoid potential crash on signal disconnection
(cherry picked from commit 32b7f835d8)
2024-09-16 17:06:19 +02:00
jordi
32f2b851ab
Redraw SubViewportContainer on SubViewport size change
(cherry picked from commit 61e2aa7914)
2024-09-16 17:06:04 +02:00
Gergely Kis
bf5907b724
StringName: Use inline static field definitions
Before this change StringName used regular static field
definitions for its mutex, _table, configured and debug_stringname
fields.

Since in the general case the ordering of the static variable and field
initialization and destruction is undefined, it was possible that
the destruction of StringName's static fields happened prior to
the destruction of statically allocated StringName instances.

By changing the static field definitions to inline in string_name.h,
the C++17 standard guarantees the correct initialization and destruction
ordering.

(cherry picked from commit 723878bbab)
2024-09-16 17:05:50 +02:00
Robert Yevdokimov
cff0ebd603
Clear drag preview material on NOTIFICATION_DRAG_END
(cherry picked from commit 6aee6c1fdd)
2024-09-16 17:05:37 +02:00
MrPersonDev
9af6e04a15
Fix backspace always unfolding previous line
(cherry picked from commit 2860b99077)
2024-09-16 17:05:16 +02:00
Hilderin
39fb871310
Fix no validation on Blender path on importation
(cherry picked from commit 2dc9cf50c5)
2024-09-16 17:05:03 +02:00
Silc Lizard (Tokage) Renew
eaa8ecb182
Fix bone2d scaling
Co-authored-by: Thiago Lages de Alencar <thiagola92@gmail.com>
(cherry picked from commit de558123bf)
2024-09-16 17:04:49 +02:00
kleonc
c7dbcbd6d4
Fix Skeleton2D.{_set|_get} always returning true
(cherry picked from commit 115cd47fd6)
2024-09-16 17:04:28 +02:00
kleonc
f0f69a7b7c
Fix Parallax2D repeats being not relative to its transform
(cherry picked from commit 1bd8372813)
2024-09-16 17:04:12 +02:00
Artemy Fedotov
4168220169
Fix EditorInterface.get_selected_paths() working incorrectly when FileSystemDock is in split mode
(cherry picked from commit b55e97cd85)
2024-09-16 17:03:50 +02:00
Hilderin
d8c13f88ed
Fix scene node selection problem when no auto expand
(cherry picked from commit e46280dbb5)
2024-09-16 17:03:02 +02:00
Radiant
7266418bdf
Fix node.duplicate, return nullptr if this operation fails.
(cherry picked from commit 70f41e414e)
2024-09-16 17:02:35 +02:00
Hilderin
b7fc063038
Fix uid:// Paths Fail to Load at Editor Startup
(cherry picked from commit b1c97313e0)
2024-09-16 17:02:12 +02:00
clayjohn
6c202154a7
Add fixed fog to the sky in the Compatibility renderer
And apply luminance multiplier after fog in RD renderer

(cherry picked from commit 578049b7b9)
2024-09-16 17:01:45 +02:00
Rémi Verschelde
6d41487459
OpenXR: Fix support for building against distro package
(cherry picked from commit 2206f5c6a4)
2024-09-16 17:01:18 +02:00
Cory Petkovsek
3876287162
Ensure selected node is a descendant of the edited scene
(cherry picked from commit b1a45d9487)
2024-09-16 17:00:54 +02:00
Kusok
8ea64814ed
Add stop_callable to AudioStreamPlayerInternal
(cherry picked from commit 8c7dd3cb61)
2024-09-16 17:00:18 +02:00
Nodragem
6b323241b1
prevent the click to get processed further after a paste action
(cherry picked from commit e7e633760a)
2024-09-16 16:57:44 +02:00
clayjohn
2d7266e764
Ensure fog_sky_affect is used even when using a background color
(cherry picked from commit 37be585fdf)
2024-09-16 16:57:44 +02:00
Rio Arswendo Rachmad
7726ced085
fix: project settings not properly saved after a file removal
(cherry picked from commit 138bcc7cfd)
2024-09-16 16:56:22 +02:00
jsjtxietian
bba8f85945
Fix Pressing Escape doesn't exit freelook in the 3D editor
(cherry picked from commit 78dc310103)
2024-09-16 16:56:10 +02:00
Juan Pablo Arce
63ff665fd0
Fix GD0107 not applying to arrays and dictionaries containing nodes
(cherry picked from commit 8aa444d212)
2024-09-16 16:55:57 +02:00
Joel Croteau
6e78eec37f
Fix reload of GDExtension libraries in framework package on macos
`GDExtension::open_library` has a check in it to see if the library was loaded
from a temp file, and if it was to restore the original name as that is the one
we actually care about. This check is breaking extension reloading on Mac when
the library path is to a framework folder, as the file inside the framework
will not generally be the same name as the folder.

This check also shouldn't be necessary even on Windows, which is the only
platform that uses `generate_temp_files`, since disposal of the created temp
file is handled within `OS_Windows::open_dynamic_library`, and
`GDExtension::open_library` (which is the only function to call
`open_dynamic_library` with a `p_data` argument) only cares about the original
library file path and has to do extra work to remove the name of the temp file.
Instead, I have removed that check and set `OS_Windows::open_dynamic_library`
to return the name of the original file and not the name of the copy.

This fixes GDExtension reloading on macOS. I do not have a Windows machine
available to test that it still works properly on Windows, so someone should
check that before merging this.

(cherry picked from commit f44d6a235f)
2024-09-16 16:55:39 +02:00
ocean
6eea970e8c
Fix Godot not quitting with --doctool --gdscript-docs.
(cherry picked from commit 13b20820ba)
2024-09-16 16:55:26 +02:00
kevinkuo52
6aff947ee5
pass in render_info to _fill_instance_data for alpha to fix overdraw call count
(cherry picked from commit 3388a4a360)
2024-09-16 16:55:12 +02:00
bruvzg
686591b948
[ImageFont] Fix escape sequence parsing, add note to the docs.
(cherry picked from commit 4cc065c2db)
2024-09-16 16:54:56 +02:00
Jiří Švejda
acba31b746
Fix SoftBody3D pinned points breaking when reloading scene
(cherry picked from commit bde8c5977b)
2024-09-16 16:47:13 +02:00
kleonc
d915947f3d
Fix transposed tiles drawing in GenericTilePolygonEditor
(cherry picked from commit 3dfac1644d)
2024-09-16 16:47:00 +02:00
kleonc
a031407e82
Fix TileAtlasView bounds checks for transposed tiles
(cherry picked from commit 6895f6f8cc)
2024-09-16 16:46:57 +02:00
Fredia Huya-Kouadio
26b151a945
Update the Android fileLastModified method to return values in seconds instead of milliseconds
(cherry picked from commit cde873b406)
2024-09-16 16:46:41 +02:00
tetrapod00
2eb2052cb9
Change "Node3D" to "Spatial" in VisualShader resource
(cherry picked from commit b9876b626d)
2024-09-16 16:46:29 +02:00
kit
1f92092b08
Fix EditorSpinSlider when hidden
(cherry picked from commit d357a7d0f9)
2024-09-16 16:46:07 +02:00
Pedro J. Estébanez
c831bdbbe2
D3D12: Be explicit about all-resources texture barriers
(cherry picked from commit 3260437afc)
2024-09-16 16:45:55 +02:00
smix8
ea5989e3f5
Add NavigationLink function to change navigation map
Adds NavigationLink function to change navigation map.

(cherry picked from commit e6ff4e56e3)
2024-09-16 16:45:38 +02:00
Jordyfel
6073b86e71
Fix typo in MultiplayerSpawner doc
(cherry picked from commit 8c626f23c1)
2024-09-16 16:45:24 +02:00
jsjtxietian
b84dbab84d
Fix undefined alpha_scissor in standard shader
(cherry picked from commit 970a237c20)
2024-09-16 16:42:01 +02:00
Michael Alexsander
1ebf488a4e
Fix incorrect parsing of nested nodes when generating the POT
(cherry picked from commit 84c5403578)
2024-09-16 16:41:48 +02:00
Hilderin
4a64c95732
Fix autoload node cannot be accessed by plugin on start-up
(cherry picked from commit 2d4e573b20)
2024-09-16 16:41:32 +02:00
Yahkub-R
2b4ade1ed6
Fix AudioStreamPlayer get_playback_position() for web build
(cherry picked from commit bcd776e441)
2024-09-16 16:41:06 +02:00
Haoyu Qiu
562e583872
Fix split_floats behavior when spaces are used as separators
(cherry picked from commit f483c3aafa)
2024-09-16 16:40:48 +02:00
Ian McCleary
cfa33666c9
Fix custom resources using incorrect icons
(cherry picked from commit 140f9dc3e7)
2024-09-16 16:40:33 +02:00
Chaosus
3dc376ec0b
Fix shader crash when the comma used in for loop as a trailing
(cherry picked from commit d74749fd60)
2024-09-16 16:39:51 +02:00
bruvzg
a7d79f9e6c
Fix TextServer::shaped_text_*_character_pos for the first character of wrapped string. Allow starting/ending RTL selection before line start.
(cherry picked from commit 932acce8f2)
2024-09-16 16:38:23 +02:00
bruvzg
fac12603ef
[.NET] Move search in files extension list definition to be after Scene level module init.
(cherry picked from commit 69d52ed081)
2024-09-16 16:38:08 +02:00
bruvzg
8c5edcb03a
Run cleanup code on DisplayServer init failure to prevent crash on exit.
(cherry picked from commit f15ad72355)
2024-09-16 16:37:54 +02:00
bruvzg
79848620ce
[BMFont] Fix importing fonts with Match char height enabled.
(cherry picked from commit e7f215c2c4)
2024-09-16 16:35:06 +02:00
Jonatan Röjder Delnavaz
91ed3cd307
* Changed the VisualShaderNodeCustom template to use the correct overrides and added the GlobalClass attribute
(cherry picked from commit 74389e8395)
2024-09-16 16:34:53 +02:00
aaronp64
302af188a1
Fix tooltip content being cut off at some display scales
When getting the minimum size for a tooltip, we get the value as a Vector2.  Window::set_size() takes a Vector2i, so this size was getting truncated.  At certain display scales, this could be enough to cut off part of the tooltip.  Updated to call Vector2::ceil() to round up before calling Window::set_size()

Fixes #91958

(cherry picked from commit ca8e3d4923)
2024-09-16 16:34:31 +02:00
Zi Ye
2eec361f5f
Corrected rotation gizmo plane math for off-center perspective view.
(cherry picked from commit 1fc8255355)
2024-09-16 16:34:16 +02:00
jsjtxietian
a70df8537e
Fix uniform subgroup in shader will carry out to next group
(cherry picked from commit e6c45fbe5d)
2024-09-16 16:34:02 +02:00
clayjohn
cbee16418a
Increase precision of skeleton transforms in the skeleton shader in the Compatibility renderer
(cherry picked from commit 1bf594fb5a)
2024-09-16 16:33:38 +02:00
clayjohn
5a33e45fed
Fail when submit or sync called on main rendering device
Fail if submit or sync called multiple times in a row

(cherry picked from commit b0e33aa00f)
2024-09-16 16:33:25 +02:00
Hugo Locurcio
6595395b8b
Fix LightmapGI not taking environment sky rotation into account when baking
The sky rotation now affects the baked environment lighting as it should,
making it match how real-time ambient light rendering works.

Co-authored-by: Per Melin <git@melin.net>
(cherry picked from commit 661cf1f351)
2024-09-16 16:33:15 +02:00
Miley Hollenberg
a7756d530e
Fixed crash on PowerVR GE8320 GPUs
(cherry picked from commit 1c31e30359)
2024-09-16 16:32:56 +02:00
Kyle Appelgate
2df506ea15
fix to ensure generated light probes do not get placed too close to manual light probes
(cherry picked from commit 97205ea5b8)
2024-09-16 16:32:22 +02:00
Slashscreen
13d5227911
Apply patch for considering visual layers for DirectionalLight
Co-authored-by: majikayogames <152851004+majikayogames@users.noreply.github.com>
(cherry picked from commit 4457b11ff0)
2024-09-16 16:31:40 +02:00
Chris Cranford
b9271608df
Remove superfluous print_line call
(cherry picked from commit b1421a0d98)
2024-09-16 16:30:46 +02:00
Silc Lizard (Tokage) Renew
5caaa6ce19
Fix incorrect warning on SkeletonModifier
(cherry picked from commit 4727c4f783)
2024-09-16 16:30:30 +02:00
David Snopek
e1af61467a
OpenGL: Unconditionally do glDisable(GL_FRAMEBUFFER_SRGB) because we do our own sRGB conversion
(cherry picked from commit dfcff4ef46)
2024-09-16 16:30:06 +02:00
Rémi Verschelde
d40fc50f08
Merge pull request #95835 from BastiaanOlij/xrnode_visibility_43
[4.3] XRNode - fix visibility issue
2024-08-30 09:47:50 +02:00
Bastiaan Olij
620cc30f2a XRNode - fix visibility issue 2024-08-29 11:55:43 +10:00
Rémi Verschelde
ff9bc04223
Bump version to 4.3.1-rc
And update CI base branch to 4.3.
2024-08-15 11:35:17 +02:00
2179 changed files with 25682 additions and 178067 deletions

View File

@ -1,59 +1,29 @@
# Commented out parameters are those with the same value as base LLVM style.
# We can uncomment them if we want to change their value, or enforce the
# chosen value in case the base style changes (last sync: Clang 18.1.8).
BasedOnStyle: LLVM
# chosen value in case the base style changes (last sync: Clang 14.0).
---
### General config, applies to all languages ###
BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: DontAlign
# AlignArrayOfStructures: None
# AlignConsecutiveAssignments:
# Enabled: false
# AcrossEmptyLines: false
# AcrossComments: false
# AlignCompound: false
# AlignFunctionPointers: false
# PadOperators: true
# AlignConsecutiveBitFields:
# Enabled: false
# AcrossEmptyLines: false
# AcrossComments: false
# AlignCompound: false
# AlignFunctionPointers: false
# PadOperators: false
# AlignConsecutiveDeclarations:
# Enabled: false
# AcrossEmptyLines: false
# AcrossComments: false
# AlignCompound: false
# AlignFunctionPointers: false
# PadOperators: false
# AlignConsecutiveMacros:
# Enabled: false
# AcrossEmptyLines: false
# AcrossComments: false
# AlignCompound: false
# AlignFunctionPointers: false
# PadOperators: false
# AlignConsecutiveShortCaseStatements:
# Enabled: false
# AcrossEmptyLines: false
# AcrossComments: false
# AlignCaseColons: false
# AlignConsecutiveMacros: None
# AlignConsecutiveAssignments: None
# AlignConsecutiveBitFields: None
# AlignConsecutiveDeclarations: None
# AlignEscapedNewlines: Right
AlignOperands: DontAlign
AlignTrailingComments:
Kind: Never
OverEmptyLines: 0
AlignOperands: DontAlign
AlignTrailingComments: false
# AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: false
# AllowBreakBeforeNoexceptSpecifier: Never
# AllowShortEnumsOnASingleLine: true
# AllowShortBlocksOnASingleLine: Never
# AllowShortCaseLabelsOnASingleLine: false
# AllowShortCompoundRequirementOnASingleLine: true
# AllowShortEnumsOnASingleLine: true
# AllowShortFunctionsOnASingleLine: All
# AllowShortIfStatementsOnASingleLine: Never
# AllowShortLambdasOnASingleLine: All
# AllowShortIfStatementsOnASingleLine: Never
# AllowShortLoopsOnASingleLine: false
# AlwaysBreakAfterDefinitionReturnType: None
# AlwaysBreakAfterReturnType: None
# AlwaysBreakBeforeMultilineStrings: false
# AlwaysBreakTemplateDeclarations: MultiLine
@ -61,49 +31,50 @@ AllowAllParametersOfDeclarationOnNextLine: false
# - __capability
# BinPackArguments: true
# BinPackParameters: true
# BitFieldColonSpacing: Both
# BraceWrapping:
# AfterCaseLabel: false
# AfterClass: false
# AfterCaseLabel: false
# AfterClass: false
# AfterControlStatement: Never
# AfterEnum: false
# AfterFunction: false
# AfterNamespace: false
# AfterEnum: false
# AfterFunction: false
# AfterNamespace: false
# AfterObjCDeclaration: false
# AfterStruct: false
# AfterUnion: false
# AfterStruct: false
# AfterUnion: false
# AfterExternBlock: false
# BeforeCatch: false
# BeforeElse: false
# BeforeCatch: false
# BeforeElse: false
# BeforeLambdaBody: false
# BeforeWhile: false
# IndentBraces: false
# BeforeWhile: false
# IndentBraces: false
# SplitEmptyFunction: true
# SplitEmptyRecord: true
# SplitEmptyNamespace: true
# BreakAdjacentStringLiterals: true
# BreakAfterAttributes: Leave
# BreakAfterJavaFieldAnnotations: false
# BreakArrays: true
# BreakBeforeBinaryOperators: None
# BreakBeforeConceptDeclarations: true
# BreakBeforeBraces: Attach
# BreakBeforeConceptDeclarations: Always
# BreakBeforeInlineASMColon: OnlyMultiline
# BreakBeforeTernaryOperators: true
BreakConstructorInitializers: AfterColon
# BreakBeforeInheritanceComma: false
# BreakInheritanceList: BeforeColon
# BreakBeforeTernaryOperators: true
# BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: AfterColon
# BreakStringLiterals: true
ColumnLimit: 0
# CommentPragmas: '^ IWYU pragma:'
ColumnLimit: 0
# CommentPragmas: '^ IWYU pragma:'
# QualifierAlignment: Leave
# CompactNamespaces: false
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8
Cpp11BracedListStyle: false
# DeriveLineEnding: true
# DerivePointerAlignment: false
# DisableFormat: false
# DisableFormat: false
# EmptyLineAfterAccessModifier: Never
# EmptyLineBeforeAccessModifier: LogicalBlock
# ExperimentalAutoDetectBinPacking: false
# PackConstructorInitializers: BinPack
ConstructorInitializerAllOnOneLineOrOnePerLine: true
# AllowAllConstructorInitializersOnNextLine: true
# FixNamespaceComments: true
# ForEachMacros:
# - foreach
@ -111,138 +82,118 @@ Cpp11BracedListStyle: false
# - BOOST_FOREACH
# IfMacros:
# - KJ_IF_MAYBE
# IncludeBlocks: Preserve
# IncludeBlocks: Preserve
IncludeCategories:
- Regex: ^".*"$
Priority: 1
- Regex: ^<.*\.h>$
Priority: 2
- Regex: ^<.*>$
Priority: 3
# IncludeIsMainRegex: (Test)?$
- Regex: '".*"'
Priority: 1
- Regex: '^<.*\.h>'
Priority: 2
- Regex: '^<.*'
Priority: 3
# IncludeIsMainRegex: '(Test)?$'
# IncludeIsMainSourceRegex: ''
# IndentAccessModifiers: false
# IndentCaseBlocks: false
IndentCaseLabels: true
# IndentExternBlock: AfterExternBlock
# IndentCaseBlocks: false
# IndentGotoLabels: true
# IndentPPDirectives: None
# IndentRequiresClause: true
IndentWidth: 4
# IndentExternBlock: AfterExternBlock
# IndentRequires: false
IndentWidth: 4
# IndentWrappedFunctionNames: false
# InsertBraces: false
# InsertNewlineAtEOF: false
# InsertTrailingCommas: None
# IntegerLiteralSeparator:
# Binary: 0
# BinaryMinDigits: 0
# Decimal: 0
# DecimalMinDigits: 0
# Hex: 0
# HexMinDigits: 0
JavaImportGroups:
- org.godotengine
- android
- androidx
- com.android
- com.google
- java
- javax
# JavaScriptQuotes: Leave
# JavaScriptWrapImports: true
# KeepEmptyLinesAtEOF: false
KeepEmptyLinesAtTheStartOfBlocks: false
# LambdaBodyIndentation: Signature
# Language: Cpp
# LineEnding: DeriveLF
# MacroBlockBegin: ''
# MacroBlockEnd: ''
# MacroBlockEnd: ''
# MaxEmptyLinesToKeep: 1
# NamespaceIndentation: None
# ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 4
# ObjCBreakBeforeNestedBlockParam: true
# ObjCSpaceAfterProperty: false
# ObjCSpaceBeforeProtocolList: true
# PPIndentWidth: -1
PackConstructorInitializers: NextLine
# PenaltyBreakAssignment: 2
# PenaltyBreakBeforeFirstCallParameter: 19
# PenaltyBreakComment: 300
# PenaltyBreakFirstLessLess: 120
# PenaltyBreakOpenParenthesis: 0
# PenaltyBreakScopeResolution: 500
# PenaltyBreakString: 1000
# PenaltyBreakTemplateDeclaration: 10
# PenaltyExcessCharacter: 1000000
# PenaltyIndentedWhitespace: 0
# PenaltyReturnTypeOnItsOwnLine: 60
# PenaltyIndentedWhitespace: 0
# PointerAlignment: Right
# QualifierAlignment: Leave
# PPIndentWidth: -1
# ReferenceAlignment: Pointer
# ReflowComments: true
# ReflowComments: true
# RemoveBracesLLVM: false
# RemoveParentheses: Leave
# RemoveSemicolon: false
# RequiresClausePosition: OwnLine
# RequiresExpressionIndentation: OuterScope
# SeparateDefinitionBlocks: Leave
# ShortNamespaceLines: 1
# SkipMacroDefinitionBody: false
# SortIncludes: CaseSensitive
# SortIncludes: CaseSensitive
# SortJavaStaticImport: Before
# SortUsingDeclarations: LexicographicNumeric
# SortUsingDeclarations: true
# SpaceAfterCStyleCast: false
# SpaceAfterLogicalNot: false
# SpaceAfterTemplateKeyword: true
# SpaceAroundPointerQualifiers: Default
# SpaceBeforeAssignmentOperators: true
# SpaceBeforeCaseColon: false
# SpaceBeforeCpp11BracedList: false
# SpaceBeforeCtorInitializerColon: true
# SpaceBeforeInheritanceColon: true
# SpaceBeforeJsonColon: false
# SpaceBeforeParens: ControlStatements
# SpaceBeforeParensOptions:
# AfterControlStatements: true
# AfterForeachMacros: true
# AfterFunctionDeclarationName: false
# AfterFunctionDefinitionName: false
# AfterIfMacros: true
# AfterFunctionDeclarationName: false
# AfterIfMacros: true
# AfterOverloadedOperator: false
# AfterPlacementOperator: true
# AfterRequiresInClause: false
# AfterRequiresInExpression: false
# BeforeNonEmptyParentheses: false
# SpaceAroundPointerQualifiers: Default
# SpaceBeforeRangeBasedForLoopColon: true
# SpaceBeforeSquareBrackets: false
# SpaceInEmptyBlock: false
# SpaceInEmptyParentheses: false
# SpacesBeforeTrailingComments: 1
# SpacesInAngles: Never
# SpacesInAngles: Never
# SpacesInConditionalStatement: false
# SpacesInContainerLiterals: true
# SpacesInCStyleCastParentheses: false
## Godot TODO: We'll want to use a min of 1, but we need to see how to fix
## our comment capitalization at the same time.
SpacesInLineCommentPrefix:
Minimum: 0
Maximum: -1
# SpacesInParens: Never
# SpacesInParensOptions:
# InConditionalStatements: false
# InCStyleCasts: false
# InEmptyParentheses: false
# Other: false
Minimum: 0
Maximum: -1
# SpacesInParentheses: false
# SpacesInSquareBrackets: false
Standard: c++17
# SpaceBeforeSquareBrackets: false
# BitFieldColonSpacing: Both
# StatementAttributeLikeMacros:
# - Q_EMIT
# StatementMacros:
# - Q_UNUSED
# - QT_REQUIRE_VERSION
TabWidth: 4
UseTab: Always
# VerilogBreakBetweenInstancePorts: true
TabWidth: 4
# UseCRLF: false
UseTab: Always
# WhitespaceSensitiveMacros:
# - BOOST_PP_STRINGIZE
# - CF_SWIFT_NAME
# - NS_SWIFT_NAME
# - PP_STRINGIZE
# - STRINGIZE
# - PP_STRINGIZE
# - BOOST_PP_STRINGIZE
# - NS_SWIFT_NAME
# - CF_SWIFT_NAME
---
### C++ specific config ###
Language: Cpp
Standard: c++17
---
### ObjC specific config ###
Language: ObjC
# ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 4
# ObjCBreakBeforeNestedBlockParam: true
# ObjCSpaceAfterProperty: false
# ObjCSpaceBeforeProtocolList: true
---
### Java specific config ###
Language: Java
# BreakAfterJavaFieldAnnotations: false
JavaImportGroups: ['org.godotengine', 'android', 'androidx', 'com.android', 'com.google', 'java', 'javax']
...

View File

@ -54,6 +54,3 @@ df61dc4b2bd54a5a40c515493c76f5a458e5b541
# Enforce template syntax `typename` over `class`
9903e6779b70fc03aae70a37b9cf053f4f355b91
# Style: Apply new `clang-format` fixes
b37fc1014abf7adda70dc30b0822d775b3a4433f

4
.gitattributes vendored
View File

@ -1,6 +1,6 @@
# Properly detect languages on Github
*.h linguist-language=C++
*.inc linguist-language=C++
*.h linguist-language=cpp
*.inc linguist-language=cpp
thirdparty/* linguist-vendored
# Normalize EOL for all files that Git considers text files

292
.github/CODEOWNERS vendored
View File

@ -4,234 +4,180 @@
# Buildsystem
* @godotengine/buildsystem
.* @godotengine/buildsystem
.github/ @godotengine/buildsystem
*.py @godotengine/buildsystem
SConstruct @godotengine/buildsystem
SCsub @godotengine/buildsystem
# Core
/core/ @godotengine/core
/core/crypto/ @godotengine/network
/core/debugger/ @godotengine/debugger
/core/extension/ @godotengine/gdextension
/core/input/ @godotengine/input
/core/ @godotengine/core
/core/crypto/ @godotengine/network
/core/debugger/ @godotengine/debugger
/core/extension/ @godotengine/gdextension
/core/input/ @godotengine/input
# Doc
/doc/ @godotengine/documentation
**/doc_classes/ @godotengine/documentation
/doc/ @godotengine/documentation
doc_classes/* @godotengine/documentation
# Drivers
## Audio
/drivers/alsa/ @godotengine/audio
/drivers/alsamidi/ @godotengine/audio
/drivers/coreaudio/ @godotengine/audio
/drivers/coremidi/ @godotengine/audio
/drivers/pulseaudio/ @godotengine/audio
/drivers/wasapi/ @godotengine/audio
/drivers/winmidi/ @godotengine/audio
/drivers/xaudio2/ @godotengine/audio
/drivers/alsa/ @godotengine/audio
/drivers/alsamidi/ @godotengine/audio
/drivers/coreaudio/ @godotengine/audio
/drivers/coremidi/ @godotengine/audio
/drivers/pulseaudio/ @godotengine/audio
/drivers/wasapi/ @godotengine/audio
/drivers/winmidi/ @godotengine/audio
/drivers/xaudio2/ @godotengine/audio
## Rendering
/drivers/d3d12/ @godotengine/rendering
/drivers/dummy/ @godotengine/rendering
/drivers/gles3/ @godotengine/rendering
/drivers/spirv-reflect/ @godotengine/rendering
/drivers/vulkan/ @godotengine/rendering
/drivers/d3d12/ @godotengine/rendering
/drivers/dummy/ @godotengine/rendering
/drivers/gles3/ @godotengine/rendering
/drivers/spirv-reflect/ @godotengine/rendering
/drivers/vulkan/ @godotengine/rendering
## OS
/drivers/unix/ @godotengine/_platforms
/drivers/windows/ @godotengine/windows
/drivers/unix/ @godotengine/_platforms
/drivers/windows/ @godotengine/windows
## Misc
/drivers/png/ @godotengine/import
/drivers/png/ @godotengine/import
# Editor
/editor/*debugger* @godotengine/debugger
/editor/gui/ @godotengine/usability @godotengine/gui-nodes
/editor/icons/ @godotengine/usability
/editor/import/ @godotengine/import
/editor/plugins/*2d_*.* @godotengine/2d-editor
/editor/plugins/*3d_*.* @godotengine/3d-editor
/editor/plugins/script_*.* @godotengine/script-editor
/editor/plugins/*shader*.* @godotengine/shaders
/editor/themes/ @godotengine/usability @godotengine/gui-nodes
/editor/code_editor.* @godotengine/script-editor
/editor/*dock*.* @godotengine/docks
/editor/*shader*.* @godotengine/shaders
/editor/*debugger* @godotengine/debugger
/editor/gui/ @godotengine/usability @godotengine/gui-nodes
/editor/icons/ @godotengine/usability
/editor/import/ @godotengine/import
/editor/plugins/*2d_*.* @godotengine/2d-editor
/editor/plugins/*3d_*.* @godotengine/3d-editor
/editor/plugins/script_*.* @godotengine/script-editor
/editor/plugins/*shader*.* @godotengine/shaders
/editor/themes/ @godotengine/usability @godotengine/gui-nodes
/editor/code_editor.* @godotengine/script-editor
/editor/*dock*.* @godotengine/docks
/editor/*shader*.* @godotengine/shaders
# Main
/main/ @godotengine/core
/main/ @godotengine/core
# Misc
/misc/ @godotengine/buildsystem
/misc/extension_api_validation/ @godotengine/gdextension @godotengine/dotnet
/misc/ @godotengine/buildsystem
/misc/extension_api_validation/ @godotengine/gdextension @godotengine/dotnet
# Modules
## Audio (+ video)
/modules/interactive_music/ @godotengine/audio
/modules/interactive_music/doc_classes/ @godotengine/audio @godotengine/documentation
/modules/minimp3/ @godotengine/audio
/modules/minimp3/doc_classes/ @godotengine/audio @godotengine/documentation
/modules/ogg/ @godotengine/audio
/modules/ogg/doc_classes/ @godotengine/audio @godotengine/documentation
/modules/theora/ @godotengine/audio
/modules/theora/doc_classes/ @godotengine/audio @godotengine/documentation
/modules/vorbis/ @godotengine/audio
/modules/vorbis/doc_classes/ @godotengine/audio @godotengine/documentation
/modules/minimp3/ @godotengine/audio
/modules/ogg/ @godotengine/audio
/modules/opus/ @godotengine/audio
/modules/theora/ @godotengine/audio
/modules/vorbis/ @godotengine/audio
/modules/webm/ @godotengine/audio
## Import
/modules/astcenc/ @godotengine/import
/modules/basis_universal/ @godotengine/import
/modules/betsy/ @godotengine/import
/modules/bmp/ @godotengine/import
/modules/cvtt/ @godotengine/import
/modules/dds/ @godotengine/import
/modules/etcpak/ @godotengine/import
/modules/fbx/ @godotengine/import
/modules/fbx/doc_classes/ @godotengine/import @godotengine/documentation
/modules/gltf/ @godotengine/import
/modules/gltf/doc_classes/ @godotengine/import @godotengine/documentation
/modules/gltf/tests/ @godotengine/import @godotengine/tests
/modules/hdr/ @godotengine/import
/modules/jpg/ @godotengine/import
/modules/ktx/ @godotengine/import
/modules/squish/ @godotengine/import
/modules/svg/ @godotengine/import
/modules/tga/ @godotengine/import
/modules/tinyexr/ @godotengine/import
/modules/webp/ @godotengine/import
/modules/basis_universal/ @godotengine/import
/modules/bmp/ @godotengine/import
/modules/cvtt/ @godotengine/import
/modules/dds/ @godotengine/import
/modules/etc/ @godotengine/import
/modules/fbx/ @godotengine/import
/modules/gltf/ @godotengine/import
/modules/hdr/ @godotengine/import
/modules/jpg/ @godotengine/import
/modules/pvr/ @godotengine/import
/modules/squish/ @godotengine/import
/modules/svg/ @godotengine/import
/modules/tga/ @godotengine/import
/modules/tinyexr/ @godotengine/import
/modules/webp/ @godotengine/import
## Network
/modules/enet/ @godotengine/network
/modules/enet/doc_classes/ @godotengine/network @godotengine/documentation
/modules/mbedtls/ @godotengine/network
/modules/mbedtls/tests/ @godotengine/network @godotengine/tests
/modules/multiplayer/ @godotengine/network
/modules/multiplayer/doc_classes/ @godotengine/network @godotengine/documentation
/modules/upnp/ @godotengine/network
/modules/upnp/doc_classes/ @godotengine/network @godotengine/documentation
/modules/webrtc/ @godotengine/network
/modules/webrtc/doc_classes/ @godotengine/network @godotengine/documentation
/modules/websocket/ @godotengine/network
/modules/websocket/doc_classes/ @godotengine/network @godotengine/documentation
## Physics
/modules/godot_physics_2d/ @godotengine/physics
/modules/godot_physics_3d/ @godotengine/physics
/modules/enet/ @godotengine/network
/modules/mbedtls/ @godotengine/network
/modules/upnp/ @godotengine/network
/modules/webrtc/ @godotengine/network
/modules/websocket/ @godotengine/network
## Rendering
/modules/glslang/ @godotengine/rendering
/modules/lightmapper_rd/ @godotengine/rendering
/modules/meshoptimizer/ @godotengine/rendering
/modules/raycast/ @godotengine/rendering
/modules/vhacd/ @godotengine/rendering
/modules/xatlas_unwrap/ @godotengine/rendering
/modules/denoise/ @godotengine/rendering
/modules/glslang/ @godotengine/rendering
/modules/lightmapper_rd/ @godotengine/rendering
/modules/meshoptimizer/ @godotengine/rendering
/modules/vhacd/ @godotengine/rendering
/modules/xatlas_unwrap/ @godotengine/rendering
## Scripting
/modules/gdscript/ @godotengine/gdscript
/modules/gdscript/doc_classes/ @godotengine/gdscript @godotengine/documentation
/modules/gdscript/icons/ @godotengine/gdscript @godotengine/usability
/modules/gdscript/tests/ @godotengine/gdscript @godotengine/tests
/modules/jsonrpc/ @godotengine/gdscript @godotengine/network
/modules/jsonrpc/tests @godotengine/gdscript @godotengine/network @godotengine/tests
/modules/mono/ @godotengine/dotnet
/modules/mono/doc_classes/ @godotengine/dotnet @godotengine/documentation
/modules/mono/icons/ @godotengine/dotnet @godotengine/usability
/modules/gdscript/ @godotengine/gdscript
/modules/jsonrpc/ @godotengine/gdscript
/modules/mono/ @godotengine/dotnet
## Text
/modules/freetype/ @godotengine/buildsystem
/modules/msdfgen/ @godotengine/buildsystem
/modules/text_server_adv/ @godotengine/gui-nodes
/modules/text_server_adv/doc_classes/ @godotengine/gui-nodes @godotengine/documentation
/modules/text_server_fb/ @godotengine/gui-nodes
/modules/text_server_fb/doc_classes/ @godotengine/gui-nodes @godotengine/documentation
/modules/freetype/ @godotengine/buildsystem
/modules/text_server_adv/ @godotengine/gui-nodes
/modules/text_server_fb/ @godotengine/gui-nodes
## XR
/modules/camera/ @godotengine/xr
/modules/mobile_vr/ @godotengine/xr
/modules/mobile_vr/doc_classes/ @godotengine/xr @godotengine/documentation
/modules/openxr/ @godotengine/xr
/modules/openxr/doc_classes/ @godotengine/xr @godotengine/documentation
/modules/webxr/ @godotengine/xr
/modules/webxr/doc_classes/ @godotengine/xr @godotengine/documentation
/modules/camera/ @godotengine/xr
/modules/gdextension/xr/ @godotengine/xr
/modules/mobile_vr/ @godotengine/xr
/modules/webxr/ @godotengine/xr
## Misc
/modules/csg/ @godotengine/3d-nodes
/modules/csg/doc_classes/ @godotengine/3d-nodes @godotengine/documentation
/modules/csg/icons/ @godotengine/3d-nodes @godotengine/usability
/modules/navigation/ @godotengine/navigation
/modules/gridmap/ @godotengine/3d-nodes
/modules/gridmap/doc_classes/ @godotengine/3d-nodes @godotengine/documentation
/modules/gridmap/icons/ @godotengine/3d-nodes @godotengine/usability
/modules/noise/ @godotengine/core
/modules/noise/doc_classes/ @godotengine/core @godotengine/documentation
/modules/noise/icons/ @godotengine/core @godotengine/usability
/modules/noise/tests/ @godotengine/core @godotengine/tests
/modules/regex/ @godotengine/core
/modules/regex/doc_classes/ @godotengine/core @godotengine/documentation
/modules/regex/icons/ @godotengine/core @godotengine/usability
/modules/regex/tests/ @godotengine/core @godotengine/tests
/modules/zip/ @godotengine/core
/modules/zip/doc_classes/ @godotengine/core @godotengine/documentation
/modules/bullet/ @godotengine/physics
/modules/csg/ @godotengine/3d-nodes
/modules/gdnavigation/ @godotengine/navigation
/modules/gridmap/ @godotengine/3d-nodes
/modules/opensimplex/ @godotengine/3d-nodes
/modules/regex/ @godotengine/core
# Platform
/platform/android/ @godotengine/android
/platform/android/doc_classes/ @godotengine/android @godotengine/documentation
/platform/ios/ @godotengine/ios
/platform/ios/doc_classes/ @godotengine/ios @godotengine/documentation
/platform/linuxbsd/ @godotengine/linux-bsd
/platform/linuxbsd/doc_classes/ @godotengine/linux-bsd @godotengine/documentation
/platform/macos/ @godotengine/macos
/platform/macos/doc_classes/ @godotengine/macos @godotengine/documentation
/platform/web/ @godotengine/web
/platform/web/doc_classes/ @godotengine/web @godotengine/documentation
/platform/windows/ @godotengine/windows
/platform/windows/doc_classes/ @godotengine/windows @godotengine/documentation
/platform/android/ @godotengine/android
/platform/ios/ @godotengine/ios
/platform/linuxbsd/ @godotengine/linux-bsd
/platform/macos/ @godotengine/macos
/platform/web/ @godotengine/web
/platform/windows/ @godotengine/windows
# Scene
/scene/2d/ @godotengine/2d-nodes
/scene/2d/physics/ @godotengine/2d-nodes @godotengine/physics
/scene/3d/ @godotengine/3d-nodes
/scene/3d/physics/ @godotengine/3d-nodes @godotengine/physics
/scene/animation/ @godotengine/animation
/scene/audio/ @godotengine/audio
/scene/debugger/ @godotengine/debugger
/scene/gui/ @godotengine/gui-nodes
/scene/main/ @godotengine/core
/scene/resources/font.* @godotengine/gui-nodes
/scene/resources/text_line.* @godotengine/gui-nodes
/scene/resources/text_paragraph.* @godotengine/gui-nodes
/scene/resources/visual_shader*.* @godotengine/shaders
/scene/theme/ @godotengine/gui-nodes
/scene/theme/icons/ @godotengine/gui-nodes @godotengine/usability
/scene/2d/ @godotengine/2d-nodes
/scene/3d/ @godotengine/3d-nodes
/scene/animation/ @godotengine/animation
/scene/audio/ @godotengine/audio
/scene/debugger/ @godotengine/debugger
/scene/gui/ @godotengine/gui-nodes
/scene/main/ @godotengine/core
/scene/resources/font.* @godotengine/gui-nodes
/scene/resources/text_line.* @godotengine/gui-nodes
/scene/resources/text_paragraph.* @godotengine/gui-nodes
/scene/resources/visual_shader*.* @godotengine/shaders
/scene/theme/ @godotengine/gui-nodes
# Servers
/servers/audio* @godotengine/audio
/servers/camera* @godotengine/xr
/servers/display_server.* @godotengine/_platforms
/servers/navigation_server*.* @godotengine/navigation
/servers/physics* @godotengine/physics
/servers/rendering* @godotengine/rendering
/servers/text_server.* @godotengine/gui-nodes
/servers/xr* @godotengine/xr
/servers/audio* @godotengine/audio
/servers/camera* @godotengine/xr
/servers/display_server.* @godotengine/_platforms
/servers/navigation_server*.* @godotengine/navigation
/servers/physics* @godotengine/physics
/servers/rendering* @godotengine/rendering
/servers/text_server.* @godotengine/gui-nodes
/servers/xr* @godotengine/xr
# Tests
/tests/ @godotengine/tests
/tests/ @godotengine/tests
# Thirdparty
/thirdparty/ @godotengine/buildsystem
# Buildsystem (After everything to catch all)
*.py @godotengine/buildsystem
SConstruct @godotengine/buildsystem
SCsub @godotengine/buildsystem
/thirdparty/ @godotengine/buildsystem

View File

@ -1,72 +1,72 @@
name: Bug report
description: Report a bug in Godot
body:
- type: markdown
attributes:
value: |
When reporting bugs, please follow the guidelines in this template. This helps identify the problem precisely and thus enables contributors to fix it faster.
- Write a descriptive issue title above.
- The golden rule is to **always open *one* issue for *one* bug**. If you notice several bugs and want to report them, make sure to create one new issue for each of them.
- Search [open](https://github.com/godotengine/godot/issues) and [closed](https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aclosed) issues to ensure it has not already been reported. If you don't find a relevant match or if you're unsure, don't hesitate to **open a new issue**. The bugsquad will handle it from there if it's a duplicate.
- Verify that you are using a [supported Godot version](https://docs.godotengine.org/en/latest/about/release_policy.html). Please always check if your issue is reproducible in the latest version it may already have been fixed!
- If you use a custom build, please test if your issue is reproducible in official builds too. Likewise if you use any C++ modules, GDExtensions, or editor plugins, you should check if the bug is reproducible in a project without these.
- type: textarea
attributes:
label: Tested versions
description: |
To properly fix a bug, we need to identify if the bug was recently introduced in the engine, or if it was always present.
- Please specify the Godot version you found the issue in, including the **Git commit hash** if using a development or non-official build. The exact Godot version (including the commit hash) can be copied by clicking the version shown in the editor (bottom bar) or in the project manager (top bar).
- If you can, **please test earlier Godot versions** (previous stable branch, and development snapshots of the current feature release) and, if applicable, newer versions (development snapshots for the next feature release). Mention whether the bug is reproducible or not in the versions you tested. You can find all Godot releases in our [download archive](https://godotengine.org/download/archive/).
- The aim is for us to identify whether a bug is a **regression**, i.e. an issue that didn't exist in a previous version, but was introduced later on, breaking existing functionality. For example, if a bug is reproducible in 4.2.stable but not in 4.1.stable, we would like you to test intermediate 4.2 dev and beta snapshots to find which snapshot is the first one where the issue can be reproduced.
placeholder: |
- type: markdown
attributes:
value: |
When reporting bugs, please follow the guidelines in this template. This helps identify the problem precisely and thus enables contributors to fix it faster.
- Write a descriptive issue title above.
- The golden rule is to **always open *one* issue for *one* bug**. If you notice several bugs and want to report them, make sure to create one new issue for each of them.
- Search [open](https://github.com/godotengine/godot/issues) and [closed](https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aclosed) issues to ensure it has not already been reported. If you don't find a relevant match or if you're unsure, don't hesitate to **open a new issue**. The bugsquad will handle it from there if it's a duplicate.
- Verify that you are using a [supported Godot version](https://docs.godotengine.org/en/latest/about/release_policy.html). Please always check if your issue is reproducible in the latest version it may already have been fixed!
- If you use a custom build, please test if your issue is reproducible in official builds too. Likewise if you use any C++ modules, GDExtensions, or editor plugins, you should check if the bug is reproducible in a project without these.
- Reproducible in: 4.3.dev [d76c1d0e5], 4.2.stable, 4.2.dev5 and later 4.2 snapshots.
- Not reproducible in: 4.1.3.stable, 4.2.dev4 and earlier 4.2 snapshots.
validations:
required: true
- type: textarea
attributes:
label: Tested versions
description: |
To properly fix a bug, we need to identify if the bug was recently introduced in the engine, or if it was always present.
- Please specify the Godot version you found the issue in, including the **Git commit hash** if using a development or non-official build. The exact Godot version (including the commit hash) can be copied by clicking the version shown in the editor (bottom bar) or in the project manager (top bar).
- If you can, **please test earlier Godot versions** (previous stable branch, and development snapshots of the current feature release) and, if applicable, newer versions (development snapshots for the next feature release). Mention whether the bug is reproducible or not in the versions you tested. You can find all Godot releases in our [download archive](https://godotengine.org/download/archive/).
- The aim is for us to identify whether a bug is a **regression**, i.e. an issue that didn't exist in a previous version, but was introduced later on, breaking existing functionality. For example, if a bug is reproducible in 4.2.stable but not in 4.1.stable, we would like you to test intermediate 4.2 dev and beta snapshots to find which snapshot is the first one where the issue can be reproduced.
placeholder: |
- type: input
attributes:
label: System information
description: |
- Specify the OS version, and when relevant hardware information.
- For issues that are likely OS-specific and/or graphics-related, please specify the CPU model and architecture.
- For graphics-related issues, specify the GPU model, driver version, and the rendering backend (GLES2, GLES3, Vulkan).
- **Bug reports not including the required information may be closed at the maintainers' discretion.** If in doubt, always include all the requested information; it's better to include too much information than not enough information.
- **Starting from Godot 4.1, you can copy this information to your clipboard by using *Help > Copy System Info* at the top of the editor window.**
placeholder: Windows 10 - Godot v4.0.3.stable - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 970 (nvidia, 510.85.02) - Intel Core i7-10700KF CPU @ 3.80GHz (16 Threads)
validations:
required: true
- Reproducible in: 4.3.dev [d76c1d0e5], 4.2.stable, 4.2.dev5 and later 4.2 snapshots.
- Not reproducible in: 4.1.3.stable, 4.2.dev4 and earlier 4.2 snapshots.
validations:
required: true
- type: textarea
attributes:
label: Issue description
description: |
Describe your issue briefly. What doesn't work, and how do you expect it to work instead?
You can include images or videos with drag and drop, and format code blocks or logs with <code>\`\`\`</code> tags, on separate lines before and after the text. (Use <code>\`\`\`gdscript</code> to add GDScript syntax highlighting.)
Please do not add code examples or error messages as screenshots, but as text, this helps searching for issues and testing the code. If you are reporting a bug in the editor interface, like the script editor, please provide both a screenshot *and* the text of the code to help with testing.
validations:
required: true
- type: input
attributes:
label: System information
description: |
- Specify the OS version, and when relevant hardware information.
- For issues that are likely OS-specific and/or graphics-related, please specify the CPU model and architecture.
- For graphics-related issues, specify the GPU model, driver version, and the rendering backend (GLES2, GLES3, Vulkan).
- **Bug reports not including the required information may be closed at the maintainers' discretion.** If in doubt, always include all the requested information; it's better to include too much information than not enough information.
- **Starting from Godot 4.1, you can copy this information to your clipboard by using *Help > Copy System Info* at the top of the editor window.**
placeholder: Windows 10 - Godot v4.0.3.stable - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 970 (nvidia, 510.85.02) - Intel Core i7-10700KF CPU @ 3.80GHz (16 Threads)
validations:
required: true
- type: textarea
attributes:
label: Steps to reproduce
description: |
List of steps or sample code that reproduces the issue. Having reproducible issues is a prerequisite for contributors to be able to solve them.
If you include a minimal reproduction project below, you can detail how to use it here.
validations:
required: true
- type: textarea
attributes:
label: Issue description
description: |
Describe your issue briefly. What doesn't work, and how do you expect it to work instead?
You can include images or videos with drag and drop, and format code blocks or logs with <code>\`\`\`</code> tags, on separate lines before and after the text. (Use <code>\`\`\`gdscript</code> to add GDScript syntax highlighting.)
Please do not add code examples or error messages as screenshots, but as text, this helps searching for issues and testing the code. If you are reporting a bug in the editor interface, like the script editor, please provide both a screenshot *and* the text of the code to help with testing.
validations:
required: true
- type: textarea
attributes:
label: Minimal reproduction project (MRP)
description: |
- A small Godot project which reproduces the issue, with no unnecessary files included. Be sure to not include the `.godot` folder in the archive (but keep `project.godot`).
- Having an MRP is very important for contributors to be able to reproduce the bug in the same way that you are experiencing it. When testing a potential fix for the issue, contributors will use the MRP to validate that the fix is working as intended.
- If the reproduction steps are not project dependent (e.g. the bug is visible in a brand new project), you can write "N/A" in the field.
- Drag and drop a ZIP archive to upload it (max 10 MB). **Do not select another field until the project is done uploading.**
- **Note for C# users:** If your issue is *not* C#-specific, please upload a minimal reproduction project written in GDScript. This will make it easier for contributors to reproduce the issue locally as not everyone has a .NET setup available.
validations:
required: true
- type: textarea
attributes:
label: Steps to reproduce
description: |
List of steps or sample code that reproduces the issue. Having reproducible issues is a prerequisite for contributors to be able to solve them.
If you include a minimal reproduction project below, you can detail how to use it here.
validations:
required: true
- type: textarea
attributes:
label: Minimal reproduction project (MRP)
description: |
- A small Godot project which reproduces the issue, with no unnecessary files included. Be sure to not include the `.godot` folder in the archive (but keep `project.godot`).
- Having an MRP is very important for contributors to be able to reproduce the bug in the same way that you are experiencing it. When testing a potential fix for the issue, contributors will use the MRP to validate that the fix is working as intended.
- If the reproduction steps are not project dependent (e.g. the bug is visible in a brand new project), you can write "N/A" in the field.
- Drag and drop a ZIP archive to upload it (max 10 MB). **Do not select another field until the project is done uploading.**
- **Note for C# users:** If your issue is *not* C#-specific, please upload a minimal reproduction project written in GDScript. This will make it easier for contributors to reproduce the issue locally as not everyone has a .NET setup available.
validations:
required: true

View File

@ -1,17 +1,15 @@
name: Download Godot artifact
description: Download the Godot artifact.
inputs:
name:
description: The artifact name.
default: ${{ github.job }}
default: "${{ github.job }}"
path:
description: The path to download and extract to.
required: true
default: ./
default: "./"
runs:
using: composite
using: "composite"
steps:
- name: Download Godot Artifact
uses: actions/download-artifact@v4

View File

@ -1,13 +1,11 @@
name: Dump Godot API
description: Dump Godot API for GDExtension
inputs:
bin:
description: The path to the Godot executable
required: true
runs:
using: composite
using: "composite"
steps:
# Dump GDExtension interface and API
- name: Dump GDExtension interface and API for godot-cpp build
@ -21,5 +19,5 @@ runs:
- name: Upload API dump
uses: ./.github/actions/upload-artifact
with:
name: godot-api-dump
path: ./godot-api/*
name: 'godot-api-dump'
path: './godot-api/*'

View File

@ -1,39 +1,34 @@
name: Build Godot
description: Build Godot with the provided options.
inputs:
target:
description: Build target (editor, template_release, template_debug).
default: editor
default: "editor"
tests:
description: Unit tests.
default: false
required: false
platform:
description: Target platform.
required: false
sconsflags:
description: Additional SCons flags.
default: ''
required: false
default: ""
scons-cache:
description: The SCons cache path.
default: ${{ github.workspace }}/.scons-cache/
default: "${{ github.workspace }}/.scons-cache/"
scons-cache-limit:
description: The SCons cache size limit.
# actions/cache has 10 GiB limit, and GitHub runners have a 14 GiB disk.
# Limit to 7 GiB to avoid having the extracted cache fill the disk.
default: 7168
runs:
using: composite
using: "composite"
steps:
- name: SCons Build
- name: Scons Build
shell: sh
env:
SCONSFLAGS: ${{ inputs.sconsflags }}
SCONS_CACHE: ${{ inputs.scons-cache }}
SCONS_CACHE_LIMIT: ${{ inputs.scons-cache-limit }}
SCONSFLAGS: ${{ inputs.sconsflags }}
SCONS_CACHE: ${{ inputs.scons-cache }}
SCONS_CACHE_LIMIT: ${{ inputs.scons-cache-limit }}
run: |
echo "Building with flags:" platform=${{ inputs.platform }} target=${{ inputs.target }} tests=${{ inputs.tests }} ${{ env.SCONSFLAGS }}

View File

@ -3,19 +3,18 @@ description: Restore Godot build cache.
inputs:
cache-name:
description: The cache base name (job name by default).
default: ${{ github.job }}
default: "${{github.job}}"
scons-cache:
description: The SCons cache path.
default: ${{ github.workspace }}/.scons-cache/
default: "${{github.workspace}}/.scons-cache/"
runs:
using: composite
using: "composite"
steps:
- name: Restore SCons cache directory
uses: actions/cache/restore@v4
with:
path: ${{ inputs.scons-cache }}
key: ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}-${{ github.sha }}
path: ${{inputs.scons-cache}}
key: ${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}}
# We try to match an existing cache to restore from it. Each potential key is checked against
# all existing caches as a prefix. E.g. 'linux-template-minimal' would match any cache that
@ -29,7 +28,7 @@ runs:
# 4. A partial match for the same base branch only (not ideal, matches any PR with the same base branch).
restore-keys: |
${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}-${{ github.sha }}
${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}
${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-refs/heads/${{ env.GODOT_BASE_BRANCH }}
${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}
${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}}
${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}
${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-refs/heads/${{env.GODOT_BASE_BRANCH}}
${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}

View File

@ -3,16 +3,15 @@ description: Save Godot build cache.
inputs:
cache-name:
description: The cache base name (job name by default).
default: ${{ github.job }}
default: "${{github.job}}"
scons-cache:
description: The SCons cache path.
default: ${{ github.workspace }}/.scons-cache/
default: "${{github.workspace}}/.scons-cache/"
runs:
using: composite
using: "composite"
steps:
- name: Save SCons cache directory
uses: actions/cache/save@v4
with:
path: ${{ inputs.scons-cache }}
key: ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}-${{ github.sha }}
path: ${{inputs.scons-cache}}
key: ${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}}

View File

@ -1,13 +1,11 @@
name: Test Godot project converter
description: Test the Godot project converter.
inputs:
bin:
description: The path to the Godot executable
required: true
runs:
using: composite
using: "composite"
steps:
- name: Test 3-to-4 conversion
shell: sh

View File

@ -1,19 +1,17 @@
name: Setup Python and SCons
description: Setup Python, install the pip version of SCons.
inputs:
python-version:
description: The Python version to use.
default: 3.x
default: "3.x"
python-arch:
description: The Python architecture.
default: x64
default: "x64"
scons-version:
description: The SCons version to use.
default: 4.8.0
default: "4.8.0"
runs:
using: composite
using: "composite"
steps:
- name: Set up Python 3.x
uses: actions/setup-python@v5

View File

@ -1,13 +1,11 @@
name: Test Godot project
description: Run the test Godot project.
inputs:
bin:
description: The path to the Godot executable
required: true
runs:
using: composite
using: "composite"
steps:
# Download and extract zip archive with project, folder is renamed to be able to easy change used project
- name: Download test project

View File

@ -1,17 +1,15 @@
name: Upload Godot artifact
description: Upload the Godot artifact.
inputs:
name:
description: The artifact name.
default: ${{ github.job }}
default: "${{ github.job }}"
path:
description: The path to upload.
required: true
default: bin/*
default: "bin/*"
runs:
using: composite
using: "composite"
steps:
- name: Upload Godot Artifact
uses: actions/upload-artifact@v4

View File

@ -5,16 +5,16 @@ on:
# Global Settings
env:
# Used for the cache key. Add version suffix to force clean build.
GODOT_BASE_BRANCH: master
SCONSFLAGS: verbose=yes warnings=extra werror=yes debug_symbols=no module_text_server_fb_enabled=yes strict_checks=yes
GODOT_BASE_BRANCH: 4.3
SCONSFLAGS: verbose=yes warnings=extra werror=yes debug_symbols=no module_text_server_fb_enabled=yes
concurrency:
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-android
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-android
cancel-in-progress: true
jobs:
build-android:
runs-on: ubuntu-20.04
runs-on: "ubuntu-20.04"
name: ${{ matrix.name }}
strategy:
fail-fast: false
@ -39,8 +39,7 @@ jobs:
sconsflags: arch=arm64
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: actions/checkout@v4
with:
submodules: recursive
@ -86,7 +85,6 @@ jobs:
run: |
cd platform/android/java
./gradlew generateGodotEditor
./gradlew generateGodotHorizonOSEditor
cd ../../..
ls -l bin/android_editor_builds/

View File

@ -5,60 +5,54 @@ on:
# Global Settings
env:
# Used for the cache key. Add version suffix to force clean build.
GODOT_BASE_BRANCH: master
GODOT_BASE_BRANCH: 4.3
# Used for the godot-cpp checkout.
GODOT_CPP_BRANCH: 4.3
GODOT_CPP_BRANCH: '4.2'
concurrency:
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-cpp-tests
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-cpp-tests
cancel-in-progress: true
jobs:
godot-cpp-tests:
runs-on: ubuntu-20.04
name: Build and test Godot CPP
runs-on: "ubuntu-20.04"
name: "Build and test Godot CPP"
steps:
- name: Checkout
uses: actions/checkout@v4
with:
sparse-checkout: .github
- name: Checkout godot-cpp
uses: actions/checkout@v4
- uses: actions/checkout@v4
with:
submodules: recursive
repository: godotengine/godot-cpp
ref: ${{ env.GODOT_CPP_BRANCH }}
path: godot-cpp
- name: Setup Python and SCons
uses: ./.github/actions/godot-deps
- name: Setup GCC problem matcher
uses: ammaraskar/gcc-problem-matcher@master
# Checkout godot-cpp
- name: Checkout godot-cpp
uses: actions/checkout@v4
with:
repository: godotengine/godot-cpp
ref: ${{ env.GODOT_CPP_BRANCH }}
submodules: 'recursive'
path: 'godot-cpp'
# Download generated API dump
- name: Download GDExtension interface and API dump
uses: ./.github/actions/download-artifact
with:
name: godot-api-dump
path: ./godot-cpp/gdextension
name: 'godot-api-dump'
path: './godot-api'
# TODO: Enable caching when godot-cpp has proper cache limiting.
# Extract and override existing files with generated files
- name: Extract GDExtension interface and API dump
run: |
cp -f godot-api/gdextension_interface.h godot-cpp/gdextension/
cp -f godot-api/extension_api.json godot-cpp/gdextension/
# - name: Restore Godot build cache
# uses: ./.github/actions/godot-cache-restore
# with:
# cache-name: godot-cpp
# continue-on-error: true
# TODO: Add caching to the SCons build and store it for CI via the godot-cache
# action.
# Build godot-cpp test extension
- name: Build godot-cpp test extension
env: # Keep synced with godot-build.
SCONS_CACHE: ${{ github.workspace }}/.scons-cache/
SCONS_CACHE_LIMIT: 7168
run: scons --directory=./godot-cpp/test target=template_debug dev_build=yes verbose=yes
# - name: Save Godot build cache
# uses: ./.github/actions/godot-cache-save
# with:
# cache-name: godot-cpp
# continue-on-error: true
run: |
cd godot-cpp/test
scons target=template_debug dev_build=yes
cd ../..

View File

@ -5,21 +5,20 @@ on:
# Global Settings
env:
# Used for the cache key. Add version suffix to force clean build.
GODOT_BASE_BRANCH: master
SCONSFLAGS: verbose=yes warnings=extra werror=yes debug_symbols=no module_text_server_fb_enabled=yes strict_checks=yes
GODOT_BASE_BRANCH: 4.3
SCONSFLAGS: verbose=yes warnings=extra werror=yes debug_symbols=no module_text_server_fb_enabled=yes
concurrency:
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-ios
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-ios
cancel-in-progress: true
jobs:
ios-template:
runs-on: macos-latest
runs-on: "macos-latest"
name: Template (target=template_release)
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: actions/checkout@v4
with:
submodules: recursive

View File

@ -5,19 +5,19 @@ on:
# Global Settings
env:
# Used for the cache key. Add version suffix to force clean build.
GODOT_BASE_BRANCH: master
SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes strict_checks=yes
GODOT_BASE_BRANCH: 4.3
SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: true
TSAN_OPTIONS: suppressions=misc/error_suppressions/tsan.txt
concurrency:
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-linux
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-linux
cancel-in-progress: true
jobs:
build-linux:
runs-on: ubuntu-20.04
runs-on: "ubuntu-20.04"
name: ${{ matrix.name }}
strategy:
fail-fast: false
@ -27,7 +27,7 @@ jobs:
cache-name: linux-editor-mono
target: editor
sconsflags: module_mono_enabled=yes
bin: ./bin/godot.linuxbsd.editor.x86_64.mono
bin: "./bin/godot.linuxbsd.editor.x86_64.mono"
build-mono: true
tests: false # Disabled due freeze caused by mix Mono build and CI
doc-test: true
@ -40,7 +40,7 @@ jobs:
target: editor
# Debug symbols disabled as they're huge on this build and we hit the 14 GB limit for runners.
sconsflags: dev_build=yes scu_build=yes debug_symbols=no precision=double use_asan=yes use_ubsan=yes linker=gold
bin: ./bin/godot.linuxbsd.editor.dev.double.x86_64.san
bin: "./bin/godot.linuxbsd.editor.dev.double.x86_64.san"
build-mono: false
tests: true
proj-test: true
@ -53,7 +53,7 @@ jobs:
cache-name: linux-editor-llvm-sanitizers
target: editor
sconsflags: dev_build=yes use_asan=yes use_ubsan=yes use_llvm=yes linker=lld
bin: ./bin/godot.linuxbsd.editor.dev.x86_64.llvm.san
bin: "./bin/godot.linuxbsd.editor.dev.x86_64.llvm.san"
build-mono: false
tests: true
# Skip 2GiB artifact speeding up action.
@ -66,37 +66,36 @@ jobs:
target: editor
tests: true
sconsflags: dev_build=yes use_tsan=yes use_llvm=yes linker=lld
bin: ./bin/godot.linuxbsd.editor.dev.x86_64.llvm.san
bin: "./bin/godot.linuxbsd.editor.dev.x86_64.llvm.san"
build-mono: false
# Skip 2GiB artifact speeding up action.
artifact: false
- name: Template w/ Mono (target=template_release, tests=yes)
- name: Template w/ Mono (target=template_release)
cache-name: linux-template-mono
target: template_release
sconsflags: module_mono_enabled=yes
bin: ./bin/godot.linuxbsd.template_release.x86_64.mono
sconsflags: module_mono_enabled=yes tests=yes
bin: "./bin/godot.linuxbsd.template_release.x86_64.mono"
build-mono: false
tests: true
artifact: true
- name: Minimal template (target=template_release, tests=yes, everything disabled)
- name: Minimal template (target=template_release, everything disabled)
cache-name: linux-template-minimal
target: template_release
sconsflags: modules_enabled_by_default=no disable_3d=yes disable_advanced_gui=yes deprecated=no minizip=no
bin: ./bin/godot.linuxbsd.template_release.x86_64
sconsflags: modules_enabled_by_default=no disable_3d=yes disable_advanced_gui=yes deprecated=no minizip=no tests=yes
bin: "./bin/godot.linuxbsd.template_release.x86_64"
tests: true
artifact: true
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: actions/checkout@v4
with:
submodules: recursive
# Need newer mesa for lavapipe to work properly.
- name: Linux dependencies for tests
if: matrix.proj-test
if: ${{ matrix.proj-test }}
run: |
sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EB8B81E14DA65431D7504EA8F63F0F2B90935439
@ -121,11 +120,11 @@ jobs:
continue-on-error: true
- name: Setup Python and SCons
if: '!matrix.legacy-scons'
if: ${{ ! matrix.legacy-scons }}
uses: ./.github/actions/godot-deps
- name: Setup Python and SCons (legacy versions)
if: matrix.legacy-scons
if: ${{ matrix.legacy-scons }}
uses: ./.github/actions/godot-deps
with:
# Sync with Ensure*Version in SConstruct.
@ -150,48 +149,48 @@ jobs:
continue-on-error: true
- name: Generate C# glue
if: matrix.build-mono
if: ${{ matrix.build-mono }}
run: |
${{ matrix.bin }} --headless --generate-mono-glue ./modules/mono/glue
- name: Build .NET solutions
if: matrix.build-mono
if: ${{ matrix.build-mono }}
run: |
./modules/mono/build_scripts/build_assemblies.py --godot-output-dir=./bin --godot-platform=linuxbsd
- name: Prepare artifact
if: matrix.artifact
if: ${{ matrix.artifact }}
run: |
strip bin/godot.*
chmod +x bin/godot.*
- name: Upload artifact
uses: ./.github/actions/upload-artifact
if: matrix.artifact
if: ${{ matrix.artifact }}
with:
name: ${{ matrix.cache-name }}
- name: Dump Godot API
uses: ./.github/actions/godot-api-dump
if: matrix.api-dump
if: ${{ matrix.api-dump }}
with:
bin: ${{ matrix.bin }}
- name: Unit tests
if: matrix.tests
if: ${{ matrix.tests }}
run: |
${{ matrix.bin }} --version
${{ matrix.bin }} --help
${{ matrix.bin }} --headless --test --force-colors
- name: .NET source generators tests
if: matrix.build-mono
if: ${{ matrix.build-mono }}
run: |
dotnet test modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests
# Check class reference
- name: Check for class reference updates
if: matrix.doc-test
if: ${{ matrix.doc-test }}
run: |
echo "Running --doctool to see if this changes the public API without updating the documentation."
echo -e "If a diff is shown, it means that your code/doc changes are incomplete and you should update the class reference with --doctool.\n\n"
@ -200,20 +199,20 @@ jobs:
# Check API backwards compatibility
- name: Check for GDExtension compatibility
if: matrix.api-compat
if: ${{ matrix.api-compat }}
run: |
./misc/scripts/validate_extension_api.sh "${{ matrix.bin }}"
# Download and run the test project
- name: Test Godot project
uses: ./.github/actions/godot-project-test
if: matrix.proj-test
if: ${{ matrix.proj-test }}
with:
bin: ${{ matrix.bin }}
# Test the project converter
- name: Test project converter
uses: ./.github/actions/godot-converter-test
if: matrix.proj-conv
if: ${{ matrix.proj-conv }}
with:
bin: ${{ matrix.bin }}

View File

@ -5,16 +5,16 @@ on:
# Global Settings
env:
# Used for the cache key. Add version suffix to force clean build.
GODOT_BASE_BRANCH: master
SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes strict_checks=yes
GODOT_BASE_BRANCH: 4.3
SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes
concurrency:
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-macos
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-macos
cancel-in-progress: true
jobs:
build-macos:
runs-on: macos-latest
runs-on: "macos-latest"
name: ${{ matrix.name }}
strategy:
fail-fast: false
@ -24,18 +24,17 @@ jobs:
cache-name: macos-editor
target: editor
tests: true
bin: ./bin/godot.macos.editor.universal
bin: "./bin/godot.macos.editor.universal"
- name: Template (target=template_release, tests=yes)
- name: Template (target=template_release)
cache-name: macos-template
target: template_release
tests: true
sconsflags: debug_symbols=no
bin: ./bin/godot.macos.template_release.universal
sconsflags: debug_symbols=no tests=yes
bin: "./bin/godot.macos.template_release.universal"
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: actions/checkout@v4
with:
submodules: recursive
@ -87,7 +86,7 @@ jobs:
name: ${{ matrix.cache-name }}
- name: Unit tests
if: matrix.tests
if: ${{ matrix.tests }}
run: |
${{ matrix.bin }} --version
${{ matrix.bin }} --help

View File

@ -1,46 +1,52 @@
name: 🔗 GHA
on: [push, pull_request, merge_group]
on: [push, pull_request]
concurrency:
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-runner
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-runner
cancel-in-progress: true
jobs:
# First stage: Only static checks, fast and prevent expensive builds from running.
static-checks:
if: '!vars.DISABLE_GODOT_CI'
if: ${{ vars.DISABLE_GODOT_CI == '' }}
name: 📊 Static checks
uses: ./.github/workflows/static_checks.yml
# Second stage: Run all the builds and some of the tests.
android-build:
if: ${{ vars.DISABLE_GODOT_CI == '' }}
name: 🤖 Android
needs: static-checks
uses: ./.github/workflows/android_builds.yml
ios-build:
if: ${{ vars.DISABLE_GODOT_CI == '' }}
name: 🍏 iOS
needs: static-checks
uses: ./.github/workflows/ios_builds.yml
linux-build:
if: ${{ vars.DISABLE_GODOT_CI == '' }}
name: 🐧 Linux
needs: static-checks
uses: ./.github/workflows/linux_builds.yml
macos-build:
if: ${{ vars.DISABLE_GODOT_CI == '' }}
name: 🍎 macOS
needs: static-checks
uses: ./.github/workflows/macos_builds.yml
windows-build:
if: ${{ vars.DISABLE_GODOT_CI == '' }}
name: 🏁 Windows
needs: static-checks
uses: ./.github/workflows/windows_builds.yml
web-build:
if: ${{ vars.DISABLE_GODOT_CI == '' }}
name: 🌐 Web
needs: static-checks
uses: ./.github/workflows/web_builds.yml
@ -50,6 +56,7 @@ jobs:
# Can be turned off for PRs that intentionally break compat with godot-cpp,
# until both the upstream PR and the matching godot-cpp changes are merged.
godot-cpp-test:
if: ${{ vars.DISABLE_GODOT_CI == '' }}
name: 🪲 Godot CPP
# This can be changed to depend on another platform, if we decide to use it for
# godot-cpp instead. Make sure to move the .github/actions/godot-api-dump step

View File

@ -3,7 +3,7 @@ on:
workflow_call:
concurrency:
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-static
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-static
cancel-in-progress: true
jobs:
@ -48,7 +48,7 @@ jobs:
- name: Style checks via pre-commit
uses: pre-commit/action@v3.0.1
with:
extra_args: --files ${{ env.CHANGED_FILES }}
extra_args: --verbose --files ${{ env.CHANGED_FILES }}
- name: Python builders checks via pytest
run: |
@ -57,7 +57,3 @@ jobs:
- name: Class reference schema checks
run: |
xmllint --noout --schema doc/class.xsd doc/classes/*.xml modules/*/doc_classes/*.xml platform/*/doc_classes/*.xml
- name: Run C compiler on `gdextension_interface.h`
run: |
gcc -c core/extension/gdextension_interface.h

View File

@ -5,18 +5,18 @@ on:
# Global Settings
env:
# Used for the cache key. Add version suffix to force clean build.
GODOT_BASE_BRANCH: master
SCONSFLAGS: verbose=yes warnings=extra werror=yes debug_symbols=no use_closure_compiler=yes strict_checks=yes
GODOT_BASE_BRANCH: 4.3
SCONSFLAGS: verbose=yes warnings=extra werror=yes debug_symbols=no use_closure_compiler=yes
EM_VERSION: 3.1.64
EM_CACHE_FOLDER: emsdk-cache
EM_CACHE_FOLDER: "emsdk-cache"
concurrency:
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-web
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-web
cancel-in-progress: true
jobs:
web-template:
runs-on: ubuntu-22.04
runs-on: "ubuntu-22.04"
name: ${{ matrix.name }}
strategy:
fail-fast: false
@ -37,17 +37,16 @@ jobs:
artifact: true
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up Emscripten latest
uses: mymindstorm/setup-emsdk@v14
with:
version: ${{ env.EM_VERSION }}
actions-cache-folder: ${{ env.EM_CACHE_FOLDER }}
cache-key: emsdk-${{ matrix.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}-${{ github.sha }}
version: ${{env.EM_VERSION}}
actions-cache-folder: ${{env.EM_CACHE_FOLDER}}
cache-key: emsdk-${{ matrix.cache-name }}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}}
- name: Verify Emscripten setup
run: |
@ -78,6 +77,6 @@ jobs:
- name: Upload artifact
uses: ./.github/actions/upload-artifact
if: matrix.artifact
if: ${{ matrix.artifact }}
with:
name: ${{ matrix.cache-name }}

View File

@ -6,18 +6,18 @@ on:
# SCONS_CACHE for windows must be set in the build environment
env:
# Used for the cache key. Add version suffix to force clean build.
GODOT_BASE_BRANCH: master
SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes d3d12=yes strict_checks=yes "angle_libs=${{ github.workspace }}/"
GODOT_BASE_BRANCH: 4.3
SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes d3d12=yes "angle_libs=${{github.workspace}}/"
SCONS_CACHE_MSVC_CONFIG: true
concurrency:
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-windows
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-windows
cancel-in-progress: true
jobs:
build-windows:
# Windows 10 with latest image
runs-on: windows-latest
runs-on: "windows-latest"
name: ${{ matrix.name }}
strategy:
fail-fast: false
@ -29,27 +29,17 @@ jobs:
tests: true
# Skip debug symbols, they're way too big with MSVC.
sconsflags: debug_symbols=no vsproj=yes vsproj_gen_only=no windows_subsystem=console
bin: ./bin/godot.windows.editor.x86_64.exe
artifact: true
bin: "./bin/godot.windows.editor.x86_64.exe"
- name: Editor w/ clang-cl (target=editor, tests=yes, use_llvm=yes)
cache-name: windows-editor-clang
target: editor
tests: true
sconsflags: debug_symbols=no windows_subsystem=console use_llvm=yes
bin: ./bin/godot.windows.editor.x86_64.llvm.exe
- name: Template (target=template_release, tests=yes)
- name: Template (target=template_release)
cache-name: windows-template
target: template_release
tests: true
sconsflags: debug_symbols=no
bin: ./bin/godot.windows.template_release.x86_64.console.exe
artifact: true
sconsflags: debug_symbols=no tests=yes
bin: "./bin/godot.windows.template_release.x86_64.console.exe"
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: actions/checkout@v4
with:
submodules: recursive
@ -74,7 +64,7 @@ jobs:
target: angle/angle.zip
- name: Extract pre-built ANGLE static libraries
run: Expand-Archive -Force angle/angle.zip ${{ github.workspace }}/
run: Expand-Archive -Force angle/angle.zip ${{github.workspace}}/
- name: Setup MSVC problem matcher
uses: ammaraskar/msvc-problem-matcher@master
@ -94,18 +84,16 @@ jobs:
continue-on-error: true
- name: Prepare artifact
if: ${{ matrix.artifact }}
run: |
Remove-Item bin/* -Include *.exp,*.lib,*.pdb -Force
- name: Upload artifact
if: ${{ matrix.artifact }}
uses: ./.github/actions/upload-artifact
with:
name: ${{ matrix.cache-name }}
- name: Unit tests
if: matrix.tests
if: ${{ matrix.tests }}
run: |
${{ matrix.bin }} --version
${{ matrix.bin }} --help

View File

@ -9,7 +9,7 @@ exclude: |
repos:
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v19.1.0
rev: v17.0.6
hooks:
- id: clang-format
files: \.(c|h|cpp|hpp|cc|hh|cxx|hxx|m|mm|inc|java|glsl)$
@ -17,7 +17,6 @@ repos:
exclude: |
(?x)^(
tests/python_build/.*|
platform/android/java/editor/src/main/java/com/android/.*|
platform/android/java/lib/src/com/.*
)
@ -31,7 +30,6 @@ repos:
exclude: |
(?x)^(
tests/python_build/.*|
platform/android/java/editor/src/main/java/com/android/.*|
platform/android/java/lib/src/com/.*
)
additional_dependencies: [clang-tidy==18.1.1]
@ -39,14 +37,14 @@ 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.6.6
rev: v0.4.4
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.11.2
rev: v0.971
hooks:
- id: mypy
files: \.py$
@ -56,11 +54,6 @@ repos:
rev: v2.3.0
hooks:
- id: codespell
exclude: |
(?x)^(
platform/android/java/editor/src/main/java/com/android/.*|
platform/android/java/lib/src/com/.*
)
additional_dependencies: [tomli]
### Requires Docker; look into alternative implementation.
@ -96,21 +89,16 @@ repos:
language: node
entry: eslint
files: ^(platform/web/js/|modules/|misc/dist/html/).*\.(js|html)$
args:
- --fix
- --no-warn-ignored
- --no-config-lookup
- --config
- platform/web/eslint.config.cjs
args: [--fix, --no-warn-ignored, --no-config-lookup, --config, platform/web/eslint.config.cjs]
additional_dependencies:
- '@eslint/js@^9.3.0'
- '@html-eslint/eslint-plugin@^0.24.1'
- '@html-eslint/parser@^0.24.1'
- '@stylistic/eslint-plugin@^2.1.0'
- eslint@^9.3.0
- eslint-plugin-html@^8.1.1
- globals@^15.3.0
- espree@^10.0.1
- 'eslint@^9.3.0'
- 'eslint-plugin-html@^8.1.1'
- 'globals@^15.3.0'
- 'espree@^10.0.1'
- id: jsdoc
name: jsdoc
@ -128,7 +116,7 @@ repos:
- -d
- dry-run
pass_filenames: false
additional_dependencies: [jsdoc@^4.0.3]
additional_dependencies: ['jsdoc@^4.0.3']
- id: svgo
name: svgo
@ -136,7 +124,7 @@ repos:
entry: svgo
files: \.svg$
args: [--quiet, --config, misc/utility/svgo.config.mjs]
additional_dependencies: [svgo@3.3.2]
additional_dependencies: ["svgo@3.3.2"]
- id: copyright-headers
name: copyright-headers
@ -147,7 +135,6 @@ repos:
(?x)^(
core/math/bvh_.*\.inc$|
platform/(?!android|ios|linuxbsd|macos|web|windows)\w+/.*|
platform/android/java/editor/src/main/java/com/android/.*|
platform/android/java/lib/src/com/.*|
platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView\.java$|
platform/android/java/lib/src/org/godotengine/godot/gl/EGLLogWrapper\.java$|
@ -175,7 +162,6 @@ repos:
modules/gdscript/tests/scripts/parser/features/mixed_indentation_on_blank_lines\.gd$|
modules/gdscript/tests/scripts/parser/warnings/empty_file_newline_comment\.notest\.gd$|
modules/gdscript/tests/scripts/parser/warnings/empty_file_newline\.notest\.gd$|
platform/android/java/editor/src/main/java/com/android/.*|
platform/android/java/lib/src/com/google/.*
)
@ -184,7 +170,7 @@ repos:
language: python
entry: python misc/scripts/dotnet_format.py
types_or: [c#]
#
# End of upstream Godot pre-commit hooks.
#
# Keep this separation to let downstream forks add their own hooks to this file,

View File

@ -63,44 +63,6 @@ Copyright: 2011, Ole Kniemeyer, MAXON, www.maxon.net
2007-2014, Juan Linietsky, Ariel Manzur
License: Expat and Zlib
Files: ./modules/godot_physics_2d/godot_joints_2d.cpp
Comment: Chipmunk2D Joint Constraints
Copyright: 2007, Scott Lembcke
License: Expat
Files: ./modules/godot_physics_3d/gjk_epa.cpp
./modules/godot_physics_3d/joints/godot_generic_6dof_joint_3d.cpp
./modules/godot_physics_3d/joints/godot_generic_6dof_joint_3d.h
./modules/godot_physics_3d/joints/godot_hinge_joint_3d.cpp
./modules/godot_physics_3d/joints/godot_hinge_joint_3d_sw.h
./modules/godot_physics_3d/joints/godot_jacobian_entry_3d_sw.h
./modules/godot_physics_3d/joints/godot_pin_joint_3d.cpp
./modules/godot_physics_3d/joints/godot_pin_joint_3d.h
./modules/godot_physics_3d/joints/godot_slider_joint_3d.cpp
./modules/godot_physics_3d/joints/godot_slider_joint_3d.h
./modules/godot_physics_3d/godot_soft_body_3d.cpp
./modules/godot_physics_3d/godot_soft_body_3d.h
./modules/godot_physics_3d/godot_shape_3d.cpp
./modules/godot_physics_3d/godot_shape_3d.h
Comment: Bullet Continuous Collision Detection and Physics Library
Copyright: 2003-2008, Erwin Coumans
2014-present, Godot Engine contributors
2007-2014, Juan Linietsky, Ariel Manzur
License: Expat and Zlib
Files: ./modules/godot_physics_3d/godot_collision_solver_3d_sat.cpp
Comment: Open Dynamics Engine
Copyright: 2001-2003, Russell L. Smith, Alen Ladavac, Nguyen Binh
License: BSD-3-clause
Files: ./modules/godot_physics_3d/joints/godot_cone_twist_joint_3d.cpp
./modules/godot_physics_3d/joints/godot_cone_twist_joint_3d.h
Comment: Bullet Continuous Collision Detection and Physics Library
Copyright: 2007, Starbreeze Studios
2014-present, Godot Engine contributors
2007-2014, Juan Linietsky, Ariel Manzur
License: Expat and Zlib
Files: ./modules/lightmapper_rd/lm_compute.glsl
Comment: Joint Non-Local Means (JNLM) denoiser
Copyright: 2020, Manuel Prandini
@ -108,8 +70,7 @@ Copyright: 2020, Manuel Prandini
2007-2014, Juan Linietsky, Ariel Manzur
License: Expat
Files: ./platform/android/java/editor/src/main/java/com/android/*
./platform/android/java/lib/aidl/com/android/*
Files: ./platform/android/java/lib/aidl/com/android/*
./platform/android/java/lib/res/layout/status_bar_ongoing_event_progress_bar.xml
./platform/android/java/lib/src/com/google/android/*
./platform/android/java/lib/src/org/godotengine/godot/input/InputManagerCompat.java
@ -131,6 +92,44 @@ Copyright: 2001, Robert Penner
2007-2014, Juan Linietsky, Ariel Manzur
License: Expat
Files: ./servers/physics_2d/godot_joints_2d.cpp
Comment: Chipmunk2D Joint Constraints
Copyright: 2007, Scott Lembcke
License: Expat
Files: ./servers/physics_3d/collision_solver_3d_sat.cpp
Comment: Open Dynamics Engine
Copyright: 2001-2003, Russell L. Smith, Alen Ladavac, Nguyen Binh
License: BSD-3-clause
Files: ./servers/physics_3d/gjk_epa.cpp
./servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp
./servers/physics_3d/joints/generic_6dof_joint_3d_sw.h
./servers/physics_3d/joints/hinge_joint_3d_sw.cpp
./servers/physics_3d/joints/hinge_joint_3d_sw.h
./servers/physics_3d/joints/jacobian_entry_3d_sw.h
./servers/physics_3d/joints/pin_joint_3d_sw.cpp
./servers/physics_3d/joints/pin_joint_3d_sw.h
./servers/physics_3d/joints/slider_joint_3d_sw.cpp
./servers/physics_3d/joints/slider_joint_3d_sw.h
./servers/physics_3d/soft_body_3d_sw.cpp
./servers/physics_3d/soft_body_3d_sw.h
./servers/physics_3d/shape_3d_sw.cpp
./servers/physics_3d/shape_3d_sw.h
Comment: Bullet Continuous Collision Detection and Physics Library
Copyright: 2003-2008, Erwin Coumans
2014-present, Godot Engine contributors
2007-2014, Juan Linietsky, Ariel Manzur
License: Expat and Zlib
Files: ./servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp
./servers/physics_3d/joints/cone_twist_joint_3d_sw.h
Comment: Bullet Continuous Collision Detection and Physics Library
Copyright: 2007, Starbreeze Studios
2014-present, Godot Engine contributors
2007-2014, Juan Linietsky, Ariel Manzur
License: Expat and Zlib
Files: ./servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl
./servers/rendering/renderer_rd/shaders/ssao_blur.glsl
./servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl
@ -476,11 +475,6 @@ Comment: RVO2
Copyright: 2016, University of North Carolina at Chapel Hill
License: Apache-2.0
Files: ./thirdparty/spirv-cross/
Comment: SPIRV-Cross
Copyright: 2015-2021, Arm Limited
License: Apache-2.0 or Expat
Files: ./thirdparty/spirv-reflect/
Comment: SPIRV-Reflect
Copyright: 2017-2022, Google Inc.

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
EnsureSConsVersion(3, 1, 2)
EnsurePythonVersion(3, 6)
@ -219,11 +218,10 @@ opts.Add(BoolVariable("deprecated", "Enable compatibility code for deprecated an
opts.Add(EnumVariable("precision", "Set the floating-point precision level", "single", ("single", "double")))
opts.Add(BoolVariable("minizip", "Enable ZIP archive support using minizip", True))
opts.Add(BoolVariable("brotli", "Enable Brotli for decompresson and WOFF2 fonts support", True))
opts.Add(BoolVariable("xaudio2", "Enable the XAudio2 audio driver on supported platforms", False))
opts.Add(BoolVariable("xaudio2", "Enable the XAudio2 audio driver", False))
opts.Add(BoolVariable("vulkan", "Enable the vulkan rendering driver", True))
opts.Add(BoolVariable("opengl3", "Enable the OpenGL/GLES3 rendering driver", True))
opts.Add(BoolVariable("d3d12", "Enable the Direct3D 12 rendering driver on supported platforms", False))
opts.Add(BoolVariable("metal", "Enable the Metal rendering driver on supported platforms (Apple arm64 only)", False))
opts.Add(BoolVariable("d3d12", "Enable the Direct3D 12 rendering driver", False))
opts.Add(BoolVariable("openxr", "Enable the OpenXR driver", True))
opts.Add(BoolVariable("use_volk", "Use the volk library to load the Vulkan loader dynamically", True))
opts.Add(BoolVariable("disable_exceptions", "Force disabling exception handling code", True))
@ -231,22 +229,11 @@ opts.Add("custom_modules", "A list of comma-separated directory paths containing
opts.Add(BoolVariable("custom_modules_recursive", "Detect custom modules recursively for each specified path.", True))
# Advanced options
opts.Add(
BoolVariable(
"dev_mode", "Alias for dev options: verbose=yes warnings=extra werror=yes tests=yes strict_checks=yes", False
)
)
opts.Add(BoolVariable("dev_mode", "Alias for dev options: verbose=yes warnings=extra werror=yes tests=yes", False))
opts.Add(BoolVariable("tests", "Build the unit tests", False))
opts.Add(BoolVariable("fast_unsafe", "Enable unsafe options for faster rebuilds", False))
opts.Add(BoolVariable("ninja", "Use the ninja backend for faster rebuilds", False))
opts.Add(BoolVariable("ninja_auto_run", "Run ninja automatically after generating the ninja file", True))
opts.Add("ninja_file", "Path to the generated ninja file", "build.ninja")
opts.Add(BoolVariable("compiledb", "Generate compilation DB (`compile_commands.json`) for external tools", False))
opts.Add(
"num_jobs",
"Use up to N jobs when compiling (equivalent to `-j N`). Defaults to max jobs - 1. Ignored if -j is used.",
"",
)
opts.Add(BoolVariable("verbose", "Enable verbose output for the compilation", False))
opts.Add(BoolVariable("progress", "Show a progress indicator during compilation", True))
opts.Add(EnumVariable("warnings", "Level of compilation warnings", "all", ("extra", "all", "moderate", "no")))
@ -267,7 +254,6 @@ opts.Add(
"",
)
opts.Add(BoolVariable("use_precise_math_checks", "Math checks use very precise epsilon (debug option)", False))
opts.Add(BoolVariable("strict_checks", "Enforce stricter checks (debug option)", False))
opts.Add(BoolVariable("scu_build", "Use single compilation unit build", False))
opts.Add("scu_limit", "Max includes per SCU file when using scu_build (determines RAM use)", "0")
opts.Add(BoolVariable("engine_update_check", "Enable engine update checks in the Project Manager", True))
@ -299,6 +285,7 @@ opts.Add(BoolVariable("builtin_pcre2_with_jit", "Use JIT compiler for the built-
opts.Add(BoolVariable("builtin_recastnavigation", "Use the built-in Recast navigation library", True))
opts.Add(BoolVariable("builtin_rvo2_2d", "Use the built-in RVO2 2D library", True))
opts.Add(BoolVariable("builtin_rvo2_3d", "Use the built-in RVO2 3D library", True))
opts.Add(BoolVariable("builtin_squish", "Use the built-in squish library", True))
opts.Add(BoolVariable("builtin_xatlas", "Use the built-in xatlas library", True))
opts.Add(BoolVariable("builtin_zlib", "Use the built-in zlib library", True))
opts.Add(BoolVariable("builtin_zstd", "Use the built-in Zstd library", True))
@ -550,22 +537,16 @@ initial_num_jobs = env.GetOption("num_jobs")
altered_num_jobs = initial_num_jobs + 1
env.SetOption("num_jobs", altered_num_jobs)
if env.GetOption("num_jobs") == altered_num_jobs:
num_jobs = env.get("num_jobs", "")
if str(num_jobs).isdigit() and int(num_jobs) > 0:
env.SetOption("num_jobs", num_jobs)
cpu_count = os.cpu_count()
if cpu_count is None:
print_warning("Couldn't auto-detect CPU count to configure build parallelism. Specify it with the -j argument.")
else:
cpu_count = os.cpu_count()
if cpu_count is None:
print_warning(
"Couldn't auto-detect CPU count to configure build parallelism. Specify it with the `-j` or `num_jobs` arguments."
)
else:
safer_cpu_count = cpu_count if cpu_count <= 4 else cpu_count - 1
print(
"Auto-detected %d CPU cores available for build parallelism. Using %d cores by default. You can override it with the `-j` or `num_jobs` arguments."
% (cpu_count, safer_cpu_count)
)
env.SetOption("num_jobs", safer_cpu_count)
safer_cpu_count = cpu_count if cpu_count <= 4 else cpu_count - 1
print(
"Auto-detected %d CPU cores available for build parallelism. Using %d cores by default. You can override it with the -j argument."
% (cpu_count, safer_cpu_count)
)
env.SetOption("num_jobs", safer_cpu_count)
env.extra_suffix = ""
@ -607,16 +588,12 @@ if env["dev_mode"]:
env["warnings"] = ARGUMENTS.get("warnings", "extra")
env["werror"] = methods.get_cmdline_bool("werror", True)
env["tests"] = methods.get_cmdline_bool("tests", True)
env["strict_checks"] = methods.get_cmdline_bool("strict_checks", True)
if env["production"]:
env["use_static_cpp"] = methods.get_cmdline_bool("use_static_cpp", True)
env["debug_symbols"] = methods.get_cmdline_bool("debug_symbols", False)
# LTO "auto" means we handle the preferred option in each platform detect.py.
env["lto"] = ARGUMENTS.get("lto", "auto")
if env["strict_checks"]:
env.Append(CPPDEFINES=["STRICT_CHECKS"])
# Run SCU file generation script if in a SCU build.
if env["scu_build"]:
max_includes_per_scu = 8
@ -639,18 +616,25 @@ if env.dev_build:
print("NOTE: Developer build, with debug optimization level and debug symbols (unless overridden).")
# Enforce our minimal compiler version requirements
cc_version = methods.get_compiler_version(env)
cc_version_major = cc_version["major"]
cc_version_minor = cc_version["minor"]
cc_version_metadata1 = cc_version["metadata1"]
cc_version = methods.get_compiler_version(env) or {
"major": None,
"minor": None,
"patch": None,
"metadata1": None,
"metadata2": None,
"date": None,
}
cc_version_major = int(cc_version["major"] or -1)
cc_version_minor = int(cc_version["minor"] or -1)
cc_version_metadata1 = cc_version["metadata1"] or ""
if cc_version_major == -1:
print_warning(
"Couldn't detect compiler version, skipping version checks. "
"Build may fail if the compiler doesn't support C++17 fully."
)
elif methods.using_gcc(env):
if cc_version_major < 9:
if methods.using_gcc(env):
if cc_version_major == -1:
print_warning(
"Couldn't detect compiler version, skipping version checks. "
"Build may fail if the compiler doesn't support C++17 fully."
)
elif cc_version_major < 9:
print_error(
"Detected GCC version older than 9, which does not fully support "
"C++17, or has bugs when compiling Godot. Supported versions are 9 "
@ -670,12 +654,17 @@ elif methods.using_gcc(env):
print_warning("GCC < 8 doesn't support -ffile-prefix-map, disabling `debug_paths_relative` option.")
env["debug_paths_relative"] = False
elif methods.using_clang(env):
if cc_version_major == -1:
print_warning(
"Couldn't detect compiler version, skipping version checks. "
"Build may fail if the compiler doesn't support C++17 fully."
)
# Apple LLVM versions differ from upstream LLVM version \o/, compare
# in https://en.wikipedia.org/wiki/Xcode#Toolchain_versions
if env["platform"] == "macos" or env["platform"] == "ios":
elif env["platform"] == "macos" or env["platform"] == "ios":
vanilla = methods.is_vanilla_clang(env)
if vanilla and cc_version_major < 6:
print_error(
print_warning(
"Detected Clang version older than 6, which does not fully support "
"C++17. Supported versions are Clang 6 and later."
)
@ -700,28 +689,6 @@ elif methods.using_clang(env):
if env["debug_paths_relative"] and cc_version_major < 10:
print_warning("Clang < 10 doesn't support -ffile-prefix-map, disabling `debug_paths_relative` option.")
env["debug_paths_relative"] = False
elif env.msvc:
# Ensure latest minor builds of Visual Studio 2017/2019.
# https://github.com/godotengine/godot/pull/94995#issuecomment-2336464574
if cc_version_major == 16 and cc_version_minor < 11:
print_error(
"Detected Visual Studio 2019 version older than 16.11, which has bugs "
"when compiling Godot. Use a newer VS2019 version, or VS2022."
)
Exit(255)
if cc_version_major == 15 and cc_version_minor < 9:
print_error(
"Detected Visual Studio 2017 version older than 15.9, which has bugs "
"when compiling Godot. Use a newer VS2017 version, or VS2019/VS2022."
)
Exit(255)
if cc_version_major < 15:
print_error(
"Detected Visual Studio 2015 or earlier, which is unsupported in Godot. "
"Supported versions are Visual Studio 2017 and later."
)
Exit(255)
# Set optimize and debug_symbols flags.
# "custom" means do nothing and let users set their own optimization flags.
@ -799,23 +766,13 @@ if env["lto"] != "none":
# This needs to come after `configure`, otherwise we don't have env.msvc.
if not env.msvc:
# Specifying GNU extensions support explicitly, which are supported by
# both GCC and Clang. Both currently default to gnu11 and gnu++17.
# both GCC and Clang. Both currently default to gnu11 and gnu++14.
env.Prepend(CFLAGS=["-std=gnu11"])
env.Prepend(CXXFLAGS=["-std=gnu++17"])
else:
# MSVC started offering C standard support with Visual Studio 2019 16.8, which covers all
# of our supported VS2019 & VS2022 versions; VS2017 will only pass the C++ standard.
env.Prepend(CXXFLAGS=["/std:c++17"])
if cc_version_major < 16:
print_warning("Visual Studio 2017 cannot specify a C-Standard.")
else:
env.Prepend(CFLAGS=["/std:c11"])
# MSVC is non-conforming with the C++ standard by default, so we enable more conformance.
# Note that this is still not complete conformance, as certain Windows-related headers
# don't compile under complete conformance.
env.Prepend(CCFLAGS=["/permissive-"])
# Allow use of `__cplusplus` macro to determine C++ standard universally.
env.Prepend(CXXFLAGS=["/Zc:__cplusplus"])
# MSVC doesn't have clear C standard support, /std only covers C++.
# We apply it to CCFLAGS (both C and C++ code) in case it impacts C features.
env.Prepend(CCFLAGS=["/std:c++17"])
# Disable exception handling. Godot doesn't use exceptions anywhere, and this
# saves around 20% of binary size and very significant build time (GH-80513).
@ -828,7 +785,7 @@ elif env.msvc:
env.Append(CXXFLAGS=["/EHsc"])
# Configure compiler warnings
if env.msvc and not methods.using_clang(env): # MSVC
if env.msvc: # MSVC
if env["warnings"] == "no":
env.Append(CCFLAGS=["/w"])
else:
@ -878,11 +835,8 @@ else: # GCC, Clang
# for putting them in `Set` or `Map`. We don't mind about unreliable ordering.
common_warnings += ["-Wno-ordered-compare-function-pointers"]
# clang-cl will interpret `-Wall` as `-Weverything`, workaround with compatibility cast
W_ALL = "-Wall" if not env.msvc else "-W3"
if env["warnings"] == "extra":
env.Append(CCFLAGS=[W_ALL, "-Wextra", "-Wwrite-strings", "-Wno-unused-parameter"] + common_warnings)
env.Append(CCFLAGS=["-Wall", "-Wextra", "-Wwrite-strings", "-Wno-unused-parameter"] + common_warnings)
env.Append(CXXFLAGS=["-Wctor-dtor-privacy", "-Wnon-virtual-dtor"])
if methods.using_gcc(env):
env.Append(
@ -904,9 +858,9 @@ else: # GCC, Clang
elif methods.using_clang(env) or methods.using_emcc(env):
env.Append(CCFLAGS=["-Wimplicit-fallthrough"])
elif env["warnings"] == "all":
env.Append(CCFLAGS=[W_ALL] + common_warnings)
env.Append(CCFLAGS=["-Wall"] + common_warnings)
elif env["warnings"] == "moderate":
env.Append(CCFLAGS=[W_ALL, "-Wno-unused"] + common_warnings)
env.Append(CCFLAGS=["-Wall", "-Wno-unused"] + common_warnings)
else: # 'no'
env.Append(CCFLAGS=["-w"])
@ -1060,9 +1014,7 @@ if env["vsproj"]:
if env["compiledb"]:
if env.scons_version < (4, 0, 0):
# Generating the compilation DB (`compile_commands.json`) requires SCons 4.0.0 or later.
print_error(
"The `compiledb=yes` option requires SCons 4.0 or later, but your version is %s." % scons_raw_version
)
print_error("The `compiledb=yes` option requires SCons 4.0 or later, but your version is %s." % scons_raw_version)
Exit(255)
env.Tool("compilation_db")
@ -1074,9 +1026,12 @@ if env["ninja"]:
Exit(255)
SetOption("experimental", "ninja")
env["NINJA_FILE_NAME"] = env["ninja_file"]
env["NINJA_DISABLE_AUTO_RUN"] = not env["ninja_auto_run"]
env.Tool("ninja", "build.ninja")
env.Tool("ninja")
# By setting this we allow the user to run ninja by themselves with all
# the flags they need, as apparently automatically running from scons
# is way slower.
SetOption("disable_execute_ninja", True)
# Threads
if env["threads"]:
@ -1138,7 +1093,7 @@ atexit.register(print_elapsed_time)
def purge_flaky_files():
paths_to_keep = ["build.ninja"]
paths_to_keep = ["ninja.build"]
for build_failure in GetBuildFailures():
path = build_failure.node.path
if os.path.isfile(path) and path not in paths_to_keep:

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")

View File

@ -263,18 +263,6 @@ bool Engine::is_generate_spirv_debug_info_enabled() const {
return generate_spirv_debug_info;
}
bool Engine::is_extra_gpu_memory_tracking_enabled() const {
return extra_gpu_memory_tracking;
}
void Engine::set_print_to_stdout(bool p_enabled) {
CoreGlobals::print_line_enabled = p_enabled;
}
bool Engine::is_printing_to_stdout() const {
return CoreGlobals::print_line_enabled;
}
void Engine::set_print_error_messages(bool p_enabled) {
CoreGlobals::print_error_enabled = p_enabled;
}

View File

@ -72,7 +72,6 @@ private:
bool abort_on_gpu_errors = false;
bool use_validation_layers = false;
bool generate_spirv_debug_info = false;
bool extra_gpu_memory_tracking = false;
int32_t gpu_idx = -1;
uint64_t _process_frames = 0;
@ -128,9 +127,6 @@ public:
void set_time_scale(double p_scale);
double get_time_scale() const;
void set_print_to_stdout(bool p_enabled);
bool is_printing_to_stdout() const;
void set_print_error_messages(bool p_enabled);
bool is_printing_error_messages() const;
void print_header(const String &p_string) const;
@ -185,7 +181,6 @@ public:
bool is_abort_on_gpu_errors_enabled() const;
bool is_validation_layers_enabled() const;
bool is_generate_spirv_debug_info_enabled() const;
bool is_extra_gpu_memory_tracking_enabled() const;
int32_t get_gpu_index() const;
void increment_frames_drawn();

View File

@ -1016,7 +1016,7 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust
}
}
// Check for the existence of a csproj file.
if (_csproj_exists(get_resource_path())) {
if (_csproj_exists(p_path.get_base_dir())) {
// If there is a csproj file, add the C# feature if it doesn't already exist.
if (!project_features.has("C#")) {
project_features.append("C#");
@ -1472,6 +1472,10 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF(PropertyInfo(Variant::INT, "display/window/size/window_height_override", PROPERTY_HINT_RANGE, "0,4320,1,or_greater"), 0); // 8K resolution
GLOBAL_DEF("display/window/energy_saving/keep_screen_on", true);
#ifdef TOOLS_ENABLED
GLOBAL_DEF("display/window/energy_saving/keep_screen_on.editor_hint", false);
#endif
GLOBAL_DEF("animation/warnings/check_invalid_track_paths", true);
GLOBAL_DEF("animation/warnings/check_angle_interpolation_type_conflicting", true);
@ -1557,11 +1561,6 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("collada/use_ambient", false);
// Input settings
GLOBAL_DEF_BASIC("input_devices/pointing/android/enable_long_press_as_right_click", false);
GLOBAL_DEF_BASIC("input_devices/pointing/android/enable_pan_and_scale_gestures", false);
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "input_devices/pointing/android/rotary_input_scroll_axis", PROPERTY_HINT_ENUM, "Horizontal,Vertical"), 1);
// These properties will not show up in the dialog. If you want to exclude whole groups, use add_hidden_prefix().
GLOBAL_DEF_INTERNAL("application/config/features", PackedStringArray());
GLOBAL_DEF_INTERNAL("internationalization/locale/translation_remaps", PackedStringArray());
@ -1574,7 +1573,6 @@ ProjectSettings::ProjectSettings() {
ProjectSettings::ProjectSettings(const String &p_path) {
if (load_custom(p_path) == OK) {
resource_path = p_path.get_base_dir();
project_loaded = true;
}
}

View File

@ -29,7 +29,6 @@
/**************************************************************************/
#include "core_bind.h"
#include "core_bind.compat.inc"
#include "core/config/project_settings.h"
#include "core/crypto/crypto_core.h"
@ -57,11 +56,8 @@ Error ResourceLoader::load_threaded_request(const String &p_path, const String &
ResourceLoader::ThreadLoadStatus ResourceLoader::load_threaded_get_status(const String &p_path, Array r_progress) {
float progress = 0;
::ResourceLoader::ThreadLoadStatus tls = ::ResourceLoader::load_threaded_get_status(p_path, &progress);
// Default array should never be modified, it causes the hash of the method to change.
if (!ClassDB::is_default_array_arg(r_progress)) {
r_progress.resize(1);
r_progress[0] = progress;
}
r_progress.resize(1);
r_progress[0] = progress;
return (ThreadLoadStatus)tls;
}
@ -119,11 +115,6 @@ bool ResourceLoader::has_cached(const String &p_path) {
return ResourceCache::has(local_path);
}
Ref<Resource> ResourceLoader::get_cached_ref(const String &p_path) {
String local_path = ProjectSettings::get_singleton()->localize_path(p_path);
return ResourceCache::get_ref(local_path);
}
bool ResourceLoader::exists(const String &p_path, const String &p_type_hint) {
return ::ResourceLoader::exists(p_path, p_type_hint);
}
@ -134,7 +125,7 @@ ResourceUID::ID ResourceLoader::get_resource_uid(const String &p_path) {
void ResourceLoader::_bind_methods() {
ClassDB::bind_method(D_METHOD("load_threaded_request", "path", "type_hint", "use_sub_threads", "cache_mode"), &ResourceLoader::load_threaded_request, DEFVAL(""), DEFVAL(false), DEFVAL(CACHE_MODE_REUSE));
ClassDB::bind_method(D_METHOD("load_threaded_get_status", "path", "progress"), &ResourceLoader::load_threaded_get_status, DEFVAL_ARRAY);
ClassDB::bind_method(D_METHOD("load_threaded_get_status", "path", "progress"), &ResourceLoader::load_threaded_get_status, DEFVAL(Array()));
ClassDB::bind_method(D_METHOD("load_threaded_get", "path"), &ResourceLoader::load_threaded_get);
ClassDB::bind_method(D_METHOD("load", "path", "type_hint", "cache_mode"), &ResourceLoader::load, DEFVAL(""), DEFVAL(CACHE_MODE_REUSE));
@ -144,7 +135,6 @@ void ResourceLoader::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_abort_on_missing_resources", "abort"), &ResourceLoader::set_abort_on_missing_resources);
ClassDB::bind_method(D_METHOD("get_dependencies", "path"), &ResourceLoader::get_dependencies);
ClassDB::bind_method(D_METHOD("has_cached", "path"), &ResourceLoader::has_cached);
ClassDB::bind_method(D_METHOD("get_cached_ref", "path"), &ResourceLoader::get_cached_ref);
ClassDB::bind_method(D_METHOD("exists", "path", "type_hint"), &ResourceLoader::exists, DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_resource_uid", "path"), &ResourceLoader::get_resource_uid);
@ -184,10 +174,6 @@ void ResourceSaver::remove_resource_format_saver(Ref<ResourceFormatSaver> p_form
::ResourceSaver::remove_resource_format_saver(p_format_saver);
}
ResourceUID::ID ResourceSaver::get_resource_id_for_path(const String &p_path, bool p_generate) {
return ::ResourceSaver::get_resource_id_for_path(p_path, p_generate);
}
ResourceSaver *ResourceSaver::singleton = nullptr;
void ResourceSaver::_bind_methods() {
@ -195,7 +181,6 @@ void ResourceSaver::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_recognized_extensions", "type"), &ResourceSaver::get_recognized_extensions);
ClassDB::bind_method(D_METHOD("add_resource_format_saver", "format_saver", "at_front"), &ResourceSaver::add_resource_format_saver, DEFVAL(false));
ClassDB::bind_method(D_METHOD("remove_resource_format_saver", "format_saver"), &ResourceSaver::remove_resource_format_saver);
ClassDB::bind_method(D_METHOD("get_resource_id_for_path", "path", "generate"), &ResourceSaver::get_resource_id_for_path, DEFVAL(false));
BIND_BITFIELD_FLAG(FLAG_NONE);
BIND_BITFIELD_FLAG(FLAG_RELATIVE_PATHS);
@ -315,22 +300,19 @@ int OS::execute(const String &p_path, const Vector<String> &p_arguments, Array r
String pipe;
int exitcode = 0;
Error err = ::OS::get_singleton()->execute(p_path, args, &pipe, &exitcode, p_read_stderr, nullptr, p_open_console);
// Default array should never be modified, it causes the hash of the method to change.
if (!ClassDB::is_default_array_arg(r_output)) {
r_output.push_back(pipe);
}
r_output.push_back(pipe);
if (err != OK) {
return -1;
}
return exitcode;
}
Dictionary OS::execute_with_pipe(const String &p_path, const Vector<String> &p_arguments, bool p_blocking) {
Dictionary OS::execute_with_pipe(const String &p_path, const Vector<String> &p_arguments) {
List<String> args;
for (const String &arg : p_arguments) {
args.push_back(arg);
}
return ::OS::get_singleton()->execute_with_pipe(p_path, args, p_blocking);
return ::OS::get_singleton()->execute_with_pipe(p_path, args);
}
int OS::create_instance(const Vector<String> &p_arguments) {
@ -629,8 +611,8 @@ void OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_system_font_path_for_text", "font_name", "text", "locale", "script", "weight", "stretch", "italic"), &OS::get_system_font_path_for_text, DEFVAL(String()), DEFVAL(String()), DEFVAL(400), DEFVAL(100), DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_executable_path"), &OS::get_executable_path);
ClassDB::bind_method(D_METHOD("read_string_from_stdin"), &OS::read_string_from_stdin);
ClassDB::bind_method(D_METHOD("execute", "path", "arguments", "output", "read_stderr", "open_console"), &OS::execute, DEFVAL_ARRAY, DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("execute_with_pipe", "path", "arguments", "blocking"), &OS::execute_with_pipe, DEFVAL(true));
ClassDB::bind_method(D_METHOD("execute", "path", "arguments", "output", "read_stderr", "open_console"), &OS::execute, DEFVAL(Array()), DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("execute_with_pipe", "path", "arguments"), &OS::execute_with_pipe);
ClassDB::bind_method(D_METHOD("create_process", "path", "arguments", "open_console"), &OS::create_process, DEFVAL(false));
ClassDB::bind_method(D_METHOD("create_instance", "arguments"), &OS::create_instance);
ClassDB::bind_method(D_METHOD("kill", "pid"), &OS::kill);
@ -710,7 +692,6 @@ void OS::_bind_methods() {
BIND_ENUM_CONSTANT(RENDERING_DRIVER_VULKAN);
BIND_ENUM_CONSTANT(RENDERING_DRIVER_OPENGL3);
BIND_ENUM_CONSTANT(RENDERING_DRIVER_D3D12);
BIND_ENUM_CONSTANT(RENDERING_DRIVER_METAL);
BIND_ENUM_CONSTANT(SYSTEM_DIR_DESKTOP);
BIND_ENUM_CONSTANT(SYSTEM_DIR_DCIM);
@ -1228,15 +1209,14 @@ bool Semaphore::try_wait() {
return semaphore.try_wait();
}
void Semaphore::post(int p_count) {
ERR_FAIL_COND(p_count <= 0);
semaphore.post(p_count);
void Semaphore::post() {
semaphore.post();
}
void Semaphore::_bind_methods() {
ClassDB::bind_method(D_METHOD("wait"), &Semaphore::wait);
ClassDB::bind_method(D_METHOD("try_wait"), &Semaphore::try_wait);
ClassDB::bind_method(D_METHOD("post", "count"), &Semaphore::post, DEFVAL(1));
ClassDB::bind_method(D_METHOD("post"), &Semaphore::post);
}
////// Mutex //////
@ -1424,11 +1404,6 @@ Variant ClassDB::instantiate(const StringName &p_class) const {
}
}
ClassDB::APIType ClassDB::class_get_api_type(const StringName &p_class) const {
::ClassDB::APIType api_type = ::ClassDB::get_api_type(p_class);
return (APIType)api_type;
}
bool ClassDB::class_has_signal(const StringName &p_class, const StringName &p_signal) const {
return ::ClassDB::has_signal(p_class, p_signal);
}
@ -1465,14 +1440,6 @@ TypedArray<Dictionary> ClassDB::class_get_property_list(const StringName &p_clas
return ret;
}
StringName ClassDB::class_get_property_getter(const StringName &p_class, const StringName &p_property) {
return ::ClassDB::get_property_getter(p_class, p_property);
}
StringName ClassDB::class_get_property_setter(const StringName &p_class, const StringName &p_property) {
return ::ClassDB::get_property_setter(p_class, p_property);
}
Variant ClassDB::class_get_property(Object *p_object, const StringName &p_property) const {
Variant ret;
::ClassDB::get_property(p_object, p_property, ret);
@ -1525,23 +1492,6 @@ TypedArray<Dictionary> ClassDB::class_get_method_list(const StringName &p_class,
return ret;
}
Variant ClassDB::class_call_static_method(const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) {
if (p_argcount < 2) {
r_call_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
return Variant::NIL;
}
if (!p_arguments[0]->is_string() || !p_arguments[1]->is_string()) {
r_call_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
return Variant::NIL;
}
StringName class_ = *p_arguments[0];
StringName method = *p_arguments[1];
const MethodBind *bind = ::ClassDB::get_method(class_, method);
ERR_FAIL_NULL_V_MSG(bind, Variant::NIL, "Cannot find static method.");
ERR_FAIL_COND_V_MSG(!bind->is_static(), Variant::NIL, "Method is not static.");
return bind->call(nullptr, p_arguments + 2, p_argcount - 2, r_call_error);
}
PackedStringArray ClassDB::class_get_integer_constant_list(const StringName &p_class, bool p_no_inheritance) const {
List<String> constants;
::ClassDB::get_integer_constant_list(p_class, &constants, p_no_inheritance);
@ -1625,7 +1575,7 @@ void ClassDB::get_argument_options(const StringName &p_function, int p_idx, List
pf == "class_has_method" || pf == "class_get_method_list" ||
pf == "class_get_integer_constant_list" || pf == "class_has_integer_constant" || pf == "class_get_integer_constant" ||
pf == "class_has_enum" || pf == "class_get_enum_list" || pf == "class_get_enum_constants" || pf == "class_get_integer_constant_enum" ||
pf == "is_class_enabled" || pf == "is_class_enum_bitfield" || pf == "class_get_api_type");
pf == "is_class_enabled" || pf == "is_class_enum_bitfield");
}
if (first_argument_is_class || pf == "is_parent_class") {
for (const String &E : get_class_list()) {
@ -1646,15 +1596,11 @@ void ClassDB::_bind_methods() {
::ClassDB::bind_method(D_METHOD("can_instantiate", "class"), &ClassDB::can_instantiate);
::ClassDB::bind_method(D_METHOD("instantiate", "class"), &ClassDB::instantiate);
::ClassDB::bind_method(D_METHOD("class_get_api_type", "class"), &ClassDB::class_get_api_type);
::ClassDB::bind_method(D_METHOD("class_has_signal", "class", "signal"), &ClassDB::class_has_signal);
::ClassDB::bind_method(D_METHOD("class_get_signal", "class", "signal"), &ClassDB::class_get_signal);
::ClassDB::bind_method(D_METHOD("class_get_signal_list", "class", "no_inheritance"), &ClassDB::class_get_signal_list, DEFVAL(false));
::ClassDB::bind_method(D_METHOD("class_get_property_list", "class", "no_inheritance"), &ClassDB::class_get_property_list, DEFVAL(false));
::ClassDB::bind_method(D_METHOD("class_get_property_getter", "class", "property"), &ClassDB::class_get_property_getter);
::ClassDB::bind_method(D_METHOD("class_get_property_setter", "class", "property"), &ClassDB::class_get_property_setter);
::ClassDB::bind_method(D_METHOD("class_get_property", "object", "property"), &ClassDB::class_get_property);
::ClassDB::bind_method(D_METHOD("class_set_property", "object", "property", "value"), &ClassDB::class_set_property);
@ -1666,8 +1612,6 @@ void ClassDB::_bind_methods() {
::ClassDB::bind_method(D_METHOD("class_get_method_list", "class", "no_inheritance"), &ClassDB::class_get_method_list, DEFVAL(false));
::ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "class_call_static_method", &ClassDB::class_call_static_method, MethodInfo("class_call_static_method", PropertyInfo(Variant::STRING_NAME, "class"), PropertyInfo(Variant::STRING_NAME, "method")));
::ClassDB::bind_method(D_METHOD("class_get_integer_constant_list", "class", "no_inheritance"), &ClassDB::class_get_integer_constant_list, DEFVAL(false));
::ClassDB::bind_method(D_METHOD("class_has_integer_constant", "class", "name"), &ClassDB::class_has_integer_constant);
@ -1681,12 +1625,6 @@ void ClassDB::_bind_methods() {
::ClassDB::bind_method(D_METHOD("is_class_enum_bitfield", "class", "enum", "no_inheritance"), &ClassDB::is_class_enum_bitfield, DEFVAL(false));
::ClassDB::bind_method(D_METHOD("is_class_enabled", "class"), &ClassDB::is_class_enabled);
BIND_ENUM_CONSTANT(API_CORE);
BIND_ENUM_CONSTANT(API_EDITOR);
BIND_ENUM_CONSTANT(API_EXTENSION);
BIND_ENUM_CONSTANT(API_EDITOR_EXTENSION);
BIND_ENUM_CONSTANT(API_NONE);
}
} // namespace special
@ -1800,7 +1738,7 @@ Object *Engine::get_singleton_object(const StringName &p_name) const {
void Engine::register_singleton(const StringName &p_name, Object *p_object) {
ERR_FAIL_COND_MSG(has_singleton(p_name), "Singleton already registered: " + String(p_name));
ERR_FAIL_COND_MSG(!String(p_name).is_valid_ascii_identifier(), "Singleton name is not a valid identifier: " + p_name);
ERR_FAIL_COND_MSG(!String(p_name).is_valid_identifier(), "Singleton name is not a valid identifier: " + p_name);
::Engine::Singleton s;
s.class_name = p_name;
s.name = p_name;
@ -1853,14 +1791,6 @@ String Engine::get_write_movie_path() const {
return ::Engine::get_singleton()->get_write_movie_path();
}
void Engine::set_print_to_stdout(bool p_enabled) {
::Engine::get_singleton()->set_print_to_stdout(p_enabled);
}
bool Engine::is_printing_to_stdout() const {
return ::Engine::get_singleton()->is_printing_to_stdout();
}
void Engine::set_print_error_messages(bool p_enabled) {
::Engine::get_singleton()->set_print_error_messages(p_enabled);
}
@ -1929,14 +1859,10 @@ void Engine::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_write_movie_path"), &Engine::get_write_movie_path);
ClassDB::bind_method(D_METHOD("set_print_to_stdout", "enabled"), &Engine::set_print_to_stdout);
ClassDB::bind_method(D_METHOD("is_printing_to_stdout"), &Engine::is_printing_to_stdout);
ClassDB::bind_method(D_METHOD("set_print_error_messages", "enabled"), &Engine::set_print_error_messages);
ClassDB::bind_method(D_METHOD("is_printing_error_messages"), &Engine::is_printing_error_messages);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "print_error_messages"), "set_print_error_messages", "is_printing_error_messages");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "print_to_stdout"), "set_print_to_stdout", "is_printing_to_stdout");
ADD_PROPERTY(PropertyInfo(Variant::INT, "physics_ticks_per_second"), "set_physics_ticks_per_second", "get_physics_ticks_per_second");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_physics_steps_per_frame"), "set_max_physics_steps_per_frame", "get_max_physics_steps_per_frame");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_fps"), "set_max_fps", "get_max_fps");

View File

@ -73,7 +73,7 @@ public:
static ResourceLoader *get_singleton() { return singleton; }
Error load_threaded_request(const String &p_path, const String &p_type_hint = "", bool p_use_sub_threads = false, CacheMode p_cache_mode = CACHE_MODE_REUSE);
ThreadLoadStatus load_threaded_get_status(const String &p_path, Array r_progress = ClassDB::default_array_arg);
ThreadLoadStatus load_threaded_get_status(const String &p_path, Array r_progress = Array());
Ref<Resource> load_threaded_get(const String &p_path);
Ref<Resource> load(const String &p_path, const String &p_type_hint = "", CacheMode p_cache_mode = CACHE_MODE_REUSE);
@ -83,7 +83,6 @@ public:
void set_abort_on_missing_resources(bool p_abort);
PackedStringArray get_dependencies(const String &p_path);
bool has_cached(const String &p_path);
Ref<Resource> get_cached_ref(const String &p_path);
bool exists(const String &p_path, const String &p_type_hint = "");
ResourceUID::ID get_resource_uid(const String &p_path);
@ -116,8 +115,6 @@ public:
void add_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver, bool p_at_front);
void remove_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver);
ResourceUID::ID get_resource_id_for_path(const String &p_path, bool p_generate = false);
ResourceSaver() { singleton = this; }
};
@ -130,18 +127,11 @@ protected:
static void _bind_methods();
static OS *singleton;
#ifndef DISABLE_DEPRECATED
Dictionary _execute_with_pipe_bind_compat_94434(const String &p_path, const Vector<String> &p_arguments);
static void _bind_compatibility_methods();
#endif
public:
enum RenderingDriver {
RENDERING_DRIVER_VULKAN,
RENDERING_DRIVER_OPENGL3,
RENDERING_DRIVER_D3D12,
RENDERING_DRIVER_METAL,
};
PackedByteArray get_entropy(int p_bytes);
@ -168,8 +158,8 @@ public:
Vector<String> get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale = String(), const String &p_script = String(), int p_weight = 400, int p_stretch = 100, bool p_italic = false) const;
String get_executable_path() const;
String read_string_from_stdin();
int execute(const String &p_path, const Vector<String> &p_arguments, Array r_output = ClassDB::default_array_arg, bool p_read_stderr = false, bool p_open_console = false);
Dictionary execute_with_pipe(const String &p_path, const Vector<String> &p_arguments, bool p_blocking = true);
int execute(const String &p_path, const Vector<String> &p_arguments, Array r_output = Array(), bool p_read_stderr = false, bool p_open_console = false);
Dictionary execute_with_pipe(const String &p_path, const Vector<String> &p_arguments);
int create_process(const String &p_path, const Vector<String> &p_arguments, bool p_open_console = false);
int create_instance(const Vector<String> &p_arguments);
Error kill(int p_pid);
@ -399,17 +389,12 @@ class Semaphore : public RefCounted {
GDCLASS(Semaphore, RefCounted);
::Semaphore semaphore;
protected:
static void _bind_methods();
#ifndef DISABLE_DEPRECATED
void _post_bind_compat_93605();
static void _bind_compatibility_methods();
#endif // DISABLE_DEPRECATED
public:
void wait();
bool try_wait();
void post(int p_count = 1);
void post();
};
class Thread : public RefCounted {
@ -449,14 +434,6 @@ protected:
static void _bind_methods();
public:
enum APIType {
API_CORE,
API_EDITOR,
API_EXTENSION,
API_EDITOR_EXTENSION,
API_NONE,
};
PackedStringArray get_class_list() const;
PackedStringArray get_inheriters_from_class(const StringName &p_class) const;
StringName get_parent_class(const StringName &p_class) const;
@ -465,14 +442,11 @@ public:
bool can_instantiate(const StringName &p_class) const;
Variant instantiate(const StringName &p_class) const;
APIType class_get_api_type(const StringName &p_class) const;
bool class_has_signal(const StringName &p_class, const StringName &p_signal) const;
Dictionary class_get_signal(const StringName &p_class, const StringName &p_signal) const;
TypedArray<Dictionary> class_get_signal_list(const StringName &p_class, bool p_no_inheritance = false) const;
TypedArray<Dictionary> class_get_property_list(const StringName &p_class, bool p_no_inheritance = false) const;
StringName class_get_property_getter(const StringName &p_class, const StringName &p_property);
StringName class_get_property_setter(const StringName &p_class, const StringName &p_property);
Variant class_get_property(Object *p_object, const StringName &p_property) const;
Error class_set_property(Object *p_object, const StringName &p_property, const Variant &p_value) const;
@ -483,7 +457,6 @@ public:
int class_get_method_argument_count(const StringName &p_class, const StringName &p_method, bool p_no_inheritance = false) const;
TypedArray<Dictionary> class_get_method_list(const StringName &p_class, bool p_no_inheritance = false) const;
Variant class_call_static_method(const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error);
PackedStringArray class_get_integer_constant_list(const StringName &p_class, bool p_no_inheritance = false) const;
bool class_has_integer_constant(const StringName &p_class, const StringName &p_name) const;
@ -569,9 +542,6 @@ public:
// `set_write_movie_path()` is not exposed to the scripting API as changing it at run-time has no effect.
String get_write_movie_path() const;
void set_print_to_stdout(bool p_enabled);
bool is_printing_to_stdout() const;
void set_print_error_messages(bool p_enabled);
bool is_printing_error_messages() const;
@ -648,6 +618,4 @@ VARIANT_ENUM_CAST(core_bind::Geometry2D::PolyEndType);
VARIANT_ENUM_CAST(core_bind::Thread::Priority);
VARIANT_ENUM_CAST(core_bind::special::ClassDB::APIType);
#endif // CORE_BIND_H

View File

@ -671,13 +671,11 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_INT_IS_OBJECTID);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_INT_IS_POINTER);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ARRAY_TYPE);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_DICTIONARY_TYPE);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LOCALE_ID);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LOCALIZABLE_STRING);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_NODE_TYPE);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_HIDE_QUATERNION_EDIT);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_PASSWORD);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_TOOL_BUTTON);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_MAX);
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NONE);

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")

View File

@ -36,10 +36,10 @@
/// Resources
CryptoKey *(*CryptoKey::_create)(bool p_notify_postinitialize) = nullptr;
CryptoKey *CryptoKey::create(bool p_notify_postinitialize) {
CryptoKey *(*CryptoKey::_create)() = nullptr;
CryptoKey *CryptoKey::create() {
if (_create) {
return _create(p_notify_postinitialize);
return _create();
}
return nullptr;
}
@ -52,10 +52,10 @@ void CryptoKey::_bind_methods() {
ClassDB::bind_method(D_METHOD("load_from_string", "string_key", "public_only"), &CryptoKey::load_from_string, DEFVAL(false));
}
X509Certificate *(*X509Certificate::_create)(bool p_notify_postinitialize) = nullptr;
X509Certificate *X509Certificate::create(bool p_notify_postinitialize) {
X509Certificate *(*X509Certificate::_create)() = nullptr;
X509Certificate *X509Certificate::create() {
if (_create) {
return _create(p_notify_postinitialize);
return _create();
}
return nullptr;
}
@ -116,10 +116,10 @@ void HMACContext::_bind_methods() {
ClassDB::bind_method(D_METHOD("finish"), &HMACContext::finish);
}
HMACContext *(*HMACContext::_create)(bool p_notify_postinitialize) = nullptr;
HMACContext *HMACContext::create(bool p_notify_postinitialize) {
HMACContext *(*HMACContext::_create)() = nullptr;
HMACContext *HMACContext::create() {
if (_create) {
return _create(p_notify_postinitialize);
return _create();
}
ERR_FAIL_V_MSG(nullptr, "HMACContext is not available when the mbedtls module is disabled.");
}
@ -127,10 +127,10 @@ HMACContext *HMACContext::create(bool p_notify_postinitialize) {
/// Crypto
void (*Crypto::_load_default_certificates)(const String &p_path) = nullptr;
Crypto *(*Crypto::_create)(bool p_notify_postinitialize) = nullptr;
Crypto *Crypto::create(bool p_notify_postinitialize) {
Crypto *(*Crypto::_create)() = nullptr;
Crypto *Crypto::create() {
if (_create) {
return _create(p_notify_postinitialize);
return _create();
}
ERR_FAIL_V_MSG(nullptr, "Crypto is not available when the mbedtls module is disabled.");
}

View File

@ -42,10 +42,10 @@ class CryptoKey : public Resource {
protected:
static void _bind_methods();
static CryptoKey *(*_create)(bool p_notify_postinitialize);
static CryptoKey *(*_create)();
public:
static CryptoKey *create(bool p_notify_postinitialize = true);
static CryptoKey *create();
virtual Error load(const String &p_path, bool p_public_only = false) = 0;
virtual Error save(const String &p_path, bool p_public_only = false) = 0;
virtual String save_to_string(bool p_public_only = false) = 0;
@ -58,10 +58,10 @@ class X509Certificate : public Resource {
protected:
static void _bind_methods();
static X509Certificate *(*_create)(bool p_notify_postinitialize);
static X509Certificate *(*_create)();
public:
static X509Certificate *create(bool p_notify_postinitialize = true);
static X509Certificate *create();
virtual Error load(const String &p_path) = 0;
virtual Error load_from_memory(const uint8_t *p_buffer, int p_len) = 0;
virtual Error save(const String &p_path) = 0;
@ -106,10 +106,10 @@ class HMACContext : public RefCounted {
protected:
static void _bind_methods();
static HMACContext *(*_create)(bool p_notify_postinitialize);
static HMACContext *(*_create)();
public:
static HMACContext *create(bool p_notify_postinitialize = true);
static HMACContext *create();
virtual Error start(HashingContext::HashType p_hash_type, const PackedByteArray &p_key) = 0;
virtual Error update(const PackedByteArray &p_data) = 0;
@ -124,11 +124,11 @@ class Crypto : public RefCounted {
protected:
static void _bind_methods();
static Crypto *(*_create)(bool p_notify_postinitialize);
static Crypto *(*_create)();
static void (*_load_default_certificates)(const String &p_path);
public:
static Crypto *create(bool p_notify_postinitialize = true);
static Crypto *create();
static void load_default_certificates(const String &p_path);
virtual PackedByteArray generate_random_bytes(int p_bytes) = 0;

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")

View File

@ -144,8 +144,9 @@ void RemoteDebuggerPeerTCP::_read_in() {
Error err = decode_variant(var, buf, in_pos, &read);
ERR_CONTINUE(read != in_pos || err != OK);
ERR_CONTINUE_MSG(var.get_type() != Variant::ARRAY, "Malformed packet received, not an Array.");
MutexLock lock(mutex);
mutex.lock();
in_queue.push_back(var);
mutex.unlock();
}
}
}

View File

@ -33,8 +33,6 @@
String DocData::get_default_value_string(const Variant &p_value) {
if (p_value.get_type() == Variant::ARRAY) {
return Variant(Array(p_value, 0, StringName(), Variant())).get_construct_string().replace("\n", " ");
} else if (p_value.get_type() == Variant::DICTIONARY) {
return Variant(Dictionary(p_value, 0, StringName(), Variant(), 0, StringName(), Variant())).get_construct_string().replace("\n", " ");
} else {
return p_value.get_construct_string().replace("\n", " ");
}
@ -59,8 +57,6 @@ void DocData::return_doc_from_retinfo(DocData::MethodDoc &p_method, const Proper
p_method.return_type = p_retinfo.class_name;
} else if (p_retinfo.type == Variant::ARRAY && p_retinfo.hint == PROPERTY_HINT_ARRAY_TYPE) {
p_method.return_type = p_retinfo.hint_string + "[]";
} else if (p_retinfo.type == Variant::DICTIONARY && p_retinfo.hint == PROPERTY_HINT_DICTIONARY_TYPE) {
p_method.return_type = "Dictionary[" + p_retinfo.hint_string.replace(";", ", ") + "]";
} else if (p_retinfo.hint == PROPERTY_HINT_RESOURCE_TYPE) {
p_method.return_type = p_retinfo.hint_string;
} else if (p_retinfo.type == Variant::NIL && p_retinfo.usage & PROPERTY_USAGE_NIL_IS_VARIANT) {
@ -93,8 +89,6 @@ void DocData::argument_doc_from_arginfo(DocData::ArgumentDoc &p_argument, const
p_argument.type = p_arginfo.class_name;
} else if (p_arginfo.type == Variant::ARRAY && p_arginfo.hint == PROPERTY_HINT_ARRAY_TYPE) {
p_argument.type = p_arginfo.hint_string + "[]";
} else if (p_arginfo.type == Variant::DICTIONARY && p_arginfo.hint == PROPERTY_HINT_DICTIONARY_TYPE) {
p_argument.type = "Dictionary[" + p_arginfo.hint_string.replace(";", ", ") + "]";
} else if (p_arginfo.hint == PROPERTY_HINT_RESOURCE_TYPE) {
p_argument.type = p_arginfo.hint_string;
} else if (p_arginfo.type == Variant::NIL) {

View File

@ -522,10 +522,6 @@ public:
String type;
String data_type;
String description;
bool is_deprecated = false;
String deprecated_message;
bool is_experimental = false;
String experimental_message;
String default_value;
String keywords;
bool operator<(const ThemeItemDoc &p_theme_item) const {
@ -554,16 +550,6 @@ public:
doc.description = p_dict["description"];
}
if (p_dict.has("deprecated")) {
doc.is_deprecated = true;
doc.deprecated_message = p_dict["deprecated"];
}
if (p_dict.has("experimental")) {
doc.is_experimental = true;
doc.experimental_message = p_dict["experimental"];
}
if (p_dict.has("default_value")) {
doc.default_value = p_dict["default_value"];
}
@ -593,14 +579,6 @@ public:
dict["description"] = p_doc.description;
}
if (p_doc.is_deprecated) {
dict["deprecated"] = p_doc.deprecated_message;
}
if (p_doc.is_experimental) {
dict["experimental"] = p_doc.experimental_message;
}
if (!p_doc.default_value.is_empty()) {
dict["default_value"] = p_doc.default_value;
}

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")

View File

@ -41,7 +41,6 @@
* - Are added to the Error enum in core/error/error_list.h
* - Have a description added to error_names in core/error/error_list.cpp
* - Are bound with BIND_CORE_ENUM_CONSTANT() in core/core_constants.cpp
* - Have a matching Android version in platform/android/java/lib/src/org/godotengine/godot/error/Error.kt
*/
enum Error {

View File

@ -34,12 +34,6 @@
#include "core/os/os.h"
#include "core/string/ustring.h"
// Optional physics interpolation warnings try to include the path to the relevant node.
#if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)
#include "core/config/project_settings.h"
#include "scene/main/node.h"
#endif
static ErrorHandlerList *error_handler_list = nullptr;
void add_error_handler(ErrorHandlerList *p_handler) {
@ -134,48 +128,3 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
void _err_flush_stdout() {
fflush(stdout);
}
// Prevent error spam by limiting the warnings to a certain frequency.
void _physics_interpolation_warning(const char *p_function, const char *p_file, int p_line, ObjectID p_id, const char *p_warn_string) {
#if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)
const uint32_t warn_max = 2048;
const uint32_t warn_timeout_seconds = 15;
static uint32_t warn_count = warn_max;
static uint32_t warn_timeout = warn_timeout_seconds;
uint32_t time_now = UINT32_MAX;
if (warn_count) {
warn_count--;
}
if (!warn_count) {
time_now = OS::get_singleton()->get_ticks_msec() / 1000;
}
if ((warn_count == 0) && (time_now >= warn_timeout)) {
warn_count = warn_max;
warn_timeout = time_now + warn_timeout_seconds;
if (GLOBAL_GET("debug/settings/physics_interpolation/enable_warnings")) {
// UINT64_MAX means unused.
if (p_id.operator uint64_t() == UINT64_MAX) {
_err_print_error(p_function, p_file, p_line, "[Physics interpolation] " + String(p_warn_string) + " (possibly benign).", false, ERR_HANDLER_WARNING);
} else {
String node_name;
if (p_id.is_valid()) {
Node *node = Object::cast_to<Node>(ObjectDB::get_instance(p_id));
if (node && node->is_inside_tree()) {
node_name = "\"" + String(node->get_path()) + "\"";
} else {
node_name = "\"unknown\"";
}
}
_err_print_error(p_function, p_file, p_line, "[Physics interpolation] " + String(p_warn_string) + ": " + node_name + " (possibly benign).", false, ERR_HANDLER_WARNING);
}
}
}
#endif
}

View File

@ -31,7 +31,6 @@
#ifndef ERROR_MACROS_H
#define ERROR_MACROS_H
#include "core/object/object_id.h"
#include "core/typedefs.h"
#include <atomic> // We'd normally use safe_refcount.h, but that would cause circular includes.
@ -72,8 +71,6 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool p_editor_notify = false, bool fatal = false);
void _err_flush_stdout();
void _physics_interpolation_warning(const char *p_function, const char *p_file, int p_line, ObjectID p_id, const char *p_warn_string);
#ifdef __GNUC__
//#define FUNCTION_STR __PRETTY_FUNCTION__ - too annoying
#define FUNCTION_STR __FUNCTION__
@ -835,14 +832,4 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
#define DEV_CHECK_ONCE(m_cond)
#endif
/**
* Physics Interpolation warnings.
* These are spam protection warnings.
*/
#define PHYSICS_INTERPOLATION_NODE_WARNING(m_object_id, m_string) \
_physics_interpolation_warning(FUNCTION_STR, __FILE__, __LINE__, m_object_id, m_string)
#define PHYSICS_INTERPOLATION_WARNING(m_string) \
_physics_interpolation_warning(FUNCTION_STR, __FILE__, __LINE__, ObjectID(UINT64_MAX), m_string)
#endif // ERROR_MACROS_H

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")

View File

@ -60,9 +60,6 @@ static String get_property_info_type_name(const PropertyInfo &p_info) {
if (p_info.type == Variant::ARRAY && (p_info.hint == PROPERTY_HINT_ARRAY_TYPE)) {
return String("typedarray::") + p_info.hint_string;
}
if (p_info.type == Variant::DICTIONARY && (p_info.hint == PROPERTY_HINT_DICTIONARY_TYPE)) {
return String("typeddictionary::") + p_info.hint_string;
}
if (p_info.type == Variant::INT && (p_info.usage & (PROPERTY_USAGE_CLASS_IS_ENUM))) {
return String("enum::") + String(p_info.class_name);
}
@ -88,7 +85,7 @@ static String get_property_info_type_name(const PropertyInfo &p_info) {
}
static String get_type_meta_name(const GodotTypeInfo::Metadata metadata) {
static const char *argmeta[13] = { "none", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float", "double", "char16", "char32" };
static const char *argmeta[11] = { "none", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float", "double" };
return argmeta[metadata];
}
@ -1017,7 +1014,6 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
d2["name"] = String(method_name);
d2["is_const"] = (F.flags & METHOD_FLAG_CONST) ? true : false;
d2["is_static"] = (F.flags & METHOD_FLAG_STATIC) ? true : false;
d2["is_required"] = (F.flags & METHOD_FLAG_VIRTUAL_REQUIRED) ? true : false;
d2["is_vararg"] = false;
d2["is_virtual"] = true;
// virtual functions have no hash since no MethodBind is involved

View File

@ -32,9 +32,11 @@
#include "gdextension.compat.inc"
#include "core/config/project_settings.h"
#include "core/io/dir_access.h"
#include "core/object/class_db.h"
#include "core/object/method_bind.h"
#include "gdextension_library_loader.h"
#include "core/os/os.h"
#include "core/version.h"
#include "gdextension_manager.h"
extern void gdextension_setup_interface();
@ -46,6 +48,146 @@ String GDExtension::get_extension_list_config_file() {
return ProjectSettings::get_singleton()->get_project_data_path().path_join("extension_list.cfg");
}
Vector<SharedObject> GDExtension::find_extension_dependencies(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature) {
Vector<SharedObject> dependencies_shared_objects;
if (p_config->has_section("dependencies")) {
List<String> config_dependencies;
p_config->get_section_keys("dependencies", &config_dependencies);
for (const String &dependency : config_dependencies) {
Vector<String> dependency_tags = dependency.split(".");
bool all_tags_met = true;
for (int i = 0; i < dependency_tags.size(); i++) {
String tag = dependency_tags[i].strip_edges();
if (!p_has_feature(tag)) {
all_tags_met = false;
break;
}
}
if (all_tags_met) {
Dictionary dependency_value = p_config->get_value("dependencies", dependency);
for (const Variant *key = dependency_value.next(nullptr); key; key = dependency_value.next(key)) {
String dependency_path = *key;
String target_path = dependency_value[*key];
if (dependency_path.is_relative_path()) {
dependency_path = p_path.get_base_dir().path_join(dependency_path);
}
dependencies_shared_objects.push_back(SharedObject(dependency_path, dependency_tags, target_path));
}
break;
}
}
}
return dependencies_shared_objects;
}
String GDExtension::find_extension_library(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature, PackedStringArray *r_tags) {
// First, check the explicit libraries.
if (p_config->has_section("libraries")) {
List<String> libraries;
p_config->get_section_keys("libraries", &libraries);
// Iterate the libraries, finding the best matching tags.
String best_library_path;
Vector<String> best_library_tags;
for (const String &E : libraries) {
Vector<String> tags = E.split(".");
bool all_tags_met = true;
for (int i = 0; i < tags.size(); i++) {
String tag = tags[i].strip_edges();
if (!p_has_feature(tag)) {
all_tags_met = false;
break;
}
}
if (all_tags_met && tags.size() > best_library_tags.size()) {
best_library_path = p_config->get_value("libraries", E);
best_library_tags = tags;
}
}
if (!best_library_path.is_empty()) {
if (best_library_path.is_relative_path()) {
best_library_path = p_path.get_base_dir().path_join(best_library_path);
}
if (r_tags != nullptr) {
r_tags->append_array(best_library_tags);
}
return best_library_path;
}
}
// Second, try to autodetect
String autodetect_library_prefix;
if (p_config->has_section_key("configuration", "autodetect_library_prefix")) {
autodetect_library_prefix = p_config->get_value("configuration", "autodetect_library_prefix");
}
if (!autodetect_library_prefix.is_empty()) {
String autodetect_path = autodetect_library_prefix;
if (autodetect_path.is_relative_path()) {
autodetect_path = p_path.get_base_dir().path_join(autodetect_path);
}
// Find the folder and file parts of the prefix.
String folder;
String file_prefix;
if (DirAccess::dir_exists_absolute(autodetect_path)) {
folder = autodetect_path;
} else if (DirAccess::dir_exists_absolute(autodetect_path.get_base_dir())) {
folder = autodetect_path.get_base_dir();
file_prefix = autodetect_path.get_file();
} else {
ERR_FAIL_V_MSG(String(), vformat("Error in extension: %s. Could not find folder for automatic detection of libraries files. autodetect_library_prefix=\"%s\"", p_path, autodetect_library_prefix));
}
// Open the folder.
Ref<DirAccess> dir = DirAccess::open(folder);
ERR_FAIL_COND_V_MSG(!dir.is_valid(), String(), vformat("Error in extension: %s. Could not open folder for automatic detection of libraries files. autodetect_library_prefix=\"%s\"", p_path, autodetect_library_prefix));
// Iterate the files and check the prefixes, finding the best matching file.
String best_file;
Vector<String> best_file_tags;
dir->list_dir_begin();
String file_name = dir->_get_next();
while (file_name != "") {
if (!dir->current_is_dir() && file_name.begins_with(file_prefix)) {
// Check if the files matches all requested feature tags.
String tags_str = file_name.trim_prefix(file_prefix);
tags_str = tags_str.trim_suffix(tags_str.get_extension());
Vector<String> tags = tags_str.split(".", false);
bool all_tags_met = true;
for (int i = 0; i < tags.size(); i++) {
String tag = tags[i].strip_edges();
if (!p_has_feature(tag)) {
all_tags_met = false;
break;
}
}
// If all tags are found in the feature list, and we found more tags than before, use this file.
if (all_tags_met && tags.size() > best_file_tags.size()) {
best_file_tags = tags;
best_file = file_name;
}
}
file_name = dir->_get_next();
}
if (!best_file.is_empty()) {
String library_path = folder.path_join(best_file);
if (r_tags != nullptr) {
r_tags->append_array(best_file_tags);
}
return library_path;
}
}
return String();
}
class GDExtensionMethodBind : public MethodBind {
GDExtensionClassMethodCall call_func;
GDExtensionClassMethodValidatedCall validated_call_func;
@ -240,7 +382,7 @@ public:
#ifndef DISABLE_DEPRECATED
void GDExtension::_register_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo *p_extension_funcs) {
const GDExtensionClassCreationInfo4 class_info4 = {
const GDExtensionClassCreationInfo3 class_info3 = {
p_extension_funcs->is_virtual, // GDExtensionBool is_virtual;
p_extension_funcs->is_abstract, // GDExtensionBool is_abstract;
true, // GDExtensionBool is_exposed;
@ -256,26 +398,25 @@ void GDExtension::_register_extension_class(GDExtensionClassLibraryPtr p_library
p_extension_funcs->to_string_func, // GDExtensionClassToString to_string_func;
p_extension_funcs->reference_func, // GDExtensionClassReference reference_func;
p_extension_funcs->unreference_func, // GDExtensionClassUnreference unreference_func;
nullptr, // GDExtensionClassCreateInstance2 create_instance_func; /* this one is mandatory */
p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
p_extension_funcs->free_instance_func, // GDExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
nullptr, // GDExtensionClassRecreateInstance recreate_instance_func;
p_extension_funcs->get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func;
nullptr, // GDExtensionClassGetVirtualCallData get_virtual_call_data_func;
nullptr, // GDExtensionClassCallVirtualWithData call_virtual_func;
p_extension_funcs->get_rid_func, // GDExtensionClassGetRID get_rid;
p_extension_funcs->class_userdata, // void *class_userdata;
};
const ClassCreationDeprecatedInfo legacy = {
p_extension_funcs->notification_func, // GDExtensionClassNotification notification_func;
p_extension_funcs->free_property_list_func, // GDExtensionClassFreePropertyList free_property_list_func;
p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance create_instance_func;
p_extension_funcs->get_rid_func, // GDExtensionClassGetRID get_rid;
};
_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info4, &legacy);
_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info3, &legacy);
}
void GDExtension::_register_extension_class2(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo2 *p_extension_funcs) {
const GDExtensionClassCreationInfo4 class_info4 = {
const GDExtensionClassCreationInfo3 class_info3 = {
p_extension_funcs->is_virtual, // GDExtensionBool is_virtual;
p_extension_funcs->is_abstract, // GDExtensionBool is_abstract;
p_extension_funcs->is_exposed, // GDExtensionBool is_exposed;
@ -291,71 +432,34 @@ void GDExtension::_register_extension_class2(GDExtensionClassLibraryPtr p_librar
p_extension_funcs->to_string_func, // GDExtensionClassToString to_string_func;
p_extension_funcs->reference_func, // GDExtensionClassReference reference_func;
p_extension_funcs->unreference_func, // GDExtensionClassUnreference unreference_func;
nullptr, // GDExtensionClassCreateInstance2 create_instance_func; /* this one is mandatory */
p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
p_extension_funcs->free_instance_func, // GDExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
p_extension_funcs->recreate_instance_func, // GDExtensionClassRecreateInstance recreate_instance_func;
p_extension_funcs->get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func;
p_extension_funcs->get_virtual_call_data_func, // GDExtensionClassGetVirtualCallData get_virtual_call_data_func;
p_extension_funcs->call_virtual_with_data_func, // GDExtensionClassCallVirtualWithData call_virtual_func;
p_extension_funcs->get_rid_func, // GDExtensionClassGetRID get_rid;
p_extension_funcs->class_userdata, // void *class_userdata;
};
const ClassCreationDeprecatedInfo legacy = {
nullptr, // GDExtensionClassNotification notification_func;
p_extension_funcs->free_property_list_func, // GDExtensionClassFreePropertyList free_property_list_func;
p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance create_instance_func;
p_extension_funcs->get_rid_func, // GDExtensionClassGetRID get_rid;
};
_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info4, &legacy);
_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info3, &legacy);
}
void GDExtension::_register_extension_class3(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo3 *p_extension_funcs) {
const GDExtensionClassCreationInfo4 class_info4 = {
p_extension_funcs->is_virtual, // GDExtensionBool is_virtual;
p_extension_funcs->is_abstract, // GDExtensionBool is_abstract;
p_extension_funcs->is_exposed, // GDExtensionBool is_exposed;
p_extension_funcs->is_runtime, // GDExtensionBool is_runtime;
p_extension_funcs->set_func, // GDExtensionClassSet set_func;
p_extension_funcs->get_func, // GDExtensionClassGet get_func;
p_extension_funcs->get_property_list_func, // GDExtensionClassGetPropertyList get_property_list_func;
p_extension_funcs->free_property_list_func, // GDExtensionClassFreePropertyList free_property_list_func;
p_extension_funcs->property_can_revert_func, // GDExtensionClassPropertyCanRevert property_can_revert_func;
p_extension_funcs->property_get_revert_func, // GDExtensionClassPropertyGetRevert property_get_revert_func;
p_extension_funcs->validate_property_func, // GDExtensionClassValidateProperty validate_property_func;
p_extension_funcs->notification_func, // GDExtensionClassNotification2 notification_func;
p_extension_funcs->to_string_func, // GDExtensionClassToString to_string_func;
p_extension_funcs->reference_func, // GDExtensionClassReference reference_func;
p_extension_funcs->unreference_func, // GDExtensionClassUnreference unreference_func;
nullptr, // GDExtensionClassCreateInstance2 create_instance_func; /* this one is mandatory */
p_extension_funcs->free_instance_func, // GDExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
p_extension_funcs->recreate_instance_func, // GDExtensionClassRecreateInstance recreate_instance_func;
p_extension_funcs->get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func;
p_extension_funcs->get_virtual_call_data_func, // GDExtensionClassGetVirtualCallData get_virtual_call_data_func;
p_extension_funcs->call_virtual_with_data_func, // GDExtensionClassCallVirtualWithData call_virtual_func;
p_extension_funcs->class_userdata, // void *class_userdata;
};
const ClassCreationDeprecatedInfo legacy = {
nullptr, // GDExtensionClassNotification notification_func;
nullptr, // GDExtensionClassFreePropertyList free_property_list_func;
p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance2 create_instance_func;
p_extension_funcs->get_rid_func, // GDExtensionClassGetRID get_rid;
};
_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info4, &legacy);
}
#endif // DISABLE_DEPRECATED
void GDExtension::_register_extension_class4(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo4 *p_extension_funcs) {
void GDExtension::_register_extension_class3(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo3 *p_extension_funcs) {
_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, p_extension_funcs);
}
void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo4 *p_extension_funcs, const ClassCreationDeprecatedInfo *p_deprecated_funcs) {
void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo3 *p_extension_funcs, const ClassCreationDeprecatedInfo *p_deprecated_funcs) {
GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
StringName parent_class_name = *reinterpret_cast<const StringName *>(p_parent_class_name);
ERR_FAIL_COND_MSG(!String(class_name).is_valid_unicode_identifier(), "Attempt to register extension class '" + class_name + "', which is not a valid class identifier.");
ERR_FAIL_COND_MSG(!String(class_name).is_valid_identifier(), "Attempt to register extension class '" + class_name + "', which is not a valid class identifier.");
ERR_FAIL_COND_MSG(ClassDB::class_exists(class_name), "Attempt to register extension class '" + class_name + "', which appears to be already registered.");
Extension *parent_extension = nullptr;
@ -426,8 +530,6 @@ void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr
if (p_deprecated_funcs) {
extension->gdextension.notification = p_deprecated_funcs->notification_func;
extension->gdextension.free_property_list = p_deprecated_funcs->free_property_list_func;
extension->gdextension.create_instance = p_deprecated_funcs->create_instance_func;
extension->gdextension.get_rid = p_deprecated_funcs->get_rid_func;
}
#endif // DISABLE_DEPRECATED
extension->gdextension.notification2 = p_extension_funcs->notification_func;
@ -435,12 +537,13 @@ void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr
extension->gdextension.reference = p_extension_funcs->reference_func;
extension->gdextension.unreference = p_extension_funcs->unreference_func;
extension->gdextension.class_userdata = p_extension_funcs->class_userdata;
extension->gdextension.create_instance2 = p_extension_funcs->create_instance_func;
extension->gdextension.create_instance = p_extension_funcs->create_instance_func;
extension->gdextension.free_instance = p_extension_funcs->free_instance_func;
extension->gdextension.recreate_instance = p_extension_funcs->recreate_instance_func;
extension->gdextension.get_virtual = p_extension_funcs->get_virtual_func;
extension->gdextension.get_virtual_call_data = p_extension_funcs->get_virtual_call_data_func;
extension->gdextension.call_virtual_with_data = p_extension_funcs->call_virtual_with_data_func;
extension->gdextension.get_rid = p_extension_funcs->get_rid_func;
extension->gdextension.reloadable = self->reloadable;
#ifdef TOOLS_ENABLED
@ -652,13 +755,7 @@ void GDExtension::_unregister_extension_class(GDExtensionClassLibraryPtr p_libra
void GDExtension::_get_library_path(GDExtensionClassLibraryPtr p_library, GDExtensionUninitializedStringPtr r_path) {
GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
Ref<GDExtensionLibraryLoader> library_loader = self->loader;
String library_path;
if (library_loader.is_valid()) {
library_path = library_loader->library_path;
}
memnew_placement(r_path, String(library_path));
memnew_placement(r_path, String(self->library_path));
}
HashMap<StringName, GDExtensionInterfaceFunctionPtr> GDExtension::gdextension_interface_functions;
@ -674,32 +771,55 @@ GDExtensionInterfaceFunctionPtr GDExtension::get_interface_function(const String
return *function;
}
Error GDExtension::open_library(const String &p_path, const Ref<GDExtensionLoader> &p_loader) {
ERR_FAIL_COND_V_MSG(p_loader.is_null(), FAILED, "Can't open GDExtension without a loader.");
loader = p_loader;
Error GDExtension::open_library(const String &p_path, const String &p_entry_symbol, Vector<SharedObject> *p_dependencies) {
String abs_path = ProjectSettings::get_singleton()->globalize_path(p_path);
Error err = loader->open_library(p_path);
Vector<String> abs_dependencies_paths;
if (p_dependencies != nullptr && !p_dependencies->is_empty()) {
for (const SharedObject &dependency : *p_dependencies) {
abs_dependencies_paths.push_back(ProjectSettings::get_singleton()->globalize_path(dependency.path));
}
}
ERR_FAIL_COND_V_MSG(err == ERR_FILE_NOT_FOUND, err, "GDExtension dynamic library not found: " + p_path);
ERR_FAIL_COND_V_MSG(err != OK, err, "Can't open GDExtension dynamic library: " + p_path);
OS::GDExtensionData data = {
true, // also_set_library_path
&library_path, // r_resolved_path
Engine::get_singleton()->is_editor_hint(), // generate_temp_files
&abs_dependencies_paths, // library_dependencies
};
Error err = OS::get_singleton()->open_dynamic_library(abs_path, library, &data);
err = loader->initialize(&gdextension_get_proc_address, this, &initialization);
ERR_FAIL_COND_V_MSG(err == ERR_FILE_NOT_FOUND, err, "GDExtension dynamic library not found: " + abs_path);
ERR_FAIL_COND_V_MSG(err != OK, err, "Can't open GDExtension dynamic library: " + abs_path);
void *entry_funcptr = nullptr;
err = OS::get_singleton()->get_dynamic_library_symbol_handle(library, p_entry_symbol, entry_funcptr, false);
if (err != OK) {
// Errors already logged in initialize().
loader->close_library();
ERR_PRINT("GDExtension entry point '" + p_entry_symbol + "' not found in library " + abs_path);
OS::get_singleton()->close_dynamic_library(library);
return err;
}
level_initialized = -1;
GDExtensionInitializationFunction initialization_function = (GDExtensionInitializationFunction)entry_funcptr;
GDExtensionBool ret = initialization_function(&gdextension_get_proc_address, this, &initialization);
return OK;
if (ret) {
level_initialized = -1;
return OK;
} else {
ERR_PRINT("GDExtension initialization function '" + p_entry_symbol + "' returned an error.");
OS::get_singleton()->close_dynamic_library(library);
return FAILED;
}
}
void GDExtension::close_library() {
ERR_FAIL_COND(!is_library_open());
loader->close_library();
ERR_FAIL_NULL(library);
OS::get_singleton()->close_dynamic_library(library);
library = nullptr;
class_icon_paths.clear();
#ifdef TOOLS_ENABLED
@ -708,16 +828,16 @@ void GDExtension::close_library() {
}
bool GDExtension::is_library_open() const {
return loader.is_valid() && loader->is_library_open();
return library != nullptr;
}
GDExtension::InitializationLevel GDExtension::get_minimum_library_initialization_level() const {
ERR_FAIL_COND_V(!is_library_open(), INITIALIZATION_LEVEL_CORE);
ERR_FAIL_NULL_V(library, INITIALIZATION_LEVEL_CORE);
return InitializationLevel(initialization.minimum_initialization_level);
}
void GDExtension::initialize_library(InitializationLevel p_level) {
ERR_FAIL_COND(!is_library_open());
ERR_FAIL_NULL(library);
ERR_FAIL_COND_MSG(p_level <= int32_t(level_initialized), vformat("Level '%d' must be higher than the current level '%d'", p_level, level_initialized));
level_initialized = int32_t(p_level);
@ -727,7 +847,7 @@ void GDExtension::initialize_library(InitializationLevel p_level) {
initialization.initialize(initialization.userdata, GDExtensionInitializationLevel(p_level));
}
void GDExtension::deinitialize_library(InitializationLevel p_level) {
ERR_FAIL_COND(!is_library_open());
ERR_FAIL_NULL(library);
ERR_FAIL_COND(p_level > int32_t(level_initialized));
level_initialized = int32_t(p_level) - 1;
@ -751,7 +871,7 @@ GDExtension::GDExtension() {
}
GDExtension::~GDExtension() {
if (is_library_open()) {
if (library != nullptr) {
close_library();
}
#ifdef TOOLS_ENABLED
@ -768,9 +888,8 @@ void GDExtension::initialize_gdextensions() {
#ifndef DISABLE_DEPRECATED
register_interface_function("classdb_register_extension_class", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class);
register_interface_function("classdb_register_extension_class2", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class2);
register_interface_function("classdb_register_extension_class3", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class3);
#endif // DISABLE_DEPRECATED
register_interface_function("classdb_register_extension_class4", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class4);
register_interface_function("classdb_register_extension_class3", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class3);
register_interface_function("classdb_register_extension_class_method", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class_method);
register_interface_function("classdb_register_extension_class_virtual_method", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class_virtual_method);
register_interface_function("classdb_register_extension_class_integer_constant", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class_integer_constant);
@ -790,15 +909,142 @@ void GDExtension::finalize_gdextensions() {
Error GDExtensionResourceLoader::load_gdextension_resource(const String &p_path, Ref<GDExtension> &p_extension) {
ERR_FAIL_COND_V_MSG(p_extension.is_valid() && p_extension->is_library_open(), ERR_ALREADY_IN_USE, "Cannot load GDExtension resource into already opened library.");
GDExtensionManager *extension_manager = GDExtensionManager::get_singleton();
Ref<ConfigFile> config;
config.instantiate();
GDExtensionManager::LoadStatus status = extension_manager->load_extension(p_path);
if (status != GDExtensionManager::LOAD_STATUS_OK && status != GDExtensionManager::LOAD_STATUS_ALREADY_LOADED) {
// Errors already logged in load_extension().
return FAILED;
Error err = config->load(p_path);
if (err != OK) {
ERR_PRINT("Error loading GDExtension configuration file: " + p_path);
return err;
}
if (!config->has_section_key("configuration", "entry_symbol")) {
ERR_PRINT("GDExtension configuration file must contain a \"configuration/entry_symbol\" key: " + p_path);
return ERR_INVALID_DATA;
}
String entry_symbol = config->get_value("configuration", "entry_symbol");
uint32_t compatibility_minimum[3] = { 0, 0, 0 };
if (config->has_section_key("configuration", "compatibility_minimum")) {
String compat_string = config->get_value("configuration", "compatibility_minimum");
Vector<int> parts = compat_string.split_ints(".");
for (int i = 0; i < parts.size(); i++) {
if (i >= 3) {
break;
}
if (parts[i] >= 0) {
compatibility_minimum[i] = parts[i];
}
}
} else {
ERR_PRINT("GDExtension configuration file must contain a \"configuration/compatibility_minimum\" key: " + p_path);
return ERR_INVALID_DATA;
}
if (compatibility_minimum[0] < 4 || (compatibility_minimum[0] == 4 && compatibility_minimum[1] == 0)) {
ERR_PRINT(vformat("GDExtension's compatibility_minimum (%d.%d.%d) must be at least 4.1.0: %s", compatibility_minimum[0], compatibility_minimum[1], compatibility_minimum[2], p_path));
return ERR_INVALID_DATA;
}
bool compatible = true;
// Check version lexicographically.
if (VERSION_MAJOR != compatibility_minimum[0]) {
compatible = VERSION_MAJOR > compatibility_minimum[0];
} else if (VERSION_MINOR != compatibility_minimum[1]) {
compatible = VERSION_MINOR > compatibility_minimum[1];
} else {
compatible = VERSION_PATCH >= compatibility_minimum[2];
}
if (!compatible) {
ERR_PRINT(vformat("GDExtension only compatible with Godot version %d.%d.%d or later: %s", compatibility_minimum[0], compatibility_minimum[1], compatibility_minimum[2], p_path));
return ERR_INVALID_DATA;
}
// Optionally check maximum compatibility.
if (config->has_section_key("configuration", "compatibility_maximum")) {
uint32_t compatibility_maximum[3] = { 0, 0, 0 };
String compat_string = config->get_value("configuration", "compatibility_maximum");
Vector<int> parts = compat_string.split_ints(".");
for (int i = 0; i < 3; i++) {
if (i < parts.size() && parts[i] >= 0) {
compatibility_maximum[i] = parts[i];
} else {
// If a version part is missing, set the maximum to an arbitrary high value.
compatibility_maximum[i] = 9999;
}
}
compatible = true;
if (VERSION_MAJOR != compatibility_maximum[0]) {
compatible = VERSION_MAJOR < compatibility_maximum[0];
} else if (VERSION_MINOR != compatibility_maximum[1]) {
compatible = VERSION_MINOR < compatibility_maximum[1];
}
#if VERSION_PATCH
// #if check to avoid -Wtype-limits warning when 0.
else {
compatible = VERSION_PATCH <= compatibility_maximum[2];
}
#endif
if (!compatible) {
ERR_PRINT(vformat("GDExtension only compatible with Godot version %s or earlier: %s", compat_string, p_path));
return ERR_INVALID_DATA;
}
}
String library_path = GDExtension::find_extension_library(p_path, config, [](const String &p_feature) { return OS::get_singleton()->has_feature(p_feature); });
if (library_path.is_empty()) {
const String os_arch = OS::get_singleton()->get_name().to_lower() + "." + Engine::get_singleton()->get_architecture_name();
ERR_PRINT(vformat("No GDExtension library found for current OS and architecture (%s) in configuration file: %s", os_arch, p_path));
return ERR_FILE_NOT_FOUND;
}
bool is_static_library = library_path.ends_with(".a") || library_path.ends_with(".xcframework");
if (!library_path.is_resource_file() && !library_path.is_absolute_path()) {
library_path = p_path.get_base_dir().path_join(library_path);
}
if (p_extension.is_null()) {
p_extension.instantiate();
}
#ifdef TOOLS_ENABLED
p_extension->set_reloadable(config->get_value("configuration", "reloadable", false) && Engine::get_singleton()->is_extension_reloading_enabled());
p_extension->update_last_modified_time(
FileAccess::get_modified_time(p_path),
FileAccess::get_modified_time(library_path));
#endif
Vector<SharedObject> library_dependencies = GDExtension::find_extension_dependencies(p_path, config, [](const String &p_feature) { return OS::get_singleton()->has_feature(p_feature); });
err = p_extension->open_library(is_static_library ? String() : library_path, entry_symbol, &library_dependencies);
if (err != OK) {
// Unreference the extension so that this loading can be considered a failure.
p_extension.unref();
// Errors already logged in open_library()
return err;
}
// Handle icons if any are specified.
if (config->has_section("icons")) {
List<String> keys;
config->get_section_keys("icons", &keys);
for (const String &key : keys) {
String icon_path = config->get_value("icons", key);
if (icon_path.is_relative_path()) {
icon_path = p_path.get_base_dir().path_join(icon_path);
}
p_extension->class_icon_paths[key] = icon_path;
}
}
p_extension = extension_manager->get_extension(p_path);
return OK;
}
@ -839,7 +1085,16 @@ String GDExtensionResourceLoader::get_resource_type(const String &p_path) const
#ifdef TOOLS_ENABLED
bool GDExtension::has_library_changed() const {
return loader->has_library_changed();
// Check only that the last modified time is different (rather than checking
// that it's newer) since some OS's (namely Windows) will preserve the modified
// time by default when copying files.
if (FileAccess::get_modified_time(get_path()) != resource_last_modified_time) {
return true;
}
if (FileAccess::get_modified_time(library_path) != library_last_modified_time) {
return true;
}
return false;
}
void GDExtension::prepare_reload() {

View File

@ -31,11 +31,13 @@
#ifndef GDEXTENSION_H
#define GDEXTENSION_H
#include <functional>
#include "core/extension/gdextension_interface.h"
#include "core/extension/gdextension_loader.h"
#include "core/io/config_file.h"
#include "core/io/resource_loader.h"
#include "core/object/ref_counted.h"
#include "core/os/shared_object.h"
class GDExtensionMethodBind;
@ -44,8 +46,8 @@ class GDExtension : public Resource {
friend class GDExtensionManager;
Ref<GDExtensionLoader> loader;
void *library = nullptr; // pointer if valid,
String library_path;
bool reloadable = false;
struct Extension {
@ -70,18 +72,15 @@ class GDExtension : public Resource {
#ifndef DISABLE_DEPRECATED
GDExtensionClassNotification notification_func = nullptr;
GDExtensionClassFreePropertyList free_property_list_func = nullptr;
GDExtensionClassCreateInstance create_instance_func = nullptr;
GDExtensionClassGetRID get_rid_func = nullptr;
#endif // DISABLE_DEPRECATED
};
#ifndef DISABLE_DEPRECATED
static void _register_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo *p_extension_funcs);
static void _register_extension_class2(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo2 *p_extension_funcs);
static void _register_extension_class3(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo3 *p_extension_funcs);
#endif // DISABLE_DEPRECATED
static void _register_extension_class4(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo4 *p_extension_funcs);
static void _register_extension_class_internal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo4 *p_extension_funcs, const ClassCreationDeprecatedInfo *p_deprecated_funcs = nullptr);
static void _register_extension_class3(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo3 *p_extension_funcs);
static void _register_extension_class_internal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo3 *p_extension_funcs, const ClassCreationDeprecatedInfo *p_deprecated_funcs = nullptr);
static void _register_extension_class_method(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassMethodInfo *p_method_info);
static void _register_extension_class_virtual_method(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassVirtualMethodInfo *p_method_info);
static void _register_extension_class_integer_constant(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_enum_name, GDExtensionConstStringNamePtr p_constant_name, GDExtensionInt p_constant_value, GDExtensionBool p_is_bitfield);
@ -97,6 +96,8 @@ class GDExtension : public Resource {
int32_t level_initialized = -1;
#ifdef TOOLS_ENABLED
uint64_t resource_last_modified_time = 0;
uint64_t library_last_modified_time = 0;
bool is_reloading = false;
Vector<GDExtensionMethodBind *> invalid_methods;
Vector<ObjectID> instance_bindings;
@ -123,12 +124,11 @@ public:
virtual bool editor_can_reload_from_file() override { return false; } // Reloading is handled in a special way.
static String get_extension_list_config_file();
static String find_extension_library(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature, PackedStringArray *r_tags = nullptr);
static Vector<SharedObject> find_extension_dependencies(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature);
const Ref<GDExtensionLoader> get_loader() const { return loader; }
Error open_library(const String &p_path, const Ref<GDExtensionLoader> &p_loader);
Error open_library(const String &p_path, const String &p_entry_symbol, Vector<SharedObject> *p_dependencies = nullptr);
void close_library();
bool is_library_open() const;
enum InitializationLevel {
INITIALIZATION_LEVEL_CORE = GDEXTENSION_INITIALIZATION_CORE,
@ -146,11 +146,17 @@ protected:
#endif
public:
bool is_library_open() const;
#ifdef TOOLS_ENABLED
bool is_reloadable() const { return reloadable; }
void set_reloadable(bool p_reloadable) { reloadable = p_reloadable; }
bool has_library_changed() const;
void update_last_modified_time(uint64_t p_resource_last_modified_time, uint64_t p_library_last_modified_time) {
resource_last_modified_time = p_resource_last_modified_time;
library_last_modified_time = p_library_last_modified_time;
}
void track_instance_binding(Object *p_object);
void untrack_instance_binding(Object *p_object);

View File

@ -103,14 +103,6 @@ void GDExtensionCompatHashes::initialize() {
mappings.insert("AcceptDialog", {
{ "add_button", 4158837846, 3328440682 },
});
mappings.insert("AnimatedSprite2D", {
{ "play", 2372066587, 3269405555 },
{ "play_backwards", 1421762485, 3323268493 },
});
mappings.insert("AnimatedSprite3D", {
{ "play", 2372066587, 3269405555 },
{ "play_backwards", 1421762485, 3323268493 },
});
mappings.insert("Animation", {
{ "add_track", 2393815928, 3843682357 },
{ "track_insert_key", 1985425300, 808952278 },
@ -154,12 +146,6 @@ void GDExtensionCompatHashes::initialize() {
{ "travel", 3683006648, 3823612587 },
{ "start", 3683006648, 3823612587 },
});
mappings.insert("AnimationPlayer", {
{ "play", 3697947785, 3118260607 },
{ "play", 2221377757, 3118260607 },
{ "play_backwards", 3890664824, 2787282401 },
{ "play_with_capture", 3180464118, 1572969103 },
});
mappings.insert("ArrayMesh", {
{ "add_surface_from_arrays", 172284304, 1796411378 },
});
@ -261,20 +247,13 @@ void GDExtensionCompatHashes::initialize() {
});
mappings.insert("DisplayServer", {
{ "global_menu_add_submenu_item", 3806306913, 2828985934 },
{ "global_menu_add_item", 3415468211, 3616842746 },
{ "global_menu_add_item", 3401266716, 3616842746 },
{ "global_menu_add_check_item", 3415468211, 3616842746 },
{ "global_menu_add_check_item", 3401266716, 3616842746 },
{ "global_menu_add_icon_item", 1700867534, 3867083847 },
{ "global_menu_add_icon_item", 4245856523, 3867083847 },
{ "global_menu_add_icon_check_item", 1700867534, 3867083847 },
{ "global_menu_add_icon_check_item", 4245856523, 3867083847 },
{ "global_menu_add_radio_check_item", 3415468211, 3616842746 },
{ "global_menu_add_radio_check_item", 3401266716, 3616842746 },
{ "global_menu_add_icon_radio_check_item", 1700867534, 3867083847 },
{ "global_menu_add_icon_radio_check_item", 4245856523, 3867083847 },
{ "global_menu_add_multistate_item", 635750054, 3297554655 },
{ "global_menu_add_multistate_item", 3431222859, 3297554655 },
{ "global_menu_add_item", 3415468211, 3401266716 },
{ "global_menu_add_check_item", 3415468211, 3401266716 },
{ "global_menu_add_icon_item", 1700867534, 4245856523 },
{ "global_menu_add_icon_check_item", 1700867534, 4245856523 },
{ "global_menu_add_radio_check_item", 3415468211, 3401266716 },
{ "global_menu_add_icon_radio_check_item", 1700867534, 4245856523 },
{ "global_menu_add_multistate_item", 635750054, 3431222859 },
{ "global_menu_add_separator", 1041533178, 3214812433 },
{ "tts_speak", 3741216677, 903992738 },
{ "is_touchscreen_available", 4162880507, 3323674545 },
@ -307,12 +286,6 @@ void GDExtensionCompatHashes::initialize() {
{ "virtual_keyboard_show", 860410478, 3042891259 },
#endif
});
mappings.insert("EditorExportPlatform", {
{ "export_project_files", 425454869, 1063735070 },
});
mappings.insert("EditorProperty", {
{ "emit_changed", 3069422438, 1822500399 },
});
mappings.insert("ENetConnection", {
{ "create_host_bound", 866250949, 1515002313 },
{ "connect_to_host", 385984708, 2171300490 },
@ -480,35 +453,18 @@ void GDExtensionCompatHashes::initialize() {
mappings.insert("MultiplayerAPI", {
{ "rpc", 1833408346, 2077486355 },
});
mappings.insert("NativeMenu", {
{ "add_item", 2553375659, 980552939 },
{ "add_check_item", 2553375659, 980552939 },
{ "add_icon_item", 2987595282, 1372188274 },
{ "add_icon_check_item", 2987595282, 1372188274 },
{ "add_radio_check_item", 2553375659, 980552939 },
{ "add_icon_radio_check_item", 2987595282, 1372188274 },
{ "add_multistate_item", 1558592568, 2674635658 },
});
mappings.insert("NavigationMeshGenerator", {
{ "parse_source_geometry_data", 3703028813, 3172802542 },
{ "parse_source_geometry_data", 685862123, 3172802542 },
{ "bake_from_source_geometry_data", 3669016597, 1286748856 },
{ "bake_from_source_geometry_data", 2469318639, 1286748856 },
{ "parse_source_geometry_data", 3703028813, 685862123 },
{ "bake_from_source_geometry_data", 3669016597, 2469318639 },
});
mappings.insert("NavigationServer2D", {
{ "map_get_path", 56240621, 3146466012 },
{ "parse_source_geometry_data", 1176164995, 1766905497 },
{ "bake_from_source_geometry_data", 2909414286, 2179660022 },
{ "bake_from_source_geometry_data_async", 2909414286, 2179660022 },
});
mappings.insert("NavigationServer3D", {
{ "map_get_path", 2121045993, 1187418690 },
{ "parse_source_geometry_data", 3703028813, 3172802542 },
{ "parse_source_geometry_data", 685862123, 3172802542 },
{ "bake_from_source_geometry_data", 3669016597, 1286748856 },
{ "bake_from_source_geometry_data", 2469318639, 1286748856 },
{ "bake_from_source_geometry_data_async", 3669016597, 1286748856 },
{ "bake_from_source_geometry_data_async", 2469318639, 1286748856 },
{ "parse_source_geometry_data", 3703028813, 685862123 },
{ "bake_from_source_geometry_data", 3669016597, 2469318639 },
{ "bake_from_source_geometry_data_async", 3669016597, 2469318639 },
});
mappings.insert("Node", {
{ "add_child", 3070154285, 3863233950 },
@ -675,11 +631,6 @@ void GDExtensionCompatHashes::initialize() {
mappings.insert("ProjectSettings", {
{ "load_resource_pack", 3001721055, 708980503 },
});
mappings.insert("RDShaderFile", {
{ "bake_from_source_geometry_data_async", 2469318639, 1286748856 },
{ "set_bytecode", 1558064255, 1526857008 },
{ "get_spirv", 3340165340, 2689310080 },
});
mappings.insert("RegEx", {
{ "search", 4087180739, 3365977994 },
{ "search_all", 3354100289, 849021363 },

View File

@ -1199,15 +1199,6 @@ static GDExtensionVariantPtr gdextension_dictionary_operator_index_const(GDExten
return (GDExtensionVariantPtr)&self->operator[](*(const Variant *)p_key);
}
void gdextension_dictionary_set_typed(GDExtensionTypePtr p_self, GDExtensionVariantType p_key_type, GDExtensionConstStringNamePtr p_key_class_name, GDExtensionConstVariantPtr p_key_script, GDExtensionVariantType p_value_type, GDExtensionConstStringNamePtr p_value_class_name, GDExtensionConstVariantPtr p_value_script) {
Dictionary *self = reinterpret_cast<Dictionary *>(p_self);
const StringName *key_class_name = reinterpret_cast<const StringName *>(p_key_class_name);
const Variant *key_script = reinterpret_cast<const Variant *>(p_key_script);
const StringName *value_class_name = reinterpret_cast<const StringName *>(p_value_class_name);
const Variant *value_script = reinterpret_cast<const Variant *>(p_value_script);
self->set_typed((uint32_t)p_key_type, *key_class_name, *key_script, (uint32_t)p_value_type, *value_class_name, *value_script);
}
/* OBJECT API */
static void gdextension_object_method_bind_call(GDExtensionMethodBindPtr p_method_bind, GDExtensionObjectPtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_arg_count, GDExtensionUninitializedVariantPtr r_return, GDExtensionCallError *r_error) {
@ -1308,7 +1299,7 @@ static void gdextension_object_call_script_method(GDExtensionObjectPtr p_object,
const StringName method = *reinterpret_cast<const StringName *>(p_method);
const Variant **args = (const Variant **)p_args;
Callable::CallError error; // TODO: Check `error`?
Callable::CallError error;
memnew_placement(r_return, Variant);
*(Variant *)r_return = o->callp(method, args, p_argument_count, error);
@ -1524,17 +1515,10 @@ static GDExtensionMethodBindPtr gdextension_classdb_get_method_bind(GDExtensionC
return (GDExtensionMethodBindPtr)mb;
}
#ifndef DISABLE_DEPRECATED
static GDExtensionObjectPtr gdextension_classdb_construct_object(GDExtensionConstStringNamePtr p_classname) {
const StringName classname = *reinterpret_cast<const StringName *>(p_classname);
return (GDExtensionObjectPtr)ClassDB::instantiate_no_placeholders(classname);
}
#endif
static GDExtensionObjectPtr gdextension_classdb_construct_object2(GDExtensionConstStringNamePtr p_classname) {
const StringName classname = *reinterpret_cast<const StringName *>(p_classname);
return (GDExtensionObjectPtr)ClassDB::instantiate_without_postinitialization(classname);
}
static void *gdextension_classdb_get_class_tag(GDExtensionConstStringNamePtr p_classname) {
const StringName classname = *reinterpret_cast<const StringName *>(p_classname);
@ -1688,7 +1672,6 @@ void gdextension_setup_interface() {
REGISTER_INTERFACE_FUNC(array_set_typed);
REGISTER_INTERFACE_FUNC(dictionary_operator_index);
REGISTER_INTERFACE_FUNC(dictionary_operator_index_const);
REGISTER_INTERFACE_FUNC(dictionary_set_typed);
REGISTER_INTERFACE_FUNC(object_method_bind_call);
REGISTER_INTERFACE_FUNC(object_method_bind_ptrcall);
REGISTER_INTERFACE_FUNC(object_destroy);
@ -1718,10 +1701,7 @@ void gdextension_setup_interface() {
#endif // DISABLE_DEPRECATED
REGISTER_INTERFACE_FUNC(callable_custom_create2);
REGISTER_INTERFACE_FUNC(callable_custom_get_userdata);
#ifndef DISABLE_DEPRECATED
REGISTER_INTERFACE_FUNC(classdb_construct_object);
#endif // DISABLE_DEPRECATED
REGISTER_INTERFACE_FUNC(classdb_construct_object2);
REGISTER_INTERFACE_FUNC(classdb_get_method_bind);
REGISTER_INTERFACE_FUNC(classdb_get_class_tag);
REGISTER_INTERFACE_FUNC(editor_add_plugin);

View File

@ -268,7 +268,6 @@ typedef void (*GDExtensionClassReference)(GDExtensionClassInstancePtr p_instance
typedef void (*GDExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance);
typedef void (*GDExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret);
typedef GDExtensionObjectPtr (*GDExtensionClassCreateInstance)(void *p_class_userdata);
typedef GDExtensionObjectPtr (*GDExtensionClassCreateInstance2)(void *p_class_userdata, GDExtensionBool p_notify_postinitialize);
typedef void (*GDExtensionClassFreeInstance)(void *p_class_userdata, GDExtensionClassInstancePtr p_instance);
typedef GDExtensionClassInstancePtr (*GDExtensionClassRecreateInstance)(void *p_class_userdata, GDExtensionObjectPtr p_object);
typedef GDExtensionClassCallVirtual (*GDExtensionClassGetVirtual)(void *p_class_userdata, GDExtensionConstStringNamePtr p_name);
@ -293,7 +292,7 @@ typedef struct {
GDExtensionClassGetVirtual get_virtual_func; // Queries a virtual function by name and returns a callback to invoke the requested virtual function.
GDExtensionClassGetRID get_rid_func;
void *class_userdata; // Per-class user data, later accessible in instance bindings.
} GDExtensionClassCreationInfo; // Deprecated. Use GDExtensionClassCreationInfo4 instead.
} GDExtensionClassCreationInfo; // Deprecated. Use GDExtensionClassCreationInfo3 instead.
typedef struct {
GDExtensionBool is_virtual;
@ -326,7 +325,7 @@ typedef struct {
GDExtensionClassCallVirtualWithData call_virtual_with_data_func;
GDExtensionClassGetRID get_rid_func;
void *class_userdata; // Per-class user data, later accessible in instance bindings.
} GDExtensionClassCreationInfo2; // Deprecated. Use GDExtensionClassCreationInfo4 instead.
} GDExtensionClassCreationInfo2; // Deprecated. Use GDExtensionClassCreationInfo3 instead.
typedef struct {
GDExtensionBool is_virtual;
@ -360,40 +359,7 @@ typedef struct {
GDExtensionClassCallVirtualWithData call_virtual_with_data_func;
GDExtensionClassGetRID get_rid_func;
void *class_userdata; // Per-class user data, later accessible in instance bindings.
} GDExtensionClassCreationInfo3; // Deprecated. Use GDExtensionClassCreationInfo4 instead.
typedef struct {
GDExtensionBool is_virtual;
GDExtensionBool is_abstract;
GDExtensionBool is_exposed;
GDExtensionBool is_runtime;
GDExtensionClassSet set_func;
GDExtensionClassGet get_func;
GDExtensionClassGetPropertyList get_property_list_func;
GDExtensionClassFreePropertyList2 free_property_list_func;
GDExtensionClassPropertyCanRevert property_can_revert_func;
GDExtensionClassPropertyGetRevert property_get_revert_func;
GDExtensionClassValidateProperty validate_property_func;
GDExtensionClassNotification2 notification_func;
GDExtensionClassToString to_string_func;
GDExtensionClassReference reference_func;
GDExtensionClassUnreference unreference_func;
GDExtensionClassCreateInstance2 create_instance_func; // (Default) constructor; mandatory. If the class is not instantiable, consider making it virtual or abstract.
GDExtensionClassFreeInstance free_instance_func; // Destructor; mandatory.
GDExtensionClassRecreateInstance recreate_instance_func;
// Queries a virtual function by name and returns a callback to invoke the requested virtual function.
GDExtensionClassGetVirtual get_virtual_func;
// Paired with `call_virtual_with_data_func`, this is an alternative to `get_virtual_func` for extensions that
// need or benefit from extra data when calling virtual functions.
// Returns user data that will be passed to `call_virtual_with_data_func`.
// Returning `NULL` from this function signals to Godot that the virtual function is not overridden.
// Data returned from this function should be managed by the extension and must be valid until the extension is deinitialized.
// You should supply either `get_virtual_func`, or `get_virtual_call_data_func` with `call_virtual_with_data_func`.
GDExtensionClassGetVirtualCallData get_virtual_call_data_func;
// Used to call virtual functions when `get_virtual_call_data_func` is not null.
GDExtensionClassCallVirtualWithData call_virtual_with_data_func;
void *class_userdata; // Per-class user data, later accessible in instance bindings.
} GDExtensionClassCreationInfo4;
} GDExtensionClassCreationInfo3;
typedef void *GDExtensionClassLibraryPtr;
@ -420,9 +386,7 @@ typedef enum {
GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT32,
GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT64,
GDEXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_FLOAT,
GDEXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_DOUBLE,
GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_CHAR16,
GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_CHAR32,
GDEXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_DOUBLE
} GDExtensionClassMethodArgumentMetadata;
typedef void (*GDExtensionClassMethodCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error);
@ -2373,22 +2337,6 @@ typedef GDExtensionVariantPtr (*GDExtensionInterfaceDictionaryOperatorIndex)(GDE
*/
typedef GDExtensionVariantPtr (*GDExtensionInterfaceDictionaryOperatorIndexConst)(GDExtensionConstTypePtr p_self, GDExtensionConstVariantPtr p_key);
/**
* @name dictionary_set_typed
* @since 4.4
*
* Makes a Dictionary into a typed Dictionary.
*
* @param p_self A pointer to the Dictionary.
* @param p_key_type The type of Variant the Dictionary key will store.
* @param p_key_class_name A pointer to a StringName with the name of the object (if p_key_type is GDEXTENSION_VARIANT_TYPE_OBJECT).
* @param p_key_script A pointer to a Script object (if p_key_type is GDEXTENSION_VARIANT_TYPE_OBJECT and the base class is extended by a script).
* @param p_value_type The type of Variant the Dictionary value will store.
* @param p_value_class_name A pointer to a StringName with the name of the object (if p_value_type is GDEXTENSION_VARIANT_TYPE_OBJECT).
* @param p_value_script A pointer to a Script object (if p_value_type is GDEXTENSION_VARIANT_TYPE_OBJECT and the base class is extended by a script).
*/
typedef void (*GDExtensionInterfaceDictionarySetTyped)(GDExtensionTypePtr p_self, GDExtensionVariantType p_key_type, GDExtensionConstStringNamePtr p_key_class_name, GDExtensionConstVariantPtr p_key_script, GDExtensionVariantType p_value_type, GDExtensionConstStringNamePtr p_value_class_name, GDExtensionConstVariantPtr p_value_script);
/* INTERFACE: Object */
/**
@ -2732,7 +2680,6 @@ typedef void *(*GDExtensionInterfaceCallableCustomGetUserData)(GDExtensionConstT
/**
* @name classdb_construct_object
* @since 4.1
* @deprecated in Godot 4.4. Use `classdb_construct_object2` instead.
*
* Constructs an Object of the requested class.
*
@ -2744,22 +2691,6 @@ typedef void *(*GDExtensionInterfaceCallableCustomGetUserData)(GDExtensionConstT
*/
typedef GDExtensionObjectPtr (*GDExtensionInterfaceClassdbConstructObject)(GDExtensionConstStringNamePtr p_classname);
/**
* @name classdb_construct_object2
* @since 4.4
*
* Constructs an Object of the requested class.
*
* The passed class must be a built-in godot class, or an already-registered extension class. In both cases, object_set_instance() should be called to fully initialize the object.
*
* "NOTIFICATION_POSTINITIALIZE" must be sent after construction.
*
* @param p_classname A pointer to a StringName with the class name.
*
* @return A pointer to the newly created Object.
*/
typedef GDExtensionObjectPtr (*GDExtensionInterfaceClassdbConstructObject2)(GDExtensionConstStringNamePtr p_classname);
/**
* @name classdb_get_method_bind
* @since 4.1
@ -2791,7 +2722,7 @@ typedef void *(*GDExtensionInterfaceClassdbGetClassTag)(GDExtensionConstStringNa
/**
* @name classdb_register_extension_class
* @since 4.1
* @deprecated in Godot 4.2. Use `classdb_register_extension_class4` instead.
* @deprecated in Godot 4.2. Use `classdb_register_extension_class3` instead.
*
* Registers an extension class in the ClassDB.
*
@ -2807,7 +2738,7 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass)(GDExtensionCla
/**
* @name classdb_register_extension_class2
* @since 4.2
* @deprecated in Godot 4.3. Use `classdb_register_extension_class4` instead.
* @deprecated in Godot 4.3. Use `classdb_register_extension_class3` instead.
*
* Registers an extension class in the ClassDB.
*
@ -2823,7 +2754,6 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass2)(GDExtensionCl
/**
* @name classdb_register_extension_class3
* @since 4.3
* @deprecated in Godot 4.4. Use `classdb_register_extension_class4` instead.
*
* Registers an extension class in the ClassDB.
*
@ -2836,21 +2766,6 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass2)(GDExtensionCl
*/
typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass3)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo3 *p_extension_funcs);
/**
* @name classdb_register_extension_class4
* @since 4.4
*
* Registers an extension class in the ClassDB.
*
* Provided struct can be safely freed once the function returns.
*
* @param p_library A pointer the library received by the GDExtension's entry point function.
* @param p_class_name A pointer to a StringName with the class name.
* @param p_parent_class_name A pointer to a StringName with the parent class name.
* @param p_extension_funcs A pointer to a GDExtensionClassCreationInfo2 struct.
*/
typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass4)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo4 *p_extension_funcs);
/**
* @name classdb_register_extension_class_method
* @since 4.1

View File

@ -1,390 +0,0 @@
/**************************************************************************/
/* gdextension_library_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_library_loader.h"
#include "core/config/project_settings.h"
#include "core/io/dir_access.h"
#include "core/version.h"
#include "gdextension.h"
Vector<SharedObject> GDExtensionLibraryLoader::find_extension_dependencies(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature) {
Vector<SharedObject> dependencies_shared_objects;
if (p_config->has_section("dependencies")) {
List<String> config_dependencies;
p_config->get_section_keys("dependencies", &config_dependencies);
for (const String &dependency : config_dependencies) {
Vector<String> dependency_tags = dependency.split(".");
bool all_tags_met = true;
for (int i = 0; i < dependency_tags.size(); i++) {
String tag = dependency_tags[i].strip_edges();
if (!p_has_feature(tag)) {
all_tags_met = false;
break;
}
}
if (all_tags_met) {
Dictionary dependency_value = p_config->get_value("dependencies", dependency);
for (const Variant *key = dependency_value.next(nullptr); key; key = dependency_value.next(key)) {
String dependency_path = *key;
String target_path = dependency_value[*key];
if (dependency_path.is_relative_path()) {
dependency_path = p_path.get_base_dir().path_join(dependency_path);
}
dependencies_shared_objects.push_back(SharedObject(dependency_path, dependency_tags, target_path));
}
break;
}
}
}
return dependencies_shared_objects;
}
String GDExtensionLibraryLoader::find_extension_library(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature, PackedStringArray *r_tags) {
// First, check the explicit libraries.
if (p_config->has_section("libraries")) {
List<String> libraries;
p_config->get_section_keys("libraries", &libraries);
// Iterate the libraries, finding the best matching tags.
String best_library_path;
Vector<String> best_library_tags;
for (const String &E : libraries) {
Vector<String> tags = E.split(".");
bool all_tags_met = true;
for (int i = 0; i < tags.size(); i++) {
String tag = tags[i].strip_edges();
if (!p_has_feature(tag)) {
all_tags_met = false;
break;
}
}
if (all_tags_met && tags.size() > best_library_tags.size()) {
best_library_path = p_config->get_value("libraries", E);
best_library_tags = tags;
}
}
if (!best_library_path.is_empty()) {
if (best_library_path.is_relative_path()) {
best_library_path = p_path.get_base_dir().path_join(best_library_path);
}
if (r_tags != nullptr) {
r_tags->append_array(best_library_tags);
}
return best_library_path;
}
}
// Second, try to autodetect.
String autodetect_library_prefix;
if (p_config->has_section_key("configuration", "autodetect_library_prefix")) {
autodetect_library_prefix = p_config->get_value("configuration", "autodetect_library_prefix");
}
if (!autodetect_library_prefix.is_empty()) {
String autodetect_path = autodetect_library_prefix;
if (autodetect_path.is_relative_path()) {
autodetect_path = p_path.get_base_dir().path_join(autodetect_path);
}
// Find the folder and file parts of the prefix.
String folder;
String file_prefix;
if (DirAccess::dir_exists_absolute(autodetect_path)) {
folder = autodetect_path;
} else if (DirAccess::dir_exists_absolute(autodetect_path.get_base_dir())) {
folder = autodetect_path.get_base_dir();
file_prefix = autodetect_path.get_file();
} else {
ERR_FAIL_V_MSG(String(), vformat("Error in extension: %s. Could not find folder for automatic detection of libraries files. autodetect_library_prefix=\"%s\"", p_path, autodetect_library_prefix));
}
// Open the folder.
Ref<DirAccess> dir = DirAccess::open(folder);
ERR_FAIL_COND_V_MSG(dir.is_null(), String(), vformat("Error in extension: %s. Could not open folder for automatic detection of libraries files. autodetect_library_prefix=\"%s\"", p_path, autodetect_library_prefix));
// Iterate the files and check the prefixes, finding the best matching file.
String best_file;
Vector<String> best_file_tags;
dir->list_dir_begin();
String file_name = dir->_get_next();
while (file_name != "") {
if (!dir->current_is_dir() && file_name.begins_with(file_prefix)) {
// Check if the files matches all requested feature tags.
String tags_str = file_name.trim_prefix(file_prefix);
tags_str = tags_str.trim_suffix(tags_str.get_extension());
Vector<String> tags = tags_str.split(".", false);
bool all_tags_met = true;
for (int i = 0; i < tags.size(); i++) {
String tag = tags[i].strip_edges();
if (!p_has_feature(tag)) {
all_tags_met = false;
break;
}
}
// If all tags are found in the feature list, and we found more tags than before, use this file.
if (all_tags_met && tags.size() > best_file_tags.size()) {
best_file_tags = tags;
best_file = file_name;
}
}
file_name = dir->_get_next();
}
if (!best_file.is_empty()) {
String library_path = folder.path_join(best_file);
if (r_tags != nullptr) {
r_tags->append_array(best_file_tags);
}
return library_path;
}
}
return String();
}
Error GDExtensionLibraryLoader::open_library(const String &p_path) {
Error err = parse_gdextension_file(p_path);
if (err != OK) {
return err;
}
String abs_path = ProjectSettings::get_singleton()->globalize_path(library_path);
Vector<String> abs_dependencies_paths;
if (!library_dependencies.is_empty()) {
for (const SharedObject &dependency : library_dependencies) {
abs_dependencies_paths.push_back(ProjectSettings::get_singleton()->globalize_path(dependency.path));
}
}
OS::GDExtensionData data = {
true, // also_set_library_path
&library_path, // r_resolved_path
Engine::get_singleton()->is_editor_hint(), // generate_temp_files
&abs_dependencies_paths, // library_dependencies
};
err = OS::get_singleton()->open_dynamic_library(is_static_library ? String() : abs_path, library, &data);
if (err != OK) {
return err;
}
return OK;
}
Error GDExtensionLibraryLoader::initialize(GDExtensionInterfaceGetProcAddress p_get_proc_address, const Ref<GDExtension> &p_extension, GDExtensionInitialization *r_initialization) {
#ifdef TOOLS_ENABLED
p_extension->set_reloadable(is_reloadable && Engine::get_singleton()->is_extension_reloading_enabled());
#endif
for (const KeyValue<String, String> &icon : class_icon_paths) {
p_extension->class_icon_paths[icon.key] = icon.value;
}
void *entry_funcptr = nullptr;
Error err = OS::get_singleton()->get_dynamic_library_symbol_handle(library, entry_symbol, entry_funcptr, false);
if (err != OK) {
ERR_PRINT("GDExtension entry point '" + entry_symbol + "' not found in library " + library_path);
return err;
}
GDExtensionInitializationFunction initialization_function = (GDExtensionInitializationFunction)entry_funcptr;
GDExtensionBool ret = initialization_function(p_get_proc_address, p_extension.ptr(), r_initialization);
if (ret) {
return OK;
} else {
ERR_PRINT("GDExtension initialization function '" + entry_symbol + "' returned an error.");
return FAILED;
}
}
void GDExtensionLibraryLoader::close_library() {
OS::get_singleton()->close_dynamic_library(library);
library = nullptr;
}
bool GDExtensionLibraryLoader::is_library_open() const {
return library != nullptr;
}
bool GDExtensionLibraryLoader::has_library_changed() const {
#ifdef TOOLS_ENABLED
// Check only that the last modified time is different (rather than checking
// that it's newer) since some OS's (namely Windows) will preserve the modified
// time by default when copying files.
if (FileAccess::get_modified_time(resource_path) != resource_last_modified_time) {
return true;
}
if (FileAccess::get_modified_time(library_path) != library_last_modified_time) {
return true;
}
#endif
return false;
}
Error GDExtensionLibraryLoader::parse_gdextension_file(const String &p_path) {
resource_path = p_path;
Ref<ConfigFile> config;
config.instantiate();
Error err = config->load(p_path);
if (err != OK) {
ERR_PRINT("Error loading GDExtension configuration file: " + p_path);
return err;
}
if (!config->has_section_key("configuration", "entry_symbol")) {
ERR_PRINT("GDExtension configuration file must contain a \"configuration/entry_symbol\" key: " + p_path);
return ERR_INVALID_DATA;
}
entry_symbol = config->get_value("configuration", "entry_symbol");
uint32_t compatibility_minimum[3] = { 0, 0, 0 };
if (config->has_section_key("configuration", "compatibility_minimum")) {
String compat_string = config->get_value("configuration", "compatibility_minimum");
Vector<int> parts = compat_string.split_ints(".");
for (int i = 0; i < parts.size(); i++) {
if (i >= 3) {
break;
}
if (parts[i] >= 0) {
compatibility_minimum[i] = parts[i];
}
}
} else {
ERR_PRINT("GDExtension configuration file must contain a \"configuration/compatibility_minimum\" key: " + p_path);
return ERR_INVALID_DATA;
}
if (compatibility_minimum[0] < 4 || (compatibility_minimum[0] == 4 && compatibility_minimum[1] == 0)) {
ERR_PRINT(vformat("GDExtension's compatibility_minimum (%d.%d.%d) must be at least 4.1.0: %s", compatibility_minimum[0], compatibility_minimum[1], compatibility_minimum[2], p_path));
return ERR_INVALID_DATA;
}
bool compatible = true;
// Check version lexicographically.
if (VERSION_MAJOR != compatibility_minimum[0]) {
compatible = VERSION_MAJOR > compatibility_minimum[0];
} else if (VERSION_MINOR != compatibility_minimum[1]) {
compatible = VERSION_MINOR > compatibility_minimum[1];
} else {
compatible = VERSION_PATCH >= compatibility_minimum[2];
}
if (!compatible) {
ERR_PRINT(vformat("GDExtension only compatible with Godot version %d.%d.%d or later: %s", compatibility_minimum[0], compatibility_minimum[1], compatibility_minimum[2], p_path));
return ERR_INVALID_DATA;
}
// Optionally check maximum compatibility.
if (config->has_section_key("configuration", "compatibility_maximum")) {
uint32_t compatibility_maximum[3] = { 0, 0, 0 };
String compat_string = config->get_value("configuration", "compatibility_maximum");
Vector<int> parts = compat_string.split_ints(".");
for (int i = 0; i < 3; i++) {
if (i < parts.size() && parts[i] >= 0) {
compatibility_maximum[i] = parts[i];
} else {
// If a version part is missing, set the maximum to an arbitrary high value.
compatibility_maximum[i] = 9999;
}
}
compatible = true;
if (VERSION_MAJOR != compatibility_maximum[0]) {
compatible = VERSION_MAJOR < compatibility_maximum[0];
} else if (VERSION_MINOR != compatibility_maximum[1]) {
compatible = VERSION_MINOR < compatibility_maximum[1];
}
#if VERSION_PATCH
// #if check to avoid -Wtype-limits warning when 0.
else {
compatible = VERSION_PATCH <= compatibility_maximum[2];
}
#endif
if (!compatible) {
ERR_PRINT(vformat("GDExtension only compatible with Godot version %s or earlier: %s", compat_string, p_path));
return ERR_INVALID_DATA;
}
}
library_path = find_extension_library(p_path, config, [](const String &p_feature) { return OS::get_singleton()->has_feature(p_feature); });
if (library_path.is_empty()) {
const String os_arch = OS::get_singleton()->get_name().to_lower() + "." + Engine::get_singleton()->get_architecture_name();
ERR_PRINT(vformat("No GDExtension library found for current OS and architecture (%s) in configuration file: %s", os_arch, p_path));
return ERR_FILE_NOT_FOUND;
}
is_static_library = library_path.ends_with(".a") || library_path.ends_with(".xcframework");
if (!library_path.is_resource_file() && !library_path.is_absolute_path()) {
library_path = p_path.get_base_dir().path_join(library_path);
}
#ifdef TOOLS_ENABLED
is_reloadable = config->get_value("configuration", "reloadable", false);
update_last_modified_time(
FileAccess::get_modified_time(resource_path),
FileAccess::get_modified_time(library_path));
#endif
library_dependencies = find_extension_dependencies(p_path, config, [](const String &p_feature) { return OS::get_singleton()->has_feature(p_feature); });
// Handle icons if any are specified.
if (config->has_section("icons")) {
List<String> keys;
config->get_section_keys("icons", &keys);
for (const String &key : keys) {
String icon_path = config->get_value("icons", key);
if (icon_path.is_relative_path()) {
icon_path = p_path.get_base_dir().path_join(icon_path);
}
class_icon_paths[key] = icon_path;
}
}
return OK;
}

View File

@ -1,84 +0,0 @@
/**************************************************************************/
/* gdextension_library_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. */
/**************************************************************************/
#ifndef GDEXTENSION_LIBRARY_LOADER_H
#define GDEXTENSION_LIBRARY_LOADER_H
#include <functional>
#include "core/extension/gdextension_loader.h"
#include "core/io/config_file.h"
#include "core/os/shared_object.h"
class GDExtensionLibraryLoader : public GDExtensionLoader {
friend class GDExtensionManager;
friend class GDExtension;
private:
String resource_path;
void *library = nullptr; // pointer if valid.
String library_path;
String entry_symbol;
bool is_static_library = false;
#ifdef TOOLS_ENABLED
bool is_reloadable = false;
#endif
Vector<SharedObject> library_dependencies;
HashMap<String, String> class_icon_paths;
#ifdef TOOLS_ENABLED
uint64_t resource_last_modified_time = 0;
uint64_t library_last_modified_time = 0;
void update_last_modified_time(uint64_t p_resource_last_modified_time, uint64_t p_library_last_modified_time) {
resource_last_modified_time = p_resource_last_modified_time;
library_last_modified_time = p_library_last_modified_time;
}
#endif
public:
static String find_extension_library(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature, PackedStringArray *r_tags = nullptr);
static Vector<SharedObject> find_extension_dependencies(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature);
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;
Error parse_gdextension_file(const String &p_path);
};
#endif // GDEXTENSION_LIBRARY_LOADER_H

View File

@ -1,47 +0,0 @@
/**************************************************************************/
/* gdextension_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. */
/**************************************************************************/
#ifndef GDEXTENSION_LOADER_H
#define GDEXTENSION_LOADER_H
#include "core/object/ref_counted.h"
class GDExtension;
class GDExtensionLoader : public RefCounted {
public:
virtual Error open_library(const String &p_path) = 0;
virtual Error initialize(GDExtensionInterfaceGetProcAddress p_get_proc_address, const Ref<GDExtension> &p_extension, GDExtensionInitialization *r_initialization) = 0;
virtual void close_library() = 0;
virtual bool is_library_open() const = 0;
virtual bool has_library_changed() const = 0;
};
#endif // GDEXTENSION_LOADER_H

View File

@ -31,19 +31,14 @@
#include "gdextension_manager.h"
#include "core/extension/gdextension_compat_hashes.h"
#include "core/extension/gdextension_library_loader.h"
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
#include "core/object/script_language.h"
GDExtensionManager::LoadStatus GDExtensionManager::_load_extension_internal(const Ref<GDExtension> &p_extension, bool p_first_load) {
GDExtensionManager::LoadStatus GDExtensionManager::_load_extension_internal(const Ref<GDExtension> &p_extension) {
if (level >= 0) { // Already initialized up to some level.
int32_t minimum_level = 0;
if (!p_first_load) {
minimum_level = p_extension->get_minimum_library_initialization_level();
if (minimum_level < MIN(level, GDExtension::INITIALIZATION_LEVEL_SCENE)) {
return LOAD_STATUS_NEEDS_RESTART;
}
int32_t minimum_level = p_extension->get_minimum_library_initialization_level();
if (minimum_level < MIN(level, GDExtension::INITIALIZATION_LEVEL_SCENE)) {
return LOAD_STATUS_NEEDS_RESTART;
}
// Initialize up to current level.
for (int32_t i = minimum_level; i <= level; i++) {
@ -55,20 +50,10 @@ GDExtensionManager::LoadStatus GDExtensionManager::_load_extension_internal(cons
gdextension_class_icon_paths[kv.key] = kv.value;
}
#ifdef TOOLS_ENABLED
// Signals that a new extension is loaded so GDScript can register new class names.
emit_signal("extension_loaded", p_extension);
#endif
return LOAD_STATUS_OK;
}
GDExtensionManager::LoadStatus GDExtensionManager::_unload_extension_internal(const Ref<GDExtension> &p_extension) {
#ifdef TOOLS_ENABLED
// Signals that a new extension is unloading so GDScript can unregister class names.
emit_signal("extension_unloading", p_extension);
#endif
if (level >= 0) { // Already initialized up to some level.
// Deinitialize down from current level.
for (int32_t i = level; i >= GDExtension::INITIALIZATION_LEVEL_CORE; i--) {
@ -84,31 +69,19 @@ GDExtensionManager::LoadStatus GDExtensionManager::_unload_extension_internal(co
}
GDExtensionManager::LoadStatus GDExtensionManager::load_extension(const String &p_path) {
Ref<GDExtensionLibraryLoader> loader;
loader.instantiate();
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) {
DEV_ASSERT(p_loader.is_valid());
if (gdextension_map.has(p_path)) {
return LOAD_STATUS_ALREADY_LOADED;
}
Ref<GDExtension> extension;
extension.instantiate();
Error err = extension->open_library(p_path, p_loader);
if (err != OK) {
Ref<GDExtension> extension = ResourceLoader::load(p_path);
if (extension.is_null()) {
return LOAD_STATUS_FAILED;
}
LoadStatus status = _load_extension_internal(extension, true);
LoadStatus status = _load_extension_internal(extension);
if (status != LOAD_STATUS_OK) {
return status;
}
extension->set_path(p_path);
gdextension_map[p_path] = extension;
return LOAD_STATUS_OK;
}
@ -144,12 +117,12 @@ GDExtensionManager::LoadStatus GDExtensionManager::reload_extension(const String
extension->close_library();
}
Error err = extension->open_library(p_path, extension->loader);
Error err = GDExtensionResourceLoader::load_gdextension_resource(p_path, extension);
if (err != OK) {
return LOAD_STATUS_FAILED;
}
status = _load_extension_internal(extension, false);
status = _load_extension_internal(extension);
if (status != LOAD_STATUS_OK) {
return status;
}
@ -288,71 +261,6 @@ void GDExtensionManager::reload_extensions() {
#endif
}
bool GDExtensionManager::ensure_extensions_loaded(const HashSet<String> &p_extensions) {
Vector<String> extensions_added;
Vector<String> extensions_removed;
for (const String &E : p_extensions) {
if (!is_extension_loaded(E)) {
extensions_added.push_back(E);
}
}
Vector<String> loaded_extensions = get_loaded_extensions();
for (const String &loaded_extension : loaded_extensions) {
if (!p_extensions.has(loaded_extension)) {
// The extension may not have a .gdextension file.
if (!FileAccess::exists(loaded_extension)) {
extensions_removed.push_back(loaded_extension);
}
}
}
String extension_list_config_file = GDExtension::get_extension_list_config_file();
if (p_extensions.size()) {
if (extensions_added.size() || extensions_removed.size()) {
// Extensions were added or removed.
Ref<FileAccess> f = FileAccess::open(extension_list_config_file, FileAccess::WRITE);
for (const String &E : p_extensions) {
f->store_line(E);
}
}
} else {
if (loaded_extensions.size() || FileAccess::exists(extension_list_config_file)) {
// Extensions were removed.
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
da->remove(extension_list_config_file);
}
}
bool needs_restart = false;
for (const String &extension : extensions_added) {
GDExtensionManager::LoadStatus st = GDExtensionManager::get_singleton()->load_extension(extension);
if (st == GDExtensionManager::LOAD_STATUS_NEEDS_RESTART) {
needs_restart = true;
}
}
for (const String &extension : extensions_removed) {
GDExtensionManager::LoadStatus st = GDExtensionManager::get_singleton()->unload_extension(extension);
if (st == GDExtensionManager::LOAD_STATUS_NEEDS_RESTART) {
needs_restart = true;
}
}
#ifdef TOOLS_ENABLED
if (extensions_added.size() || extensions_removed.size()) {
// Emitting extensions_reloaded so EditorNode can reload Inspector and regenerate documentation.
emit_signal("extensions_reloaded");
// Reload all scripts to clear out old references.
callable_mp_static(&GDExtensionManager::_reload_all_scripts).call_deferred();
}
#endif
return needs_restart;
}
GDExtensionManager *GDExtensionManager::get_singleton() {
return singleton;
}
@ -373,8 +281,6 @@ void GDExtensionManager::_bind_methods() {
BIND_ENUM_CONSTANT(LOAD_STATUS_NEEDS_RESTART);
ADD_SIGNAL(MethodInfo("extensions_reloaded"));
ADD_SIGNAL(MethodInfo("extension_loaded", PropertyInfo(Variant::OBJECT, "extension", PROPERTY_HINT_RESOURCE_TYPE, "GDExtension")));
ADD_SIGNAL(MethodInfo("extension_unloading", PropertyInfo(Variant::OBJECT, "extension", PROPERTY_HINT_RESOURCE_TYPE, "GDExtension")));
}
GDExtensionManager *GDExtensionManager::singleton = nullptr;

View File

@ -54,7 +54,7 @@ public:
};
private:
LoadStatus _load_extension_internal(const Ref<GDExtension> &p_extension, bool p_first_load);
LoadStatus _load_extension_internal(const Ref<GDExtension> &p_extension);
LoadStatus _unload_extension_internal(const Ref<GDExtension> &p_extension);
#ifdef TOOLS_ENABLED
@ -63,7 +63,6 @@ private:
public:
LoadStatus load_extension(const String &p_path);
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);
bool is_extension_loaded(const String &p_path) const;
@ -85,7 +84,6 @@ public:
void load_extensions();
void reload_extensions();
bool ensure_extensions_loaded(const HashSet<String> &p_extensions);
GDExtensionManager();
~GDExtensionManager();

View File

@ -55,10 +55,10 @@ def generate_mod_version(argcount, const=False, returns=False):
proto_ex = """
#define EXBIND$VER($RETTYPE m_name$ARG) \\
GDVIRTUAL$VER_REQUIRED($RETTYPE_##m_name$ARG)\\
GDVIRTUAL$VER($RETTYPE_##m_name$ARG)\\
virtual $RETVAL m_name($FUNCARGS) $CONST override { \\
$RETPRE\\
GDVIRTUAL_CALL(_##m_name$CALLARGS$RETREF);\\
GDVIRTUAL_REQUIRED_CALL(_##m_name$CALLARGS$RETREF);\\
$RETPOST\\
}
"""

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")

View File

@ -513,49 +513,21 @@ void Input::joy_connection_changed(int p_idx, bool p_connected, const String &p_
Vector3 Input::get_gravity() const {
_THREAD_SAFE_METHOD_
#ifdef DEBUG_ENABLED
if (!gravity_enabled) {
WARN_PRINT_ONCE("`input_devices/sensors/enable_gravity` is not enabled in project settings.");
}
#endif
return gravity;
}
Vector3 Input::get_accelerometer() const {
_THREAD_SAFE_METHOD_
#ifdef DEBUG_ENABLED
if (!accelerometer_enabled) {
WARN_PRINT_ONCE("`input_devices/sensors/enable_accelerometer` is not enabled in project settings.");
}
#endif
return accelerometer;
}
Vector3 Input::get_magnetometer() const {
_THREAD_SAFE_METHOD_
#ifdef DEBUG_ENABLED
if (!magnetometer_enabled) {
WARN_PRINT_ONCE("`input_devices/sensors/enable_magnetometer` is not enabled in project settings.");
}
#endif
return magnetometer;
}
Vector3 Input::get_gyroscope() const {
_THREAD_SAFE_METHOD_
#ifdef DEBUG_ENABLED
if (!gyroscope_enabled) {
WARN_PRINT_ONCE("`input_devices/sensors/enable_gyroscope` is not enabled in project settings.");
}
#endif
return gyroscope;
}
@ -1711,11 +1683,6 @@ Input::Input() {
// Always use standard behavior in the editor.
legacy_just_pressed_behavior = false;
}
accelerometer_enabled = GLOBAL_DEF_RST_BASIC("input_devices/sensors/enable_accelerometer", false);
gravity_enabled = GLOBAL_DEF_RST_BASIC("input_devices/sensors/enable_gravity", false);
gyroscope_enabled = GLOBAL_DEF_RST_BASIC("input_devices/sensors/enable_gyroscope", false);
magnetometer_enabled = GLOBAL_DEF_RST_BASIC("input_devices/sensors/enable_magnetometer", false);
}
Input::~Input() {

View File

@ -92,13 +92,9 @@ private:
RBSet<JoyButton> joy_buttons_pressed;
RBMap<JoyAxis, float> _joy_axis;
//RBMap<StringName,int> custom_action_press;
bool gravity_enabled = false;
Vector3 gravity;
bool accelerometer_enabled = false;
Vector3 accelerometer;
bool magnetometer_enabled = false;
Vector3 magnetometer;
bool gyroscope_enabled = false;
Vector3 gyroscope;
Vector2 mouse_pos;
int64_t mouse_window = 0;

View File

@ -33,7 +33,7 @@ def make_default_controller_mappings(target, source, env):
guid = line_parts[0]
if guid in platform_mappings[current_platform]:
g.write(
"// WARNING: DATABASE {} OVERWROTE PRIOR MAPPING: {} {}\n".format(
"// WARNING - DATABASE {} OVERWROTE PRIOR MAPPING: {} {}\n".format(
src_path, current_platform, platform_mappings[current_platform][guid]
)
)

View File

@ -1088,7 +1088,7 @@ void InputEventMouseMotion::_bind_methods() {
///////////////////////////////////
void InputEventJoypadMotion::set_axis(JoyAxis p_axis) {
ERR_FAIL_COND(p_axis < JoyAxis::INVALID || p_axis > JoyAxis::MAX);
ERR_FAIL_COND(p_axis < JoyAxis::LEFT_X || p_axis > JoyAxis::MAX);
axis = p_axis;
emit_changed();

View File

@ -400,7 +400,6 @@ static const _BuiltinActionDisplayName _builtin_action_display_names[] = {
{ "ui_filedialog_refresh", TTRC("Refresh") },
{ "ui_filedialog_show_hidden", TTRC("Show Hidden") },
{ "ui_swap_input_direction ", TTRC("Swap Input Direction") },
{ "ui_unicode_start", TTRC("Start Unicode Character Input") },
{ "", ""}
/* clang-format on */
};
@ -755,10 +754,6 @@ const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
inputs.push_back(InputEventKey::create_reference(Key::KP_ENTER));
default_builtin_cache.insert("ui_text_submit", inputs);
inputs = List<Ref<InputEvent>>();
inputs.push_back(InputEventKey::create_reference(Key::U | KeyModifierMask::CTRL | KeyModifierMask::SHIFT));
default_builtin_cache.insert("ui_unicode_start", inputs);
// ///// UI Graph Shortcuts /////
inputs = List<Ref<InputEvent>>();

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")

View File

@ -33,12 +33,12 @@
#include "core/config/project_settings.h"
#include "core/io/file_access.h"
DTLSServer *(*DTLSServer::_create)(bool p_notify_postinitialize) = nullptr;
DTLSServer *(*DTLSServer::_create)() = nullptr;
bool DTLSServer::available = false;
DTLSServer *DTLSServer::create(bool p_notify_postinitialize) {
DTLSServer *DTLSServer::create() {
if (_create) {
return _create(p_notify_postinitialize);
return _create();
}
return nullptr;
}

View File

@ -38,14 +38,14 @@ class DTLSServer : public RefCounted {
GDCLASS(DTLSServer, RefCounted);
protected:
static DTLSServer *(*_create)(bool p_notify_postinitialize);
static DTLSServer *(*_create)();
static void _bind_methods();
static bool available;
public:
static bool is_available();
static DTLSServer *create(bool p_notify_postinitialize = true);
static DTLSServer *create();
virtual Error setup(Ref<TLSOptions> p_options) = 0;
virtual void stop() = 0;

View File

@ -59,9 +59,11 @@ bool FileAccess::exists(const String &p_name) {
return true;
}
// Using file_exists because it's faster than trying to open the file.
Ref<FileAccess> ret = create_for_path(p_name);
return ret->file_exists(p_name);
Ref<FileAccess> f = open(p_name, READ);
if (f.is_null()) {
return false;
}
return true;
}
void FileAccess::_set_access_type(AccessType p_access) {
@ -223,44 +225,59 @@ String FileAccess::fix_path(const String &p_path) const {
}
/* these are all implemented for ease of porting, then can later be optimized */
uint8_t FileAccess::get_8() const {
uint8_t data = 0;
get_buffer(&data, sizeof(uint8_t));
return data;
}
uint16_t FileAccess::get_16() const {
uint16_t data = 0;
get_buffer(reinterpret_cast<uint8_t *>(&data), sizeof(uint16_t));
uint16_t res;
uint8_t a, b;
a = get_8();
b = get_8();
if (big_endian) {
data = BSWAP16(data);
SWAP(a, b);
}
return data;
res = b;
res <<= 8;
res |= a;
return res;
}
uint32_t FileAccess::get_32() const {
uint32_t data = 0;
get_buffer(reinterpret_cast<uint8_t *>(&data), sizeof(uint32_t));
uint32_t res;
uint16_t a, b;
a = get_16();
b = get_16();
if (big_endian) {
data = BSWAP32(data);
SWAP(a, b);
}
return data;
res = b;
res <<= 16;
res |= a;
return res;
}
uint64_t FileAccess::get_64() const {
uint64_t data = 0;
get_buffer(reinterpret_cast<uint8_t *>(&data), sizeof(uint64_t));
uint64_t res;
uint32_t a, b;
a = get_32();
b = get_32();
if (big_endian) {
data = BSWAP64(data);
SWAP(a, b);
}
return data;
res = b;
res <<= 32;
res |= a;
return res;
}
float FileAccess::get_float() const {
@ -450,6 +467,17 @@ String FileAccess::get_as_text(bool p_skip_cr) const {
return text;
}
uint64_t FileAccess::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
uint64_t i = 0;
for (i = 0; i < p_length && !eof_reached(); i++) {
p_dst[i] = get_8();
}
return i;
}
Vector<uint8_t> FileAccess::get_buffer(int64_t p_length) const {
Vector<uint8_t> data;
@ -462,7 +490,7 @@ Vector<uint8_t> FileAccess::get_buffer(int64_t p_length) const {
ERR_FAIL_COND_V_MSG(err != OK, data, "Can't resize data to " + itos(p_length) + " elements.");
uint8_t *w = data.ptrw();
int64_t len = get_buffer(w, p_length);
int64_t len = get_buffer(&w[0], p_length);
if (len < p_length) {
data.resize(len);
@ -486,32 +514,46 @@ String FileAccess::get_as_utf8_string(bool p_skip_cr) const {
return s;
}
void FileAccess::store_8(uint8_t p_dest) {
store_buffer(&p_dest, sizeof(uint8_t));
}
void FileAccess::store_16(uint16_t p_dest) {
uint8_t a, b;
a = p_dest & 0xFF;
b = p_dest >> 8;
if (big_endian) {
p_dest = BSWAP16(p_dest);
SWAP(a, b);
}
store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint16_t));
store_8(a);
store_8(b);
}
void FileAccess::store_32(uint32_t p_dest) {
uint16_t a, b;
a = p_dest & 0xFFFF;
b = p_dest >> 16;
if (big_endian) {
p_dest = BSWAP32(p_dest);
SWAP(a, b);
}
store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint32_t));
store_16(a);
store_16(b);
}
void FileAccess::store_64(uint64_t p_dest) {
uint32_t a, b;
a = p_dest & 0xFFFFFFFF;
b = p_dest >> 32;
if (big_endian) {
p_dest = BSWAP64(p_dest);
SWAP(a, b);
}
store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint64_t));
store_32(a);
store_32(b);
}
void FileAccess::store_real(real_t p_real) {
@ -668,11 +710,22 @@ void FileAccess::store_csv_line(const Vector<String> &p_values, const String &p_
store_line(line);
}
void FileAccess::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND(!p_src && p_length > 0);
for (uint64_t i = 0; i < p_length; i++) {
store_8(p_src[i]);
}
}
void FileAccess::store_buffer(const Vector<uint8_t> &p_buffer) {
uint64_t len = p_buffer.size();
if (len == 0) {
return;
}
const uint8_t *r = p_buffer.ptr();
store_buffer(r, len);
store_buffer(&r[0], len);
}
void FileAccess::store_var(const Variant &p_var, bool p_full_objects) {

View File

@ -137,7 +137,7 @@ public:
virtual bool eof_reached() const = 0; ///< reading passed EOF
virtual uint8_t get_8() const; ///< get a byte
virtual uint8_t get_8() const = 0; ///< get a byte
virtual uint16_t get_16() const; ///< get 16 bits uint
virtual uint32_t get_32() const; ///< get 32 bits uint
virtual uint64_t get_64() const; ///< get 64 bits uint
@ -148,7 +148,7 @@ public:
Variant get_var(bool p_allow_objects = false) const;
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const = 0; ///< get an array of bytes, needs to be overwritten by children.
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; ///< get an array of bytes
Vector<uint8_t> get_buffer(int64_t p_length) const;
virtual String get_line() const;
virtual String get_token() const;
@ -168,7 +168,7 @@ public:
virtual Error resize(int64_t p_length) = 0;
virtual void flush() = 0;
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual void store_8(uint8_t p_dest) = 0; ///< store a byte
virtual void store_16(uint16_t p_dest); ///< store 16 bits uint
virtual void store_32(uint32_t p_dest); ///< store 32 bits uint
virtual void store_64(uint64_t p_dest); ///< store 64 bits uint
@ -184,7 +184,7 @@ public:
virtual void store_pascal_string(const String &p_string);
virtual String get_pascal_string();
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) = 0; ///< store an array of bytes, needs to be overwritten by children.
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes
void store_buffer(const Vector<uint8_t> &p_buffer);
void store_var(const Variant &p_var, bool p_full_objects = false);

View File

@ -260,6 +260,38 @@ bool FileAccessCompressed::eof_reached() const {
}
}
uint8_t FileAccessCompressed::get_8() const {
ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use.");
ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode.");
if (at_end) {
read_eof = true;
return 0;
}
uint8_t ret = read_ptr[read_pos];
read_pos++;
if (read_pos >= read_block_size) {
read_block++;
if (read_block < read_block_count) {
//read another block of compressed data
f->get_buffer(comp_buffer.ptrw(), read_blocks[read_block].csize);
int total = Compression::decompress(buffer.ptrw(), read_blocks.size() == 1 ? read_total : block_size, comp_buffer.ptr(), read_blocks[read_block].csize, cmode);
ERR_FAIL_COND_V_MSG(total == -1, 0, "Compressed file is corrupt.");
read_block_size = read_block == read_block_count - 1 ? read_total % block_size : block_size;
read_pos = 0;
} else {
read_block--;
at_end = true;
}
}
return ret;
}
uint64_t FileAccessCompressed::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
ERR_FAIL_COND_V_MSG(f.is_null(), -1, "File must be opened before use.");
@ -309,13 +341,12 @@ void FileAccessCompressed::flush() {
// compressed files keep data in memory till close()
}
void FileAccessCompressed::store_buffer(const uint8_t *p_src, uint64_t p_length) {
void FileAccessCompressed::store_8(uint8_t p_dest) {
ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use.");
ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode.");
WRITE_FIT(p_length);
memcpy(write_ptr + write_pos, p_src, p_length);
write_pos += p_length;
WRITE_FIT(1);
write_ptr[write_pos++] = p_dest;
}
bool FileAccessCompressed::file_exists(const String &p_name) {

View File

@ -83,13 +83,14 @@ public:
virtual bool eof_reached() const override; ///< reading passed EOF
virtual uint8_t get_8() const override; ///< get a byte
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
virtual Error get_error() const override; ///< get last error
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
virtual void flush() override;
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual void store_8(uint8_t p_dest) override; ///< store a byte
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists

View File

@ -37,7 +37,7 @@
#include <stdio.h>
Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic) {
ERR_FAIL_COND_V_MSG(file.is_valid(), ERR_ALREADY_IN_USE, "Can't open file while another file from path '" + file->get_path_absolute() + "' is open.");
ERR_FAIL_COND_V_MSG(file != nullptr, ERR_ALREADY_IN_USE, "Can't open file while another file from path '" + file->get_path_absolute() + "' is open.");
ERR_FAIL_COND_V(p_key.size() != 32, ERR_INVALID_PARAMETER);
pos = 0;
@ -162,7 +162,7 @@ void FileAccessEncrypted::_close() {
}
bool FileAccessEncrypted::is_open() const {
return file.is_valid();
return file != nullptr;
}
String FileAccessEncrypted::get_path() const {
@ -206,13 +206,26 @@ bool FileAccessEncrypted::eof_reached() const {
return eofed;
}
uint8_t FileAccessEncrypted::get_8() const {
ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode.");
if (pos >= get_length()) {
eofed = true;
return 0;
}
uint8_t b = data[pos];
pos++;
return b;
}
uint64_t FileAccessEncrypted::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
ERR_FAIL_COND_V_MSG(writing, -1, "File has not been opened in read mode.");
uint64_t to_copy = MIN(p_length, get_length() - pos);
memcpy(p_dst, data.ptr() + pos, to_copy);
pos += to_copy;
for (uint64_t i = 0; i < to_copy; i++) {
p_dst[i] = data[pos++];
}
if (to_copy < p_length) {
eofed = true;
@ -229,12 +242,17 @@ void FileAccessEncrypted::store_buffer(const uint8_t *p_src, uint64_t p_length)
ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode.");
ERR_FAIL_COND(!p_src && p_length > 0);
if (pos + p_length >= get_length()) {
if (pos < get_length()) {
for (uint64_t i = 0; i < p_length; i++) {
store_8(p_src[i]);
}
} else if (pos == get_length()) {
data.resize(pos + p_length);
for (uint64_t i = 0; i < p_length; i++) {
data.write[pos + i] = p_src[i];
}
pos += p_length;
}
memcpy(data.ptrw() + pos, p_src, p_length);
pos += p_length;
}
void FileAccessEncrypted::flush() {
@ -243,6 +261,18 @@ void FileAccessEncrypted::flush() {
// encrypted files keep data in memory till close()
}
void FileAccessEncrypted::store_8(uint8_t p_dest) {
ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode.");
if (pos < get_length()) {
data.write[pos] = p_dest;
pos++;
} else if (pos == get_length()) {
data.push_back(p_dest);
pos++;
}
}
bool FileAccessEncrypted::file_exists(const String &p_name) {
Ref<FileAccess> fa = FileAccess::open(p_name, FileAccess::READ);
if (fa.is_null()) {

View File

@ -73,12 +73,14 @@ public:
virtual bool eof_reached() const override; ///< reading passed EOF
virtual uint8_t get_8() const override; ///< get a byte
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
virtual Error get_error() const override; ///< get last error
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
virtual void flush() override;
virtual void store_8(uint8_t p_dest) override; ///< store a byte
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists

View File

@ -122,6 +122,16 @@ bool FileAccessMemory::eof_reached() const {
return pos >= length;
}
uint8_t FileAccessMemory::get_8() const {
uint8_t ret = 0;
if (pos < length) {
ret = data[pos];
}
++pos;
return ret;
}
uint64_t FileAccessMemory::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
ERR_FAIL_NULL_V(data, -1);
@ -147,12 +157,16 @@ void FileAccessMemory::flush() {
ERR_FAIL_NULL(data);
}
void FileAccessMemory::store_8(uint8_t p_byte) {
ERR_FAIL_NULL(data);
ERR_FAIL_COND(pos >= length);
data[pos++] = p_byte;
}
void FileAccessMemory::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND(!p_src && p_length > 0);
uint64_t left = length - pos;
uint64_t write = MIN(p_length, left);
if (write < p_length) {
WARN_PRINT("Writing less data than requested");
}

View File

@ -55,12 +55,15 @@ public:
virtual bool eof_reached() const override; ///< reading passed EOF
virtual uint8_t get_8() const override; ///< get a byte
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override; ///< get an array of bytes
virtual Error get_error() const override; ///< get last error
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
virtual void flush() override;
virtual void store_8(uint8_t p_byte) override; ///< store a byte
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists

View File

@ -102,22 +102,6 @@ void PackedData::add_pack_source(PackSource *p_source) {
}
}
uint8_t *PackedData::get_file_hash(const String &p_path) {
PathMD5 pmd5(p_path.md5_buffer());
HashMap<PathMD5, PackedFile, PathMD5>::Iterator E = files.find(pmd5);
if (!E || E->value.offset == 0) {
return nullptr;
}
return E->value.md5;
}
void PackedData::clear() {
files.clear();
_free_packed_dirs(root);
root = memnew(PackedDir);
}
PackedData *PackedData::singleton = nullptr;
PackedData::PackedData() {
@ -329,6 +313,17 @@ bool FileAccessPack::eof_reached() const {
return eof;
}
uint8_t FileAccessPack::get_8() const {
ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use.");
if (pos >= pf.size) {
eof = true;
return 0;
}
pos++;
return f->get_8();
}
uint64_t FileAccessPack::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V_MSG(f.is_null(), -1, "File must be opened before use.");
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
@ -371,6 +366,10 @@ void FileAccessPack::flush() {
ERR_FAIL();
}
void FileAccessPack::store_8(uint8_t p_dest) {
ERR_FAIL();
}
void FileAccessPack::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL();
}

View File

@ -111,7 +111,6 @@ private:
public:
void add_pack_source(PackSource *p_source);
void add_path(const String &p_pkg_path, const String &p_path, uint64_t p_ofs, uint64_t p_size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted = false); // for PackSource
uint8_t *get_file_hash(const String &p_path);
void set_disabled(bool p_disabled) { disabled = p_disabled; }
_FORCE_INLINE_ bool is_disabled() const { return disabled; }
@ -119,8 +118,6 @@ public:
static PackedData *get_singleton() { return singleton; }
Error add_pack(const String &p_path, bool p_replace_files, uint64_t p_offset);
void clear();
_FORCE_INLINE_ Ref<FileAccess> try_open_path(const String &p_path);
_FORCE_INLINE_ bool has_path(const String &p_path);
@ -172,6 +169,8 @@ public:
virtual bool eof_reached() const override;
virtual uint8_t get_8() const override;
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
virtual void set_big_endian(bool p_big_endian) override;
@ -180,6 +179,8 @@ public:
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
virtual void flush() override;
virtual void store_8(uint8_t p_dest) override;
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual bool file_exists(const String &p_name) override;

View File

@ -291,6 +291,12 @@ bool FileAccessZip::eof_reached() const {
return at_eof;
}
uint8_t FileAccessZip::get_8() const {
uint8_t ret = 0;
get_buffer(&ret, 1);
return ret;
}
uint64_t FileAccessZip::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
ERR_FAIL_NULL_V(zfile, -1);
@ -322,7 +328,7 @@ void FileAccessZip::flush() {
ERR_FAIL();
}
void FileAccessZip::store_buffer(const uint8_t *p_src, uint64_t p_length) {
void FileAccessZip::store_8(uint8_t p_dest) {
ERR_FAIL();
}

View File

@ -95,13 +95,14 @@ public:
virtual bool eof_reached() const override; ///< reading passed EOF
virtual uint8_t get_8() const override; ///< get a byte
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
virtual Error get_error() const override; ///< get last error
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
virtual void flush() override;
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual void store_8(uint8_t p_dest) override; ///< store a byte
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists

View File

@ -42,9 +42,9 @@ const char *HTTPClient::_methods[METHOD_MAX] = {
"PATCH"
};
HTTPClient *HTTPClient::create(bool p_notify_postinitialize) {
HTTPClient *HTTPClient::create() {
if (_create) {
return _create(p_notify_postinitialize);
return _create();
}
return nullptr;
}

View File

@ -158,12 +158,12 @@ protected:
Error _request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const Vector<uint8_t> &p_body);
Error _request(Method p_method, const String &p_url, const Vector<String> &p_headers, const String &p_body = String());
static HTTPClient *(*_create)(bool p_notify_postinitialize);
static HTTPClient *(*_create)();
static void _bind_methods();
public:
static HTTPClient *create(bool p_notify_postinitialize = true);
static HTTPClient *create();
String query_string_from_dict(const Dictionary &p_dict);
Error verify_headers(const Vector<String> &p_headers);

View File

@ -35,8 +35,8 @@
#include "core/io/stream_peer_tls.h"
#include "core/version.h"
HTTPClient *HTTPClientTCP::_create_func(bool p_notify_postinitialize) {
return static_cast<HTTPClient *>(ClassDB::creator<HTTPClientTCP>(p_notify_postinitialize));
HTTPClient *HTTPClientTCP::_create_func() {
return memnew(HTTPClientTCP);
}
Error HTTPClientTCP::connect_to_host(const String &p_host, int p_port, Ref<TLSOptions> p_options) {
@ -792,6 +792,6 @@ HTTPClientTCP::HTTPClientTCP() {
request_buffer.instantiate();
}
HTTPClient *(*HTTPClient::_create)(bool p_notify_postinitialize) = HTTPClientTCP::_create_func;
HTTPClient *(*HTTPClient::_create)() = HTTPClientTCP::_create_func;
#endif // WEB_ENABLED

View File

@ -76,7 +76,7 @@ private:
Error _get_http_data(uint8_t *p_buffer, int p_bytes, int &r_received);
public:
static HTTPClient *_create_func(bool p_notify_postinitialize);
static HTTPClient *_create_func();
Error request(Method p_method, const String &p_url, const Vector<String> &p_headers, const uint8_t *p_body, int p_body_size) override;

View File

@ -30,7 +30,6 @@
#include "image.h"
#include "core/config/project_settings.h"
#include "core/error/error_list.h"
#include "core/error/error_macros.h"
#include "core/io/image_loader.h"
@ -502,38 +501,6 @@ static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p
}
}
template <typename T, uint32_t read_channels, uint32_t write_channels, T def_zero, T def_one>
static void _convert_fast(int p_width, int p_height, const T *p_src, T *p_dst) {
uint32_t dst_count = 0;
uint32_t src_count = 0;
const int resolution = p_width * p_height;
for (int i = 0; i < resolution; i++) {
memcpy(p_dst + dst_count, p_src + src_count, MIN(read_channels, write_channels) * sizeof(T));
if constexpr (write_channels > read_channels) {
const T def_value[4] = { def_zero, def_zero, def_zero, def_one };
memcpy(p_dst + dst_count + read_channels, &def_value[read_channels], (write_channels - read_channels) * sizeof(T));
}
dst_count += write_channels;
src_count += read_channels;
}
}
static bool _are_formats_compatible(Image::Format p_format0, Image::Format p_format1) {
if (p_format0 <= Image::FORMAT_RGBA8 && p_format1 <= Image::FORMAT_RGBA8) {
return true;
} else if (p_format0 <= Image::FORMAT_RGBAH && p_format0 >= Image::FORMAT_RH && p_format1 <= Image::FORMAT_RGBAH && p_format1 >= Image::FORMAT_RH) {
return true;
} else if (p_format0 <= Image::FORMAT_RGBAF && p_format0 >= Image::FORMAT_RF && p_format1 <= Image::FORMAT_RGBAF && p_format1 >= Image::FORMAT_RF) {
return true;
}
return false;
}
void Image::convert(Format p_new_format) {
ERR_FAIL_INDEX_MSG(p_new_format, FORMAT_MAX, "The Image format specified (" + itos(p_new_format) + ") is out of range. See Image's Format enum.");
if (data.size() == 0) {
@ -550,7 +517,7 @@ void Image::convert(Format p_new_format) {
if (Image::is_format_compressed(format) || Image::is_format_compressed(p_new_format)) {
ERR_FAIL_MSG("Cannot convert to <-> from compressed formats. Use compress() and decompress() instead.");
} else if (!_are_formats_compatible(format, p_new_format)) {
} else if (format > FORMAT_RGBA8 || p_new_format > FORMAT_RGBA8) {
//use put/set pixel which is slower but works with non byte formats
Image new_img(width, height, mipmaps, p_new_format);
@ -681,78 +648,6 @@ void Image::convert(Format p_new_format) {
case FORMAT_RGBA8 | (FORMAT_RGB8 << 8):
_convert<3, true, 3, false, false, false>(mip_width, mip_height, rptr, wptr);
break;
case FORMAT_RH | (FORMAT_RGH << 8):
_convert_fast<uint16_t, 1, 2, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RH | (FORMAT_RGBH << 8):
_convert_fast<uint16_t, 1, 3, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RH | (FORMAT_RGBAH << 8):
_convert_fast<uint16_t, 1, 4, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RGH | (FORMAT_RH << 8):
_convert_fast<uint16_t, 2, 1, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RGH | (FORMAT_RGBH << 8):
_convert_fast<uint16_t, 2, 3, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RGH | (FORMAT_RGBAH << 8):
_convert_fast<uint16_t, 2, 4, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RGBH | (FORMAT_RH << 8):
_convert_fast<uint16_t, 3, 1, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RGBH | (FORMAT_RGH << 8):
_convert_fast<uint16_t, 3, 2, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RGBH | (FORMAT_RGBAH << 8):
_convert_fast<uint16_t, 3, 4, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RGBAH | (FORMAT_RH << 8):
_convert_fast<uint16_t, 4, 1, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RGBAH | (FORMAT_RGH << 8):
_convert_fast<uint16_t, 4, 2, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RGBAH | (FORMAT_RGBH << 8):
_convert_fast<uint16_t, 4, 3, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
break;
case FORMAT_RF | (FORMAT_RGF << 8):
_convert_fast<uint32_t, 1, 2, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
break;
case FORMAT_RF | (FORMAT_RGBF << 8):
_convert_fast<uint32_t, 1, 3, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
break;
case FORMAT_RF | (FORMAT_RGBAF << 8):
_convert_fast<uint32_t, 1, 4, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
break;
case FORMAT_RGF | (FORMAT_RF << 8):
_convert_fast<uint32_t, 2, 1, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
break;
case FORMAT_RGF | (FORMAT_RGBF << 8):
_convert_fast<uint32_t, 2, 3, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
break;
case FORMAT_RGF | (FORMAT_RGBAF << 8):
_convert_fast<uint32_t, 2, 4, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
break;
case FORMAT_RGBF | (FORMAT_RF << 8):
_convert_fast<uint32_t, 3, 1, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
break;
case FORMAT_RGBF | (FORMAT_RGF << 8):
_convert_fast<uint32_t, 3, 2, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
break;
case FORMAT_RGBF | (FORMAT_RGBAF << 8):
_convert_fast<uint32_t, 3, 4, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
break;
case FORMAT_RGBAF | (FORMAT_RF << 8):
_convert_fast<uint32_t, 4, 1, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
break;
case FORMAT_RGBAF | (FORMAT_RGF << 8):
_convert_fast<uint32_t, 4, 2, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
break;
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;
}
}
@ -866,10 +761,12 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_
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);
constexpr uint32_t FRAC_HALF = (FRAC_LEN >> 1);
constexpr uint32_t FRAC_MASK = FRAC_LEN - 1;
enum {
FRAC_BITS = 8,
FRAC_LEN = (1 << FRAC_BITS),
FRAC_HALF = (FRAC_LEN >> 1),
FRAC_MASK = FRAC_LEN - 1
};
for (uint32_t i = 0; i < p_dst_height; i++) {
// Add 0.5 in order to interpolate based on pixel center
@ -2733,40 +2630,6 @@ Error Image::compress(CompressMode p_mode, CompressSource p_source, ASTCFormat p
Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, ASTCFormat p_astc_format) {
ERR_FAIL_COND_V(data.is_empty(), ERR_INVALID_DATA);
// RenderingDevice only.
if (GLOBAL_GET("rendering/textures/vram_compression/compress_with_gpu")) {
switch (p_mode) {
case COMPRESS_BPTC: {
// BC7 is unsupported currently.
if ((format >= FORMAT_RF && format <= FORMAT_RGBE9995) && _image_compress_bptc_rd_func) {
Error result = _image_compress_bptc_rd_func(this, p_channels);
// If the image was compressed successfully, we return here. If not, we fall back to the default compression scheme.
if (result == OK) {
return OK;
}
}
} break;
case COMPRESS_S3TC: {
// BC3 is unsupported currently.
if ((p_channels == USED_CHANNELS_RGB || p_channels == USED_CHANNELS_L) && _image_compress_bc_rd_func) {
Error result = _image_compress_bc_rd_func(this, p_channels);
// If the image was compressed successfully, we return here. If not, we fall back to the default compression scheme.
if (result == OK) {
return OK;
}
}
} break;
default: {
}
}
}
switch (p_mode) {
case COMPRESS_S3TC: {
ERR_FAIL_NULL_V(_image_compress_bc_func, ERR_UNAVAILABLE);
@ -3148,8 +3011,6 @@ void (*Image::_image_compress_bptc_func)(Image *, Image::UsedChannels) = nullptr
void (*Image::_image_compress_etc1_func)(Image *) = nullptr;
void (*Image::_image_compress_etc2_func)(Image *, Image::UsedChannels) = nullptr;
void (*Image::_image_compress_astc_func)(Image *, Image::ASTCFormat) = nullptr;
Error (*Image::_image_compress_bptc_rd_func)(Image *, Image::UsedChannels) = nullptr;
Error (*Image::_image_compress_bc_rd_func)(Image *, Image::UsedChannels) = nullptr;
void (*Image::_image_decompress_bc)(Image *) = nullptr;
void (*Image::_image_decompress_bptc)(Image *) = nullptr;
void (*Image::_image_decompress_etc1)(Image *) = nullptr;
@ -3599,7 +3460,6 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("fix_alpha_edges"), &Image::fix_alpha_edges);
ClassDB::bind_method(D_METHOD("premultiply_alpha"), &Image::premultiply_alpha);
ClassDB::bind_method(D_METHOD("srgb_to_linear"), &Image::srgb_to_linear);
ClassDB::bind_method(D_METHOD("linear_to_srgb"), &Image::linear_to_srgb);
ClassDB::bind_method(D_METHOD("normal_map_to_xy"), &Image::normal_map_to_xy);
ClassDB::bind_method(D_METHOD("rgbe_to_srgb"), &Image::rgbe_to_srgb);
ClassDB::bind_method(D_METHOD("bump_map_to_normal_map", "bump_scale"), &Image::bump_map_to_normal_map, DEFVAL(1.0));
@ -3836,33 +3696,6 @@ void Image::bump_map_to_normal_map(float bump_scale) {
data = result_image;
}
bool Image::detect_signed(bool p_include_mips) const {
ERR_FAIL_COND_V(is_compressed(), false);
if (format >= Image::FORMAT_RH && format <= Image::FORMAT_RGBAH) {
const uint16_t *img_data = reinterpret_cast<const uint16_t *>(data.ptr());
const uint64_t img_size = p_include_mips ? (data.size() / 2) : (width * height * get_format_pixel_size(format) / 2);
for (uint64_t i = 0; i < img_size; i++) {
if ((img_data[i] & 0x8000) != 0 && (img_data[i] & 0x7fff) != 0) {
return true;
}
}
} else if (format >= Image::FORMAT_RF && format <= Image::FORMAT_RGBAF) {
const uint32_t *img_data = reinterpret_cast<const uint32_t *>(data.ptr());
const uint64_t img_size = p_include_mips ? (data.size() / 4) : (width * height * get_format_pixel_size(format) / 4);
for (uint64_t i = 0; i < img_size; i++) {
if ((img_data[i] & 0x80000000) != 0 && (img_data[i] & 0x7fffffff) != 0) {
return true;
}
}
}
return false;
}
void Image::srgb_to_linear() {
if (data.size() == 0) {
return;
@ -3894,37 +3727,6 @@ void Image::srgb_to_linear() {
}
}
void Image::linear_to_srgb() {
if (data.size() == 0) {
return;
}
static const uint8_t lin2srgb[256] = { 0, 12, 21, 28, 33, 38, 42, 46, 49, 52, 55, 58, 61, 63, 66, 68, 70, 73, 75, 77, 79, 81, 82, 84, 86, 88, 89, 91, 93, 94, 96, 97, 99, 100, 102, 103, 104, 106, 107, 109, 110, 111, 112, 114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126, 127, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 151, 152, 153, 154, 155, 156, 157, 157, 158, 159, 160, 161, 161, 162, 163, 164, 165, 165, 166, 167, 168, 168, 169, 170, 171, 171, 172, 173, 174, 174, 175, 176, 176, 177, 178, 179, 179, 180, 181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193, 193, 194, 194, 195, 196, 196, 197, 197, 198, 199, 199, 200, 201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 206, 207, 208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222, 222, 223, 223, 224, 224, 225, 226, 226, 227, 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, 233, 234, 234, 235, 235, 236, 236, 237, 237, 237, 238, 238, 239, 239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 245, 246, 246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 251, 252, 252, 253, 253, 254, 254, 255 };
ERR_FAIL_COND(format != FORMAT_RGB8 && format != FORMAT_RGBA8);
if (format == FORMAT_RGBA8) {
int len = data.size() / 4;
uint8_t *data_ptr = data.ptrw();
for (int i = 0; i < len; i++) {
data_ptr[(i << 2) + 0] = lin2srgb[data_ptr[(i << 2) + 0]];
data_ptr[(i << 2) + 1] = lin2srgb[data_ptr[(i << 2) + 1]];
data_ptr[(i << 2) + 2] = lin2srgb[data_ptr[(i << 2) + 2]];
}
} else if (format == FORMAT_RGB8) {
int len = data.size() / 3;
uint8_t *data_ptr = data.ptrw();
for (int i = 0; i < len; i++) {
data_ptr[(i * 3) + 0] = lin2srgb[data_ptr[(i * 3) + 0]];
data_ptr[(i * 3) + 1] = lin2srgb[data_ptr[(i * 3) + 1]];
data_ptr[(i * 3) + 2] = lin2srgb[data_ptr[(i * 3) + 2]];
}
}
}
void Image::premultiply_alpha() {
if (data.size() == 0) {
return;
@ -4237,7 +4039,7 @@ Dictionary Image::compute_image_metrics(const Ref<Image> p_compared_image, bool
result["root_mean_squared"] = INFINITY;
result["peak_snr"] = 0.0f;
ERR_FAIL_COND_V(p_compared_image.is_null(), result);
ERR_FAIL_NULL_V(p_compared_image, result);
Error err = OK;
Ref<Image> compared_image = duplicate(true);
if (compared_image->is_compressed()) {

View File

@ -159,9 +159,6 @@ public:
static void (*_image_compress_etc2_func)(Image *, UsedChannels p_channels);
static void (*_image_compress_astc_func)(Image *, ASTCFormat p_format);
static Error (*_image_compress_bptc_rd_func)(Image *, UsedChannels p_channels);
static Error (*_image_compress_bc_rd_func)(Image *, UsedChannels p_channels);
static void (*_image_decompress_bc)(Image *);
static void (*_image_decompress_bptc)(Image *);
static void (*_image_decompress_etc1)(Image *);
@ -386,14 +383,11 @@ public:
void fix_alpha_edges();
void premultiply_alpha();
void srgb_to_linear();
void linear_to_srgb();
void normal_map_to_xy();
Ref<Image> rgbe_to_srgb();
Ref<Image> get_image_from_mipmap(int p_mipmap) const;
void bump_map_to_normal_map(float bump_scale = 1.0);
bool detect_signed(bool p_include_mips = true) const;
void blit_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest);
void blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2i &p_src_rect, const Point2i &p_dest);
void blend_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest);

View File

@ -81,17 +81,17 @@ struct _IP_ResolverPrivate {
continue;
}
MutexLock lock(mutex);
mutex.lock();
List<IPAddress> response;
String hostname = queue[i].hostname;
IP::Type type = queue[i].type;
lock.temp_unlock();
mutex.unlock();
// We should not lock while resolving the hostname,
// only when modifying the queue.
IP::get_singleton()->_resolve_hostname(response, hostname, type);
lock.temp_relock();
MutexLock lock(mutex);
// Could have been completed by another function, or deleted.
if (queue[i].status.get() != IP::RESOLVER_STATUS_WAITING) {
continue;
@ -131,22 +131,21 @@ PackedStringArray IP::resolve_hostname_addresses(const String &p_hostname, Type
List<IPAddress> res;
String key = _IP_ResolverPrivate::get_cache_key(p_hostname, p_type);
{
MutexLock lock(resolver->mutex);
if (resolver->cache.has(key)) {
res = resolver->cache[key];
} else {
// This should be run unlocked so the resolver thread can keep resolving
// other requests.
lock.temp_unlock();
_resolve_hostname(res, p_hostname, p_type);
lock.temp_relock();
// We might be overriding another result, but we don't care as long as the result is valid.
if (res.size()) {
resolver->cache[key] = res;
}
resolver->mutex.lock();
if (resolver->cache.has(key)) {
res = resolver->cache[key];
} else {
// This should be run unlocked so the resolver thread can keep resolving
// other requests.
resolver->mutex.unlock();
_resolve_hostname(res, p_hostname, p_type);
resolver->mutex.lock();
// We might be overriding another result, but we don't care as long as the result is valid.
if (res.size()) {
resolver->cache[key] = res;
}
}
resolver->mutex.unlock();
PackedStringArray result;
for (const IPAddress &E : res) {

View File

@ -588,756 +588,10 @@ void JSON::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_error_line"), &JSON::get_error_line);
ClassDB::bind_method(D_METHOD("get_error_message"), &JSON::get_error_message);
ClassDB::bind_static_method("JSON", D_METHOD("to_native", "json", "allow_classes", "allow_scripts"), &JSON::to_native, DEFVAL(false), DEFVAL(false));
ClassDB::bind_static_method("JSON", D_METHOD("from_native", "variant", "allow_classes", "allow_scripts"), &JSON::from_native, DEFVAL(false), DEFVAL(false));
ADD_PROPERTY(PropertyInfo(Variant::NIL, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT), "set_data", "get_data"); // Ensures that it can be serialized as binary.
}
#define GDTYPE "__gdtype"
#define VALUES "values"
#define PASS_ARG p_allow_classes, p_allow_scripts
Variant JSON::from_native(const Variant &p_variant, bool p_allow_classes, bool p_allow_scripts) {
switch (p_variant.get_type()) {
case Variant::NIL: {
Dictionary nil;
nil[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return nil;
} break;
case Variant::BOOL: {
return p_variant;
} break;
case Variant::INT: {
return p_variant;
} break;
case Variant::FLOAT: {
return p_variant;
} break;
case Variant::STRING: {
return p_variant;
} break;
case Variant::VECTOR2: {
Dictionary d;
Vector2 v = p_variant;
Array values;
values.push_back(v.x);
values.push_back(v.y);
d[VALUES] = values;
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::VECTOR2I: {
Dictionary d;
Vector2i v = p_variant;
Array values;
values.push_back(v.x);
values.push_back(v.y);
d[VALUES] = values;
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::RECT2: {
Dictionary d;
Rect2 r = p_variant;
d["position"] = from_native(r.position);
d["size"] = from_native(r.size);
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::RECT2I: {
Dictionary d;
Rect2i r = p_variant;
d["position"] = from_native(r.position);
d["size"] = from_native(r.size);
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::VECTOR3: {
Dictionary d;
Vector3 v = p_variant;
Array values;
values.push_back(v.x);
values.push_back(v.y);
values.push_back(v.z);
d[VALUES] = values;
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::VECTOR3I: {
Dictionary d;
Vector3i v = p_variant;
Array values;
values.push_back(v.x);
values.push_back(v.y);
values.push_back(v.z);
d[VALUES] = values;
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::TRANSFORM2D: {
Dictionary d;
Transform2D t = p_variant;
d["x"] = from_native(t[0]);
d["y"] = from_native(t[1]);
d["origin"] = from_native(t[2]);
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::VECTOR4: {
Dictionary d;
Vector4 v = p_variant;
Array values;
values.push_back(v.x);
values.push_back(v.y);
values.push_back(v.z);
values.push_back(v.w);
d[VALUES] = values;
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::VECTOR4I: {
Dictionary d;
Vector4i v = p_variant;
Array values;
values.push_back(v.x);
values.push_back(v.y);
values.push_back(v.z);
values.push_back(v.w);
d[VALUES] = values;
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::PLANE: {
Dictionary d;
Plane p = p_variant;
d["normal"] = from_native(p.normal);
d["d"] = p.d;
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::QUATERNION: {
Dictionary d;
Quaternion q = p_variant;
Array values;
values.push_back(q.x);
values.push_back(q.y);
values.push_back(q.z);
values.push_back(q.w);
d[VALUES] = values;
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::AABB: {
Dictionary d;
AABB aabb = p_variant;
d["position"] = from_native(aabb.position);
d["size"] = from_native(aabb.size);
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::BASIS: {
Dictionary d;
Basis t = p_variant;
d["x"] = from_native(t.get_column(0));
d["y"] = from_native(t.get_column(1));
d["z"] = from_native(t.get_column(2));
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::TRANSFORM3D: {
Dictionary d;
Transform3D t = p_variant;
d["basis"] = from_native(t.basis);
d["origin"] = from_native(t.origin);
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::PROJECTION: {
Dictionary d;
Projection t = p_variant;
d["x"] = from_native(t[0]);
d["y"] = from_native(t[1]);
d["z"] = from_native(t[2]);
d["w"] = from_native(t[3]);
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::COLOR: {
Dictionary d;
Color c = p_variant;
Array values;
values.push_back(c.r);
values.push_back(c.g);
values.push_back(c.b);
values.push_back(c.a);
d[VALUES] = values;
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::STRING_NAME: {
Dictionary d;
d["name"] = String(p_variant);
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::NODE_PATH: {
Dictionary d;
d["path"] = String(p_variant);
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::RID: {
Dictionary d;
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::OBJECT: {
Object *obj = p_variant.get_validated_object();
if (p_allow_classes && obj) {
Dictionary d;
List<PropertyInfo> property_list;
obj->get_property_list(&property_list);
d["type"] = obj->get_class();
Dictionary p;
for (const PropertyInfo &P : property_list) {
if (P.usage & PROPERTY_USAGE_STORAGE) {
if (P.name == "script" && !p_allow_scripts) {
continue;
}
p[P.name] = from_native(obj->get(P.name), PASS_ARG);
}
}
d["properties"] = p;
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} else {
Dictionary nil;
nil[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return nil;
}
} break;
case Variant::CALLABLE:
case Variant::SIGNAL: {
Dictionary nil;
nil[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return nil;
} break;
case Variant::DICTIONARY: {
Dictionary d = p_variant;
List<Variant> keys;
d.get_key_list(&keys);
bool all_strings = true;
for (const Variant &K : keys) {
if (K.get_type() != Variant::STRING) {
all_strings = false;
break;
}
}
if (all_strings) {
Dictionary ret_dict;
for (const Variant &K : keys) {
ret_dict[K] = from_native(d[K], PASS_ARG);
}
return ret_dict;
} else {
Dictionary ret;
Array pairs;
for (const Variant &K : keys) {
Dictionary pair;
pair["key"] = from_native(K, PASS_ARG);
pair["value"] = from_native(d[K], PASS_ARG);
pairs.push_back(pair);
}
ret["pairs"] = pairs;
ret[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return ret;
}
} break;
case Variant::ARRAY: {
Array arr = p_variant;
Array ret;
for (int i = 0; i < arr.size(); i++) {
ret.push_back(from_native(arr[i], PASS_ARG));
}
return ret;
} break;
case Variant::PACKED_BYTE_ARRAY: {
Dictionary d;
PackedByteArray arr = p_variant;
Array values;
for (int i = 0; i < arr.size(); i++) {
values.push_back(arr[i]);
}
d[VALUES] = values;
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::PACKED_INT32_ARRAY: {
Dictionary d;
PackedInt32Array arr = p_variant;
Array values;
for (int i = 0; i < arr.size(); i++) {
values.push_back(arr[i]);
}
d[VALUES] = values;
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::PACKED_INT64_ARRAY: {
Dictionary d;
PackedInt64Array arr = p_variant;
Array values;
for (int i = 0; i < arr.size(); i++) {
values.push_back(arr[i]);
}
d[VALUES] = values;
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::PACKED_FLOAT32_ARRAY: {
Dictionary d;
PackedFloat32Array arr = p_variant;
Array values;
for (int i = 0; i < arr.size(); i++) {
values.push_back(arr[i]);
}
d[VALUES] = values;
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::PACKED_FLOAT64_ARRAY: {
Dictionary d;
PackedFloat64Array arr = p_variant;
Array values;
for (int i = 0; i < arr.size(); i++) {
values.push_back(arr[i]);
}
d[VALUES] = values;
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::PACKED_STRING_ARRAY: {
Dictionary d;
PackedStringArray arr = p_variant;
Array values;
for (int i = 0; i < arr.size(); i++) {
values.push_back(arr[i]);
}
d[VALUES] = values;
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::PACKED_VECTOR2_ARRAY: {
Dictionary d;
PackedVector2Array arr = p_variant;
Array values;
for (int i = 0; i < arr.size(); i++) {
Vector2 v = arr[i];
values.push_back(v.x);
values.push_back(v.y);
}
d[VALUES] = values;
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::PACKED_VECTOR3_ARRAY: {
Dictionary d;
PackedVector3Array arr = p_variant;
Array values;
for (int i = 0; i < arr.size(); i++) {
Vector3 v = arr[i];
values.push_back(v.x);
values.push_back(v.y);
values.push_back(v.z);
}
d[VALUES] = values;
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::PACKED_COLOR_ARRAY: {
Dictionary d;
PackedColorArray arr = p_variant;
Array values;
for (int i = 0; i < arr.size(); i++) {
Color v = arr[i];
values.push_back(v.r);
values.push_back(v.g);
values.push_back(v.b);
values.push_back(v.a);
}
d[VALUES] = values;
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
case Variant::PACKED_VECTOR4_ARRAY: {
Dictionary d;
PackedVector4Array arr = p_variant;
Array values;
for (int i = 0; i < arr.size(); i++) {
Vector4 v = arr[i];
values.push_back(v.x);
values.push_back(v.y);
values.push_back(v.z);
values.push_back(v.w);
}
d[VALUES] = values;
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return d;
} break;
default: {
ERR_PRINT(vformat("Unhandled conversion from native Variant type '%s' to JSON.", Variant::get_type_name(p_variant.get_type())));
} break;
}
Dictionary nil;
nil[GDTYPE] = Variant::get_type_name(p_variant.get_type());
return nil;
}
Variant JSON::to_native(const Variant &p_json, bool p_allow_classes, bool p_allow_scripts) {
switch (p_json.get_type()) {
case Variant::BOOL: {
return p_json;
} break;
case Variant::INT: {
return p_json;
} break;
case Variant::FLOAT: {
return p_json;
} break;
case Variant::STRING: {
return p_json;
} break;
case Variant::STRING_NAME: {
return p_json;
} break;
case Variant::CALLABLE: {
return p_json;
} break;
case Variant::DICTIONARY: {
Dictionary d = p_json;
if (d.has(GDTYPE)) {
// Specific Godot Variant types serialized to JSON.
String type = d[GDTYPE];
if (type == Variant::get_type_name(Variant::VECTOR2)) {
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
Array values = d[VALUES];
ERR_FAIL_COND_V(values.size() != 2, Variant());
Vector2 v;
v.x = values[0];
v.y = values[1];
return v;
} else if (type == Variant::get_type_name(Variant::VECTOR2I)) {
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
Array values = d[VALUES];
ERR_FAIL_COND_V(values.size() != 2, Variant());
Vector2i v;
v.x = values[0];
v.y = values[1];
return v;
} else if (type == Variant::get_type_name(Variant::RECT2)) {
ERR_FAIL_COND_V(!d.has("position"), Variant());
ERR_FAIL_COND_V(!d.has("size"), Variant());
Rect2 r;
r.position = to_native(d["position"]);
r.size = to_native(d["size"]);
return r;
} else if (type == Variant::get_type_name(Variant::RECT2I)) {
ERR_FAIL_COND_V(!d.has("position"), Variant());
ERR_FAIL_COND_V(!d.has("size"), Variant());
Rect2i r;
r.position = to_native(d["position"]);
r.size = to_native(d["size"]);
return r;
} else if (type == Variant::get_type_name(Variant::VECTOR3)) {
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
Array values = d[VALUES];
ERR_FAIL_COND_V(values.size() != 3, Variant());
Vector3 v;
v.x = values[0];
v.y = values[1];
v.z = values[2];
return v;
} else if (type == Variant::get_type_name(Variant::VECTOR3I)) {
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
Array values = d[VALUES];
ERR_FAIL_COND_V(values.size() != 3, Variant());
Vector3i v;
v.x = values[0];
v.y = values[1];
v.z = values[2];
return v;
} else if (type == Variant::get_type_name(Variant::TRANSFORM2D)) {
ERR_FAIL_COND_V(!d.has("x"), Variant());
ERR_FAIL_COND_V(!d.has("y"), Variant());
ERR_FAIL_COND_V(!d.has("origin"), Variant());
Transform2D t;
t[0] = to_native(d["x"]);
t[1] = to_native(d["y"]);
t[2] = to_native(d["origin"]);
return t;
} else if (type == Variant::get_type_name(Variant::VECTOR4)) {
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
Array values = d[VALUES];
ERR_FAIL_COND_V(values.size() != 4, Variant());
Vector4 v;
v.x = values[0];
v.y = values[1];
v.z = values[2];
v.w = values[3];
return v;
} else if (type == Variant::get_type_name(Variant::VECTOR4I)) {
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
Array values = d[VALUES];
ERR_FAIL_COND_V(values.size() != 4, Variant());
Vector4i v;
v.x = values[0];
v.y = values[1];
v.z = values[2];
v.w = values[3];
return v;
} else if (type == Variant::get_type_name(Variant::PLANE)) {
ERR_FAIL_COND_V(!d.has("normal"), Variant());
ERR_FAIL_COND_V(!d.has("d"), Variant());
Plane p;
p.normal = to_native(d["normal"]);
p.d = d["d"];
return p;
} else if (type == Variant::get_type_name(Variant::QUATERNION)) {
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
Array values = d[VALUES];
ERR_FAIL_COND_V(values.size() != 4, Variant());
Quaternion v;
v.x = values[0];
v.y = values[1];
v.z = values[2];
v.w = values[3];
return v;
} else if (type == Variant::get_type_name(Variant::AABB)) {
ERR_FAIL_COND_V(!d.has("position"), Variant());
ERR_FAIL_COND_V(!d.has("size"), Variant());
AABB r;
r.position = to_native(d["position"]);
r.size = to_native(d["size"]);
return r;
} else if (type == Variant::get_type_name(Variant::BASIS)) {
ERR_FAIL_COND_V(!d.has("x"), Variant());
ERR_FAIL_COND_V(!d.has("y"), Variant());
ERR_FAIL_COND_V(!d.has("z"), Variant());
Basis b;
b.set_column(0, to_native(d["x"]));
b.set_column(1, to_native(d["y"]));
b.set_column(2, to_native(d["z"]));
return b;
} else if (type == Variant::get_type_name(Variant::TRANSFORM3D)) {
ERR_FAIL_COND_V(!d.has("basis"), Variant());
ERR_FAIL_COND_V(!d.has("origin"), Variant());
Transform3D t;
t.basis = to_native(d["basis"]);
t.origin = to_native(d["origin"]);
return t;
} else if (type == Variant::get_type_name(Variant::PROJECTION)) {
ERR_FAIL_COND_V(!d.has("x"), Variant());
ERR_FAIL_COND_V(!d.has("y"), Variant());
ERR_FAIL_COND_V(!d.has("z"), Variant());
ERR_FAIL_COND_V(!d.has("w"), Variant());
Projection p;
p[0] = to_native(d["x"]);
p[1] = to_native(d["y"]);
p[2] = to_native(d["z"]);
p[3] = to_native(d["w"]);
return p;
} else if (type == Variant::get_type_name(Variant::COLOR)) {
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
Array values = d[VALUES];
ERR_FAIL_COND_V(values.size() != 4, Variant());
Color c;
c.r = values[0];
c.g = values[1];
c.b = values[2];
c.a = values[3];
return c;
} else if (type == Variant::get_type_name(Variant::NODE_PATH)) {
ERR_FAIL_COND_V(!d.has("path"), Variant());
NodePath np = d["path"];
return np;
} else if (type == Variant::get_type_name(Variant::STRING_NAME)) {
ERR_FAIL_COND_V(!d.has("name"), Variant());
StringName s = d["name"];
return s;
} else if (type == Variant::get_type_name(Variant::OBJECT)) {
ERR_FAIL_COND_V(!d.has("type"), Variant());
ERR_FAIL_COND_V(!d.has("properties"), Variant());
ERR_FAIL_COND_V(!p_allow_classes, Variant());
String obj_type = d["type"];
bool is_script = obj_type == "Script" || ClassDB::is_parent_class(obj_type, "Script");
ERR_FAIL_COND_V(!p_allow_scripts && is_script, Variant());
Object *obj = ClassDB::instantiate(obj_type);
ERR_FAIL_NULL_V(obj, Variant());
Dictionary p = d["properties"];
List<Variant> keys;
p.get_key_list(&keys);
for (const Variant &K : keys) {
String property = K;
Variant value = to_native(p[K], PASS_ARG);
obj->set(property, value);
}
Variant v(obj);
return v;
} else if (type == Variant::get_type_name(Variant::DICTIONARY)) {
ERR_FAIL_COND_V(!d.has("pairs"), Variant());
Array pairs = d["pairs"];
Dictionary r;
for (int i = 0; i < pairs.size(); i++) {
Dictionary p = pairs[i];
ERR_CONTINUE(!p.has("key"));
ERR_CONTINUE(!p.has("value"));
r[to_native(p["key"], PASS_ARG)] = to_native(p["value"]);
}
return r;
} else if (type == Variant::get_type_name(Variant::ARRAY)) {
ERR_PRINT(vformat("Unexpected Array with '%s' key. Arrays are supported natively.", GDTYPE));
} else if (type == Variant::get_type_name(Variant::PACKED_BYTE_ARRAY)) {
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
Array values = d[VALUES];
PackedByteArray pbarr;
pbarr.resize(values.size());
for (int i = 0; i < pbarr.size(); i++) {
pbarr.write[i] = values[i];
}
return pbarr;
} else if (type == Variant::get_type_name(Variant::PACKED_INT32_ARRAY)) {
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
Array values = d[VALUES];
PackedInt32Array arr;
arr.resize(values.size());
for (int i = 0; i < arr.size(); i++) {
arr.write[i] = values[i];
}
return arr;
} else if (type == Variant::get_type_name(Variant::PACKED_INT64_ARRAY)) {
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
Array values = d[VALUES];
PackedInt64Array arr;
arr.resize(values.size());
for (int i = 0; i < arr.size(); i++) {
arr.write[i] = values[i];
}
return arr;
} else if (type == Variant::get_type_name(Variant::PACKED_FLOAT32_ARRAY)) {
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
Array values = d[VALUES];
PackedFloat32Array arr;
arr.resize(values.size());
for (int i = 0; i < arr.size(); i++) {
arr.write[i] = values[i];
}
return arr;
} else if (type == Variant::get_type_name(Variant::PACKED_FLOAT64_ARRAY)) {
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
Array values = d[VALUES];
PackedFloat64Array arr;
arr.resize(values.size());
for (int i = 0; i < arr.size(); i++) {
arr.write[i] = values[i];
}
return arr;
} else if (type == Variant::get_type_name(Variant::PACKED_STRING_ARRAY)) {
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
Array values = d[VALUES];
PackedStringArray arr;
arr.resize(values.size());
for (int i = 0; i < arr.size(); i++) {
arr.write[i] = values[i];
}
return arr;
} else if (type == Variant::get_type_name(Variant::PACKED_VECTOR2_ARRAY)) {
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
Array values = d[VALUES];
ERR_FAIL_COND_V(values.size() % 2 != 0, Variant());
PackedVector2Array arr;
arr.resize(values.size() / 2);
for (int i = 0; i < arr.size(); i++) {
arr.write[i] = Vector2(values[i * 2 + 0], values[i * 2 + 1]);
}
return arr;
} else if (type == Variant::get_type_name(Variant::PACKED_VECTOR3_ARRAY)) {
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
Array values = d[VALUES];
ERR_FAIL_COND_V(values.size() % 3 != 0, Variant());
PackedVector3Array arr;
arr.resize(values.size() / 3);
for (int i = 0; i < arr.size(); i++) {
arr.write[i] = Vector3(values[i * 3 + 0], values[i * 3 + 1], values[i * 3 + 2]);
}
return arr;
} else if (type == Variant::get_type_name(Variant::PACKED_COLOR_ARRAY)) {
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
Array values = d[VALUES];
ERR_FAIL_COND_V(values.size() % 4 != 0, Variant());
PackedColorArray arr;
arr.resize(values.size() / 4);
for (int i = 0; i < arr.size(); i++) {
arr.write[i] = Color(values[i * 4 + 0], values[i * 4 + 1], values[i * 4 + 2], values[i * 4 + 3]);
}
return arr;
} else if (type == Variant::get_type_name(Variant::PACKED_VECTOR4_ARRAY)) {
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
Array values = d[VALUES];
ERR_FAIL_COND_V(values.size() % 4 != 0, Variant());
PackedVector4Array arr;
arr.resize(values.size() / 4);
for (int i = 0; i < arr.size(); i++) {
arr.write[i] = Vector4(values[i * 4 + 0], values[i * 4 + 1], values[i * 4 + 2], values[i * 4 + 3]);
}
return arr;
} else {
return Variant();
}
} else {
// Regular dictionary with string keys.
List<Variant> keys;
d.get_key_list(&keys);
Dictionary r;
for (const Variant &K : keys) {
r[K] = to_native(d[K], PASS_ARG);
}
return r;
}
} break;
case Variant::ARRAY: {
Array arr = p_json;
Array ret;
ret.resize(arr.size());
for (int i = 0; i < arr.size(); i++) {
ret[i] = to_native(arr[i], PASS_ARG);
}
return ret;
} break;
default: {
ERR_PRINT(vformat("Unhandled conversion from JSON type '%s' to native Variant type.", Variant::get_type_name(p_json.get_type())));
return Variant();
}
}
return Variant();
}
#undef GDTYPE
#undef VALUES
#undef PASS_ARG
////
////////////

View File

@ -94,9 +94,6 @@ public:
void set_data(const Variant &p_data);
inline int get_error_line() const { return err_line; }
inline String get_error_message() const { return err_str; }
static Variant from_native(const Variant &p_variant, bool p_allow_classes = false, bool p_allow_scripts = false);
static Variant to_native(const Variant &p_json, bool p_allow_classes = false, bool p_allow_scripts = false);
};
class ResourceFormatLoaderJSON : public ResourceFormatLoader {

View File

@ -84,7 +84,11 @@ void Logger::log_error(const char *p_function, const char *p_file, int p_line, c
err_details = p_code;
}
logf_error("%s: %s\n", err_type, err_details);
if (p_editor_notify) {
logf_error("%s: %s\n", err_type, err_details);
} else {
logf_error("USER %s: %s\n", err_type, err_details);
}
logf_error(" at: %s (%s:%i)\n", p_function, p_file, p_line);
}

View File

@ -36,7 +36,7 @@
class PackedDataContainer : public Resource {
GDCLASS(PackedDataContainer, Resource);
enum : uint32_t {
enum {
TYPE_DICT = 0xFFFFFFFF,
TYPE_ARRAY = 0xFFFFFFFE,
};

View File

@ -299,7 +299,7 @@ Ref<StreamPeer> PacketPeerStream::get_stream_peer() const {
void PacketPeerStream::set_input_buffer_max_size(int p_max_size) {
ERR_FAIL_COND_MSG(p_max_size < 0, "Max size of input buffer size cannot be smaller than 0.");
// WARNING: May lose packets.
//warning may lose packets
ERR_FAIL_COND_MSG(ring_buffer.data_left(), "Buffer in use, resizing would cause loss of data.");
ring_buffer.resize(nearest_shift(next_power_of_2(p_max_size + 4)) - 1);
input_buffer.resize(next_power_of_2(p_max_size + 4));

View File

@ -32,12 +32,12 @@
#include "core/config/project_settings.h"
#include "core/io/file_access.h"
PacketPeerDTLS *(*PacketPeerDTLS::_create)(bool p_notify_postinitialize) = nullptr;
PacketPeerDTLS *(*PacketPeerDTLS::_create)() = nullptr;
bool PacketPeerDTLS::available = false;
PacketPeerDTLS *PacketPeerDTLS::create(bool p_notify_postinitialize) {
PacketPeerDTLS *PacketPeerDTLS::create() {
if (_create) {
return _create(p_notify_postinitialize);
return _create();
}
return nullptr;
}

View File

@ -38,7 +38,7 @@ class PacketPeerDTLS : public PacketPeer {
GDCLASS(PacketPeerDTLS, PacketPeer);
protected:
static PacketPeerDTLS *(*_create)(bool p_notify_postinitialize);
static PacketPeerDTLS *(*_create)();
static void _bind_methods();
static bool available;
@ -57,7 +57,7 @@ public:
virtual void disconnect_from_peer() = 0;
virtual Status get_status() const = 0;
static PacketPeerDTLS *create(bool p_notify_postinitialize = true);
static PacketPeerDTLS *create();
static bool is_available();
PacketPeerDTLS() {}

View File

@ -47,12 +47,12 @@ static int _get_pad(int p_alignment, int p_n) {
}
void PCKPacker::_bind_methods() {
ClassDB::bind_method(D_METHOD("pck_start", "pck_path", "alignment", "key", "encrypt_directory"), &PCKPacker::pck_start, DEFVAL(32), DEFVAL("0000000000000000000000000000000000000000000000000000000000000000"), DEFVAL(false));
ClassDB::bind_method(D_METHOD("pck_start", "pck_name", "alignment", "key", "encrypt_directory"), &PCKPacker::pck_start, DEFVAL(32), DEFVAL("0000000000000000000000000000000000000000000000000000000000000000"), DEFVAL(false));
ClassDB::bind_method(D_METHOD("add_file", "pck_path", "source_path", "encrypt"), &PCKPacker::add_file, DEFVAL(false));
ClassDB::bind_method(D_METHOD("flush", "verbose"), &PCKPacker::flush, DEFVAL(false));
}
Error PCKPacker::pck_start(const String &p_pck_path, int p_alignment, const String &p_key, bool p_encrypt_directory) {
Error PCKPacker::pck_start(const String &p_file, int p_alignment, const String &p_key, bool p_encrypt_directory) {
ERR_FAIL_COND_V_MSG((p_key.is_empty() || !p_key.is_valid_hex_number(false) || p_key.length() != 64), ERR_CANT_CREATE, "Invalid Encryption Key (must be 64 characters long).");
ERR_FAIL_COND_V_MSG(p_alignment <= 0, ERR_CANT_CREATE, "Invalid alignment, must be greater then 0.");
@ -83,8 +83,8 @@ Error PCKPacker::pck_start(const String &p_pck_path, int p_alignment, const Stri
}
enc_dir = p_encrypt_directory;
file = FileAccess::open(p_pck_path, FileAccess::WRITE);
ERR_FAIL_COND_V_MSG(file.is_null(), ERR_CANT_CREATE, "Can't open file to write: " + String(p_pck_path) + ".");
file = FileAccess::open(p_file, FileAccess::WRITE);
ERR_FAIL_COND_V_MSG(file.is_null(), ERR_CANT_CREATE, "Can't open file to write: " + String(p_file) + ".");
alignment = p_alignment;
@ -106,7 +106,7 @@ Error PCKPacker::pck_start(const String &p_pck_path, int p_alignment, const Stri
return OK;
}
Error PCKPacker::add_file(const String &p_pck_path, const String &p_src, bool p_encrypt) {
Error PCKPacker::add_file(const String &p_file, const String &p_src, bool p_encrypt) {
ERR_FAIL_COND_V_MSG(file.is_null(), ERR_INVALID_PARAMETER, "File must be opened before use.");
Ref<FileAccess> f = FileAccess::open(p_src, FileAccess::READ);
@ -117,7 +117,7 @@ Error PCKPacker::add_file(const String &p_pck_path, const String &p_src, bool p_
File pf;
// Simplify path here and on every 'files' access so that paths that have extra '/'
// symbols in them still match to the MD5 hash for the saved path.
pf.path = p_pck_path.simplify_path();
pf.path = p_file.simplify_path();
pf.src_path = p_src;
pf.ofs = ofs;
pf.size = f->get_length();

View File

@ -58,8 +58,8 @@ class PCKPacker : public RefCounted {
Vector<File> files;
public:
Error pck_start(const String &p_pck_path, int p_alignment = 32, const String &p_key = "0000000000000000000000000000000000000000000000000000000000000000", bool p_encrypt_directory = false);
Error add_file(const String &p_pck_path, const String &p_src, bool p_encrypt = false);
Error pck_start(const String &p_file, int p_alignment = 32, const String &p_key = "0000000000000000000000000000000000000000000000000000000000000000", bool p_encrypt_directory = false);
Error add_file(const String &p_file, const String &p_src, bool p_encrypt = false);
Error flush(bool p_verbose = false);
PCKPacker() {}

View File

@ -814,7 +814,7 @@ bool PList::load_string(const String &p_string, String &r_err_out) {
}
PackedByteArray PList::save_asn1() const {
if (root.is_null()) {
if (root == nullptr) {
ERR_FAIL_V_MSG(PackedByteArray(), "PList: Invalid PList, no root node.");
}
size_t size = root->get_asn1_size(1);
@ -848,7 +848,7 @@ PackedByteArray PList::save_asn1() const {
}
String PList::save_text() const {
if (root.is_null()) {
if (root == nullptr) {
ERR_FAIL_V_MSG(String(), "PList: Invalid PList, no root node.");
}

View File

@ -40,12 +40,12 @@
#include <stdio.h>
void Resource::emit_changed() {
if (ResourceLoader::is_within_load() && !Thread::is_main_thread()) {
ResourceLoader::resource_changed_emit(this);
return;
if (ResourceLoader::is_within_load() && MessageQueue::get_main_singleton() != MessageQueue::get_singleton() && !MessageQueue::get_singleton()->is_flushing()) {
// Let the connection happen on the call queue, later, since signals are not thread-safe.
call_deferred("emit_signal", CoreStringName(changed));
} else {
emit_signal(CoreStringName(changed));
}
emit_signal(CoreStringName(changed));
}
void Resource::_resource_path_changed() {
@ -60,33 +60,33 @@ void Resource::set_path(const String &p_path, bool p_take_over) {
p_take_over = false; // Can't take over an empty path
}
{
MutexLock lock(ResourceCache::lock);
ResourceCache::lock.lock();
if (!path_cache.is_empty()) {
ResourceCache::resources.erase(path_cache);
}
if (!path_cache.is_empty()) {
ResourceCache::resources.erase(path_cache);
}
path_cache = "";
path_cache = "";
Ref<Resource> existing = ResourceCache::get_ref(p_path);
Ref<Resource> existing = ResourceCache::get_ref(p_path);
if (existing.is_valid()) {
if (p_take_over) {
existing->path_cache = String();
ResourceCache::resources.erase(p_path);
} else {
ERR_FAIL_MSG("Another resource is loaded from path '" + p_path + "' (possible cyclic resource inclusion).");
}
}
path_cache = p_path;
if (!path_cache.is_empty()) {
ResourceCache::resources[path_cache] = this;
if (existing.is_valid()) {
if (p_take_over) {
existing->path_cache = String();
ResourceCache::resources.erase(p_path);
} else {
ResourceCache::lock.unlock();
ERR_FAIL_MSG("Another resource is loaded from path '" + p_path + "' (possible cyclic resource inclusion).");
}
}
path_cache = p_path;
if (!path_cache.is_empty()) {
ResourceCache::resources[path_cache] = this;
}
ResourceCache::lock.unlock();
_resource_path_changed();
}
@ -96,7 +96,6 @@ String Resource::get_path() const {
void Resource::set_path_cache(const String &p_path) {
path_cache = p_path;
GDVIRTUAL_CALL(_set_path_cache, p_path);
}
String Resource::generate_scene_unique_id() {
@ -167,29 +166,28 @@ bool Resource::editor_can_reload_from_file() {
}
void Resource::connect_changed(const Callable &p_callable, uint32_t p_flags) {
if (ResourceLoader::is_within_load() && !Thread::is_main_thread()) {
ResourceLoader::resource_changed_connect(this, p_callable, p_flags);
if (ResourceLoader::is_within_load() && MessageQueue::get_main_singleton() != MessageQueue::get_singleton() && !MessageQueue::get_singleton()->is_flushing()) {
// Let the check and connection happen on the call queue, later, since signals are not thread-safe.
callable_mp(this, &Resource::connect_changed).call_deferred(p_callable, p_flags);
return;
}
if (!is_connected(CoreStringName(changed), p_callable) || p_flags & CONNECT_REFERENCE_COUNTED) {
connect(CoreStringName(changed), p_callable, p_flags);
}
}
void Resource::disconnect_changed(const Callable &p_callable) {
if (ResourceLoader::is_within_load() && !Thread::is_main_thread()) {
ResourceLoader::resource_changed_disconnect(this, p_callable);
if (ResourceLoader::is_within_load() && MessageQueue::get_main_singleton() != MessageQueue::get_singleton() && !MessageQueue::get_singleton()->is_flushing()) {
// Let the check and disconnection happen on the call queue, later, since signals are not thread-safe.
callable_mp(this, &Resource::disconnect_changed).call_deferred(p_callable);
return;
}
if (is_connected(CoreStringName(changed), p_callable)) {
disconnect(CoreStringName(changed), p_callable);
}
}
void Resource::reset_state() {
GDVIRTUAL_CALL(_reset_state);
}
Error Resource::copy_from(const Ref<Resource> &p_resource) {
@ -418,15 +416,21 @@ void Resource::_take_over_path(const String &p_path) {
}
RID Resource::get_rid() const {
RID ret;
if (!GDVIRTUAL_CALL(_get_rid, ret)) {
#ifndef DISABLE_DEPRECATED
if (_get_extension() && _get_extension()->get_rid) {
ret = RID::from_uint64(_get_extension()->get_rid(_get_extension_instance()));
if (get_script_instance()) {
Callable::CallError ce;
RID ret = get_script_instance()->callp(SNAME("_get_rid"), nullptr, 0, ce);
if (ce.error == Callable::CallError::CALL_OK && ret.is_valid()) {
return ret;
}
#endif
}
return ret;
if (_get_extension() && _get_extension()->get_rid) {
RID ret = RID::from_uint64(_get_extension()->get_rid(_get_extension_instance()));
if (ret.is_valid()) {
return ret;
}
}
return RID();
}
#ifdef TOOLS_ENABLED
@ -488,18 +492,20 @@ void Resource::set_as_translation_remapped(bool p_remapped) {
return;
}
MutexLock lock(ResourceCache::lock);
ResourceCache::lock.lock();
if (p_remapped) {
ResourceLoader::remapped_list.add(&remapped_list);
} else {
ResourceLoader::remapped_list.remove(&remapped_list);
}
ResourceCache::lock.unlock();
}
#ifdef TOOLS_ENABLED
//helps keep IDs same number when loading/saving scenes. -1 clears ID and it Returns -1 when no id stored
void Resource::set_id_for_path(const String &p_path, const String &p_id) {
#ifdef TOOLS_ENABLED
if (p_id.is_empty()) {
ResourceCache::path_cache_lock.write_lock();
ResourceCache::resource_path_cache[p_path].erase(get_path());
@ -509,11 +515,9 @@ void Resource::set_id_for_path(const String &p_path, const String &p_id) {
ResourceCache::resource_path_cache[p_path][get_path()] = p_id;
ResourceCache::path_cache_lock.write_unlock();
}
#endif
}
String Resource::get_id_for_path(const String &p_path) const {
#ifdef TOOLS_ENABLED
ResourceCache::path_cache_lock.read_lock();
if (ResourceCache::resource_path_cache[p_path].has(get_path())) {
String result = ResourceCache::resource_path_cache[p_path][get_path()];
@ -523,16 +527,13 @@ String Resource::get_id_for_path(const String &p_path) const {
ResourceCache::path_cache_lock.read_unlock();
return "";
}
#else
return "";
#endif
}
#endif
void Resource::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_path", "path"), &Resource::_set_path);
ClassDB::bind_method(D_METHOD("take_over_path", "path"), &Resource::_take_over_path);
ClassDB::bind_method(D_METHOD("get_path"), &Resource::get_path);
ClassDB::bind_method(D_METHOD("set_path_cache", "path"), &Resource::set_path_cache);
ClassDB::bind_method(D_METHOD("set_name", "name"), &Resource::set_name);
ClassDB::bind_method(D_METHOD("get_name"), &Resource::get_name);
ClassDB::bind_method(D_METHOD("get_rid"), &Resource::get_rid);
@ -540,12 +541,6 @@ void Resource::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_local_to_scene"), &Resource::is_local_to_scene);
ClassDB::bind_method(D_METHOD("get_local_scene"), &Resource::get_local_scene);
ClassDB::bind_method(D_METHOD("setup_local_to_scene"), &Resource::setup_local_to_scene);
ClassDB::bind_method(D_METHOD("reset_state"), &Resource::reset_state);
ClassDB::bind_method(D_METHOD("set_id_for_path", "path", "id"), &Resource::set_id_for_path);
ClassDB::bind_method(D_METHOD("get_id_for_path", "path"), &Resource::get_id_for_path);
ClassDB::bind_method(D_METHOD("is_built_in"), &Resource::is_built_in);
ClassDB::bind_static_method("Resource", D_METHOD("generate_scene_unique_id"), &Resource::generate_scene_unique_id);
ClassDB::bind_method(D_METHOD("set_scene_unique_id", "id"), &Resource::set_scene_unique_id);
@ -563,10 +558,11 @@ void Resource::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "resource_name"), "set_name", "get_name");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "resource_scene_unique_id", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_scene_unique_id", "get_scene_unique_id");
MethodInfo get_rid_bind("_get_rid");
get_rid_bind.return_val.type = Variant::RID;
::ClassDB::add_virtual_method(get_class_static(), get_rid_bind, true, Vector<String>(), true);
GDVIRTUAL_BIND(_setup_local_to_scene);
GDVIRTUAL_BIND(_get_rid);
GDVIRTUAL_BIND(_reset_state);
GDVIRTUAL_BIND(_set_path_cache, "path");
}
Resource::Resource() :
@ -577,13 +573,14 @@ Resource::~Resource() {
return;
}
MutexLock lock(ResourceCache::lock);
ResourceCache::lock.lock();
// Only unregister from the cache if this is the actual resource listed there.
// (Other resources can have the same value in `path_cache` if loaded with `CACHE_IGNORE`.)
HashMap<String, Resource *>::Iterator E = ResourceCache::resources.find(path_cache);
if (likely(E && E->value == this)) {
ResourceCache::resources.remove(E);
}
ResourceCache::lock.unlock();
}
HashMap<String, Resource *> ResourceCache::resources;
@ -612,21 +609,19 @@ void ResourceCache::clear() {
}
bool ResourceCache::has(const String &p_path) {
Resource **res = nullptr;
lock.lock();
{
MutexLock mutex_lock(lock);
Resource **res = resources.getptr(p_path);
res = resources.getptr(p_path);
if (res && (*res)->get_reference_count() == 0) {
// This resource is in the process of being deleted, ignore its existence.
(*res)->path_cache = String();
resources.erase(p_path);
res = nullptr;
}
if (res && (*res)->get_reference_count() == 0) {
// This resource is in the process of being deleted, ignore its existence.
(*res)->path_cache = String();
resources.erase(p_path);
res = nullptr;
}
lock.unlock();
if (!res) {
return false;
}
@ -636,27 +631,28 @@ bool ResourceCache::has(const String &p_path) {
Ref<Resource> ResourceCache::get_ref(const String &p_path) {
Ref<Resource> ref;
{
MutexLock mutex_lock(lock);
Resource **res = resources.getptr(p_path);
lock.lock();
if (res) {
ref = Ref<Resource>(*res);
}
Resource **res = resources.getptr(p_path);
if (res && !ref.is_valid()) {
// This resource is in the process of being deleted, ignore its existence
(*res)->path_cache = String();
resources.erase(p_path);
res = nullptr;
}
if (res) {
ref = Ref<Resource>(*res);
}
if (res && !ref.is_valid()) {
// This resource is in the process of being deleted, ignore its existence
(*res)->path_cache = String();
resources.erase(p_path);
res = nullptr;
}
lock.unlock();
return ref;
}
void ResourceCache::get_cached_resources(List<Ref<Resource>> *p_resources) {
MutexLock mutex_lock(lock);
lock.lock();
LocalVector<String> to_remove;
@ -676,9 +672,14 @@ void ResourceCache::get_cached_resources(List<Ref<Resource>> *p_resources) {
for (const String &E : to_remove) {
resources.erase(E);
}
lock.unlock();
}
int ResourceCache::get_cached_resource_count() {
MutexLock mutex_lock(lock);
return resources.size();
lock.lock();
int rc = resources.size();
lock.unlock();
return rc;
}

View File

@ -87,11 +87,6 @@ protected:
virtual void reset_local_to_scene();
GDVIRTUAL0(_setup_local_to_scene);
GDVIRTUAL0RC(RID, _get_rid);
GDVIRTUAL1C(_set_path_cache, String);
GDVIRTUAL0(_reset_state);
public:
static Node *(*_get_local_scene_func)(); //used by editor
static void (*_update_configuration_warning)(); //used by editor
@ -147,9 +142,11 @@ public:
virtual RID get_rid() const; // some resources may offer conversion to RID
#ifdef TOOLS_ENABLED
//helps keep IDs same number when loading/saving scenes. -1 clears ID and it Returns -1 when no id stored
void set_id_for_path(const String &p_path, const String &p_id);
String get_id_for_path(const String &p_path) const;
#endif
Resource();
~Resource();

View File

@ -845,29 +845,14 @@ Error ResourceLoaderBinary::load() {
}
}
if (ClassDB::has_property(res->get_class_name(), name)) {
if (value.get_type() == Variant::ARRAY) {
Array set_array = value;
bool is_get_valid = false;
Variant get_value = res->get(name, &is_get_valid);
if (is_get_valid && get_value.get_type() == Variant::ARRAY) {
Array get_array = get_value;
if (!set_array.is_same_typed(get_array)) {
value = Array(set_array, get_array.get_typed_builtin(), get_array.get_typed_class_name(), get_array.get_typed_script());
}
}
}
if (value.get_type() == Variant::DICTIONARY) {
Dictionary set_dict = value;
bool is_get_valid = false;
Variant get_value = res->get(name, &is_get_valid);
if (is_get_valid && get_value.get_type() == Variant::DICTIONARY) {
Dictionary get_dict = get_value;
if (!set_dict.is_same_typed(get_dict)) {
value = Dictionary(set_dict, get_dict.get_typed_key_builtin(), get_dict.get_typed_key_class_name(), get_dict.get_typed_key_script(),
get_dict.get_typed_value_builtin(), get_dict.get_typed_value_class_name(), get_dict.get_typed_value_script());
}
if (value.get_type() == Variant::ARRAY) {
Array set_array = value;
bool is_get_valid = false;
Variant get_value = res->get(name, &is_get_valid);
if (is_get_valid && get_value.get_type() == Variant::ARRAY) {
Array get_array = get_value;
if (!set_array.is_same_typed(get_array)) {
value = Array(set_array, get_array.get_typed_builtin(), get_array.get_typed_class_name(), get_array.get_typed_script());
}
}
}
@ -2079,8 +2064,6 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant
case Variant::DICTIONARY: {
Dictionary d = p_variant;
_find_resources(d.get_typed_key_script());
_find_resources(d.get_typed_value_script());
List<Variant> keys;
d.get_key_list(&keys);
for (const Variant &E : keys) {

View File

@ -35,8 +35,6 @@
#include "core/os/os.h"
#include "core/variant/variant_parser.h"
ResourceFormatImporterLoadOnStartup ResourceImporter::load_on_startup = nullptr;
bool ResourceFormatImporter::SortImporterByName::operator()(const Ref<ResourceImporter> &p_a, const Ref<ResourceImporter> &p_b) const {
return p_a->get_importer_name() < p_b->get_importer_name();
}
@ -139,20 +137,6 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy
}
Ref<Resource> ResourceFormatImporter::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
#ifdef TOOLS_ENABLED
// When loading a resource on startup, we use the load_on_startup callback,
// which executes the loading in the EditorFileSystem. It can reimport
// the resource and retry the load, allowing the resource to be loaded
// even if it is not yet imported.
if (ResourceImporter::load_on_startup != nullptr) {
return ResourceImporter::load_on_startup(this, p_path, r_error, p_use_sub_threads, r_progress, p_cache_mode);
}
#endif
return load_internal(p_path, r_error, p_use_sub_threads, r_progress, p_cache_mode, false);
}
Ref<Resource> ResourceFormatImporter::load_internal(const String &p_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode, bool p_silence_errors) {
PathAndType pat;
Error err = _get_path_and_type(p_path, pat);
@ -164,13 +148,6 @@ Ref<Resource> ResourceFormatImporter::load_internal(const String &p_path, Error
return Ref<Resource>();
}
if (p_silence_errors) {
// Note: Some importers do not create files in the .godot folder, so we need to check if the path is empty.
if (!pat.path.is_empty() && !FileAccess::exists(pat.path)) {
return Ref<Resource>();
}
}
Ref<Resource> res = ResourceLoader::_load(pat.path, p_path, pat.type, p_cache_mode, r_error, p_use_sub_threads, r_progress);
#ifdef TOOLS_ENABLED
@ -387,23 +364,6 @@ ResourceUID::ID ResourceFormatImporter::get_resource_uid(const String &p_path) c
return pat.uid;
}
Error ResourceFormatImporter::get_resource_import_info(const String &p_path, StringName &r_type, ResourceUID::ID &r_uid, String &r_import_group_file) const {
PathAndType pat;
Error err = _get_path_and_type(p_path, pat);
if (err == OK) {
r_type = pat.type;
r_uid = pat.uid;
r_import_group_file = pat.group_file;
} else {
r_type = "";
r_uid = ResourceUID::INVALID_ID;
r_import_group_file = "";
}
return err;
}
Variant ResourceFormatImporter::get_resource_metadata(const String &p_path) const {
PathAndType pat;
Error err = _get_path_and_type(p_path, pat);
@ -507,7 +467,7 @@ bool ResourceFormatImporter::are_import_settings_valid(const String &p_path) con
for (int i = 0; i < importers.size(); i++) {
if (importers[i]->get_importer_name() == pat.importer) {
if (!importers[i]->are_import_settings_valid(p_path, pat.metadata)) { //importer thinks this is not valid
if (!importers[i]->are_import_settings_valid(p_path)) { //importer thinks this is not valid
return false;
}
}

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