mirror of
https://github.com/godotengine/godot.git
synced 2025-10-19 16:03:29 +00:00
Compare commits
95 commits
master
...
4.5.1-stab
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f62fdbde15 | ||
![]() |
8522dfd066 | ||
![]() |
41acf6a75d | ||
![]() |
d3b052df8f | ||
![]() |
d632731ba8 | ||
![]() |
eb7c869f84 | ||
![]() |
183f6cdd63 | ||
![]() |
83a78186ca | ||
![]() |
1c078fee01 | ||
![]() |
07596299e6 | ||
![]() |
ce8f9dfea8 | ||
![]() |
e146c46214 | ||
![]() |
d18aaaa5d3 | ||
![]() |
69796bf7d6 | ||
![]() |
7f9232c84e | ||
![]() |
1d50fc26b4 | ||
![]() |
b891558050 | ||
![]() |
bcd06b478a | ||
![]() |
29f8d9f504 | ||
![]() |
d92413782b | ||
![]() |
a3b924766d | ||
![]() |
0234028f7c | ||
![]() |
a5fa61bcfe | ||
![]() |
670c0707a7 | ||
![]() |
368f0c75c3 | ||
![]() |
33b6898494 | ||
![]() |
25415a831e | ||
![]() |
ccf3976dc5 | ||
![]() |
48466413c1 | ||
![]() |
b0a2063d8f | ||
![]() |
24bc49d557 | ||
![]() |
e788127654 | ||
![]() |
9058a406ea | ||
![]() |
d841779578 | ||
![]() |
5bd344b259 | ||
![]() |
2d7f6f32ce | ||
![]() |
3ac14dfe01 | ||
![]() |
0e179c0e5c | ||
![]() |
42ef49fa99 | ||
![]() |
9d08253661 | ||
![]() |
632d29232b | ||
![]() |
90d1d9e957 | ||
![]() |
f12cc7a014 | ||
![]() |
95d452fad9 | ||
![]() |
c4a375ca55 | ||
![]() |
452332621f | ||
![]() |
a156af98c3 | ||
![]() |
28f4d5d6a7 | ||
![]() |
fb9d73438d | ||
![]() |
b70ddd29a0 | ||
![]() |
8a9ef4a891 | ||
![]() |
d72311f6ae | ||
![]() |
dd92108759 | ||
![]() |
0990896d91 | ||
![]() |
f5b146cc61 | ||
![]() |
3f97c33dac | ||
![]() |
e6cf63cb88 | ||
![]() |
1aed7cefdd | ||
![]() |
2cb6d30dd1 | ||
![]() |
c834443ef1 | ||
![]() |
899ef8df88 | ||
![]() |
eed94508f0 | ||
![]() |
da0c3122f1 | ||
![]() |
757dbe621f | ||
![]() |
6c180272b4 | ||
![]() |
354b02f92d | ||
![]() |
b963cf15ef | ||
![]() |
0f17c184e4 | ||
![]() |
50aad8e62b | ||
![]() |
25ed1b3811 | ||
![]() |
9166e4d5a7 | ||
![]() |
a52de93373 | ||
![]() |
1e743ad0ab | ||
![]() |
eca3785100 | ||
![]() |
d488e962df | ||
![]() |
928ee70231 | ||
![]() |
777649d574 | ||
![]() |
79dd13f6fb | ||
![]() |
cb878d90a2 | ||
![]() |
6bf74272f9 | ||
![]() |
6f121b29b9 | ||
![]() |
4aedc06168 | ||
![]() |
49d2dbc027 | ||
![]() |
68ea3d8aad | ||
![]() |
168f401db6 | ||
![]() |
9abec0666e | ||
![]() |
0f760c7c97 | ||
![]() |
35833f8dbf | ||
![]() |
fcd2ab70e0 | ||
![]() |
acab46d09e | ||
![]() |
11e6e4afef | ||
![]() |
4e62b91749 | ||
![]() |
63b1d72795 | ||
![]() |
e13771d562 | ||
![]() |
7176fc231f |
1954 changed files with 24137 additions and 51894 deletions
24
.github/CODEOWNERS
vendored
24
.github/CODEOWNERS
vendored
|
@ -45,6 +45,8 @@
|
||||||
# Editor
|
# Editor
|
||||||
|
|
||||||
/editor/ @godotengine/docks
|
/editor/ @godotengine/docks
|
||||||
|
/editor/script/ @godotengine/script-editor
|
||||||
|
/editor/shader/ @godotengine/script-editor @godotengine/shaders
|
||||||
/editor/animation/ @godotengine/animation
|
/editor/animation/ @godotengine/animation
|
||||||
/editor/audio/ @godotengine/audio
|
/editor/audio/ @godotengine/audio
|
||||||
/editor/debugger/ @godotengine/debugger
|
/editor/debugger/ @godotengine/debugger
|
||||||
|
@ -55,12 +57,10 @@
|
||||||
/editor/import/ @godotengine/import
|
/editor/import/ @godotengine/import
|
||||||
/editor/inspector/ @godotengine/docks
|
/editor/inspector/ @godotengine/docks
|
||||||
/editor/scene/2d/ @godotengine/2d-editor
|
/editor/scene/2d/ @godotengine/2d-editor
|
||||||
/editor/scene/2d/physics/ @godotengine/2d-editor @godotengine/physics
|
/editor/scene/2d/physics @godotengine/2d-editor @godotengine/physics
|
||||||
/editor/scene/3d/ @godotengine/3d-editor
|
/editor/scene/3d/ @godotengine/3d-editor
|
||||||
/editor/scene/3d/physics/ @godotengine/3d-editor @godotengine/physics
|
/editor/scene/3d/physics @godotengine/3d-editor @godotengine/physics
|
||||||
/editor/scene/gui/ @godotengine/gui-nodes
|
/editor/scene/gui/ @godotengine/gui-nodes
|
||||||
/editor/script/ @godotengine/script-editor
|
|
||||||
/editor/shader/ @godotengine/script-editor @godotengine/shaders
|
|
||||||
/editor/themes/ @godotengine/usability @godotengine/gui-nodes
|
/editor/themes/ @godotengine/usability @godotengine/gui-nodes
|
||||||
/editor/translations/ @godotengine/usability
|
/editor/translations/ @godotengine/usability
|
||||||
|
|
||||||
|
@ -205,12 +205,9 @@
|
||||||
# Scene
|
# Scene
|
||||||
|
|
||||||
/scene/2d/ @godotengine/2d-nodes
|
/scene/2d/ @godotengine/2d-nodes
|
||||||
/scene/2d/navigation/ @godotengine/2d-nodes @godotengine/navigation
|
|
||||||
/scene/2d/physics/ @godotengine/2d-nodes @godotengine/physics
|
/scene/2d/physics/ @godotengine/2d-nodes @godotengine/physics
|
||||||
/scene/3d/ @godotengine/3d-nodes
|
/scene/3d/ @godotengine/3d-nodes
|
||||||
/scene/3d/navigation/ @godotengine/3d-nodes @godotengine/navigation
|
|
||||||
/scene/3d/physics/ @godotengine/3d-nodes @godotengine/physics
|
/scene/3d/physics/ @godotengine/3d-nodes @godotengine/physics
|
||||||
/scene/3d/xr/ @godotengine/3d-nodes @godotengine/xr
|
|
||||||
/scene/animation/ @godotengine/animation
|
/scene/animation/ @godotengine/animation
|
||||||
/scene/audio/ @godotengine/audio
|
/scene/audio/ @godotengine/audio
|
||||||
/scene/debugger/ @godotengine/debugger
|
/scene/debugger/ @godotengine/debugger
|
||||||
|
@ -230,13 +227,18 @@
|
||||||
|
|
||||||
# Servers
|
# Servers
|
||||||
|
|
||||||
|
/servers/**/audio_* @godotengine/audio
|
||||||
|
/servers/**/camera_* @godotengine/xr
|
||||||
|
/servers/**/debugger_* @godotengine/debugger
|
||||||
|
/servers/**/navigation_* @godotengine/navigation
|
||||||
|
/servers/**/physics_* @godotengine/physics
|
||||||
|
/servers/**/rendering_* @godotengine/rendering
|
||||||
|
/servers/**/text_* @godotengine/gui-nodes
|
||||||
|
/servers/**/xr_* @godotengine/xr
|
||||||
/servers/audio/ @godotengine/audio
|
/servers/audio/ @godotengine/audio
|
||||||
/servers/camera/ @godotengine/xr
|
/servers/camera/ @godotengine/xr
|
||||||
/servers/debugger/ @godotengine/debugger
|
/servers/debugger/ @godotengine/debugger
|
||||||
/servers/navigation_2d/ @godotengine/navigation
|
/servers/navigation/ @godotengine/navigation
|
||||||
/servers/navigation_3d/ @godotengine/navigation
|
|
||||||
/servers/physics_2d/ @godotengine/physics
|
|
||||||
/servers/physics_3d/ @godotengine/physics
|
|
||||||
/servers/rendering/ @godotengine/rendering
|
/servers/rendering/ @godotengine/rendering
|
||||||
/servers/text/ @godotengine/gui-nodes
|
/servers/text/ @godotengine/gui-nodes
|
||||||
/servers/xr/ @godotengine/xr
|
/servers/xr/ @godotengine/xr
|
||||||
|
|
2
.github/actions/godot-deps/action.yml
vendored
2
.github/actions/godot-deps/action.yml
vendored
|
@ -10,7 +10,7 @@ inputs:
|
||||||
default: x64
|
default: x64
|
||||||
scons-version:
|
scons-version:
|
||||||
description: The SCons version to use.
|
description: The SCons version to use.
|
||||||
default: 4.10.0
|
default: 4.9.0
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: composite
|
using: composite
|
||||||
|
|
10
.github/workflows/android_builds.yml
vendored
10
.github/workflows/android_builds.yml
vendored
|
@ -26,14 +26,14 @@ jobs:
|
||||||
arch=arm64
|
arch=arm64
|
||||||
production=yes
|
production=yes
|
||||||
|
|
||||||
- name: Template arm32 (target=template_debug, arch=arm32)
|
- name: Template arm32 (target=template_release, arch=arm32)
|
||||||
cache-name: android-template-arm32
|
cache-name: android-template-arm32
|
||||||
target: template_debug
|
target: template_release
|
||||||
scons-flags: arch=arm32
|
scons-flags: arch=arm32
|
||||||
|
|
||||||
- name: Template arm64 (target=template_debug, arch=arm64)
|
- name: Template arm64 (target=template_release, arch=arm64)
|
||||||
cache-name: android-template-arm64
|
cache-name: android-template-arm64
|
||||||
target: template_debug
|
target: template_release
|
||||||
scons-flags: arch=arm64
|
scons-flags: arch=arm64
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
@ -82,7 +82,7 @@ jobs:
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|
||||||
- name: Generate Godot templates
|
- name: Generate Godot templates
|
||||||
if: matrix.target == 'template_debug'
|
if: matrix.target == 'template_release'
|
||||||
run: |
|
run: |
|
||||||
cd platform/android/java
|
cd platform/android/java
|
||||||
./gradlew generateGodotTemplates
|
./gradlew generateGodotTemplates
|
||||||
|
|
2
.github/workflows/linux_builds.yml
vendored
2
.github/workflows/linux_builds.yml
vendored
|
@ -8,7 +8,7 @@ env:
|
||||||
dev_mode=yes
|
dev_mode=yes
|
||||||
module_text_server_fb_enabled=yes
|
module_text_server_fb_enabled=yes
|
||||||
"accesskit_sdk_path=${{ github.workspace }}/accesskit-c-0.17.0/"
|
"accesskit_sdk_path=${{ github.workspace }}/accesskit-c-0.17.0/"
|
||||||
GODOT_CPP_BRANCH: 4.5
|
GODOT_CPP_BRANCH: 4.4
|
||||||
DOTNET_NOLOGO: true
|
DOTNET_NOLOGO: true
|
||||||
DOTNET_CLI_TELEMETRY_OPTOUT: true
|
DOTNET_CLI_TELEMETRY_OPTOUT: true
|
||||||
ASAN_OPTIONS: color=always:print_suppressions=1:suppressions=${{ github.workspace }}/misc/error_suppressions/asan.txt
|
ASAN_OPTIONS: color=always:print_suppressions=1:suppressions=${{ github.workspace }}/misc/error_suppressions/asan.txt
|
||||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -217,7 +217,7 @@ xcuserdata/
|
||||||
*.xcscmblueprint
|
*.xcscmblueprint
|
||||||
*.xccheckout
|
*.xccheckout
|
||||||
*.xcodeproj/*
|
*.xcodeproj/*
|
||||||
!misc/misc/dist/apple_embedded_xcode/godot.xcodeproj/project.pbxproj
|
!misc/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
|
||||||
|
|
||||||
# Zed
|
# Zed
|
||||||
.zed/
|
.zed/
|
||||||
|
|
|
@ -34,9 +34,9 @@ repos:
|
||||||
stages: [manual] # Not automatically triggered, invoked via `pre-commit run --hook-stage manual clang-tidy`
|
stages: [manual] # Not automatically triggered, invoked via `pre-commit run --hook-stage manual clang-tidy`
|
||||||
|
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
rev: v0.13.1
|
rev: v0.12.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff-check
|
- id: ruff
|
||||||
args: [--fix]
|
args: [--fix]
|
||||||
files: (\.py|SConstruct|SCsub)$
|
files: (\.py|SConstruct|SCsub)$
|
||||||
types_or: [text]
|
types_or: [text]
|
||||||
|
|
184
CHANGELOG.md
184
CHANGELOG.md
|
@ -7,6 +7,157 @@ previous feature release. It is equivalent to the listings on our
|
||||||
Changelogs for earlier feature releases are available in their respective Git
|
Changelogs for earlier feature releases are available in their respective Git
|
||||||
branches, and linked at the [end of this file](#Past-releases).
|
branches, and linked at the [end of this file](#Past-releases).
|
||||||
|
|
||||||
|
## 4.5 - 2025-10-13
|
||||||
|
|
||||||
|
- [Release announcement](https://godotengine.org/article/maintenance-release-godot-4-5-1)
|
||||||
|
- [Interactive changelog](https://godotengine.github.io/godot-interactive-changelog/#4.5.1)
|
||||||
|
|
||||||
|
#### 2D
|
||||||
|
|
||||||
|
- Fix redundant calls of `CanvasItemEditor::_update_lock_and_group_button` on `SceneTreeEditor` node selection ([GH-110320](https://github.com/godotengine/godot/pull/110320)).
|
||||||
|
|
||||||
|
#### 3D
|
||||||
|
|
||||||
|
- GridMap: fix cell scale not applying to the cursor mesh ([GH-104510](https://github.com/godotengine/godot/pull/104510)).
|
||||||
|
|
||||||
|
#### Animation
|
||||||
|
|
||||||
|
- Fix Reset on Save corrupt poses if scene has multiple Skeletons ([GH-110506](https://github.com/godotengine/godot/pull/110506)).
|
||||||
|
- Fix backward/pingpong root motion in AnimationTree ([GH-110982](https://github.com/godotengine/godot/pull/110982)).
|
||||||
|
- Make extended SkeletonModifiers retrieve interpolated global transform ([GH-110987](https://github.com/godotengine/godot/pull/110987)).
|
||||||
|
|
||||||
|
#### Audio
|
||||||
|
|
||||||
|
- Add one padding frame to QOA buffer for short streams ([GH-110515](https://github.com/godotengine/godot/pull/110515)).
|
||||||
|
|
||||||
|
#### Buildsystem
|
||||||
|
|
||||||
|
- Linux: Allow unbundling libjpeg-turbo to use system package ([GH-110540](https://github.com/godotengine/godot/pull/110540)).
|
||||||
|
- Editor: Generate translation data in separate cpp files ([GH-110618](https://github.com/godotengine/godot/pull/110618)).
|
||||||
|
- SCons: Fix Windows `silence_msvc` logfile encoding ([GH-110691](https://github.com/godotengine/godot/pull/110691)).
|
||||||
|
- Windows: Migrate `godot.manifest` to `platform/windows`, include as dependency ([GH-110897](https://github.com/godotengine/godot/pull/110897)).
|
||||||
|
- Fix compiling SDL without DBus under Linux ([GH-111146](https://github.com/godotengine/godot/pull/111146)).
|
||||||
|
- macOS: Move includes inside `#ifdef` so OpenGL can be disabled ([GH-111301](https://github.com/godotengine/godot/pull/111301)).
|
||||||
|
- SCons: Don't activate `fast_unsafe` automatically on `dev_build` ([GH-111411](https://github.com/godotengine/godot/pull/111411)).
|
||||||
|
|
||||||
|
#### Codestyle
|
||||||
|
|
||||||
|
- Remove dependency of `variant.h` in `print_string.h` ([GH-107721](https://github.com/godotengine/godot/pull/107721)).
|
||||||
|
|
||||||
|
#### Core
|
||||||
|
|
||||||
|
- Initialize `Quaternion` variant with identity ([GH-84658](https://github.com/godotengine/godot/pull/84658)).
|
||||||
|
- Avoid repeated `_copy_on_write()` calls in `Array::resize()` ([GH-110535](https://github.com/godotengine/godot/pull/110535)).
|
||||||
|
- Check for `NUL` characters in string parsing functions ([GH-110556](https://github.com/godotengine/godot/pull/110556)).
|
||||||
|
- X11 input: prevent non-printable keys from producing empty strings ([GH-110635](https://github.com/godotengine/godot/pull/110635)).
|
||||||
|
- Change "reserve called with a capacity smaller than the current size" error message to a verbose message ([GH-110826](https://github.com/godotengine/godot/pull/110826)).
|
||||||
|
|
||||||
|
#### Documentation
|
||||||
|
|
||||||
|
- Document typed dictionaries and arrays in the class reference ([GH-107071](https://github.com/godotengine/godot/pull/107071)).
|
||||||
|
- Clarify that velocity doesn't need delta multiplication in CharacterBody documentation ([GH-109925](https://github.com/godotengine/godot/pull/109925)).
|
||||||
|
- Document the interaction between Light3D cull mask and GI/volumetric fog ([GH-110423](https://github.com/godotengine/godot/pull/110423)).
|
||||||
|
- Fix Basis.determinant() doc: uniform scale determinant is scale^3 ([GH-110424](https://github.com/godotengine/godot/pull/110424)).
|
||||||
|
- Fix and improve `Node2D.move_local_{x,y}()` description ([GH-110878](https://github.com/godotengine/godot/pull/110878)).
|
||||||
|
- Fix /tutorial added twice in offline docs ([GH-110881](https://github.com/godotengine/godot/pull/110881)).
|
||||||
|
|
||||||
|
#### Editor
|
||||||
|
|
||||||
|
- Correct the order of Diagonal Mode in Add Property ([GH-109214](https://github.com/godotengine/godot/pull/109214)).
|
||||||
|
- Fix typos in BlendSpace2D editor's axis labels' accessibility names ([GH-109847](https://github.com/godotengine/godot/pull/109847)).
|
||||||
|
- Add column boundary check in the autocompletion ([GH-110017](https://github.com/godotengine/godot/pull/110017)).
|
||||||
|
- Fix favorite folders that are outside of the project being displayed in `FileSystemDock`'s file list ([GH-110415](https://github.com/godotengine/godot/pull/110415)).
|
||||||
|
- Fix crash due to null pointer dereference when moving/renaming folders in `FileSystemDock` ([GH-110420](https://github.com/godotengine/godot/pull/110420)).
|
||||||
|
- Fix the project file was not updated when some files were removed ([GH-110576](https://github.com/godotengine/godot/pull/110576)).
|
||||||
|
- Fix DPITexture editor icon name ([GH-110661](https://github.com/godotengine/godot/pull/110661)).
|
||||||
|
- Fix selection of remote tree using the keyboard ([GH-110738](https://github.com/godotengine/godot/pull/110738)).
|
||||||
|
- Tweak macOS notarization export message in the editor ([GH-110793](https://github.com/godotengine/godot/pull/110793)).
|
||||||
|
- Fix Quick Open history ([GH-111068](https://github.com/godotengine/godot/pull/111068)).
|
||||||
|
- Set correct saved history after clearing ([GH-111136](https://github.com/godotengine/godot/pull/111136)).
|
||||||
|
- Cherry-picks for the 4.5 branch (future 4.5.1) - 3rd batch ([GH-111388](https://github.com/godotengine/godot/pull/111388)).
|
||||||
|
- Enable script templates by default ([GH-111454](https://github.com/godotengine/godot/pull/111454)).
|
||||||
|
|
||||||
|
#### Export
|
||||||
|
|
||||||
|
- Android: Only validate keystore relevant to current export mode ([GH-109568](https://github.com/godotengine/godot/pull/109568)).
|
||||||
|
- Android: Ensure proper cleanup of the fragment ([GH-109764](https://github.com/godotengine/godot/pull/109764)).
|
||||||
|
- iOS/visionOS: Fix export plugin crash on exit ([GH-110485](https://github.com/godotengine/godot/pull/110485)).
|
||||||
|
- Metal: Fix Metal compiler version inspection ([GH-110873](https://github.com/godotengine/godot/pull/110873)).
|
||||||
|
- Windows: Fix application manifest in exported projects with modified resources ([GH-111316](https://github.com/godotengine/godot/pull/111316)).
|
||||||
|
|
||||||
|
#### GDExtension
|
||||||
|
|
||||||
|
- Fix `--dump-extension-api-with-docs` indentation ([GH-110557](https://github.com/godotengine/godot/pull/110557)).
|
||||||
|
- Prevent breaking compatibility for unexposed classes that can only be created once ([GH-111090](https://github.com/godotengine/godot/pull/111090)).
|
||||||
|
|
||||||
|
#### GDScript
|
||||||
|
|
||||||
|
- LSP: Fix repeated restart attempts ([GH-111290](https://github.com/godotengine/godot/pull/111290)).
|
||||||
|
|
||||||
|
#### GUI
|
||||||
|
|
||||||
|
- Fix LineEdit icon position in right-to-left layout ([GH-109363](https://github.com/godotengine/godot/pull/109363)).
|
||||||
|
- Editor font: do not embolden the Main Font if it's variable ([GH-110737](https://github.com/godotengine/godot/pull/110737)).
|
||||||
|
- Fix LineEdit's placeholder text being selected when double clicking ([GH-110886](https://github.com/godotengine/godot/pull/110886)).
|
||||||
|
- Fix text servers build with disabled FreeType ([GH-111001](https://github.com/godotengine/godot/pull/111001)).
|
||||||
|
- TextServer: Enforce zero width spaces and joiners to actually be zero width and not fallback to regular space ([GH-111014](https://github.com/godotengine/godot/pull/111014)).
|
||||||
|
- Fix bottom panel being unintentionally draggable ([GH-111121](https://github.com/godotengine/godot/pull/111121)).
|
||||||
|
- Enforce zero width spaces and joiners with missing font. Do not warn about missing non-visual characters ([GH-111355](https://github.com/godotengine/godot/pull/111355)).
|
||||||
|
|
||||||
|
#### Import
|
||||||
|
|
||||||
|
- Material Conversion Error Handling ([GH-109369](https://github.com/godotengine/godot/pull/109369)).
|
||||||
|
- OBJ importer: Support bump multiplier (normal scale) ([GH-110925](https://github.com/godotengine/godot/pull/110925)).
|
||||||
|
|
||||||
|
#### Input
|
||||||
|
|
||||||
|
- macOS: Remove old embedded window joystick init code ([GH-110491](https://github.com/godotengine/godot/pull/110491)).
|
||||||
|
- Fix the bug causing `java.lang.StringIndexOutOfBoundsException` crashes when showing the virtual keyboard ([GH-110611](https://github.com/godotengine/godot/pull/110611)).
|
||||||
|
- Fix weak and strong joypad vibration being swapped ([GH-111191](https://github.com/godotengine/godot/pull/111191)).
|
||||||
|
- Fix invalid reported joypad presses ([GH-111192](https://github.com/godotengine/godot/pull/111192)).
|
||||||
|
|
||||||
|
#### Navigation
|
||||||
|
|
||||||
|
- [Navigation 2D] Fix sign of cross product ([GH-110815](https://github.com/godotengine/godot/pull/110815)).
|
||||||
|
- Make navmesh rasterization errors more lenient ([GH-110841](https://github.com/godotengine/godot/pull/110841)).
|
||||||
|
|
||||||
|
#### Physics
|
||||||
|
|
||||||
|
- Fix bug in ManifoldBetweenTwoFaces ([GH-110507](https://github.com/godotengine/godot/pull/110507)).
|
||||||
|
- Fix CCD bodies adding multiple contact manifolds when using Jolt ([GH-110914](https://github.com/godotengine/godot/pull/110914)).
|
||||||
|
- Fix crash when calling `move_and_collide` with a null `jolt_body` ([GH-110964](https://github.com/godotengine/godot/pull/110964)).
|
||||||
|
- JoltPhysics: Fix Generic6DOFJoint3D not respecting angular limits ([GH-111087](https://github.com/godotengine/godot/pull/111087)).
|
||||||
|
|
||||||
|
#### Porting
|
||||||
|
|
||||||
|
- Wayland: Emulate frame event for old `wl_seat` versions ([GH-105587](https://github.com/godotengine/godot/pull/105587)).
|
||||||
|
- Workaround X11 crash issue ([GH-106798](https://github.com/godotengine/godot/pull/106798)).
|
||||||
|
- macOS: Always use "Regular" activation policy for GUI, and headless main loop for command line only tools ([GH-109795](https://github.com/godotengine/godot/pull/109795)).
|
||||||
|
- Wayland: Inhibit idle in DisplayServerWayland::screen_set_keep_on ([GH-110875](https://github.com/godotengine/godot/pull/110875)).
|
||||||
|
- Change `macos.permission.RECORD_SCREEN` version check from 10.15 to 11.0 ([GH-110936](https://github.com/godotengine/godot/pull/110936)).
|
||||||
|
- Unix: Fix retrieval of PID exit code ([GH-111058](https://github.com/godotengine/godot/pull/111058)).
|
||||||
|
|
||||||
|
#### Rendering
|
||||||
|
|
||||||
|
- DirectX DescriptorsHeap pooling on CPU ([GH-106809](https://github.com/godotengine/godot/pull/106809)).
|
||||||
|
- Disable unsupported SSR, SSS, DoF on transparent viewports ([GH-108206](https://github.com/godotengine/godot/pull/108206)).
|
||||||
|
- Windows: Try reading GPU driver information directly from registry ([GH-109346](https://github.com/godotengine/godot/pull/109346)).
|
||||||
|
- Compatibility: Fix backface culling gets ignored when double-sided shadows are used ([GH-109793](https://github.com/godotengine/godot/pull/109793)).
|
||||||
|
- OpenXR: Fix ViewportTextures not displaying correct texture (OpenGL) ([GH-110002](https://github.com/godotengine/godot/pull/110002)).
|
||||||
|
- Divide screen texture by luminance multiplier in compatibility ([GH-110004](https://github.com/godotengine/godot/pull/110004)).
|
||||||
|
- Increase precision of SpotLight attenuation calculation to avoid driver bug on Intel devices ([GH-110363](https://github.com/godotengine/godot/pull/110363)).
|
||||||
|
- Move check for sky cubemap array back into the SkyRD initializer ([GH-110627](https://github.com/godotengine/godot/pull/110627)).
|
||||||
|
- Fix glow intensity not showing in compatibility renderer ([GH-110843](https://github.com/godotengine/godot/pull/110843)).
|
||||||
|
- Fix OpenXR with D3D12 using the wrong clip space projection matrix ([GH-110865](https://github.com/godotengine/godot/pull/110865)).
|
||||||
|
- Fix d3d12 stencil buffer not clearing ([GH-111032](https://github.com/godotengine/godot/pull/111032)).
|
||||||
|
- Sort render list correctly in RD renderers ([GH-111054](https://github.com/godotengine/godot/pull/111054)).
|
||||||
|
- Fix LightmapGI not being correctly applied to objects ([GH-111125](https://github.com/godotengine/godot/pull/111125)).
|
||||||
|
- Fix uniform name for luminance multiplier in shader compiler ([GH-111438](https://github.com/godotengine/godot/pull/111438)).
|
||||||
|
|
||||||
|
#### XR
|
||||||
|
|
||||||
|
- Fix late destruction access violation with OpenXRAPIExtension object ([GH-110868](https://github.com/godotengine/godot/pull/110868)).
|
||||||
|
|
||||||
## 4.5 - 2025-09-15
|
## 4.5 - 2025-09-15
|
||||||
|
|
||||||
- [Release announcement](https://godotengine.org/releases/4.5/)
|
- [Release announcement](https://godotengine.org/releases/4.5/)
|
||||||
|
@ -207,7 +358,7 @@ Table of contents:
|
||||||
- Implement `ModifierBoneTarget3D` which can be target of the other `SkeletonModifier3D`s ([GH-106846](https://github.com/godotengine/godot/pull/106846)).
|
- Implement `ModifierBoneTarget3D` which can be target of the other `SkeletonModifier3D`s ([GH-106846](https://github.com/godotengine/godot/pull/106846)).
|
||||||
- Fix ambiguous AnimationNode's parameter type in default value and make `validate_type_match()` static function ([GH-107005](https://github.com/godotengine/godot/pull/107005)).
|
- Fix ambiguous AnimationNode's parameter type in default value and make `validate_type_match()` static function ([GH-107005](https://github.com/godotengine/godot/pull/107005)).
|
||||||
- Fix animation track filter size bug ([GH-107084](https://github.com/godotengine/godot/pull/107084)).
|
- Fix animation track filter size bug ([GH-107084](https://github.com/godotengine/godot/pull/107084)).
|
||||||
- Add default paramater for AnimationNode as super class ([GH-107171](https://github.com/godotengine/godot/pull/107171)).
|
- Add default parameter for AnimationNode as super class ([GH-107171](https://github.com/godotengine/godot/pull/107171)).
|
||||||
- Fix animation track inserted path and key type ([GH-107241](https://github.com/godotengine/godot/pull/107241)).
|
- Fix animation track inserted path and key type ([GH-107241](https://github.com/godotengine/godot/pull/107241)).
|
||||||
- Fix AnimationPlayer finished state in the editor ([GH-107244](https://github.com/godotengine/godot/pull/107244)).
|
- Fix AnimationPlayer finished state in the editor ([GH-107244](https://github.com/godotengine/godot/pull/107244)).
|
||||||
- Fix editing/removal of bone meta ([GH-107546](https://github.com/godotengine/godot/pull/107546)).
|
- Fix editing/removal of bone meta ([GH-107546](https://github.com/godotengine/godot/pull/107546)).
|
||||||
|
@ -308,12 +459,10 @@ Table of contents:
|
||||||
- Android: Replace the deprecated version macro ([GH-104797](https://github.com/godotengine/godot/pull/104797)).
|
- Android: Replace the deprecated version macro ([GH-104797](https://github.com/godotengine/godot/pull/104797)).
|
||||||
- CI: Validate `scons-cache` via action output ([GH-104803](https://github.com/godotengine/godot/pull/104803)).
|
- CI: Validate `scons-cache` via action output ([GH-104803](https://github.com/godotengine/godot/pull/104803)).
|
||||||
- SCons: Only set GCC `-Wvirtual-inheritance` for C++ and `warnings=extra` ([GH-104841](https://github.com/godotengine/godot/pull/104841)).
|
- SCons: Only set GCC `-Wvirtual-inheritance` for C++ and `warnings=extra` ([GH-104841](https://github.com/godotengine/godot/pull/104841)).
|
||||||
- SCons: Add `CPPEXTPATH` for external includes ([GH-104893](https://github.com/godotengine/godot/pull/104893)).
|
|
||||||
- mbedtls: Disable ASM when compiling with LLVM MemorySanitizer (MSAN) ([GH-104912](https://github.com/godotengine/godot/pull/104912)).
|
- mbedtls: Disable ASM when compiling with LLVM MemorySanitizer (MSAN) ([GH-104912](https://github.com/godotengine/godot/pull/104912)).
|
||||||
- Organize ifdefs for disabling navigation, physics, and XR ([GH-104915](https://github.com/godotengine/godot/pull/104915)).
|
- Organize ifdefs for disabling navigation, physics, and XR ([GH-104915](https://github.com/godotengine/godot/pull/104915)).
|
||||||
- Fix compiling with `disable_xr=yes` when 3d enabled ([GH-104978](https://github.com/godotengine/godot/pull/104978)).
|
- Fix compiling with `disable_xr=yes` when 3d enabled ([GH-104978](https://github.com/godotengine/godot/pull/104978)).
|
||||||
- SCons: Integrate `WARNLEVEL` & `OPTIMIZELEVEL` ([GH-104982](https://github.com/godotengine/godot/pull/104982)).
|
- SCons: Integrate `WARNLEVEL` & `OPTIMIZELEVEL` ([GH-104982](https://github.com/godotengine/godot/pull/104982)).
|
||||||
- CI: Remove "Free disk space on runner" job (REVERTED) ([GH-105025](https://github.com/godotengine/godot/pull/105025)).
|
|
||||||
- Fix issue where vsproj=yes vsproj_gen_only=no sometimes fails to build ([GH-105238](https://github.com/godotengine/godot/pull/105238)).
|
- Fix issue where vsproj=yes vsproj_gen_only=no sometimes fails to build ([GH-105238](https://github.com/godotengine/godot/pull/105238)).
|
||||||
- Web: Add the equivalent of `-Werror` for `wasm-ld` ([GH-105242](https://github.com/godotengine/godot/pull/105242)).
|
- Web: Add the equivalent of `-Werror` for `wasm-ld` ([GH-105242](https://github.com/godotengine/godot/pull/105242)).
|
||||||
- Fix missing `gdb.printing` import for the pretty print script ([GH-105494](https://github.com/godotengine/godot/pull/105494)).
|
- Fix missing `gdb.printing` import for the pretty print script ([GH-105494](https://github.com/godotengine/godot/pull/105494)).
|
||||||
|
@ -395,7 +544,6 @@ Table of contents:
|
||||||
- macOS: Regenerate editor `icns` file to include all resolutions ([GH-109292](https://github.com/godotengine/godot/pull/109292)).
|
- macOS: Regenerate editor `icns` file to include all resolutions ([GH-109292](https://github.com/godotengine/godot/pull/109292)).
|
||||||
- Meta: Move /editor/scene folder from `core` to `docks` codeowner ([GH-109424](https://github.com/godotengine/godot/pull/109424)).
|
- Meta: Move /editor/scene folder from `core` to `docks` codeowner ([GH-109424](https://github.com/godotengine/godot/pull/109424)).
|
||||||
- CI: Update dependency setup on Linux actions ([GH-109573](https://github.com/godotengine/godot/pull/109573)).
|
- CI: Update dependency setup on Linux actions ([GH-109573](https://github.com/godotengine/godot/pull/109573)).
|
||||||
- SCons: Temporarily revert Mesa includes to `CPPPATH` ([GH-109749](https://github.com/godotengine/godot/pull/109749)).
|
|
||||||
- SCons: Fix `dlltool` on Windows MinGW builds ([GH-109758](https://github.com/godotengine/godot/pull/109758)).
|
- SCons: Fix `dlltool` on Windows MinGW builds ([GH-109758](https://github.com/godotengine/godot/pull/109758)).
|
||||||
- CI: Fix detection of Windows D3D12 dependencies ([GH-109912](https://github.com/godotengine/godot/pull/109912)).
|
- CI: Fix detection of Windows D3D12 dependencies ([GH-109912](https://github.com/godotengine/godot/pull/109912)).
|
||||||
- CI: Ensure prettier/clearer sanitizer output ([GH-109960](https://github.com/godotengine/godot/pull/109960)).
|
- CI: Ensure prettier/clearer sanitizer output ([GH-109960](https://github.com/godotengine/godot/pull/109960)).
|
||||||
|
@ -409,7 +557,7 @@ Table of contents:
|
||||||
- Resolve the hostfxr path using dotnet CLI ([GH-96146](https://github.com/godotengine/godot/pull/96146)).
|
- Resolve the hostfxr path using dotnet CLI ([GH-96146](https://github.com/godotengine/godot/pull/96146)).
|
||||||
- Add `linux-bionic` RID export option to support NativeAOT on Android ([GH-97908](https://github.com/godotengine/godot/pull/97908)).
|
- Add `linux-bionic` RID export option to support NativeAOT on Android ([GH-97908](https://github.com/godotengine/godot/pull/97908)).
|
||||||
- Use `ObjectID` when converting `Variant` to `GodotObject` ([GH-98034](https://github.com/godotengine/godot/pull/98034)).
|
- Use `ObjectID` when converting `Variant` to `GodotObject` ([GH-98034](https://github.com/godotengine/godot/pull/98034)).
|
||||||
- Editor: Prevent `TOOLS` .NET `DefineConstants` being overriden by the user ([GH-98153](https://github.com/godotengine/godot/pull/98153)).
|
- Editor: Prevent `TOOLS` .NET `DefineConstants` being overridden by the user ([GH-98153](https://github.com/godotengine/godot/pull/98153)).
|
||||||
- Fix thread deadlock when using a worker thread to load a script with a generic base class ([GH-99798](https://github.com/godotengine/godot/pull/99798)).
|
- Fix thread deadlock when using a worker thread to load a script with a generic base class ([GH-99798](https://github.com/godotengine/godot/pull/99798)).
|
||||||
- Update Dotnet iOS Export Process ([GH-100187](https://github.com/godotengine/godot/pull/100187)).
|
- Update Dotnet iOS Export Process ([GH-100187](https://github.com/godotengine/godot/pull/100187)).
|
||||||
- Fix `RefCounted` not disposed correctly in certain case ([GH-101006](https://github.com/godotengine/godot/pull/101006)).
|
- Fix `RefCounted` not disposed correctly in certain case ([GH-101006](https://github.com/godotengine/godot/pull/101006)).
|
||||||
|
@ -680,7 +828,7 @@ Table of contents:
|
||||||
- Smoke test: Log an error if `reserve()` is called with fewer elements than `size()` ([GH-105278](https://github.com/godotengine/godot/pull/105278)).
|
- Smoke test: Log an error if `reserve()` is called with fewer elements than `size()` ([GH-105278](https://github.com/godotengine/godot/pull/105278)).
|
||||||
- Fix custom scene argument if it's referenced as UID ([GH-105288](https://github.com/godotengine/godot/pull/105288)).
|
- Fix custom scene argument if it's referenced as UID ([GH-105288](https://github.com/godotengine/godot/pull/105288)).
|
||||||
- Add `--scene` command line argument ([GH-105302](https://github.com/godotengine/godot/pull/105302)).
|
- Add `--scene` command line argument ([GH-105302](https://github.com/godotengine/godot/pull/105302)).
|
||||||
- Supress unused paramater warning conflicting with if constexpr ([GH-105326](https://github.com/godotengine/godot/pull/105326)).
|
- Suppress unused parameter warning conflicting with if constexpr ([GH-105326](https://github.com/godotengine/godot/pull/105326)).
|
||||||
- Allow inserting at end of array again ([GH-105334](https://github.com/godotengine/godot/pull/105334)).
|
- Allow inserting at end of array again ([GH-105334](https://github.com/godotengine/godot/pull/105334)).
|
||||||
- Optimize `Array` `min`/`max` methods ([GH-105392](https://github.com/godotengine/godot/pull/105392)).
|
- Optimize `Array` `min`/`max` methods ([GH-105392](https://github.com/godotengine/godot/pull/105392)).
|
||||||
- Add thread safety to Object signals ([GH-105453](https://github.com/godotengine/godot/pull/105453)).
|
- Add thread safety to Object signals ([GH-105453](https://github.com/godotengine/godot/pull/105453)).
|
||||||
|
@ -727,7 +875,7 @@ Table of contents:
|
||||||
- Remove redundant `data.inside_tree` ([GH-106903](https://github.com/godotengine/godot/pull/106903)).
|
- Remove redundant `data.inside_tree` ([GH-106903](https://github.com/godotengine/godot/pull/106903)).
|
||||||
- JavaClassWrapper: Don't discard overloaded methods that differ by object type ([GH-106908](https://github.com/godotengine/godot/pull/106908)).
|
- JavaClassWrapper: Don't discard overloaded methods that differ by object type ([GH-106908](https://github.com/godotengine/godot/pull/106908)).
|
||||||
- Add missing headers in `FixedVector` and `Span` ([GH-106954](https://github.com/godotengine/godot/pull/106954)).
|
- Add missing headers in `FixedVector` and `Span` ([GH-106954](https://github.com/godotengine/godot/pull/106954)).
|
||||||
- Remove `OAHashMap`, in favour of `AHashMap` ([GH-106996](https://github.com/godotengine/godot/pull/106996)).
|
- Remove `OAHashMap`, in favor of `AHashMap` ([GH-106996](https://github.com/godotengine/godot/pull/106996)).
|
||||||
- Expose `WorkerThreadPool.get_caller_task_id()` ([GH-107029](https://github.com/godotengine/godot/pull/107029)).
|
- Expose `WorkerThreadPool.get_caller_task_id()` ([GH-107029](https://github.com/godotengine/godot/pull/107029)).
|
||||||
- Add `WorkerThreadPool.get_caller_group_id` ([GH-107040](https://github.com/godotengine/godot/pull/107040)).
|
- Add `WorkerThreadPool.get_caller_group_id` ([GH-107040](https://github.com/godotengine/godot/pull/107040)).
|
||||||
- Fix `ResourceSaver` saving default value of `Resource` ([GH-107049](https://github.com/godotengine/godot/pull/107049)).
|
- Fix `ResourceSaver` saving default value of `Resource` ([GH-107049](https://github.com/godotengine/godot/pull/107049)).
|
||||||
|
@ -909,7 +1057,7 @@ Table of contents:
|
||||||
- C#: Fix Shortcut example ([GH-107609](https://github.com/godotengine/godot/pull/107609)).
|
- C#: Fix Shortcut example ([GH-107609](https://github.com/godotengine/godot/pull/107609)).
|
||||||
- Clarify `_set`/`_get` description ([GH-107823](https://github.com/godotengine/godot/pull/107823)).
|
- Clarify `_set`/`_get` description ([GH-107823](https://github.com/godotengine/godot/pull/107823)).
|
||||||
- Docs: Various grammar and spelling fixes ([GH-107895](https://github.com/godotengine/godot/pull/107895)).
|
- Docs: Various grammar and spelling fixes ([GH-107895](https://github.com/godotengine/godot/pull/107895)).
|
||||||
- Specifiy return value in several store methods in `FileAccess` ([GH-107938](https://github.com/godotengine/godot/pull/107938)).
|
- Specify return value in several store methods in `FileAccess` ([GH-107938](https://github.com/godotengine/godot/pull/107938)).
|
||||||
- Fix OptionButton ID value range documentation ([GH-107940](https://github.com/godotengine/godot/pull/107940)).
|
- Fix OptionButton ID value range documentation ([GH-107940](https://github.com/godotengine/godot/pull/107940)).
|
||||||
- Document `Gradient.sample()` clamping behavior ([GH-107976](https://github.com/godotengine/godot/pull/107976)).
|
- Document `Gradient.sample()` clamping behavior ([GH-107976](https://github.com/godotengine/godot/pull/107976)).
|
||||||
- Clarify `visible_characters` ([GH-108029](https://github.com/godotengine/godot/pull/108029)).
|
- Clarify `visible_characters` ([GH-108029](https://github.com/godotengine/godot/pull/108029)).
|
||||||
|
@ -1294,7 +1442,7 @@ Table of contents:
|
||||||
- Add single-object inspect command backwards compatible API for potential regression ([GH-110043](https://github.com/godotengine/godot/pull/110043)).
|
- Add single-object inspect command backwards compatible API for potential regression ([GH-110043](https://github.com/godotengine/godot/pull/110043)).
|
||||||
- Add missing range hint to `Viewport.oversampling_override` in the editor ([GH-110094](https://github.com/godotengine/godot/pull/110094)).
|
- Add missing range hint to `Viewport.oversampling_override` in the editor ([GH-110094](https://github.com/godotengine/godot/pull/110094)).
|
||||||
- Fix Range scale overflow ([GH-110107](https://github.com/godotengine/godot/pull/110107)).
|
- Fix Range scale overflow ([GH-110107](https://github.com/godotengine/godot/pull/110107)).
|
||||||
- Fix "SpriteFrames" editor not fully hidding the bottom panel ([GH-110280](https://github.com/godotengine/godot/pull/110280)).
|
- Fix "SpriteFrames" editor not fully hiding the bottom panel ([GH-110280](https://github.com/godotengine/godot/pull/110280)).
|
||||||
|
|
||||||
#### Export
|
#### Export
|
||||||
|
|
||||||
|
@ -1330,7 +1478,7 @@ Table of contents:
|
||||||
- [Windows export] Use project version as fallback ([GH-108472](https://github.com/godotengine/godot/pull/108472)).
|
- [Windows export] Use project version as fallback ([GH-108472](https://github.com/godotengine/godot/pull/108472)).
|
||||||
- Remove selective shader baking ([GH-108914](https://github.com/godotengine/godot/pull/108914)).
|
- Remove selective shader baking ([GH-108914](https://github.com/godotengine/godot/pull/108914)).
|
||||||
- Reduce log spam during headless import/export ([GH-109334](https://github.com/godotengine/godot/pull/109334)).
|
- Reduce log spam during headless import/export ([GH-109334](https://github.com/godotengine/godot/pull/109334)).
|
||||||
- Android: Thread Syncronization for FileAccessHandler ([GH-109340](https://github.com/godotengine/godot/pull/109340)).
|
- Android: Thread Synchronization for FileAccessHandler ([GH-109340](https://github.com/godotengine/godot/pull/109340)).
|
||||||
- Fix headless import/export reporting progress greater than 100% ([GH-109391](https://github.com/godotengine/godot/pull/109391)).
|
- Fix headless import/export reporting progress greater than 100% ([GH-109391](https://github.com/godotengine/godot/pull/109391)).
|
||||||
- Android: Fix build command for AAB export ([GH-109608](https://github.com/godotengine/godot/pull/109608)).
|
- Android: Fix build command for AAB export ([GH-109608](https://github.com/godotengine/godot/pull/109608)).
|
||||||
- Add default param value to `EditorExportPlatform::get_forced_export_files` ([GH-109662](https://github.com/godotengine/godot/pull/109662)).
|
- Add default param value to `EditorExportPlatform::get_forced_export_files` ([GH-109662](https://github.com/godotengine/godot/pull/109662)).
|
||||||
|
@ -1402,7 +1550,7 @@ Table of contents:
|
||||||
- Fix a few GDScript warning messages for grammar and consistency ([GH-104729](https://github.com/godotengine/godot/pull/104729)).
|
- Fix a few GDScript warning messages for grammar and consistency ([GH-104729](https://github.com/godotengine/godot/pull/104729)).
|
||||||
- Fix invalid DAP responses when content has non-ASCII content ([GH-104936](https://github.com/godotengine/godot/pull/104936)).
|
- Fix invalid DAP responses when content has non-ASCII content ([GH-104936](https://github.com/godotengine/godot/pull/104936)).
|
||||||
- LSP: Fix relative path handling for document links ([GH-105059](https://github.com/godotengine/godot/pull/105059)).
|
- LSP: Fix relative path handling for document links ([GH-105059](https://github.com/godotengine/godot/pull/105059)).
|
||||||
- LSP: Don't advertize support for workspace symbols ([GH-105061](https://github.com/godotengine/godot/pull/105061)).
|
- LSP: Don't advertise support for workspace symbols ([GH-105061](https://github.com/godotengine/godot/pull/105061)).
|
||||||
- Add autocompletion for `@export_tool_button` ([GH-105081](https://github.com/godotengine/godot/pull/105081)).
|
- Add autocompletion for `@export_tool_button` ([GH-105081](https://github.com/godotengine/godot/pull/105081)).
|
||||||
- LSP: Extract annotations from `EditorHelp` ([GH-105087](https://github.com/godotengine/godot/pull/105087)).
|
- LSP: Extract annotations from `EditorHelp` ([GH-105087](https://github.com/godotengine/godot/pull/105087)).
|
||||||
- Fix LSP not returning expected localization for API docs ([GH-105344](https://github.com/godotengine/godot/pull/105344)).
|
- Fix LSP not returning expected localization for API docs ([GH-105344](https://github.com/godotengine/godot/pull/105344)).
|
||||||
|
@ -1552,7 +1700,7 @@ Table of contents:
|
||||||
- Remove macros from FontFile test case ([GH-104709](https://github.com/godotengine/godot/pull/104709)).
|
- Remove macros from FontFile test case ([GH-104709](https://github.com/godotengine/godot/pull/104709)).
|
||||||
- Implement Stackable Text Outline on `Label` ([GH-104731](https://github.com/godotengine/godot/pull/104731)).
|
- Implement Stackable Text Outline on `Label` ([GH-104731](https://github.com/godotengine/godot/pull/104731)).
|
||||||
- Fix TextEdit VScroll max tolerance ([GH-104776](https://github.com/godotengine/godot/pull/104776)).
|
- Fix TextEdit VScroll max tolerance ([GH-104776](https://github.com/godotengine/godot/pull/104776)).
|
||||||
- Replace global oversampling with overrideable per-viewport oversampling ([GH-104872](https://github.com/godotengine/godot/pull/104872)).
|
- Replace global oversampling with overridable per-viewport oversampling ([GH-104872](https://github.com/godotengine/godot/pull/104872)).
|
||||||
- Add font import flag to toggle modulation of colored glyphs ([GH-104878](https://github.com/godotengine/godot/pull/104878)).
|
- Add font import flag to toggle modulation of colored glyphs ([GH-104878](https://github.com/godotengine/godot/pull/104878)).
|
||||||
- Make `swap_cancel_ok` setting 3-state instead of boolean ([GH-104958](https://github.com/godotengine/godot/pull/104958)).
|
- Make `swap_cancel_ok` setting 3-state instead of boolean ([GH-104958](https://github.com/godotengine/godot/pull/104958)).
|
||||||
- Linux: Detect KDE/LXQt and swap OK/Cancel buttons to Windows style ([GH-104959](https://github.com/godotengine/godot/pull/104959)).
|
- Linux: Detect KDE/LXQt and swap OK/Cancel buttons to Windows style ([GH-104959](https://github.com/godotengine/godot/pull/104959)).
|
||||||
|
@ -1961,7 +2109,7 @@ Table of contents:
|
||||||
- Fix CapsuleShape2D outline for navmesh baking ([GH-107263](https://github.com/godotengine/godot/pull/107263)).
|
- Fix CapsuleShape2D outline for navmesh baking ([GH-107263](https://github.com/godotengine/godot/pull/107263)).
|
||||||
- Change 2D navigation region and link updates to an async process ([GH-107381](https://github.com/godotengine/godot/pull/107381)).
|
- Change 2D navigation region and link updates to an async process ([GH-107381](https://github.com/godotengine/godot/pull/107381)).
|
||||||
- Only repath a NavigationAgent with a target position ([GH-107513](https://github.com/godotengine/godot/pull/107513)).
|
- Only repath a NavigationAgent with a target position ([GH-107513](https://github.com/godotengine/godot/pull/107513)).
|
||||||
- Remove `get_used_cells` to avoid unecessary allocations in navigation baking ([GH-107559](https://github.com/godotengine/godot/pull/107559)).
|
- Remove `get_used_cells` to avoid unnecessary allocations in navigation baking ([GH-107559](https://github.com/godotengine/godot/pull/107559)).
|
||||||
- NavigationServer2D: Bind missing `merge_rasterizer_cell_scale` setting and functions ([GH-107802](https://github.com/godotengine/godot/pull/107802)).
|
- NavigationServer2D: Bind missing `merge_rasterizer_cell_scale` setting and functions ([GH-107802](https://github.com/godotengine/godot/pull/107802)).
|
||||||
- NavMap3D: check if obstacles have avoidance enabled ([GH-108281](https://github.com/godotengine/godot/pull/108281)).
|
- NavMap3D: check if obstacles have avoidance enabled ([GH-108281](https://github.com/godotengine/godot/pull/108281)).
|
||||||
- NavMap2D: check if obstacles have avoidance enabled ([GH-108284](https://github.com/godotengine/godot/pull/108284)).
|
- NavMap2D: check if obstacles have avoidance enabled ([GH-108284](https://github.com/godotengine/godot/pull/108284)).
|
||||||
|
@ -2172,7 +2320,7 @@ Table of contents:
|
||||||
- Fix wrong default texture for global uniforms of type `sampler2DArray` ([GH-101941](https://github.com/godotengine/godot/pull/101941)).
|
- Fix wrong default texture for global uniforms of type `sampler2DArray` ([GH-101941](https://github.com/godotengine/godot/pull/101941)).
|
||||||
- Pass angular diameter into light size constants for sky shaders ([GH-101971](https://github.com/godotengine/godot/pull/101971)).
|
- Pass angular diameter into light size constants for sky shaders ([GH-101971](https://github.com/godotengine/godot/pull/101971)).
|
||||||
- Optimize ProceduralSkyMaterial by removing uses of acos and simplifying logic ([GH-101973](https://github.com/godotengine/godot/pull/101973)).
|
- Optimize ProceduralSkyMaterial by removing uses of acos and simplifying logic ([GH-101973](https://github.com/godotengine/godot/pull/101973)).
|
||||||
- Rendering compositor identifies `is_opengl` API; minor optimisation ([GH-102302](https://github.com/godotengine/godot/pull/102302)).
|
- Rendering compositor identifies `is_opengl` API; minor optimization ([GH-102302](https://github.com/godotengine/godot/pull/102302)).
|
||||||
- Add SMAA 1x to screenspace AA options ([GH-102330](https://github.com/godotengine/godot/pull/102330)).
|
- Add SMAA 1x to screenspace AA options ([GH-102330](https://github.com/godotengine/godot/pull/102330)).
|
||||||
- Add ASTC HDR format variants ([GH-102777](https://github.com/godotengine/godot/pull/102777)).
|
- Add ASTC HDR format variants ([GH-102777](https://github.com/godotengine/godot/pull/102777)).
|
||||||
- GLES3: Fix errors baking light map with compatibility renderer ([GH-102783](https://github.com/godotengine/godot/pull/102783)).
|
- GLES3: Fix errors baking light map with compatibility renderer ([GH-102783](https://github.com/godotengine/godot/pull/102783)).
|
||||||
|
@ -2235,7 +2383,7 @@ Table of contents:
|
||||||
- Fix reflection probe dark borders ([GH-105899](https://github.com/godotengine/godot/pull/105899)).
|
- Fix reflection probe dark borders ([GH-105899](https://github.com/godotengine/godot/pull/105899)).
|
||||||
- Fix error spam to due wrong use of `reserve()` in D3D12 driver ([GH-105906](https://github.com/godotengine/godot/pull/105906)).
|
- Fix error spam to due wrong use of `reserve()` in D3D12 driver ([GH-105906](https://github.com/godotengine/godot/pull/105906)).
|
||||||
- FTI - Add custom interpolation for wheels ([GH-105915](https://github.com/godotengine/godot/pull/105915)).
|
- FTI - Add custom interpolation for wheels ([GH-105915](https://github.com/godotengine/godot/pull/105915)).
|
||||||
- FTI - Fix `SceneTreeFTI` behaviour on exit tree ([GH-105973](https://github.com/godotengine/godot/pull/105973)).
|
- FTI - Fix `SceneTreeFTI` behavior on exit tree ([GH-105973](https://github.com/godotengine/godot/pull/105973)).
|
||||||
- Avoid crash when allocating specular and normal-roughness buffers when render buffers aren't available ([GH-106079](https://github.com/godotengine/godot/pull/106079)).
|
- Avoid crash when allocating specular and normal-roughness buffers when render buffers aren't available ([GH-106079](https://github.com/godotengine/godot/pull/106079)).
|
||||||
- Check for GL ES version of BPTC extension when using the OpenGL renderer ([GH-106086](https://github.com/godotengine/godot/pull/106086)).
|
- Check for GL ES version of BPTC extension when using the OpenGL renderer ([GH-106086](https://github.com/godotengine/godot/pull/106086)).
|
||||||
- Add specular occlusion from ambient light ([GH-106145](https://github.com/godotengine/godot/pull/106145)).
|
- Add specular occlusion from ambient light ([GH-106145](https://github.com/godotengine/godot/pull/106145)).
|
||||||
|
@ -2263,7 +2411,7 @@ Table of contents:
|
||||||
- Mobile: Move `_setup_lightmaps` before `_fill_render_list` ([GH-106748](https://github.com/godotengine/godot/pull/106748)).
|
- Mobile: Move `_setup_lightmaps` before `_fill_render_list` ([GH-106748](https://github.com/godotengine/godot/pull/106748)).
|
||||||
- D3D12: Fix inconsistent value for `DCOMP_ENABLED` in platform code ([GH-106827](https://github.com/godotengine/godot/pull/106827)).
|
- D3D12: Fix inconsistent value for `DCOMP_ENABLED` in platform code ([GH-106827](https://github.com/godotengine/godot/pull/106827)).
|
||||||
- Fix missing ibl reconstruction from DFG multiscattering ([GH-106844](https://github.com/godotengine/godot/pull/106844)).
|
- Fix missing ibl reconstruction from DFG multiscattering ([GH-106844](https://github.com/godotengine/godot/pull/106844)).
|
||||||
- Minor rendering and XR changes to allow Meta enivornment depth API to work entirely from GDExtension ([GH-106880](https://github.com/godotengine/godot/pull/106880)).
|
- Minor rendering and XR changes to allow Meta environment depth API to work entirely from GDExtension ([GH-106880](https://github.com/godotengine/godot/pull/106880)).
|
||||||
- Vulkan Mobile: Fix lightmap instances count ([GH-106907](https://github.com/godotengine/godot/pull/106907)).
|
- Vulkan Mobile: Fix lightmap instances count ([GH-106907](https://github.com/godotengine/godot/pull/106907)).
|
||||||
- Correctly place viewport and use viewport relative rect for the final blit in Compatibility renderer ([GH-106924](https://github.com/godotengine/godot/pull/106924)).
|
- Correctly place viewport and use viewport relative rect for the final blit in Compatibility renderer ([GH-106924](https://github.com/godotengine/godot/pull/106924)).
|
||||||
- Metal: Fix multi-view support ([GH-106925](https://github.com/godotengine/godot/pull/106925)).
|
- Metal: Fix multi-view support ([GH-106925](https://github.com/godotengine/godot/pull/106925)).
|
||||||
|
@ -2309,13 +2457,13 @@ Table of contents:
|
||||||
- Fix VVL errors by changing `frag_color` to FP32 and dFdx/y ([GH-108015](https://github.com/godotengine/godot/pull/108015)).
|
- Fix VVL errors by changing `frag_color` to FP32 and dFdx/y ([GH-108015](https://github.com/godotengine/godot/pull/108015)).
|
||||||
- Metal: Use image atomic operations on supported Apple hardware ([GH-108028](https://github.com/godotengine/godot/pull/108028)).
|
- Metal: Use image atomic operations on supported Apple hardware ([GH-108028](https://github.com/godotengine/godot/pull/108028)).
|
||||||
- Fix opaque stencil rendering ([GH-108044](https://github.com/godotengine/godot/pull/108044)).
|
- Fix opaque stencil rendering ([GH-108044](https://github.com/godotengine/godot/pull/108044)).
|
||||||
- FTI: - Fix `MultiMesh` init and stable behaviour ([GH-108109](https://github.com/godotengine/godot/pull/108109)).
|
- FTI: - Fix `MultiMesh` init and stable behavior ([GH-108109](https://github.com/godotengine/godot/pull/108109)).
|
||||||
- FTI: - Add reset on setting `top_level` ([GH-108112](https://github.com/godotengine/godot/pull/108112)).
|
- FTI: - Add reset on setting `top_level` ([GH-108112](https://github.com/godotengine/godot/pull/108112)).
|
||||||
- Metal: Use correct environment variable to generate labels ([GH-108123](https://github.com/godotengine/godot/pull/108123)).
|
- Metal: Use correct environment variable to generate labels ([GH-108123](https://github.com/godotengine/godot/pull/108123)).
|
||||||
- FTI: - Clear `SceneTreeFTI` completely on enabling / disabling ([GH-108131](https://github.com/godotengine/godot/pull/108131)).
|
- FTI: - Clear `SceneTreeFTI` completely on enabling / disabling ([GH-108131](https://github.com/godotengine/godot/pull/108131)).
|
||||||
- Web: Restrict rendering method selection ([GH-108276](https://github.com/godotengine/godot/pull/108276)).
|
- Web: Restrict rendering method selection ([GH-108276](https://github.com/godotengine/godot/pull/108276)).
|
||||||
- Fix `surface_get_arrays` returns wrong index array when using empty vertex array ([GH-108308](https://github.com/godotengine/godot/pull/108308)).
|
- Fix `surface_get_arrays` returns wrong index array when using empty vertex array ([GH-108308](https://github.com/godotengine/godot/pull/108308)).
|
||||||
- Fix underculling of occulusion culling ([GH-108347](https://github.com/godotengine/godot/pull/108347)).
|
- Fix underculling of occlusion culling ([GH-108347](https://github.com/godotengine/godot/pull/108347)).
|
||||||
- Fix division by zero in clearcoat specular BRDF ([GH-108378](https://github.com/godotengine/godot/pull/108378)).
|
- Fix division by zero in clearcoat specular BRDF ([GH-108378](https://github.com/godotengine/godot/pull/108378)).
|
||||||
- Fix crash when creating voxel GI data ([GH-108397](https://github.com/godotengine/godot/pull/108397)).
|
- Fix crash when creating voxel GI data ([GH-108397](https://github.com/godotengine/godot/pull/108397)).
|
||||||
- Metal: Remove invalid assumption for image atomic operations ([GH-108452](https://github.com/godotengine/godot/pull/108452)).
|
- Metal: Remove invalid assumption for image atomic operations ([GH-108452](https://github.com/godotengine/godot/pull/108452)).
|
||||||
|
|
|
@ -214,7 +214,7 @@ License: Apache-2.0
|
||||||
|
|
||||||
Files: thirdparty/basis_universal/*
|
Files: thirdparty/basis_universal/*
|
||||||
Comment: Basis Universal
|
Comment: Basis Universal
|
||||||
Copyright: 2019-2025, Binomial LLC.
|
Copyright: 2019-2024, Binomial LLC.
|
||||||
License: Apache-2.0
|
License: Apache-2.0
|
||||||
|
|
||||||
Files: thirdparty/brotli/*
|
Files: thirdparty/brotli/*
|
||||||
|
@ -555,7 +555,7 @@ License: Zlib
|
||||||
Files: thirdparty/sdl/hidapi/*
|
Files: thirdparty/sdl/hidapi/*
|
||||||
Comment: hidapi
|
Comment: hidapi
|
||||||
Copyright: 2010, Alan Ott, Signal 11 Software
|
Copyright: 2010, Alan Ott, Signal 11 Software
|
||||||
License: BSD-3-clause
|
License: BSD-3-Clause
|
||||||
|
|
||||||
Files: thirdparty/spirv-cross/*
|
Files: thirdparty/spirv-cross/*
|
||||||
Comment: SPIRV-Cross
|
Comment: SPIRV-Cross
|
||||||
|
|
20
SConstruct
20
SConstruct
|
@ -239,7 +239,6 @@ opts.Add(BoolVariable("disable_physics_3d", "Disable 3D physics nodes and server
|
||||||
opts.Add(BoolVariable("disable_navigation_2d", "Disable 2D navigation features", False))
|
opts.Add(BoolVariable("disable_navigation_2d", "Disable 2D navigation features", False))
|
||||||
opts.Add(BoolVariable("disable_navigation_3d", "Disable 3D navigation features", False))
|
opts.Add(BoolVariable("disable_navigation_3d", "Disable 3D navigation features", False))
|
||||||
opts.Add(BoolVariable("disable_xr", "Disable XR nodes and server", False))
|
opts.Add(BoolVariable("disable_xr", "Disable XR nodes and server", False))
|
||||||
opts.Add(BoolVariable("disable_overrides", "Disable project settings overrides and related CLI arguments", False))
|
|
||||||
opts.Add("build_profile", "Path to a file containing a feature build profile", "")
|
opts.Add("build_profile", "Path to a file containing a feature build profile", "")
|
||||||
opts.Add("custom_modules", "A list of comma-separated directory paths containing custom modules to build.", "")
|
opts.Add("custom_modules", "A list of comma-separated directory paths containing custom modules to build.", "")
|
||||||
opts.Add(BoolVariable("custom_modules_recursive", "Detect custom modules recursively for each specified path.", True))
|
opts.Add(BoolVariable("custom_modules_recursive", "Detect custom modules recursively for each specified path.", True))
|
||||||
|
@ -265,14 +264,6 @@ opts.Add(
|
||||||
True,
|
True,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
opts.Add(
|
|
||||||
EnumVariable(
|
|
||||||
"library_type",
|
|
||||||
"Build library type",
|
|
||||||
"executable",
|
|
||||||
("executable", "static_library", "shared_library"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Thirdparty libraries
|
# Thirdparty libraries
|
||||||
opts.Add(BoolVariable("builtin_brotli", "Use the built-in Brotli library", True))
|
opts.Add(BoolVariable("builtin_brotli", "Use the built-in Brotli library", True))
|
||||||
|
@ -555,13 +546,6 @@ if not env["deprecated"]:
|
||||||
if env["precision"] == "double":
|
if env["precision"] == "double":
|
||||||
env.Append(CPPDEFINES=["REAL_T_IS_DOUBLE"])
|
env.Append(CPPDEFINES=["REAL_T_IS_DOUBLE"])
|
||||||
|
|
||||||
# Library Support
|
|
||||||
if env["library_type"] != "executable":
|
|
||||||
if "library" not in env.get("supported", []):
|
|
||||||
print_error(f"Library builds unsupported for {env['platform']}")
|
|
||||||
Exit(255)
|
|
||||||
env.Append(CPPDEFINES=["LIBGODOT_ENABLED"])
|
|
||||||
|
|
||||||
# Default num_jobs to local cpu count if not user specified.
|
# Default num_jobs to local cpu count if not user specified.
|
||||||
# SCons has a peculiarity where user-specified options won't be overridden
|
# SCons has a peculiarity where user-specified options won't be overridden
|
||||||
# by SetOption, so we can rely on this to know if we should use our default.
|
# by SetOption, so we can rely on this to know if we should use our default.
|
||||||
|
@ -640,7 +624,6 @@ if env["strict_checks"]:
|
||||||
|
|
||||||
# Run SCU file generation script if in a SCU build.
|
# Run SCU file generation script if in a SCU build.
|
||||||
if env["scu_build"]:
|
if env["scu_build"]:
|
||||||
env.Append(CPPDEFINES=["SCU_BUILD_ENABLED"])
|
|
||||||
max_includes_per_scu = 8
|
max_includes_per_scu = 8
|
||||||
if env.dev_build:
|
if env.dev_build:
|
||||||
max_includes_per_scu = 1024
|
max_includes_per_scu = 1024
|
||||||
|
@ -1036,9 +1019,6 @@ if env["minizip"]:
|
||||||
if env["brotli"]:
|
if env["brotli"]:
|
||||||
env.Append(CPPDEFINES=["BROTLI_ENABLED"])
|
env.Append(CPPDEFINES=["BROTLI_ENABLED"])
|
||||||
|
|
||||||
if not env["disable_overrides"]:
|
|
||||||
env.Append(CPPDEFINES=["OVERRIDE_ENABLED"])
|
|
||||||
|
|
||||||
if not env["verbose"]:
|
if not env["verbose"]:
|
||||||
methods.no_verbose(env)
|
methods.no_verbose(env)
|
||||||
|
|
||||||
|
|
|
@ -38,40 +38,24 @@
|
||||||
#include "core/version.h"
|
#include "core/version.h"
|
||||||
#include "servers/rendering/rendering_device.h"
|
#include "servers/rendering/rendering_device.h"
|
||||||
|
|
||||||
void Engine::_update_time_scale() {
|
|
||||||
_time_scale = _user_time_scale * _game_time_scale;
|
|
||||||
user_ips = MAX(1, ips * _user_time_scale);
|
|
||||||
max_user_physics_steps_per_frame = MAX(max_physics_steps_per_frame, max_physics_steps_per_frame * _user_time_scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Engine::set_physics_ticks_per_second(int p_ips) {
|
void Engine::set_physics_ticks_per_second(int p_ips) {
|
||||||
ERR_FAIL_COND_MSG(p_ips <= 0, "Engine iterations per second must be greater than 0.");
|
ERR_FAIL_COND_MSG(p_ips <= 0, "Engine iterations per second must be greater than 0.");
|
||||||
ips = p_ips;
|
ips = p_ips;
|
||||||
_update_time_scale();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Engine::get_physics_ticks_per_second() const {
|
int Engine::get_physics_ticks_per_second() const {
|
||||||
return ips;
|
return ips;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Engine::get_user_physics_ticks_per_second() const {
|
|
||||||
return user_ips;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Engine::set_max_physics_steps_per_frame(int p_max_physics_steps) {
|
void Engine::set_max_physics_steps_per_frame(int p_max_physics_steps) {
|
||||||
ERR_FAIL_COND_MSG(p_max_physics_steps <= 0, "Maximum number of physics steps per frame must be greater than 0.");
|
ERR_FAIL_COND_MSG(p_max_physics_steps <= 0, "Maximum number of physics steps per frame must be greater than 0.");
|
||||||
max_physics_steps_per_frame = p_max_physics_steps;
|
max_physics_steps_per_frame = p_max_physics_steps;
|
||||||
_update_time_scale();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Engine::get_max_physics_steps_per_frame() const {
|
int Engine::get_max_physics_steps_per_frame() const {
|
||||||
return max_physics_steps_per_frame;
|
return max_physics_steps_per_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Engine::get_user_max_physics_steps_per_frame() const {
|
|
||||||
return max_user_physics_steps_per_frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Engine::set_physics_jitter_fix(double p_threshold) {
|
void Engine::set_physics_jitter_fix(double p_threshold) {
|
||||||
if (p_threshold < 0) {
|
if (p_threshold < 0) {
|
||||||
p_threshold = 0;
|
p_threshold = 0;
|
||||||
|
@ -128,21 +112,11 @@ uint32_t Engine::get_frame_delay() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::set_time_scale(double p_scale) {
|
void Engine::set_time_scale(double p_scale) {
|
||||||
_game_time_scale = p_scale;
|
_time_scale = p_scale;
|
||||||
_update_time_scale();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double Engine::get_time_scale() const {
|
double Engine::get_time_scale() const {
|
||||||
return freeze_time_scale ? 0.0 : _game_time_scale;
|
return freeze_time_scale ? 0 : _time_scale;
|
||||||
}
|
|
||||||
|
|
||||||
void Engine::set_user_time_scale(double p_scale) {
|
|
||||||
_user_time_scale = p_scale;
|
|
||||||
_update_time_scale();
|
|
||||||
}
|
|
||||||
|
|
||||||
double Engine::get_effective_time_scale() const {
|
|
||||||
return freeze_time_scale ? 0.0 : _time_scale;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double Engine::get_unfrozen_time_scale() const {
|
double Engine::get_unfrozen_time_scale() const {
|
||||||
|
|
|
@ -30,13 +30,10 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/string/string_name.h"
|
#include "core/os/main_loop.h"
|
||||||
#include "core/templates/hash_map.h"
|
#include "core/string/ustring.h"
|
||||||
#include "core/templates/list.h"
|
#include "core/templates/list.h"
|
||||||
|
|
||||||
class Object;
|
|
||||||
class Dictionary;
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class TypedArray;
|
class TypedArray;
|
||||||
|
|
||||||
|
@ -62,17 +59,13 @@ private:
|
||||||
double _process_step = 0;
|
double _process_step = 0;
|
||||||
|
|
||||||
int ips = 60;
|
int ips = 60;
|
||||||
int user_ips = 60;
|
|
||||||
double physics_jitter_fix = 0.5;
|
double physics_jitter_fix = 0.5;
|
||||||
double _fps = 1;
|
double _fps = 1;
|
||||||
int _max_fps = 0;
|
int _max_fps = 0;
|
||||||
int _audio_output_latency = 0;
|
int _audio_output_latency = 0;
|
||||||
double _time_scale = 1.0;
|
double _time_scale = 1.0;
|
||||||
double _game_time_scale = 1.0;
|
|
||||||
double _user_time_scale = 1.0;
|
|
||||||
uint64_t _physics_frames = 0;
|
uint64_t _physics_frames = 0;
|
||||||
int max_physics_steps_per_frame = 8;
|
int max_physics_steps_per_frame = 8;
|
||||||
int max_user_physics_steps_per_frame = 8;
|
|
||||||
double _physics_interpolation_fraction = 0.0f;
|
double _physics_interpolation_fraction = 0.0f;
|
||||||
bool abort_on_gpu_errors = false;
|
bool abort_on_gpu_errors = false;
|
||||||
bool use_validation_layers = false;
|
bool use_validation_layers = false;
|
||||||
|
@ -108,19 +101,14 @@ private:
|
||||||
|
|
||||||
bool freeze_time_scale = false;
|
bool freeze_time_scale = false;
|
||||||
|
|
||||||
protected:
|
|
||||||
void _update_time_scale();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Engine *get_singleton();
|
static Engine *get_singleton();
|
||||||
|
|
||||||
virtual void set_physics_ticks_per_second(int p_ips);
|
virtual void set_physics_ticks_per_second(int p_ips);
|
||||||
virtual int get_physics_ticks_per_second() const;
|
virtual int get_physics_ticks_per_second() const;
|
||||||
virtual int get_user_physics_ticks_per_second() const;
|
|
||||||
|
|
||||||
virtual void set_max_physics_steps_per_frame(int p_max_physics_steps);
|
virtual void set_max_physics_steps_per_frame(int p_max_physics_steps);
|
||||||
virtual int get_max_physics_steps_per_frame() const;
|
virtual int get_max_physics_steps_per_frame() const;
|
||||||
virtual int get_user_max_physics_steps_per_frame() const;
|
|
||||||
|
|
||||||
void set_physics_jitter_fix(double p_threshold);
|
void set_physics_jitter_fix(double p_threshold);
|
||||||
double get_physics_jitter_fix() const;
|
double get_physics_jitter_fix() const;
|
||||||
|
@ -144,8 +132,6 @@ public:
|
||||||
|
|
||||||
void set_time_scale(double p_scale);
|
void set_time_scale(double p_scale);
|
||||||
double get_time_scale() const;
|
double get_time_scale() const;
|
||||||
void set_user_time_scale(double p_scale);
|
|
||||||
double get_effective_time_scale() const;
|
|
||||||
double get_unfrozen_time_scale() const;
|
double get_unfrozen_time_scale() const;
|
||||||
|
|
||||||
void set_print_to_stdout(bool p_enabled);
|
void set_print_to_stdout(bool p_enabled);
|
||||||
|
|
|
@ -83,11 +83,6 @@ const PackedStringArray ProjectSettings::get_required_features() {
|
||||||
// Returns the features supported by this build of Godot. Includes all required features.
|
// Returns the features supported by this build of Godot. Includes all required features.
|
||||||
const PackedStringArray ProjectSettings::_get_supported_features() {
|
const PackedStringArray ProjectSettings::_get_supported_features() {
|
||||||
PackedStringArray features = get_required_features();
|
PackedStringArray features = get_required_features();
|
||||||
|
|
||||||
#ifdef LIBGODOT_ENABLED
|
|
||||||
features.append("LibGodot");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MODULE_MONO_ENABLED
|
#ifdef MODULE_MONO_ENABLED
|
||||||
features.append("C#");
|
features.append("C#");
|
||||||
#endif
|
#endif
|
||||||
|
@ -285,7 +280,7 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
|
||||||
if (p_value.get_type() == Variant::NIL) {
|
if (p_value.get_type() == Variant::NIL) {
|
||||||
props.erase(p_name);
|
props.erase(p_name);
|
||||||
if (p_name.operator String().begins_with("autoload/")) {
|
if (p_name.operator String().begins_with("autoload/")) {
|
||||||
String node_name = p_name.operator String().get_slicec('/', 1);
|
String node_name = p_name.operator String().split("/")[1];
|
||||||
if (autoloads.has(node_name)) {
|
if (autoloads.has(node_name)) {
|
||||||
remove_autoload(node_name);
|
remove_autoload(node_name);
|
||||||
}
|
}
|
||||||
|
@ -331,7 +326,7 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
|
||||||
props[p_name] = VariantContainer(p_value, last_order++);
|
props[p_name] = VariantContainer(p_value, last_order++);
|
||||||
}
|
}
|
||||||
if (p_name.operator String().begins_with("autoload/")) {
|
if (p_name.operator String().begins_with("autoload/")) {
|
||||||
String node_name = p_name.operator String().get_slicec('/', 1);
|
String node_name = p_name.operator String().split("/")[1];
|
||||||
AutoloadInfo autoload;
|
AutoloadInfo autoload;
|
||||||
autoload.name = node_name;
|
autoload.name = node_name;
|
||||||
String path = p_value;
|
String path = p_value;
|
||||||
|
@ -648,16 +643,11 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
|
||||||
ERR_FAIL_COND_V_MSG(!ok, ERR_CANT_OPEN, vformat("Cannot open resource pack '%s'.", p_main_pack));
|
ERR_FAIL_COND_V_MSG(!ok, ERR_CANT_OPEN, vformat("Cannot open resource pack '%s'.", p_main_pack));
|
||||||
|
|
||||||
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
|
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
|
||||||
#ifdef OVERRIDE_ENABLED
|
|
||||||
if (err == OK && !p_ignore_override) {
|
if (err == OK && !p_ignore_override) {
|
||||||
// Load override from location of the main pack
|
// Load override from location of the main pack
|
||||||
// Optional, we don't mind if it fails
|
// Optional, we don't mind if it fails
|
||||||
bool disable_override = GLOBAL_GET("application/config/disable_project_settings_override");
|
_load_settings_text(p_main_pack.get_base_dir().path_join("override.cfg"));
|
||||||
if (!disable_override) {
|
|
||||||
_load_settings_text(p_main_pack.get_base_dir().path_join("override.cfg"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif // OVERRIDE_ENABLED
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -703,17 +693,12 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
|
||||||
// If we opened our package, try and load our project.
|
// If we opened our package, try and load our project.
|
||||||
if (found) {
|
if (found) {
|
||||||
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
|
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
|
||||||
#ifdef OVERRIDE_ENABLED
|
|
||||||
if (err == OK && !p_ignore_override) {
|
if (err == OK && !p_ignore_override) {
|
||||||
// Load overrides from the PCK and the executable location.
|
// Load overrides from the PCK and the executable location.
|
||||||
// Optional, we don't mind if either fails.
|
// Optional, we don't mind if either fails.
|
||||||
bool disable_override = GLOBAL_GET("application/config/disable_project_settings_override");
|
_load_settings_text("res://override.cfg");
|
||||||
if (!disable_override) {
|
_load_settings_text(exec_path.get_base_dir().path_join("override.cfg"));
|
||||||
_load_settings_text("res://override.cfg");
|
|
||||||
_load_settings_text(exec_path.get_base_dir().path_join("override.cfg"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif // OVERRIDE_ENABLED
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -728,15 +713,10 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
|
||||||
|
|
||||||
if (!OS::get_singleton()->get_resource_dir().is_empty()) {
|
if (!OS::get_singleton()->get_resource_dir().is_empty()) {
|
||||||
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
|
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
|
||||||
#ifdef OVERRIDE_ENABLED
|
|
||||||
if (err == OK && !p_ignore_override) {
|
if (err == OK && !p_ignore_override) {
|
||||||
// Optional, we don't mind if it fails.
|
// Optional, we don't mind if it fails.
|
||||||
bool disable_override = GLOBAL_GET("application/config/disable_project_settings_override");
|
_load_settings_text("res://override.cfg");
|
||||||
if (!disable_override) {
|
|
||||||
_load_settings_text("res://override.cfg");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif // OVERRIDE_ENABLED
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,16 +736,11 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
|
||||||
err = _load_settings_text_or_binary(resource_path.path_join("project.godot"), resource_path.path_join("project.binary"));
|
err = _load_settings_text_or_binary(resource_path.path_join("project.godot"), resource_path.path_join("project.binary"));
|
||||||
if (err == OK && !p_ignore_override) {
|
if (err == OK && !p_ignore_override) {
|
||||||
// Optional, we don't mind if it fails.
|
// Optional, we don't mind if it fails.
|
||||||
#ifdef OVERRIDE_ENABLED
|
_load_settings_text(resource_path.path_join("override.cfg"));
|
||||||
bool disable_override = GLOBAL_GET("application/config/disable_project_settings_override");
|
|
||||||
if (!disable_override) {
|
|
||||||
_load_settings_text(resource_path.path_join("override.cfg"));
|
|
||||||
}
|
|
||||||
#endif // OVERRIDE_ENABLED
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // MACOS_ENABLED
|
#endif
|
||||||
|
|
||||||
// Nothing was found, try to find a project file in provided path (`p_path`)
|
// Nothing was found, try to find a project file in provided path (`p_path`)
|
||||||
// or, if requested (`p_upwards`) in parent directories.
|
// or, if requested (`p_upwards`) in parent directories.
|
||||||
|
@ -785,12 +760,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
|
||||||
err = _load_settings_text_or_binary(current_dir.path_join("project.godot"), current_dir.path_join("project.binary"));
|
err = _load_settings_text_or_binary(current_dir.path_join("project.godot"), current_dir.path_join("project.binary"));
|
||||||
if (err == OK && !p_ignore_override) {
|
if (err == OK && !p_ignore_override) {
|
||||||
// Optional, we don't mind if it fails.
|
// Optional, we don't mind if it fails.
|
||||||
#ifdef OVERRIDE_ENABLED
|
_load_settings_text(current_dir.path_join("override.cfg"));
|
||||||
bool disable_override = GLOBAL_GET("application/config/disable_project_settings_override");
|
|
||||||
if (!disable_override) {
|
|
||||||
_load_settings_text(current_dir.path_join("override.cfg"));
|
|
||||||
}
|
|
||||||
#endif // OVERRIDE_ENABLED
|
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1599,7 +1569,6 @@ ProjectSettings::ProjectSettings() {
|
||||||
GLOBAL_DEF("application/config/use_custom_user_dir", false);
|
GLOBAL_DEF("application/config/use_custom_user_dir", false);
|
||||||
GLOBAL_DEF("application/config/custom_user_dir_name", "");
|
GLOBAL_DEF("application/config/custom_user_dir_name", "");
|
||||||
GLOBAL_DEF("application/config/project_settings_override", "");
|
GLOBAL_DEF("application/config/project_settings_override", "");
|
||||||
GLOBAL_DEF("application/config/disable_project_settings_override", false);
|
|
||||||
|
|
||||||
GLOBAL_DEF("application/run/main_loop_type", "SceneTree");
|
GLOBAL_DEF("application/run/main_loop_type", "SceneTree");
|
||||||
GLOBAL_DEF("application/config/auto_accept_quit", true);
|
GLOBAL_DEF("application/config/auto_accept_quit", true);
|
||||||
|
@ -1706,7 +1675,6 @@ ProjectSettings::ProjectSettings() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GLOBAL_DEF_BASIC("gui/common/snap_controls_to_pixels", true);
|
GLOBAL_DEF_BASIC("gui/common/snap_controls_to_pixels", true);
|
||||||
GLOBAL_DEF("gui/common/always_show_focus_state", false);
|
|
||||||
GLOBAL_DEF_BASIC("gui/fonts/dynamic_fonts/use_oversampling", true);
|
GLOBAL_DEF_BASIC("gui/fonts/dynamic_fonts/use_oversampling", true);
|
||||||
|
|
||||||
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/rendering_device/vsync/frame_queue_size", PROPERTY_HINT_RANGE, "2,3,1"), 2);
|
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/rendering_device/vsync/frame_queue_size", PROPERTY_HINT_RANGE, "2,3,1"), 2);
|
||||||
|
@ -1730,7 +1698,7 @@ ProjectSettings::ProjectSettings() {
|
||||||
// installed by the scripts provided in the repository
|
// installed by the scripts provided in the repository
|
||||||
// (check `misc/scripts/install_d3d12_sdk_windows.py`).
|
// (check `misc/scripts/install_d3d12_sdk_windows.py`).
|
||||||
// For example, if the script installs 1.613.3, the default value must be 613.
|
// For example, if the script installs 1.613.3, the default value must be 613.
|
||||||
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/rendering_device/d3d12/agility_sdk_version", PROPERTY_HINT_RANGE, "0,10000,1,or_greater,hide_control"), 613);
|
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/rendering_device/d3d12/agility_sdk_version", PROPERTY_HINT_RANGE, "0,10000,1,or_greater,hide_slider"), 613);
|
||||||
|
|
||||||
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/textures/canvas_textures/default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Linear Mipmap,Nearest Mipmap"), 1);
|
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/textures/canvas_textures/default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Linear Mipmap,Nearest Mipmap"), 1);
|
||||||
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/textures/canvas_textures/default_texture_repeat", PROPERTY_HINT_ENUM, "Disable,Enable,Mirror"), 0);
|
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/textures/canvas_textures/default_texture_repeat", PROPERTY_HINT_ENUM, "Disable,Enable,Mirror"), 0);
|
||||||
|
|
|
@ -30,8 +30,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/object/object.h"
|
#include "core/object/class_db.h"
|
||||||
#include "core/templates/rb_map.h"
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class TypedArray;
|
class TypedArray;
|
||||||
|
@ -50,7 +49,7 @@ class ProjectSettings : public Object {
|
||||||
public:
|
public:
|
||||||
typedef HashMap<String, Variant> CustomMap;
|
typedef HashMap<String, Variant> CustomMap;
|
||||||
static inline const String PROJECT_DATA_DIR_NAME_SUFFIX = "godot";
|
static inline const String PROJECT_DATA_DIR_NAME_SUFFIX = "godot";
|
||||||
static inline const String EDITOR_SETTING_OVERRIDE_PREFIX = PNAME("editor_overrides") + String("/");
|
static inline const String EDITOR_SETTING_OVERRIDE_PREFIX = "editor_overrides/";
|
||||||
|
|
||||||
// Properties that are not for built in values begin from this value, so builtin ones are displayed first.
|
// Properties that are not for built in values begin from this value, so builtin ones are displayed first.
|
||||||
constexpr static const int32_t NO_BUILTIN_ORDER_BASE = 1 << 16;
|
constexpr static const int32_t NO_BUILTIN_ORDER_BASE = 1 << 16;
|
||||||
|
|
|
@ -35,12 +35,10 @@
|
||||||
#include "core/crypto/crypto_core.h"
|
#include "core/crypto/crypto_core.h"
|
||||||
#include "core/debugger/engine_debugger.h"
|
#include "core/debugger/engine_debugger.h"
|
||||||
#include "core/debugger/script_debugger.h"
|
#include "core/debugger/script_debugger.h"
|
||||||
#include "core/io/file_access.h"
|
|
||||||
#include "core/io/marshalls.h"
|
#include "core/io/marshalls.h"
|
||||||
#include "core/math/geometry_2d.h"
|
#include "core/math/geometry_2d.h"
|
||||||
#include "core/math/geometry_3d.h"
|
#include "core/math/geometry_3d.h"
|
||||||
#include "core/os/keyboard.h"
|
#include "core/os/keyboard.h"
|
||||||
#include "core/os/main_loop.h"
|
|
||||||
#include "core/os/thread_safe.h"
|
#include "core/os/thread_safe.h"
|
||||||
#include "core/variant/typed_array.h"
|
#include "core/variant/typed_array.h"
|
||||||
|
|
||||||
|
@ -1528,10 +1526,6 @@ void Thread::set_thread_safety_checks_enabled(bool p_enabled) {
|
||||||
set_current_thread_safe_for_nodes(!p_enabled);
|
set_current_thread_safe_for_nodes(!p_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Thread::is_main_thread() {
|
|
||||||
return ::Thread::is_main_thread();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Thread::_bind_methods() {
|
void Thread::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("start", "callable", "priority"), &Thread::start, DEFVAL(PRIORITY_NORMAL));
|
ClassDB::bind_method(D_METHOD("start", "callable", "priority"), &Thread::start, DEFVAL(PRIORITY_NORMAL));
|
||||||
ClassDB::bind_method(D_METHOD("get_id"), &Thread::get_id);
|
ClassDB::bind_method(D_METHOD("get_id"), &Thread::get_id);
|
||||||
|
@ -1540,7 +1534,6 @@ void Thread::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("wait_to_finish"), &Thread::wait_to_finish);
|
ClassDB::bind_method(D_METHOD("wait_to_finish"), &Thread::wait_to_finish);
|
||||||
|
|
||||||
ClassDB::bind_static_method("Thread", D_METHOD("set_thread_safety_checks_enabled", "enabled"), &Thread::set_thread_safety_checks_enabled);
|
ClassDB::bind_static_method("Thread", D_METHOD("set_thread_safety_checks_enabled", "enabled"), &Thread::set_thread_safety_checks_enabled);
|
||||||
ClassDB::bind_static_method("Thread", D_METHOD("is_main_thread"), &Thread::is_main_thread);
|
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(PRIORITY_LOW);
|
BIND_ENUM_CONSTANT(PRIORITY_LOW);
|
||||||
BIND_ENUM_CONSTANT(PRIORITY_NORMAL);
|
BIND_ENUM_CONSTANT(PRIORITY_NORMAL);
|
||||||
|
@ -1552,16 +1545,14 @@ namespace Special {
|
||||||
////// ClassDB //////
|
////// ClassDB //////
|
||||||
|
|
||||||
PackedStringArray ClassDB::get_class_list() const {
|
PackedStringArray ClassDB::get_class_list() const {
|
||||||
LocalVector<StringName> classes;
|
List<StringName> classes;
|
||||||
::ClassDB::get_class_list(classes);
|
::ClassDB::get_class_list(&classes);
|
||||||
|
|
||||||
PackedStringArray ret;
|
PackedStringArray ret;
|
||||||
ret.resize(classes.size());
|
ret.resize(classes.size());
|
||||||
String *ptrw = ret.ptrw();
|
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
for (const StringName &cls : classes) {
|
for (const StringName &E : classes) {
|
||||||
ptrw[idx] = cls;
|
ret.set(idx++, E);
|
||||||
idx++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1815,12 +1806,8 @@ void ClassDB::get_argument_options(const StringName &p_function, int p_idx, List
|
||||||
pf == "is_class_enabled" || pf == "is_class_enum_bitfield" || pf == "class_get_api_type");
|
pf == "is_class_enabled" || pf == "is_class_enum_bitfield" || pf == "class_get_api_type");
|
||||||
}
|
}
|
||||||
if (first_argument_is_class || pf == "is_parent_class") {
|
if (first_argument_is_class || pf == "is_parent_class") {
|
||||||
LocalVector<StringName> classes;
|
for (const String &E : get_class_list()) {
|
||||||
::ClassDB::get_class_list(classes);
|
r_options->push_back(E.quote());
|
||||||
for (const StringName &E : classes) {
|
|
||||||
if (::ClassDB::is_class_exposed(E)) {
|
|
||||||
r_options->push_back(E.operator String().quote());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -495,7 +495,6 @@ public:
|
||||||
Variant wait_to_finish();
|
Variant wait_to_finish();
|
||||||
|
|
||||||
static void set_thread_safety_checks_enabled(bool p_enabled);
|
static void set_thread_safety_checks_enabled(bool p_enabled);
|
||||||
static bool is_main_thread();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Special {
|
namespace Special {
|
||||||
|
|
|
@ -11,7 +11,7 @@ def disabled_class_builder(target, source, env):
|
||||||
with methods.generated_wrapper(str(target[0])) as file:
|
with methods.generated_wrapper(str(target[0])) as file:
|
||||||
for c in source[0].read():
|
for c in source[0].read():
|
||||||
if cs := c.strip():
|
if cs := c.strip():
|
||||||
file.write(f"class {cs}; template <> struct is_class_enabled<{cs}> : std::false_type {{}};\n")
|
file.write(f"#define ClassDB_Disable_{cs} 1\n")
|
||||||
|
|
||||||
|
|
||||||
# Generate version info
|
# Generate version info
|
||||||
|
|
|
@ -75,7 +75,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CONSTANT(m_constant) \
|
#define BIND_CORE_ENUM_CONSTANT(m_constant) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_constant); \
|
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
|
||||||
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -83,7 +83,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_BITFIELD_FLAG(m_constant) \
|
#define BIND_CORE_BITFIELD_FLAG(m_constant) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_bitfield_name(m_constant); \
|
StringName enum_name = __constant_get_bitfield_name(m_constant, #m_constant); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant, false, true)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant, false, true)); \
|
||||||
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -92,7 +92,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
// This just binds enum classes as if they were regular enum constants.
|
// This just binds enum classes as if they were regular enum constants.
|
||||||
#define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \
|
#define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
|
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
|
||||||
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -100,7 +100,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_BITFIELD_CLASS_FLAG(m_enum, m_prefix, m_member) \
|
#define BIND_CORE_BITFIELD_CLASS_FLAG(m_enum, m_prefix, m_member) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member); \
|
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member, #m_prefix "_" #m_member); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member, false, true)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member, false, true)); \
|
||||||
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -108,7 +108,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \
|
#define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
|
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_name); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member)); \
|
||||||
_global_constants_map[#m_name] = _global_constants.size() - 1; \
|
_global_constants_map[#m_name] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -116,7 +116,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(m_enum, m_name, m_member) \
|
#define BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(m_enum, m_name, m_member) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member); \
|
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member, #m_name); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member, false, true)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member, false, true)); \
|
||||||
_global_constants_map[#m_name] = _global_constants.size() - 1; \
|
_global_constants_map[#m_name] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -124,7 +124,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CLASS_CONSTANT_NO_VAL(m_enum, m_prefix, m_member) \
|
#define BIND_CORE_ENUM_CLASS_CONSTANT_NO_VAL(m_enum, m_prefix, m_member) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
|
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member, true)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member, true)); \
|
||||||
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -132,7 +132,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \
|
#define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_constant); \
|
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant)); \
|
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant)); \
|
||||||
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
|
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -144,7 +144,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CONSTANT_NO_VAL(m_constant) \
|
#define BIND_CORE_ENUM_CONSTANT_NO_VAL(m_constant) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_constant); \
|
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant, true)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant, true)); \
|
||||||
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -152,7 +152,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CONSTANT_CUSTOM_NO_VAL(m_custom_name, m_constant) \
|
#define BIND_CORE_ENUM_CONSTANT_CUSTOM_NO_VAL(m_custom_name, m_constant) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_constant); \
|
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant, true)); \
|
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant, true)); \
|
||||||
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
|
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -166,7 +166,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CONSTANT(m_constant) \
|
#define BIND_CORE_ENUM_CONSTANT(m_constant) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_constant); \
|
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
|
||||||
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -174,7 +174,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_BITFIELD_FLAG(m_constant) \
|
#define BIND_CORE_BITFIELD_FLAG(m_constant) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_bitfield_name(m_constant); \
|
StringName enum_name = __constant_get_bitfield_name(m_constant, #m_constant); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
|
||||||
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -183,7 +183,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
// This just binds enum classes as if they were regular enum constants.
|
// This just binds enum classes as if they were regular enum constants.
|
||||||
#define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \
|
#define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
|
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
|
||||||
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -191,7 +191,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_BITFIELD_CLASS_FLAG(m_enum, m_prefix, m_member) \
|
#define BIND_CORE_BITFIELD_CLASS_FLAG(m_enum, m_prefix, m_member) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member); \
|
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member, #m_prefix "_" #m_member); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
|
||||||
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -199,7 +199,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \
|
#define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
|
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_name); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member)); \
|
||||||
_global_constants_map[#m_name] = _global_constants.size() - 1; \
|
_global_constants_map[#m_name] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -207,7 +207,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(m_enum, m_name, m_member) \
|
#define BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(m_enum, m_name, m_member) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member); \
|
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member, #m_name); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member)); \
|
||||||
_global_constants_map[#m_name] = _global_constants.size() - 1; \
|
_global_constants_map[#m_name] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -215,7 +215,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CLASS_CONSTANT_NO_VAL(m_enum, m_prefix, m_member) \
|
#define BIND_CORE_ENUM_CLASS_CONSTANT_NO_VAL(m_enum, m_prefix, m_member) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
|
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
|
||||||
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -223,7 +223,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \
|
#define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_constant); \
|
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant)); \
|
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant)); \
|
||||||
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
|
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -235,7 +235,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CONSTANT_NO_VAL(m_constant) \
|
#define BIND_CORE_ENUM_CONSTANT_NO_VAL(m_constant) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_constant); \
|
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
|
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
|
||||||
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
@ -243,7 +243,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
|
||||||
|
|
||||||
#define BIND_CORE_ENUM_CONSTANT_CUSTOM_NO_VAL(m_custom_name, m_constant) \
|
#define BIND_CORE_ENUM_CONSTANT_CUSTOM_NO_VAL(m_custom_name, m_constant) \
|
||||||
{ \
|
{ \
|
||||||
StringName enum_name = __constant_get_enum_name(m_constant); \
|
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
|
||||||
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant)); \
|
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant)); \
|
||||||
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
|
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
|
||||||
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
|
||||||
|
|
|
@ -149,8 +149,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResourceFormatLoaderCrypto : public ResourceFormatLoader {
|
class ResourceFormatLoaderCrypto : public ResourceFormatLoader {
|
||||||
GDSOFTCLASS(ResourceFormatLoaderCrypto, ResourceFormatLoader);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
|
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
|
||||||
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
|
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
|
||||||
|
@ -163,8 +161,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResourceFormatSaverCrypto : public ResourceFormatSaver {
|
class ResourceFormatSaverCrypto : public ResourceFormatSaver {
|
||||||
GDSOFTCLASS(ResourceFormatSaverCrypto, ResourceFormatSaver);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0) override;
|
virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0) override;
|
||||||
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const override;
|
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const override;
|
||||||
|
|
|
@ -121,10 +121,7 @@ void EngineDebugger::iteration(uint64_t p_frame_ticks, uint64_t p_process_ticks,
|
||||||
}
|
}
|
||||||
|
|
||||||
void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, bool p_ignore_error_breaks, const Vector<String> &p_breakpoints, void (*p_allow_focus_steal_fn)()) {
|
void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, bool p_ignore_error_breaks, const Vector<String> &p_breakpoints, void (*p_allow_focus_steal_fn)()) {
|
||||||
register_uri_handler("tcp://", RemoteDebuggerPeerTCP::create_tcp); // TCP is the default protocol. Platforms/modules can add more.
|
register_uri_handler("tcp://", RemoteDebuggerPeerTCP::create); // TCP is the default protocol. Platforms/modules can add more.
|
||||||
#ifdef UNIX_ENABLED
|
|
||||||
register_uri_handler("unix://", RemoteDebuggerPeerTCP::create_unix);
|
|
||||||
#endif
|
|
||||||
if (p_uri.is_empty()) {
|
if (p_uri.is_empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -135,10 +132,10 @@ void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, bo
|
||||||
OS::get_singleton()->initialize_debugging();
|
OS::get_singleton()->initialize_debugging();
|
||||||
} else if (p_uri.contains("://")) {
|
} else if (p_uri.contains("://")) {
|
||||||
const String proto = p_uri.substr(0, p_uri.find("://") + 3);
|
const String proto = p_uri.substr(0, p_uri.find("://") + 3);
|
||||||
CreatePeerFunc *create_fn = protocols.getptr(proto);
|
if (!protocols.has(proto)) {
|
||||||
ERR_FAIL_NULL_MSG(create_fn, vformat("Invalid protocol: %s.", proto));
|
return;
|
||||||
|
}
|
||||||
RemoteDebuggerPeer *peer = (*create_fn)(p_uri);
|
RemoteDebuggerPeer *peer = protocols[proto](p_uri);
|
||||||
if (!peer) {
|
if (!peer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
#include "local_debugger.h"
|
#include "local_debugger.h"
|
||||||
|
|
||||||
#include "core/debugger/script_debugger.h"
|
#include "core/debugger/script_debugger.h"
|
||||||
#include "core/os/main_loop.h"
|
|
||||||
#include "core/os/os.h"
|
#include "core/os/os.h"
|
||||||
|
|
||||||
struct LocalDebugger::ScriptsProfiler {
|
struct LocalDebugger::ScriptsProfiler {
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
#include "core/math/expression.h"
|
#include "core/math/expression.h"
|
||||||
#include "core/object/script_language.h"
|
#include "core/object/script_language.h"
|
||||||
#include "core/os/os.h"
|
#include "core/os/os.h"
|
||||||
#include "servers/display/display_server.h"
|
#include "servers/display_server.h"
|
||||||
|
|
||||||
class RemoteDebugger::PerformanceProfiler : public EngineProfiler {
|
class RemoteDebugger::PerformanceProfiler : public EngineProfiler {
|
||||||
Object *performance = nullptr;
|
Object *performance = nullptr;
|
||||||
|
@ -48,9 +48,9 @@ class RemoteDebugger::PerformanceProfiler : public EngineProfiler {
|
||||||
uint64_t last_monitor_modification_time = 0;
|
uint64_t last_monitor_modification_time = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void toggle(bool p_enable, const Array &p_opts) override {}
|
void toggle(bool p_enable, const Array &p_opts) {}
|
||||||
void add(const Array &p_data) override {}
|
void add(const Array &p_data) {}
|
||||||
void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) override {
|
void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) {
|
||||||
if (!performance) {
|
if (!performance) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -566,25 +566,25 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
|
||||||
input_vals.append(V);
|
input_vals.append(V);
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalVector<StringName> native_types;
|
List<StringName> native_types;
|
||||||
ClassDB::get_class_list(native_types);
|
ClassDB::get_class_list(&native_types);
|
||||||
for (const StringName &class_name : native_types) {
|
for (const StringName &E : native_types) {
|
||||||
if (!ClassDB::is_class_exposed(class_name) || !Engine::get_singleton()->has_singleton(class_name) || Engine::get_singleton()->is_singleton_editor_only(class_name)) {
|
if (!ClassDB::is_class_exposed(E) || !Engine::get_singleton()->has_singleton(E) || Engine::get_singleton()->is_singleton_editor_only(E)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
input_names.append(class_name);
|
input_names.append(E);
|
||||||
input_vals.append(Engine::get_singleton()->get_singleton_object(class_name));
|
input_vals.append(Engine::get_singleton()->get_singleton_object(E));
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalVector<StringName> user_types;
|
List<StringName> user_types;
|
||||||
ScriptServer::get_global_class_list(user_types);
|
ScriptServer::get_global_class_list(&user_types);
|
||||||
for (const StringName &class_name : user_types) {
|
for (const StringName &S : user_types) {
|
||||||
String scr_path = ScriptServer::get_global_class_path(class_name);
|
String scr_path = ScriptServer::get_global_class_path(S);
|
||||||
Ref<Script> scr = ResourceLoader::load(scr_path, "Script");
|
Ref<Script> scr = ResourceLoader::load(scr_path, "Script");
|
||||||
ERR_CONTINUE_MSG(scr.is_null(), vformat(R"(Could not load the global class %s from resource path: "%s".)", class_name, scr_path));
|
ERR_CONTINUE_MSG(scr.is_null(), vformat(R"(Could not load the global class %s from resource path: "%s".)", S, scr_path));
|
||||||
|
|
||||||
input_names.append(class_name);
|
input_names.append(S);
|
||||||
input_vals.append(scr);
|
input_vals.append(scr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,19 +76,18 @@ void RemoteDebuggerPeerTCP::close() {
|
||||||
in_buf.clear();
|
in_buf.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoteDebuggerPeerTCP::RemoteDebuggerPeerTCP() {
|
RemoteDebuggerPeerTCP::RemoteDebuggerPeerTCP(Ref<StreamPeerTCP> p_tcp) {
|
||||||
// This means remote debugger takes 16 MiB just because it exists...
|
// This means remote debugger takes 16 MiB just because it exists...
|
||||||
in_buf.resize((8 << 20) + 4); // 8 MiB should be way more than enough (need 4 extra bytes for encoding packet size).
|
in_buf.resize((8 << 20) + 4); // 8 MiB should be way more than enough (need 4 extra bytes for encoding packet size).
|
||||||
out_buf.resize(8 << 20); // 8 MiB should be way more than enough
|
out_buf.resize(8 << 20); // 8 MiB should be way more than enough
|
||||||
}
|
tcp_client = p_tcp;
|
||||||
|
if (tcp_client.is_valid()) { // Attaching to an already connected stream.
|
||||||
RemoteDebuggerPeerTCP::RemoteDebuggerPeerTCP(Ref<StreamPeerSocket> p_stream) :
|
connected = true;
|
||||||
RemoteDebuggerPeerTCP() {
|
running = true;
|
||||||
DEV_ASSERT(p_stream.is_valid());
|
thread.start(_thread_func, this);
|
||||||
tcp_client = p_stream;
|
} else {
|
||||||
connected = true;
|
tcp_client.instantiate();
|
||||||
running = true;
|
}
|
||||||
thread.start(_thread_func, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoteDebuggerPeerTCP::~RemoteDebuggerPeerTCP() {
|
RemoteDebuggerPeerTCP::~RemoteDebuggerPeerTCP() {
|
||||||
|
@ -155,10 +154,22 @@ void RemoteDebuggerPeerTCP::_read_in() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Error RemoteDebuggerPeerTCP::_try_connect(Ref<StreamPeerSocket> tcp_client) {
|
Error RemoteDebuggerPeerTCP::connect_to_host(const String &p_host, uint16_t p_port) {
|
||||||
|
IPAddress ip;
|
||||||
|
if (p_host.is_valid_ip_address()) {
|
||||||
|
ip = p_host;
|
||||||
|
} else {
|
||||||
|
ip = IP::get_singleton()->resolve_hostname(p_host);
|
||||||
|
}
|
||||||
|
|
||||||
|
int port = p_port;
|
||||||
|
|
||||||
const int tries = 6;
|
const int tries = 6;
|
||||||
const int waits[tries] = { 1, 10, 100, 1000, 1000, 1000 };
|
const int waits[tries] = { 1, 10, 100, 1000, 1000, 1000 };
|
||||||
|
|
||||||
|
Error err = tcp_client->connect_to_host(ip, port);
|
||||||
|
ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Remote Debugger: Unable to connect to host '%s:%d'.", p_host, port));
|
||||||
|
|
||||||
for (int i = 0; i < tries; i++) {
|
for (int i = 0; i < tries; i++) {
|
||||||
tcp_client->poll();
|
tcp_client->poll();
|
||||||
if (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED) {
|
if (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED) {
|
||||||
|
@ -175,6 +186,9 @@ Error RemoteDebuggerPeerTCP::_try_connect(Ref<StreamPeerSocket> tcp_client) {
|
||||||
ERR_PRINT(vformat("Remote Debugger: Unable to connect. Status: %s.", String::num_int64(tcp_client->get_status())));
|
ERR_PRINT(vformat("Remote Debugger: Unable to connect. Status: %s.", String::num_int64(tcp_client->get_status())));
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
|
connected = true;
|
||||||
|
running = true;
|
||||||
|
thread.start(_thread_func, this);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +222,7 @@ void RemoteDebuggerPeerTCP::_poll() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create_tcp(const String &p_uri) {
|
RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create(const String &p_uri) {
|
||||||
ERR_FAIL_COND_V(!p_uri.begins_with("tcp://"), nullptr);
|
ERR_FAIL_COND_V(!p_uri.begins_with("tcp://"), nullptr);
|
||||||
|
|
||||||
String debug_host = p_uri.replace("tcp://", "");
|
String debug_host = p_uri.replace("tcp://", "");
|
||||||
|
@ -220,30 +234,13 @@ RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create_tcp(const String &p_uri) {
|
||||||
debug_host = debug_host.substr(0, sep_pos);
|
debug_host = debug_host.substr(0, sep_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPAddress ip;
|
RemoteDebuggerPeerTCP *peer = memnew(RemoteDebuggerPeerTCP);
|
||||||
if (debug_host.is_valid_ip_address()) {
|
Error err = peer->connect_to_host(debug_host, debug_port);
|
||||||
ip = debug_host;
|
if (err != OK) {
|
||||||
} else {
|
memdelete(peer);
|
||||||
ip = IP::get_singleton()->resolve_hostname(debug_host);
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
return peer;
|
||||||
Ref<StreamPeerTCP> stream;
|
|
||||||
stream.instantiate();
|
|
||||||
ERR_FAIL_COND_V_MSG(stream->connect_to_host(ip, debug_port) != OK, nullptr, vformat("Remote Debugger: Unable to connect to host '%s:%d'.", debug_host, debug_port));
|
|
||||||
ERR_FAIL_COND_V(_try_connect(stream), nullptr);
|
|
||||||
return memnew(RemoteDebuggerPeerTCP(stream));
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create_unix(const String &p_uri) {
|
|
||||||
ERR_FAIL_COND_V(!p_uri.begins_with("unix://"), nullptr);
|
|
||||||
|
|
||||||
String debug_path = p_uri.replace("unix://", "");
|
|
||||||
Ref<StreamPeerUDS> stream;
|
|
||||||
stream.instantiate();
|
|
||||||
Error err = stream->connect_to_host(debug_path);
|
|
||||||
ERR_FAIL_COND_V_MSG(err != OK && err != ERR_BUSY, nullptr, vformat("Remote Debugger: Unable to connect to socket path '%s'.", debug_path));
|
|
||||||
ERR_FAIL_COND_V(_try_connect(stream), nullptr);
|
|
||||||
return memnew(RemoteDebuggerPeerTCP(stream));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoteDebuggerPeer::RemoteDebuggerPeer() {
|
RemoteDebuggerPeer::RemoteDebuggerPeer() {
|
||||||
|
|
|
@ -31,15 +31,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/io/stream_peer_tcp.h"
|
#include "core/io/stream_peer_tcp.h"
|
||||||
#include "core/io/stream_peer_uds.h"
|
|
||||||
#include "core/object/ref_counted.h"
|
#include "core/object/ref_counted.h"
|
||||||
#include "core/os/mutex.h"
|
#include "core/os/mutex.h"
|
||||||
#include "core/os/thread.h"
|
#include "core/os/thread.h"
|
||||||
#include "core/string/ustring.h"
|
#include "core/string/ustring.h"
|
||||||
|
|
||||||
class RemoteDebuggerPeer : public RefCounted {
|
class RemoteDebuggerPeer : public RefCounted {
|
||||||
GDSOFTCLASS(RemoteDebuggerPeer, RefCounted);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int max_queued_messages = 4096;
|
int max_queued_messages = 4096;
|
||||||
|
|
||||||
|
@ -57,10 +54,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class RemoteDebuggerPeerTCP : public RemoteDebuggerPeer {
|
class RemoteDebuggerPeerTCP : public RemoteDebuggerPeer {
|
||||||
GDSOFTCLASS(RemoteDebuggerPeerTCP, RemoteDebuggerPeer);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ref<StreamPeerSocket> tcp_client;
|
Ref<StreamPeerTCP> tcp_client;
|
||||||
Mutex mutex;
|
Mutex mutex;
|
||||||
Thread thread;
|
Thread thread;
|
||||||
List<Array> in_queue;
|
List<Array> in_queue;
|
||||||
|
@ -79,11 +74,11 @@ private:
|
||||||
void _poll();
|
void _poll();
|
||||||
void _write_out();
|
void _write_out();
|
||||||
void _read_in();
|
void _read_in();
|
||||||
static Error _try_connect(Ref<StreamPeerSocket> p_stream);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static RemoteDebuggerPeer *create_tcp(const String &p_uri);
|
static RemoteDebuggerPeer *create(const String &p_uri);
|
||||||
static RemoteDebuggerPeer *create_unix(const String &p_uri);
|
|
||||||
|
Error connect_to_host(const String &p_host, uint16_t p_port);
|
||||||
|
|
||||||
bool is_peer_connected() override;
|
bool is_peer_connected() override;
|
||||||
int get_max_message_size() const override;
|
int get_max_message_size() const override;
|
||||||
|
@ -93,7 +88,6 @@ public:
|
||||||
void poll() override;
|
void poll() override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
RemoteDebuggerPeerTCP(Ref<StreamPeerSocket> p_stream);
|
RemoteDebuggerPeerTCP(Ref<StreamPeerTCP> p_stream = Ref<StreamPeerTCP>());
|
||||||
RemoteDebuggerPeerTCP();
|
|
||||||
~RemoteDebuggerPeerTCP();
|
~RemoteDebuggerPeerTCP();
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
#include "error_list.h"
|
#include "error_list.h"
|
||||||
|
|
||||||
#include "core/typedefs.h"
|
#include <iterator>
|
||||||
|
|
||||||
const char *error_names[] = {
|
const char *error_names[] = {
|
||||||
"OK", // OK
|
"OK", // OK
|
||||||
|
@ -84,4 +84,4 @@ const char *error_names[] = {
|
||||||
"Printer on fire", // ERR_PRINTER_ON_FIRE
|
"Printer on fire", // ERR_PRINTER_ON_FIRE
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(std_size(error_names) == ERR_MAX);
|
static_assert(std::size(error_names) == ERR_MAX);
|
||||||
|
|
|
@ -900,9 +900,11 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
|
||||||
// classes
|
// classes
|
||||||
Array classes;
|
Array classes;
|
||||||
|
|
||||||
LocalVector<StringName> class_list;
|
List<StringName> class_list;
|
||||||
|
|
||||||
ClassDB::get_class_list(class_list);
|
ClassDB::get_class_list(&class_list);
|
||||||
|
|
||||||
|
class_list.sort_custom<StringName::AlphCompare>();
|
||||||
|
|
||||||
for (const StringName &class_name : class_list) {
|
for (const StringName &class_name : class_list) {
|
||||||
if (!ClassDB::is_class_exposed(class_name)) {
|
if (!ClassDB::is_class_exposed(class_name)) {
|
||||||
|
|
|
@ -184,8 +184,6 @@ public:
|
||||||
VARIANT_ENUM_CAST(GDExtension::InitializationLevel)
|
VARIANT_ENUM_CAST(GDExtension::InitializationLevel)
|
||||||
|
|
||||||
class GDExtensionResourceLoader : public ResourceFormatLoader {
|
class GDExtensionResourceLoader : public ResourceFormatLoader {
|
||||||
GDSOFTCLASS(GDExtensionResourceLoader, ResourceFormatLoader);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Error load_gdextension_resource(const String &p_path, Ref<GDExtension> &p_extension);
|
static Error load_gdextension_resource(const String &p_path, Ref<GDExtension> &p_extension);
|
||||||
|
|
||||||
|
|
|
@ -1,74 +0,0 @@
|
||||||
/**************************************************************************/
|
|
||||||
/* gdextension_function_loader.cpp */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
|
||||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
#include "gdextension_function_loader.h"
|
|
||||||
|
|
||||||
#include "gdextension.h"
|
|
||||||
|
|
||||||
Error GDExtensionFunctionLoader::open_library(const String &p_path) {
|
|
||||||
ERR_FAIL_COND_V_MSG(!p_path.begins_with("libgodot://"), ERR_FILE_NOT_FOUND, "Function based GDExtensions should have a path starting with libgodot://");
|
|
||||||
ERR_FAIL_COND_V_MSG(!initialization_function, ERR_DOES_NOT_EXIST, "Initialization function is required for function based GDExtensions.");
|
|
||||||
|
|
||||||
library_path = p_path;
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
Error GDExtensionFunctionLoader::initialize(GDExtensionInterfaceGetProcAddress p_get_proc_address, const Ref<GDExtension> &p_extension, GDExtensionInitialization *r_initialization) {
|
|
||||||
ERR_FAIL_COND_V_MSG(!initialization_function, ERR_DOES_NOT_EXIST, "Initialization function is required for function based GDExtensions.");
|
|
||||||
GDExtensionBool ret = initialization_function(p_get_proc_address, p_extension.ptr(), r_initialization);
|
|
||||||
|
|
||||||
if (ret) {
|
|
||||||
return OK;
|
|
||||||
} else {
|
|
||||||
ERR_FAIL_V_MSG(FAILED, "GDExtension initialization function for '" + library_path + "' returned an error.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GDExtensionFunctionLoader::close_library() {
|
|
||||||
initialization_function = nullptr;
|
|
||||||
library_path.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GDExtensionFunctionLoader::is_library_open() const {
|
|
||||||
return !library_path.is_empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GDExtensionFunctionLoader::has_library_changed() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GDExtensionFunctionLoader::library_exists() const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GDExtensionFunctionLoader::set_initialization_function(GDExtensionInitializationFunction p_initialization_function) {
|
|
||||||
initialization_function = p_initialization_function;
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
/**************************************************************************/
|
|
||||||
/* gdextension_function_loader.h */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
|
||||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/extension/gdextension_loader.h"
|
|
||||||
#include "core/os/shared_object.h"
|
|
||||||
|
|
||||||
class GDExtension;
|
|
||||||
|
|
||||||
class GDExtensionFunctionLoader : public GDExtensionLoader {
|
|
||||||
friend class GDExtensionManager;
|
|
||||||
friend class GDExtension;
|
|
||||||
|
|
||||||
String library_path;
|
|
||||||
GDExtensionInitializationFunction initialization_function = nullptr;
|
|
||||||
|
|
||||||
public:
|
|
||||||
virtual Error open_library(const String &p_path) override;
|
|
||||||
virtual Error initialize(GDExtensionInterfaceGetProcAddress p_get_proc_address, const Ref<GDExtension> &p_extension, GDExtensionInitialization *r_initialization) override;
|
|
||||||
virtual void close_library() override;
|
|
||||||
virtual bool is_library_open() const override;
|
|
||||||
virtual bool has_library_changed() const override;
|
|
||||||
virtual bool library_exists() const override;
|
|
||||||
|
|
||||||
void set_initialization_function(GDExtensionInitializationFunction p_initialization_function);
|
|
||||||
};
|
|
|
@ -261,7 +261,6 @@ static void gdextension_get_godot_version2(GDExtensionGodotVersion2 *r_godot_ver
|
||||||
}
|
}
|
||||||
|
|
||||||
// Memory Functions
|
// Memory Functions
|
||||||
#ifndef DISABLE_DEPRECATED
|
|
||||||
static void *gdextension_mem_alloc(size_t p_size) {
|
static void *gdextension_mem_alloc(size_t p_size) {
|
||||||
return memalloc(p_size);
|
return memalloc(p_size);
|
||||||
}
|
}
|
||||||
|
@ -273,19 +272,6 @@ static void *gdextension_mem_realloc(void *p_mem, size_t p_size) {
|
||||||
static void gdextension_mem_free(void *p_mem) {
|
static void gdextension_mem_free(void *p_mem) {
|
||||||
memfree(p_mem);
|
memfree(p_mem);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static void *gdextension_mem_alloc2(size_t p_size, GDExtensionBool p_prepad_align) {
|
|
||||||
return Memory::alloc_static(p_size, p_prepad_align);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *gdextension_mem_realloc2(void *p_mem, size_t p_size, GDExtensionBool p_prepad_align) {
|
|
||||||
return Memory::realloc_static(p_mem, p_size, p_prepad_align);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void gdextension_mem_free2(void *p_mem, GDExtensionBool p_prepad_align) {
|
|
||||||
Memory::free_static(p_mem, p_prepad_align);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper print functions.
|
// Helper print functions.
|
||||||
static void gdextension_print_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify) {
|
static void gdextension_print_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify) {
|
||||||
|
@ -1701,14 +1687,9 @@ void gdextension_setup_interface() {
|
||||||
REGISTER_INTERFACE_FUNC(get_godot_version);
|
REGISTER_INTERFACE_FUNC(get_godot_version);
|
||||||
#endif // DISABLE_DEPRECATED
|
#endif // DISABLE_DEPRECATED
|
||||||
REGISTER_INTERFACE_FUNC(get_godot_version2);
|
REGISTER_INTERFACE_FUNC(get_godot_version2);
|
||||||
#ifndef DISABLE_DEPRECATED
|
|
||||||
REGISTER_INTERFACE_FUNC(mem_alloc);
|
REGISTER_INTERFACE_FUNC(mem_alloc);
|
||||||
REGISTER_INTERFACE_FUNC(mem_realloc);
|
REGISTER_INTERFACE_FUNC(mem_realloc);
|
||||||
REGISTER_INTERFACE_FUNC(mem_free);
|
REGISTER_INTERFACE_FUNC(mem_free);
|
||||||
#endif // DISABLE_DEPRECATED
|
|
||||||
REGISTER_INTERFACE_FUNC(mem_alloc2);
|
|
||||||
REGISTER_INTERFACE_FUNC(mem_realloc2);
|
|
||||||
REGISTER_INTERFACE_FUNC(mem_free2);
|
|
||||||
REGISTER_INTERFACE_FUNC(print_error);
|
REGISTER_INTERFACE_FUNC(print_error);
|
||||||
REGISTER_INTERFACE_FUNC(print_error_with_message);
|
REGISTER_INTERFACE_FUNC(print_error_with_message);
|
||||||
REGISTER_INTERFACE_FUNC(print_warning);
|
REGISTER_INTERFACE_FUNC(print_warning);
|
||||||
|
|
|
@ -858,7 +858,6 @@ typedef void (*GDExtensionInterfaceGetGodotVersion2)(GDExtensionGodotVersion2 *r
|
||||||
/**
|
/**
|
||||||
* @name mem_alloc
|
* @name mem_alloc
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
* @deprecated in Godot 4.6. Use `mem_alloc2` instead.
|
|
||||||
*
|
*
|
||||||
* Allocates memory.
|
* Allocates memory.
|
||||||
*
|
*
|
||||||
|
@ -871,7 +870,6 @@ typedef void *(*GDExtensionInterfaceMemAlloc)(size_t p_bytes);
|
||||||
/**
|
/**
|
||||||
* @name mem_realloc
|
* @name mem_realloc
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
* @deprecated in Godot 4.6. Use `mem_realloc2` instead.
|
|
||||||
*
|
*
|
||||||
* Reallocates memory.
|
* Reallocates memory.
|
||||||
*
|
*
|
||||||
|
@ -885,7 +883,6 @@ typedef void *(*GDExtensionInterfaceMemRealloc)(void *p_ptr, size_t p_bytes);
|
||||||
/**
|
/**
|
||||||
* @name mem_free
|
* @name mem_free
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
* @deprecated in Godot 4.6. Use `mem_free2` instead.
|
|
||||||
*
|
*
|
||||||
* Frees memory.
|
* Frees memory.
|
||||||
*
|
*
|
||||||
|
@ -893,45 +890,7 @@ typedef void *(*GDExtensionInterfaceMemRealloc)(void *p_ptr, size_t p_bytes);
|
||||||
*/
|
*/
|
||||||
typedef void (*GDExtensionInterfaceMemFree)(void *p_ptr);
|
typedef void (*GDExtensionInterfaceMemFree)(void *p_ptr);
|
||||||
|
|
||||||
/**
|
/* INTERFACE: Godot Core */
|
||||||
* @name mem_alloc2
|
|
||||||
* @since 4.6
|
|
||||||
*
|
|
||||||
* Allocates memory.
|
|
||||||
*
|
|
||||||
* @param p_bytes The amount of memory to allocate in bytes.
|
|
||||||
* @param p_pad_align If true, the returned memory will have prepadding of at least 8 bytes.
|
|
||||||
*
|
|
||||||
* @return A pointer to the allocated memory, or NULL if unsuccessful.
|
|
||||||
*/
|
|
||||||
typedef void *(*GDExtensionInterfaceMemAlloc2)(size_t p_bytes, GDExtensionBool p_pad_align);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @name mem_realloc2
|
|
||||||
* @since 4.6
|
|
||||||
*
|
|
||||||
* Reallocates memory.
|
|
||||||
*
|
|
||||||
* @param p_ptr A pointer to the previously allocated memory.
|
|
||||||
* @param p_bytes The number of bytes to resize the memory block to.
|
|
||||||
* @param p_pad_align If true, the returned memory will have prepadding of at least 8 bytes.
|
|
||||||
*
|
|
||||||
* @return A pointer to the allocated memory, or NULL if unsuccessful.
|
|
||||||
*/
|
|
||||||
typedef void *(*GDExtensionInterfaceMemRealloc2)(void *p_ptr, size_t p_bytes, GDExtensionBool p_pad_align);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @name mem_free2
|
|
||||||
* @since 4.6
|
|
||||||
*
|
|
||||||
* Frees memory.
|
|
||||||
*
|
|
||||||
* @param p_ptr A pointer to the previously allocated memory.
|
|
||||||
* @param p_pad_align If true, the given memory was allocated with prepadding.
|
|
||||||
*/
|
|
||||||
typedef void (*GDExtensionInterfaceMemFree2)(void *p_ptr, GDExtensionBool p_pad_align);
|
|
||||||
|
|
||||||
//* INTERFACE: Godot Core */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name print_error
|
* @name print_error
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
|
|
||||||
#include "gdextension_manager.h"
|
#include "gdextension_manager.h"
|
||||||
|
|
||||||
#include "core/extension/gdextension_function_loader.h"
|
|
||||||
#include "core/extension/gdextension_library_loader.h"
|
#include "core/extension/gdextension_library_loader.h"
|
||||||
#include "core/extension/gdextension_special_compat_hashes.h"
|
#include "core/extension/gdextension_special_compat_hashes.h"
|
||||||
#include "core/io/dir_access.h"
|
#include "core/io/dir_access.h"
|
||||||
|
@ -115,14 +114,7 @@ GDExtensionManager::LoadStatus GDExtensionManager::load_extension(const String &
|
||||||
|
|
||||||
Ref<GDExtensionLibraryLoader> loader;
|
Ref<GDExtensionLibraryLoader> loader;
|
||||||
loader.instantiate();
|
loader.instantiate();
|
||||||
return load_extension_with_loader(p_path, loader);
|
return GDExtensionManager::get_singleton()->load_extension_with_loader(p_path, loader);
|
||||||
}
|
|
||||||
|
|
||||||
GDExtensionManager::LoadStatus GDExtensionManager::load_extension_from_function(const String &p_path, GDExtensionConstPtr<const GDExtensionInitializationFunction> p_init_func) {
|
|
||||||
Ref<GDExtensionFunctionLoader> func_loader;
|
|
||||||
func_loader.instantiate();
|
|
||||||
func_loader->set_initialization_function((GDExtensionInitializationFunction)*p_init_func.data);
|
|
||||||
return load_extension_with_loader(p_path, func_loader);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GDExtensionManager::LoadStatus GDExtensionManager::load_extension_with_loader(const String &p_path, const Ref<GDExtensionLoader> &p_loader) {
|
GDExtensionManager::LoadStatus GDExtensionManager::load_extension_with_loader(const String &p_path, const Ref<GDExtensionLoader> &p_loader) {
|
||||||
|
@ -462,7 +454,6 @@ GDExtensionManager *GDExtensionManager::get_singleton() {
|
||||||
|
|
||||||
void GDExtensionManager::_bind_methods() {
|
void GDExtensionManager::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("load_extension", "path"), &GDExtensionManager::load_extension);
|
ClassDB::bind_method(D_METHOD("load_extension", "path"), &GDExtensionManager::load_extension);
|
||||||
ClassDB::bind_method(D_METHOD("load_extension_from_function", "path", "init_func"), &GDExtensionManager::load_extension_from_function);
|
|
||||||
ClassDB::bind_method(D_METHOD("reload_extension", "path"), &GDExtensionManager::reload_extension);
|
ClassDB::bind_method(D_METHOD("reload_extension", "path"), &GDExtensionManager::reload_extension);
|
||||||
ClassDB::bind_method(D_METHOD("unload_extension", "path"), &GDExtensionManager::unload_extension);
|
ClassDB::bind_method(D_METHOD("unload_extension", "path"), &GDExtensionManager::unload_extension);
|
||||||
ClassDB::bind_method(D_METHOD("is_extension_loaded", "path"), &GDExtensionManager::is_extension_loaded);
|
ClassDB::bind_method(D_METHOD("is_extension_loaded", "path"), &GDExtensionManager::is_extension_loaded);
|
||||||
|
|
|
@ -31,9 +31,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/extension/gdextension.h"
|
#include "core/extension/gdextension.h"
|
||||||
#include "core/variant/native_ptr.h"
|
|
||||||
|
|
||||||
GDVIRTUAL_NATIVE_PTR(GDExtensionInitializationFunction)
|
|
||||||
|
|
||||||
class GDExtensionManager : public Object {
|
class GDExtensionManager : public Object {
|
||||||
GDCLASS(GDExtensionManager, Object);
|
GDCLASS(GDExtensionManager, Object);
|
||||||
|
@ -69,7 +66,6 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LoadStatus load_extension(const String &p_path);
|
LoadStatus load_extension(const String &p_path);
|
||||||
LoadStatus load_extension_from_function(const String &p_path, GDExtensionConstPtr<const GDExtensionInitializationFunction> p_init_func);
|
|
||||||
LoadStatus load_extension_with_loader(const String &p_path, const Ref<GDExtensionLoader> &p_loader);
|
LoadStatus load_extension_with_loader(const String &p_path, const Ref<GDExtensionLoader> &p_loader);
|
||||||
LoadStatus reload_extension(const String &p_path);
|
LoadStatus reload_extension(const String &p_path);
|
||||||
LoadStatus unload_extension(const String &p_path);
|
LoadStatus unload_extension(const String &p_path);
|
||||||
|
|
|
@ -63,7 +63,7 @@ bool GDExtensionSpecialCompatHashes::get_legacy_hashes(const StringName &p_class
|
||||||
if (p_check_valid) {
|
if (p_check_valid) {
|
||||||
MethodBind *mb = ClassDB::get_method_with_compatibility(p_class, p_method, mapping.current_hash);
|
MethodBind *mb = ClassDB::get_method_with_compatibility(p_class, p_method, mapping.current_hash);
|
||||||
if (!mb) {
|
if (!mb) {
|
||||||
WARN_PRINT(vformat("Compatibility hash %d for %s::%s() mapped to non-existent hash %d in gdextension_special_compat_hashes.cpp.", mapping.legacy_hash, p_class, p_method, mapping.current_hash));
|
WARN_PRINT(vformat("Compatibility hash %d for %s::%s() mapped to non-existent hash %d. Please update gdextension_special_compat_hashes.cpp.", mapping.legacy_hash, p_class, p_method, mapping.current_hash));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,6 @@
|
||||||
#include "core/templates/hash_map.h"
|
#include "core/templates/hash_map.h"
|
||||||
#include "core/templates/local_vector.h"
|
#include "core/templates/local_vector.h"
|
||||||
|
|
||||||
class Array;
|
|
||||||
|
|
||||||
// Note: In most situations, compatibility methods should be registered via ClassDB::bind_compatibility_method().
|
// Note: In most situations, compatibility methods should be registered via ClassDB::bind_compatibility_method().
|
||||||
// This class is only meant to be used in exceptional circumstances, for example, when Godot's hashing
|
// This class is only meant to be used in exceptional circumstances, for example, when Godot's hashing
|
||||||
// algorithm changes and registering compatibility methods for all affect methods would be onerous.
|
// algorithm changes and registering compatibility methods for all affect methods would be onerous.
|
||||||
|
|
|
@ -1,126 +0,0 @@
|
||||||
/**************************************************************************/
|
|
||||||
/* godot_instance.cpp */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
|
||||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
#include "godot_instance.h"
|
|
||||||
|
|
||||||
#include "core/extension/gdextension_manager.h"
|
|
||||||
#include "core/os/main_loop.h"
|
|
||||||
#include "main/main.h"
|
|
||||||
#include "servers/display/display_server.h"
|
|
||||||
|
|
||||||
void GodotInstance::_bind_methods() {
|
|
||||||
ClassDB::bind_method(D_METHOD("start"), &GodotInstance::start);
|
|
||||||
ClassDB::bind_method(D_METHOD("is_started"), &GodotInstance::is_started);
|
|
||||||
ClassDB::bind_method(D_METHOD("iteration"), &GodotInstance::iteration);
|
|
||||||
ClassDB::bind_method(D_METHOD("focus_in"), &GodotInstance::focus_in);
|
|
||||||
ClassDB::bind_method(D_METHOD("focus_out"), &GodotInstance::focus_out);
|
|
||||||
ClassDB::bind_method(D_METHOD("pause"), &GodotInstance::pause);
|
|
||||||
ClassDB::bind_method(D_METHOD("resume"), &GodotInstance::resume);
|
|
||||||
}
|
|
||||||
|
|
||||||
GodotInstance::GodotInstance() {
|
|
||||||
}
|
|
||||||
|
|
||||||
GodotInstance::~GodotInstance() {
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GodotInstance::initialize(GDExtensionInitializationFunction p_init_func) {
|
|
||||||
print_verbose("Godot Instance initialization");
|
|
||||||
GDExtensionManager *gdextension_manager = GDExtensionManager::get_singleton();
|
|
||||||
GDExtensionConstPtr<const GDExtensionInitializationFunction> ptr((const GDExtensionInitializationFunction *)&p_init_func);
|
|
||||||
GDExtensionManager::LoadStatus status = gdextension_manager->load_extension_from_function("libgodot://main", ptr);
|
|
||||||
return status == GDExtensionManager::LoadStatus::LOAD_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GodotInstance::start() {
|
|
||||||
print_verbose("GodotInstance::start()");
|
|
||||||
Error err = Main::setup2();
|
|
||||||
if (err != OK) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
started = Main::start() == EXIT_SUCCESS;
|
|
||||||
if (started) {
|
|
||||||
OS::get_singleton()->get_main_loop()->initialize();
|
|
||||||
}
|
|
||||||
return started;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GodotInstance::is_started() {
|
|
||||||
return started;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GodotInstance::iteration() {
|
|
||||||
DisplayServer::get_singleton()->process_events();
|
|
||||||
return Main::iteration();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GodotInstance::stop() {
|
|
||||||
print_verbose("GodotInstance::stop()");
|
|
||||||
if (started) {
|
|
||||||
OS::get_singleton()->get_main_loop()->finalize();
|
|
||||||
}
|
|
||||||
started = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GodotInstance::focus_out() {
|
|
||||||
print_verbose("GodotInstance::focus_out()");
|
|
||||||
if (started) {
|
|
||||||
if (OS::get_singleton()->get_main_loop()) {
|
|
||||||
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GodotInstance::focus_in() {
|
|
||||||
print_verbose("GodotInstance::focus_in()");
|
|
||||||
if (started) {
|
|
||||||
if (OS::get_singleton()->get_main_loop()) {
|
|
||||||
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GodotInstance::pause() {
|
|
||||||
print_verbose("GodotInstance::pause()");
|
|
||||||
if (started) {
|
|
||||||
if (OS::get_singleton()->get_main_loop()) {
|
|
||||||
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_PAUSED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GodotInstance::resume() {
|
|
||||||
print_verbose("GodotInstance::resume()");
|
|
||||||
if (started) {
|
|
||||||
if (OS::get_singleton()->get_main_loop()) {
|
|
||||||
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_RESUMED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
/**************************************************************************/
|
|
||||||
/* godot_instance.h */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
|
||||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/extension/gdextension_interface.h"
|
|
||||||
#include "core/object/class_db.h"
|
|
||||||
|
|
||||||
class GodotInstance : public Object {
|
|
||||||
GDCLASS(GodotInstance, Object);
|
|
||||||
|
|
||||||
bool started = false;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static void _bind_methods();
|
|
||||||
|
|
||||||
public:
|
|
||||||
GodotInstance();
|
|
||||||
~GodotInstance();
|
|
||||||
|
|
||||||
bool initialize(GDExtensionInitializationFunction p_init_func);
|
|
||||||
|
|
||||||
bool start();
|
|
||||||
bool is_started();
|
|
||||||
bool iteration();
|
|
||||||
void stop();
|
|
||||||
|
|
||||||
void focus_out();
|
|
||||||
void focus_in();
|
|
||||||
void pause();
|
|
||||||
void resume();
|
|
||||||
};
|
|
|
@ -1,73 +0,0 @@
|
||||||
/**************************************************************************/
|
|
||||||
/* libgodot.h */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
|
||||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "gdextension_interface.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Export macros for DLL visibility
|
|
||||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
|
||||||
#define LIBGODOT_API __declspec(dllexport)
|
|
||||||
#elif defined(__GNUC__) || defined(__clang__)
|
|
||||||
#define LIBGODOT_API __attribute__((visibility("default")))
|
|
||||||
#endif // if defined(_MSC_VER)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @name libgodot_create_godot_instance
|
|
||||||
* @since 4.6
|
|
||||||
*
|
|
||||||
* Creates a new Godot instance.
|
|
||||||
*
|
|
||||||
* @param p_argc The number of command line arguments.
|
|
||||||
* @param p_argv The C-style array of command line arguments.
|
|
||||||
* @param p_init_func GDExtension initialization function of the host application.
|
|
||||||
*
|
|
||||||
* @return A pointer to created \ref GodotInstance GDExtension object or nullptr if there was an error.
|
|
||||||
*/
|
|
||||||
LIBGODOT_API GDExtensionObjectPtr libgodot_create_godot_instance(int p_argc, char *p_argv[], GDExtensionInitializationFunction p_init_func);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @name libgodot_destroy_godot_instance
|
|
||||||
* @since 4.6
|
|
||||||
*
|
|
||||||
* Destroys an existing Godot instance.
|
|
||||||
*
|
|
||||||
* @param p_godot_instance The reference to the GodotInstance object to destroy.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
LIBGODOT_API void libgodot_destroy_godot_instance(GDExtensionObjectPtr p_godot_instance);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1756,7 +1756,8 @@ void Input::parse_mapping(const String &p_mapping) {
|
||||||
void Input::add_joy_mapping(const String &p_mapping, bool p_update_existing) {
|
void Input::add_joy_mapping(const String &p_mapping, bool p_update_existing) {
|
||||||
parse_mapping(p_mapping);
|
parse_mapping(p_mapping);
|
||||||
if (p_update_existing) {
|
if (p_update_existing) {
|
||||||
const String uid = p_mapping.get_slicec(',', 0);
|
Vector<String> entry = p_mapping.split(",");
|
||||||
|
const String &uid = entry[0];
|
||||||
for (KeyValue<int, Joypad> &E : joy_names) {
|
for (KeyValue<int, Joypad> &E : joy_names) {
|
||||||
Joypad &joy = E.value;
|
Joypad &joy = E.value;
|
||||||
if (joy.uid == uid) {
|
if (joy.uid == uid) {
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
#include "core/object/object.h"
|
#include "core/object/object.h"
|
||||||
#include "core/os/keyboard.h"
|
#include "core/os/keyboard.h"
|
||||||
#include "core/os/thread_safe.h"
|
#include "core/os/thread_safe.h"
|
||||||
#include "core/templates/rb_map.h"
|
|
||||||
#include "core/templates/rb_set.h"
|
#include "core/templates/rb_set.h"
|
||||||
#include "core/variant/typed_array.h"
|
#include "core/variant/typed_array.h"
|
||||||
|
|
||||||
|
|
|
@ -260,12 +260,12 @@ String InputEventWithModifiers::as_text() const {
|
||||||
if (is_ctrl_pressed()) {
|
if (is_ctrl_pressed()) {
|
||||||
mod_names.push_back(find_keycode_name(Key::CTRL));
|
mod_names.push_back(find_keycode_name(Key::CTRL));
|
||||||
}
|
}
|
||||||
if (is_alt_pressed()) {
|
|
||||||
mod_names.push_back(find_keycode_name(Key::ALT));
|
|
||||||
}
|
|
||||||
if (is_shift_pressed()) {
|
if (is_shift_pressed()) {
|
||||||
mod_names.push_back(find_keycode_name(Key::SHIFT));
|
mod_names.push_back(find_keycode_name(Key::SHIFT));
|
||||||
}
|
}
|
||||||
|
if (is_alt_pressed()) {
|
||||||
|
mod_names.push_back(find_keycode_name(Key::ALT));
|
||||||
|
}
|
||||||
if (is_meta_pressed()) {
|
if (is_meta_pressed()) {
|
||||||
mod_names.push_back(find_keycode_name(Key::META));
|
mod_names.push_back(find_keycode_name(Key::META));
|
||||||
}
|
}
|
||||||
|
@ -277,7 +277,7 @@ String InputEventWithModifiers::as_text() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventWithModifiers::_to_string() {
|
String InputEventWithModifiers::to_string() {
|
||||||
return as_text();
|
return as_text();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,7 +488,7 @@ String InputEventKey::as_text() const {
|
||||||
return mods_text.is_empty() ? kc : mods_text + "+" + kc;
|
return mods_text.is_empty() ? kc : mods_text + "+" + kc;
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventKey::_to_string() {
|
String InputEventKey::to_string() {
|
||||||
String p = is_pressed() ? "true" : "false";
|
String p = is_pressed() ? "true" : "false";
|
||||||
String e = is_echo() ? "true" : "false";
|
String e = is_echo() ? "true" : "false";
|
||||||
|
|
||||||
|
@ -848,7 +848,7 @@ String InputEventMouseButton::as_text() const {
|
||||||
return full_string;
|
return full_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventMouseButton::_to_string() {
|
String InputEventMouseButton::to_string() {
|
||||||
String p = is_pressed() ? "true" : "false";
|
String p = is_pressed() ? "true" : "false";
|
||||||
String canceled_state = is_canceled() ? "true" : "false";
|
String canceled_state = is_canceled() ? "true" : "false";
|
||||||
String d = double_click ? "true" : "false";
|
String d = double_click ? "true" : "false";
|
||||||
|
@ -988,7 +988,7 @@ String InputEventMouseMotion::as_text() const {
|
||||||
return vformat(RTR("Mouse motion at position (%s) with velocity (%s)"), String(get_position()), String(get_velocity()));
|
return vformat(RTR("Mouse motion at position (%s) with velocity (%s)"), String(get_position()), String(get_velocity()));
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventMouseMotion::_to_string() {
|
String InputEventMouseMotion::to_string() {
|
||||||
BitField<MouseButtonMask> mouse_button_mask = get_button_mask();
|
BitField<MouseButtonMask> mouse_button_mask = get_button_mask();
|
||||||
String button_mask_string = itos((int64_t)mouse_button_mask);
|
String button_mask_string = itos((int64_t)mouse_button_mask);
|
||||||
|
|
||||||
|
@ -1184,16 +1184,15 @@ String InputEventJoypadMotion::as_text() const {
|
||||||
return vformat(RTR("Joypad Motion on Axis %d (%s) with Value %.2f"), axis, desc, axis_value);
|
return vformat(RTR("Joypad Motion on Axis %d (%s) with Value %.2f"), axis, desc, axis_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventJoypadMotion::_to_string() {
|
String InputEventJoypadMotion::to_string() {
|
||||||
return vformat("InputEventJoypadMotion: axis=%d, axis_value=%.2f", axis, axis_value);
|
return vformat("InputEventJoypadMotion: axis=%d, axis_value=%.2f", axis, axis_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<InputEventJoypadMotion> InputEventJoypadMotion::create_reference(JoyAxis p_axis, float p_value, int p_device) {
|
Ref<InputEventJoypadMotion> InputEventJoypadMotion::create_reference(JoyAxis p_axis, float p_value) {
|
||||||
Ref<InputEventJoypadMotion> ie;
|
Ref<InputEventJoypadMotion> ie;
|
||||||
ie.instantiate();
|
ie.instantiate();
|
||||||
ie->set_axis(p_axis);
|
ie->set_axis(p_axis);
|
||||||
ie->set_axis_value(p_value);
|
ie->set_axis_value(p_value);
|
||||||
ie->set_device(p_device);
|
|
||||||
|
|
||||||
return ie;
|
return ie;
|
||||||
}
|
}
|
||||||
|
@ -1303,16 +1302,15 @@ String InputEventJoypadButton::as_text() const {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventJoypadButton::_to_string() {
|
String InputEventJoypadButton::to_string() {
|
||||||
String p = is_pressed() ? "true" : "false";
|
String p = is_pressed() ? "true" : "false";
|
||||||
return vformat("InputEventJoypadButton: button_index=%d, pressed=%s, pressure=%.2f", button_index, p, pressure);
|
return vformat("InputEventJoypadButton: button_index=%d, pressed=%s, pressure=%.2f", button_index, p, pressure);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<InputEventJoypadButton> InputEventJoypadButton::create_reference(JoyButton p_btn_index, int p_device) {
|
Ref<InputEventJoypadButton> InputEventJoypadButton::create_reference(JoyButton p_btn_index) {
|
||||||
Ref<InputEventJoypadButton> ie;
|
Ref<InputEventJoypadButton> ie;
|
||||||
ie.instantiate();
|
ie.instantiate();
|
||||||
ie->set_button_index(p_btn_index);
|
ie->set_button_index(p_btn_index);
|
||||||
ie->set_device(p_device);
|
|
||||||
|
|
||||||
return ie;
|
return ie;
|
||||||
}
|
}
|
||||||
|
@ -1386,7 +1384,7 @@ String InputEventScreenTouch::as_text() const {
|
||||||
return vformat(RTR("Screen %s at (%s) with %s touch points"), status, String(get_position()), itos(index));
|
return vformat(RTR("Screen %s at (%s) with %s touch points"), status, String(get_position()), itos(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventScreenTouch::_to_string() {
|
String InputEventScreenTouch::to_string() {
|
||||||
String p = pressed ? "true" : "false";
|
String p = pressed ? "true" : "false";
|
||||||
String canceled_state = canceled ? "true" : "false";
|
String canceled_state = canceled ? "true" : "false";
|
||||||
String double_tap_string = double_tap ? "true" : "false";
|
String double_tap_string = double_tap ? "true" : "false";
|
||||||
|
@ -1514,7 +1512,7 @@ String InputEventScreenDrag::as_text() const {
|
||||||
return vformat(RTR("Screen dragged with %s touch points at position (%s) with velocity of (%s)"), itos(index), String(get_position()), String(get_velocity()));
|
return vformat(RTR("Screen dragged with %s touch points at position (%s) with velocity of (%s)"), itos(index), String(get_position()), String(get_velocity()));
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventScreenDrag::_to_string() {
|
String InputEventScreenDrag::to_string() {
|
||||||
return vformat("InputEventScreenDrag: index=%d, position=(%s), relative=(%s), velocity=(%s), pressure=%.2f, tilt=(%s), pen_inverted=(%s)", index, String(get_position()), String(get_relative()), String(get_velocity()), get_pressure(), String(get_tilt()), get_pen_inverted());
|
return vformat("InputEventScreenDrag: index=%d, position=(%s), relative=(%s), velocity=(%s), pressure=%.2f, tilt=(%s), pen_inverted=(%s)", index, String(get_position()), String(get_relative()), String(get_velocity()), get_pressure(), String(get_tilt()), get_pen_inverted());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1656,7 +1654,7 @@ String InputEventAction::as_text() const {
|
||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventAction::_to_string() {
|
String InputEventAction::to_string() {
|
||||||
String p = is_pressed() ? "true" : "false";
|
String p = is_pressed() ? "true" : "false";
|
||||||
return vformat("InputEventAction: action=\"%s\", pressed=%s", action, p);
|
return vformat("InputEventAction: action=\"%s\", pressed=%s", action, p);
|
||||||
}
|
}
|
||||||
|
@ -1727,7 +1725,7 @@ String InputEventMagnifyGesture::as_text() const {
|
||||||
return vformat(RTR("Magnify Gesture at (%s) with factor %s"), String(get_position()), rtos(get_factor()));
|
return vformat(RTR("Magnify Gesture at (%s) with factor %s"), String(get_position()), rtos(get_factor()));
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventMagnifyGesture::_to_string() {
|
String InputEventMagnifyGesture::to_string() {
|
||||||
return vformat("InputEventMagnifyGesture: factor=%.2f, position=(%s)", factor, String(get_position()));
|
return vformat("InputEventMagnifyGesture: factor=%.2f, position=(%s)", factor, String(get_position()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1769,7 +1767,7 @@ String InputEventPanGesture::as_text() const {
|
||||||
return vformat(RTR("Pan Gesture at (%s) with delta (%s)"), String(get_position()), String(get_delta()));
|
return vformat(RTR("Pan Gesture at (%s) with delta (%s)"), String(get_position()), String(get_delta()));
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventPanGesture::_to_string() {
|
String InputEventPanGesture::to_string() {
|
||||||
return vformat("InputEventPanGesture: delta=(%s), position=(%s)", String(get_delta()), String(get_position()));
|
return vformat("InputEventPanGesture: delta=(%s), position=(%s)", String(get_delta()), String(get_position()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1850,7 +1848,7 @@ String InputEventMIDI::as_text() const {
|
||||||
return vformat(RTR("MIDI Input on Channel=%s Message=%s"), itos(channel), itos((int64_t)message));
|
return vformat(RTR("MIDI Input on Channel=%s Message=%s"), itos(channel), itos((int64_t)message));
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventMIDI::_to_string() {
|
String InputEventMIDI::to_string() {
|
||||||
String ret;
|
String ret;
|
||||||
switch (message) {
|
switch (message) {
|
||||||
case MIDIMessage::NOTE_ON:
|
case MIDIMessage::NOTE_ON:
|
||||||
|
@ -1926,7 +1924,7 @@ String InputEventShortcut::as_text() const {
|
||||||
return vformat(RTR("Input Event with Shortcut=%s"), shortcut->get_as_text());
|
return vformat(RTR("Input Event with Shortcut=%s"), shortcut->get_as_text());
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventShortcut::_to_string() {
|
String InputEventShortcut::to_string() {
|
||||||
ERR_FAIL_COND_V(shortcut.is_null(), "None");
|
ERR_FAIL_COND_V(shortcut.is_null(), "None");
|
||||||
|
|
||||||
return vformat("InputEventShortcut: shortcut=%s", shortcut->get_as_text());
|
return vformat("InputEventShortcut: shortcut=%s", shortcut->get_as_text());
|
||||||
|
|
|
@ -146,7 +146,7 @@ public:
|
||||||
BitField<KeyModifierMask> get_modifiers_mask() const;
|
BitField<KeyModifierMask> get_modifiers_mask() const;
|
||||||
|
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String _to_string() override;
|
virtual String to_string() override;
|
||||||
|
|
||||||
InputEventWithModifiers() {}
|
InputEventWithModifiers() {}
|
||||||
};
|
};
|
||||||
|
@ -200,7 +200,7 @@ public:
|
||||||
virtual String as_text_key_label() const;
|
virtual String as_text_key_label() const;
|
||||||
virtual String as_text_location() const;
|
virtual String as_text_location() const;
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String _to_string() override;
|
virtual String to_string() override;
|
||||||
|
|
||||||
static Ref<InputEventKey> create_reference(Key p_keycode_with_modifier_masks, bool p_physical = false);
|
static Ref<InputEventKey> create_reference(Key p_keycode_with_modifier_masks, bool p_physical = false);
|
||||||
|
|
||||||
|
@ -263,7 +263,7 @@ public:
|
||||||
|
|
||||||
virtual bool is_action_type() const override { return true; }
|
virtual bool is_action_type() const override { return true; }
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String _to_string() override;
|
virtual String to_string() override;
|
||||||
|
|
||||||
InputEventType get_type() const final override { return InputEventType::MOUSE_BUTTON; }
|
InputEventType get_type() const final override { return InputEventType::MOUSE_BUTTON; }
|
||||||
|
|
||||||
|
@ -308,7 +308,7 @@ public:
|
||||||
|
|
||||||
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
|
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String _to_string() override;
|
virtual String to_string() override;
|
||||||
|
|
||||||
virtual bool accumulate(const Ref<InputEvent> &p_event) override;
|
virtual bool accumulate(const Ref<InputEvent> &p_event) override;
|
||||||
|
|
||||||
|
@ -337,10 +337,9 @@ public:
|
||||||
|
|
||||||
virtual bool is_action_type() const override { return true; }
|
virtual bool is_action_type() const override { return true; }
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String _to_string() override;
|
virtual String to_string() override;
|
||||||
|
|
||||||
// The default device ID is `InputMap::ALL_DEVICES`.
|
static Ref<InputEventJoypadMotion> create_reference(JoyAxis p_axis, float p_value);
|
||||||
static Ref<InputEventJoypadMotion> create_reference(JoyAxis p_axis, float p_value, int p_device = -1);
|
|
||||||
|
|
||||||
InputEventType get_type() const final override { return InputEventType::JOY_MOTION; }
|
InputEventType get_type() const final override { return InputEventType::JOY_MOTION; }
|
||||||
|
|
||||||
|
@ -370,10 +369,9 @@ public:
|
||||||
virtual bool is_action_type() const override { return true; }
|
virtual bool is_action_type() const override { return true; }
|
||||||
|
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String _to_string() override;
|
virtual String to_string() override;
|
||||||
|
|
||||||
// The default device ID is `InputMap::ALL_DEVICES`.
|
static Ref<InputEventJoypadButton> create_reference(JoyButton p_btn_index);
|
||||||
static Ref<InputEventJoypadButton> create_reference(JoyButton p_btn_index, int p_device = -1);
|
|
||||||
|
|
||||||
InputEventType get_type() const final override { return InputEventType::JOY_BUTTON; }
|
InputEventType get_type() const final override { return InputEventType::JOY_BUTTON; }
|
||||||
|
|
||||||
|
@ -404,7 +402,7 @@ public:
|
||||||
|
|
||||||
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
|
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String _to_string() override;
|
virtual String to_string() override;
|
||||||
|
|
||||||
InputEventType get_type() const final override { return InputEventType::SCREEN_TOUCH; }
|
InputEventType get_type() const final override { return InputEventType::SCREEN_TOUCH; }
|
||||||
|
|
||||||
|
@ -456,7 +454,7 @@ public:
|
||||||
|
|
||||||
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
|
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String _to_string() override;
|
virtual String to_string() override;
|
||||||
|
|
||||||
virtual bool accumulate(const Ref<InputEvent> &p_event) override;
|
virtual bool accumulate(const Ref<InputEvent> &p_event) override;
|
||||||
|
|
||||||
|
@ -495,7 +493,7 @@ public:
|
||||||
virtual bool is_action_type() const override { return true; }
|
virtual bool is_action_type() const override { return true; }
|
||||||
|
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String _to_string() override;
|
virtual String to_string() override;
|
||||||
|
|
||||||
InputEventType get_type() const final override { return InputEventType::ACTION; }
|
InputEventType get_type() const final override { return InputEventType::ACTION; }
|
||||||
|
|
||||||
|
@ -528,7 +526,7 @@ public:
|
||||||
|
|
||||||
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
|
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String _to_string() override;
|
virtual String to_string() override;
|
||||||
|
|
||||||
InputEventType get_type() const final override { return InputEventType::MAGNIFY_GESTURE; }
|
InputEventType get_type() const final override { return InputEventType::MAGNIFY_GESTURE; }
|
||||||
|
|
||||||
|
@ -548,7 +546,7 @@ public:
|
||||||
|
|
||||||
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
|
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String _to_string() override;
|
virtual String to_string() override;
|
||||||
|
|
||||||
InputEventType get_type() const final override { return InputEventType::PAN_GESTURE; }
|
InputEventType get_type() const final override { return InputEventType::PAN_GESTURE; }
|
||||||
|
|
||||||
|
@ -596,7 +594,7 @@ public:
|
||||||
int get_controller_value() const;
|
int get_controller_value() const;
|
||||||
|
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String _to_string() override;
|
virtual String to_string() override;
|
||||||
|
|
||||||
InputEventType get_type() const final override { return InputEventType::MIDI; }
|
InputEventType get_type() const final override { return InputEventType::MIDI; }
|
||||||
|
|
||||||
|
@ -616,7 +614,7 @@ public:
|
||||||
Ref<Shortcut> get_shortcut();
|
Ref<Shortcut> get_shortcut();
|
||||||
|
|
||||||
virtual String as_text() const override;
|
virtual String as_text() const override;
|
||||||
virtual String _to_string() override;
|
virtual String to_string() override;
|
||||||
|
|
||||||
InputEventType get_type() const final override { return InputEventType::SHORTCUT; }
|
InputEventType get_type() const final override { return InputEventType::SHORTCUT; }
|
||||||
|
|
||||||
|
|
|
@ -403,12 +403,9 @@ static const _BuiltinActionDisplayName _builtin_action_display_names[] = {
|
||||||
{ "ui_graph_delete", TTRC("Delete Nodes") },
|
{ "ui_graph_delete", TTRC("Delete Nodes") },
|
||||||
{ "ui_graph_follow_left", TTRC("Follow Input Port Connection") },
|
{ "ui_graph_follow_left", TTRC("Follow Input Port Connection") },
|
||||||
{ "ui_graph_follow_right", TTRC("Follow Output Port Connection") },
|
{ "ui_graph_follow_right", TTRC("Follow Output Port Connection") },
|
||||||
{ "ui_filedialog_delete", TTRC("Delete") },
|
|
||||||
{ "ui_filedialog_up_one_level", TTRC("Go Up One Level") },
|
{ "ui_filedialog_up_one_level", TTRC("Go Up One Level") },
|
||||||
{ "ui_filedialog_refresh", TTRC("Refresh") },
|
{ "ui_filedialog_refresh", TTRC("Refresh") },
|
||||||
{ "ui_filedialog_show_hidden", TTRC("Show Hidden") },
|
{ "ui_filedialog_show_hidden", TTRC("Show Hidden") },
|
||||||
{ "ui_filedialog_find", TTRC("Find") },
|
|
||||||
{ "ui_filedialog_focus_path", TTRC("Focus Path") },
|
|
||||||
{ "ui_swap_input_direction ", TTRC("Swap Input Direction") },
|
{ "ui_swap_input_direction ", TTRC("Swap Input Direction") },
|
||||||
{ "ui_unicode_start", TTRC("Start Unicode Character Input") },
|
{ "ui_unicode_start", TTRC("Start Unicode Character Input") },
|
||||||
{ "ui_colorpicker_delete_preset", TTRC("ColorPicker: Delete Preset") },
|
{ "ui_colorpicker_delete_preset", TTRC("ColorPicker: Delete Preset") },
|
||||||
|
@ -418,7 +415,7 @@ static const _BuiltinActionDisplayName _builtin_action_display_names[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
String InputMap::get_builtin_display_name(const String &p_name) const {
|
String InputMap::get_builtin_display_name(const String &p_name) const {
|
||||||
constexpr int len = std_size(_builtin_action_display_names);
|
constexpr int len = std::size(_builtin_action_display_names);
|
||||||
|
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
if (_builtin_action_display_names[i].name == p_name) {
|
if (_builtin_action_display_names[i].name == p_name) {
|
||||||
|
@ -807,10 +804,6 @@ const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
|
||||||
default_builtin_cache.insert("ui_graph_follow_right.macos", inputs);
|
default_builtin_cache.insert("ui_graph_follow_right.macos", inputs);
|
||||||
|
|
||||||
// ///// UI File Dialog Shortcuts /////
|
// ///// UI File Dialog Shortcuts /////
|
||||||
inputs = List<Ref<InputEvent>>();
|
|
||||||
inputs.push_back(InputEventKey::create_reference(Key::KEY_DELETE));
|
|
||||||
default_builtin_cache.insert("ui_filedialog_delete", inputs);
|
|
||||||
|
|
||||||
inputs = List<Ref<InputEvent>>();
|
inputs = List<Ref<InputEvent>>();
|
||||||
inputs.push_back(InputEventKey::create_reference(Key::BACKSPACE));
|
inputs.push_back(InputEventKey::create_reference(Key::BACKSPACE));
|
||||||
default_builtin_cache.insert("ui_filedialog_up_one_level", inputs);
|
default_builtin_cache.insert("ui_filedialog_up_one_level", inputs);
|
||||||
|
@ -823,22 +816,6 @@ const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
|
||||||
inputs.push_back(InputEventKey::create_reference(Key::H));
|
inputs.push_back(InputEventKey::create_reference(Key::H));
|
||||||
default_builtin_cache.insert("ui_filedialog_show_hidden", inputs);
|
default_builtin_cache.insert("ui_filedialog_show_hidden", inputs);
|
||||||
|
|
||||||
inputs = List<Ref<InputEvent>>();
|
|
||||||
inputs.push_back(InputEventKey::create_reference(Key::F | KeyModifierMask::CMD_OR_CTRL));
|
|
||||||
default_builtin_cache.insert("ui_filedialog_find", inputs);
|
|
||||||
|
|
||||||
inputs = List<Ref<InputEvent>>();
|
|
||||||
// Ctrl + L (matches most Windows/Linux file managers' "focus on path bar" shortcut,
|
|
||||||
// plus macOS Safari's "focus on address bar" shortcut).
|
|
||||||
inputs.push_back(InputEventKey::create_reference(Key::L | KeyModifierMask::CMD_OR_CTRL));
|
|
||||||
default_builtin_cache.insert("ui_filedialog_focus_path", inputs);
|
|
||||||
|
|
||||||
inputs = List<Ref<InputEvent>>();
|
|
||||||
// Cmd + Shift + G (matches Finder's "Go To" shortcut).
|
|
||||||
inputs.push_back(InputEventKey::create_reference(Key::G | KeyModifierMask::CMD_OR_CTRL));
|
|
||||||
inputs.push_back(InputEventKey::create_reference(Key::L | KeyModifierMask::CMD_OR_CTRL));
|
|
||||||
default_builtin_cache.insert("ui_filedialog_focus_path.macos", inputs);
|
|
||||||
|
|
||||||
inputs = List<Ref<InputEvent>>();
|
inputs = List<Ref<InputEvent>>();
|
||||||
inputs.push_back(InputEventKey::create_reference(Key::QUOTELEFT | KeyModifierMask::CMD_OR_CTRL));
|
inputs.push_back(InputEventKey::create_reference(Key::QUOTELEFT | KeyModifierMask::CMD_OR_CTRL));
|
||||||
default_builtin_cache.insert("ui_swap_input_direction", inputs);
|
default_builtin_cache.insert("ui_swap_input_direction", inputs);
|
||||||
|
@ -866,8 +843,9 @@ const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins_with_featur
|
||||||
for (const KeyValue<String, List<Ref<InputEvent>>> &E : builtins) {
|
for (const KeyValue<String, List<Ref<InputEvent>>> &E : builtins) {
|
||||||
String fullname = E.key;
|
String fullname = E.key;
|
||||||
|
|
||||||
const String &name = fullname.get_slicec('.', 0);
|
Vector<String> split = fullname.split(".");
|
||||||
String override_for = fullname.get_slice_count(".") > 1 ? fullname.get_slicec('.', 1) : String();
|
const String &name = split[0];
|
||||||
|
String override_for = split.size() > 1 ? split[1] : String();
|
||||||
|
|
||||||
if (!override_for.is_empty() && OS::get_singleton()->has_feature(override_for)) {
|
if (!override_for.is_empty() && OS::get_singleton()->has_feature(override_for)) {
|
||||||
builtins_with_overrides[name].push_back(override_for);
|
builtins_with_overrides[name].push_back(override_for);
|
||||||
|
@ -877,8 +855,9 @@ const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins_with_featur
|
||||||
for (const KeyValue<String, List<Ref<InputEvent>>> &E : builtins) {
|
for (const KeyValue<String, List<Ref<InputEvent>>> &E : builtins) {
|
||||||
String fullname = E.key;
|
String fullname = E.key;
|
||||||
|
|
||||||
const String &name = fullname.get_slicec('.', 0);
|
Vector<String> split = fullname.split(".");
|
||||||
String override_for = fullname.get_slice_count(".") > 1 ? fullname.get_slicec('.', 1) : String();
|
const String &name = split[0];
|
||||||
|
String override_for = split.size() > 1 ? split[1] : String();
|
||||||
|
|
||||||
if (builtins_with_overrides.has(name) && override_for.is_empty()) {
|
if (builtins_with_overrides.has(name) && override_for.is_empty()) {
|
||||||
// Builtin has an override but this particular one is not an override, so skip.
|
// Builtin has an override but this particular one is not an override, so skip.
|
||||||
|
|
|
@ -85,17 +85,6 @@ String Shortcut::get_as_text() const {
|
||||||
return "None";
|
return "None";
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<Shortcut> Shortcut::make_from_action(const StringName &p_action) {
|
|
||||||
Ref<InputEventAction> event;
|
|
||||||
event.instantiate();
|
|
||||||
event->set_action(p_action);
|
|
||||||
|
|
||||||
Ref<Shortcut> shortcut;
|
|
||||||
shortcut.instantiate();
|
|
||||||
shortcut->set_events({ event });
|
|
||||||
return shortcut;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Shortcut::has_valid_event() const {
|
bool Shortcut::has_valid_event() const {
|
||||||
// Tests if there is ANY input event which is valid.
|
// Tests if there is ANY input event which is valid.
|
||||||
for (int i = 0; i < events.size(); i++) {
|
for (int i = 0; i < events.size(); i++) {
|
||||||
|
|
|
@ -52,7 +52,5 @@ public:
|
||||||
|
|
||||||
String get_as_text() const;
|
String get_as_text() const;
|
||||||
|
|
||||||
static Ref<Shortcut> make_from_action(const StringName &p_action);
|
|
||||||
|
|
||||||
static bool is_event_array_equal(const Array &p_event_array1, const Array &p_event_array2);
|
static bool is_event_array_equal(const Array &p_event_array1, const Array &p_event_array2);
|
||||||
};
|
};
|
||||||
|
|
|
@ -90,14 +90,6 @@ void FileAccess::store_pascal_string_bind_compat_78289(const String &p_string) {
|
||||||
store_pascal_string(p_string);
|
store_pascal_string(p_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
String FileAccess::get_as_text_bind_compat_110867(bool p_skip_cr) const {
|
|
||||||
String text = get_as_text();
|
|
||||||
if (unlikely(p_skip_cr)) {
|
|
||||||
text = text.remove_char('\r');
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileAccess::_bind_compatibility_methods() {
|
void FileAccess::_bind_compatibility_methods() {
|
||||||
ClassDB::bind_compatibility_static_method("FileAccess", D_METHOD("open_encrypted", "path", "mode_flags", "key"), &FileAccess::_open_encrypted_bind_compat_98918);
|
ClassDB::bind_compatibility_static_method("FileAccess", D_METHOD("open_encrypted", "path", "mode_flags", "key"), &FileAccess::_open_encrypted_bind_compat_98918);
|
||||||
|
|
||||||
|
@ -115,7 +107,6 @@ void FileAccess::_bind_compatibility_methods() {
|
||||||
ClassDB::bind_compatibility_method(D_METHOD("store_string", "string"), &FileAccess::store_string_bind_compat_78289);
|
ClassDB::bind_compatibility_method(D_METHOD("store_string", "string"), &FileAccess::store_string_bind_compat_78289);
|
||||||
ClassDB::bind_compatibility_method(D_METHOD("store_var", "value", "full_objects"), &FileAccess::store_var_bind_compat_78289, DEFVAL(false));
|
ClassDB::bind_compatibility_method(D_METHOD("store_var", "value", "full_objects"), &FileAccess::store_var_bind_compat_78289, DEFVAL(false));
|
||||||
ClassDB::bind_compatibility_method(D_METHOD("store_pascal_string", "string"), &FileAccess::store_pascal_string_bind_compat_78289);
|
ClassDB::bind_compatibility_method(D_METHOD("store_pascal_string", "string"), &FileAccess::store_pascal_string_bind_compat_78289);
|
||||||
ClassDB::bind_compatibility_method(D_METHOD("get_as_text", "skip_cr"), &FileAccess::get_as_text_bind_compat_110867, DEFVAL(false));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -37,7 +37,6 @@
|
||||||
#include "core/io/file_access_encrypted.h"
|
#include "core/io/file_access_encrypted.h"
|
||||||
#include "core/io/file_access_pack.h"
|
#include "core/io/file_access_pack.h"
|
||||||
#include "core/io/marshalls.h"
|
#include "core/io/marshalls.h"
|
||||||
#include "core/io/resource_uid.h"
|
|
||||||
#include "core/os/os.h"
|
#include "core/os/os.h"
|
||||||
#include "core/os/time.h"
|
#include "core/os/time.h"
|
||||||
|
|
||||||
|
@ -82,12 +81,12 @@ Ref<FileAccess> FileAccess::create_for_path(const String &p_path) {
|
||||||
Ref<FileAccess> FileAccess::create_temp(int p_mode_flags, const String &p_prefix, const String &p_extension, bool p_keep, Error *r_error) {
|
Ref<FileAccess> FileAccess::create_temp(int p_mode_flags, const String &p_prefix, const String &p_extension, bool p_keep, Error *r_error) {
|
||||||
const String ERROR_COMMON_PREFIX = "Error while creating temporary file";
|
const String ERROR_COMMON_PREFIX = "Error while creating temporary file";
|
||||||
|
|
||||||
if (!p_prefix.is_empty() && !p_prefix.is_valid_filename()) {
|
if (!p_prefix.is_valid_filename()) {
|
||||||
*r_error = ERR_FILE_BAD_PATH;
|
*r_error = ERR_FILE_BAD_PATH;
|
||||||
ERR_FAIL_V_MSG(Ref<FileAccess>(), vformat(R"(%s: "%s" is not a valid prefix.)", ERROR_COMMON_PREFIX, p_prefix));
|
ERR_FAIL_V_MSG(Ref<FileAccess>(), vformat(R"(%s: "%s" is not a valid prefix.)", ERROR_COMMON_PREFIX, p_prefix));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p_extension.is_empty() && !p_extension.is_valid_filename()) {
|
if (!p_extension.is_valid_filename()) {
|
||||||
*r_error = ERR_FILE_BAD_PATH;
|
*r_error = ERR_FILE_BAD_PATH;
|
||||||
ERR_FAIL_V_MSG(Ref<FileAccess>(), vformat(R"(%s: "%s" is not a valid extension.)", ERROR_COMMON_PREFIX, p_extension));
|
ERR_FAIL_V_MSG(Ref<FileAccess>(), vformat(R"(%s: "%s" is not a valid extension.)", ERROR_COMMON_PREFIX, p_extension));
|
||||||
}
|
}
|
||||||
|
@ -446,7 +445,7 @@ class CharBuffer {
|
||||||
public:
|
public:
|
||||||
_FORCE_INLINE_ CharBuffer() :
|
_FORCE_INLINE_ CharBuffer() :
|
||||||
buffer(stack_buffer),
|
buffer(stack_buffer),
|
||||||
capacity(std_size(stack_buffer)) {
|
capacity(std::size(stack_buffer)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
_FORCE_INLINE_ void push_back(char c) {
|
_FORCE_INLINE_ void push_back(char c) {
|
||||||
|
@ -468,22 +467,10 @@ String FileAccess::get_line() const {
|
||||||
uint8_t c = get_8();
|
uint8_t c = get_8();
|
||||||
|
|
||||||
while (!eof_reached()) {
|
while (!eof_reached()) {
|
||||||
if (c == '\r' || c == '\n' || c == '\0' || get_error() != OK) {
|
if (c == '\n' || c == '\0' || get_error() != OK) {
|
||||||
if (c == '\r') {
|
|
||||||
// Check for Windows-style EOL.
|
|
||||||
const uint64_t prev_pos = get_position() - 1;
|
|
||||||
if (unlikely(get_8() != '\n')) {
|
|
||||||
// HACK: We can't simply check the next value in a vacuum, so we risk triggering
|
|
||||||
// an EOL false-positive in the unlikely event that this `\r` was the final
|
|
||||||
// value of the file. Unilaterally work around by re-reading the *previous*
|
|
||||||
// byte (the starting `\r`) to ensure `get_error()` returns `OK`.
|
|
||||||
const_cast<FileAccess *>(this)->seek(prev_pos);
|
|
||||||
get_8();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
line.push_back(0);
|
line.push_back(0);
|
||||||
return String::utf8(line.get_data());
|
return String::utf8(line.get_data());
|
||||||
} else {
|
} else if (c != '\r') {
|
||||||
line.push_back(char(c));
|
line.push_back(char(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -551,11 +538,11 @@ Vector<String> FileAccess::get_csv_line(const String &p_delim) const {
|
||||||
return strings;
|
return strings;
|
||||||
}
|
}
|
||||||
|
|
||||||
String FileAccess::get_as_text() const {
|
String FileAccess::get_as_text(bool p_skip_cr) const {
|
||||||
uint64_t original_pos = get_position();
|
uint64_t original_pos = get_position();
|
||||||
const_cast<FileAccess *>(this)->seek(0);
|
const_cast<FileAccess *>(this)->seek(0);
|
||||||
|
|
||||||
String text = get_as_utf8_string();
|
String text = get_as_utf8_string(p_skip_cr);
|
||||||
|
|
||||||
const_cast<FileAccess *>(this)->seek(original_pos);
|
const_cast<FileAccess *>(this)->seek(original_pos);
|
||||||
|
|
||||||
|
@ -570,7 +557,6 @@ Vector<uint8_t> FileAccess::get_buffer(int64_t p_length) const {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.reserve_exact(p_length);
|
|
||||||
Error err = data.resize(p_length);
|
Error err = data.resize(p_length);
|
||||||
ERR_FAIL_COND_V_MSG(err != OK, data, vformat("Can't resize data to %d elements.", p_length));
|
ERR_FAIL_COND_V_MSG(err != OK, data, vformat("Can't resize data to %d elements.", p_length));
|
||||||
|
|
||||||
|
@ -584,7 +570,7 @@ Vector<uint8_t> FileAccess::get_buffer(int64_t p_length) const {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
String FileAccess::get_as_utf8_string() const {
|
String FileAccess::get_as_utf8_string(bool p_skip_cr) const {
|
||||||
Vector<uint8_t> sourcef;
|
Vector<uint8_t> sourcef;
|
||||||
uint64_t len = get_length();
|
uint64_t len = get_length();
|
||||||
sourcef.resize(len + 1);
|
sourcef.resize(len + 1);
|
||||||
|
@ -595,7 +581,7 @@ String FileAccess::get_as_utf8_string() const {
|
||||||
w[len] = 0;
|
w[len] = 0;
|
||||||
|
|
||||||
String s;
|
String s;
|
||||||
s.append_utf8((const char *)w, len);
|
s.append_utf8((const char *)w, len, p_skip_cr);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -865,7 +851,6 @@ Vector<uint8_t> FileAccess::get_file_as_bytes(const String &p_path, Error *r_err
|
||||||
ERR_FAIL_V_MSG(Vector<uint8_t>(), vformat("Can't open file from path '%s'.", String(p_path)));
|
ERR_FAIL_V_MSG(Vector<uint8_t>(), vformat("Can't open file from path '%s'.", String(p_path)));
|
||||||
}
|
}
|
||||||
Vector<uint8_t> data;
|
Vector<uint8_t> data;
|
||||||
data.reserve_exact(f->get_length());
|
|
||||||
data.resize(f->get_length());
|
data.resize(f->get_length());
|
||||||
f->get_buffer(data.ptrw(), data.size());
|
f->get_buffer(data.ptrw(), data.size());
|
||||||
return data;
|
return data;
|
||||||
|
@ -1002,7 +987,7 @@ void FileAccess::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("get_buffer", "length"), (Vector<uint8_t> (FileAccess::*)(int64_t) const) & FileAccess::get_buffer);
|
ClassDB::bind_method(D_METHOD("get_buffer", "length"), (Vector<uint8_t> (FileAccess::*)(int64_t) const) & FileAccess::get_buffer);
|
||||||
ClassDB::bind_method(D_METHOD("get_line"), &FileAccess::get_line);
|
ClassDB::bind_method(D_METHOD("get_line"), &FileAccess::get_line);
|
||||||
ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &FileAccess::get_csv_line, DEFVAL(","));
|
ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &FileAccess::get_csv_line, DEFVAL(","));
|
||||||
ClassDB::bind_method(D_METHOD("get_as_text"), &FileAccess::get_as_text);
|
ClassDB::bind_method(D_METHOD("get_as_text", "skip_cr"), &FileAccess::get_as_text, DEFVAL(false));
|
||||||
ClassDB::bind_static_method("FileAccess", D_METHOD("get_md5", "path"), &FileAccess::get_md5);
|
ClassDB::bind_static_method("FileAccess", D_METHOD("get_md5", "path"), &FileAccess::get_md5);
|
||||||
ClassDB::bind_static_method("FileAccess", D_METHOD("get_sha256", "path"), &FileAccess::get_sha256);
|
ClassDB::bind_static_method("FileAccess", D_METHOD("get_sha256", "path"), &FileAccess::get_sha256);
|
||||||
ClassDB::bind_method(D_METHOD("is_big_endian"), &FileAccess::is_big_endian);
|
ClassDB::bind_method(D_METHOD("is_big_endian"), &FileAccess::is_big_endian);
|
||||||
|
|
|
@ -132,7 +132,6 @@ protected:
|
||||||
void store_line_bind_compat_78289(const String &p_line);
|
void store_line_bind_compat_78289(const String &p_line);
|
||||||
void store_csv_line_bind_compat_78289(const Vector<String> &p_values, const String &p_delim = ",");
|
void store_csv_line_bind_compat_78289(const Vector<String> &p_values, const String &p_delim = ",");
|
||||||
void store_pascal_string_bind_compat_78289(const String &p_string);
|
void store_pascal_string_bind_compat_78289(const String &p_string);
|
||||||
String get_as_text_bind_compat_110867(bool p_skip_cr) const;
|
|
||||||
|
|
||||||
static void _bind_compatibility_methods();
|
static void _bind_compatibility_methods();
|
||||||
#endif
|
#endif
|
||||||
|
@ -189,8 +188,8 @@ public:
|
||||||
virtual String get_line() const;
|
virtual String get_line() const;
|
||||||
virtual String get_token() const;
|
virtual String get_token() const;
|
||||||
virtual Vector<String> get_csv_line(const String &p_delim = ",") const;
|
virtual Vector<String> get_csv_line(const String &p_delim = ",") const;
|
||||||
String get_as_text() const;
|
String get_as_text(bool p_skip_cr = false) const;
|
||||||
virtual String get_as_utf8_string() const;
|
virtual String get_as_utf8_string(bool p_skip_cr = false) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
|
|
|
@ -130,37 +130,34 @@ void FileAccessCompressed::_close() {
|
||||||
f->store_32(0); //compressed sizes, will update later
|
f->store_32(0); //compressed sizes, will update later
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t last_block_size = write_max % block_size;
|
Vector<int> block_sizes;
|
||||||
|
|
||||||
// Temporary buffer for compressed data blocks.
|
|
||||||
LocalVector<uint8_t> temp_cblock;
|
|
||||||
temp_cblock.resize(Compression::get_max_compressed_buffer_size(bc == 1 ? last_block_size : block_size, cmode));
|
|
||||||
uint8_t *temp_cblock_ptr = temp_cblock.ptr();
|
|
||||||
|
|
||||||
// Compress and store the blocks.
|
|
||||||
LocalVector<uint32_t> block_sizes;
|
|
||||||
for (uint32_t i = 0; i < bc; i++) {
|
for (uint32_t i = 0; i < bc; i++) {
|
||||||
uint32_t bl = i == (bc - 1) ? last_block_size : block_size;
|
uint32_t bl = i == (bc - 1) ? write_max % block_size : block_size;
|
||||||
uint8_t *bp = &write_ptr[i * block_size];
|
uint8_t *bp = &write_ptr[i * block_size];
|
||||||
|
|
||||||
const int64_t compressed_size = Compression::compress(temp_cblock_ptr, bp, bl, cmode);
|
Vector<uint8_t> cblock;
|
||||||
|
cblock.resize(Compression::get_max_compressed_buffer_size(bl, cmode));
|
||||||
|
const int64_t compressed_size = Compression::compress(cblock.ptrw(), bp, bl, cmode);
|
||||||
ERR_FAIL_COND_MSG(compressed_size < 0, "FileAccessCompressed: Error compressing data.");
|
ERR_FAIL_COND_MSG(compressed_size < 0, "FileAccessCompressed: Error compressing data.");
|
||||||
|
|
||||||
f->store_buffer(temp_cblock_ptr, (uint64_t)compressed_size);
|
f->store_buffer(cblock.ptr(), (uint64_t)compressed_size);
|
||||||
block_sizes.push_back(compressed_size);
|
block_sizes.push_back(compressed_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
f->seek(16); //ok write block sizes
|
f->seek(16); //ok write block sizes
|
||||||
for (uint32_t i = 0; i < bc; i++) {
|
for (uint32_t i = 0; i < bc; i++) {
|
||||||
f->store_32(block_sizes[i]);
|
f->store_32(uint32_t(block_sizes[i]));
|
||||||
}
|
}
|
||||||
f->seek_end();
|
f->seek_end();
|
||||||
f->store_buffer((const uint8_t *)mgc.get_data(), mgc.length()); //magic at the end too
|
f->store_buffer((const uint8_t *)mgc.get_data(), mgc.length()); //magic at the end too
|
||||||
|
|
||||||
|
buffer.clear();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
comp_buffer.clear();
|
comp_buffer.clear();
|
||||||
|
buffer.clear();
|
||||||
read_blocks.clear();
|
read_blocks.clear();
|
||||||
}
|
}
|
||||||
buffer.clear();
|
|
||||||
f.unref();
|
f.unref();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,7 +140,7 @@ void FileAccessEncrypted::_close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (writing) {
|
if (writing) {
|
||||||
LocalVector<uint8_t> compressed;
|
Vector<uint8_t> compressed;
|
||||||
uint64_t len = data.size();
|
uint64_t len = data.size();
|
||||||
if (len % 16) {
|
if (len % 16) {
|
||||||
len += 16 - (len % 16);
|
len += 16 - (len % 16);
|
||||||
|
@ -150,8 +150,10 @@ void FileAccessEncrypted::_close() {
|
||||||
ERR_FAIL_COND(CryptoCore::md5(data.ptr(), data.size(), hash) != OK); // Bug?
|
ERR_FAIL_COND(CryptoCore::md5(data.ptr(), data.size(), hash) != OK); // Bug?
|
||||||
|
|
||||||
compressed.resize(len);
|
compressed.resize(len);
|
||||||
memcpy(compressed.ptr(), data.ptr(), data.size());
|
memset(compressed.ptrw(), 0, len);
|
||||||
memset(compressed.ptr() + data.size(), 0, len - data.size());
|
for (int i = 0; i < data.size(); i++) {
|
||||||
|
compressed.write[i] = data[i];
|
||||||
|
}
|
||||||
|
|
||||||
CryptoCore::AESContext ctx;
|
CryptoCore::AESContext ctx;
|
||||||
ctx.set_encode_key(key.ptrw(), 256);
|
ctx.set_encode_key(key.ptrw(), 256);
|
||||||
|
@ -164,7 +166,7 @@ void FileAccessEncrypted::_close() {
|
||||||
file->store_64(data.size());
|
file->store_64(data.size());
|
||||||
file->store_buffer(iv.ptr(), 16);
|
file->store_buffer(iv.ptr(), 16);
|
||||||
|
|
||||||
ctx.encrypt_cfb(len, iv.ptrw(), compressed.ptr(), compressed.ptr());
|
ctx.encrypt_cfb(len, iv.ptrw(), compressed.ptrw(), compressed.ptrw());
|
||||||
|
|
||||||
file->store_buffer(compressed.ptr(), compressed.size());
|
file->store_buffer(compressed.ptr(), compressed.size());
|
||||||
data.clear();
|
data.clear();
|
||||||
|
|
|
@ -35,8 +35,6 @@
|
||||||
#include "core/crypto/crypto.h"
|
#include "core/crypto/crypto.h"
|
||||||
|
|
||||||
class HTTPClientTCP : public HTTPClient {
|
class HTTPClientTCP : public HTTPClient {
|
||||||
GDSOFTCLASS(HTTPClientTCP, HTTPClient);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Status status = STATUS_DISCONNECTED;
|
Status status = STATUS_DISCONNECTED;
|
||||||
IP::ResolverID resolving = IP::RESOLVER_INVALID_ID;
|
IP::ResolverID resolving = IP::RESOLVER_INVALID_ID;
|
||||||
|
|
|
@ -78,14 +78,6 @@ const char *Image::format_names[Image::FORMAT_MAX] = {
|
||||||
"ASTC_4x4_HDR",
|
"ASTC_4x4_HDR",
|
||||||
"ASTC_8x8",
|
"ASTC_8x8",
|
||||||
"ASTC_8x8_HDR",
|
"ASTC_8x8_HDR",
|
||||||
"R16",
|
|
||||||
"RG16",
|
|
||||||
"RGB16",
|
|
||||||
"RGBA16",
|
|
||||||
"R16Int",
|
|
||||||
"RG16Int",
|
|
||||||
"RGB16Int",
|
|
||||||
"RGBA16Int",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// External VRAM compression function pointers.
|
// External VRAM compression function pointers.
|
||||||
|
@ -209,22 +201,6 @@ int Image::get_format_pixel_size(Format p_format) {
|
||||||
return 1;
|
return 1;
|
||||||
case FORMAT_ASTC_8x8_HDR:
|
case FORMAT_ASTC_8x8_HDR:
|
||||||
return 1;
|
return 1;
|
||||||
case FORMAT_R16:
|
|
||||||
return 2;
|
|
||||||
case FORMAT_RG16:
|
|
||||||
return 4;
|
|
||||||
case FORMAT_RGB16:
|
|
||||||
return 6;
|
|
||||||
case FORMAT_RGBA16:
|
|
||||||
return 8;
|
|
||||||
case FORMAT_R16I:
|
|
||||||
return 2;
|
|
||||||
case FORMAT_RG16I:
|
|
||||||
return 4;
|
|
||||||
case FORMAT_RGB16I:
|
|
||||||
return 6;
|
|
||||||
case FORMAT_RGBA16I:
|
|
||||||
return 8;
|
|
||||||
case FORMAT_MAX: {
|
case FORMAT_MAX: {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -783,78 +759,6 @@ void Image::convert(Format p_new_format) {
|
||||||
case FORMAT_RGBAF | (FORMAT_RGBF << 8):
|
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);
|
_convert_fast<uint32_t, 4, 3, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
|
||||||
break;
|
break;
|
||||||
case FORMAT_R16 | (FORMAT_RG16 << 8):
|
|
||||||
_convert_fast<uint16_t, 1, 2, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
case FORMAT_R16 | (FORMAT_RGB16 << 8):
|
|
||||||
_convert_fast<uint16_t, 1, 3, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
case FORMAT_R16 | (FORMAT_RGBA16 << 8):
|
|
||||||
_convert_fast<uint16_t, 1, 4, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
case FORMAT_RG16 | (FORMAT_R16 << 8):
|
|
||||||
_convert_fast<uint16_t, 2, 1, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
case FORMAT_RG16 | (FORMAT_RGB16 << 8):
|
|
||||||
_convert_fast<uint16_t, 2, 3, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
case FORMAT_RG16 | (FORMAT_RGBA16 << 8):
|
|
||||||
_convert_fast<uint16_t, 2, 4, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
case FORMAT_RGB16 | (FORMAT_R16 << 8):
|
|
||||||
_convert_fast<uint16_t, 3, 1, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
case FORMAT_RGB16 | (FORMAT_RG16 << 8):
|
|
||||||
_convert_fast<uint16_t, 3, 2, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
case FORMAT_RGB16 | (FORMAT_RGBA16 << 8):
|
|
||||||
_convert_fast<uint16_t, 3, 4, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
case FORMAT_RGBA16 | (FORMAT_R16 << 8):
|
|
||||||
_convert_fast<uint16_t, 4, 1, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
case FORMAT_RGBA16 | (FORMAT_RG16 << 8):
|
|
||||||
_convert_fast<uint16_t, 4, 2, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
case FORMAT_RGBA16 | (FORMAT_RGB16 << 8):
|
|
||||||
_convert_fast<uint16_t, 4, 3, 0x0000, 0xFFFF>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
case FORMAT_R16I | (FORMAT_RG16I << 8):
|
|
||||||
_convert_fast<uint16_t, 1, 2, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
case FORMAT_R16I | (FORMAT_RGB16I << 8):
|
|
||||||
_convert_fast<uint16_t, 1, 3, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
case FORMAT_R16I | (FORMAT_RGBA16I << 8):
|
|
||||||
_convert_fast<uint16_t, 1, 4, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
case FORMAT_RG16I | (FORMAT_R16I << 8):
|
|
||||||
_convert_fast<uint16_t, 2, 1, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
case FORMAT_RG16I | (FORMAT_RGB16I << 8):
|
|
||||||
_convert_fast<uint16_t, 2, 3, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
case FORMAT_RG16I | (FORMAT_RGBA16I << 8):
|
|
||||||
_convert_fast<uint16_t, 2, 4, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
case FORMAT_RGB16I | (FORMAT_R16I << 8):
|
|
||||||
_convert_fast<uint16_t, 3, 1, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
case FORMAT_RGB16I | (FORMAT_RG16I << 8):
|
|
||||||
_convert_fast<uint16_t, 3, 2, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
case FORMAT_RGB16I | (FORMAT_RGBA16I << 8):
|
|
||||||
_convert_fast<uint16_t, 3, 4, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
case FORMAT_RGBA16I | (FORMAT_R16I << 8):
|
|
||||||
_convert_fast<uint16_t, 4, 1, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
case FORMAT_RGBA16I | (FORMAT_RG16I << 8):
|
|
||||||
_convert_fast<uint16_t, 4, 2, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
case FORMAT_RGBA16I | (FORMAT_RGB16I << 8):
|
|
||||||
_convert_fast<uint16_t, 4, 3, 0x0000, 0x0001>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -865,11 +769,6 @@ Image::Format Image::get_format() const {
|
||||||
return format;
|
return format;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ImageScaleType {
|
|
||||||
IMAGE_SCALING_INT,
|
|
||||||
IMAGE_SCALING_FLOAT,
|
|
||||||
};
|
|
||||||
|
|
||||||
static double _bicubic_interp_kernel(double x) {
|
static double _bicubic_interp_kernel(double x) {
|
||||||
x = Math::abs(x);
|
x = Math::abs(x);
|
||||||
|
|
||||||
|
@ -884,7 +783,7 @@ static double _bicubic_interp_kernel(double x) {
|
||||||
return bc;
|
return bc;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int CC, typename T, ImageScaleType TYPE>
|
template <int CC, typename T>
|
||||||
static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
|
static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
|
||||||
// get source image size
|
// get source image size
|
||||||
int width = p_src_width;
|
int width = p_src_width;
|
||||||
|
@ -946,7 +845,7 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_
|
||||||
const T *__restrict p = ((T *)p_src) + (oy2 * p_src_width + ox2) * CC;
|
const T *__restrict p = ((T *)p_src) + (oy2 * p_src_width + ox2) * CC;
|
||||||
|
|
||||||
for (int i = 0; i < CC; i++) {
|
for (int i = 0; i < CC; i++) {
|
||||||
if constexpr (sizeof(T) == 2 && TYPE == IMAGE_SCALING_FLOAT) { //half float
|
if constexpr (sizeof(T) == 2) { //half float
|
||||||
color[i] = Math::half_to_float(p[i]);
|
color[i] = Math::half_to_float(p[i]);
|
||||||
} else {
|
} else {
|
||||||
color[i] += p[i] * k2;
|
color[i] += p[i] * k2;
|
||||||
|
@ -958,12 +857,8 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_
|
||||||
for (int i = 0; i < CC; i++) {
|
for (int i = 0; i < CC; i++) {
|
||||||
if constexpr (sizeof(T) == 1) { //byte
|
if constexpr (sizeof(T) == 1) { //byte
|
||||||
dst[i] = CLAMP(Math::fast_ftoi(color[i]), 0, 255);
|
dst[i] = CLAMP(Math::fast_ftoi(color[i]), 0, 255);
|
||||||
} else if constexpr (sizeof(T) == 2) {
|
} else if constexpr (sizeof(T) == 2) { //half float
|
||||||
if constexpr (TYPE == IMAGE_SCALING_FLOAT) {
|
dst[i] = Math::make_half_float(color[i]);
|
||||||
dst[i] = Math::make_half_float(color[i]); //half float
|
|
||||||
} else {
|
|
||||||
dst[i] = CLAMP(Math::fast_ftoi(color[i]), 0, 65535); // uint16
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
dst[i] = color[i];
|
dst[i] = color[i];
|
||||||
}
|
}
|
||||||
|
@ -972,7 +867,7 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int CC, typename T, ImageScaleType TYPE>
|
template <int CC, typename T>
|
||||||
static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
|
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_BITS = 8;
|
||||||
constexpr uint32_t FRAC_LEN = (1 << FRAC_BITS);
|
constexpr uint32_t FRAC_LEN = (1 << FRAC_BITS);
|
||||||
|
@ -1020,40 +915,23 @@ static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict
|
||||||
uint32_t interp = interp_up + (((interp_down - interp_up) * src_yofs_frac) >> FRAC_BITS);
|
uint32_t interp = interp_up + (((interp_down - interp_up) * src_yofs_frac) >> FRAC_BITS);
|
||||||
interp >>= FRAC_BITS;
|
interp >>= FRAC_BITS;
|
||||||
p_dst[i * p_dst_width * CC + j * CC + l] = uint8_t(interp);
|
p_dst[i * p_dst_width * CC + j * CC + l] = uint8_t(interp);
|
||||||
} else if constexpr (sizeof(T) == 2) {
|
} else if constexpr (sizeof(T) == 2) { //half float
|
||||||
if constexpr (TYPE == IMAGE_SCALING_FLOAT) { //half float
|
|
||||||
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
|
|
||||||
float yofs_frac = float(src_yofs_frac) / (1 << FRAC_BITS);
|
|
||||||
const T *src = ((const T *)p_src);
|
|
||||||
T *dst = ((T *)p_dst);
|
|
||||||
|
|
||||||
float p00 = Math::half_to_float(src[y_ofs_up + src_xofs_left + l]);
|
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
|
||||||
float p10 = Math::half_to_float(src[y_ofs_up + src_xofs_right + l]);
|
float yofs_frac = float(src_yofs_frac) / (1 << FRAC_BITS);
|
||||||
float p01 = Math::half_to_float(src[y_ofs_down + src_xofs_left + l]);
|
const T *src = ((const T *)p_src);
|
||||||
float p11 = Math::half_to_float(src[y_ofs_down + src_xofs_right + l]);
|
T *dst = ((T *)p_dst);
|
||||||
|
|
||||||
float interp_up = p00 + (p10 - p00) * xofs_frac;
|
float p00 = Math::half_to_float(src[y_ofs_up + src_xofs_left + l]);
|
||||||
float interp_down = p01 + (p11 - p01) * xofs_frac;
|
float p10 = Math::half_to_float(src[y_ofs_up + src_xofs_right + l]);
|
||||||
float interp = interp_up + ((interp_down - interp_up) * yofs_frac);
|
float p01 = Math::half_to_float(src[y_ofs_down + src_xofs_left + l]);
|
||||||
|
float p11 = Math::half_to_float(src[y_ofs_down + src_xofs_right + l]);
|
||||||
|
|
||||||
dst[i * p_dst_width * CC + j * CC + l] = Math::make_half_float(interp);
|
float interp_up = p00 + (p10 - p00) * xofs_frac;
|
||||||
} else { //uint16
|
float interp_down = p01 + (p11 - p01) * xofs_frac;
|
||||||
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
|
float interp = interp_up + ((interp_down - interp_up) * yofs_frac);
|
||||||
float yofs_frac = float(src_yofs_frac) / (1 << FRAC_BITS);
|
|
||||||
const T *src = ((const T *)p_src);
|
|
||||||
T *dst = ((T *)p_dst);
|
|
||||||
|
|
||||||
float p00 = src[y_ofs_up + src_xofs_left + l];
|
dst[i * p_dst_width * CC + j * CC + l] = Math::make_half_float(interp);
|
||||||
float p10 = src[y_ofs_up + src_xofs_right + l];
|
|
||||||
float p01 = src[y_ofs_down + src_xofs_left + l];
|
|
||||||
float p11 = src[y_ofs_down + src_xofs_right + l];
|
|
||||||
|
|
||||||
float interp_up = p00 + (p10 - p00) * xofs_frac;
|
|
||||||
float interp_down = p01 + (p11 - p01) * xofs_frac;
|
|
||||||
float interp = interp_up + ((interp_down - interp_up) * yofs_frac);
|
|
||||||
|
|
||||||
dst[i * p_dst_width * CC + j * CC + l] = uint16_t(interp);
|
|
||||||
}
|
|
||||||
} else if constexpr (sizeof(T) == 4) { //float
|
} else if constexpr (sizeof(T) == 4) { //float
|
||||||
|
|
||||||
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
|
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
|
||||||
|
@ -1104,7 +982,7 @@ static float _lanczos(float p_x) {
|
||||||
return Math::abs(p_x) >= LANCZOS_TYPE ? 0 : Math::sincn(p_x) * Math::sincn(p_x / LANCZOS_TYPE);
|
return Math::abs(p_x) >= LANCZOS_TYPE ? 0 : Math::sincn(p_x) * Math::sincn(p_x / LANCZOS_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int CC, typename T, ImageScaleType TYPE>
|
template <int CC, typename T>
|
||||||
static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
|
static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
|
||||||
int32_t src_width = p_src_width;
|
int32_t src_width = p_src_width;
|
||||||
int32_t src_height = p_src_height;
|
int32_t src_height = p_src_height;
|
||||||
|
@ -1145,7 +1023,7 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict
|
||||||
const T *__restrict src_data = ((const T *)p_src) + (buffer_y * src_width + target_x) * CC;
|
const T *__restrict src_data = ((const T *)p_src) + (buffer_y * src_width + target_x) * CC;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < CC; i++) {
|
for (uint32_t i = 0; i < CC; i++) {
|
||||||
if constexpr (sizeof(T) == 2 && TYPE == IMAGE_SCALING_FLOAT) { //half float
|
if constexpr (sizeof(T) == 2) { //half float
|
||||||
pixel[i] += Math::half_to_float(src_data[i]) * lanczos_val;
|
pixel[i] += Math::half_to_float(src_data[i]) * lanczos_val;
|
||||||
} else {
|
} else {
|
||||||
pixel[i] += src_data[i] * lanczos_val;
|
pixel[i] += src_data[i] * lanczos_val;
|
||||||
|
@ -1204,13 +1082,8 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict
|
||||||
|
|
||||||
if constexpr (sizeof(T) == 1) { //byte
|
if constexpr (sizeof(T) == 1) { //byte
|
||||||
dst_data[i] = CLAMP(Math::fast_ftoi(pixel[i]), 0, 255);
|
dst_data[i] = CLAMP(Math::fast_ftoi(pixel[i]), 0, 255);
|
||||||
} else if constexpr (sizeof(T) == 2) {
|
} else if constexpr (sizeof(T) == 2) { //half float
|
||||||
if constexpr (TYPE == IMAGE_SCALING_FLOAT) { //half float
|
dst_data[i] = Math::make_half_float(pixel[i]);
|
||||||
dst_data[i] = Math::make_half_float(pixel[i]);
|
|
||||||
} else { //uint16
|
|
||||||
dst_data[i] = CLAMP(Math::fast_ftoi(pixel[i]), 0, 65535);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else { // float
|
} else { // float
|
||||||
dst_data[i] = pixel[i];
|
dst_data[i] = pixel[i];
|
||||||
}
|
}
|
||||||
|
@ -1353,21 +1226,6 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
|
||||||
_scale_nearest<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_nearest<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
|
|
||||||
switch (get_format_pixel_size(format)) {
|
|
||||||
case 2:
|
|
||||||
_scale_nearest<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
_scale_nearest<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
_scale_nearest<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
_scale_nearest<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
@ -1412,61 +1270,46 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
|
||||||
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
|
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
|
||||||
switch (get_format_pixel_size(format)) {
|
switch (get_format_pixel_size(format)) {
|
||||||
case 1:
|
case 1:
|
||||||
_scale_bilinear<1, uint8_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<1, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
_scale_bilinear<2, uint8_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<2, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
_scale_bilinear<3, uint8_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<3, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
_scale_bilinear<4, uint8_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<4, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
|
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
|
||||||
switch (get_format_pixel_size(format)) {
|
switch (get_format_pixel_size(format)) {
|
||||||
case 4:
|
case 4:
|
||||||
_scale_bilinear<1, float, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<1, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
_scale_bilinear<2, float, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<2, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 12:
|
case 12:
|
||||||
_scale_bilinear<3, float, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<3, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
_scale_bilinear<4, float, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<4, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
|
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
|
||||||
switch (get_format_pixel_size(format)) {
|
switch (get_format_pixel_size(format)) {
|
||||||
case 2:
|
case 2:
|
||||||
_scale_bilinear<1, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<1, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
_scale_bilinear<2, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<2, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
_scale_bilinear<3, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<3, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
_scale_bilinear<4, uint16_t, IMAGE_SCALING_FLOAT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
_scale_bilinear<4, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
|
|
||||||
switch (get_format_pixel_size(format)) {
|
|
||||||
case 2:
|
|
||||||
_scale_bilinear<1, uint16_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
_scale_bilinear<2, uint16_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
_scale_bilinear<3, uint16_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
_scale_bilinear<4, uint16_t, IMAGE_SCALING_INT>(src_ptr, w_ptr, src_width, src_height, p_width, p_height);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1483,61 +1326,46 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
|
||||||
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
|
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
|
||||||
switch (get_format_pixel_size(format)) {
|
switch (get_format_pixel_size(format)) {
|
||||||
case 1:
|
case 1:
|
||||||
_scale_cubic<1, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
_scale_cubic<2, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
_scale_cubic<3, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
_scale_cubic<4, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
|
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
|
||||||
switch (get_format_pixel_size(format)) {
|
switch (get_format_pixel_size(format)) {
|
||||||
case 4:
|
case 4:
|
||||||
_scale_cubic<1, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<1, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
_scale_cubic<2, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<2, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 12:
|
case 12:
|
||||||
_scale_cubic<3, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<3, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
_scale_cubic<4, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<4, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
|
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
|
||||||
switch (get_format_pixel_size(format)) {
|
switch (get_format_pixel_size(format)) {
|
||||||
case 2:
|
case 2:
|
||||||
_scale_cubic<1, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
_scale_cubic<2, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
_scale_cubic<3, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
_scale_cubic<4, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_cubic<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
|
|
||||||
switch (get_format_pixel_size(format)) {
|
|
||||||
case 2:
|
|
||||||
_scale_cubic<1, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
_scale_cubic<2, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
_scale_cubic<3, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
_scale_cubic<4, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1546,61 +1374,46 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
|
||||||
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
|
if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) {
|
||||||
switch (get_format_pixel_size(format)) {
|
switch (get_format_pixel_size(format)) {
|
||||||
case 1:
|
case 1:
|
||||||
_scale_lanczos<1, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
_scale_lanczos<2, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
_scale_lanczos<3, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
_scale_lanczos<4, uint8_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
|
} else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) {
|
||||||
switch (get_format_pixel_size(format)) {
|
switch (get_format_pixel_size(format)) {
|
||||||
case 4:
|
case 4:
|
||||||
_scale_lanczos<1, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<1, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
_scale_lanczos<2, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<2, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 12:
|
case 12:
|
||||||
_scale_lanczos<3, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<3, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
_scale_lanczos<4, float, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<4, float>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
|
} else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) {
|
||||||
switch (get_format_pixel_size(format)) {
|
switch (get_format_pixel_size(format)) {
|
||||||
case 2:
|
case 2:
|
||||||
_scale_lanczos<1, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
_scale_lanczos<2, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
_scale_lanczos<3, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
_scale_lanczos<4, uint16_t, IMAGE_SCALING_FLOAT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
_scale_lanczos<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height);
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (format >= FORMAT_R16 && format <= FORMAT_RGBA16I) {
|
|
||||||
switch (get_format_pixel_size(format)) {
|
|
||||||
case 2:
|
|
||||||
_scale_lanczos<1, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
_scale_lanczos<2, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
_scale_lanczos<3, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
_scale_lanczos<4, uint16_t, IMAGE_SCALING_INT>(r_ptr, w_ptr, width, height, p_width, p_height);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1969,7 +1782,7 @@ static void _generate_po2_mipmap(const Component *p_src, Component *p_dst, uint3
|
||||||
average_func(dst_ptr[j], rup_ptr[j], rup_ptr[j + right_step], rdown_ptr[j], rdown_ptr[j + right_step]);
|
average_func(dst_ptr[j], rup_ptr[j], rup_ptr[j + right_step], rdown_ptr[j], rdown_ptr[j + right_step]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (renormalize) {
|
if (renormalize) {
|
||||||
renormalize_func(dst_ptr);
|
renormalize_func(dst_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2015,12 +1828,6 @@ void Image::_generate_mipmap_from_format(Image::Format p_format, const uint8_t *
|
||||||
_generate_po2_mipmap<uint8_t, 4, false, Image::average_4_uint8, Image::renormalize_uint8>(p_src, p_dst, p_width, p_height);
|
_generate_po2_mipmap<uint8_t, 4, false, Image::average_4_uint8, Image::renormalize_uint8>(p_src, p_dst, p_width, p_height);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case Image::FORMAT_RGBA4444: {
|
|
||||||
_generate_po2_mipmap<uint16_t, 1, false, Image::average_4_rgba4444, nullptr>(src_u16, dst_u16, p_width, p_height);
|
|
||||||
} break;
|
|
||||||
case Image::FORMAT_RGB565: {
|
|
||||||
_generate_po2_mipmap<uint16_t, 1, false, Image::average_4_rgb565, nullptr>(src_u16, dst_u16, p_width, p_height);
|
|
||||||
} break;
|
|
||||||
case Image::FORMAT_RF:
|
case Image::FORMAT_RF:
|
||||||
_generate_po2_mipmap<float, 1, false, Image::average_4_float, Image::renormalize_float>(src_float, dst_float, p_width, p_height);
|
_generate_po2_mipmap<float, 1, false, Image::average_4_float, Image::renormalize_float>(src_float, dst_float, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
|
@ -2062,32 +1869,8 @@ void Image::_generate_mipmap_from_format(Image::Format p_format, const uint8_t *
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case Image::FORMAT_RGBE9995:
|
case Image::FORMAT_RGBE9995:
|
||||||
_generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, nullptr>(src_u32, dst_u32, p_width, p_height);
|
_generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(src_u32, dst_u32, p_width, p_height);
|
||||||
break;
|
break;
|
||||||
case Image::FORMAT_R16:
|
|
||||||
case Image::FORMAT_R16I:
|
|
||||||
_generate_po2_mipmap<uint16_t, 1, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
|
||||||
break;
|
|
||||||
case Image::FORMAT_RG16:
|
|
||||||
case Image::FORMAT_RG16I:
|
|
||||||
_generate_po2_mipmap<uint16_t, 2, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
|
||||||
break;
|
|
||||||
case Image::FORMAT_RGB16:
|
|
||||||
case Image::FORMAT_RGB16I: {
|
|
||||||
if (p_renormalize) {
|
|
||||||
_generate_po2_mipmap<uint16_t, 3, true, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
|
||||||
} else {
|
|
||||||
_generate_po2_mipmap<uint16_t, 3, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
case Image::FORMAT_RGBA16:
|
|
||||||
case Image::FORMAT_RGBA16I: {
|
|
||||||
if (p_renormalize) {
|
|
||||||
_generate_po2_mipmap<uint16_t, 4, true, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
|
||||||
} else {
|
|
||||||
_generate_po2_mipmap<uint16_t, 4, false, Image::average_4_uint16, Image::renormalize_uint16>(src_u16, dst_u16, p_width, p_height);
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
|
@ -2147,6 +1930,7 @@ void Image::normalize() {
|
||||||
|
|
||||||
Error Image::generate_mipmaps(bool p_renormalize) {
|
Error Image::generate_mipmaps(bool p_renormalize) {
|
||||||
ERR_FAIL_COND_V_MSG(is_compressed(), ERR_UNAVAILABLE, "Cannot generate mipmaps from compressed image formats.");
|
ERR_FAIL_COND_V_MSG(is_compressed(), ERR_UNAVAILABLE, "Cannot generate mipmaps from compressed image formats.");
|
||||||
|
ERR_FAIL_COND_V_MSG(format == FORMAT_RGBA4444, ERR_UNAVAILABLE, "Cannot generate mipmaps from RGBA4444 format.");
|
||||||
ERR_FAIL_COND_V_MSG(width == 0 || height == 0, ERR_UNCONFIGURED, "Cannot generate mipmaps with width or height equal to 0.");
|
ERR_FAIL_COND_V_MSG(width == 0 || height == 0, ERR_UNCONFIGURED, "Cannot generate mipmaps with width or height equal to 0.");
|
||||||
|
|
||||||
int gen_mipmap_count;
|
int gen_mipmap_count;
|
||||||
|
@ -2684,17 +2468,6 @@ bool Image::is_invisible() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case FORMAT_RGBA16:
|
|
||||||
case FORMAT_RGBA16I: {
|
|
||||||
const int pixel_count = len / 8;
|
|
||||||
const uint16_t *pixeldata = reinterpret_cast<const uint16_t *>(data.ptr());
|
|
||||||
|
|
||||||
for (int i = 0; i < pixel_count; i++) {
|
|
||||||
if (pixeldata[i * 4 + 3] != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
default: {
|
default: {
|
||||||
// Formats that are compressed or don't support alpha channels are presumed to be visible.
|
// Formats that are compressed or don't support alpha channels are presumed to be visible.
|
||||||
return false;
|
return false;
|
||||||
|
@ -2898,7 +2671,7 @@ bool Image::is_compressed() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Image::is_format_compressed(Format p_format) {
|
bool Image::is_format_compressed(Format p_format) {
|
||||||
return p_format > FORMAT_RGBE9995 && p_format < FORMAT_R16;
|
return p_format > FORMAT_RGBE9995;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error Image::decompress() {
|
Error Image::decompress() {
|
||||||
|
@ -3129,17 +2902,20 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const P
|
||||||
|
|
||||||
int pixel_size = get_format_pixel_size(format);
|
int pixel_size = get_format_pixel_size(format);
|
||||||
|
|
||||||
// If the rect width is equivalent for both src and dst and the x offset is 0, we can blit in a single memcpy.
|
for (int i = 0; i < dest_rect.size.y; i++) {
|
||||||
// Else, we do a per-line copy.
|
for (int j = 0; j < dest_rect.size.x; j++) {
|
||||||
if ((dest_rect.size.x == p_src->width) && (p_src->width == width) && (dest_rect.position.x == 0) && (src_rect.position.x == 0)) {
|
int src_x = src_rect.position.x + j;
|
||||||
const uint8_t *src = &src_data_ptr[(src_rect.position.y * p_src->width) * pixel_size];
|
int src_y = src_rect.position.y + i;
|
||||||
uint8_t *dst = &dst_data_ptr[(dest_rect.position.y * width) * pixel_size];
|
|
||||||
memcpy(dst, src, width * dest_rect.size.y * pixel_size);
|
int dst_x = dest_rect.position.x + j;
|
||||||
} else {
|
int dst_y = dest_rect.position.y + i;
|
||||||
for (int i = 0; i < dest_rect.size.y; i++) {
|
|
||||||
const uint8_t *src = &src_data_ptr[((src_rect.position.y + i) * p_src->width + src_rect.position.x) * pixel_size];
|
const uint8_t *src = &src_data_ptr[(src_y * p_src->width + src_x) * pixel_size];
|
||||||
uint8_t *dst = &dst_data_ptr[((dest_rect.position.y + i) * width + dest_rect.position.x) * pixel_size];
|
uint8_t *dst = &dst_data_ptr[(dst_y * width + dst_x) * pixel_size];
|
||||||
memcpy(dst, src, pixel_size * dest_rect.size.x);
|
|
||||||
|
for (int k = 0; k < pixel_size; k++) {
|
||||||
|
dst[k] = src[k];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3295,13 +3071,13 @@ void Image::fill(const Color &p_color) {
|
||||||
ERR_FAIL_COND_MSG(is_compressed(), "Cannot fill in compressed image formats.");
|
ERR_FAIL_COND_MSG(is_compressed(), "Cannot fill in compressed image formats.");
|
||||||
|
|
||||||
uint8_t *dst_data_ptr = data.ptrw();
|
uint8_t *dst_data_ptr = data.ptrw();
|
||||||
|
|
||||||
int pixel_size = get_format_pixel_size(format);
|
int pixel_size = get_format_pixel_size(format);
|
||||||
int64_t pixel_count = data.size() / pixel_size;
|
|
||||||
|
|
||||||
// Put first pixel with the format-aware API.
|
// Put first pixel with the format-aware API.
|
||||||
_set_color_at_ofs(dst_data_ptr, 0, p_color);
|
_set_color_at_ofs(dst_data_ptr, 0, p_color);
|
||||||
|
|
||||||
_repeat_pixel_over_subsequent_memory(dst_data_ptr, pixel_size, pixel_count);
|
_repeat_pixel_over_subsequent_memory(dst_data_ptr, pixel_size, width * height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::fill_rect(const Rect2i &p_rect, const Color &p_color) {
|
void Image::fill_rect(const Rect2i &p_rect, const Color &p_color) {
|
||||||
|
@ -3381,42 +3157,6 @@ void Image::_copy_internals_from(const Image &p_image) {
|
||||||
data = p_image.data;
|
data = p_image.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
_FORCE_INLINE_ Color color_from_rgba4444(uint16_t p_col) {
|
|
||||||
float r = ((p_col >> 12) & 0xF) / 15.0;
|
|
||||||
float g = ((p_col >> 8) & 0xF) / 15.0;
|
|
||||||
float b = ((p_col >> 4) & 0xF) / 15.0;
|
|
||||||
float a = (p_col & 0xF) / 15.0;
|
|
||||||
return Color(r, g, b, a);
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ uint16_t color_to_rgba4444(Color p_col) {
|
|
||||||
uint16_t rgba = 0;
|
|
||||||
|
|
||||||
rgba = uint16_t(CLAMP(p_col.r * 15.0, 0, 15)) << 12;
|
|
||||||
rgba |= uint16_t(CLAMP(p_col.g * 15.0, 0, 15)) << 8;
|
|
||||||
rgba |= uint16_t(CLAMP(p_col.b * 15.0, 0, 15)) << 4;
|
|
||||||
rgba |= uint16_t(CLAMP(p_col.a * 15.0, 0, 15));
|
|
||||||
|
|
||||||
return rgba;
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ Color color_from_rgb565(uint16_t p_col) {
|
|
||||||
float r = ((p_col >> 11) & 0x1F) / 31.0;
|
|
||||||
float g = ((p_col >> 5) & 0x3F) / 63.0;
|
|
||||||
float b = (p_col & 0x1F) / 31.0;
|
|
||||||
return Color(r, g, b, 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ uint16_t color_to_rgb565(Color p_col) {
|
|
||||||
uint16_t rgba = 0;
|
|
||||||
|
|
||||||
rgba = uint16_t(CLAMP(p_col.r * 31.0, 0, 31)) << 11;
|
|
||||||
rgba |= uint16_t(CLAMP(p_col.g * 63.0, 0, 63)) << 5;
|
|
||||||
rgba |= uint16_t(CLAMP(p_col.b * 31.0, 0, 31));
|
|
||||||
|
|
||||||
return rgba;
|
|
||||||
}
|
|
||||||
|
|
||||||
Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const {
|
Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case FORMAT_L8: {
|
case FORMAT_L8: {
|
||||||
|
@ -3451,10 +3191,19 @@ Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const {
|
||||||
return Color(r, g, b, a);
|
return Color(r, g, b, a);
|
||||||
}
|
}
|
||||||
case FORMAT_RGBA4444: {
|
case FORMAT_RGBA4444: {
|
||||||
return color_from_rgba4444(((uint16_t *)ptr)[ofs]);
|
uint16_t u = ((uint16_t *)ptr)[ofs];
|
||||||
|
float r = ((u >> 12) & 0xF) / 15.0;
|
||||||
|
float g = ((u >> 8) & 0xF) / 15.0;
|
||||||
|
float b = ((u >> 4) & 0xF) / 15.0;
|
||||||
|
float a = (u & 0xF) / 15.0;
|
||||||
|
return Color(r, g, b, a);
|
||||||
}
|
}
|
||||||
case FORMAT_RGB565: {
|
case FORMAT_RGB565: {
|
||||||
return color_from_rgb565(((uint16_t *)ptr)[ofs]);
|
uint16_t u = ((uint16_t *)ptr)[ofs];
|
||||||
|
float r = ((u >> 11) & 0x1F) / 31.0;
|
||||||
|
float g = ((u >> 5) & 0x3F) / 63.0;
|
||||||
|
float b = (u & 0x1F) / 31.0;
|
||||||
|
return Color(r, g, b, 1.0);
|
||||||
}
|
}
|
||||||
case FORMAT_RF: {
|
case FORMAT_RF: {
|
||||||
float r = ((float *)ptr)[ofs];
|
float r = ((float *)ptr)[ofs];
|
||||||
|
@ -3503,50 +3252,6 @@ Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const {
|
||||||
case FORMAT_RGBE9995: {
|
case FORMAT_RGBE9995: {
|
||||||
return Color::from_rgbe9995(((uint32_t *)ptr)[ofs]);
|
return Color::from_rgbe9995(((uint32_t *)ptr)[ofs]);
|
||||||
}
|
}
|
||||||
case FORMAT_R16: {
|
|
||||||
float r = ((uint16_t *)ptr)[ofs] / 65535.0f;
|
|
||||||
return Color(r, 0, 0, 1);
|
|
||||||
}
|
|
||||||
case FORMAT_RG16: {
|
|
||||||
float r = ((uint16_t *)ptr)[ofs * 2 + 0] / 65535.0f;
|
|
||||||
float g = ((uint16_t *)ptr)[ofs * 2 + 1] / 65535.0f;
|
|
||||||
return Color(r, g, 0, 1);
|
|
||||||
}
|
|
||||||
case FORMAT_RGB16: {
|
|
||||||
float r = ((uint16_t *)ptr)[ofs * 3 + 0] / 65535.0f;
|
|
||||||
float g = ((uint16_t *)ptr)[ofs * 3 + 1] / 65535.0f;
|
|
||||||
float b = ((uint16_t *)ptr)[ofs * 3 + 2] / 65535.0f;
|
|
||||||
return Color(r, g, b, 1);
|
|
||||||
}
|
|
||||||
case FORMAT_RGBA16: {
|
|
||||||
float r = ((uint16_t *)ptr)[ofs * 4 + 0] / 65535.0f;
|
|
||||||
float g = ((uint16_t *)ptr)[ofs * 4 + 1] / 65535.0f;
|
|
||||||
float b = ((uint16_t *)ptr)[ofs * 4 + 2] / 65535.0f;
|
|
||||||
float a = ((uint16_t *)ptr)[ofs * 4 + 3] / 65535.0f;
|
|
||||||
return Color(r, g, b, a);
|
|
||||||
}
|
|
||||||
case FORMAT_R16I: {
|
|
||||||
uint16_t r = ((uint16_t *)ptr)[ofs];
|
|
||||||
return Color(r, 0, 0, 1);
|
|
||||||
}
|
|
||||||
case FORMAT_RG16I: {
|
|
||||||
uint16_t r = ((uint16_t *)ptr)[ofs * 2 + 0];
|
|
||||||
uint16_t g = ((uint16_t *)ptr)[ofs * 2 + 1];
|
|
||||||
return Color(r, g, 0, 1);
|
|
||||||
}
|
|
||||||
case FORMAT_RGB16I: {
|
|
||||||
uint16_t r = ((uint16_t *)ptr)[ofs * 3 + 0];
|
|
||||||
uint16_t g = ((uint16_t *)ptr)[ofs * 3 + 1];
|
|
||||||
uint16_t b = ((uint16_t *)ptr)[ofs * 3 + 2];
|
|
||||||
return Color(r, g, b, 1);
|
|
||||||
}
|
|
||||||
case FORMAT_RGBA16I: {
|
|
||||||
uint16_t r = ((uint16_t *)ptr)[ofs * 4 + 0];
|
|
||||||
uint16_t g = ((uint16_t *)ptr)[ofs * 4 + 1];
|
|
||||||
uint16_t b = ((uint16_t *)ptr)[ofs * 4 + 2];
|
|
||||||
uint16_t a = ((uint16_t *)ptr)[ofs * 4 + 3];
|
|
||||||
return Color(r, g, b, a);
|
|
||||||
}
|
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
ERR_FAIL_V_MSG(Color(), "Can't get_pixel() on compressed image, sorry.");
|
ERR_FAIL_V_MSG(Color(), "Can't get_pixel() on compressed image, sorry.");
|
||||||
|
@ -3582,10 +3287,23 @@ void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color)
|
||||||
ptr[ofs * 4 + 3] = uint8_t(CLAMP(p_color.a * 255.0, 0, 255));
|
ptr[ofs * 4 + 3] = uint8_t(CLAMP(p_color.a * 255.0, 0, 255));
|
||||||
} break;
|
} break;
|
||||||
case FORMAT_RGBA4444: {
|
case FORMAT_RGBA4444: {
|
||||||
((uint16_t *)ptr)[ofs] = color_to_rgba4444(p_color);
|
uint16_t rgba = 0;
|
||||||
|
|
||||||
|
rgba = uint16_t(CLAMP(p_color.r * 15.0, 0, 15)) << 12;
|
||||||
|
rgba |= uint16_t(CLAMP(p_color.g * 15.0, 0, 15)) << 8;
|
||||||
|
rgba |= uint16_t(CLAMP(p_color.b * 15.0, 0, 15)) << 4;
|
||||||
|
rgba |= uint16_t(CLAMP(p_color.a * 15.0, 0, 15));
|
||||||
|
|
||||||
|
((uint16_t *)ptr)[ofs] = rgba;
|
||||||
} break;
|
} break;
|
||||||
case FORMAT_RGB565: {
|
case FORMAT_RGB565: {
|
||||||
((uint16_t *)ptr)[ofs] = color_to_rgb565(p_color);
|
uint16_t rgba = 0;
|
||||||
|
|
||||||
|
rgba = uint16_t(CLAMP(p_color.r * 31.0, 0, 31)) << 11;
|
||||||
|
rgba |= uint16_t(CLAMP(p_color.g * 63.0, 0, 63)) << 5;
|
||||||
|
rgba |= uint16_t(CLAMP(p_color.b * 31.0, 0, 31));
|
||||||
|
|
||||||
|
((uint16_t *)ptr)[ofs] = rgba;
|
||||||
} break;
|
} break;
|
||||||
case FORMAT_RF: {
|
case FORMAT_RF: {
|
||||||
((float *)ptr)[ofs] = p_color.r;
|
((float *)ptr)[ofs] = p_color.r;
|
||||||
|
@ -3626,42 +3344,6 @@ void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color)
|
||||||
case FORMAT_RGBE9995: {
|
case FORMAT_RGBE9995: {
|
||||||
((uint32_t *)ptr)[ofs] = p_color.to_rgbe9995();
|
((uint32_t *)ptr)[ofs] = p_color.to_rgbe9995();
|
||||||
} break;
|
} break;
|
||||||
case FORMAT_R16: {
|
|
||||||
((uint16_t *)ptr)[ofs] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
|
|
||||||
} break;
|
|
||||||
case FORMAT_RG16: {
|
|
||||||
((uint16_t *)ptr)[ofs * 2 + 0] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
|
|
||||||
((uint16_t *)ptr)[ofs * 2 + 1] = uint16_t(CLAMP(p_color.g * 65535.0, 0, 65535));
|
|
||||||
} break;
|
|
||||||
case FORMAT_RGB16: {
|
|
||||||
((uint16_t *)ptr)[ofs * 3 + 0] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
|
|
||||||
((uint16_t *)ptr)[ofs * 3 + 1] = uint16_t(CLAMP(p_color.g * 65535.0, 0, 65535));
|
|
||||||
((uint16_t *)ptr)[ofs * 3 + 2] = uint16_t(CLAMP(p_color.b * 65535.0, 0, 65535));
|
|
||||||
} break;
|
|
||||||
case FORMAT_RGBA16: {
|
|
||||||
((uint16_t *)ptr)[ofs * 4 + 0] = uint16_t(CLAMP(p_color.r * 65535.0, 0, 65535));
|
|
||||||
((uint16_t *)ptr)[ofs * 4 + 1] = uint16_t(CLAMP(p_color.g * 65535.0, 0, 65535));
|
|
||||||
((uint16_t *)ptr)[ofs * 4 + 2] = uint16_t(CLAMP(p_color.b * 65535.0, 0, 65535));
|
|
||||||
((uint16_t *)ptr)[ofs * 4 + 3] = uint16_t(CLAMP(p_color.a * 65535.0, 0, 65535));
|
|
||||||
} break;
|
|
||||||
case FORMAT_R16I: {
|
|
||||||
((uint16_t *)ptr)[ofs] = uint16_t(CLAMP(p_color.r, 0, 65535));
|
|
||||||
} break;
|
|
||||||
case FORMAT_RG16I: {
|
|
||||||
((uint16_t *)ptr)[ofs * 2 + 0] = uint16_t(CLAMP(p_color.r, 0, 65535));
|
|
||||||
((uint16_t *)ptr)[ofs * 2 + 1] = uint16_t(CLAMP(p_color.g, 0, 65535));
|
|
||||||
} break;
|
|
||||||
case FORMAT_RGB16I: {
|
|
||||||
((uint16_t *)ptr)[ofs * 3 + 0] = uint16_t(CLAMP(p_color.r, 0, 65535));
|
|
||||||
((uint16_t *)ptr)[ofs * 3 + 1] = uint16_t(CLAMP(p_color.g, 0, 65535));
|
|
||||||
((uint16_t *)ptr)[ofs * 3 + 2] = uint16_t(CLAMP(p_color.b, 0, 65535));
|
|
||||||
} break;
|
|
||||||
case FORMAT_RGBA16I: {
|
|
||||||
((uint16_t *)ptr)[ofs * 4 + 0] = uint16_t(CLAMP(p_color.r, 0, 65535));
|
|
||||||
((uint16_t *)ptr)[ofs * 4 + 1] = uint16_t(CLAMP(p_color.g, 0, 65535));
|
|
||||||
((uint16_t *)ptr)[ofs * 4 + 2] = uint16_t(CLAMP(p_color.b, 0, 65535));
|
|
||||||
((uint16_t *)ptr)[ofs * 4 + 3] = uint16_t(CLAMP(p_color.a, 0, 65535));
|
|
||||||
} break;
|
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
ERR_FAIL_MSG("Can't set_pixel() on compressed image, sorry.");
|
ERR_FAIL_MSG("Can't set_pixel() on compressed image, sorry.");
|
||||||
|
@ -3737,11 +3419,11 @@ Image::UsedChannels Image::detect_used_channels(CompressSource p_source) const {
|
||||||
|
|
||||||
if (format == FORMAT_L8) {
|
if (format == FORMAT_L8) {
|
||||||
return USED_CHANNELS_L; // Grayscale only cannot have any channel less.
|
return USED_CHANNELS_L; // Grayscale only cannot have any channel less.
|
||||||
} else if (format == FORMAT_R8 || format == FORMAT_RH || format == FORMAT_RF || format == FORMAT_R16 || format == FORMAT_R16I) {
|
} else if (format == FORMAT_R8 || format == FORMAT_RH || format == FORMAT_RF) {
|
||||||
return USED_CHANNELS_R; // Red only cannot have any channel less.
|
return USED_CHANNELS_R; // Red only cannot have any channel less.
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool supports_alpha = format == FORMAT_RGBA8 || format == FORMAT_RGBA4444 || format == FORMAT_RGBAH || format == FORMAT_RGBAF || format == FORMAT_RGBA16 || format == FORMAT_RGBA16I;
|
const bool supports_alpha = format == FORMAT_RGBA8 || format == FORMAT_RGBA4444 || format == FORMAT_RGBAH || format == FORMAT_RGBAF;
|
||||||
bool r = false, g = false, b = false, a = false, c = false;
|
bool r = false, g = false, b = false, a = false, c = false;
|
||||||
|
|
||||||
const uint8_t *data_ptr = data.ptr();
|
const uint8_t *data_ptr = data.ptr();
|
||||||
|
@ -3975,14 +3657,6 @@ void Image::_bind_methods() {
|
||||||
BIND_ENUM_CONSTANT(FORMAT_ASTC_4x4_HDR);
|
BIND_ENUM_CONSTANT(FORMAT_ASTC_4x4_HDR);
|
||||||
BIND_ENUM_CONSTANT(FORMAT_ASTC_8x8);
|
BIND_ENUM_CONSTANT(FORMAT_ASTC_8x8);
|
||||||
BIND_ENUM_CONSTANT(FORMAT_ASTC_8x8_HDR);
|
BIND_ENUM_CONSTANT(FORMAT_ASTC_8x8_HDR);
|
||||||
BIND_ENUM_CONSTANT(FORMAT_R16);
|
|
||||||
BIND_ENUM_CONSTANT(FORMAT_RG16);
|
|
||||||
BIND_ENUM_CONSTANT(FORMAT_RGB16);
|
|
||||||
BIND_ENUM_CONSTANT(FORMAT_RGBA16);
|
|
||||||
BIND_ENUM_CONSTANT(FORMAT_R16I);
|
|
||||||
BIND_ENUM_CONSTANT(FORMAT_RG16I);
|
|
||||||
BIND_ENUM_CONSTANT(FORMAT_RGB16I);
|
|
||||||
BIND_ENUM_CONSTANT(FORMAT_RGBA16I);
|
|
||||||
BIND_ENUM_CONSTANT(FORMAT_MAX);
|
BIND_ENUM_CONSTANT(FORMAT_MAX);
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(INTERPOLATE_NEAREST);
|
BIND_ENUM_CONSTANT(INTERPOLATE_NEAREST);
|
||||||
|
@ -4396,22 +4070,6 @@ uint32_t Image::get_format_component_mask(Format p_format) {
|
||||||
return rgba;
|
return rgba;
|
||||||
case FORMAT_ASTC_8x8_HDR:
|
case FORMAT_ASTC_8x8_HDR:
|
||||||
return rgba;
|
return rgba;
|
||||||
case FORMAT_R16:
|
|
||||||
return r;
|
|
||||||
case FORMAT_RG16:
|
|
||||||
return rg;
|
|
||||||
case FORMAT_RGB16:
|
|
||||||
return rgb;
|
|
||||||
case FORMAT_RGBA16:
|
|
||||||
return rgba;
|
|
||||||
case FORMAT_R16I:
|
|
||||||
return r;
|
|
||||||
case FORMAT_RG16I:
|
|
||||||
return rg;
|
|
||||||
case FORMAT_RGB16I:
|
|
||||||
return rgb;
|
|
||||||
case FORMAT_RGBA16I:
|
|
||||||
return rgba;
|
|
||||||
default:
|
default:
|
||||||
ERR_PRINT("Unhandled format.");
|
ERR_PRINT("Unhandled format.");
|
||||||
return rgba;
|
return rgba;
|
||||||
|
@ -4555,18 +4213,6 @@ void Image::average_4_rgbe9995(uint32_t &p_out, const uint32_t &p_a, const uint3
|
||||||
p_out = ((Color::from_rgbe9995(p_a) + Color::from_rgbe9995(p_b) + Color::from_rgbe9995(p_c) + Color::from_rgbe9995(p_d)) * 0.25f).to_rgbe9995();
|
p_out = ((Color::from_rgbe9995(p_a) + Color::from_rgbe9995(p_b) + Color::from_rgbe9995(p_c) + Color::from_rgbe9995(p_d)) * 0.25f).to_rgbe9995();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::average_4_uint16(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d) {
|
|
||||||
p_out = static_cast<uint16_t>((p_a + p_b + p_c + p_d + 2) >> 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Image::average_4_rgba4444(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d) {
|
|
||||||
p_out = color_to_rgba4444((color_from_rgba4444(p_a) + color_from_rgba4444(p_b) + color_from_rgba4444(p_c) + color_from_rgba4444(p_d)) * 0.25f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Image::average_4_rgb565(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d) {
|
|
||||||
p_out = color_to_rgb565((color_from_rgb565(p_a) + color_from_rgb565(p_b) + color_from_rgb565(p_c) + color_from_rgb565(p_d)) * 0.25f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Image::renormalize_uint8(uint8_t *p_rgb) {
|
void Image::renormalize_uint8(uint8_t *p_rgb) {
|
||||||
Vector3 n(p_rgb[0] / 255.0, p_rgb[1] / 255.0, p_rgb[2] / 255.0);
|
Vector3 n(p_rgb[0] / 255.0, p_rgb[1] / 255.0, p_rgb[2] / 255.0);
|
||||||
n *= 2.0;
|
n *= 2.0;
|
||||||
|
@ -4596,17 +4242,8 @@ void Image::renormalize_half(uint16_t *p_rgb) {
|
||||||
p_rgb[2] = Math::make_half_float(n.z);
|
p_rgb[2] = Math::make_half_float(n.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::renormalize_uint16(uint16_t *p_rgb) {
|
void Image::renormalize_rgbe9995(uint32_t *p_rgb) {
|
||||||
Vector3 n(p_rgb[0] / 65535.0, p_rgb[1] / 65535.0, p_rgb[2] / 65535.0);
|
// Never used.
|
||||||
n *= 2.0;
|
|
||||||
n -= Vector3(1, 1, 1);
|
|
||||||
n.normalize();
|
|
||||||
n += Vector3(1, 1, 1);
|
|
||||||
n *= 0.5;
|
|
||||||
n *= 65535;
|
|
||||||
p_rgb[0] = CLAMP(int(n.x), 0, 65535);
|
|
||||||
p_rgb[1] = CLAMP(int(n.y), 0, 65535);
|
|
||||||
p_rgb[2] = CLAMP(int(n.z), 0, 65535);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Image::Image(const uint8_t *p_mem_png_jpg, int p_len) {
|
Image::Image(const uint8_t *p_mem_png_jpg, int p_len) {
|
||||||
|
|
|
@ -111,14 +111,6 @@ public:
|
||||||
FORMAT_ASTC_4x4_HDR,
|
FORMAT_ASTC_4x4_HDR,
|
||||||
FORMAT_ASTC_8x8,
|
FORMAT_ASTC_8x8,
|
||||||
FORMAT_ASTC_8x8_HDR,
|
FORMAT_ASTC_8x8_HDR,
|
||||||
FORMAT_R16,
|
|
||||||
FORMAT_RG16,
|
|
||||||
FORMAT_RGB16,
|
|
||||||
FORMAT_RGBA16,
|
|
||||||
FORMAT_R16I,
|
|
||||||
FORMAT_RG16I,
|
|
||||||
FORMAT_RGB16I,
|
|
||||||
FORMAT_RGBA16I,
|
|
||||||
FORMAT_MAX
|
FORMAT_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -290,14 +282,10 @@ private:
|
||||||
static void average_4_float(float &p_out, const float &p_a, const float &p_b, const float &p_c, const float &p_d);
|
static void average_4_float(float &p_out, const float &p_a, const float &p_b, const float &p_c, const float &p_d);
|
||||||
static void average_4_half(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d);
|
static void average_4_half(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d);
|
||||||
static void average_4_rgbe9995(uint32_t &p_out, const uint32_t &p_a, const uint32_t &p_b, const uint32_t &p_c, const uint32_t &p_d);
|
static void average_4_rgbe9995(uint32_t &p_out, const uint32_t &p_a, const uint32_t &p_b, const uint32_t &p_c, const uint32_t &p_d);
|
||||||
static void average_4_uint16(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d);
|
|
||||||
static void average_4_rgba4444(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d);
|
|
||||||
static void average_4_rgb565(uint16_t &p_out, const uint16_t &p_a, const uint16_t &p_b, const uint16_t &p_c, const uint16_t &p_d);
|
|
||||||
|
|
||||||
static void renormalize_uint8(uint8_t *p_rgb);
|
static void renormalize_uint8(uint8_t *p_rgb);
|
||||||
static void renormalize_float(float *p_rgb);
|
static void renormalize_float(float *p_rgb);
|
||||||
static void renormalize_half(uint16_t *p_rgb);
|
static void renormalize_half(uint16_t *p_rgb);
|
||||||
static void renormalize_uint16(uint16_t *p_rgb);
|
static void renormalize_rgbe9995(uint32_t *p_rgb);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int get_width() const;
|
int get_width() const;
|
||||||
|
|
|
@ -101,8 +101,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResourceFormatLoaderImage : public ResourceFormatLoader {
|
class ResourceFormatLoaderImage : public ResourceFormatLoader {
|
||||||
GDSOFTCLASS(ResourceFormatLoaderImage, ResourceFormatLoader);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
|
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
|
||||||
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
|
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
#include "json.h"
|
#include "json.h"
|
||||||
|
|
||||||
#include "core/config/engine.h"
|
#include "core/config/engine.h"
|
||||||
#include "core/io/file_access.h"
|
|
||||||
#include "core/object/script_language.h"
|
#include "core/object/script_language.h"
|
||||||
#include "core/variant/container_type_validate.h"
|
#include "core/variant/container_type_validate.h"
|
||||||
|
|
||||||
|
@ -83,18 +82,11 @@ void JSON::_stringify(String &r_result, const Variant &p_var, const String &p_in
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_full_precision) {
|
const double magnitude = std::log10(Math::abs(num));
|
||||||
const String num_sci = String::num_scientific(num);
|
const int total_digits = p_full_precision ? 17 : 14;
|
||||||
if (num_sci.contains_char('.') || num_sci.contains_char('e')) {
|
const int precision = MAX(1, total_digits - (int)Math::floor(magnitude));
|
||||||
r_result += num_sci;
|
|
||||||
} else {
|
r_result += String::num(num, precision);
|
||||||
r_result += num_sci + ".0";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const double magnitude = std::log10(Math::abs(num));
|
|
||||||
const int precision = MAX(1, 14 - (int)Math::floor(magnitude));
|
|
||||||
r_result += String::num(num, precision);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case Variant::PACKED_INT32_ARRAY:
|
case Variant::PACKED_INT32_ARRAY:
|
||||||
|
|
|
@ -107,8 +107,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResourceFormatLoaderJSON : public ResourceFormatLoader {
|
class ResourceFormatLoaderJSON : public ResourceFormatLoader {
|
||||||
GDSOFTCLASS(ResourceFormatLoaderJSON, ResourceFormatLoader);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
|
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
|
||||||
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
|
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
|
||||||
|
@ -121,8 +119,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResourceFormatSaverJSON : public ResourceFormatSaver {
|
class ResourceFormatSaverJSON : public ResourceFormatSaver {
|
||||||
GDSOFTCLASS(ResourceFormatSaverJSON, ResourceFormatSaver);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0) override;
|
virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0) override;
|
||||||
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const override;
|
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const override;
|
||||||
|
|
|
@ -32,8 +32,6 @@
|
||||||
|
|
||||||
#include "core/core_globals.h"
|
#include "core/core_globals.h"
|
||||||
#include "core/io/dir_access.h"
|
#include "core/io/dir_access.h"
|
||||||
#include "core/io/file_access.h"
|
|
||||||
#include "core/object/script_backtrace.h"
|
|
||||||
#include "core/os/time.h"
|
#include "core/os/time.h"
|
||||||
#include "core/templates/rb_set.h"
|
#include "core/templates/rb_set.h"
|
||||||
|
|
||||||
|
|
|
@ -30,15 +30,14 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/object/ref_counted.h"
|
#include "core/io/file_access.h"
|
||||||
|
#include "core/object/script_backtrace.h"
|
||||||
#include "core/string/ustring.h"
|
#include "core/string/ustring.h"
|
||||||
#include "core/templates/vector.h"
|
#include "core/templates/vector.h"
|
||||||
|
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
|
||||||
class FileAccess;
|
|
||||||
class RegEx;
|
class RegEx;
|
||||||
class ScriptBacktrace;
|
|
||||||
|
|
||||||
class Logger {
|
class Logger {
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -34,8 +34,6 @@
|
||||||
#include "core/object/ref_counted.h"
|
#include "core/object/ref_counted.h"
|
||||||
|
|
||||||
class NetSocket : public RefCounted {
|
class NetSocket : public RefCounted {
|
||||||
GDSOFTCLASS(NetSocket, RefCounted);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static NetSocket *(*_create)();
|
static NetSocket *(*_create)();
|
||||||
|
|
||||||
|
@ -54,61 +52,21 @@ public:
|
||||||
TYPE_UDP,
|
TYPE_UDP,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Family {
|
virtual Error open(Type p_type, IP::Type &ip_type) = 0;
|
||||||
NONE,
|
|
||||||
INET,
|
|
||||||
UNIX,
|
|
||||||
};
|
|
||||||
|
|
||||||
class Address {
|
|
||||||
Family _family = Family::NONE;
|
|
||||||
CharString _path;
|
|
||||||
IPAddress _ip;
|
|
||||||
uint16_t _port = 0;
|
|
||||||
|
|
||||||
public:
|
|
||||||
_FORCE_INLINE_ Family get_family() const { return _family; }
|
|
||||||
_FORCE_INLINE_ bool is_inet() const { return _family == Family::INET; }
|
|
||||||
_FORCE_INLINE_ bool is_unix() const { return _family == Family::UNIX; }
|
|
||||||
_FORCE_INLINE_ bool is_valid() const { return is_inet() || is_unix(); }
|
|
||||||
|
|
||||||
_FORCE_INLINE_ const IPAddress &ip() const { return _ip; }
|
|
||||||
_FORCE_INLINE_ const uint16_t &port() const { return _port; }
|
|
||||||
|
|
||||||
_FORCE_INLINE_ const CharString &get_path() const { return _path; }
|
|
||||||
|
|
||||||
Address() {}
|
|
||||||
|
|
||||||
Address(const IPAddress &p_addr, uint16_t p_port) :
|
|
||||||
_family(Family::INET) {
|
|
||||||
_ip = p_addr;
|
|
||||||
_port = p_port;
|
|
||||||
}
|
|
||||||
|
|
||||||
Address(const String &p_path) :
|
|
||||||
_family(Family::UNIX), _path(p_path.utf8()) {
|
|
||||||
}
|
|
||||||
|
|
||||||
Address(const CharString &p_path) :
|
|
||||||
_family(Family::UNIX), _path(p_path) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual Error open(Family p_family, Type p_type, IP::Type &r_ip_type) = 0;
|
|
||||||
virtual void close() = 0;
|
virtual void close() = 0;
|
||||||
virtual Error bind(Address p_addr) = 0;
|
virtual Error bind(IPAddress p_addr, uint16_t p_port) = 0;
|
||||||
virtual Error listen(int p_max_pending) = 0;
|
virtual Error listen(int p_max_pending) = 0;
|
||||||
virtual Error connect_to_host(Address p_addr) = 0;
|
virtual Error connect_to_host(IPAddress p_addr, uint16_t p_port) = 0;
|
||||||
virtual Error poll(PollType p_type, int timeout) const = 0;
|
virtual Error poll(PollType p_type, int timeout) const = 0;
|
||||||
virtual Error recv(uint8_t *p_buffer, int p_len, int &r_read) = 0;
|
virtual Error recv(uint8_t *p_buffer, int p_len, int &r_read) = 0;
|
||||||
virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port, bool p_peek = false) = 0;
|
virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port, bool p_peek = false) = 0;
|
||||||
virtual Error send(const uint8_t *p_buffer, int p_len, int &r_sent) = 0;
|
virtual Error send(const uint8_t *p_buffer, int p_len, int &r_sent) = 0;
|
||||||
virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) = 0;
|
virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) = 0;
|
||||||
virtual Ref<NetSocket> accept(Address &r_addr) = 0;
|
virtual Ref<NetSocket> accept(IPAddress &r_ip, uint16_t &r_port) = 0;
|
||||||
|
|
||||||
virtual bool is_open() const = 0;
|
virtual bool is_open() const = 0;
|
||||||
virtual int get_available_bytes() const = 0;
|
virtual int get_available_bytes() const = 0;
|
||||||
virtual Error get_socket_address(Address *r_addr) const = 0;
|
virtual Error get_socket_address(IPAddress *r_ip, uint16_t *r_port) const = 0;
|
||||||
|
|
||||||
virtual Error set_broadcasting_enabled(bool p_enabled) = 0; // Returns OK if the socket option has been set successfully.
|
virtual Error set_broadcasting_enabled(bool p_enabled) = 0; // Returns OK if the socket option has been set successfully.
|
||||||
virtual void set_blocking_enabled(bool p_enabled) = 0;
|
virtual void set_blocking_enabled(bool p_enabled) = 0;
|
||||||
|
|
|
@ -52,7 +52,7 @@ Error PacketPeerUDP::join_multicast_group(IPAddress p_multi_address, const Strin
|
||||||
|
|
||||||
if (!_sock->is_open()) {
|
if (!_sock->is_open()) {
|
||||||
IP::Type ip_type = p_multi_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
IP::Type ip_type = p_multi_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
||||||
Error err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_UDP, ip_type);
|
Error err = _sock->open(NetSocket::TYPE_UDP, ip_type);
|
||||||
ERR_FAIL_COND_V(err != OK, err);
|
ERR_FAIL_COND_V(err != OK, err);
|
||||||
_sock->set_blocking_enabled(false);
|
_sock->set_blocking_enabled(false);
|
||||||
_sock->set_broadcasting_enabled(broadcast);
|
_sock->set_broadcasting_enabled(broadcast);
|
||||||
|
@ -141,7 +141,7 @@ Error PacketPeerUDP::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
|
||||||
|
|
||||||
if (!_sock->is_open()) {
|
if (!_sock->is_open()) {
|
||||||
IP::Type ip_type = peer_addr.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
IP::Type ip_type = peer_addr.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
||||||
err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_UDP, ip_type);
|
err = _sock->open(NetSocket::TYPE_UDP, ip_type);
|
||||||
ERR_FAIL_COND_V(err != OK, err);
|
ERR_FAIL_COND_V(err != OK, err);
|
||||||
_sock->set_blocking_enabled(false);
|
_sock->set_blocking_enabled(false);
|
||||||
_sock->set_broadcasting_enabled(broadcast);
|
_sock->set_broadcasting_enabled(broadcast);
|
||||||
|
@ -186,7 +186,7 @@ Error PacketPeerUDP::bind(int p_port, const IPAddress &p_bind_address, int p_rec
|
||||||
ip_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
ip_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_UDP, ip_type);
|
err = _sock->open(NetSocket::TYPE_UDP, ip_type);
|
||||||
|
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return ERR_CANT_CREATE;
|
return ERR_CANT_CREATE;
|
||||||
|
@ -194,8 +194,7 @@ Error PacketPeerUDP::bind(int p_port, const IPAddress &p_bind_address, int p_rec
|
||||||
|
|
||||||
_sock->set_blocking_enabled(false);
|
_sock->set_blocking_enabled(false);
|
||||||
_sock->set_broadcasting_enabled(broadcast);
|
_sock->set_broadcasting_enabled(broadcast);
|
||||||
NetSocket::Address addr(p_bind_address, p_port);
|
err = _sock->bind(p_bind_address, p_port);
|
||||||
err = _sock->bind(addr);
|
|
||||||
|
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
_sock->close();
|
_sock->close();
|
||||||
|
@ -232,13 +231,12 @@ Error PacketPeerUDP::connect_to_host(const IPAddress &p_host, int p_port) {
|
||||||
|
|
||||||
if (!_sock->is_open()) {
|
if (!_sock->is_open()) {
|
||||||
IP::Type ip_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
IP::Type ip_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
||||||
err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_UDP, ip_type);
|
err = _sock->open(NetSocket::TYPE_UDP, ip_type);
|
||||||
ERR_FAIL_COND_V(err != OK, ERR_CANT_OPEN);
|
ERR_FAIL_COND_V(err != OK, ERR_CANT_OPEN);
|
||||||
_sock->set_blocking_enabled(false);
|
_sock->set_blocking_enabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
NetSocket::Address addr(p_host, p_port);
|
err = _sock->connect_to_host(p_host, p_port);
|
||||||
err = _sock->connect_to_host(addr);
|
|
||||||
|
|
||||||
// I see no reason why we should get ERR_BUSY (wouldblock/eagain) here.
|
// I see no reason why we should get ERR_BUSY (wouldblock/eagain) here.
|
||||||
// This is UDP, so connect is only used to tell the OS to which socket
|
// This is UDP, so connect is only used to tell the OS to which socket
|
||||||
|
@ -347,9 +345,9 @@ int PacketPeerUDP::get_packet_port() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
int PacketPeerUDP::get_local_port() const {
|
int PacketPeerUDP::get_local_port() const {
|
||||||
NetSocket::Address addr;
|
uint16_t local_port;
|
||||||
_sock->get_socket_address(&addr);
|
_sock->get_socket_address(nullptr, &local_port);
|
||||||
return addr.port();
|
return local_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacketPeerUDP::set_dest_address(const IPAddress &p_address, int p_port) {
|
void PacketPeerUDP::set_dest_address(const IPAddress &p_address, int p_port) {
|
||||||
|
|
|
@ -37,8 +37,6 @@
|
||||||
class PListNode;
|
class PListNode;
|
||||||
|
|
||||||
class PList : public RefCounted {
|
class PList : public RefCounted {
|
||||||
GDSOFTCLASS(PList, RefCounted);
|
|
||||||
|
|
||||||
friend class PListNode;
|
friend class PListNode;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -660,10 +660,6 @@ void Resource::reset_local_to_scene() {
|
||||||
// Restores the state as if setup_local_to_scene() hadn't been called.
|
// Restores the state as if setup_local_to_scene() hadn't been called.
|
||||||
}
|
}
|
||||||
|
|
||||||
String Resource::_to_string() {
|
|
||||||
return (name.is_empty() ? "" : String(name) + " ") + "(" + path_cache + "):" + Object::_to_string();
|
|
||||||
}
|
|
||||||
|
|
||||||
Node *(*Resource::_get_local_scene_func)() = nullptr;
|
Node *(*Resource::_get_local_scene_func)() = nullptr;
|
||||||
void (*Resource::_update_configuration_warning)() = nullptr;
|
void (*Resource::_update_configuration_warning)() = nullptr;
|
||||||
|
|
||||||
|
@ -762,9 +758,7 @@ void Resource::_bind_methods() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Resource::Resource() :
|
Resource::Resource() :
|
||||||
remapped_list(this) {
|
remapped_list(this) {}
|
||||||
_define_ancestry(AncestralClass::RESOURCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
Resource::~Resource() {
|
Resource::~Resource() {
|
||||||
if (unlikely(path_cache.is_empty())) {
|
if (unlikely(path_cache.is_empty())) {
|
||||||
|
|
|
@ -54,8 +54,6 @@ class Resource : public RefCounted {
|
||||||
GDCLASS(Resource, RefCounted);
|
GDCLASS(Resource, RefCounted);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr AncestralClass static_ancestral_class = AncestralClass::RESOURCE;
|
|
||||||
|
|
||||||
static void register_custom_data_to_otdb() { ClassDB::add_resource_base_extension("res", get_class_static()); }
|
static void register_custom_data_to_otdb() { ClassDB::add_resource_base_extension("res", get_class_static()); }
|
||||||
virtual String get_base_extension() const { return "res"; }
|
virtual String get_base_extension() const { return "res"; }
|
||||||
|
|
||||||
|
@ -122,7 +120,6 @@ protected:
|
||||||
GDVIRTUAL0(_reset_state);
|
GDVIRTUAL0(_reset_state);
|
||||||
|
|
||||||
virtual Ref<Resource> _duplicate(const DuplicateParams &p_params) const;
|
virtual Ref<Resource> _duplicate(const DuplicateParams &p_params) const;
|
||||||
virtual String _to_string() override;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Node *(*_get_local_scene_func)(); // Used by the editor.
|
static Node *(*_get_local_scene_func)(); // Used by the editor.
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
#include "core/io/file_access.h"
|
#include "core/io/file_access.h"
|
||||||
#include "core/io/resource_loader.h"
|
#include "core/io/resource_loader.h"
|
||||||
#include "core/io/resource_saver.h"
|
#include "core/io/resource_saver.h"
|
||||||
#include "core/templates/rb_map.h"
|
|
||||||
|
|
||||||
class ResourceLoaderBinary {
|
class ResourceLoaderBinary {
|
||||||
bool translation_remapped = false;
|
bool translation_remapped = false;
|
||||||
|
@ -109,8 +108,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResourceFormatLoaderBinary : public ResourceFormatLoader {
|
class ResourceFormatLoaderBinary : public ResourceFormatLoader {
|
||||||
GDSOFTCLASS(ResourceFormatLoaderBinary, ResourceFormatLoader);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
|
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
|
||||||
virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const override;
|
virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const override;
|
||||||
|
@ -182,8 +179,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResourceFormatSaverBinary : public ResourceFormatSaver {
|
class ResourceFormatSaverBinary : public ResourceFormatSaver {
|
||||||
GDSOFTCLASS(ResourceFormatSaverBinary, ResourceFormatSaver);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static inline ResourceFormatSaverBinary *singleton = nullptr;
|
static inline ResourceFormatSaverBinary *singleton = nullptr;
|
||||||
virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0) override;
|
virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0) override;
|
||||||
|
|
|
@ -39,8 +39,6 @@ class ResourceFormatImporter;
|
||||||
typedef Ref<Resource> (*ResourceFormatImporterLoadOnStartup)(ResourceFormatImporter *p_importer, const String &p_path, Error *r_error, bool p_use_sub_threads, float *r_progress, ResourceFormatLoader::CacheMode p_cache_mode);
|
typedef Ref<Resource> (*ResourceFormatImporterLoadOnStartup)(ResourceFormatImporter *p_importer, const String &p_path, Error *r_error, bool p_use_sub_threads, float *r_progress, ResourceFormatLoader::CacheMode p_cache_mode);
|
||||||
|
|
||||||
class ResourceFormatImporter : public ResourceFormatLoader {
|
class ResourceFormatImporter : public ResourceFormatLoader {
|
||||||
GDSOFTCLASS(ResourceFormatImporter, ResourceFormatLoader);
|
|
||||||
|
|
||||||
struct PathAndType {
|
struct PathAndType {
|
||||||
String path;
|
String path;
|
||||||
String type;
|
String type;
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
#include "core/string/translation_server.h"
|
#include "core/string/translation_server.h"
|
||||||
#include "core/templates/rb_set.h"
|
#include "core/templates/rb_set.h"
|
||||||
#include "core/variant/variant_parser.h"
|
#include "core/variant/variant_parser.h"
|
||||||
#include "servers/rendering/rendering_server.h"
|
#include "servers/rendering_server.h"
|
||||||
|
|
||||||
#ifdef DEBUG_LOAD_THREADED
|
#ifdef DEBUG_LOAD_THREADED
|
||||||
#define print_lt(m_text) print_line(m_text)
|
#define print_lt(m_text) print_line(m_text)
|
||||||
|
@ -174,7 +174,7 @@ Ref<Resource> ResourceFormatLoader::load(const String &p_path, const String &p_o
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ref<Resource>();
|
ERR_FAIL_V_MSG(Ref<Resource>(), vformat("Failed to load resource '%s'. ResourceFormatLoader::load was not implemented for this resource type.", p_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
|
void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
|
||||||
|
@ -1465,8 +1465,8 @@ void ResourceLoader::add_custom_loaders() {
|
||||||
|
|
||||||
String custom_loader_base_class = ResourceFormatLoader::get_class_static();
|
String custom_loader_base_class = ResourceFormatLoader::get_class_static();
|
||||||
|
|
||||||
LocalVector<StringName> global_classes;
|
List<StringName> global_classes;
|
||||||
ScriptServer::get_global_class_list(global_classes);
|
ScriptServer::get_global_class_list(&global_classes);
|
||||||
|
|
||||||
for (const StringName &class_name : global_classes) {
|
for (const StringName &class_name : global_classes) {
|
||||||
StringName base_class = ScriptServer::get_global_class_native_base(class_name);
|
StringName base_class = ScriptServer::get_global_class_native_base(class_name);
|
||||||
|
|
|
@ -70,7 +70,7 @@ protected:
|
||||||
GDVIRTUAL2RC(Error, _rename_dependencies, String, Dictionary)
|
GDVIRTUAL2RC(Error, _rename_dependencies, String, Dictionary)
|
||||||
GDVIRTUAL1RC(bool, _exists, String)
|
GDVIRTUAL1RC(bool, _exists, String)
|
||||||
|
|
||||||
GDVIRTUAL4RC_REQUIRED(Variant, _load, String, String, bool, int)
|
GDVIRTUAL4RC(Variant, _load, String, String, bool, int)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
|
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
|
||||||
|
|
|
@ -255,8 +255,8 @@ void ResourceSaver::add_custom_savers() {
|
||||||
|
|
||||||
String custom_saver_base_class = ResourceFormatSaver::get_class_static();
|
String custom_saver_base_class = ResourceFormatSaver::get_class_static();
|
||||||
|
|
||||||
LocalVector<StringName> global_classes;
|
List<StringName> global_classes;
|
||||||
ScriptServer::get_global_class_list(global_classes);
|
ScriptServer::get_global_class_list(&global_classes);
|
||||||
|
|
||||||
for (const StringName &class_name : global_classes) {
|
for (const StringName &class_name : global_classes) {
|
||||||
StringName base_class = ScriptServer::get_global_class_native_base(class_name);
|
StringName base_class = ScriptServer::get_global_class_native_base(class_name);
|
||||||
|
|
|
@ -47,7 +47,7 @@ String ResourceUID::get_cache_file() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr uint8_t uuid_characters[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', '0', '1', '2', '3', '4', '5', '6', '7', '8' };
|
static constexpr uint8_t uuid_characters[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', '0', '1', '2', '3', '4', '5', '6', '7', '8' };
|
||||||
static constexpr uint32_t uuid_characters_element_count = std_size(uuid_characters);
|
static constexpr uint32_t uuid_characters_element_count = std::size(uuid_characters);
|
||||||
static constexpr uint8_t max_uuid_number_length = 13; // Max 0x7FFFFFFFFFFFFFFF (uid://d4n4ub6itg400) size is 13 characters.
|
static constexpr uint8_t max_uuid_number_length = 13; // Max 0x7FFFFFFFFFFFFFFF (uid://d4n4ub6itg400) size is 13 characters.
|
||||||
|
|
||||||
String ResourceUID::id_to_text(ID p_id) const {
|
String ResourceUID::id_to_text(ID p_id) const {
|
||||||
|
@ -351,7 +351,6 @@ void ResourceUID::clear() {
|
||||||
unique_ids.clear();
|
unique_ids.clear();
|
||||||
changed = false;
|
changed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceUID::_bind_methods() {
|
void ResourceUID::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("id_to_text", "id"), &ResourceUID::id_to_text);
|
ClassDB::bind_method(D_METHOD("id_to_text", "id"), &ResourceUID::id_to_text);
|
||||||
ClassDB::bind_method(D_METHOD("text_to_id", "text_id"), &ResourceUID::text_to_id);
|
ClassDB::bind_method(D_METHOD("text_to_id", "text_id"), &ResourceUID::text_to_id);
|
||||||
|
|
|
@ -1,90 +0,0 @@
|
||||||
/**************************************************************************/
|
|
||||||
/* socket_server.cpp */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
|
||||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
#include "socket_server.h"
|
|
||||||
|
|
||||||
void SocketServer::_bind_methods() {
|
|
||||||
ClassDB::bind_method(D_METHOD("is_connection_available"), &SocketServer::is_connection_available);
|
|
||||||
ClassDB::bind_method(D_METHOD("is_listening"), &SocketServer::is_listening);
|
|
||||||
ClassDB::bind_method(D_METHOD("stop"), &SocketServer::stop);
|
|
||||||
ClassDB::bind_method(D_METHOD("take_socket_connection"), &SocketServer::take_socket_connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
Error SocketServer::_listen(const NetSocket::Address &p_addr) {
|
|
||||||
DEV_ASSERT(_sock.is_valid());
|
|
||||||
DEV_ASSERT(_sock->is_open());
|
|
||||||
|
|
||||||
_sock->set_blocking_enabled(false);
|
|
||||||
Error err = _sock->bind(p_addr);
|
|
||||||
|
|
||||||
if (err != OK) {
|
|
||||||
_sock->close();
|
|
||||||
return ERR_ALREADY_IN_USE;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = _sock->listen(MAX_PENDING_CONNECTIONS);
|
|
||||||
|
|
||||||
if (err != OK) {
|
|
||||||
_sock->close();
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SocketServer::is_listening() const {
|
|
||||||
ERR_FAIL_COND_V(_sock.is_null(), false);
|
|
||||||
|
|
||||||
return _sock->is_open();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SocketServer::is_connection_available() const {
|
|
||||||
ERR_FAIL_COND_V(_sock.is_null(), false);
|
|
||||||
|
|
||||||
if (!_sock->is_open()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Error err = _sock->poll(NetSocket::POLL_TYPE_IN, 0);
|
|
||||||
return (err == OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SocketServer::stop() {
|
|
||||||
if (_sock.is_valid()) {
|
|
||||||
_sock->close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SocketServer::SocketServer() :
|
|
||||||
_sock(NetSocket::create()) {
|
|
||||||
}
|
|
||||||
|
|
||||||
SocketServer::~SocketServer() {
|
|
||||||
stop();
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
/**************************************************************************/
|
|
||||||
/* socket_server.h */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
|
||||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/io/net_socket.h"
|
|
||||||
#include "core/io/stream_peer_socket.h"
|
|
||||||
|
|
||||||
class SocketServer : public RefCounted {
|
|
||||||
GDCLASS(SocketServer, RefCounted);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
enum {
|
|
||||||
MAX_PENDING_CONNECTIONS = 8,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ref<NetSocket> _sock;
|
|
||||||
static void _bind_methods();
|
|
||||||
|
|
||||||
Error _listen(const NetSocket::Address &p_addr);
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
Ref<T> _take_connection() {
|
|
||||||
Ref<T> conn;
|
|
||||||
if (!is_connection_available()) {
|
|
||||||
return conn;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<NetSocket> ns;
|
|
||||||
NetSocket::Address addr;
|
|
||||||
ns = _sock->accept(addr);
|
|
||||||
if (ns.is_null()) {
|
|
||||||
return conn;
|
|
||||||
}
|
|
||||||
|
|
||||||
conn.instantiate();
|
|
||||||
conn->accept_socket(ns, addr);
|
|
||||||
return conn;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool is_listening() const;
|
|
||||||
bool is_connection_available() const;
|
|
||||||
virtual Ref<StreamPeerSocket> take_socket_connection() = 0;
|
|
||||||
|
|
||||||
void stop(); // Stop listening
|
|
||||||
|
|
||||||
SocketServer();
|
|
||||||
~SocketServer();
|
|
||||||
};
|
|
|
@ -1,52 +0,0 @@
|
||||||
/**************************************************************************/
|
|
||||||
/* stream_peer_socket.compat.inc */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
|
||||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
#ifndef DISABLE_DEPRECATED
|
|
||||||
|
|
||||||
namespace compat::StreamPeerTCP {
|
|
||||||
enum class Status {
|
|
||||||
STATUS_NONE = StreamPeerSocket::STATUS_NONE,
|
|
||||||
STATUS_CONNECTING = StreamPeerSocket::STATUS_CONNECTING,
|
|
||||||
STATUS_CONNECTED = StreamPeerSocket::STATUS_CONNECTED,
|
|
||||||
STATUS_ERROR = StreamPeerSocket::STATUS_ERROR,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
VARIANT_ENUM_CAST(compat::StreamPeerTCP::Status);
|
|
||||||
|
|
||||||
compat::StreamPeerTCP::Status StreamPeerSocket::_get_status_compat_107954() const {
|
|
||||||
return (compat::StreamPeerTCP::Status)get_status();
|
|
||||||
}
|
|
||||||
|
|
||||||
void StreamPeerSocket::_bind_compatibility_methods() {
|
|
||||||
ClassDB::bind_compatibility_method(D_METHOD("get_status"), &StreamPeerSocket::_get_status_compat_107954);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,236 +0,0 @@
|
||||||
/**************************************************************************/
|
|
||||||
/* stream_peer_socket.cpp */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
|
||||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
#include "stream_peer_socket.h"
|
|
||||||
#include "stream_peer_socket.compat.inc"
|
|
||||||
|
|
||||||
Error StreamPeerSocket::poll() {
|
|
||||||
if (status == STATUS_CONNECTED) {
|
|
||||||
Error err;
|
|
||||||
err = _sock->poll(NetSocket::POLL_TYPE_IN, 0);
|
|
||||||
if (err == OK) {
|
|
||||||
// FIN received
|
|
||||||
if (_sock->get_available_bytes() == 0) {
|
|
||||||
disconnect_from_host();
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Also poll write
|
|
||||||
err = _sock->poll(NetSocket::POLL_TYPE_IN_OUT, 0);
|
|
||||||
if (err != OK && err != ERR_BUSY) {
|
|
||||||
// Got an error
|
|
||||||
disconnect_from_host();
|
|
||||||
status = STATUS_ERROR;
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
return OK;
|
|
||||||
} else if (status != STATUS_CONNECTING) {
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
Error err = _sock->connect_to_host(peer_address);
|
|
||||||
|
|
||||||
if (err == OK) {
|
|
||||||
status = STATUS_CONNECTED;
|
|
||||||
return OK;
|
|
||||||
} else if (err == ERR_BUSY) {
|
|
||||||
// Check for connect timeout
|
|
||||||
if (OS::get_singleton()->get_ticks_msec() > timeout) {
|
|
||||||
disconnect_from_host();
|
|
||||||
status = STATUS_ERROR;
|
|
||||||
return ERR_CONNECTION_ERROR;
|
|
||||||
}
|
|
||||||
// Still trying to connect
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
disconnect_from_host();
|
|
||||||
status = STATUS_ERROR;
|
|
||||||
return ERR_CONNECTION_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
Error StreamPeerSocket::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block) {
|
|
||||||
ERR_FAIL_COND_V(_sock.is_null(), ERR_UNAVAILABLE);
|
|
||||||
|
|
||||||
if (status != STATUS_CONNECTED) {
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
Error err;
|
|
||||||
int data_to_send = p_bytes;
|
|
||||||
const uint8_t *offset = p_data;
|
|
||||||
int total_sent = 0;
|
|
||||||
|
|
||||||
while (data_to_send) {
|
|
||||||
int sent_amount = 0;
|
|
||||||
err = _sock->send(offset, data_to_send, sent_amount);
|
|
||||||
|
|
||||||
if (err != OK) {
|
|
||||||
if (err != ERR_BUSY) {
|
|
||||||
disconnect_from_host();
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!p_block) {
|
|
||||||
r_sent = total_sent;
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Block and wait for the socket to accept more data
|
|
||||||
err = _sock->poll(NetSocket::POLL_TYPE_OUT, -1);
|
|
||||||
if (err != OK) {
|
|
||||||
disconnect_from_host();
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
data_to_send -= sent_amount;
|
|
||||||
offset += sent_amount;
|
|
||||||
total_sent += sent_amount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r_sent = total_sent;
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
Error StreamPeerSocket::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block) {
|
|
||||||
if (status != STATUS_CONNECTED) {
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
Error err;
|
|
||||||
int to_read = p_bytes;
|
|
||||||
int total_read = 0;
|
|
||||||
r_received = 0;
|
|
||||||
|
|
||||||
while (to_read) {
|
|
||||||
int read = 0;
|
|
||||||
err = _sock->recv(p_buffer + total_read, to_read, read);
|
|
||||||
|
|
||||||
if (err != OK) {
|
|
||||||
if (err != ERR_BUSY) {
|
|
||||||
disconnect_from_host();
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!p_block) {
|
|
||||||
r_received = total_read;
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = _sock->poll(NetSocket::POLL_TYPE_IN, -1);
|
|
||||||
|
|
||||||
if (err != OK) {
|
|
||||||
disconnect_from_host();
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (read == 0) {
|
|
||||||
disconnect_from_host();
|
|
||||||
r_received = total_read;
|
|
||||||
return ERR_FILE_EOF;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
to_read -= read;
|
|
||||||
total_read += read;
|
|
||||||
|
|
||||||
if (!p_block) {
|
|
||||||
r_received = total_read;
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r_received = total_read;
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamPeerSocket::Status StreamPeerSocket::get_status() const {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StreamPeerSocket::disconnect_from_host() {
|
|
||||||
if (_sock.is_valid() && _sock->is_open()) {
|
|
||||||
_sock->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout = 0;
|
|
||||||
status = STATUS_NONE;
|
|
||||||
peer_address = NetSocket::Address();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error StreamPeerSocket::wait(NetSocket::PollType p_type, int p_timeout) {
|
|
||||||
ERR_FAIL_COND_V(_sock.is_null() || !_sock->is_open(), ERR_UNAVAILABLE);
|
|
||||||
return _sock->poll(p_type, p_timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
Error StreamPeerSocket::put_data(const uint8_t *p_data, int p_bytes) {
|
|
||||||
int total;
|
|
||||||
return write(p_data, p_bytes, total, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Error StreamPeerSocket::put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) {
|
|
||||||
return write(p_data, p_bytes, r_sent, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
Error StreamPeerSocket::get_data(uint8_t *p_buffer, int p_bytes) {
|
|
||||||
int total;
|
|
||||||
return read(p_buffer, p_bytes, total, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Error StreamPeerSocket::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) {
|
|
||||||
return read(p_buffer, p_bytes, r_received, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
int StreamPeerSocket::get_available_bytes() const {
|
|
||||||
ERR_FAIL_COND_V(_sock.is_null(), -1);
|
|
||||||
return _sock->get_available_bytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
void StreamPeerSocket::_bind_methods() {
|
|
||||||
ClassDB::bind_method(D_METHOD("poll"), &StreamPeerSocket::poll);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_status"), &StreamPeerSocket::get_status);
|
|
||||||
ClassDB::bind_method(D_METHOD("disconnect_from_host"), &StreamPeerSocket::disconnect_from_host);
|
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(STATUS_NONE);
|
|
||||||
BIND_ENUM_CONSTANT(STATUS_CONNECTING);
|
|
||||||
BIND_ENUM_CONSTANT(STATUS_CONNECTED);
|
|
||||||
BIND_ENUM_CONSTANT(STATUS_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamPeerSocket::StreamPeerSocket() :
|
|
||||||
_sock(NetSocket::create()) {
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamPeerSocket::~StreamPeerSocket() {
|
|
||||||
disconnect_from_host();
|
|
||||||
}
|
|
|
@ -1,93 +0,0 @@
|
||||||
/**************************************************************************/
|
|
||||||
/* stream_peer_socket.h */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
|
||||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/io/net_socket.h"
|
|
||||||
#include "core/io/stream_peer.h"
|
|
||||||
|
|
||||||
#ifndef DISABLE_DEPRECATED
|
|
||||||
namespace compat::StreamPeerTCP {
|
|
||||||
enum class Status;
|
|
||||||
} //namespace compat::StreamPeerTCP
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class StreamPeerSocket : public StreamPeer {
|
|
||||||
GDCLASS(StreamPeerSocket, StreamPeer);
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum Status {
|
|
||||||
STATUS_NONE,
|
|
||||||
STATUS_CONNECTING,
|
|
||||||
STATUS_CONNECTED,
|
|
||||||
STATUS_ERROR,
|
|
||||||
};
|
|
||||||
|
|
||||||
protected:
|
|
||||||
#ifndef DISABLE_DEPRECATED
|
|
||||||
compat::StreamPeerTCP::Status _get_status_compat_107954() const;
|
|
||||||
static void _bind_compatibility_methods();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Ref<NetSocket> _sock;
|
|
||||||
uint64_t timeout = 0;
|
|
||||||
Status status = STATUS_NONE;
|
|
||||||
NetSocket::Address peer_address;
|
|
||||||
|
|
||||||
Error write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block);
|
|
||||||
Error read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block);
|
|
||||||
|
|
||||||
static void _bind_methods();
|
|
||||||
|
|
||||||
public:
|
|
||||||
virtual void accept_socket(Ref<NetSocket> p_sock, const NetSocket::Address &p_addr) = 0;
|
|
||||||
|
|
||||||
void disconnect_from_host();
|
|
||||||
|
|
||||||
int get_available_bytes() const override;
|
|
||||||
Status get_status() const;
|
|
||||||
|
|
||||||
// Poll socket updating its state.
|
|
||||||
Error poll();
|
|
||||||
|
|
||||||
// Wait or check for writable, readable.
|
|
||||||
Error wait(NetSocket::PollType p_type, int p_timeout = 0);
|
|
||||||
|
|
||||||
// Read/Write from StreamPeer
|
|
||||||
Error put_data(const uint8_t *p_data, int p_bytes) override;
|
|
||||||
Error put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) override;
|
|
||||||
Error get_data(uint8_t *p_buffer, int p_bytes) override;
|
|
||||||
Error get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) override;
|
|
||||||
|
|
||||||
StreamPeerSocket();
|
|
||||||
virtual ~StreamPeerSocket();
|
|
||||||
};
|
|
||||||
|
|
||||||
VARIANT_ENUM_CAST(StreamPeerSocket::Status);
|
|
|
@ -32,14 +32,60 @@
|
||||||
|
|
||||||
#include "core/config/project_settings.h"
|
#include "core/config/project_settings.h"
|
||||||
|
|
||||||
void StreamPeerTCP::accept_socket(Ref<NetSocket> p_sock, const NetSocket::Address &p_addr) {
|
Error StreamPeerTCP::poll() {
|
||||||
|
if (status == STATUS_CONNECTED) {
|
||||||
|
Error err;
|
||||||
|
err = _sock->poll(NetSocket::POLL_TYPE_IN, 0);
|
||||||
|
if (err == OK) {
|
||||||
|
// FIN received
|
||||||
|
if (_sock->get_available_bytes() == 0) {
|
||||||
|
disconnect_from_host();
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Also poll write
|
||||||
|
err = _sock->poll(NetSocket::POLL_TYPE_IN_OUT, 0);
|
||||||
|
if (err != OK && err != ERR_BUSY) {
|
||||||
|
// Got an error
|
||||||
|
disconnect_from_host();
|
||||||
|
status = STATUS_ERROR;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
} else if (status != STATUS_CONNECTING) {
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error err = _sock->connect_to_host(peer_host, peer_port);
|
||||||
|
|
||||||
|
if (err == OK) {
|
||||||
|
status = STATUS_CONNECTED;
|
||||||
|
return OK;
|
||||||
|
} else if (err == ERR_BUSY) {
|
||||||
|
// Check for connect timeout
|
||||||
|
if (OS::get_singleton()->get_ticks_msec() > timeout) {
|
||||||
|
disconnect_from_host();
|
||||||
|
status = STATUS_ERROR;
|
||||||
|
return ERR_CONNECTION_ERROR;
|
||||||
|
}
|
||||||
|
// Still trying to connect
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnect_from_host();
|
||||||
|
status = STATUS_ERROR;
|
||||||
|
return ERR_CONNECTION_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamPeerTCP::accept_socket(Ref<NetSocket> p_sock, IPAddress p_host, uint16_t p_port) {
|
||||||
_sock = p_sock;
|
_sock = p_sock;
|
||||||
_sock->set_blocking_enabled(false);
|
_sock->set_blocking_enabled(false);
|
||||||
|
|
||||||
timeout = OS::get_singleton()->get_ticks_msec() + (((uint64_t)GLOBAL_GET("network/limits/tcp/connect_timeout_seconds")) * 1000);
|
timeout = OS::get_singleton()->get_ticks_msec() + (((uint64_t)GLOBAL_GET("network/limits/tcp/connect_timeout_seconds")) * 1000);
|
||||||
status = STATUS_CONNECTED;
|
status = STATUS_CONNECTED;
|
||||||
|
|
||||||
peer_address = p_addr;
|
peer_host = p_host;
|
||||||
|
peer_port = p_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error StreamPeerTCP::bind(int p_port, const IPAddress &p_host) {
|
Error StreamPeerTCP::bind(int p_port, const IPAddress &p_host) {
|
||||||
|
@ -51,13 +97,12 @@ Error StreamPeerTCP::bind(int p_port, const IPAddress &p_host) {
|
||||||
if (p_host.is_wildcard()) {
|
if (p_host.is_wildcard()) {
|
||||||
ip_type = IP::TYPE_ANY;
|
ip_type = IP::TYPE_ANY;
|
||||||
}
|
}
|
||||||
Error err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_TCP, ip_type);
|
Error err = _sock->open(NetSocket::TYPE_TCP, ip_type);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
_sock->set_blocking_enabled(false);
|
_sock->set_blocking_enabled(false);
|
||||||
NetSocket::Address addr(p_host, p_port);
|
return _sock->bind(p_host, p_port);
|
||||||
return _sock->bind(addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Error StreamPeerTCP::connect_to_host(const IPAddress &p_host, int p_port) {
|
Error StreamPeerTCP::connect_to_host(const IPAddress &p_host, int p_port) {
|
||||||
|
@ -68,7 +113,7 @@ Error StreamPeerTCP::connect_to_host(const IPAddress &p_host, int p_port) {
|
||||||
|
|
||||||
if (!_sock->is_open()) {
|
if (!_sock->is_open()) {
|
||||||
IP::Type ip_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
IP::Type ip_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
||||||
Error err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_TCP, ip_type);
|
Error err = _sock->open(NetSocket::TYPE_TCP, ip_type);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -76,9 +121,7 @@ Error StreamPeerTCP::connect_to_host(const IPAddress &p_host, int p_port) {
|
||||||
}
|
}
|
||||||
|
|
||||||
timeout = OS::get_singleton()->get_ticks_msec() + (((uint64_t)GLOBAL_GET("network/limits/tcp/connect_timeout_seconds")) * 1000);
|
timeout = OS::get_singleton()->get_ticks_msec() + (((uint64_t)GLOBAL_GET("network/limits/tcp/connect_timeout_seconds")) * 1000);
|
||||||
|
Error err = _sock->connect_to_host(p_host, p_port);
|
||||||
NetSocket::Address addr(p_host, p_port);
|
|
||||||
Error err = _sock->connect_to_host(addr);
|
|
||||||
|
|
||||||
if (err == OK) {
|
if (err == OK) {
|
||||||
status = STATUS_CONNECTED;
|
status = STATUS_CONNECTED;
|
||||||
|
@ -90,7 +133,106 @@ Error StreamPeerTCP::connect_to_host(const IPAddress &p_host, int p_port) {
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
peer_address = addr;
|
peer_host = p_host;
|
||||||
|
peer_port = p_port;
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error StreamPeerTCP::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block) {
|
||||||
|
ERR_FAIL_COND_V(_sock.is_null(), ERR_UNAVAILABLE);
|
||||||
|
|
||||||
|
if (status != STATUS_CONNECTED) {
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error err;
|
||||||
|
int data_to_send = p_bytes;
|
||||||
|
const uint8_t *offset = p_data;
|
||||||
|
int total_sent = 0;
|
||||||
|
|
||||||
|
while (data_to_send) {
|
||||||
|
int sent_amount = 0;
|
||||||
|
err = _sock->send(offset, data_to_send, sent_amount);
|
||||||
|
|
||||||
|
if (err != OK) {
|
||||||
|
if (err != ERR_BUSY) {
|
||||||
|
disconnect_from_host();
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!p_block) {
|
||||||
|
r_sent = total_sent;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Block and wait for the socket to accept more data
|
||||||
|
err = _sock->poll(NetSocket::POLL_TYPE_OUT, -1);
|
||||||
|
if (err != OK) {
|
||||||
|
disconnect_from_host();
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data_to_send -= sent_amount;
|
||||||
|
offset += sent_amount;
|
||||||
|
total_sent += sent_amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r_sent = total_sent;
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error StreamPeerTCP::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block) {
|
||||||
|
if (status != STATUS_CONNECTED) {
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error err;
|
||||||
|
int to_read = p_bytes;
|
||||||
|
int total_read = 0;
|
||||||
|
r_received = 0;
|
||||||
|
|
||||||
|
while (to_read) {
|
||||||
|
int read = 0;
|
||||||
|
err = _sock->recv(p_buffer + total_read, to_read, read);
|
||||||
|
|
||||||
|
if (err != OK) {
|
||||||
|
if (err != ERR_BUSY) {
|
||||||
|
disconnect_from_host();
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!p_block) {
|
||||||
|
r_received = total_read;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = _sock->poll(NetSocket::POLL_TYPE_IN, -1);
|
||||||
|
|
||||||
|
if (err != OK) {
|
||||||
|
disconnect_from_host();
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (read == 0) {
|
||||||
|
disconnect_from_host();
|
||||||
|
r_received = total_read;
|
||||||
|
return ERR_FILE_EOF;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
to_read -= read;
|
||||||
|
total_read += read;
|
||||||
|
|
||||||
|
if (!p_block) {
|
||||||
|
r_received = total_read;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r_received = total_read;
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
@ -100,18 +242,61 @@ void StreamPeerTCP::set_no_delay(bool p_enabled) {
|
||||||
_sock->set_tcp_no_delay_enabled(p_enabled);
|
_sock->set_tcp_no_delay_enabled(p_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StreamPeerTCP::Status StreamPeerTCP::get_status() const {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamPeerTCP::disconnect_from_host() {
|
||||||
|
if (_sock.is_valid() && _sock->is_open()) {
|
||||||
|
_sock->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
timeout = 0;
|
||||||
|
status = STATUS_NONE;
|
||||||
|
peer_host = IPAddress();
|
||||||
|
peer_port = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error StreamPeerTCP::wait(NetSocket::PollType p_type, int p_timeout) {
|
||||||
|
ERR_FAIL_COND_V(_sock.is_null() || !_sock->is_open(), ERR_UNAVAILABLE);
|
||||||
|
return _sock->poll(p_type, p_timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
Error StreamPeerTCP::put_data(const uint8_t *p_data, int p_bytes) {
|
||||||
|
int total;
|
||||||
|
return write(p_data, p_bytes, total, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Error StreamPeerTCP::put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) {
|
||||||
|
return write(p_data, p_bytes, r_sent, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Error StreamPeerTCP::get_data(uint8_t *p_buffer, int p_bytes) {
|
||||||
|
int total;
|
||||||
|
return read(p_buffer, p_bytes, total, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Error StreamPeerTCP::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) {
|
||||||
|
return read(p_buffer, p_bytes, r_received, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
int StreamPeerTCP::get_available_bytes() const {
|
||||||
|
ERR_FAIL_COND_V(_sock.is_null(), -1);
|
||||||
|
return _sock->get_available_bytes();
|
||||||
|
}
|
||||||
|
|
||||||
IPAddress StreamPeerTCP::get_connected_host() const {
|
IPAddress StreamPeerTCP::get_connected_host() const {
|
||||||
return peer_address.ip();
|
return peer_host;
|
||||||
}
|
}
|
||||||
|
|
||||||
int StreamPeerTCP::get_connected_port() const {
|
int StreamPeerTCP::get_connected_port() const {
|
||||||
return peer_address.port();
|
return peer_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
int StreamPeerTCP::get_local_port() const {
|
int StreamPeerTCP::get_local_port() const {
|
||||||
NetSocket::Address addr;
|
uint16_t local_port;
|
||||||
_sock->get_socket_address(&addr);
|
_sock->get_socket_address(nullptr, &local_port);
|
||||||
return addr.port();
|
return local_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error StreamPeerTCP::_connect(const String &p_address, int p_port) {
|
Error StreamPeerTCP::_connect(const String &p_address, int p_port) {
|
||||||
|
@ -131,8 +316,24 @@ Error StreamPeerTCP::_connect(const String &p_address, int p_port) {
|
||||||
void StreamPeerTCP::_bind_methods() {
|
void StreamPeerTCP::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("bind", "port", "host"), &StreamPeerTCP::bind, DEFVAL("*"));
|
ClassDB::bind_method(D_METHOD("bind", "port", "host"), &StreamPeerTCP::bind, DEFVAL("*"));
|
||||||
ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port"), &StreamPeerTCP::_connect);
|
ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port"), &StreamPeerTCP::_connect);
|
||||||
|
ClassDB::bind_method(D_METHOD("poll"), &StreamPeerTCP::poll);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_status"), &StreamPeerTCP::get_status);
|
||||||
ClassDB::bind_method(D_METHOD("get_connected_host"), &StreamPeerTCP::get_connected_host);
|
ClassDB::bind_method(D_METHOD("get_connected_host"), &StreamPeerTCP::get_connected_host);
|
||||||
ClassDB::bind_method(D_METHOD("get_connected_port"), &StreamPeerTCP::get_connected_port);
|
ClassDB::bind_method(D_METHOD("get_connected_port"), &StreamPeerTCP::get_connected_port);
|
||||||
ClassDB::bind_method(D_METHOD("get_local_port"), &StreamPeerTCP::get_local_port);
|
ClassDB::bind_method(D_METHOD("get_local_port"), &StreamPeerTCP::get_local_port);
|
||||||
|
ClassDB::bind_method(D_METHOD("disconnect_from_host"), &StreamPeerTCP::disconnect_from_host);
|
||||||
ClassDB::bind_method(D_METHOD("set_no_delay", "enabled"), &StreamPeerTCP::set_no_delay);
|
ClassDB::bind_method(D_METHOD("set_no_delay", "enabled"), &StreamPeerTCP::set_no_delay);
|
||||||
|
|
||||||
|
BIND_ENUM_CONSTANT(STATUS_NONE);
|
||||||
|
BIND_ENUM_CONSTANT(STATUS_CONNECTING);
|
||||||
|
BIND_ENUM_CONSTANT(STATUS_CONNECTED);
|
||||||
|
BIND_ENUM_CONSTANT(STATUS_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
StreamPeerTCP::StreamPeerTCP() :
|
||||||
|
_sock(Ref<NetSocket>(NetSocket::create())) {
|
||||||
|
}
|
||||||
|
|
||||||
|
StreamPeerTCP::~StreamPeerTCP() {
|
||||||
|
disconnect_from_host();
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,24 +32,62 @@
|
||||||
|
|
||||||
#include "core/io/ip.h"
|
#include "core/io/ip.h"
|
||||||
#include "core/io/ip_address.h"
|
#include "core/io/ip_address.h"
|
||||||
#include "core/io/stream_peer_socket.h"
|
#include "core/io/net_socket.h"
|
||||||
|
#include "core/io/stream_peer.h"
|
||||||
|
|
||||||
class StreamPeerTCP : public StreamPeerSocket {
|
class StreamPeerTCP : public StreamPeer {
|
||||||
GDCLASS(StreamPeerTCP, StreamPeerSocket);
|
GDCLASS(StreamPeerTCP, StreamPeer);
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Status {
|
||||||
|
STATUS_NONE,
|
||||||
|
STATUS_CONNECTING,
|
||||||
|
STATUS_CONNECTED,
|
||||||
|
STATUS_ERROR,
|
||||||
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
Ref<NetSocket> _sock;
|
||||||
|
uint64_t timeout = 0;
|
||||||
|
Status status = STATUS_NONE;
|
||||||
|
IPAddress peer_host;
|
||||||
|
uint16_t peer_port = 0;
|
||||||
|
|
||||||
Error _connect(const String &p_address, int p_port);
|
Error _connect(const String &p_address, int p_port);
|
||||||
|
Error write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block);
|
||||||
|
Error read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block);
|
||||||
|
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void accept_socket(Ref<NetSocket> p_sock, const NetSocket::Address &p_addr) override;
|
void accept_socket(Ref<NetSocket> p_sock, IPAddress p_host, uint16_t p_port);
|
||||||
|
|
||||||
Error bind(int p_port, const IPAddress &p_host);
|
Error bind(int p_port, const IPAddress &p_host);
|
||||||
Error connect_to_host(const IPAddress &p_host, int p_port);
|
Error connect_to_host(const IPAddress &p_host, int p_port);
|
||||||
IPAddress get_connected_host() const;
|
IPAddress get_connected_host() const;
|
||||||
int get_connected_port() const;
|
int get_connected_port() const;
|
||||||
int get_local_port() const;
|
int get_local_port() const;
|
||||||
|
void disconnect_from_host();
|
||||||
|
|
||||||
|
int get_available_bytes() const override;
|
||||||
|
Status get_status() const;
|
||||||
|
|
||||||
void set_no_delay(bool p_enabled);
|
void set_no_delay(bool p_enabled);
|
||||||
|
|
||||||
|
// Poll socket updating its state.
|
||||||
|
Error poll();
|
||||||
|
|
||||||
|
// Wait or check for writable, readable.
|
||||||
|
Error wait(NetSocket::PollType p_type, int p_timeout = 0);
|
||||||
|
|
||||||
|
// Read/Write from StreamPeer
|
||||||
|
Error put_data(const uint8_t *p_data, int p_bytes) override;
|
||||||
|
Error put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) override;
|
||||||
|
Error get_data(uint8_t *p_buffer, int p_bytes) override;
|
||||||
|
Error get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) override;
|
||||||
|
|
||||||
|
StreamPeerTCP();
|
||||||
|
~StreamPeerTCP();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
VARIANT_ENUM_CAST(StreamPeerTCP::Status);
|
||||||
|
|
|
@ -1,99 +0,0 @@
|
||||||
/**************************************************************************/
|
|
||||||
/* stream_peer_uds.cpp */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
|
||||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
#include "stream_peer_uds.h"
|
|
||||||
|
|
||||||
#include "core/config/project_settings.h"
|
|
||||||
|
|
||||||
void StreamPeerUDS::_bind_methods() {
|
|
||||||
ClassDB::bind_method(D_METHOD("bind", "path"), &StreamPeerUDS::bind);
|
|
||||||
ClassDB::bind_method(D_METHOD("connect_to_host", "path"), &StreamPeerUDS::connect_to_host);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_connected_path"), &StreamPeerUDS::get_connected_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StreamPeerUDS::accept_socket(Ref<NetSocket> p_sock, const NetSocket::Address &p_addr) {
|
|
||||||
_sock = p_sock;
|
|
||||||
_sock->set_blocking_enabled(false);
|
|
||||||
|
|
||||||
timeout = OS::get_singleton()->get_ticks_msec() + (((uint64_t)GLOBAL_GET("network/limits/unix/connect_timeout_seconds")) * 1000);
|
|
||||||
status = STATUS_CONNECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
Error StreamPeerUDS::bind(const String &p_path) {
|
|
||||||
ERR_FAIL_COND_V(_sock.is_null(), ERR_UNAVAILABLE);
|
|
||||||
ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE);
|
|
||||||
|
|
||||||
IP::Type ip_type = IP::TYPE_NONE;
|
|
||||||
Error err = _sock->open(NetSocket::Family::UNIX, NetSocket::TYPE_NONE, ip_type);
|
|
||||||
if (err != OK) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
_sock->set_blocking_enabled(false);
|
|
||||||
NetSocket::Address addr(p_path);
|
|
||||||
return _sock->bind(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Error StreamPeerUDS::connect_to_host(const String &p_path) {
|
|
||||||
ERR_FAIL_COND_V(_sock.is_null(), ERR_UNAVAILABLE);
|
|
||||||
ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE);
|
|
||||||
ERR_FAIL_COND_V(p_path.is_empty(), ERR_INVALID_PARAMETER);
|
|
||||||
|
|
||||||
if (!_sock->is_open()) {
|
|
||||||
IP::Type ip_type = IP::TYPE_NONE;
|
|
||||||
Error err = _sock->open(NetSocket::Family::UNIX, NetSocket::TYPE_NONE, ip_type);
|
|
||||||
if (err != OK) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
_sock->set_blocking_enabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout = OS::get_singleton()->get_ticks_msec() + (((uint64_t)GLOBAL_GET("network/limits/unix/connect_timeout_seconds")) * 1000);
|
|
||||||
NetSocket::Address addr(p_path);
|
|
||||||
Error err = _sock->connect_to_host(addr);
|
|
||||||
|
|
||||||
if (err == OK) {
|
|
||||||
status = STATUS_CONNECTED;
|
|
||||||
} else if (err == ERR_BUSY) {
|
|
||||||
status = STATUS_CONNECTING;
|
|
||||||
} else {
|
|
||||||
ERR_PRINT("Connection to remote host failed!");
|
|
||||||
disconnect_from_host();
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
peer_address = addr;
|
|
||||||
peer_path = p_path;
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
const String StreamPeerUDS::get_connected_path() const {
|
|
||||||
return String(peer_address.get_path().get_data());
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
/**************************************************************************/
|
|
||||||
/* stream_peer_uds.h */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
|
||||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/io/stream_peer_socket.h"
|
|
||||||
|
|
||||||
class StreamPeerUDS : public StreamPeerSocket {
|
|
||||||
GDCLASS(StreamPeerUDS, StreamPeerSocket);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
String peer_path;
|
|
||||||
static void _bind_methods();
|
|
||||||
|
|
||||||
public:
|
|
||||||
void accept_socket(Ref<NetSocket> p_sock, const NetSocket::Address &p_addr) override;
|
|
||||||
|
|
||||||
Error bind(const String &p_path);
|
|
||||||
Error connect_to_host(const String &p_path);
|
|
||||||
const String get_connected_path() const;
|
|
||||||
};
|
|
|
@ -32,8 +32,11 @@
|
||||||
|
|
||||||
void TCPServer::_bind_methods() {
|
void TCPServer::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("listen", "port", "bind_address"), &TCPServer::listen, DEFVAL("*"));
|
ClassDB::bind_method(D_METHOD("listen", "port", "bind_address"), &TCPServer::listen, DEFVAL("*"));
|
||||||
|
ClassDB::bind_method(D_METHOD("is_connection_available"), &TCPServer::is_connection_available);
|
||||||
|
ClassDB::bind_method(D_METHOD("is_listening"), &TCPServer::is_listening);
|
||||||
ClassDB::bind_method(D_METHOD("get_local_port"), &TCPServer::get_local_port);
|
ClassDB::bind_method(D_METHOD("get_local_port"), &TCPServer::get_local_port);
|
||||||
ClassDB::bind_method(D_METHOD("take_connection"), &TCPServer::take_connection);
|
ClassDB::bind_method(D_METHOD("take_connection"), &TCPServer::take_connection);
|
||||||
|
ClassDB::bind_method(D_METHOD("stop"), &TCPServer::stop);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error TCPServer::listen(uint16_t p_port, const IPAddress &p_bind_address) {
|
Error TCPServer::listen(uint16_t p_port, const IPAddress &p_bind_address) {
|
||||||
|
@ -49,21 +52,81 @@ Error TCPServer::listen(uint16_t p_port, const IPAddress &p_bind_address) {
|
||||||
ip_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
ip_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_TCP, ip_type);
|
err = _sock->open(NetSocket::TYPE_TCP, ip_type);
|
||||||
|
|
||||||
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
|
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
|
||||||
|
|
||||||
|
_sock->set_blocking_enabled(false);
|
||||||
_sock->set_reuse_address_enabled(true);
|
_sock->set_reuse_address_enabled(true);
|
||||||
|
|
||||||
return _listen(NetSocket::Address(p_bind_address, p_port));
|
err = _sock->bind(p_bind_address, p_port);
|
||||||
|
|
||||||
|
if (err != OK) {
|
||||||
|
_sock->close();
|
||||||
|
return ERR_ALREADY_IN_USE;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = _sock->listen(MAX_PENDING_CONNECTIONS);
|
||||||
|
|
||||||
|
if (err != OK) {
|
||||||
|
_sock->close();
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TCPServer::get_local_port() const {
|
int TCPServer::get_local_port() const {
|
||||||
NetSocket::Address addr;
|
uint16_t local_port;
|
||||||
_sock->get_socket_address(&addr);
|
_sock->get_socket_address(nullptr, &local_port);
|
||||||
return addr.port();
|
return local_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TCPServer::is_listening() const {
|
||||||
|
ERR_FAIL_COND_V(_sock.is_null(), false);
|
||||||
|
|
||||||
|
return _sock->is_open();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TCPServer::is_connection_available() const {
|
||||||
|
ERR_FAIL_COND_V(_sock.is_null(), false);
|
||||||
|
|
||||||
|
if (!_sock->is_open()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error err = _sock->poll(NetSocket::POLL_TYPE_IN, 0);
|
||||||
|
return (err == OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<StreamPeerTCP> TCPServer::take_connection() {
|
Ref<StreamPeerTCP> TCPServer::take_connection() {
|
||||||
return _take_connection<StreamPeerTCP>();
|
Ref<StreamPeerTCP> conn;
|
||||||
|
if (!is_connection_available()) {
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<NetSocket> ns;
|
||||||
|
IPAddress ip;
|
||||||
|
uint16_t port = 0;
|
||||||
|
ns = _sock->accept(ip, port);
|
||||||
|
if (ns.is_null()) {
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.instantiate();
|
||||||
|
conn->accept_socket(ns, ip, port);
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCPServer::stop() {
|
||||||
|
if (_sock.is_valid()) {
|
||||||
|
_sock->close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TCPServer::TCPServer() :
|
||||||
|
_sock(Ref<NetSocket>(NetSocket::create())) {
|
||||||
|
}
|
||||||
|
|
||||||
|
TCPServer::~TCPServer() {
|
||||||
|
stop();
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,18 +31,30 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/io/ip.h"
|
#include "core/io/ip.h"
|
||||||
#include "core/io/socket_server.h"
|
#include "core/io/net_socket.h"
|
||||||
|
#include "core/io/stream_peer.h"
|
||||||
#include "core/io/stream_peer_tcp.h"
|
#include "core/io/stream_peer_tcp.h"
|
||||||
|
|
||||||
class TCPServer : public SocketServer {
|
class TCPServer : public RefCounted {
|
||||||
GDCLASS(TCPServer, SocketServer);
|
GDCLASS(TCPServer, RefCounted);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
enum {
|
||||||
|
MAX_PENDING_CONNECTIONS = 8
|
||||||
|
};
|
||||||
|
|
||||||
|
Ref<NetSocket> _sock;
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Error listen(uint16_t p_port, const IPAddress &p_bind_address = IPAddress("*"));
|
Error listen(uint16_t p_port, const IPAddress &p_bind_address = IPAddress("*"));
|
||||||
int get_local_port() const;
|
int get_local_port() const;
|
||||||
|
bool is_listening() const;
|
||||||
|
bool is_connection_available() const;
|
||||||
Ref<StreamPeerTCP> take_connection();
|
Ref<StreamPeerTCP> take_connection();
|
||||||
Ref<StreamPeerSocket> take_socket_connection() override { return take_connection(); }
|
|
||||||
|
void stop(); // Stop listening
|
||||||
|
|
||||||
|
TCPServer();
|
||||||
|
~TCPServer();
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
#include "translation_loader_po.h"
|
#include "translation_loader_po.h"
|
||||||
|
|
||||||
#include "core/io/file_access.h"
|
#include "core/io/file_access.h"
|
||||||
#include "core/string/translation.h"
|
#include "core/string/translation_po.h"
|
||||||
|
|
||||||
Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_error) {
|
Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_error) {
|
||||||
if (r_error) {
|
if (r_error) {
|
||||||
|
@ -39,8 +39,7 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
|
||||||
}
|
}
|
||||||
|
|
||||||
const String path = f->get_path();
|
const String path = f->get_path();
|
||||||
Ref<Translation> translation;
|
Ref<TranslationPO> translation = Ref<TranslationPO>(memnew(TranslationPO));
|
||||||
translation.instantiate();
|
|
||||||
String config;
|
String config;
|
||||||
|
|
||||||
uint32_t magic = f->get_32();
|
uint32_t magic = f->get_32();
|
||||||
|
@ -113,7 +112,7 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
|
||||||
int p_start = config.find("Plural-Forms");
|
int p_start = config.find("Plural-Forms");
|
||||||
if (p_start != -1) {
|
if (p_start != -1) {
|
||||||
int p_end = config.find_char('\n', p_start);
|
int p_end = config.find_char('\n', p_start);
|
||||||
translation->set_plural_rules_override(config.substr(p_start, p_end - p_start));
|
translation->set_plural_rule(config.substr(p_start, p_end - p_start));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
uint32_t str_start = 0;
|
uint32_t str_start = 0;
|
||||||
|
@ -229,8 +228,8 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
|
||||||
int p_start = config.find("Plural-Forms");
|
int p_start = config.find("Plural-Forms");
|
||||||
if (p_start != -1) {
|
if (p_start != -1) {
|
||||||
int p_end = config.find_char('\n', p_start);
|
int p_end = config.find_char('\n', p_start);
|
||||||
translation->set_plural_rules_override(config.substr(p_start, p_end - p_start));
|
translation->set_plural_rule(config.substr(p_start, p_end - p_start));
|
||||||
plural_forms = translation->get_nplurals();
|
plural_forms = translation->get_plural_forms();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,10 +32,9 @@
|
||||||
|
|
||||||
#include "core/io/file_access.h"
|
#include "core/io/file_access.h"
|
||||||
#include "core/io/resource_loader.h"
|
#include "core/io/resource_loader.h"
|
||||||
|
#include "core/string/translation.h"
|
||||||
|
|
||||||
class TranslationLoaderPO : public ResourceFormatLoader {
|
class TranslationLoaderPO : public ResourceFormatLoader {
|
||||||
GDSOFTCLASS(TranslationLoaderPO, ResourceFormatLoader);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Ref<Resource> load_translation(Ref<FileAccess> f, Error *r_error = nullptr);
|
static Ref<Resource> load_translation(Ref<FileAccess> f, Error *r_error = nullptr);
|
||||||
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
|
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
|
||||||
|
|
|
@ -99,7 +99,7 @@ Error UDPServer::listen(uint16_t p_port, const IPAddress &p_bind_address) {
|
||||||
ip_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
ip_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = _sock->open(NetSocket::Family::INET, NetSocket::TYPE_UDP, ip_type);
|
err = _sock->open(NetSocket::TYPE_UDP, ip_type);
|
||||||
|
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return ERR_CANT_CREATE;
|
return ERR_CANT_CREATE;
|
||||||
|
@ -107,8 +107,7 @@ Error UDPServer::listen(uint16_t p_port, const IPAddress &p_bind_address) {
|
||||||
|
|
||||||
_sock->set_blocking_enabled(false);
|
_sock->set_blocking_enabled(false);
|
||||||
_sock->set_reuse_address_enabled(true);
|
_sock->set_reuse_address_enabled(true);
|
||||||
NetSocket::Address addr(p_bind_address, p_port);
|
err = _sock->bind(p_bind_address, p_port);
|
||||||
err = _sock->bind(addr);
|
|
||||||
|
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
stop();
|
stop();
|
||||||
|
@ -118,9 +117,9 @@ Error UDPServer::listen(uint16_t p_port, const IPAddress &p_bind_address) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int UDPServer::get_local_port() const {
|
int UDPServer::get_local_port() const {
|
||||||
NetSocket::Address addr;
|
uint16_t local_port;
|
||||||
_sock->get_socket_address(&addr);
|
_sock->get_socket_address(nullptr, &local_port);
|
||||||
return addr.port();
|
return local_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UDPServer::is_listening() const {
|
bool UDPServer::is_listening() const {
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
/**************************************************************************/
|
|
||||||
/* uds_server.cpp */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
|
||||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
#include "uds_server.h"
|
|
||||||
|
|
||||||
void UDSServer::_bind_methods() {
|
|
||||||
ClassDB::bind_method(D_METHOD("listen", "path"), &UDSServer::listen);
|
|
||||||
ClassDB::bind_method(D_METHOD("take_connection"), &UDSServer::take_connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
Error UDSServer::listen(const String &p_path) {
|
|
||||||
ERR_FAIL_COND_V(_sock.is_null(), ERR_UNAVAILABLE);
|
|
||||||
ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE);
|
|
||||||
ERR_FAIL_COND_V(p_path.is_empty(), ERR_INVALID_PARAMETER);
|
|
||||||
|
|
||||||
IP::Type ip_type = IP::TYPE_NONE;
|
|
||||||
Error err = _sock->open(NetSocket::Family::UNIX, NetSocket::TYPE_NONE, ip_type);
|
|
||||||
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
|
|
||||||
|
|
||||||
return _listen(p_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<StreamPeerUDS> UDSServer::take_connection() {
|
|
||||||
return _take_connection<StreamPeerUDS>();
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
/**************************************************************************/
|
|
||||||
/* uds_server.h */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/**************************************************************************/
|
|
||||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
|
||||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/io/socket_server.h"
|
|
||||||
#include "core/io/stream_peer_uds.h"
|
|
||||||
|
|
||||||
class UDSServer : public SocketServer {
|
|
||||||
GDCLASS(UDSServer, SocketServer);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static void _bind_methods();
|
|
||||||
|
|
||||||
public:
|
|
||||||
Error listen(const String &p_path);
|
|
||||||
Ref<StreamPeerUDS> take_connection();
|
|
||||||
Ref<StreamPeerSocket> take_socket_connection() override { return take_connection(); }
|
|
||||||
};
|
|
|
@ -32,7 +32,6 @@
|
||||||
|
|
||||||
#include "core/math/plane.h"
|
#include "core/math/plane.h"
|
||||||
#include "core/math/vector3.h"
|
#include "core/math/vector3.h"
|
||||||
#include "core/templates/hashfuncs.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AABB (Axis Aligned Bounding Box)
|
* AABB (Axis Aligned Bounding Box)
|
||||||
|
@ -132,16 +131,6 @@ struct [[nodiscard]] AABB {
|
||||||
return position + (size * 0.5f);
|
return position + (size * 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t hash() const {
|
|
||||||
uint32_t h = hash_murmur3_one_real(position.x);
|
|
||||||
h = hash_murmur3_one_real(position.y, h);
|
|
||||||
h = hash_murmur3_one_real(position.z, h);
|
|
||||||
h = hash_murmur3_one_real(size.x, h);
|
|
||||||
h = hash_murmur3_one_real(size.y, h);
|
|
||||||
h = hash_murmur3_one_real(size.z, h);
|
|
||||||
return hash_fmix32(h);
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit operator String() const;
|
explicit operator String() const;
|
||||||
|
|
||||||
AABB() = default;
|
AABB() = default;
|
||||||
|
|
|
@ -34,10 +34,6 @@
|
||||||
#include "core/math/vector3.h"
|
#include "core/math/vector3.h"
|
||||||
|
|
||||||
struct [[nodiscard]] Basis {
|
struct [[nodiscard]] Basis {
|
||||||
static const Basis FLIP_X;
|
|
||||||
static const Basis FLIP_Y;
|
|
||||||
static const Basis FLIP_Z;
|
|
||||||
|
|
||||||
Vector3 rows[3] = {
|
Vector3 rows[3] = {
|
||||||
Vector3(1, 0, 0),
|
Vector3(1, 0, 0),
|
||||||
Vector3(0, 1, 0),
|
Vector3(0, 1, 0),
|
||||||
|
@ -228,7 +224,7 @@ struct [[nodiscard]] Basis {
|
||||||
|
|
||||||
operator Quaternion() const { return get_quaternion(); }
|
operator Quaternion() const { return get_quaternion(); }
|
||||||
|
|
||||||
static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3::UP, bool p_use_model_front = false);
|
static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false);
|
||||||
|
|
||||||
Basis(const Quaternion &p_quaternion) { set_quaternion(p_quaternion); }
|
Basis(const Quaternion &p_quaternion) { set_quaternion(p_quaternion); }
|
||||||
Basis(const Quaternion &p_quaternion, const Vector3 &p_scale) { set_quaternion_scale(p_quaternion, p_scale); }
|
Basis(const Quaternion &p_quaternion, const Vector3 &p_scale) { set_quaternion_scale(p_quaternion, p_scale); }
|
||||||
|
@ -251,10 +247,6 @@ private:
|
||||||
void _set_diagonal(const Vector3 &p_diag);
|
void _set_diagonal(const Vector3 &p_diag);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline constexpr Basis Basis::FLIP_X = { { -1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
|
|
||||||
inline constexpr Basis Basis::FLIP_Y = { { 1, 0, 0 }, { 0, -1, 0 }, { 0, 0, 1 } };
|
|
||||||
inline constexpr Basis Basis::FLIP_Z = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, -1 } };
|
|
||||||
|
|
||||||
constexpr bool Basis::operator==(const Basis &p_matrix) const {
|
constexpr bool Basis::operator==(const Basis &p_matrix) const {
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
for (int j = 0; j < 3; j++) {
|
for (int j = 0; j < 3; j++) {
|
||||||
|
|
|
@ -432,7 +432,7 @@ int Color::find_named_color(const String &p_name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int Color::get_named_color_count() {
|
int Color::get_named_color_count() {
|
||||||
return std_size(named_colors);
|
return std::size(named_colors);
|
||||||
}
|
}
|
||||||
|
|
||||||
String Color::get_named_color_name(int p_idx) {
|
String Color::get_named_color_name(int p_idx) {
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/math/math_funcs.h"
|
#include "core/math/math_funcs.h"
|
||||||
#include "core/templates/hashfuncs.h"
|
|
||||||
|
|
||||||
class String;
|
class String;
|
||||||
|
|
||||||
|
@ -240,14 +239,6 @@ struct [[nodiscard]] Color {
|
||||||
_FORCE_INLINE_ void set_ok_hsl_s(float p_s) { set_ok_hsl(get_ok_hsl_h(), p_s, get_ok_hsl_l(), a); }
|
_FORCE_INLINE_ void set_ok_hsl_s(float p_s) { set_ok_hsl(get_ok_hsl_h(), p_s, get_ok_hsl_l(), a); }
|
||||||
_FORCE_INLINE_ void set_ok_hsl_l(float p_l) { set_ok_hsl(get_ok_hsl_h(), get_ok_hsl_s(), p_l, a); }
|
_FORCE_INLINE_ void set_ok_hsl_l(float p_l) { set_ok_hsl(get_ok_hsl_h(), get_ok_hsl_s(), p_l, a); }
|
||||||
|
|
||||||
uint32_t hash() const {
|
|
||||||
uint32_t h = hash_murmur3_one_float(r);
|
|
||||||
h = hash_murmur3_one_float(r, h);
|
|
||||||
h = hash_murmur3_one_float(b, h);
|
|
||||||
h = hash_murmur3_one_float(a, h);
|
|
||||||
return hash_fmix32(h);
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr Color() :
|
constexpr Color() :
|
||||||
r(0), g(0), b(0), a(1) {}
|
r(0), g(0), b(0), a(1) {}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
#include "core/math/aabb.h"
|
#include "core/math/aabb.h"
|
||||||
#include "core/math/projection.h"
|
#include "core/math/projection.h"
|
||||||
#include "core/math/vector3.h"
|
#include "core/math/vector3.h"
|
||||||
#include "core/math/vector3i.h"
|
|
||||||
#include "core/templates/a_hash_map.h"
|
#include "core/templates/a_hash_map.h"
|
||||||
#include "core/templates/list.h"
|
#include "core/templates/list.h"
|
||||||
#include "core/templates/local_vector.h"
|
#include "core/templates/local_vector.h"
|
||||||
|
|
|
@ -30,9 +30,7 @@
|
||||||
|
|
||||||
#include "geometry_2d.h"
|
#include "geometry_2d.h"
|
||||||
|
|
||||||
GODOT_GCC_WARNING_PUSH_AND_IGNORE("-Walloc-zero")
|
|
||||||
#include "thirdparty/clipper2/include/clipper2/clipper.h"
|
#include "thirdparty/clipper2/include/clipper2/clipper.h"
|
||||||
GODOT_GCC_WARNING_POP
|
|
||||||
#include "thirdparty/misc/polypartition.h"
|
#include "thirdparty/misc/polypartition.h"
|
||||||
#define STB_RECT_PACK_IMPLEMENTATION
|
#define STB_RECT_PACK_IMPLEMENTATION
|
||||||
#include "thirdparty/misc/stb_rect_pack.h"
|
#include "thirdparty/misc/stb_rect_pack.h"
|
||||||
|
@ -294,16 +292,14 @@ Vector<Vector<Point2>> Geometry2D::_polypaths_do_operation(PolyBooleanOperation
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<Vector<Point2>> polypaths;
|
Vector<Vector<Point2>> polypaths;
|
||||||
polypaths.resize(paths.size());
|
for (PathsD::size_type i = 0; i < paths.size(); ++i) {
|
||||||
for (PathsD::size_type i = 0; i < paths.size(); i++) {
|
|
||||||
const PathD &path = paths[i];
|
const PathD &path = paths[i];
|
||||||
|
|
||||||
Vector<Vector2> polypath;
|
Vector<Vector2> polypath;
|
||||||
polypath.resize(path.size());
|
|
||||||
for (PathsD::size_type j = 0; j < path.size(); ++j) {
|
for (PathsD::size_type j = 0; j < path.size(); ++j) {
|
||||||
polypath.set(j, Point2(static_cast<real_t>(path[j].x), static_cast<real_t>(path[j].y)));
|
polypath.push_back(Point2(static_cast<real_t>(path[j].x), static_cast<real_t>(path[j].y)));
|
||||||
}
|
}
|
||||||
polypaths.set(i, polypath);
|
polypaths.push_back(polypath);
|
||||||
}
|
}
|
||||||
return polypaths;
|
return polypaths;
|
||||||
}
|
}
|
||||||
|
@ -357,16 +353,14 @@ Vector<Vector<Point2>> Geometry2D::_polypath_offset(const Vector<Point2> &p_poly
|
||||||
// to attain the desired precision.
|
// to attain the desired precision.
|
||||||
|
|
||||||
Vector<Vector<Point2>> polypaths;
|
Vector<Vector<Point2>> polypaths;
|
||||||
polypaths.resize(paths.size());
|
|
||||||
for (PathsD::size_type i = 0; i < paths.size(); ++i) {
|
for (PathsD::size_type i = 0; i < paths.size(); ++i) {
|
||||||
const PathD &path = paths[i];
|
const PathD &path = paths[i];
|
||||||
|
|
||||||
Vector<Vector2> polypath2;
|
Vector<Vector2> polypath2;
|
||||||
polypath2.resize(path.size());
|
|
||||||
for (PathsD::size_type j = 0; j < path.size(); ++j) {
|
for (PathsD::size_type j = 0; j < path.size(); ++j) {
|
||||||
polypath2.set(j, Point2(static_cast<real_t>(path[j].x), static_cast<real_t>(path[j].y)));
|
polypath2.push_back(Point2(static_cast<real_t>(path[j].x), static_cast<real_t>(path[j].y)));
|
||||||
}
|
}
|
||||||
polypaths.set(i, polypath2);
|
polypaths.push_back(polypath2);
|
||||||
}
|
}
|
||||||
return polypaths;
|
return polypaths;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,10 +30,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/math/color.h"
|
|
||||||
#include "core/math/delaunay_3d.h"
|
#include "core/math/delaunay_3d.h"
|
||||||
#include "core/math/face3.h"
|
#include "core/math/face3.h"
|
||||||
#include "core/math/vector2.h"
|
|
||||||
#include "core/templates/local_vector.h"
|
#include "core/templates/local_vector.h"
|
||||||
#include "core/templates/vector.h"
|
#include "core/templates/vector.h"
|
||||||
|
|
||||||
|
@ -294,10 +292,6 @@ public:
|
||||||
real_t den = p.normal.dot(dir);
|
real_t den = p.normal.dot(dir);
|
||||||
|
|
||||||
if (Math::abs(den) <= (real_t)CMP_EPSILON) {
|
if (Math::abs(den) <= (real_t)CMP_EPSILON) {
|
||||||
if (p.is_point_over(p_from)) {
|
|
||||||
// Separating plane.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
continue; // Ignore parallel plane.
|
continue; // Ignore parallel plane.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,10 +35,6 @@
|
||||||
class Variant;
|
class Variant;
|
||||||
|
|
||||||
struct [[nodiscard]] Plane {
|
struct [[nodiscard]] Plane {
|
||||||
static const Plane PLANE_YZ;
|
|
||||||
static const Plane PLANE_XZ;
|
|
||||||
static const Plane PLANE_XY;
|
|
||||||
|
|
||||||
Vector3 normal;
|
Vector3 normal;
|
||||||
real_t d = 0;
|
real_t d = 0;
|
||||||
|
|
||||||
|
@ -94,10 +90,6 @@ struct [[nodiscard]] Plane {
|
||||||
_FORCE_INLINE_ Plane(const Vector3 &p_point1, const Vector3 &p_point2, const Vector3 &p_point3, ClockDirection p_dir = CLOCKWISE);
|
_FORCE_INLINE_ Plane(const Vector3 &p_point1, const Vector3 &p_point2, const Vector3 &p_point3, ClockDirection p_dir = CLOCKWISE);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline constexpr Plane Plane::PLANE_YZ = { 1, 0, 0, 0 };
|
|
||||||
inline constexpr Plane Plane::PLANE_XZ = { 0, 1, 0, 0 };
|
|
||||||
inline constexpr Plane Plane::PLANE_XY = { 0, 0, 1, 0 };
|
|
||||||
|
|
||||||
bool Plane::is_point_over(const Vector3 &p_point) const {
|
bool Plane::is_point_over(const Vector3 &p_point) const {
|
||||||
return (normal.dot(p_point) > d);
|
return (normal.dot(p_point) > d);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
|
|
||||||
#include "core/error/error_macros.h"
|
#include "core/error/error_macros.h"
|
||||||
#include "core/math/vector2.h"
|
#include "core/math/vector2.h"
|
||||||
#include "core/templates/hashfuncs.h"
|
|
||||||
|
|
||||||
class String;
|
class String;
|
||||||
struct Rect2i;
|
struct Rect2i;
|
||||||
|
@ -362,14 +361,6 @@ struct [[nodiscard]] Rect2 {
|
||||||
explicit operator String() const;
|
explicit operator String() const;
|
||||||
operator Rect2i() const;
|
operator Rect2i() const;
|
||||||
|
|
||||||
uint32_t hash() const {
|
|
||||||
uint32_t h = hash_murmur3_one_real(position.x);
|
|
||||||
h = hash_murmur3_one_real(position.y, h);
|
|
||||||
h = hash_murmur3_one_real(size.x, h);
|
|
||||||
h = hash_murmur3_one_real(size.y, h);
|
|
||||||
return hash_fmix32(h);
|
|
||||||
}
|
|
||||||
|
|
||||||
Rect2() = default;
|
Rect2() = default;
|
||||||
constexpr Rect2(real_t p_x, real_t p_y, real_t p_width, real_t p_height) :
|
constexpr Rect2(real_t p_x, real_t p_y, real_t p_width, real_t p_height) :
|
||||||
position(Point2(p_x, p_y)),
|
position(Point2(p_x, p_y)),
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
|
|
||||||
#include "core/error/error_macros.h"
|
#include "core/error/error_macros.h"
|
||||||
#include "core/math/vector2i.h"
|
#include "core/math/vector2i.h"
|
||||||
#include "core/templates/hashfuncs.h"
|
|
||||||
|
|
||||||
class String;
|
class String;
|
||||||
struct Rect2;
|
struct Rect2;
|
||||||
|
@ -227,14 +226,6 @@ struct [[nodiscard]] Rect2i {
|
||||||
explicit operator String() const;
|
explicit operator String() const;
|
||||||
operator Rect2() const;
|
operator Rect2() const;
|
||||||
|
|
||||||
uint32_t hash() const {
|
|
||||||
uint32_t h = hash_murmur3_one_32(uint32_t(position.x));
|
|
||||||
h = hash_murmur3_one_32(uint32_t(position.y), h);
|
|
||||||
h = hash_murmur3_one_32(uint32_t(size.x), h);
|
|
||||||
h = hash_murmur3_one_32(uint32_t(size.y), h);
|
|
||||||
return hash_fmix32(h);
|
|
||||||
}
|
|
||||||
|
|
||||||
Rect2i() = default;
|
Rect2i() = default;
|
||||||
constexpr Rect2i(int p_x, int p_y, int p_width, int p_height) :
|
constexpr Rect2i(int p_x, int p_y, int p_width, int p_height) :
|
||||||
position(Point2i(p_x, p_y)),
|
position(Point2i(p_x, p_y)),
|
||||||
|
|
|
@ -52,9 +52,6 @@ struct [[nodiscard]] Transform2D {
|
||||||
// WARNING: Be aware that unlike 3D code, 2D code uses a left-handed coordinate system:
|
// WARNING: Be aware that unlike 3D code, 2D code uses a left-handed coordinate system:
|
||||||
// Y-axis points down, and angle is measure from +X to +Y in a clockwise-fashion.
|
// Y-axis points down, and angle is measure from +X to +Y in a clockwise-fashion.
|
||||||
|
|
||||||
static const Transform2D FLIP_X;
|
|
||||||
static const Transform2D FLIP_Y;
|
|
||||||
|
|
||||||
Vector2 columns[3] = {
|
Vector2 columns[3] = {
|
||||||
{ 1, 0 },
|
{ 1, 0 },
|
||||||
{ 0, 1 },
|
{ 0, 1 },
|
||||||
|
@ -152,9 +149,6 @@ struct [[nodiscard]] Transform2D {
|
||||||
Transform2D() = default;
|
Transform2D() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline constexpr Transform2D Transform2D::FLIP_X = { { -1, 0 }, { 0, 1 }, { 0, 0 } };
|
|
||||||
inline constexpr Transform2D Transform2D::FLIP_Y = { { 1, 0 }, { 0, -1 }, { 0, 0 } };
|
|
||||||
|
|
||||||
constexpr bool Transform2D::operator==(const Transform2D &p_transform) const {
|
constexpr bool Transform2D::operator==(const Transform2D &p_transform) const {
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
if (columns[i] != p_transform.columns[i]) {
|
if (columns[i] != p_transform.columns[i]) {
|
||||||
|
|
|
@ -36,10 +36,6 @@
|
||||||
#include "core/templates/vector.h"
|
#include "core/templates/vector.h"
|
||||||
|
|
||||||
struct [[nodiscard]] Transform3D {
|
struct [[nodiscard]] Transform3D {
|
||||||
static const Transform3D FLIP_X;
|
|
||||||
static const Transform3D FLIP_Y;
|
|
||||||
static const Transform3D FLIP_Z;
|
|
||||||
|
|
||||||
Basis basis;
|
Basis basis;
|
||||||
Vector3 origin;
|
Vector3 origin;
|
||||||
|
|
||||||
|
@ -55,8 +51,8 @@ struct [[nodiscard]] Transform3D {
|
||||||
void rotate(const Vector3 &p_axis, real_t p_angle);
|
void rotate(const Vector3 &p_axis, real_t p_angle);
|
||||||
void rotate_basis(const Vector3 &p_axis, real_t p_angle);
|
void rotate_basis(const Vector3 &p_axis, real_t p_angle);
|
||||||
|
|
||||||
void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up = Vector3::UP, bool p_use_model_front = false);
|
void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false);
|
||||||
Transform3D looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3::UP, bool p_use_model_front = false) const;
|
Transform3D looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false) const;
|
||||||
|
|
||||||
void scale(const Vector3 &p_scale);
|
void scale(const Vector3 &p_scale);
|
||||||
Transform3D scaled(const Vector3 &p_scale) const;
|
Transform3D scaled(const Vector3 &p_scale) const;
|
||||||
|
@ -140,10 +136,6 @@ struct [[nodiscard]] Transform3D {
|
||||||
origin(p_ox, p_oy, p_oz) {}
|
origin(p_ox, p_oy, p_oz) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline constexpr Transform3D Transform3D::FLIP_X = { Basis::FLIP_X };
|
|
||||||
inline constexpr Transform3D Transform3D::FLIP_Y = { Basis::FLIP_Y };
|
|
||||||
inline constexpr Transform3D Transform3D::FLIP_Z = { Basis::FLIP_Z };
|
|
||||||
|
|
||||||
constexpr bool Transform3D::operator==(const Transform3D &p_transform) const {
|
constexpr bool Transform3D::operator==(const Transform3D &p_transform) const {
|
||||||
return (basis == p_transform.basis && origin == p_transform.origin);
|
return (basis == p_transform.basis && origin == p_transform.origin);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,18 +32,12 @@
|
||||||
|
|
||||||
#include "core/error/error_macros.h"
|
#include "core/error/error_macros.h"
|
||||||
#include "core/math/math_funcs.h"
|
#include "core/math/math_funcs.h"
|
||||||
#include "core/templates/hashfuncs.h"
|
|
||||||
|
|
||||||
class String;
|
class String;
|
||||||
struct Vector2i;
|
struct Vector2i;
|
||||||
|
|
||||||
struct [[nodiscard]] Vector2 {
|
struct [[nodiscard]] Vector2 {
|
||||||
static const Vector2 LEFT;
|
static const int AXIS_COUNT = 2;
|
||||||
static const Vector2 RIGHT;
|
|
||||||
static const Vector2 UP;
|
|
||||||
static const Vector2 DOWN;
|
|
||||||
|
|
||||||
static constexpr int AXIS_COUNT = 2;
|
|
||||||
|
|
||||||
enum Axis {
|
enum Axis {
|
||||||
AXIS_X,
|
AXIS_X,
|
||||||
|
@ -191,12 +185,6 @@ struct [[nodiscard]] Vector2 {
|
||||||
explicit operator String() const;
|
explicit operator String() const;
|
||||||
operator Vector2i() const;
|
operator Vector2i() const;
|
||||||
|
|
||||||
uint32_t hash() const {
|
|
||||||
uint32_t h = hash_murmur3_one_real(x);
|
|
||||||
h = hash_murmur3_one_real(y, h);
|
|
||||||
return hash_fmix32(h);
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOLINTBEGIN(cppcoreguidelines-pro-type-member-init)
|
// NOLINTBEGIN(cppcoreguidelines-pro-type-member-init)
|
||||||
constexpr Vector2() :
|
constexpr Vector2() :
|
||||||
x(0), y(0) {}
|
x(0), y(0) {}
|
||||||
|
@ -205,11 +193,6 @@ struct [[nodiscard]] Vector2 {
|
||||||
// NOLINTEND(cppcoreguidelines-pro-type-member-init)
|
// NOLINTEND(cppcoreguidelines-pro-type-member-init)
|
||||||
};
|
};
|
||||||
|
|
||||||
inline constexpr Vector2 Vector2::LEFT = { -1, 0 };
|
|
||||||
inline constexpr Vector2 Vector2::RIGHT = { 1, 0 };
|
|
||||||
inline constexpr Vector2 Vector2::UP = { 0, -1 };
|
|
||||||
inline constexpr Vector2 Vector2::DOWN = { 0, 1 };
|
|
||||||
|
|
||||||
_FORCE_INLINE_ Vector2 Vector2::plane_project(real_t p_d, const Vector2 &p_vec) const {
|
_FORCE_INLINE_ Vector2 Vector2::plane_project(real_t p_d, const Vector2 &p_vec) const {
|
||||||
return p_vec - *this * (dot(p_vec) - p_d);
|
return p_vec - *this * (dot(p_vec) - p_d);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,18 +32,12 @@
|
||||||
|
|
||||||
#include "core/error/error_macros.h"
|
#include "core/error/error_macros.h"
|
||||||
#include "core/math/math_funcs.h"
|
#include "core/math/math_funcs.h"
|
||||||
#include "core/templates/hashfuncs.h"
|
|
||||||
|
|
||||||
class String;
|
class String;
|
||||||
struct Vector2;
|
struct Vector2;
|
||||||
|
|
||||||
struct [[nodiscard]] Vector2i {
|
struct [[nodiscard]] Vector2i {
|
||||||
static const Vector2i LEFT;
|
static const int AXIS_COUNT = 2;
|
||||||
static const Vector2i RIGHT;
|
|
||||||
static const Vector2i UP;
|
|
||||||
static const Vector2i DOWN;
|
|
||||||
|
|
||||||
static constexpr int AXIS_COUNT = 2;
|
|
||||||
|
|
||||||
enum Axis {
|
enum Axis {
|
||||||
AXIS_X,
|
AXIS_X,
|
||||||
|
@ -148,12 +142,6 @@ struct [[nodiscard]] Vector2i {
|
||||||
explicit operator String() const;
|
explicit operator String() const;
|
||||||
operator Vector2() const;
|
operator Vector2() const;
|
||||||
|
|
||||||
uint32_t hash() const {
|
|
||||||
uint32_t h = hash_murmur3_one_32(uint32_t(x));
|
|
||||||
h = hash_murmur3_one_32(uint32_t(y), h);
|
|
||||||
return hash_fmix32(h);
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOLINTBEGIN(cppcoreguidelines-pro-type-member-init)
|
// NOLINTBEGIN(cppcoreguidelines-pro-type-member-init)
|
||||||
constexpr Vector2i() :
|
constexpr Vector2i() :
|
||||||
x(0), y(0) {}
|
x(0), y(0) {}
|
||||||
|
@ -162,11 +150,6 @@ struct [[nodiscard]] Vector2i {
|
||||||
// NOLINTEND(cppcoreguidelines-pro-type-member-init)
|
// NOLINTEND(cppcoreguidelines-pro-type-member-init)
|
||||||
};
|
};
|
||||||
|
|
||||||
inline constexpr Vector2i Vector2i::LEFT = { -1, 0 };
|
|
||||||
inline constexpr Vector2i Vector2i::RIGHT = { 1, 0 };
|
|
||||||
inline constexpr Vector2i Vector2i::UP = { 0, -1 };
|
|
||||||
inline constexpr Vector2i Vector2i::DOWN = { 0, 1 };
|
|
||||||
|
|
||||||
constexpr Vector2i Vector2i::operator+(const Vector2i &p_v) const {
|
constexpr Vector2i Vector2i::operator+(const Vector2i &p_v) const {
|
||||||
return Vector2i(x + p_v.x, y + p_v.y);
|
return Vector2i(x + p_v.x, y + p_v.y);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,20 @@ Vector3 Vector3::rotated(const Vector3 &p_axis, real_t p_angle) const {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector3 Vector3::clamp(const Vector3 &p_min, const Vector3 &p_max) const {
|
||||||
|
return Vector3(
|
||||||
|
CLAMP(x, p_min.x, p_max.x),
|
||||||
|
CLAMP(y, p_min.y, p_max.y),
|
||||||
|
CLAMP(z, p_min.z, p_max.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 Vector3::clampf(real_t p_min, real_t p_max) const {
|
||||||
|
return Vector3(
|
||||||
|
CLAMP(x, p_min, p_max),
|
||||||
|
CLAMP(y, p_min, p_max),
|
||||||
|
CLAMP(z, p_min, p_max));
|
||||||
|
}
|
||||||
|
|
||||||
void Vector3::snap(const Vector3 &p_step) {
|
void Vector3::snap(const Vector3 &p_step) {
|
||||||
x = Math::snapped(x, p_step.x);
|
x = Math::snapped(x, p_step.x);
|
||||||
y = Math::snapped(y, p_step.y);
|
y = Math::snapped(y, p_step.y);
|
||||||
|
|
|
@ -39,20 +39,7 @@ struct Vector2;
|
||||||
struct Vector3i;
|
struct Vector3i;
|
||||||
|
|
||||||
struct [[nodiscard]] Vector3 {
|
struct [[nodiscard]] Vector3 {
|
||||||
static const Vector3 LEFT;
|
static const int AXIS_COUNT = 3;
|
||||||
static const Vector3 RIGHT;
|
|
||||||
static const Vector3 UP;
|
|
||||||
static const Vector3 DOWN;
|
|
||||||
static const Vector3 FORWARD;
|
|
||||||
static const Vector3 BACK;
|
|
||||||
static const Vector3 MODEL_LEFT;
|
|
||||||
static const Vector3 MODEL_RIGHT;
|
|
||||||
static const Vector3 MODEL_TOP;
|
|
||||||
static const Vector3 MODEL_BOTTOM;
|
|
||||||
static const Vector3 MODEL_FRONT;
|
|
||||||
static const Vector3 MODEL_REAR;
|
|
||||||
|
|
||||||
static constexpr int AXIS_COUNT = 3;
|
|
||||||
|
|
||||||
enum Axis {
|
enum Axis {
|
||||||
AXIS_X,
|
AXIS_X,
|
||||||
|
@ -106,20 +93,6 @@ struct [[nodiscard]] Vector3 {
|
||||||
return Vector3(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar));
|
return Vector3(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar));
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 clamp(const Vector3 &p_min, const Vector3 &p_max) const {
|
|
||||||
return Vector3(
|
|
||||||
CLAMP(x, p_min.x, p_max.x),
|
|
||||||
CLAMP(y, p_min.y, p_max.y),
|
|
||||||
CLAMP(z, p_min.z, p_max.z));
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 clampf(real_t p_min, real_t p_max) const {
|
|
||||||
return Vector3(
|
|
||||||
CLAMP(x, p_min, p_max),
|
|
||||||
CLAMP(y, p_min, p_max),
|
|
||||||
CLAMP(z, p_min, p_max));
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ real_t length() const;
|
_FORCE_INLINE_ real_t length() const;
|
||||||
_FORCE_INLINE_ real_t length_squared() const;
|
_FORCE_INLINE_ real_t length_squared() const;
|
||||||
|
|
||||||
|
@ -165,6 +138,8 @@ struct [[nodiscard]] Vector3 {
|
||||||
_FORCE_INLINE_ Vector3 sign() const;
|
_FORCE_INLINE_ Vector3 sign() const;
|
||||||
_FORCE_INLINE_ Vector3 ceil() const;
|
_FORCE_INLINE_ Vector3 ceil() const;
|
||||||
_FORCE_INLINE_ Vector3 round() const;
|
_FORCE_INLINE_ Vector3 round() const;
|
||||||
|
Vector3 clamp(const Vector3 &p_min, const Vector3 &p_max) const;
|
||||||
|
Vector3 clampf(real_t p_min, real_t p_max) const;
|
||||||
|
|
||||||
_FORCE_INLINE_ real_t distance_to(const Vector3 &p_to) const;
|
_FORCE_INLINE_ real_t distance_to(const Vector3 &p_to) const;
|
||||||
_FORCE_INLINE_ real_t distance_squared_to(const Vector3 &p_to) const;
|
_FORCE_INLINE_ real_t distance_squared_to(const Vector3 &p_to) const;
|
||||||
|
@ -214,32 +189,12 @@ struct [[nodiscard]] Vector3 {
|
||||||
explicit operator String() const;
|
explicit operator String() const;
|
||||||
operator Vector3i() const;
|
operator Vector3i() const;
|
||||||
|
|
||||||
uint32_t hash() const {
|
|
||||||
uint32_t h = hash_murmur3_one_real(x);
|
|
||||||
h = hash_murmur3_one_real(y, h);
|
|
||||||
h = hash_murmur3_one_real(z, h);
|
|
||||||
return hash_fmix32(h);
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr Vector3() :
|
constexpr Vector3() :
|
||||||
x(0), y(0), z(0) {}
|
x(0), y(0), z(0) {}
|
||||||
constexpr Vector3(real_t p_x, real_t p_y, real_t p_z) :
|
constexpr Vector3(real_t p_x, real_t p_y, real_t p_z) :
|
||||||
x(p_x), y(p_y), z(p_z) {}
|
x(p_x), y(p_y), z(p_z) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline constexpr Vector3 Vector3::LEFT = { -1, 0, 0 };
|
|
||||||
inline constexpr Vector3 Vector3::RIGHT = { 1, 0, 0 };
|
|
||||||
inline constexpr Vector3 Vector3::UP = { 0, 1, 0 };
|
|
||||||
inline constexpr Vector3 Vector3::DOWN = { 0, -1, 0 };
|
|
||||||
inline constexpr Vector3 Vector3::FORWARD = { 0, 0, -1 };
|
|
||||||
inline constexpr Vector3 Vector3::BACK = { 0, 0, 1 };
|
|
||||||
inline constexpr Vector3 Vector3::MODEL_LEFT = { 1, 0, 0 };
|
|
||||||
inline constexpr Vector3 Vector3::MODEL_RIGHT = { -1, 0, 0 };
|
|
||||||
inline constexpr Vector3 Vector3::MODEL_TOP = { 0, 1, 0 };
|
|
||||||
inline constexpr Vector3 Vector3::MODEL_BOTTOM = { 0, -1, 0 };
|
|
||||||
inline constexpr Vector3 Vector3::MODEL_FRONT = { 0, 0, 1 };
|
|
||||||
inline constexpr Vector3 Vector3::MODEL_REAR = { 0, 0, -1 };
|
|
||||||
|
|
||||||
Vector3 Vector3::cross(const Vector3 &p_with) const {
|
Vector3 Vector3::cross(const Vector3 &p_with) const {
|
||||||
Vector3 ret(
|
Vector3 ret(
|
||||||
(y * p_with.z) - (z * p_with.y),
|
(y * p_with.z) - (z * p_with.y),
|
||||||
|
@ -379,7 +334,7 @@ Vector3 Vector3::get_any_perpendicular() const {
|
||||||
// since it could be a different vector depending on the prior branching code Math::abs(x) <= Math::abs(y) && Math::abs(x) <= Math::abs(z).
|
// since it could be a different vector depending on the prior branching code Math::abs(x) <= Math::abs(y) && Math::abs(x) <= Math::abs(z).
|
||||||
// However, it would be reasonable to use any of the axes of the basis, as it is simpler to calculate.
|
// However, it would be reasonable to use any of the axes of the basis, as it is simpler to calculate.
|
||||||
ERR_FAIL_COND_V_MSG(is_zero_approx(), Vector3(0, 0, 0), "The Vector3 must not be zero.");
|
ERR_FAIL_COND_V_MSG(is_zero_approx(), Vector3(0, 0, 0), "The Vector3 must not be zero.");
|
||||||
return cross((Math::abs(x) <= Math::abs(y) && Math::abs(x) <= Math::abs(z)) ? Vector3::RIGHT : Vector3::UP).normalized();
|
return cross((Math::abs(x) <= Math::abs(y) && Math::abs(x) <= Math::abs(z)) ? Vector3(1, 0, 0) : Vector3(0, 1, 0)).normalized();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Operators */
|
/* Operators */
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue