feat: updated godot version

This commit is contained in:
Sara Gerretsen 2026-04-04 19:38:56 +02:00
parent 0c508b0831
commit 42b028dbb5
4694 changed files with 236470 additions and 401376 deletions

View file

@ -1,6 +1,3 @@
# If you change this file, please format all files of the codebase as part of your PR:
# pre-commit run clang-format --all
# Commented out parameters are those with the same value as base LLVM style.
# We can uncomment them if we want to change their value, or enforce the
# chosen value in case the base style changes (last sync: Clang 18.1.8).
@ -41,7 +38,7 @@ AlignAfterOpenBracket: DontAlign
# AcrossEmptyLines: false
# AcrossComments: false
# AlignCaseColons: false
AlignEscapedNewlines: DontAlign # Aligning leads to long diffs
# AlignEscapedNewlines: Right
AlignOperands: DontAlign
AlignTrailingComments:
Kind: Never
@ -117,25 +114,14 @@ Cpp11BracedListStyle: false
# - BOOST_FOREACH
# IfMacros:
# - KJ_IF_MAYBE
IncludeBlocks: Regroup
# IncludeBlocks: Preserve
IncludeCategories:
- Regex: ^"(core|drivers|editor|main|scene|servers|tests)/.*"$
Priority: 20
- Regex: ^"(modules|platform)/.*"$
Priority: 30
- Regex: ^<thirdparty/.*>$
Priority: 40
- Regex: ^<(windows|Jolt/Jolt|platform_gl)\.h>$
Priority: 50
- Regex: ^<.*\.(h|hpp)>$
Priority: 60
- Regex: ^<.*>$
Priority: 70
- Regex: ^".*\.compat\.inc"$
Priority: 0
SortPriority: 1
- Regex: ^".*"$
Priority: 10
Priority: 1
- Regex: ^<.*\.h>$
Priority: 2
- Regex: ^<.*>$
Priority: 3
# IncludeIsMainRegex: (Test)?$
# IncludeIsMainSourceRegex: ""
# IndentAccessModifiers: false

View file

@ -1,26 +1,21 @@
# If you change this file, please format all files of the codebase as part of your PR:
# pre-commit run --hook-stage manual clang-tidy --all
Checks:
- -*
- performance-move-const-arg
- bugprone-use-after-move
- cppcoreguidelines-pro-type-member-init
- modernize-deprecated-headers
- modernize-redundant-void-arg
- modernize-use-bool-literals
# - modernize-use-default-member-init # TODO Re-activate
- modernize-use-default-member-init
- modernize-use-nullptr
- readability-braces-around-statements
- readability-redundant-member-init
- readability-operators-representation
HeaderFileExtensions: ["", h, hh, hpp, hxx, inc, glsl]
ImplementationFileExtensions: [c, cc, cpp, cxx, m, mm, java]
HeaderFilterRegex: (core|doc|drivers|editor|main|modules|platform|scene|servers|tests)/
FormatStyle: file
CheckOptions:
cppcoreguidelines-pro-type-member-init.IgnoreArrays: true
cppcoreguidelines-pro-type-member-init.UseAssignment: true
modernize-deprecated-headers.CheckHeaderFile: true
modernize-use-bool-literals.IgnoreMacros: false
modernize-use-default-member-init.IgnoreMacros: false
modernize-use-default-member-init.UseAssignment: true
readability-operators-representation.BinaryOperators: "&&;&=;&;|;~;!;!=;||;|=;^;^="
readability-operators-representation.OverloadedOperators: "&&;&=;&;|;~;!;!=;||;|=;^;^="

View file

@ -1,21 +1,12 @@
# https://clangd.llvm.org/config
---
# Default conditions, apply everywhere.
CompileFlags:
Add:
# Some thirdparty includes seem to require a high -ferror-limit to pass checks.
- -ferror-limit=100
Diagnostics:
Includes:
IgnoreHeader:
- \.compat\.inc
---
# Header-specific conditions.
If:
@ -29,19 +20,11 @@ CompileFlags:
- -Wno-unused-const-variable
- -Wno-unused-function
- -Wno-unused-variable
---
# Suppress warnings for third-party or partial code.
# Suppress all third-party warnings.
If:
PathMatch:
- bin/build_deps/.*
- misc/dist/apple_embedded_xcode/.*
- tests/compatibility_test/.*
- thirdparty/.*
- .*/thirdparty/.*
- .*-so_wrap.[ch]
PathMatch: thirdparty/.*
Diagnostics:
Suppress: "*"

View file

@ -72,18 +72,3 @@ e06d83860d798b6766b23d6eae48557387a7db85
# Style: Replace header guards with `#pragma once`
324512e11c1b7663c3cf47bec6ddbe65c6b8db2b
# Style: Don't right-align escaped newlines
c5df0cb82bc539eff7dcfb2add99d60771fc50c5
# Style: Convert `*.gen.inc` to `*.gen.h`
7dae5da1982f4a55ba91557814905faef9ce461b
# Move RenderingServer enums to a dedicated RenderingServerEnums (`RSE`) namespace
f5a290ac462765afca34e64dd39f883511510147
# Style: Add `class_db.h` includes explicitly
e380a417526c11f15a9ddb3997292409b10da2af
# Move DisplayServer enums and typedefs to DisplayServerEnums
a447ac95ec170ee117c2eae55f1bfff0d0cf0dce

View file

@ -1,6 +1,8 @@
<!--
Please target the `master` branch. We will take care of backporting relevant fixes to older versions.
Please target the `master` branch in priority.
Before submitting, please read our checklist for new contributors:
https://contributing.godotengine.org/en/latest/engine/introduction.html#checklist-for-new-contributors
Relevant fixes are cherry-picked for stable branches as needed by maintainers.
To speed up the contribution process and avoid CI errors, please set up pre-commit hooks locally:
https://contributing.godotengine.org/en/latest/engine/guidelines/code_style.html
-->

View file

@ -1,30 +0,0 @@
name: clangd-tidy
description: Setup and run clangd-tidy on relevant files
inputs:
changed-files:
description: A pre-filtered list of changed files.
required: true
type: string
runs:
using: composite
steps:
- name: Setup clangd-tidy
shell: sh
run: |
echo "::group::Prerequisite checks"
if [ ! -f "compile_commands.json" ]; then
echo "::error::clangd-tidy checker requires a compilation database to function"
exit 1
fi
echo "::endgroup::"
echo "::group::Installing clangd-tidy"
# Don't know which python we're using, so just access the global scope.
python -m pip install clangd clangd-tidy clang-tidy==22.1.0
echo "::endgroup::"
echo "::group::Running clangd-tidy"
clangd-tidy ${{ inputs.changed-files }}
echo "::endgroup::"

View file

@ -1,33 +0,0 @@
name: Godot hash compatibility test
description: Check if methods with given hashes used by the older GDExtensions still can be loaded with given Godot version.
inputs:
bin:
description: Path to the Godot binary.
required: true
type: string
reftags:
description: Reference tags of Godot versions to check (comma separated).
required: true
type: string
runs:
using: composite
steps:
- name: Extract GDExtension interface
shell: sh
run: |
${{ inputs.bin }} --headless --dump-gdextension-interface
mkdir tests/compatibility_test/src/deps/
mv gdextension_interface.h tests/compatibility_test/src/deps/
- name: Build minimal GDExtension
shell: sh
run: scons --directory=./tests/compatibility_test
- name: Download reference GDExtension API JSON and try to load it
shell: sh
env:
GODOT4_BIN: ${{ inputs.bin }}
REFTAGS: ${{ inputs.reftags }}
run: ./tests/compatibility_test/run_compatibility_test.py

View file

@ -1,55 +0,0 @@
name: Export Godot project
description: Export a test Godot project.
inputs:
bin:
description: The path to the Godot executable
required: true
runs:
using: composite
steps:
- name: Import resources and export project
shell: sh
run: |
git clone --depth=1 https://github.com/godotengine/godot-tests.git /tmp/godot-tests
echo "Exporting project for Linux (PCK)"
${{ inputs.bin }} --headless --path /tmp/godot-tests/tests/test_project/ --export-pack "Linux" /tmp/test_project.pck 2>&1 | tee log.txt || true
GODOT_CHECK_CI_LOG_ALL_ERRORS=1 misc/scripts/check_ci_log.py log.txt
echo "Exporting project for Linux (ZIP)"
${{ inputs.bin }} --headless --path /tmp/godot-tests/tests/test_project/ --export-pack "Linux" /tmp/test_project.zip 2>&1 | tee log.txt || true
GODOT_CHECK_CI_LOG_ALL_ERRORS=1 misc/scripts/check_ci_log.py log.txt
echo "Exporting project for Linux as dedicated server (PCK)"
${{ inputs.bin }} --headless --path /tmp/godot-tests/tests/test_project/ --export-pack "Linux Server" /tmp/test_project_server.pck 2>&1 | tee log.txt || true
GODOT_CHECK_CI_LOG_ALL_ERRORS=1 misc/scripts/check_ci_log.py log.txt
- name: Run project files from folder
shell: sh
run: |
xvfb-run ${{ inputs.bin }} --path /tmp/godot-tests/tests/test_project/ --language fr --resolution 64x64 --write-movie /tmp/test_project_folder.png --quit 2>&1 | tee log.txt || true
GODOT_CHECK_CI_LOG_ALL_ERRORS=1 misc/scripts/check_ci_log.py log.txt
${{ inputs.bin }} --headless --path /tmp/godot-tests/tests/test_project/ --quit 2>&1 | tee log.txt || true
GODOT_CHECK_CI_LOG_ALL_ERRORS=1 misc/scripts/check_ci_log.py log.txt
- name: Run exported project PCK/ZIP
shell: sh
run: |
xvfb-run ${{ inputs.bin }} --main-pack /tmp/test_project.pck --language fr --resolution 64x64 --write-movie /tmp/test_project_pck.png --quit 2>&1 | tee log.txt || true
GODOT_CHECK_CI_LOG_ALL_ERRORS=1 misc/scripts/check_ci_log.py log.txt
xvfb-run ${{ inputs.bin }} --main-pack /tmp/test_project.zip --language fr --resolution 64x64 --write-movie /tmp/test_project_zip.png --quit 2>&1 | tee log.txt || true
GODOT_CHECK_CI_LOG_ALL_ERRORS=1 misc/scripts/check_ci_log.py log.txt
# Headless mode is implied for dedicated server PCKs.
${{ inputs.bin }} --main-pack /tmp/test_project_server.pck --quit 2>&1 | tee log.txt || true
GODOT_CHECK_CI_LOG_ALL_ERRORS=1 misc/scripts/check_ci_log.py log.txt
echo "Checking whether video output from project folder and exported project match..."
md5sum /tmp/test_project*.png | md5sum --check
echo "Checking whether audio output from project folder and exported project match..."
md5sum /tmp/test_project*.wav | md5sum --check

View file

@ -1,29 +0,0 @@
# We lack a convenient means of gathering *all* the changes when specializations are passed, so
# a catch-all variable is the easiest workaround.
everything:
- "**"
# Determines if build actions should occur after static checks are ran. Broadly speaking, these
# files changing would result in SCons rebuilding the engine, or are otherwise pertinent to the
# buildsystem itself.
sources:
- .github/{actions/*,workflows}/*.yml
- "**/{SConstruct,SCsub,*.py}"
- "**/*.{h,hpp,hh,hxx,c,cpp,cc,cxx,m,mm,inc,glsl}"
- modules/mono/**/*.{cs,csproj,sln,props,targets}
- platform/android/java/{gradle*,**/*.{jar,java,kt,gradle}}
- platform/web/{package{,-lock}.json,js/**/*.js}
- tests/**
# Determines which files are appropriate for running clangd-tidy checks on. This is a subset out
# of necessity, as we're only evaluating a Linux runner.
clangd:
- "**/*.{h,hpp,hxx,hh,c,cpp,cxx,cc}"
- "!**/thirdparty/**"
- "!**/*-so_wrap.{h,c}"
- "!drivers/{apple*,core*,d3d12,metal,wasapi,windows,winmidi,xaudio2}/**"
- "!editor/shader/shader_baker/shader_baker_export_plugin_platform_{d3d12,metal}.{h,cpp}"
- "!modules/camera/camera_{android,macos,win}.{h,cpp}"
- "!modules/openxr/extensions/platform/openxr_{android,metal}_extension.{h,cpp}"
- "!platform/{android,ios,macos,visionos,web,windows}/**"
- "platform/{android,ios,macos,visionos,web,windows}/{api,export}/*.{h,hpp,hxx,hh,c,cpp,cxx,cc}"

View file

@ -1,10 +1,6 @@
name: 🤖 Android Builds
on:
workflow_call:
secrets:
SERVICE_ACCOUNT_KEY:
required: true
workflow_dispatch:
# Global Settings
@ -12,6 +8,7 @@ env:
SCONS_FLAGS: >-
dev_mode=yes
module_text_server_fb_enabled=yes
tests=no
swappy=yes
jobs:
@ -26,7 +23,6 @@ jobs:
- name: Editor (target=editor)
cache-name: android-editor
target: editor
instrumented_tests: true
scons-flags: >-
arch=arm64
production=yes
@ -34,23 +30,21 @@ jobs:
- name: Template arm32 (target=template_debug, arch=arm32)
cache-name: android-template-arm32
target: template_debug
instrumented_tests: false
scons-flags: arch=arm32
- name: Template arm64 (target=template_debug, arch=arm64)
cache-name: android-template-arm64
target: template_debug
instrumented_tests: true
scons-flags: arch=arm64
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up Java 17
uses: actions/setup-java@v5
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17
@ -122,54 +116,3 @@ jobs:
with:
name: ${{ matrix.cache-name }}-picoos
path: picoos
- name: Generate Instrumented test APKs
if: matrix.instrumented_tests && github.repository == 'godotengine/godot' && github.event_name == 'push' && github.ref_name == github.event.repository.default_branch
run: |
cd platform/android/java
if [ "${{ matrix.target }}" = "editor" ]; then
./gradlew :editor:assembleAndroidAndroidTest :editor:assembleAndroidDebug -Pperform_signing=true
else
./gradlew :app:assembleAndroidTest :app:assembleInstrumentedDebug -Pperform_signing=true
fi
cd ../../..
- name: Create credentials file
if: matrix.instrumented_tests && github.repository == 'godotengine/godot' && github.event_name == 'push' && github.ref_name == github.event.repository.default_branch
uses: google-github-actions/auth@v3
with:
credentials_json: ${{ secrets.SERVICE_ACCOUNT_KEY }}
- name: Set up gcloud CLI
if: matrix.instrumented_tests && github.repository == 'godotengine/godot' && github.event_name == 'push' && github.ref_name == github.event.repository.default_branch
uses: google-github-actions/setup-gcloud@v3
- name: Run tests on Firebase Test Lab
if: matrix.instrumented_tests && github.repository == 'godotengine/godot' && github.event_name == 'push' && github.ref_name == github.event.repository.default_branch
run: |
set +e
if [ "${{ matrix.target }}" = "editor" ]; then
APP_APK="platform/android/java/editor/build/outputs/apk/android/debug/android_editor-android-debug.apk"
TEST_APK="platform/android/java/editor/build/outputs/apk/androidTest/android/debug/android_editor-android-debug-androidTest.apk"
else
APP_APK="platform/android/java/app/build/outputs/apk/instrumented/debug/android_debug.apk"
TEST_APK="platform/android/java/app/build/outputs/apk/androidTest/instrumented/debug/app-instrumented-debug-androidTest.apk"
fi
output=$(gcloud firebase test android run \
--type instrumentation \
--app "$APP_APK" \
--test "$TEST_APK" \
--device model=pa3q,version=35,orientation=landscape \
--device model=java,version=30,orientation=landscape \
--device model=MediumPhone.arm,version=26,orientation=landscape \
--use-orchestrator \
--timeout 2m 2>&1)
exit_code=$?
echo "$output"
if [[ $exit_code -eq 1 && "$output" == *"TEST_QUOTA_EXCEEDED"* ]]; then
echo "::warning title=Firebase Test Lab::Test quota exceeded."
exit_code=0
fi
exit "$exit_code"

View file

@ -8,21 +8,26 @@ env:
SCONS_FLAGS: >-
dev_mode=yes
module_text_server_fb_enabled=yes
tests=no
debug_symbols=no
jobs:
ios-template:
# From https://docs.github.com/en/actions/how-tos/write-workflows/choose-where-workflows-run/choose-the-runner-for-a-job#choosing-github-hosted-runners
runs-on: macos-26
runs-on: macos-latest
name: Template (target=template_release)
timeout-minutes: 60
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
submodules: recursive
# From https://github.com/actions/runner-images/blob/main/images/macos
- name: Select Xcode 26
run: sudo xcode-select -s /Applications/Xcode_26.0.1.app
- name: Restore Godot build cache
uses: ./.github/actions/godot-cache-restore
continue-on-error: true

View file

@ -1,11 +1,6 @@
name: 🐧 Linux Builds
on:
workflow_call:
inputs:
changed-files:
description: A list of changed files, pre-filtered for parsing by clangd-tidy.
required: true
type: string
workflow_dispatch:
# Global Settings
@ -13,6 +8,7 @@ env:
SCONS_FLAGS: >-
dev_mode=yes
module_text_server_fb_enabled=yes
"accesskit_sdk_path=${{ github.workspace }}/accesskit-c-0.21.2/"
GODOT_CPP_BRANCH: 4.5
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: true
@ -34,17 +30,15 @@ jobs:
- name: Editor w/ Mono (target=editor)
cache-name: linux-editor-mono
target: editor
scons-flags: module_mono_enabled=yes compiledb=yes
scons-flags: module_mono_enabled=yes
bin: ./bin/godot.linuxbsd.editor.x86_64.mono
build-mono: true
doc-test: true
proj-conv: true
proj-export: true
api-compat: true
artifact: true
# Validate godot-cpp compatibility on one arbitrary editor build.
godot-cpp: true
clangd-tidy: true
- name: Editor with doubles and GCC sanitizers (target=editor, dev_build=yes, scu_build=yes, precision=double, use_asan=yes, use_ubsan=yes, linker=mold)
cache-name: linux-editor-double-sanitizers
@ -116,7 +110,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
submodules: recursive
@ -124,7 +118,7 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install libwayland-bin # TODO: Figure out somehow how to embed this one.
if [ "${{ matrix.proj-test }}" == "true" -o "${{ matrix.proj-export }}" == "true" ]; then
if [ "${{ matrix.proj-test }}" == "true" ]; then
sudo apt-get install mesa-vulkan-drivers
fi
@ -149,7 +143,7 @@ jobs:
uses: ./.github/actions/godot-deps
with:
# Sync with Ensure*Version in SConstruct.
python-version: 3.9
python-version: 3.8
scons-version: 4.0
- name: Force remove preinstalled .NET SDKs
@ -165,15 +159,15 @@ jobs:
dotnet-version: 8.0.100
- name: Download pre-built AccessKit
shell: sh
id: accesskit-sdk
run: |
if python ./misc/scripts/install_accesskit.py; then
echo "ACCESSKIT_ENABLED=yes" >> "$GITHUB_OUTPUT"
else
echo "::warning::AccessKit SDK installation failed, building without AccessKit support."
echo "ACCESSKIT_ENABLED=no" >> "$GITHUB_OUTPUT"
fi
uses: dsaltares/fetch-gh-release-asset@1.1.2
with:
repo: godotengine/godot-accesskit-c-static
version: tags/0.21.2
file: accesskit-c-0.21.2.zip
target: accesskit-c-0.21.2/accesskit_c.zip
- name: Extract pre-built AccessKit
run: unzip -o accesskit-c-0.21.2/accesskit_c.zip
- name: Install mold linker
if: matrix.proj-test
@ -182,16 +176,10 @@ jobs:
- name: Compilation
uses: ./.github/actions/godot-build
with:
scons-flags: ${{ env.SCONS_FLAGS }} ${{ matrix.scons-flags }} accesskit=${{ steps.accesskit-sdk.outputs.ACCESSKIT_ENABLED }}
scons-flags: ${{ env.SCONS_FLAGS }} ${{ matrix.scons-flags }}
platform: linuxbsd
target: ${{ matrix.target }}
- name: Style checks via clangd-tidy
if: matrix.clangd-tidy
uses: ./.github/actions/clangd-tidy
with:
changed-files: ${{ inputs.changed-files }}
- name: Compilation (godot-cpp)
uses: ./.github/actions/godot-cpp-build
if: matrix.godot-cpp
@ -220,7 +208,6 @@ jobs:
- name: Prepare artifact
if: matrix.artifact
run: |
rm -rf ./bin/build_deps
strip bin/godot.*
chmod +x bin/godot.*
@ -251,18 +238,11 @@ jobs:
git diff --color --exit-code && ! git ls-files --others --exclude-standard | sed -e 's/^/New doc file missing in PR: /' | grep 'xml$'
# Check API backwards compatibility
- name: Check for GDExtension compatibility JSON check
- name: Check for GDExtension compatibility
if: matrix.api-compat
run: |
./misc/scripts/validate_extension_api.sh "${{ matrix.bin }}"
- name: Test GDExtension compatibility load methods
uses: ./.github/actions/godot-compat-test
if: matrix.api-compat
with:
bin: ${{ matrix.bin }}
reftags: "4.5-stable,4.4-stable"
# Download and run the test project
- name: Test Godot project
uses: ./.github/actions/godot-project-test
@ -270,13 +250,6 @@ jobs:
with:
bin: ${{ matrix.bin }}
# Test project export
- name: Test project export
uses: ./.github/actions/godot-project-export
if: matrix.proj-export
with:
bin: ${{ matrix.bin }}
# Test the project converter
- name: Test project converter
uses: ./.github/actions/godot-converter-test

View file

@ -8,11 +8,12 @@ env:
SCONS_FLAGS: >-
dev_mode=yes
module_text_server_fb_enabled=yes
"accesskit_sdk_path=${{ github.workspace }}/accesskit-c-0.21.2/"
jobs:
build-macos:
# From https://docs.github.com/en/actions/how-tos/write-workflows/choose-where-workflows-run/choose-the-runner-for-a-job#choosing-github-hosted-runners
runs-on: macos-26
runs-on: macos-latest
name: ${{ matrix.name }}
timeout-minutes: 120
strategy:
@ -32,10 +33,14 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
submodules: recursive
# From https://github.com/actions/runner-images/blob/main/images/macos
- name: Select Xcode 26
run: sudo xcode-select -s /Applications/Xcode_26.0.1.app
- name: Restore Godot build cache
uses: ./.github/actions/godot-cache-restore
with:
@ -45,27 +50,16 @@ jobs:
- name: Setup Python and SCons
uses: ./.github/actions/godot-deps
- name: Download pre-built ANGLE
shell: sh
id: angle-sdk
run: |
if python ./misc/scripts/install_angle.py; then
echo "ANGLE_ENABLED=yes" >> "$GITHUB_OUTPUT"
else
echo "::warning::ANGLE SDK installation failed, building without ANGLE support."
echo "ANGLE_ENABLED=no" >> "$GITHUB_OUTPUT"
fi
- name: Download pre-built AccessKit
shell: sh
id: accesskit-sdk
run: |
if python3 ./misc/scripts/install_accesskit.py; then
echo "ACCESSKIT_ENABLED=yes" >> "$GITHUB_OUTPUT"
else
echo "::warning::AccessKit SDK installation failed, building without AccessKit support."
echo "ACCESSKIT_ENABLED=no" >> "$GITHUB_OUTPUT"
fi
uses: dsaltares/fetch-gh-release-asset@1.1.2
with:
repo: godotengine/godot-accesskit-c-static
version: tags/0.21.2
file: accesskit-c-0.21.2.zip
target: accesskit-c-0.21.2/accesskit_c.zip
- name: Extract pre-built AccessKit
run: unzip -o accesskit-c-0.21.2/accesskit_c.zip
- name: Setup Vulkan SDK
id: vulkan-sdk
@ -81,14 +75,14 @@ jobs:
- name: Compilation (x86_64)
uses: ./.github/actions/godot-build
with:
scons-flags: ${{ env.SCONS_FLAGS }} ${{ matrix.scons-flags }} arch=x86_64 vulkan=${{ steps.vulkan-sdk.outputs.VULKAN_ENABLED }} accesskit=${{ steps.accesskit-sdk.outputs.ACCESSKIT_ENABLED }} angle=${{ steps.angle-sdk.outputs.ANGLE_ENABLED }}
scons-flags: ${{ env.SCONS_FLAGS }} ${{ matrix.scons-flags }} arch=x86_64 vulkan=${{ steps.vulkan-sdk.outputs.VULKAN_ENABLED }}
platform: macos
target: ${{ matrix.target }}
- name: Compilation (arm64)
uses: ./.github/actions/godot-build
with:
scons-flags: ${{ env.SCONS_FLAGS }} ${{ matrix.scons-flags }} arch=arm64 vulkan=${{ steps.vulkan-sdk.outputs.VULKAN_ENABLED }} accesskit=${{ steps.accesskit-sdk.outputs.ACCESSKIT_ENABLED }} angle=${{ steps.angle-sdk.outputs.ANGLE_ENABLED }}
scons-flags: ${{ env.SCONS_FLAGS }} ${{ matrix.scons-flags }} arch=arm64 vulkan=${{ steps.vulkan-sdk.outputs.VULKAN_ENABLED }}
platform: macos
target: ${{ matrix.target }}
@ -102,7 +96,6 @@ jobs:
run: |
lipo -create ./bin/godot.macos.${{ matrix.target }}.x86_64 ./bin/godot.macos.${{ matrix.target }}.arm64 -output ./bin/godot.macos.${{ matrix.target }}.universal
rm ./bin/godot.macos.${{ matrix.target }}.x86_64 ./bin/godot.macos.${{ matrix.target }}.arm64
rm -rf ./bin/build_deps
strip bin/godot.*
chmod +x bin/godot.*

View file

@ -18,39 +18,29 @@ jobs:
android-build:
name: 🤖 Android
needs: static-checks
if: needs.static-checks.outputs.sources-changed == 'true' || github.event_name != 'pull_request'
uses: ./.github/workflows/android_builds.yml
secrets:
SERVICE_ACCOUNT_KEY: ${{ secrets.SERVICE_ACCOUNT_KEY }}
ios-build:
name: 🍏 iOS
needs: static-checks
if: needs.static-checks.outputs.sources-changed == 'true' || github.event_name != 'pull_request'
uses: ./.github/workflows/ios_builds.yml
linux-build:
name: 🐧 Linux
needs: static-checks
if: needs.static-checks.outputs.sources-changed == 'true' || github.event_name != 'pull_request'
uses: ./.github/workflows/linux_builds.yml
with:
changed-files: ${{ needs.static-checks.outputs.changed-files }}
macos-build:
name: 🍎 macOS
needs: static-checks
if: needs.static-checks.outputs.sources-changed == 'true' || github.event_name != 'pull_request'
uses: ./.github/workflows/macos_builds.yml
windows-build:
name: 🏁 Windows
needs: static-checks
if: needs.static-checks.outputs.sources-changed == 'true' || github.event_name != 'pull_request'
uses: ./.github/workflows/windows_builds.yml
web-build:
name: 🌐 Web
needs: static-checks
if: needs.static-checks.outputs.sources-changed == 'true' || github.event_name != 'pull_request'
uses: ./.github/workflows/web_builds.yml

View file

@ -1,13 +1,6 @@
name: 📊 Static Checks
on:
workflow_call:
outputs:
changed-files:
description: A list of changed files, pre-filtered for parsing by clangd-tidy.
value: ${{ jobs.static-checks.outputs.changed-files }}
sources-changed:
description: Determines if any source files were changed.
value: ${{ jobs.static-checks.outputs.sources-changed }}
workflow_dispatch:
jobs:
@ -15,15 +8,11 @@ jobs:
name: Code style, file formatting, and docs
runs-on: ubuntu-24.04
timeout-minutes: 30
outputs:
changed-files: '"${{ steps.changed-files.outputs.clangd_all_changed_files }}"' # Wrap with quotes to bookend internal quote separators.
sources-changed: ${{ steps.changed-files.outputs.sources_any_changed }}
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 0 # Treeless clone. Slightly less performant than a shallow clone, but makes finding diffs instantaneous.
filter: tree:0 # See: https://github.blog/open-source/git/get-up-to-speed-with-partial-clone-and-shallow-clone/
fetch-depth: 2
# This needs to happen before Python and npm execution; it must happen before any extra files are written.
- name: .gitignore checks (gitignore_check.sh)
@ -31,17 +20,18 @@ jobs:
bash ./misc/scripts/gitignore_check.sh
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v47
with:
safe_output: false # Output passed to environment variable to avoid command injection.
separator: '" "' # To account for paths with spaces, ensure our items are split by quotes internally.
skip_initial_fetch: true
files_yaml_from_source_file: .github/changed_files.yml
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if [ "${{ github.event_name }}" == "pull_request" ]; then
files=$(git diff-tree --no-commit-id --name-only -r HEAD^1..HEAD 2> /dev/null || true)
elif [ "${{ github.event_name }}" == "push" -a "${{ github.event.forced }}" == "false" -a "${{ github.event.created }}" == "false" ]; then
files=$(git diff-tree --no-commit-id --name-only -r ${{ github.event.before }}..${{ github.event.after }} 2> /dev/null || true)
fi
files=$(echo "$files" | xargs -I {} sh -c 'echo "\"./{}\""' | tr '\n' ' ')
echo "CHANGED_FILES=$files" >> $GITHUB_ENV
- name: Style checks via pre-commit
uses: pre-commit/action@v3.0.1
env:
CHANGED_FILES: '"${{ steps.changed-files.outputs.everything_all_changed_files }}"' # Wrap with quotes to bookend internal quote separators.
with:
extra_args: --files ${{ env.CHANGED_FILES }}

View file

@ -7,6 +7,7 @@ on:
env:
SCONS_FLAGS: >-
dev_mode=yes
tests=no
debug_symbols=no
use_closure_compiler=yes
EM_VERSION: 4.0.11
@ -20,21 +21,21 @@ jobs:
fail-fast: false
matrix:
include:
- name: Template w/ threads, 64-bit (target=template_release, threads=yes, arch=wasm64)
- name: Template w/ threads (target=template_release, threads=yes)
cache-name: web-template
target: template_release
scons-flags: threads=yes arch=wasm64
scons-flags: threads=yes
artifact: true
- name: Template w/o threads, 32-bit (target=template_release, threads=no, arch=wasm32)
- name: Template w/o threads (target=template_release, threads=no)
cache-name: web-nothreads-template
target: template_release
scons-flags: threads=no arch=wasm32
scons-flags: threads=no
artifact: true
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
submodules: recursive

View file

@ -9,6 +9,8 @@ env:
dev_mode=yes
module_text_server_fb_enabled=yes
debug_symbols=no
"angle_libs=${{ github.workspace }}/"
"accesskit_sdk_path=${{ github.workspace }}/accesskit-c-0.21.2/"
SCONS_CACHE_MSVC_CONFIG: true
PYTHONIOENCODING: utf8
@ -57,7 +59,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
submodules: recursive
@ -82,37 +84,32 @@ jobs:
fi
continue-on-error: true
- name: Download pre-built ANGLE
shell: sh
id: angle-sdk
run: |
if python ./misc/scripts/install_angle.py; then
echo "ANGLE_ENABLED=yes" >> "$GITHUB_OUTPUT"
else
echo "::warning::ANGLE SDK installation failed, building without ANGLE support."
echo "ANGLE_ENABLED=no" >> "$GITHUB_OUTPUT"
fi
- name: Download pre-built ANGLE static libraries
uses: dsaltares/fetch-gh-release-asset@1.1.2
with:
repo: godotengine/godot-angle-static
version: tags/chromium/6601.2
file: godot-angle-static-x86_64-${{ matrix.compiler == 'gcc' && 'gcc' || 'msvc' }}-release.zip
target: angle/angle.zip
- name: Download WinRT components
shell: sh
run: python ./misc/scripts/install_winrt.py
continue-on-error: true
- name: Extract pre-built ANGLE static libraries
run: Expand-Archive -Force angle/angle.zip ${{ github.workspace }}/
- name: Download pre-built AccessKit
shell: sh
id: accesskit-sdk
run: |
if python ./misc/scripts/install_accesskit.py; then
echo "ACCESSKIT_ENABLED=yes" >> "$GITHUB_OUTPUT"
else
echo "::warning::AccessKit SDK installation failed, building without AccessKit support."
echo "ACCESSKIT_ENABLED=no" >> "$GITHUB_OUTPUT"
fi
uses: dsaltares/fetch-gh-release-asset@1.1.2
with:
repo: godotengine/godot-accesskit-c-static
version: tags/0.21.2
file: accesskit-c-0.21.2.zip
target: accesskit-c-0.21.2/accesskit_c.zip
- name: Extract pre-built AccessKit
run: unzip -o accesskit-c-0.21.2/accesskit_c.zip
- name: Compilation
uses: ./.github/actions/godot-build
with:
scons-flags: ${{ env.SCONS_FLAGS }} ${{ matrix.scons-flags }} d3d12=${{ steps.d3d12-sdk.outputs.D3D12_ENABLED }} accesskit=${{ steps.accesskit-sdk.outputs.ACCESSKIT_ENABLED }} angle=${{ steps.angle-sdk.outputs.ANGLE_ENABLED }}
scons-flags: ${{ env.SCONS_FLAGS }} ${{ matrix.scons-flags }} d3d12=${{ steps.d3d12-sdk.outputs.D3D12_ENABLED }}
platform: windows
target: ${{ matrix.target }}

View file

@ -29,36 +29,30 @@ repos:
types_or: [text]
args: [-style=file:misc/utility/clang_format_glsl.yml]
# Not automatically triggered (because it requires compile_commands.json to be up-to-date).
# Invoke it manually via `pre-commit run --hook-stage manual clang-tidy`
- repo: https://github.com/pocc/pre-commit-hooks
rev: v1.3.5
hooks:
- id: clang-tidy
# TODO .inc ignored for now because they don't include their parent header.
# TODO Platform-specific subfolders currently fail, we should try to include them
files: ^(core|main|scene)/.*\.(c|h|cpp|hpp|cc|hh|cxx|hxx|m|mm|java)$
# No unknown warning suppression used for easier compatibility with gcc
args: [--fix, --quiet, --use-color, -p=compile_commands.json, -extra-arg=-Wno-unknown-warning-option]
files: \.(c|h|cpp|hpp|cc|hh|cxx|hxx|m|mm|inc|java|glsl)$
args: [--fix, --quiet, --use-color]
types_or: [text]
additional_dependencies: [clang-tidy==21.1.6]
require_serial: false
stages: [manual]
require_serial: true
stages: [manual] # Not automatically triggered, invoked via `pre-commit run --hook-stage manual clang-tidy`
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.8
rev: v0.14.7
hooks:
- id: ruff-check
args: [--color=always]
args: [--fix]
files: (\.py|SConstruct|SCsub)$
types_or: [text]
- id: ruff-format
args: [--color=always]
files: (\.py|SConstruct|SCsub)$
types_or: [text]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.19.1
rev: v1.14.1 # Latest version that supports Python 3.8
hooks:
- id: mypy
files: \.py$
@ -109,18 +103,6 @@ repos:
files: ^(doc/classes|.*/doc_classes)/.*\.xml$
additional_dependencies: [xmlschema]
- id: validate-codeowners
name: validate-codeowners
language: python
entry: python misc/scripts/validate_codeowners.py
args: [--unowned]
- id: validate-includes
name: validate-includes
language: python
entry: python misc/scripts/validate_includes.py
files: \.(c|h|cpp|hpp|cc|hh|cxx|hxx|m|mm|inc)$
- id: eslint
name: eslint
language: node

View file

@ -7,6 +7,289 @@ previous feature release. It is equivalent to the listings on our
Changelogs for earlier feature releases are available in their respective Git
branches, and linked at the [end of this file](#Past-releases).
## 4.6.2 - 2026-04-01
- [Release announcement](https://godotengine.org/article/maintenance-release-godot-4-6-2)
- [Interactive changelog](https://godotengine.github.io/godot-interactive-changelog/#4.6.2)
#### 3D
- Fix `GridMap` editor pasting when orbiting using the "Alt" key ([GH-116778](https://github.com/godotengine/godot/pull/116778)).
- Fix 3D editor camera not updating correctly ([GH-106219](https://github.com/godotengine/godot/pull/106219)).
- Fix 3D focus selection for subgizmos ([GH-116972](https://github.com/godotengine/godot/pull/116972)).
- Fix collision repositioning for child nodes ([GH-115353](https://github.com/godotengine/godot/pull/115353)).
- Fix DirectionalLight3D property list ([GH-117189](https://github.com/godotengine/godot/pull/117189)).
- Fix some UI issues with the `GridMap` editor ([GH-116555](https://github.com/godotengine/godot/pull/116555)).
- Remove unneeded checks for undo-redo history from Skeleton3DEditor ([GH-115784](https://github.com/godotengine/godot/pull/115784)).
#### Animation
- Account for the current section when processing AnimationTracks ([GH-116046](https://github.com/godotengine/godot/pull/116046)).
- Check `playback_queue` existence after emit `animation_finished` signal ([GH-116676](https://github.com/godotengine/godot/pull/116676)).
- Clear fade-out on request firing in AnimationNodeOneShot ([GH-115125](https://github.com/godotengine/godot/pull/115125)).
- Deselect bezier keyframes when switching animations ([GH-116953](https://github.com/godotengine/godot/pull/116953)).
- Fix animation player crash when setting current animation to stop ([GH-116264](https://github.com/godotengine/godot/pull/116264)).
- Fix icon size in AnimationPlayer tracks ([GH-115576](https://github.com/godotengine/godot/pull/115576)).
- Fix visual shift of animation editor keys during selection ([GH-117290](https://github.com/godotengine/godot/pull/117290)).
- Fix timeline cursor following mouse during marker selection ([GH-117634](https://github.com/godotengine/godot/pull/117634)).
#### Assetlib
- Fix TLS handshake fail preventing AssetLib use with `builtin_certs=no` ([GH-115450](https://github.com/godotengine/godot/pull/115450)).
#### Audio
- AudioStreamWAV: Check for `eof_reached` when reading LIST INFO tags ([GH-116719](https://github.com/godotengine/godot/pull/116719)).
- Fix `AudioStreamPlaybackMicrophone` shutdown crash ([GH-116299](https://github.com/godotengine/godot/pull/116299)).
#### Buildsystem
- Add UTF-8 encoding to svg file open in `platform_builders.py` ([GH-117454](https://github.com/godotengine/godot/pull/117454)).
- CI: Bump JavaScript actions to Node 24 ([GH-117428](https://github.com/godotengine/godot/pull/117428)).
- CI: Restore godot-cpp caching ([GH-116586](https://github.com/godotengine/godot/pull/116586)).
- Fix Metal driver build with Xcode 26.4 ([GH-117989](https://github.com/godotengine/godot/pull/117989)).
- ScrollBar: Fix compilation with `precision=double` ([GH-117224](https://github.com/godotengine/godot/pull/117224)).
- Update CODEOWNERS ([GH-117674](https://github.com/godotengine/godot/pull/117674)).
#### C#
- Revert "[.NET] Remove EFS update on reloading assemblies" but with deferred call ([GH-117617](https://github.com/godotengine/godot/pull/117617)).
#### Core
- Fix `String::split_` crash on empty string ([GH-117353](https://github.com/godotengine/godot/pull/117353)).
- Fix editable children state when duplicating instantiated nodes ([GH-117041](https://github.com/godotengine/godot/pull/117041)).
- Make sure `ScriptLanguage` is initialized even after `init_languages` call ([GH-114131](https://github.com/godotengine/godot/pull/114131)).
- RingBuffer: Fix `T read()` method reading empty buffer ([GH-117388](https://github.com/godotengine/godot/pull/117388)).
- RingBuffer: Fix overreading on methods that take an offset as an argument ([GH-117151](https://github.com/godotengine/godot/pull/117151)).
#### Documentation
- Editor Settings: Prevent crash when viewing `filesystem/import/blender/blender_path` ([GH-115895](https://github.com/godotengine/godot/pull/115895)).
- Fix UPNP code sample using `OK` constant incorrectly ([GH-115549](https://github.com/godotengine/godot/pull/115549)).
#### Editor
- Add support for `--ignore-error-breaks` to `LocalDebugger` ([GH-116823](https://github.com/godotengine/godot/pull/116823)).
- Check if a resource from a snapshot exists before loading it ([GH-115194](https://github.com/godotengine/godot/pull/115194)).
- Create EditorHelpHighlighter in Project Manager ([GH-116014](https://github.com/godotengine/godot/pull/116014)).
- Don't tint the preview camera icon ([GH-116525](https://github.com/godotengine/godot/pull/116525)).
- Ensure debug features get cleared after use ([GH-115116](https://github.com/godotengine/godot/pull/115116)).
- Fix build profile generator always enabling 2D navigation ([GH-115412](https://github.com/godotengine/godot/pull/115412)).
- Fix build profile generator creating bogus profiles ([GH-115410](https://github.com/godotengine/godot/pull/115410)).
- Fix Change version link in web editor shell ([GH-117763](https://github.com/godotengine/godot/pull/117763)).
- Fix code completion popup colors not being updated properly ([GH-115315](https://github.com/godotengine/godot/pull/115315)).
- Fix detection of some features in Engine Compilation Configuration Editor ([GH-115230](https://github.com/godotengine/godot/pull/115230)).
- Fix editor not handling unsaved changes on restart from settings ([GH-116218](https://github.com/godotengine/godot/pull/116218)).
- Fix EditorSettings error due to `android_sdk_path` when exporting a project ([GH-116515](https://github.com/godotengine/godot/pull/116515)).
- Fix extend script button styling in scene tree dock ([GH-115045](https://github.com/godotengine/godot/pull/115045)).
- Fix hidden `Import` tab height ([GH-115172](https://github.com/godotengine/godot/pull/115172)).
- Fix mute button after pausing and stopping ([GH-116537](https://github.com/godotengine/godot/pull/116537)).
- Fix theme item inspector tooltips for Window subclasses ([GH-115245](https://github.com/godotengine/godot/pull/115245)).
- Hide property groups from the "Members" section in Debugger ([GH-116790](https://github.com/godotengine/godot/pull/116790)).
- macOS: Set apple menu node name to non empty value ([GH-115726](https://github.com/godotengine/godot/pull/115726)).
- Properly update region editor window when undoing changes to `region_rect` ([GH-108875](https://github.com/godotengine/godot/pull/108875)).
- Scene tree dock: Don't log error if there is no selection upon handling `item_icon_double_clicked` signal ([GH-115347](https://github.com/godotengine/godot/pull/115347)).
- Set accessibility name on Tree inline cell editor when editing ([GH-117135](https://github.com/godotengine/godot/pull/117135)).
- Stop autocomplete from eating words by default ([GH-117464](https://github.com/godotengine/godot/pull/117464)).
#### Export
- Android Editor: Copy keystore to temp file during export ([GH-116161](https://github.com/godotengine/godot/pull/116161)).
- Linux: Handle debug symbols with renamed executable ([GH-114947](https://github.com/godotengine/godot/pull/114947)).
#### GDExtension
- Add missing `GDVIRTUAL_BIND(_get_supported_extensions)` on `MovieWriter` ([GH-117479](https://github.com/godotengine/godot/pull/117479)).
#### GDScript
- Stop `RemoteDebugger` from improperly flushing messages during break ([GH-115532](https://github.com/godotengine/godot/pull/115532)).
#### GUI
- Fix "Custom" anchor preset being ignored if the parent isn't a `Control` ([GH-117488](https://github.com/godotengine/godot/pull/117488)).
- Fix `SplitContainerDragger` dragging with enabled screen reader, allow resizing with keyboard shortcuts ([GH-116628](https://github.com/godotengine/godot/pull/116628)).
- Fix `TabContainer` accessibility sub-element cleanup ([GH-116617](https://github.com/godotengine/godot/pull/116617)).
- Fix camera focus triggered by double-clicking Tree buttons ([GH-114519](https://github.com/godotengine/godot/pull/114519)).
- Fix crash on removing Windows PopupMenu submenu ([GH-115373](https://github.com/godotengine/godot/pull/115373)).
- Fix drag-resizing `Control` with non-zero `pivot_offset_ratio` ([GH-116057](https://github.com/godotengine/godot/pull/116057)).
- Fix error after setting native PopupMenu item ID ([GH-115378](https://github.com/godotengine/godot/pull/115378)).
- Fix LCD batching flag for StyleBoxTexture ([GH-116647](https://github.com/godotengine/godot/pull/116647)).
- Fix RichTextLabel drag selection not working after double-click ([GH-117201](https://github.com/godotengine/godot/pull/117201)).
- Fix soft hyphen not working with small (or zero) line breaking width ([GH-116196](https://github.com/godotengine/godot/pull/116196)).
- Fix SplitContainer accessibility errors ([GH-116601](https://github.com/godotengine/godot/pull/116601)).
- Fix wrong normal icon color in FileDialog ([GH-115917](https://github.com/godotengine/godot/pull/115917)).
- PopupMenu: Use parent `GraphEdit` scale for popups inside `GraphElement` instead of completely disabling it ([GH-115620](https://github.com/godotengine/godot/pull/115620)).
- RTL: Fix `%` handling in `[img=WxH]` tags ([GH-116928](https://github.com/godotengine/godot/pull/116928)).
- Stop exposing external theme item properties ([GH-115392](https://github.com/godotengine/godot/pull/115392)).
- TextEdit: Fix clipping of last character due to right margin rounding ([GH-116850](https://github.com/godotengine/godot/pull/116850)).
- TextServer: Fix numeric keycap emoji sequence rendering ([GH-115687](https://github.com/godotengine/godot/pull/115687)).
- TextServer: Ignore language of embedded object replacement spans when updating line breaks ([GH-116197](https://github.com/godotengine/godot/pull/116197)).
#### Import
- Blender attempts should be incremented to avoid endless loop ([GH-116589](https://github.com/godotengine/godot/pull/116589)).
#### Input
- Fix issues with `InputMap::load_from_project_settings()` when called in tool script ([GH-105045](https://github.com/godotengine/godot/pull/105045)).
- macOS: Hide input accessory popups when no text control selected ([GH-115619](https://github.com/godotengine/godot/pull/115619)).
- Sync controller mappings DB with SDL community repo ([GH-115752](https://github.com/godotengine/godot/pull/115752)).
#### Physics
- Jolt Physics: Make MoveKinematic more accurate when rotating a body by a very small angle ([GH-115327](https://github.com/godotengine/godot/pull/115327)).
- Jolt Physics: Rework how gravity is applied to dynamic bodies to prevent energy increase on elastic collisions ([GH-115305](https://github.com/godotengine/godot/pull/115305)).
- Jolt Physics: Swapping vertices of triangle if it is scaled inside out ([GH-115089](https://github.com/godotengine/godot/pull/115089)).
#### Platforms
- Android: Enable native file picker support on all devices ([GH-115257](https://github.com/godotengine/godot/pull/115257)).
- Android: Fix FileAccess crash when using treeUri in Gradle-built apps ([GH-117131](https://github.com/godotengine/godot/pull/117131)).
- Android: Fix JavaClassWrapper test crashes on API 26 and lower ([GH-115800](https://github.com/godotengine/godot/pull/115800)).
- Android: Remove version check for `FEATURE_NATIVE_DIALOG_FILE` support ([GH-116584](https://github.com/godotengine/godot/pull/116584)).
- Apple Embedded: Fix static .a/.xcframework library loading in `open_dynamic_library` ([GH-117469](https://github.com/godotengine/godot/pull/117469)).
- Fix macOS Steam time tracking lost when opening a project ([GH-117335](https://github.com/godotengine/godot/pull/117335)).
- Fix startup errors/warnings on X11 when the Prefer Wayland editor setting is enabled ([GH-116366](https://github.com/godotengine/godot/pull/116366)).
- iOS: Add UIScene lifecycle events ([GH-116395](https://github.com/godotengine/godot/pull/116395)).
- iOS: Propagate VC UI preferences to SwiftUI hosting controller ([GH-116633](https://github.com/godotengine/godot/pull/116633)).
- LinuxBSD: Fix UI freeze when opening file manager ([GH-114521](https://github.com/godotengine/godot/pull/114521)).
- macOS: Add `nullptr` checks of `script_debugger` in `LayerHost::gui_input` ([GH-116724](https://github.com/godotengine/godot/pull/116724)).
- macOS: Add null check to `get_framework_executable` ([GH-116354](https://github.com/godotengine/godot/pull/116354)).
- macOS: Enable wake for events if `Magnet` is running ([GH-116524](https://github.com/godotengine/godot/pull/116524)).
- macOS: Fix confined mouse movement getting out of sync ([GH-116242](https://github.com/godotengine/godot/pull/116242)).
- Wayland: Improve mapping robustness and synchronization ([GH-117385](https://github.com/godotengine/godot/pull/117385)).
- Wayland: Only handle the current output mode ([GH-116236](https://github.com/godotengine/godot/pull/116236)).
- Wayland: Skip resize request when the size is the same ([GH-116376](https://github.com/godotengine/godot/pull/116376)).
- Windows: Set current driver when ANGLE init fails ([GH-117253](https://github.com/godotengine/godot/pull/117253)).
- Windows: Use executable icon as default for the window ([GH-115294](https://github.com/godotengine/godot/pull/115294)).
#### Plugin
- Android: Fix java.util.HashMap handling ([GH-114941](https://github.com/godotengine/godot/pull/114941)).
- Fix EditorDock not reopening ([GH-117340](https://github.com/godotengine/godot/pull/117340)).
#### Rendering
- Add compatibility fallback to `textureLod` when reading from `RADIANCE` ([GH-116155](https://github.com/godotengine/godot/pull/116155)).
- Apply fixed size properly for mono/stereo rendering ([GH-115147](https://github.com/godotengine/godot/pull/115147)).
- Fix accidental write-combined memory reads in canvas renderer ([GH-115757](https://github.com/godotengine/godot/pull/115757)).
- Fix shader compilation error when writing to `FOG` when `render_mode fog_disabled` ([GH-115026](https://github.com/godotengine/godot/pull/115026)).
- Fix Tangent decoding detection when computing vertex skinning ([GH-117401](https://github.com/godotengine/godot/pull/117401)).
- Fix viewport debanding not working with spatial scalers ([GH-114890](https://github.com/godotengine/godot/pull/114890)).
- Handle nearest filtering modes in D3D12 driver when anisotropy is enabled ([GH-115504](https://github.com/godotengine/godot/pull/115504)).
- macOS: Force ANGLE (GL over Metal) when running in VM ([GH-117371](https://github.com/godotengine/godot/pull/117371)).
- Restore default sky roughness levels to 8 ([GH-116154](https://github.com/godotengine/godot/pull/116154)).
#### Shaders
- Fix UTF-8 handling in GLES3 shaders ([GH-116756](https://github.com/godotengine/godot/pull/116756)).
- Fixes for completion of shader preprocessor defines ([GH-116413](https://github.com/godotengine/godot/pull/116413)).
- VisualShader: Fix nodes not attaching to new Frame on duplication ([GH-115193](https://github.com/godotengine/godot/pull/115193)).
#### Tests
- Android: Fail instrumented tests when test function doesn't complete ([GH-115713](https://github.com/godotengine/godot/pull/115713)).
- Fix file access tests failing on older Android devices ([GH-115718](https://github.com/godotengine/godot/pull/115718)).
#### Thirdparty
- Accessibility: Handle adapter activation/deactivation ([GH-115565](https://github.com/godotengine/godot/pull/115565)).
- Add missing patch files to `thirdparty/jolt_physics` ([GH-115884](https://github.com/godotengine/godot/pull/115884)).
- libpng: Update to 1.6.55 ([GH-117564](https://github.com/godotengine/godot/pull/117564)).
- Update access-kit to 0.21.2 ([GH-117433](https://github.com/godotengine/godot/pull/117433)).
## 4.6.1 - 2026-02-16
- [Release announcement](https://godotengine.org/article/maintenance-release-godot-4-6-1)
- [Interactive changelog](https://godotengine.github.io/godot-interactive-changelog/#4.6.1)
#### 3D
- Change orbit snap shortcut with navigation scheme ([GH-115298](https://github.com/godotengine/godot/pull/115298)).
- Fix `Skeleton3D` Edit Mode bone buttons have priority over transform gizmo ([GH-115608](https://github.com/godotengine/godot/pull/115608)).
- Fix viewport orbit snap defaulting to always snapping when shortcut(s) are set to none ([GH-115002](https://github.com/godotengine/godot/pull/115002)).
- Increase float precision in the editor inspector for Quaternions ([GH-106352](https://github.com/godotengine/godot/pull/106352)).
- Register zoom shortcuts to match preset `Godot` navigation scheme ([GH-115290](https://github.com/godotengine/godot/pull/115290)).
#### Animation
- Fix double memdelete of `dummy_player` ([GH-115968](https://github.com/godotengine/godot/pull/115968)).
- Fix LookAtModifier3D / AimModifier3D forward vector ([GH-115689](https://github.com/godotengine/godot/pull/115689)).
- Fix use-after-free in Animation Blend Tree ([GH-115919](https://github.com/godotengine/godot/pull/115919)).
- Fix use-after-free in AnimationTree (AHashMap realloc) ([GH-115931](https://github.com/godotengine/godot/pull/115931)).
#### Buildsystem
- Fix missing lib with `builtin_glslang=false` ([GH-93478](https://github.com/godotengine/godot/pull/93478)).
#### C#
- Revert "Improve performance of `CSharpLanguage::reload_assemblies`" ([GH-115759](https://github.com/godotengine/godot/pull/115759)).
#### Core
- Fix ClassDB class list sorting regression ([GH-115923](https://github.com/godotengine/godot/pull/115923)).
- Fix the `NodePath` hash function to not yield the same value for similar paths ([GH-115473](https://github.com/godotengine/godot/pull/115473)).
#### Editor
- Fix `NodePath` `EditorProperty` using the wrong scene root ([GH-115422](https://github.com/godotengine/godot/pull/115422)).
- Fix create dialog recents ([GH-115314](https://github.com/godotengine/godot/pull/115314)).
- Fix Rename option for instance roots ([GH-115575](https://github.com/godotengine/godot/pull/115575)).
- Fix Unique Resources from Inherited Scenes ([GH-115862](https://github.com/godotengine/godot/pull/115862)).
- Fix wrong base type when creating script ([GH-115778](https://github.com/godotengine/godot/pull/115778)).
#### Export
- Load translation files to check locale for ICU data export ([GH-115827](https://github.com/godotengine/godot/pull/115827)).
#### GDScript
- LSP: Add `godot` to known language ids ([GH-115671](https://github.com/godotengine/godot/pull/115671)).
- LSP: Handle clients that do not support `CompletionContext` ([GH-115672](https://github.com/godotengine/godot/pull/115672)).
#### GUI
- Fix current line highlight not extending into gutter ([GH-115729](https://github.com/godotengine/godot/pull/115729)).
#### Input
- Update editor shortcuts when changing 3D navigation scheme ([GH-115289](https://github.com/godotengine/godot/pull/115289)).
#### Particles
- Revert "Change curve range for particle multipliers" ([GH-116140](https://github.com/godotengine/godot/pull/116140)).
#### Physics
- Fix transform updates sometimes being discarded when using Jolt ([GH-115364](https://github.com/godotengine/godot/pull/115364)).
#### Platforms
- Android: Fix `Bad file descriptor` in SAF/MediaStore in long term access ([GH-115751](https://github.com/godotengine/godot/pull/115751)).
- Fix crash in `StorageScope.kt` on Android ([GH-115515](https://github.com/godotengine/godot/pull/115515)).
- Wayland Embedder: Fix FD leak with inert objects ([GH-115823](https://github.com/godotengine/godot/pull/115823)).
- Windows: Disable MSVC control flow check on IAT hooks ([GH-115430](https://github.com/godotengine/godot/pull/115430)).
#### Plugin
- Android: Fix plugin type mismatch regression ([GH-115685](https://github.com/godotengine/godot/pull/115685)).
#### Rendering
- Avoid reading from sky pointer when rendering background without sky ([GH-115874](https://github.com/godotengine/godot/pull/115874)).
- Ensure that uv border size is passed in to sky rendering functions ([GH-115606](https://github.com/godotengine/godot/pull/115606)).
- Pick the sample closer to the camera when resolving 2x MSAA ([GH-115124](https://github.com/godotengine/godot/pull/115124)).
- Update re-spirv with more derivative operations ([GH-115921](https://github.com/godotengine/godot/pull/115921)).
- Use sky's corrected camera projection for `combined_reprojection` ([GH-115292](https://github.com/godotengine/godot/pull/115292)).
- Use transmittance instead of opacity in the early-out branch when calculating volumetric fog ([GH-116107](https://github.com/godotengine/godot/pull/116107)).
#### Thirdparty
- libpng: Update to 1.6.54 ([GH-115714](https://github.com/godotengine/godot/pull/115714)).
## 4.6 - 2026-01-26
- [Release announcement](https://godotengine.org/releases/4.6/)

View file

@ -65,7 +65,7 @@ for an introduction to developing on Godot.
The [Contributing docs](https://contributing.godotengine.org/en/latest/organization/how_to_contribute.html)
also have important information on the [PR workflow](https://contributing.godotengine.org/en/latest/organization/pull_requests/creating_pull_requests.html)
(with a helpful guide for Git usage), and our [Code style guidelines](https://contributing.godotengine.org/en/latest/engine/guidelines/cpp_usage_guidelines.html)
(with a helpful guide for Git usage), and our [Code style guidelines](https://contributing.godotengine.org/en/latest/engine/guidelines/code_style.html)
which all contributions need to follow.
### Be mindful of your commits

View file

@ -310,11 +310,6 @@ Comment: The FreeType Project
Copyright: 1996-2025, David Turner, Robert Wilhelm, and Werner Lemberg.
License: FTL
Files: thirdparty/gamepadmotionhelpers/*
Comment: GamepadMotionHelpers
Copyright: 2020-2023, Julian "Jibb" Smart
License: Expat
Files: thirdparty/glad/*
Comment: glad
Copyright: 2013-2022, David Herberth
@ -432,11 +427,6 @@ Comment: meshoptimizer
Copyright: 2016-2024, Arseny Kapoulkine
License: Expat
Files: thirdparty/metal-cpp/*
Comment: metal-cpp
Copyright: 2024, Apple Inc.
License: Apache-2.0
Files: thirdparty/mingw-std-threads/*
Comment: mingw-std-threads
Copyright: 2016, Mega Limited
@ -584,11 +574,6 @@ Comment: SPIRV-Cross
Copyright: 2015-2021, Arm Limited
License: Apache-2.0 or Expat
Files: thirdparty/spirv-headers/*
Comment: SPIRV-Headers
Copyright: 2015-2024, The Khronos Group Inc.
License: Expat
Files: thirdparty/spirv-reflect/*
Comment: SPIRV-Reflect
Copyright: 2017-2022, Google Inc.
@ -601,7 +586,7 @@ License: Apache-2.0
Files: thirdparty/thorvg/*
Comment: ThorVG
Copyright: 2020-2026, The ThorVG Project
Copyright: 2020-2024, The ThorVG Project
License: Expat
Files: thirdparty/tinyexr/*
@ -623,19 +608,19 @@ License: BSD-3-clause
Files: thirdparty/volk/*
Comment: volk
Copyright: 2018-2025, Arseny Kapoulkine
Copyright: 2018-2024, Arseny Kapoulkine
License: Expat
Files: thirdparty/vulkan/*
Comment: Vulkan Headers
Copyright: 2015-2025, The Khronos Group Inc.
2015-2025, Valve Corporation
2015-2025, LunarG, Inc.
Copyright: 2014-2024, The Khronos Group Inc.
2014-2024, Valve Corporation
2014-2024, LunarG, Inc.
License: Apache-2.0
Files: thirdparty/vulkan/vk_mem_alloc.h
Comment: Vulkan Memory Allocator
Copyright: 2017-2025, Advanced Micro Devices, Inc.
Copyright: 2017-2024, Advanced Micro Devices, Inc.
License: Expat
Files: thirdparty/wayland/*

View file

@ -2,7 +2,7 @@
from misc.utility.scons_hints import *
EnsureSConsVersion(4, 0)
EnsurePythonVersion(3, 9)
EnsurePythonVersion(3, 8)
# System
import glob
@ -199,8 +199,8 @@ opts.Add(BoolVariable("opengl3", "Enable the OpenGL/GLES3 rendering driver", Tru
opts.Add(BoolVariable("d3d12", "Enable the Direct3D 12 rendering driver on supported platforms", False))
opts.Add(BoolVariable("metal", "Enable the Metal rendering driver on supported platforms (Apple arm64 only)", False))
opts.Add(BoolVariable("use_volk", "Use the volk library to load the Vulkan loader dynamically", True))
opts.Add(BoolVariable("accesskit", "Enable the AccessKit driver for screen reader support", True))
opts.Add(BoolVariable("angle", "Enable the ANGLE rendering driver for OpenGL ES 3.0 on supported platforms", True))
opts.Add(BoolVariable("accesskit", "Use AccessKit C SDK", True))
opts.Add(("accesskit_sdk_path", "Path to the AccessKit C SDK", ""))
opts.Add(BoolVariable("sdl", "Enable the SDL3 input driver", True))
opts.Add(
EnumVariable(
@ -222,13 +222,6 @@ opts.Add(
False,
)
)
opts.Add(
BoolVariable(
"profiler_record_on_demand",
"Record only when the profiler is connected, if the profiler supports it. In Tracy, this configures TRACY_ON_DEMAND, which has a performance impact if enabled.",
True,
)
)
# Advanced options
@ -243,7 +236,6 @@ opts.Add(BoolVariable("ninja", "Use the ninja backend for faster rebuilds", Fals
opts.Add(BoolVariable("ninja_auto_run", "Run ninja automatically after generating the ninja file", True))
opts.Add("ninja_file", "Path to the generated ninja file", "build.ninja")
opts.Add(BoolVariable("compiledb", "Generate compilation DB (`compile_commands.json`) for external tools", False))
opts.Add(BoolVariable("compiledb_gen_only", "Exit after building the compilation database", False))
opts.Add(
"num_jobs",
"Use up to N jobs when compiling (equivalent to `-j N`). Defaults to max jobs - 1. Ignored if -j is used.",
@ -656,11 +648,8 @@ if env["build_profile"] != "":
dbo = ft["disabled_build_options"]
for c in dbo:
env[c] = dbo[c]
except json.JSONDecodeError as err:
print_error(f'Failed to open feature build profile due to JSON decoding error: "{env["build_profile"]}"\n{err}')
Exit(255)
except FileNotFoundError:
print_error(f'Feature build profile not found at: "{env["build_profile"]}"')
except json.JSONDecodeError:
print_error(f'Failed to open feature build profile: "{env["build_profile"]}"')
Exit(255)
# 'dev_mode' and 'production' are aliases to set default options if they haven't been
@ -1180,6 +1169,7 @@ env.Append(BUILDERS=GLSL_BUILDERS)
if env["compiledb"]:
env.Tool("compilation_db")
env.Alias("compiledb", env.CompilationDatabase())
env.NoCache(env.CompilationDatabase())
if not env["verbose"]:
env["COMPILATIONDB_COMSTR"] = "$GENCOMSTR"
@ -1239,12 +1229,6 @@ if env["vsproj"]:
# Miscellaneous & post-build methods.
if not env.GetOption("clean") and not env.GetOption("help"):
if env["compiledb"] and env["compiledb_gen_only"]:
from SCons.Tool.compilation_db import write_compilation_db
write_compilation_db([env.File("compile_commands.json")], [], env)
env.Exit()
methods.dump(env)
methods.show_progress(env)
methods.prepare_purge(env)

View file

@ -34,7 +34,6 @@
#include "core/config/project_settings.h"
#include "core/donors.gen.h"
#include "core/license.gen.h"
#include "core/object/ref_counted.h"
#include "core/variant/typed_array.h"
#include "core/version.h"
#include "servers/rendering/rendering_device.h"

View file

@ -30,28 +30,23 @@
#include "project_settings.h"
#include "core/core_bind.h" // For Compression enum.
#include "core/input/input_map.h"
#include "core/io/compression.h"
#include "core/io/config_file.h"
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
#include "core/io/file_access_pack.h"
#include "core/io/marshalls.h"
#include "core/io/resource_uid.h"
#include "core/object/callable_mp.h"
#include "core/object/class_db.h"
#include "core/object/message_queue.h"
#include "core/object/script_language.h"
#include "core/os/os.h"
#include "core/templates/rb_set.h"
#include "core/variant/typed_array.h"
#include "core/variant/variant_parser.h"
#include "core/version.h"
#include "servers/rendering/rendering_server.h"
#ifdef TOOLS_ENABLED
#include "core/config/engine.h"
#include "modules/modules_enabled.gen.h" // IWYU pragma: keep. For mono.
#include "modules/modules_enabled.gen.h" // For mono.
#endif // TOOLS_ENABLED
ProjectSettings *ProjectSettings::get_singleton() {
@ -640,8 +635,7 @@ void ProjectSettings::_convert_to_last_version(int p_from_version) {
} else if (p_from_version <= 6) {
// Check if we still have legacy boot splash (removed in 4.6), map it to new project setting, then remove legacy setting.
if (has_setting("application/boot_splash/fullsize")) {
// See RenderingServerEnums::SplashStretchMode.
set_setting("application/boot_splash/stretch_mode", get_setting("application/boot_splash/fullsize") ? 1 : 0);
set_setting("application/boot_splash/stretch_mode", RenderingServer::map_scaling_option_to_stretch_mode(get_setting("application/boot_splash/fullsize")));
set_setting("application/boot_splash/fullsize", Variant());
}
}
@ -1063,7 +1057,6 @@ bool ProjectSettings::is_builtin_setting(const String &p_name) const {
void ProjectSettings::clear(const String &p_name) {
ERR_FAIL_COND_MSG(!props.has(p_name), vformat("Request for nonexistent project setting: '%s'.", p_name));
props.erase(p_name);
_queue_changed(p_name);
}
Error ProjectSettings::save() {
@ -1647,7 +1640,7 @@ void ProjectSettings::_bind_methods() {
void ProjectSettings::_add_builtin_input_map() {
if (InputMap::get_singleton()) {
HashMap<String, List<Ref<InputEvent>>> builtins(InputMap::get_singleton()->get_builtins());
HashMap<String, List<Ref<InputEvent>>> builtins = InputMap::get_singleton()->get_builtins();
for (KeyValue<String, List<Ref<InputEvent>>> &E : builtins) {
Array events;
@ -1710,7 +1703,6 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "accessibility/general/accessibility_support", PROPERTY_HINT_ENUM, "Auto (When Screen Reader is Running),Always Active,Disabled"), 0);
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "accessibility/general/updates_per_second", PROPERTY_HINT_RANGE, "1,100,1"), 60);
GLOBAL_DEF(PropertyInfo(Variant::STRING, "accessibility/general/accessibility_driver", PROPERTY_HINT_ENUM, "accesskit,dummy"), "accesskit");
// The default window size is tuned to:
// - Have a 16:9 aspect ratio,
@ -1740,10 +1732,7 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF(PropertyInfo(Variant::INT, "display/window/size/window_width_override", PROPERTY_HINT_RANGE, "0,7680,1,or_greater"), 0); // 8K resolution
GLOBAL_DEF(PropertyInfo(Variant::INT, "display/window/size/window_height_override", PROPERTY_HINT_RANGE, "0,4320,1,or_greater"), 0); // 8K resolution
GLOBAL_DEF("display/window/hdr/request_hdr_output", false);
GLOBAL_DEF("display/window/energy_saving/keep_screen_on", true);
GLOBAL_DEF("animation/warnings/check_invalid_skeleton_modifier_node_paths", true);
GLOBAL_DEF("animation/warnings/check_invalid_track_paths", true);
GLOBAL_DEF("animation/warnings/check_angle_interpolation_type_conflicting", true);
#ifndef DISABLE_DEPRECATED
@ -1762,10 +1751,10 @@ ProjectSettings::ProjectSettings() {
_add_builtin_input_map();
// Keep the enum values in sync with the `DisplayServerEnums::ScreenOrientation` enum.
// Keep the enum values in sync with the `DisplayServer::ScreenOrientation` enum.
custom_prop_info["display/window/handheld/orientation"] = PropertyInfo(Variant::INT, "display/window/handheld/orientation", PROPERTY_HINT_ENUM, "Landscape,Portrait,Reverse Landscape,Reverse Portrait,Sensor Landscape,Sensor Portrait,Sensor");
GLOBAL_DEF("display/window/subwindows/embed_subwindows", true);
// Keep the enum values in sync with the `DisplayServerEnums::VSyncMode` enum.
// Keep the enum values in sync with the `DisplayServer::VSyncMode` enum.
custom_prop_info["display/window/vsync/vsync_mode"] = PropertyInfo(Variant::INT, "display/window/vsync/vsync_mode", PROPERTY_HINT_ENUM, "Disabled,Enabled,Adaptive,Mailbox");
GLOBAL_DEF("display/window/frame_pacing/android/enable_frame_pacing", true);
@ -1817,7 +1806,7 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("gui/common/drag_threshold", 10);
GLOBAL_DEF_BASIC("gui/common/snap_controls_to_pixels", true);
GLOBAL_DEF(PropertyInfo(Variant::INT, "gui/common/show_focus_state_on_pointer_event", PROPERTY_HINT_ENUM, "Never,Text Input Controls,Always"), 1);
GLOBAL_DEF(PropertyInfo(Variant::INT, "gui/common/show_focus_state_on_pointer_event", PROPERTY_HINT_ENUM, "Never,Control Supports Keyboard Input,Always"), 1);
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);

View file

@ -31,7 +31,6 @@
#pragma once
#include "core/object/object.h"
#include "core/os/thread_safe.h"
#include "core/templates/rb_map.h"
template <typename T>
@ -205,7 +204,7 @@ public:
const HashMap<StringName, PropertyInfo> &get_custom_property_info() const;
uint64_t get_last_saved_time() { return last_save_time; }
List<String> get_input_presets() const { return List<String>(input_presets); }
List<String> get_input_presets() const { return input_presets; }
Variant get_setting_with_override(const StringName &p_name) const;
Variant get_setting_with_override_and_custom_features(const StringName &p_name, const Vector<String> &p_features) const;

View file

@ -30,10 +30,6 @@
#ifndef DISABLE_DEPRECATED
#include "core_bind.h"
#include "core/object/class_db.h"
namespace CoreBind {
// Semaphore

View file

@ -31,7 +31,6 @@
#include "core_bind.h"
#include "core_bind.compat.inc"
#include "core/config/engine.h"
#include "core/config/project_settings.h"
#include "core/crypto/crypto_core.h"
#include "core/debugger/engine_debugger.h"
@ -40,11 +39,8 @@
#include "core/io/marshalls.h"
#include "core/math/geometry_2d.h"
#include "core/math/geometry_3d.h"
#include "core/object/class_db.h"
#include "core/os/keyboard.h"
#include "core/os/main_loop.h"
#include "core/os/os.h"
#include "core/os/process_id.h"
#include "core/os/thread_safe.h"
#include "core/variant/typed_array.h"
@ -429,7 +425,7 @@ int OS::create_instance(const Vector<String> &p_arguments) {
for (const String &arg : p_arguments) {
args.push_back(arg);
}
ProcessID pid = 0;
::OS::ProcessID pid = 0;
Error err = ::OS::get_singleton()->create_instance(args, &pid);
if (err != OK) {
return -1;
@ -450,7 +446,7 @@ int OS::create_process(const String &p_path, const Vector<String> &p_arguments,
for (const String &arg : p_arguments) {
args.push_back(arg);
}
ProcessID pid = 0;
::OS::ProcessID pid = 0;
Error err = ::OS::get_singleton()->create_process(p_path, args, &pid, p_open_console);
if (err != OK) {
return -1;

View file

@ -31,10 +31,8 @@
#pragma once
#include "core/debugger/engine_profiler.h"
#include "core/io/logger.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
#include "core/object/class_db.h"
#include "core/object/script_backtrace.h"
#include "core/os/semaphore.h"
#include "core/os/thread.h"

View file

@ -41,7 +41,7 @@ def version_hash_builder(target, source, env):
#include "core/version.h"
const char *const GODOT_VERSION_HASH = "{git_hash}";
const unsigned long long GODOT_VERSION_TIMESTAMP = {git_timestamp};
const uint64_t GODOT_VERSION_TIMESTAMP = {git_timestamp};
""".format(**source[0].read())
)
@ -63,7 +63,7 @@ def encryption_key_builder(target, source, env):
with methods.generated_wrapper(str(target[0])) as file:
file.write(
f"""\
#include <cstdint>
#include "core/config/project_settings.h"
uint8_t script_encryption_key[32] = {{
{methods.format_buffer(buffer, 1)}

View file

@ -30,12 +30,10 @@
#include "core_constants.h"
#include "core/input/input_enums.h"
#include "core/object/method_bind_common.h" // IWYU pragma: keep. For `VARIANT_BITFIELD_CAST(MethodFlags)`.
#include "core/input/input_event.h"
#include "core/object/class_db.h"
#include "core/os/keyboard.h"
#include "core/variant/type_info.h"
#include "core/variant/variant.h"
#include "core/variant/variant_caster.h"
struct _CoreConstant {
#ifdef DEBUG_ENABLED
@ -71,183 +69,183 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#ifdef DEBUG_ENABLED
#define BIND_CORE_CONSTANT(m_constant) \
#define BIND_CORE_CONSTANT(m_constant) \
_global_constants.push_back(_CoreConstant(StringName(), #m_constant, m_constant)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1;
#define BIND_CORE_ENUM_CONSTANT(m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
#define BIND_CORE_ENUM_CONSTANT(m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
}
#define BIND_CORE_BITFIELD_FLAG(m_constant) \
{ \
StringName enum_name = __constant_get_bitfield_name(m_constant); \
#define BIND_CORE_BITFIELD_FLAG(m_constant) \
{ \
StringName enum_name = __constant_get_bitfield_name(m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant, false, true)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
}
// This just binds enum classes as if they were regular enum constants.
#define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \
{ \
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
#define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \
{ \
StringName enum_name = __constant_get_enum_name(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_enums[enum_name].push_back((_global_constants.ptr())[_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]); \
}
#define BIND_CORE_BITFIELD_CLASS_FLAG(m_enum, m_prefix, m_member) \
{ \
StringName enum_name = __constant_get_bitfield_name(m_enum::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); \
_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]); \
}
#define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \
{ \
StringName enum_name = __constant_get_enum_name(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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
}
#define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \
{ \
StringName enum_name = __constant_get_enum_name(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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
}
#define BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(m_enum, m_name, m_member) \
{ \
StringName enum_name = __constant_get_bitfield_name(m_enum::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); \
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member, false, true)); \
_global_constants_map[#m_name] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
_global_constants_map[#m_name] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
}
#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); \
#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); \
_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]); \
}
#define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \
{ \
StringName enum_name = __constant_get_enum_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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
}
#define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \
{ \
StringName enum_name = __constant_get_enum_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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
}
#define BIND_CORE_CONSTANT_NO_VAL(m_constant) \
#define BIND_CORE_CONSTANT_NO_VAL(m_constant) \
_global_constants.push_back(_CoreConstant(StringName(), #m_constant, m_constant, true)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1;
#define BIND_CORE_ENUM_CONSTANT_NO_VAL(m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant, true)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
#define BIND_CORE_ENUM_CONSTANT_NO_VAL(m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant, true)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
}
#define BIND_CORE_ENUM_CONSTANT_CUSTOM_NO_VAL(m_custom_name, m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant, true)); \
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
#define BIND_CORE_ENUM_CONSTANT_CUSTOM_NO_VAL(m_custom_name, m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant, true)); \
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
}
#else
#define BIND_CORE_CONSTANT(m_constant) \
#define BIND_CORE_CONSTANT(m_constant) \
_global_constants.push_back(_CoreConstant(StringName(), #m_constant, m_constant)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1;
#define BIND_CORE_ENUM_CONSTANT(m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
#define BIND_CORE_ENUM_CONSTANT(m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
}
#define BIND_CORE_BITFIELD_FLAG(m_constant) \
{ \
StringName enum_name = __constant_get_bitfield_name(m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
#define BIND_CORE_BITFIELD_FLAG(m_constant) \
{ \
StringName enum_name = __constant_get_bitfield_name(m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
}
// This just binds enum classes as if they were regular enum constants.
#define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \
{ \
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
#define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \
{ \
StringName enum_name = __constant_get_enum_name(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_enums[enum_name].push_back((_global_constants.ptr())[_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]); \
}
#define BIND_CORE_BITFIELD_CLASS_FLAG(m_enum, m_prefix, m_member) \
{ \
StringName enum_name = __constant_get_bitfield_name(m_enum::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); \
_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]); \
}
#define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \
{ \
StringName enum_name = __constant_get_enum_name(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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
}
#define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \
{ \
StringName enum_name = __constant_get_enum_name(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; \
#define BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(m_enum, m_name, m_member) \
{ \
StringName enum_name = __constant_get_bitfield_name(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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
}
#define BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(m_enum, m_name, m_member) \
{ \
StringName enum_name = __constant_get_bitfield_name(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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
}
#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); \
#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); \
_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]); \
}
#define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \
{ \
StringName enum_name = __constant_get_enum_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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
}
#define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \
{ \
StringName enum_name = __constant_get_enum_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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
}
#define BIND_CORE_CONSTANT_NO_VAL(m_constant) \
#define BIND_CORE_CONSTANT_NO_VAL(m_constant) \
_global_constants.push_back(_CoreConstant(StringName(), #m_constant, m_constant)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1;
#define BIND_CORE_ENUM_CONSTANT_NO_VAL(m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
#define BIND_CORE_ENUM_CONSTANT_NO_VAL(m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
}
#define BIND_CORE_ENUM_CONSTANT_CUSTOM_NO_VAL(m_custom_name, m_constant) \
{ \
StringName enum_name = __constant_get_enum_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; \
#define BIND_CORE_ENUM_CONSTANT_CUSTOM_NO_VAL(m_custom_name, m_constant) \
{ \
StringName enum_name = __constant_get_enum_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_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
}
@ -551,11 +549,6 @@ void register_global_constants() {
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, PADDLE3);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, PADDLE4);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, TOUCHPAD);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, MISC2);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, MISC3);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, MISC4);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, MISC5);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, MISC6);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, SDL_MAX);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, MAX);
@ -736,18 +729,6 @@ void register_global_constants() {
BIND_CORE_BITFIELD_FLAG(METHOD_FLAG_VIRTUAL_REQUIRED);
BIND_CORE_BITFIELD_FLAG(METHOD_FLAGS_DEFAULT);
BIND_CORE_CONSTANT(UINT8_MAX);
BIND_CORE_CONSTANT(UINT16_MAX);
BIND_CORE_CONSTANT(UINT32_MAX);
BIND_CORE_CONSTANT(INT8_MIN);
BIND_CORE_CONSTANT(INT8_MAX);
BIND_CORE_CONSTANT(INT16_MIN);
BIND_CORE_CONSTANT(INT16_MAX);
BIND_CORE_CONSTANT(INT32_MIN);
BIND_CORE_CONSTANT(INT32_MAX);
BIND_CORE_CONSTANT(INT64_MIN);
BIND_CORE_CONSTANT(INT64_MAX);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_NIL", Variant::NIL);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_BOOL", Variant::BOOL);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_INT", Variant::INT);

View file

@ -38,5 +38,4 @@ public:
static inline bool leak_reporting_enabled = true;
static inline bool print_line_enabled = true;
static inline bool print_error_enabled = true;
static inline bool print_ready = false;
};

View file

@ -28,9 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "aes_context.h"
#include "core/object/class_db.h"
#include "core/crypto/aes_context.h"
Error AESContext::start(Mode p_mode, const PackedByteArray &p_key, const PackedByteArray &p_iv) {
ERR_FAIL_COND_V_MSG(mode != MODE_MAX, ERR_ALREADY_IN_USE, "AESContext already started. Call 'finish' before starting a new one.");

View file

@ -32,7 +32,6 @@
#include "core/crypto/crypto_core.h"
#include "core/object/ref_counted.h"
#include "core/variant/type_info.h"
class AESContext : public RefCounted {
GDCLASS(AESContext, RefCounted);

View file

@ -30,8 +30,6 @@
#include "crypto.h"
#include "core/object/class_db.h"
/// Resources
CryptoKey *(*CryptoKey::_create)(bool p_notify_postinitialize) = nullptr;
@ -179,3 +177,82 @@ void Crypto::_bind_methods() {
ClassDB::bind_method(D_METHOD("hmac_digest", "hash_type", "key", "msg"), &Crypto::hmac_digest);
ClassDB::bind_method(D_METHOD("constant_time_compare", "trusted", "received"), &Crypto::constant_time_compare);
}
/// Resource loader/saver
Ref<Resource> ResourceFormatLoaderCrypto::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
String el = p_path.get_extension().to_lower();
if (el == "crt") {
X509Certificate *cert = X509Certificate::create();
if (cert) {
cert->load(p_path);
}
return cert;
} else if (el == "key") {
CryptoKey *key = CryptoKey::create();
if (key) {
key->load(p_path, false);
}
return key;
} else if (el == "pub") {
CryptoKey *key = CryptoKey::create();
if (key) {
key->load(p_path, true);
}
return key;
}
return nullptr;
}
void ResourceFormatLoaderCrypto::get_recognized_extensions(List<String> *p_extensions) const {
p_extensions->push_back("crt");
p_extensions->push_back("key");
p_extensions->push_back("pub");
}
bool ResourceFormatLoaderCrypto::handles_type(const String &p_type) const {
return p_type == "X509Certificate" || p_type == "CryptoKey";
}
String ResourceFormatLoaderCrypto::get_resource_type(const String &p_path) const {
String el = p_path.get_extension().to_lower();
if (el == "crt") {
return "X509Certificate";
} else if (el == "key" || el == "pub") {
return "CryptoKey";
}
return "";
}
Error ResourceFormatSaverCrypto::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) {
Error err;
Ref<X509Certificate> cert = p_resource;
Ref<CryptoKey> key = p_resource;
if (cert.is_valid()) {
err = cert->save(p_path);
} else if (key.is_valid()) {
err = key->save(p_path, p_path.has_extension("pub"));
} else {
ERR_FAIL_V(ERR_INVALID_PARAMETER);
}
ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Cannot save Crypto resource to file '%s'.", p_path));
return OK;
}
void ResourceFormatSaverCrypto::get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const {
const X509Certificate *cert = Object::cast_to<X509Certificate>(*p_resource);
const CryptoKey *key = Object::cast_to<CryptoKey>(*p_resource);
if (cert) {
p_extensions->push_back("crt");
}
if (key) {
if (!key->is_public_only()) {
p_extensions->push_back("key");
}
p_extensions->push_back("pub");
}
}
bool ResourceFormatSaverCrypto::recognize(const Ref<Resource> &p_resource) const {
return Object::cast_to<X509Certificate>(*p_resource) || Object::cast_to<CryptoKey>(*p_resource);
}

View file

@ -32,6 +32,8 @@
#include "core/crypto/hashing_context.h"
#include "core/io/resource.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
#include "core/object/ref_counted.h"
class CryptoKey : public Resource {
@ -142,3 +144,26 @@ public:
// @see: https://paragonie.com/blog/2015/11/preventing-timing-attacks-on-string-comparison-with-double-hmac-strategy
bool constant_time_compare(const PackedByteArray &p_trusted, const PackedByteArray &p_received);
};
class ResourceFormatLoaderCrypto : public ResourceFormatLoader {
GDSOFTCLASS(ResourceFormatLoaderCrypto, ResourceFormatLoader);
public:
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
virtual bool handles_type(const String &p_type) const override;
virtual String get_resource_type(const String &p_path) const override;
// Treat certificates as text files, do not generate a `*.{crt,key,pub}.uid` file.
virtual ResourceUID::ID get_resource_uid(const String &p_path) const override { return ResourceUID::INVALID_ID; }
virtual bool has_custom_uid_support() const override { return true; }
};
class ResourceFormatSaverCrypto : public ResourceFormatSaver {
GDSOFTCLASS(ResourceFormatSaverCrypto, ResourceFormatSaver);
public:
virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0) override;
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const override;
virtual bool recognize(const Ref<Resource> &p_resource) const override;
};

View file

@ -31,7 +31,6 @@
#include "crypto_core.h"
#include "core/os/os.h"
#include "core/string/ustring.h"
#include <mbedtls/aes.h>
#include <mbedtls/base64.h>

View file

@ -30,12 +30,7 @@
#pragma once
#include "core/error/error_list.h"
#include <cstddef>
#include <cstdint>
class String;
#include "core/object/ref_counted.h"
class CryptoCore {
public:

View file

@ -1,110 +0,0 @@
/**************************************************************************/
/* crypto_resource_format.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 "crypto_resource_format.h"
#include "core/crypto/crypto.h"
Ref<Resource> ResourceFormatLoaderCrypto::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
String el = p_path.get_extension().to_lower();
if (el == "crt") {
X509Certificate *cert = X509Certificate::create();
if (cert) {
cert->load(p_path);
}
return cert;
} else if (el == "key") {
CryptoKey *key = CryptoKey::create();
if (key) {
key->load(p_path, false);
}
return key;
} else if (el == "pub") {
CryptoKey *key = CryptoKey::create();
if (key) {
key->load(p_path, true);
}
return key;
}
return nullptr;
}
void ResourceFormatLoaderCrypto::get_recognized_extensions(List<String> *p_extensions) const {
p_extensions->push_back("crt");
p_extensions->push_back("key");
p_extensions->push_back("pub");
}
bool ResourceFormatLoaderCrypto::handles_type(const String &p_type) const {
return p_type == "X509Certificate" || p_type == "CryptoKey";
}
String ResourceFormatLoaderCrypto::get_resource_type(const String &p_path) const {
String el = p_path.get_extension().to_lower();
if (el == "crt") {
return "X509Certificate";
} else if (el == "key" || el == "pub") {
return "CryptoKey";
}
return "";
}
Error ResourceFormatSaverCrypto::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) {
Error err;
Ref<X509Certificate> cert = p_resource;
Ref<CryptoKey> key = p_resource;
if (cert.is_valid()) {
err = cert->save(p_path);
} else if (key.is_valid()) {
err = key->save(p_path, p_path.has_extension("pub"));
} else {
ERR_FAIL_V(ERR_INVALID_PARAMETER);
}
ERR_FAIL_COND_V_MSG(err != OK, err, vformat("Cannot save Crypto resource to file '%s'.", p_path));
return OK;
}
void ResourceFormatSaverCrypto::get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const {
const X509Certificate *cert = Object::cast_to<X509Certificate>(*p_resource);
const CryptoKey *key = Object::cast_to<CryptoKey>(*p_resource);
if (cert) {
p_extensions->push_back("crt");
}
if (key) {
if (!key->is_public_only()) {
p_extensions->push_back("key");
}
p_extensions->push_back("pub");
}
}
bool ResourceFormatSaverCrypto::recognize(const Ref<Resource> &p_resource) const {
return Object::cast_to<X509Certificate>(*p_resource) || Object::cast_to<CryptoKey>(*p_resource);
}

View file

@ -1,58 +0,0 @@
/**************************************************************************/
/* crypto_resource_format.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/resource_loader.h"
#include "core/io/resource_saver.h"
#include "core/io/resource_uid.h"
class ResourceFormatLoaderCrypto : public ResourceFormatLoader {
GDSOFTCLASS(ResourceFormatLoaderCrypto, ResourceFormatLoader);
public:
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
virtual bool handles_type(const String &p_type) const override;
virtual String get_resource_type(const String &p_path) const override;
// Treat certificates as text files, do not generate a `*.{crt,key,pub}.uid` file.
virtual ResourceUID::ID get_resource_uid(const String &p_path) const override { return ResourceUID::INVALID_ID; }
virtual bool has_custom_uid_support() const override { return true; }
};
class ResourceFormatSaverCrypto : public ResourceFormatSaver {
GDSOFTCLASS(ResourceFormatSaverCrypto, ResourceFormatSaver);
public:
virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0) override;
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const override;
virtual bool recognize(const Ref<Resource> &p_resource) const override;
};

View file

@ -31,7 +31,6 @@
#include "hashing_context.h"
#include "core/crypto/crypto_core.h"
#include "core/object/class_db.h"
Error HashingContext::start(HashType p_type) {
ERR_FAIL_COND_V(ctx != nullptr, ERR_ALREADY_IN_USE);

View file

@ -31,7 +31,6 @@
#pragma once
#include "core/object/ref_counted.h"
#include "core/variant/type_info.h"
class HashingContext : public RefCounted {
GDCLASS(HashingContext, RefCounted);

View file

@ -81,20 +81,16 @@ Array DebuggerMarshalls::ScriptStackVariable::serialize(int max_size) {
} else {
arr.push_back(var);
}
arr.push_back(type_hint);
return arr;
}
bool DebuggerMarshalls::ScriptStackVariable::deserialize(const Array &p_arr) {
CHECK_SIZE(p_arr, 5, "ScriptStackVariable");
CHECK_SIZE(p_arr, 4, "ScriptStackVariable");
name = p_arr[0];
type = p_arr[1];
var_type = p_arr[2];
value = p_arr[3];
type_hint = p_arr[4];
CHECK_END(p_arr, 5, "ScriptStackVariable");
CHECK_END(p_arr, 4, "ScriptStackVariable");
return true;
}
@ -181,27 +177,3 @@ Ref<Shortcut> DebuggerMarshalls::deserialize_key_shortcut(const Array &p_keys) {
shortcut->set_events(key_events);
return shortcut;
}
String DebuggerMarshalls::parse_type_from_variant(const Variant &p_variant) {
String name;
if (p_variant.get_type() == Variant::OBJECT) {
const Object *obj = p_variant.get_validated_object();
if (obj) {
const ScriptInstance *script_instance = obj->get_script_instance();
if (script_instance) {
Ref<Script> script = script_instance->get_script();
if (script.is_valid()) {
name = script->get_global_name();
}
}
if (name.is_empty()) {
return obj->get_class();
}
}
}
return name;
}

View file

@ -39,7 +39,6 @@ struct DebuggerMarshalls {
Variant value;
int type = -1;
int var_type = -1;
String type_hint;
Array serialize(int max_size = 1 << 20); // 1 MiB default.
bool deserialize(const Array &p_arr);
@ -71,6 +70,4 @@ struct DebuggerMarshalls {
static Array serialize_key_shortcut(const Ref<Shortcut> &p_shortcut);
static Ref<Shortcut> deserialize_key_shortcut(const Array &p_keys);
static String parse_type_from_variant(const Variant &p_variant);
};

View file

@ -138,8 +138,8 @@ void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, bo
CreatePeerFunc *create_fn = protocols.getptr(proto);
ERR_FAIL_NULL_MSG(create_fn, vformat("Invalid protocol: %s.", proto));
Ref<RemoteDebuggerPeer> peer = (*create_fn)(p_uri);
if (peer.is_null()) {
RemoteDebuggerPeer *peer = (*create_fn)(p_uri);
if (!peer) {
return;
}
singleton = memnew(RemoteDebugger(Ref<RemoteDebuggerPeer>(peer)));

View file

@ -30,7 +30,6 @@
#pragma once
#include "core/object/ref_counted.h"
#include "core/string/string_name.h"
#include "core/string/ustring.h"
#include "core/templates/hash_map.h"
@ -48,7 +47,7 @@ public:
typedef Error (*CaptureFunc)(void *p_user, const String &p_msg, const Array &p_args, bool &r_captured);
typedef Ref<RemoteDebuggerPeer> (*CreatePeerFunc)(const String &p_uri);
typedef RemoteDebuggerPeer *(*CreatePeerFunc)(const String &p_uri);
class Profiler {
friend class EngineDebugger;

View file

@ -31,7 +31,6 @@
#include "engine_profiler.h"
#include "core/debugger/engine_debugger.h"
#include "core/object/class_db.h" // IWYU pragma: keep. `GDVIRTUAL_BIND` macro.
void EngineProfiler::_bind_methods() {
GDVIRTUAL_BIND(_toggle, "enable", "options");

View file

@ -30,7 +30,7 @@
#pragma once
#include "core/object/gdvirtual.gen.h"
#include "core/object/gdvirtual.gen.inc"
#include "core/object/ref_counted.h"
class EngineProfiler : public RefCounted {

View file

@ -34,8 +34,6 @@
#include "core/os/main_loop.h"
#include "core/os/os.h"
#include <cstdio>
struct LocalDebugger::ScriptsProfiler {
struct ProfileInfoSort {
bool operator()(const ScriptLanguage::ProfilingInfo &A, const ScriptLanguage::ProfilingInfo &B) const {

View file

@ -31,6 +31,7 @@
#pragma once
#include "core/debugger/engine_debugger.h"
#include "core/object/script_language.h"
#include "core/templates/list.h"
class LocalDebugger : public EngineDebugger {

View file

@ -30,7 +30,6 @@
#include "remote_debugger.h"
#include "core/config/engine.h"
#include "core/config/project_settings.h"
#include "core/debugger/debugger_marshalls.h"
#include "core/debugger/engine_debugger.h"
@ -39,7 +38,6 @@
#include "core/input/input.h"
#include "core/io/resource_loader.h"
#include "core/math/expression.h"
#include "core/object/class_db.h"
#include "core/object/script_language.h"
#include "core/os/os.h"
#include "servers/display/display_server.h"
@ -329,7 +327,6 @@ void RemoteDebugger::_send_stack_vars(List<String> &p_names, List<Variant> &p_va
stvar.name = E->get();
stvar.value = F->get();
stvar.type = p_type;
stvar.type_hint = DebuggerMarshalls::parse_type_from_variant(F->get());
send_message("stack_frame_var", stvar.serialize());
E = E->next();
F = F->next();
@ -429,12 +426,12 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
}
send_message("debug_enter", msg);
Input::MouseMode mouse_mode = Input::MouseMode::MOUSE_MODE_VISIBLE;
Input::MouseMode mouse_mode = Input::MOUSE_MODE_VISIBLE;
if (Thread::is_main_thread()) {
mouse_mode = Input::get_singleton()->get_mouse_mode();
if (mouse_mode != Input::MouseMode::MOUSE_MODE_VISIBLE) {
Input::get_singleton()->set_mouse_mode(Input::MouseMode::MOUSE_MODE_VISIBLE);
if (mouse_mode != Input::MOUSE_MODE_VISIBLE) {
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
}
} else {
MutexLock mutex_lock(mutex);

View file

@ -33,6 +33,8 @@
#include "core/debugger/debugger_marshalls.h"
#include "core/debugger/engine_debugger.h"
#include "core/debugger/remote_debugger_peer.h"
#include "core/object/class_db.h"
#include "core/string/string_name.h"
#include "core/string/ustring.h"
#include "core/variant/array.h"

View file

@ -32,9 +32,6 @@
#include "core/config/project_settings.h"
#include "core/io/marshalls.h"
#include "core/io/stream_peer_socket.h"
#include "core/io/stream_peer_tcp.h"
#include "core/io/stream_peer_uds.h"
#include "core/os/os.h"
bool RemoteDebuggerPeerTCP::is_peer_connected() {
@ -211,7 +208,7 @@ void RemoteDebuggerPeerTCP::_poll() {
}
}
Ref<RemoteDebuggerPeer> RemoteDebuggerPeerTCP::create_tcp(const String &p_uri) {
RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create_tcp(const String &p_uri) {
ERR_FAIL_COND_V(!p_uri.begins_with("tcp://"), nullptr);
String debug_host = p_uri.replace("tcp://", "");
@ -237,7 +234,7 @@ Ref<RemoteDebuggerPeer> RemoteDebuggerPeerTCP::create_tcp(const String &p_uri) {
return memnew(RemoteDebuggerPeerTCP(stream));
}
Ref<RemoteDebuggerPeer> RemoteDebuggerPeerTCP::create_unix(const String &p_uri) {
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://", "");

View file

@ -30,13 +30,13 @@
#pragma once
#include "core/io/stream_peer_tcp.h"
#include "core/io/stream_peer_uds.h"
#include "core/object/ref_counted.h"
#include "core/os/mutex.h"
#include "core/os/thread.h"
#include "core/string/ustring.h"
class StreamPeerSocket;
class RemoteDebuggerPeer : public RefCounted {
GDSOFTCLASS(RemoteDebuggerPeer, RefCounted);
@ -82,8 +82,8 @@ private:
static Error _try_connect(Ref<StreamPeerSocket> p_stream);
public:
static Ref<RemoteDebuggerPeer> create_tcp(const String &p_uri);
static Ref<RemoteDebuggerPeer> create_unix(const String &p_uri);
static RemoteDebuggerPeer *create_tcp(const String &p_uri);
static RemoteDebuggerPeer *create_unix(const String &p_uri);
bool is_peer_connected() override;
int get_max_message_size() const override;

View file

@ -30,9 +30,6 @@
#include "doc_data.h"
#include "core/object/method_info.h"
#include "core/object/property_info.h"
String DocData::get_default_value_string(const Variant &p_value) {
const Variant::Type type = p_value.get_type();
if (type == Variant::ARRAY) {

View file

@ -30,6 +30,7 @@
#pragma once
#include "core/io/xml_parser.h"
#include "core/variant/variant.h"
class DocData {
@ -698,7 +699,6 @@ public:
struct ClassDoc {
String name;
String inherits;
String api_type;
String brief_description;
String description;
String keywords;
@ -732,10 +732,6 @@ public:
doc.inherits = p_dict["inherits"];
}
if (p_dict.has("api_type")) {
doc.api_type = p_dict["api_type"];
}
if (p_dict.has("brief_description")) {
doc.brief_description = p_dict["brief_description"];
}
@ -869,10 +865,6 @@ public:
dict["inherits"] = p_doc.inherits;
}
if (!p_doc.api_type.is_empty()) {
dict["api_type"] = p_doc.api_type;
}
if (!p_doc.brief_description.is_empty()) {
dict["brief_description"] = p_doc.brief_description;
}

View file

@ -30,15 +30,12 @@
#include "error_macros.h"
#include "core/core_globals.h"
#include "core/io/logger.h"
#include "core/object/object_id.h"
#include "core/object/script_language.h"
#include "core/os/os.h"
#include "core/string/ustring.h"
#include <cstdio>
// Optional physics interpolation warnings try to include the path to the relevant node.
#if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)
#include "core/config/project_settings.h"
@ -107,12 +104,6 @@ void _err_print_error(const char *p_function, const char *p_file, int p_line, co
// Main error printing function.
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_editor_notify, ErrorHandlerType p_type) {
if (!CoreGlobals::print_ready) {
const char *err_details = (p_message && *p_message) ? p_message : p_error;
_err_print_fallback(p_function, p_file, p_line, err_details, p_type, false);
return;
}
if (is_printing_error) {
// Fallback if we're already printing an error, to prevent infinite recursion.
const char *err_details = (p_message && *p_message) ? p_message : p_error;
@ -149,11 +140,6 @@ void _err_print_error(const char *p_function, const char *p_file, int p_line, co
void _err_print_error_asap(const String &p_error, ErrorHandlerType p_type) {
const char *err_details = p_error.utf8().get_data();
if (!CoreGlobals::print_ready) {
_err_print_fallback(nullptr, nullptr, 0, err_details, p_type, false);
return;
}
if (is_printing_error) {
// Fallback if we're already printing an error, to prevent infinite recursion.
_err_print_fallback(nullptr, nullptr, 0, err_details, p_type, true);

View file

@ -32,6 +32,10 @@
#include "core/typedefs.h"
#ifdef _MSC_VER
#include <intrin.h> // `__fastfail()`.
#endif
class String;
class ObjectID;
@ -91,11 +95,11 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
#define FUNCTION_STR __FUNCTION__
#endif
#if defined(_MSC_VER) && !defined(__clang__)
#ifdef _MSC_VER
/**
* Don't use GENERATE_TRAP() directly, should only be used be the macros below.
*/
#define GENERATE_TRAP() __debugbreak()
#define GENERATE_TRAP() __fastfail(7 /* FAST_FAIL_FATAL_APP_EXIT */)
#else
/**
* Don't use GENERATE_TRAP() directly, should only be used be the macros below.
@ -131,32 +135,32 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
* If not, the current function returns.
*/
#define ERR_FAIL_INDEX(m_index, m_size) \
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
#define ERR_FAIL_INDEX(m_index, m_size) \
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
return; \
} else \
return; \
} else \
((void)0)
/**
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
* If not, prints `m_msg` and the current function returns.
*/
#define ERR_FAIL_INDEX_MSG(m_index, m_size, m_msg) \
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
#define ERR_FAIL_INDEX_MSG(m_index, m_size, m_msg) \
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg); \
return; \
} else \
return; \
} else \
((void)0)
/**
* Same as `ERR_FAIL_INDEX_MSG` but also notifies the editor.
*/
#define ERR_FAIL_INDEX_EDMSG(m_index, m_size, m_msg) \
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
#define ERR_FAIL_INDEX_EDMSG(m_index, m_size, m_msg) \
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
return; \
} else \
return; \
} else \
((void)0)
/**
@ -166,32 +170,32 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
* If not, the current function returns `m_retval`.
*/
#define ERR_FAIL_INDEX_V(m_index, m_size, m_retval) \
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
#define ERR_FAIL_INDEX_V(m_index, m_size, m_retval) \
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
return m_retval; \
} else \
return m_retval; \
} else \
((void)0)
/**
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
* If not, prints `m_msg` and the current function returns `m_retval`.
*/
#define ERR_FAIL_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
#define ERR_FAIL_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg); \
return m_retval; \
} else \
return m_retval; \
} else \
((void)0)
/**
* Same as `ERR_FAIL_INDEX_V_MSG` but also notifies the editor.
*/
#define ERR_FAIL_INDEX_V_EDMSG(m_index, m_size, m_retval, m_msg) \
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
#define ERR_FAIL_INDEX_V_EDMSG(m_index, m_size, m_retval, m_msg) \
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
return m_retval; \
} else \
return m_retval; \
} else \
((void)0)
/**
@ -202,12 +206,12 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
* If not, the application crashes.
*/
#define CRASH_BAD_INDEX(m_index, m_size) \
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
#define CRASH_BAD_INDEX(m_index, m_size) \
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), "", false, true); \
_err_flush_stdout(); \
GENERATE_TRAP(); \
} else \
_err_flush_stdout(); \
GENERATE_TRAP(); \
} else \
((void)0)
/**
@ -217,12 +221,12 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
* Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
* If not, prints `m_msg` and the application crashes.
*/
#define CRASH_BAD_INDEX_MSG(m_index, m_size, m_msg) \
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
#define CRASH_BAD_INDEX_MSG(m_index, m_size, m_msg) \
if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, false, true); \
_err_flush_stdout(); \
GENERATE_TRAP(); \
} else \
_err_flush_stdout(); \
GENERATE_TRAP(); \
} else \
((void)0)
// Unsigned integer index out of bounds error macros.
@ -234,32 +238,32 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
* Ensures an unsigned integer index `m_index` is less than `m_size`.
* If not, the current function returns.
*/
#define ERR_FAIL_UNSIGNED_INDEX(m_index, m_size) \
if (unlikely((m_index) >= (m_size))) { \
#define ERR_FAIL_UNSIGNED_INDEX(m_index, m_size) \
if (unlikely((m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
return; \
} else \
return; \
} else \
((void)0)
/**
* Ensures an unsigned integer index `m_index` is less than `m_size`.
* If not, prints `m_msg` and the current function returns.
*/
#define ERR_FAIL_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg) \
if (unlikely((m_index) >= (m_size))) { \
#define ERR_FAIL_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg) \
if (unlikely((m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg); \
return; \
} else \
return; \
} else \
((void)0)
/**
* Same as `ERR_FAIL_UNSIGNED_INDEX_MSG` but also notifies the editor.
*/
#define ERR_FAIL_UNSIGNED_INDEX_EDMSG(m_index, m_size, m_msg) \
if (unlikely((m_index) >= (m_size))) { \
#define ERR_FAIL_UNSIGNED_INDEX_EDMSG(m_index, m_size, m_msg) \
if (unlikely((m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
return; \
} else \
return; \
} else \
((void)0)
/**
@ -269,32 +273,32 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
* Ensures an unsigned integer index `m_index` is less than `m_size`.
* If not, the current function returns `m_retval`.
*/
#define ERR_FAIL_UNSIGNED_INDEX_V(m_index, m_size, m_retval) \
if (unlikely((m_index) >= (m_size))) { \
#define ERR_FAIL_UNSIGNED_INDEX_V(m_index, m_size, m_retval) \
if (unlikely((m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
return m_retval; \
} else \
return m_retval; \
} else \
((void)0)
/**
* Ensures an unsigned integer index `m_index` is less than `m_size`.
* If not, prints `m_msg` and the current function returns `m_retval`.
*/
#define ERR_FAIL_UNSIGNED_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \
if (unlikely((m_index) >= (m_size))) { \
#define ERR_FAIL_UNSIGNED_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \
if (unlikely((m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg); \
return m_retval; \
} else \
return m_retval; \
} else \
((void)0)
/**
* Same as `ERR_FAIL_UNSIGNED_INDEX_V_MSG` but also notifies the editor.
*/
#define ERR_FAIL_UNSIGNED_INDEX_V_EDMSG(m_index, m_size, m_retval, m_msg) \
if (unlikely((m_index) >= (m_size))) { \
#define ERR_FAIL_UNSIGNED_INDEX_V_EDMSG(m_index, m_size, m_retval, m_msg) \
if (unlikely((m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \
return m_retval; \
} else \
return m_retval; \
} else \
((void)0)
/**
@ -305,12 +309,12 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
* Ensures an unsigned integer index `m_index` is less than `m_size`.
* If not, the application crashes.
*/
#define CRASH_BAD_UNSIGNED_INDEX(m_index, m_size) \
if (unlikely((m_index) >= (m_size))) { \
#define CRASH_BAD_UNSIGNED_INDEX(m_index, m_size) \
if (unlikely((m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), "", false, true); \
_err_flush_stdout(); \
GENERATE_TRAP(); \
} else \
_err_flush_stdout(); \
GENERATE_TRAP(); \
} else \
((void)0)
/**
@ -320,12 +324,12 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
* Ensures an unsigned integer index `m_index` is less than `m_size`.
* If not, prints `m_msg` and the application crashes.
*/
#define CRASH_BAD_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg) \
if (unlikely((m_index) >= (m_size))) { \
#define CRASH_BAD_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg) \
if (unlikely((m_index) >= (m_size))) { \
_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, false, true); \
_err_flush_stdout(); \
GENERATE_TRAP(); \
} else \
_err_flush_stdout(); \
GENERATE_TRAP(); \
} else \
((void)0)
// Null reference error macros.
@ -337,32 +341,32 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
* Ensures a pointer `m_param` is not null.
* If it is null, the current function returns.
*/
#define ERR_FAIL_NULL(m_param) \
if (unlikely(m_param == nullptr)) { \
#define ERR_FAIL_NULL(m_param) \
if (unlikely(m_param == nullptr)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \
return; \
} else \
return; \
} else \
((void)0)
/**
* Ensures a pointer `m_param` is not null.
* If it is null, prints `m_msg` and the current function returns.
*/
#define ERR_FAIL_NULL_MSG(m_param, m_msg) \
if (unlikely(m_param == nullptr)) { \
#define ERR_FAIL_NULL_MSG(m_param, m_msg) \
if (unlikely(m_param == nullptr)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg); \
return; \
} else \
return; \
} else \
((void)0)
/**
* Same as `ERR_FAIL_NULL_MSG` but also notifies the editor.
*/
#define ERR_FAIL_NULL_EDMSG(m_param, m_msg) \
if (unlikely(m_param == nullptr)) { \
#define ERR_FAIL_NULL_EDMSG(m_param, m_msg) \
if (unlikely(m_param == nullptr)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg, true); \
return; \
} else \
return; \
} else \
((void)0)
/**
@ -372,32 +376,32 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
* Ensures a pointer `m_param` is not null.
* If it is null, the current function returns `m_retval`.
*/
#define ERR_FAIL_NULL_V(m_param, m_retval) \
if (unlikely(m_param == nullptr)) { \
#define ERR_FAIL_NULL_V(m_param, m_retval) \
if (unlikely(m_param == nullptr)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \
return m_retval; \
} else \
return m_retval; \
} else \
((void)0)
/**
* Ensures a pointer `m_param` is not null.
* If it is null, prints `m_msg` and the current function returns `m_retval`.
*/
#define ERR_FAIL_NULL_V_MSG(m_param, m_retval, m_msg) \
if (unlikely(m_param == nullptr)) { \
#define ERR_FAIL_NULL_V_MSG(m_param, m_retval, m_msg) \
if (unlikely(m_param == nullptr)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg); \
return m_retval; \
} else \
return m_retval; \
} else \
((void)0)
/**
* Same as `ERR_FAIL_NULL_V_MSG` but also notifies the editor.
*/
#define ERR_FAIL_NULL_V_EDMSG(m_param, m_retval, m_msg) \
if (unlikely(m_param == nullptr)) { \
#define ERR_FAIL_NULL_V_EDMSG(m_param, m_retval, m_msg) \
if (unlikely(m_param == nullptr)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg, true); \
return m_retval; \
} else \
return m_retval; \
} else \
((void)0)
/**
@ -409,11 +413,11 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
* Ensures `m_cond` is false.
* If `m_cond` is true, the current function returns.
*/
#define ERR_FAIL_COND(m_cond) \
if (unlikely(m_cond)) { \
#define ERR_FAIL_COND(m_cond) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true."); \
return; \
} else \
return; \
} else \
((void)0)
/**
@ -423,21 +427,21 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
* If checking for null use ERR_FAIL_NULL_MSG instead.
* If checking index bounds use ERR_FAIL_INDEX_MSG instead.
*/
#define ERR_FAIL_COND_MSG(m_cond, m_msg) \
if (unlikely(m_cond)) { \
#define ERR_FAIL_COND_MSG(m_cond, m_msg) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true.", m_msg); \
return; \
} else \
return; \
} else \
((void)0)
/**
* Same as `ERR_FAIL_COND_MSG` but also notifies the editor.
*/
#define ERR_FAIL_COND_EDMSG(m_cond, m_msg) \
if (unlikely(m_cond)) { \
#define ERR_FAIL_COND_EDMSG(m_cond, m_msg) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true.", m_msg, true); \
return; \
} else \
return; \
} else \
((void)0)
/**
@ -449,11 +453,11 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
* Ensures `m_cond` is false.
* If `m_cond` is true, the current function returns `m_retval`.
*/
#define ERR_FAIL_COND_V(m_cond, m_retval) \
if (unlikely(m_cond)) { \
#define ERR_FAIL_COND_V(m_cond, m_retval) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval)); \
return m_retval; \
} else \
return m_retval; \
} else \
((void)0)
/**
@ -463,21 +467,21 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
* If checking for null use ERR_FAIL_NULL_V_MSG instead.
* If checking index bounds use ERR_FAIL_INDEX_V_MSG instead.
*/
#define ERR_FAIL_COND_V_MSG(m_cond, m_retval, m_msg) \
if (unlikely(m_cond)) { \
#define ERR_FAIL_COND_V_MSG(m_cond, m_retval, m_msg) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval), m_msg); \
return m_retval; \
} else \
return m_retval; \
} else \
((void)0)
/**
* Same as `ERR_FAIL_COND_V_MSG` but also notifies the editor.
*/
#define ERR_FAIL_COND_V_EDMSG(m_cond, m_retval, m_msg) \
if (unlikely(m_cond)) { \
#define ERR_FAIL_COND_V_EDMSG(m_cond, m_retval, m_msg) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval), m_msg, true); \
return m_retval; \
} else \
return m_retval; \
} else \
((void)0)
/**
@ -487,32 +491,32 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
* Ensures `m_cond` is false.
* If `m_cond` is true, the current loop continues.
*/
#define ERR_CONTINUE(m_cond) \
if (unlikely(m_cond)) { \
#define ERR_CONTINUE(m_cond) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing."); \
continue; \
} else \
continue; \
} else \
((void)0)
/**
* Ensures `m_cond` is false.
* If `m_cond` is true, prints `m_msg` and the current loop continues.
*/
#define ERR_CONTINUE_MSG(m_cond, m_msg) \
if (unlikely(m_cond)) { \
#define ERR_CONTINUE_MSG(m_cond, m_msg) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing.", m_msg); \
continue; \
} else \
continue; \
} else \
((void)0)
/**
* Same as `ERR_CONTINUE_MSG` but also notifies the editor.
*/
#define ERR_CONTINUE_EDMSG(m_cond, m_msg) \
if (unlikely(m_cond)) { \
#define ERR_CONTINUE_EDMSG(m_cond, m_msg) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing.", m_msg, true); \
continue; \
} else \
continue; \
} else \
((void)0)
/**
@ -522,32 +526,32 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
* Ensures `m_cond` is false.
* If `m_cond` is true, the current loop breaks.
*/
#define ERR_BREAK(m_cond) \
if (unlikely(m_cond)) { \
#define ERR_BREAK(m_cond) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking."); \
break; \
} else \
break; \
} else \
((void)0)
/**
* Ensures `m_cond` is false.
* If `m_cond` is true, prints `m_msg` and the current loop breaks.
*/
#define ERR_BREAK_MSG(m_cond, m_msg) \
if (unlikely(m_cond)) { \
#define ERR_BREAK_MSG(m_cond, m_msg) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking.", m_msg); \
break; \
} else \
break; \
} else \
((void)0)
/**
* Same as `ERR_BREAK_MSG` but also notifies the editor.
*/
#define ERR_BREAK_EDMSG(m_cond, m_msg) \
if (unlikely(m_cond)) { \
#define ERR_BREAK_EDMSG(m_cond, m_msg) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking.", m_msg, true); \
break; \
} else \
break; \
} else \
((void)0)
/**
@ -558,12 +562,12 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
* Ensures `m_cond` is false.
* If `m_cond` is true, the application crashes.
*/
#define CRASH_COND(m_cond) \
if (unlikely(m_cond)) { \
#define CRASH_COND(m_cond) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true."); \
_err_flush_stdout(); \
GENERATE_TRAP(); \
} else \
_err_flush_stdout(); \
GENERATE_TRAP(); \
} else \
((void)0)
/**
@ -573,12 +577,12 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
* Ensures `m_cond` is false.
* If `m_cond` is true, prints `m_msg` and the application crashes.
*/
#define CRASH_COND_MSG(m_cond, m_msg) \
if (unlikely(m_cond)) { \
#define CRASH_COND_MSG(m_cond, m_msg) \
if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true.", m_msg); \
_err_flush_stdout(); \
GENERATE_TRAP(); \
} else \
_err_flush_stdout(); \
GENERATE_TRAP(); \
} else \
((void)0)
// Generic error macros.
@ -590,11 +594,11 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
*
* The current function returns.
*/
#define ERR_FAIL() \
if (true) { \
#define ERR_FAIL() \
if (true) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed."); \
return; \
} else \
return; \
} else \
((void)0)
/**
@ -603,21 +607,21 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
*
* Prints `m_msg`, and the current function returns.
*/
#define ERR_FAIL_MSG(m_msg) \
if (true) { \
#define ERR_FAIL_MSG(m_msg) \
if (true) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed.", m_msg); \
return; \
} else \
return; \
} else \
((void)0)
/**
* Same as `ERR_FAIL_MSG` but also notifies the editor.
*/
#define ERR_FAIL_EDMSG(m_msg) \
if (true) { \
#define ERR_FAIL_EDMSG(m_msg) \
if (true) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed.", m_msg, true); \
return; \
} else \
return; \
} else \
((void)0)
/**
@ -627,11 +631,11 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
*
* The current function returns `m_retval`.
*/
#define ERR_FAIL_V(m_retval) \
if (true) { \
#define ERR_FAIL_V(m_retval) \
if (true) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval)); \
return m_retval; \
} else \
return m_retval; \
} else \
((void)0)
/**
@ -640,21 +644,21 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
*
* Prints `m_msg`, and the current function returns `m_retval`.
*/
#define ERR_FAIL_V_MSG(m_retval, m_msg) \
if (true) { \
#define ERR_FAIL_V_MSG(m_retval, m_msg) \
if (true) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval), m_msg); \
return m_retval; \
} else \
return m_retval; \
} else \
((void)0)
/**
* Same as `ERR_FAIL_V_MSG` but also notifies the editor.
*/
#define ERR_FAIL_V_EDMSG(m_retval, m_msg) \
if (true) { \
#define ERR_FAIL_V_EDMSG(m_retval, m_msg) \
if (true) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval), m_msg, true); \
return m_retval; \
} else \
return m_retval; \
} else \
((void)0)
/**
@ -676,27 +680,27 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
/**
* Prints `m_msg` once during the application lifetime.
*/
#define ERR_PRINT_ONCE(m_msg) \
if (true) { \
static bool warning_shown = false; \
if (unlikely(!warning_shown)) { \
warning_shown = true; \
#define ERR_PRINT_ONCE(m_msg) \
if (true) { \
static bool warning_shown = false; \
if (unlikely(!warning_shown)) { \
warning_shown = true; \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg); \
} \
} else \
} \
} else \
((void)0)
/**
* Same as `ERR_PRINT_ONCE` but also notifies the editor.
*/
#define ERR_PRINT_ONCE_ED(m_msg) \
if (true) { \
static bool warning_shown = false; \
if (unlikely(!warning_shown)) { \
warning_shown = true; \
#define ERR_PRINT_ONCE_ED(m_msg) \
if (true) { \
static bool warning_shown = false; \
if (unlikely(!warning_shown)) { \
warning_shown = true; \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true); \
} \
} else \
} \
} else \
((void)0)
// Print warning message macros.
@ -720,37 +724,37 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
*
* If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead.
*/
#define WARN_PRINT_ONCE(m_msg) \
if (true) { \
static bool warning_shown = false; \
if (unlikely(!warning_shown)) { \
warning_shown = true; \
#define WARN_PRINT_ONCE(m_msg) \
if (true) { \
static bool warning_shown = false; \
if (unlikely(!warning_shown)) { \
warning_shown = true; \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, false, ERR_HANDLER_WARNING); \
} \
} else \
} \
} else \
((void)0)
/**
* Same as `WARN_PRINT_ONCE` but also notifies the editor.
*/
#define WARN_PRINT_ONCE_ED(m_msg) \
if (true) { \
static bool warning_shown = false; \
if (unlikely(!warning_shown)) { \
warning_shown = true; \
#define WARN_PRINT_ONCE_ED(m_msg) \
if (true) { \
static bool warning_shown = false; \
if (unlikely(!warning_shown)) { \
warning_shown = true; \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true, ERR_HANDLER_WARNING); \
} \
} else \
} \
} else \
((void)0)
/**
* Warns about `m_msg` only when verbose mode is enabled.
*/
#define WARN_VERBOSE(m_msg) \
{ \
#define WARN_VERBOSE(m_msg) \
{ \
if (is_print_verbose_enabled()) { \
WARN_PRINT(m_msg); \
} \
WARN_PRINT(m_msg); \
} \
}
// Print deprecated warning message macros.
@ -758,27 +762,27 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
/**
* Warns that the current function is deprecated.
*/
#define WARN_DEPRECATED \
if (true) { \
static bool warning_shown = false; \
if (unlikely(!warning_shown)) { \
warning_shown = true; \
#define WARN_DEPRECATED \
if (true) { \
static bool warning_shown = false; \
if (unlikely(!warning_shown)) { \
warning_shown = true; \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", false, ERR_HANDLER_WARNING); \
} \
} else \
} \
} else \
((void)0)
/**
* Warns that the current function is deprecated and prints `m_msg`.
*/
#define WARN_DEPRECATED_MSG(m_msg) \
if (true) { \
static bool warning_shown = false; \
if (unlikely(!warning_shown)) { \
warning_shown = true; \
#define WARN_DEPRECATED_MSG(m_msg) \
if (true) { \
static bool warning_shown = false; \
if (unlikely(!warning_shown)) { \
warning_shown = true; \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", m_msg, false, ERR_HANDLER_WARNING); \
} \
} else \
} \
} else \
((void)0)
/**
@ -787,12 +791,12 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
*
* The application crashes.
*/
#define CRASH_NOW() \
if (true) { \
#define CRASH_NOW() \
if (true) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/function failed."); \
_err_flush_stdout(); \
GENERATE_TRAP(); \
} else \
_err_flush_stdout(); \
GENERATE_TRAP(); \
} else \
((void)0)
/**
@ -800,12 +804,12 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
*
* Prints `m_msg`, and then the application crashes.
*/
#define CRASH_NOW_MSG(m_msg) \
if (true) { \
#define CRASH_NOW_MSG(m_msg) \
if (true) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/function failed.", m_msg); \
_err_flush_stdout(); \
GENERATE_TRAP(); \
} else \
_err_flush_stdout(); \
GENERATE_TRAP(); \
} else \
((void)0)
/**
@ -824,26 +828,26 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
* and that can't fail for other contributors once the code is finished and merged.
*/
#ifdef DEV_ENABLED
#define DEV_ASSERT(m_cond) \
if (unlikely(!(m_cond))) { \
#define DEV_ASSERT(m_cond) \
if (unlikely(!(m_cond))) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: DEV_ASSERT failed \"" _STR(m_cond) "\" is false."); \
_err_flush_stdout(); \
GENERATE_TRAP(); \
} else \
_err_flush_stdout(); \
GENERATE_TRAP(); \
} else \
((void)0)
#else
#define DEV_ASSERT(m_cond)
#endif
#ifdef DEV_ENABLED
#define DEV_CHECK_ONCE(m_cond) \
if (true) { \
static bool first_print = true; \
if (first_print && unlikely(!(m_cond))) { \
#define DEV_CHECK_ONCE(m_cond) \
if (true) { \
static bool first_print = true; \
if (first_print && unlikely(!(m_cond))) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "DEV_CHECK_ONCE failed \"" _STR(m_cond) "\" is false."); \
first_print = false; \
} \
} else \
first_print = false; \
} \
} else \
((void)0)
#else
#define DEV_CHECK_ONCE(m_cond)

View file

@ -7,7 +7,7 @@ import make_interface_dumper
import make_interface_header
import make_wrappers
env.CommandNoCache("ext_wrappers.gen.h", "make_wrappers.py", env.Run(make_wrappers.run))
env.CommandNoCache(["ext_wrappers.gen.inc"], "make_wrappers.py", env.Run(make_wrappers.run))
env.CommandNoCache(
"gdextension_interface_dump.gen.h",
["gdextension_interface.json", "make_interface_dumper.py"],

View file

@ -35,7 +35,6 @@
#include "core/extension/gdextension_special_compat_hashes.h"
#include "core/io/file_access.h"
#include "core/io/json.h"
#include "core/object/class_db.h"
#include "core/templates/pair.h"
#include "core/version.h"
@ -282,59 +281,59 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
// Member offsets, meta types and sizes.
#define REAL_MEMBER_OFFSET(type, member) \
{ \
type, \
member, \
"float", \
sizeof(float), \
"float", \
sizeof(float), \
"double", \
sizeof(double), \
"double", \
sizeof(double), \
{ \
type, \
member, \
"float", \
sizeof(float), \
"float", \
sizeof(float), \
"double", \
sizeof(double), \
"double", \
sizeof(double), \
}
#define INT32_MEMBER_OFFSET(type, member) \
{ \
type, \
member, \
"int32", \
sizeof(int32_t), \
"int32", \
sizeof(int32_t), \
"int32", \
sizeof(int32_t), \
"int32", \
sizeof(int32_t), \
{ \
type, \
member, \
"int32", \
sizeof(int32_t), \
"int32", \
sizeof(int32_t), \
"int32", \
sizeof(int32_t), \
"int32", \
sizeof(int32_t), \
}
#define INT32_BASED_BUILTIN_MEMBER_OFFSET(type, member, member_type, member_elems) \
{ \
type, \
member, \
member_type, \
sizeof(int32_t) * member_elems, \
member_type, \
sizeof(int32_t) * member_elems, \
member_type, \
sizeof(int32_t) * member_elems, \
member_type, \
sizeof(int32_t) * member_elems, \
{ \
type, \
member, \
member_type, \
sizeof(int32_t) * member_elems, \
member_type, \
sizeof(int32_t) * member_elems, \
member_type, \
sizeof(int32_t) * member_elems, \
member_type, \
sizeof(int32_t) * member_elems, \
}
#define REAL_BASED_BUILTIN_MEMBER_OFFSET(type, member, member_type, member_elems) \
{ \
type, \
member, \
member_type, \
sizeof(float) * member_elems, \
member_type, \
sizeof(float) * member_elems, \
member_type, \
sizeof(double) * member_elems, \
member_type, \
sizeof(double) * member_elems, \
{ \
type, \
member, \
member_type, \
sizeof(float) * member_elems, \
member_type, \
sizeof(float) * member_elems, \
member_type, \
sizeof(double) * member_elems, \
member_type, \
sizeof(double) * member_elems, \
}
struct {

View file

@ -30,11 +30,9 @@
#pragma once
#ifdef TOOLS_ENABLED
#include "core/extension/gdextension.h"
#include "core/error/error_list.h"
#include "core/string/ustring.h"
#include "core/variant/dictionary.h"
#ifdef TOOLS_ENABLED
class GDExtensionAPIDump {
public:
@ -42,5 +40,4 @@ public:
static void generate_extension_json_file(const String &p_path, bool p_include_docs = false);
static Error validate_extension_json_file(const String &p_path);
};
#endif

View file

@ -30,10 +30,6 @@
#ifndef DISABLE_DEPRECATED
#include "gdextension.h"
#include "core/object/class_db.h"
Error GDExtension::_open_library_bind_compat_88418(const String &p_path, const String &p_entry_symbol) {
return ERR_UNAVAILABLE;
}
@ -50,4 +46,4 @@ void GDExtension::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("initialize_library", "level"), &GDExtension::_initialize_library_bind_compat_88418);
}
#endif // DISABLE_DEPRECATED
#endif

View file

@ -32,10 +32,10 @@
#include "gdextension.compat.inc"
#include "core/config/project_settings.h"
#include "core/extension/gdextension_library_loader.h"
#include "core/object/callable_mp.h"
#include "core/object/class_db.h"
#include "core/object/method_bind.h"
#include "gdextension_library_loader.h"
#include "gdextension_manager.h"
extern void gdextension_setup_interface();
extern GDExtensionInterfaceFunctionPtr gdextension_get_proc_address(const char *p_name);
@ -844,7 +844,68 @@ void GDExtension::finalize_gdextensions() {
gdextension_interface_functions.clear();
}
Error GDExtensionResourceLoader::load_gdextension_resource(const String &p_path, Ref<GDExtension> &p_extension) {
ERR_FAIL_COND_V_MSG(p_extension.is_valid() && p_extension->is_library_open(), ERR_ALREADY_IN_USE, "Cannot load GDExtension resource into already opened library.");
GDExtensionManager *extension_manager = GDExtensionManager::get_singleton();
GDExtensionManager::LoadStatus status = extension_manager->load_extension(p_path);
if (status != GDExtensionManager::LOAD_STATUS_OK && status != GDExtensionManager::LOAD_STATUS_ALREADY_LOADED) {
// Errors already logged in load_extension().
return FAILED;
}
p_extension = extension_manager->get_extension(p_path);
return OK;
}
Ref<Resource> GDExtensionResourceLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
// We can't have two GDExtension resource object representing the same library, because
// loading (or unloading) a GDExtension affects global data. So, we need reuse the same
// object if one has already been loaded (even if caching is disabled at the resource
// loader level).
GDExtensionManager *manager = GDExtensionManager::get_singleton();
if (manager->is_extension_loaded(p_path)) {
return manager->get_extension(p_path);
}
Ref<GDExtension> lib;
Error err = load_gdextension_resource(p_path, lib);
if (err != OK && r_error) {
// Errors already logged in load_gdextension_resource().
*r_error = err;
}
return lib;
}
void GDExtensionResourceLoader::get_recognized_extensions(List<String> *p_extensions) const {
p_extensions->push_back("gdextension");
}
bool GDExtensionResourceLoader::handles_type(const String &p_type) const {
return p_type == "GDExtension";
}
String GDExtensionResourceLoader::get_resource_type(const String &p_path) const {
if (p_path.has_extension("gdextension")) {
return "GDExtension";
}
return "";
}
#ifdef TOOLS_ENABLED
void GDExtensionResourceLoader::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) {
Ref<GDExtension> gdext = ResourceLoader::load(p_path);
if (gdext.is_null()) {
return;
}
for (const StringName class_name : gdext->get_classes_used()) {
if (ClassDB::class_exists(class_name)) {
r_classes->insert(class_name);
}
}
}
bool GDExtension::has_library_changed() const {
return loader->has_library_changed();
@ -889,7 +950,7 @@ void GDExtension::prepare_reload() {
state.push_back(Pair<String, Variant>(P.name, value));
}
E.value.instance_state[obj_id] = {
std::move(state), // List<Pair<String, Variant>> properties;
state, // List<Pair<String, Variant>> properties;
obj->is_extension_placeholder(), // bool is_placeholder;
};
}

View file

@ -32,7 +32,9 @@
#include "core/extension/gdextension_interface.gen.h"
#include "core/extension/gdextension_loader.h"
#include "core/io/resource.h"
#include "core/io/config_file.h"
#include "core/io/resource_loader.h"
#include "core/object/ref_counted.h"
class GDExtensionMethodBind;
@ -180,6 +182,21 @@ public:
VARIANT_ENUM_CAST(GDExtension::InitializationLevel)
class GDExtensionResourceLoader : public ResourceFormatLoader {
GDSOFTCLASS(GDExtensionResourceLoader, ResourceFormatLoader);
public:
static Error load_gdextension_resource(const String &p_path, Ref<GDExtension> &p_extension);
virtual Ref<Resource> load(const String &p_path, const String &p_original_path, Error *r_error, 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 bool handles_type(const String &p_type) const override;
virtual String get_resource_type(const String &p_path) const override;
#ifdef TOOLS_ENABLED
virtual void get_classes_used(const String &p_path, HashSet<StringName> *r_classes) override;
#endif // TOOLS_ENABLED
};
#ifdef TOOLS_ENABLED
class GDExtensionEditorPlugins {
private:

View file

@ -30,7 +30,7 @@
#include "gdextension_function_loader.h"
#include "core/extension/gdextension.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://");

View file

@ -31,6 +31,7 @@
#pragma once
#include "core/extension/gdextension_loader.h"
#include "core/os/shared_object.h"
class GDExtension;

View file

@ -77,7 +77,7 @@ class CallableCustomExtension : public CallableCustom {
const CallableCustomExtension *b = static_cast<const CallableCustomExtension *>(p_b);
if (a->call_func != b->call_func) {
return (uintptr_t)a->call_func < (uintptr_t)b->call_func;
return a->call_func < b->call_func;
}
return a->userdata < b->userdata;
}

View file

@ -5859,7 +5859,7 @@
"return_value": {
"type": "GDExtensionInt",
"description": [
"The resulting encoded string length in characters, not including a null terminator. Characters that cannot be converted to Latin-1 are replaced with a space."
"The resulting encoded string length in characters (not bytes), not including a null terminator."
]
},
"arguments": [
@ -5896,7 +5896,7 @@
"return_value": {
"type": "GDExtensionInt",
"description": [
"The resulting encoded string length in bytes (not characters), not including a null terminator."
"The resulting encoded string length in characters (not bytes), not including a null terminator."
]
},
"arguments": [
@ -5933,7 +5933,7 @@
"return_value": {
"type": "GDExtensionInt",
"description": [
"The resulting encoded string length in 16-bit code units (not bytes or characters), not including a null terminator."
"The resulting encoded string length in characters (not bytes), not including a null terminator."
]
},
"arguments": [
@ -6007,7 +6007,7 @@
"return_value": {
"type": "GDExtensionInt",
"description": [
"The resulting encoded string length in characters (for UTF-32) or 16-bit code units (for UTF-16), depending on the wchar_t representation. Does not include a null terminator."
"The resulting encoded string length in characters (not bytes), not including a null terminator."
]
},
"arguments": [

View file

@ -32,8 +32,8 @@
#include "gdextension_interface_header_generator.h"
#include "core/extension/gdextension_interface_dump.gen.h"
#include "core/io/json.h"
#include "gdextension_interface_dump.gen.h"
static const char *FILE_HEADER =
"/**************************************************************************/\n"

View file

@ -30,12 +30,10 @@
#include "gdextension_library_loader.h"
#include "core/config/engine.h"
#include "core/config/project_settings.h"
#include "core/extension/gdextension.h"
#include "core/io/dir_access.h"
#include "core/os/os.h"
#include "core/version.h"
#include "gdextension.h"
Vector<SharedObject> GDExtensionLibraryLoader::find_extension_dependencies(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature) {
Vector<SharedObject> dependencies_shared_objects;

View file

@ -30,12 +30,12 @@
#pragma once
#include <functional>
#include "core/extension/gdextension_loader.h"
#include "core/io/config_file.h"
#include "core/os/shared_object.h"
#include <functional>
class GDExtensionLibraryLoader : public GDExtensionLoader {
GDSOFTCLASS(GDExtensionLibraryLoader, GDExtensionLoader);

View file

@ -30,16 +30,12 @@
#include "gdextension_manager.h"
#include "core/config/engine.h"
#include "core/extension/gdextension_function_loader.h"
#include "core/extension/gdextension_library_loader.h"
#include "core/extension/gdextension_special_compat_hashes.h"
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
#include "core/object/callable_mp.h"
#include "core/object/class_db.h"
#include "core/object/script_language.h"
#include "core/os/os.h"
GDExtensionManager::LoadStatus GDExtensionManager::_load_extension_internal(const Ref<GDExtension> &p_extension, bool p_first_load) {
if (level >= 0) { // Already initialized up to some level.
@ -481,8 +477,8 @@ void GDExtensionManager::_bind_methods() {
BIND_ENUM_CONSTANT(LOAD_STATUS_NEEDS_RESTART);
ADD_SIGNAL(MethodInfo("extensions_reloaded"));
ADD_SIGNAL(MethodInfo("extension_loaded", PropertyInfo(Variant::OBJECT, "extension", PROPERTY_HINT_RESOURCE_TYPE, GDExtension::get_class_static())));
ADD_SIGNAL(MethodInfo("extension_unloading", PropertyInfo(Variant::OBJECT, "extension", PROPERTY_HINT_RESOURCE_TYPE, GDExtension::get_class_static())));
ADD_SIGNAL(MethodInfo("extension_loaded", PropertyInfo(Variant::OBJECT, "extension", PROPERTY_HINT_RESOURCE_TYPE, "GDExtension")));
ADD_SIGNAL(MethodInfo("extension_unloading", PropertyInfo(Variant::OBJECT, "extension", PROPERTY_HINT_RESOURCE_TYPE, "GDExtension")));
}
GDExtensionManager::GDExtensionManager() {

View file

@ -1,98 +0,0 @@
/**************************************************************************/
/* gdextension_resource_format.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_resource_format.h"
#include "core/extension/gdextension_manager.h"
#include "core/object/class_db.h"
Ref<Resource> GDExtensionResourceLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
// We can't have two GDExtension resource object representing the same library, because
// loading (or unloading) a GDExtension affects global data. So, we need reuse the same
// object if one has already been loaded (even if caching is disabled at the resource
// loader level).
GDExtensionManager *manager = GDExtensionManager::get_singleton();
if (manager->is_extension_loaded(p_path)) {
return manager->get_extension(p_path);
}
Ref<GDExtension> lib;
Error err = load_gdextension_resource(p_path, lib);
if (err != OK && r_error) {
// Errors already logged in load_gdextension_resource().
*r_error = err;
}
return lib;
}
void GDExtensionResourceLoader::get_recognized_extensions(List<String> *p_extensions) const {
p_extensions->push_back("gdextension");
}
bool GDExtensionResourceLoader::handles_type(const String &p_type) const {
return p_type == "GDExtension";
}
String GDExtensionResourceLoader::get_resource_type(const String &p_path) const {
if (p_path.has_extension("gdextension")) {
return "GDExtension";
}
return "";
}
Error GDExtensionResourceLoader::load_gdextension_resource(const String &p_path, Ref<GDExtension> &p_extension) {
ERR_FAIL_COND_V_MSG(p_extension.is_valid() && p_extension->is_library_open(), ERR_ALREADY_IN_USE, "Cannot load GDExtension resource into already opened library.");
GDExtensionManager *extension_manager = GDExtensionManager::get_singleton();
GDExtensionManager::LoadStatus status = extension_manager->load_extension(p_path);
if (status != GDExtensionManager::LOAD_STATUS_OK && status != GDExtensionManager::LOAD_STATUS_ALREADY_LOADED) {
// Errors already logged in load_extension().
return FAILED;
}
p_extension = extension_manager->get_extension(p_path);
return OK;
}
#ifdef TOOLS_ENABLED
void GDExtensionResourceLoader::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) {
Ref<GDExtension> gdext = ResourceLoader::load(p_path);
if (gdext.is_null()) {
return;
}
for (const StringName class_name : gdext->get_classes_used()) {
if (ClassDB::class_exists(class_name)) {
r_classes->insert(class_name);
}
}
}
#endif // TOOLS_ENABLED

View file

@ -1,49 +0,0 @@
/**************************************************************************/
/* gdextension_resource_format.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.h"
#include "core/io/resource_loader.h"
class GDExtensionResourceLoader : public ResourceFormatLoader {
GDSOFTCLASS(GDExtensionResourceLoader, ResourceFormatLoader);
public:
static Error load_gdextension_resource(const String &p_path, Ref<GDExtension> &p_extension);
virtual Ref<Resource> load(const String &p_path, const String &p_original_path, Error *r_error, 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 bool handles_type(const String &p_type) const override;
virtual String get_resource_type(const String &p_path) const override;
#ifdef TOOLS_ENABLED
virtual void get_classes_used(const String &p_path, HashSet<StringName> *r_classes) override;
#endif // TOOLS_ENABLED
};

View file

@ -31,9 +31,7 @@
#include "godot_instance.h"
#include "core/extension/gdextension_manager.h"
#include "core/object/class_db.h"
#include "core/os/main_loop.h"
#include "core/os/os.h"
#include "main/main.h"
#include "servers/display/display_server.h"

View file

@ -31,7 +31,7 @@
#pragma once
#include "core/extension/gdextension_interface.gen.h"
#include "core/object/object.h"
#include "core/object/class_db.h"
class GodotInstance : public Object {
GDCLASS(GodotInstance, Object);

View file

@ -30,7 +30,7 @@
#pragma once
#include "core/extension/gdextension_interface.gen.h"
#include "gdextension_interface.gen.h"
#ifdef __cplusplus
extern "C" {

View file

@ -30,10 +30,6 @@
#ifndef DISABLE_DEPRECATED
#include "input.h"
#include "core/object/class_db.h"
void Input::_vibrate_handheld_bind_compat_91143(int p_duration_ms) {
vibrate_handheld(p_duration_ms, -1.0);
}

View file

@ -31,21 +31,15 @@
#include "input.h"
#include "input.compat.inc"
#include "core/config/engine.h"
#include "core/config/project_settings.h"
#include "core/input/default_controller_mappings.h"
#include "core/input/input_map.h"
#include "core/object/class_db.h"
#include "core/os/os.h"
#ifdef DEV_ENABLED
#include "core/os/thread.h"
#endif
#include <thirdparty/gamepadmotionhelpers/GamepadMotion.hpp>
#define STANDARD_GRAVITY 9.80665f
static const char *_joy_buttons[(size_t)JoyButton::SDL_MAX] = {
"a",
"b",
@ -68,11 +62,6 @@ static const char *_joy_buttons[(size_t)JoyButton::SDL_MAX] = {
"paddle3",
"paddle4",
"touchpad",
"misc2",
"misc3",
"misc4",
"misc5",
"misc6",
};
static const char *_joy_axes[(size_t)JoyAxis::SDL_MAX] = {
@ -125,8 +114,6 @@ bool Input::is_mouse_mode_override_enabled() {
}
void Input::_bind_methods() {
using namespace InputClassEnums;
ClassDB::bind_method(D_METHOD("is_anything_pressed"), &Input::is_anything_pressed);
ClassDB::bind_method(D_METHOD("is_key_pressed", "keycode"), &Input::is_key_pressed);
ClassDB::bind_method(D_METHOD("is_physical_key_pressed", "keycode"), &Input::is_physical_key_pressed);
@ -153,32 +140,13 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_connected_joypads"), &Input::get_connected_joypads);
ClassDB::bind_method(D_METHOD("get_joy_vibration_strength", "device"), &Input::get_joy_vibration_strength);
ClassDB::bind_method(D_METHOD("get_joy_vibration_duration", "device"), &Input::get_joy_vibration_duration);
ClassDB::bind_method(D_METHOD("get_joy_vibration_remaining_duration", "device"), &Input::get_joy_vibration_remaining_duration);
ClassDB::bind_method(D_METHOD("is_joy_vibrating", "device"), &Input::is_joy_vibrating);
ClassDB::bind_method(D_METHOD("has_joy_vibration", "device"), &Input::has_joy_vibration);
ClassDB::bind_method(D_METHOD("start_joy_vibration", "device", "weak_magnitude", "strong_magnitude", "duration"), &Input::start_joy_vibration, DEFVAL(0));
ClassDB::bind_method(D_METHOD("stop_joy_vibration", "device"), &Input::stop_joy_vibration);
ClassDB::bind_method(D_METHOD("vibrate_handheld", "duration_ms", "amplitude"), &Input::vibrate_handheld, DEFVAL(500), DEFVAL(-1.0));
ClassDB::bind_method(D_METHOD("set_ignore_joypad_on_unfocused_application", "enable"), &Input::set_ignore_joypad_on_unfocused_application);
ClassDB::bind_method(D_METHOD("is_ignoring_joypad_on_unfocused_application"), &Input::is_ignoring_joypad_on_unfocused_application);
ClassDB::bind_method(D_METHOD("get_gravity"), &Input::get_gravity);
ClassDB::bind_method(D_METHOD("get_accelerometer"), &Input::get_accelerometer);
ClassDB::bind_method(D_METHOD("get_magnetometer"), &Input::get_magnetometer);
ClassDB::bind_method(D_METHOD("get_gyroscope"), &Input::get_gyroscope);
ClassDB::bind_method(D_METHOD("get_joy_accelerometer", "device"), &Input::get_joy_accelerometer);
ClassDB::bind_method(D_METHOD("get_joy_gravity", "device"), &Input::get_joy_gravity);
ClassDB::bind_method(D_METHOD("get_joy_gyroscope", "device"), &Input::get_joy_gyroscope);
ClassDB::bind_method(D_METHOD("get_joy_motion_sensors_rate", "device"), &Input::get_joy_motion_sensors_rate);
ClassDB::bind_method(D_METHOD("is_joy_motion_sensors_enabled", "device"), &Input::is_joy_motion_sensors_enabled);
ClassDB::bind_method(D_METHOD("set_joy_motion_sensors_enabled", "device", "enable"), &Input::set_joy_motion_sensors_enabled);
ClassDB::bind_method(D_METHOD("has_joy_motion_sensors", "device"), &Input::has_joy_motion_sensors);
ClassDB::bind_method(D_METHOD("start_joy_motion_sensors_calibration", "device"), &Input::start_joy_motion_sensors_calibration);
ClassDB::bind_method(D_METHOD("stop_joy_motion_sensors_calibration", "device"), &Input::stop_joy_motion_sensors_calibration);
ClassDB::bind_method(D_METHOD("clear_joy_motion_sensors_calibration", "device"), &Input::clear_joy_motion_sensors_calibration);
ClassDB::bind_method(D_METHOD("get_joy_motion_sensors_calibration", "device"), &Input::get_joy_motion_sensors_calibration);
ClassDB::bind_method(D_METHOD("set_joy_motion_sensors_calibration", "device", "calibration_info"), &Input::set_joy_motion_sensors_calibration);
ClassDB::bind_method(D_METHOD("is_joy_motion_sensors_calibrated", "device"), &Input::is_joy_motion_sensors_calibrated);
ClassDB::bind_method(D_METHOD("is_joy_motion_sensors_calibrating", "device"), &Input::is_joy_motion_sensors_calibrating);
ClassDB::bind_method(D_METHOD("set_gravity", "value"), &Input::set_gravity);
ClassDB::bind_method(D_METHOD("set_accelerometer", "value"), &Input::set_accelerometer);
ClassDB::bind_method(D_METHOD("set_magnetometer", "value"), &Input::set_magnetometer);
@ -209,7 +177,6 @@ void Input::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_accumulated_input"), "set_use_accumulated_input", "is_using_accumulated_input");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emulate_mouse_from_touch"), "set_emulate_mouse_from_touch", "is_emulating_mouse_from_touch");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emulate_touch_from_mouse"), "set_emulate_touch_from_mouse", "is_emulating_touch_from_mouse");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_joypad_on_unfocused_application"), "set_ignore_joypad_on_unfocused_application", "is_ignoring_joypad_on_unfocused_application");
BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE);
BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN);
@ -329,14 +296,24 @@ bool Input::is_anything_pressed() const {
return false;
}
bool Input::is_any_key_pressed() const {
bool Input::is_anything_pressed_except_mouse() const {
_THREAD_SAFE_METHOD_
if (disable_input) {
return false;
}
return !keys_pressed.is_empty();
if (!keys_pressed.is_empty() || !joy_buttons_pressed.is_empty()) {
return true;
}
for (const KeyValue<StringName, Input::ActionState> &E : action_states) {
if (E.value.cache.pressed) {
return true;
}
}
return false;
}
bool Input::is_key_pressed(Key p_keycode) const {
@ -379,10 +356,6 @@ bool Input::is_mouse_button_pressed(MouseButton p_button) const {
return mouse_button_mask.has_flag(mouse_button_to_mask(p_button));
}
bool Input::_should_ignore_joypad_events() const {
return ignore_joypad_on_unfocused_application && !application_focused && !embedder_focused;
}
static JoyAxis _combine_device(JoyAxis p_value, int p_device) {
return JoyAxis((int)p_value | (p_device << 20));
}
@ -642,33 +615,6 @@ float Input::get_joy_vibration_duration(int p_device) {
}
}
float Input::get_joy_vibration_remaining_duration(int p_device) {
_THREAD_SAFE_METHOD_
const Joypad *joypad = joy_names.getptr(p_device);
if (joypad == nullptr || !joypad->has_vibration) {
return 0.f;
}
const VibrationInfo *vibration = joy_vibration.getptr(p_device);
if (vibration == nullptr || (vibration->weak_magnitude == 0.f && vibration->strong_magnitude == 0.f) || vibration->duration < 0.f) {
return 0.f;
}
float vibration_duration = vibration->duration;
if (vibration_duration > 0xFFFF / 1000.f || vibration_duration == 0.f) {
vibration_duration = 0xFFFF / 1000.f; // SDL_MAX_RUMBLE_DURATION_MS / 1000.f
}
return MAX(vibration_duration - (OS::get_singleton()->get_ticks_usec() - vibration->timestamp) / 1e6, 0.f);
}
bool Input::is_joy_vibrating(int p_device) {
return get_joy_vibration_remaining_duration(p_device) > 0.0f;
}
bool Input::has_joy_vibration(int p_device) const {
_THREAD_SAFE_METHOD_
const Joypad *joypad = joy_names.getptr(p_device);
return joypad != nullptr && joypad->has_vibration;
}
static String _hex_str(uint8_t p_byte) {
static const char *dict = "0123456789abcdef";
char ret[3];
@ -738,11 +684,6 @@ void Input::joy_connection_changed(int p_idx, bool p_connected, const String &p_
for (int i = 0; i < (int)JoyAxis::MAX; i++) {
set_joy_axis(p_idx, (JoyAxis)i, 0.0f);
}
MotionInfo *motion = joy_motion.getptr(p_idx);
if (motion != nullptr && motion->gamepad_motion != nullptr) {
delete motion->gamepad_motion;
}
joy_motion.erase(p_idx);
}
joy_names[p_idx] = js;
@ -1018,7 +959,6 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
device_state.pressed[event_index] = is_pressed;
device_state.strength[event_index] = p_event->get_action_strength(E.key);
device_state.raw_strength[event_index] = p_event->get_action_raw_strength(E.key);
device_state.event_type[event_index] = p_event->get_type();
// Update the action's global state and cache.
if (!is_pressed) {
@ -1065,12 +1005,6 @@ void Input::set_joy_features(int p_device, JoypadFeatures *p_features) {
}
void Input::set_joy_light(int p_device, const Color &p_color) {
_THREAD_SAFE_METHOD_
if (_should_ignore_joypad_events()) {
return;
}
Joypad *joypad = joy_names.getptr(p_device);
if (!joypad || !joypad->has_light || joypad->features == nullptr) {
return;
@ -1084,218 +1018,8 @@ bool Input::has_joy_light(int p_device) const {
return joypad && joypad->has_light;
}
Vector3 Input::get_joy_accelerometer(int p_device) const {
_THREAD_SAFE_METHOD_
if (_should_ignore_joypad_events()) {
return Vector3();
}
const MotionInfo *motion = joy_motion.getptr(p_device);
if (motion == nullptr) {
return Vector3();
}
float joy_acceleration_data[3];
motion->gamepad_motion->GetProcessedAcceleration(joy_acceleration_data[0], joy_acceleration_data[1], joy_acceleration_data[2]);
Vector3 joy_acceleration(joy_acceleration_data[0], joy_acceleration_data[1], joy_acceleration_data[2]);
float joy_gravity_data[3];
motion->gamepad_motion->GetGravity(joy_gravity_data[0], joy_gravity_data[1], joy_gravity_data[2]);
Vector3 joy_gravity(joy_gravity_data[0], joy_gravity_data[1], joy_gravity_data[2]);
return (-joy_acceleration + joy_gravity) * STANDARD_GRAVITY;
}
Vector3 Input::get_joy_gravity(int p_device) const {
_THREAD_SAFE_METHOD_
if (_should_ignore_joypad_events()) {
return Vector3();
}
const MotionInfo *motion = joy_motion.getptr(p_device);
if (motion == nullptr) {
return Vector3();
}
float joy_gravity_data[3];
motion->gamepad_motion->GetGravity(joy_gravity_data[0], joy_gravity_data[1], joy_gravity_data[2]);
Vector3 joy_gravity(joy_gravity_data[0], joy_gravity_data[1], joy_gravity_data[2]);
return joy_gravity.normalized() * STANDARD_GRAVITY;
}
Vector3 Input::get_joy_gyroscope(int p_device) const {
_THREAD_SAFE_METHOD_
if (_should_ignore_joypad_events()) {
return Vector3();
}
const MotionInfo *motion = joy_motion.getptr(p_device);
if (motion == nullptr) {
return Vector3();
}
float joy_gyro_data[3];
motion->gamepad_motion->GetCalibratedGyro(joy_gyro_data[0], joy_gyro_data[1], joy_gyro_data[2]);
Vector3 joy_gyro(joy_gyro_data[0], joy_gyro_data[1], joy_gyro_data[2]);
return joy_gyro * M_PI / 180.0;
}
void Input::set_joy_motion_sensors_enabled(int p_device, bool p_enable) {
_THREAD_SAFE_METHOD_
Joypad *joypad = joy_names.getptr(p_device);
if (joypad == nullptr || joypad->features == nullptr) {
return;
}
MotionInfo *motion = joy_motion.getptr(p_device);
if (motion == nullptr) {
return;
}
joypad->features->set_joy_motion_sensors_enabled(p_enable);
motion->sensors_enabled = p_enable;
}
bool Input::is_joy_motion_sensors_enabled(int p_device) const {
_THREAD_SAFE_METHOD_
const MotionInfo *motion = joy_motion.getptr(p_device);
return motion != nullptr && motion->sensors_enabled;
}
bool Input::has_joy_motion_sensors(int p_device) const {
_THREAD_SAFE_METHOD_
return joy_motion.has(p_device);
}
float Input::get_joy_motion_sensors_rate(int p_device) const {
_THREAD_SAFE_METHOD_
const MotionInfo *motion = joy_motion.getptr(p_device);
if (motion == nullptr) {
return 0.0f;
}
return motion->sensor_data_rate;
}
void Input::start_joy_motion_sensors_calibration(int p_device) {
_THREAD_SAFE_METHOD_
MotionInfo *motion = joy_motion.getptr(p_device);
if (motion == nullptr) {
return;
}
ERR_FAIL_COND_MSG(!motion->sensors_enabled, "Motion sensors are not enabled on the joypad.");
ERR_FAIL_COND_MSG(motion->calibrating, "Calibration already in progress.");
motion->gamepad_motion->ResetContinuousCalibration();
motion->gamepad_motion->StartContinuousCalibration();
motion->calibrating = true;
motion->calibrated = false;
}
void Input::stop_joy_motion_sensors_calibration(int p_device) {
_THREAD_SAFE_METHOD_
MotionInfo *motion = joy_motion.getptr(p_device);
if (motion == nullptr) {
return;
}
ERR_FAIL_COND_MSG(!motion->sensors_enabled, "Motion sensors are not enabled on the joypad.");
ERR_FAIL_COND_MSG(!motion->calibrating, "Calibration hasn't been started.");
motion->gamepad_motion->PauseContinuousCalibration();
motion->calibrating = false;
motion->calibrated = true;
}
void Input::clear_joy_motion_sensors_calibration(int p_device) {
_THREAD_SAFE_METHOD_
MotionInfo *motion = joy_motion.getptr(p_device);
if (motion == nullptr) {
return;
}
// Calibration might be in progress and the developer or the user might want to reset it,
// so no need to stop the calibration.
motion->gamepad_motion->ResetContinuousCalibration();
}
Dictionary Input::get_joy_motion_sensors_calibration(int p_device) const {
_THREAD_SAFE_METHOD_
const MotionInfo *motion = joy_motion.getptr(p_device);
if (motion == nullptr) {
return Dictionary();
}
if (!motion->calibrated) {
return Dictionary();
}
float joy_gyro_offset_data[3];
motion->gamepad_motion->GetCalibrationOffset(joy_gyro_offset_data[0], joy_gyro_offset_data[1], joy_gyro_offset_data[2]);
Vector3 joy_gyro_offset(joy_gyro_offset_data[0], joy_gyro_offset_data[1], joy_gyro_offset_data[2]);
Dictionary result;
result["gyroscope_offset"] = joy_gyro_offset * M_PI / 180.0;
return result;
}
void Input::set_joy_motion_sensors_calibration(int p_device, const Dictionary &p_calibration_info) {
_THREAD_SAFE_METHOD_
MotionInfo *motion = joy_motion.getptr(p_device);
if (motion == nullptr) {
return;
}
ERR_FAIL_COND_MSG(motion->calibrating, "Calibration is currently in progress.");
Vector3 gyro_offset = p_calibration_info.get("gyroscope_offset", Vector3()).operator Vector3() * 180.0 / M_PI;
motion->gamepad_motion->SetCalibrationOffset(gyro_offset.x, gyro_offset.y, gyro_offset.z, 1);
motion->calibrating = false;
motion->calibrated = true;
}
bool Input::is_joy_motion_sensors_calibrating(int p_device) const {
_THREAD_SAFE_METHOD_
const MotionInfo *motion = joy_motion.getptr(p_device);
if (motion == nullptr) {
return false;
}
return motion->calibrating;
}
bool Input::is_joy_motion_sensors_calibrated(int p_device) const {
_THREAD_SAFE_METHOD_
const MotionInfo *motion = joy_motion.getptr(p_device);
if (motion == nullptr) {
return false;
}
return motion->calibrated;
}
void Input::set_joy_motion_sensors_rate(int p_device, float p_rate) {
_THREAD_SAFE_METHOD_
MotionInfo *motion = joy_motion.getptr(p_device);
if (motion == nullptr) {
return;
}
motion->sensor_data_rate = p_rate;
}
void Input::start_joy_vibration(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration) {
_THREAD_SAFE_METHOD_
if (_should_ignore_joypad_events()) {
return;
}
if (p_weak_magnitude < 0.f || p_weak_magnitude > 1.f || p_strong_magnitude < 0.f || p_strong_magnitude > 1.f) {
return;
}
@ -1321,17 +1045,6 @@ void Input::vibrate_handheld(int p_duration_ms, float p_amplitude) {
OS::get_singleton()->vibrate_handheld(p_duration_ms, p_amplitude);
}
void Input::set_ignore_joypad_on_unfocused_application(bool p_ignore) {
ignore_joypad_on_unfocused_application = p_ignore;
if (_should_ignore_joypad_events()) {
release_pressed_events();
}
}
bool Input::is_ignoring_joypad_on_unfocused_application() const {
return ignore_joypad_on_unfocused_application;
}
void Input::set_gravity(const Vector3 &p_gravity) {
_THREAD_SAFE_METHOD_
@ -1598,49 +1311,17 @@ bool Input::is_using_accumulated_input() {
}
void Input::release_pressed_events() {
// Don't release the events if the application (or the window it's embedded in) is still focused.
if (application_focused || embedder_focused) {
return;
}
flush_buffered_events(); // this is needed to release actions strengths
keys_pressed.clear();
physical_keys_pressed.clear();
key_label_pressed.clear();
if (ignore_joypad_on_unfocused_application) {
joy_buttons_pressed.clear();
_joy_axis.clear();
joy_buttons_pressed.clear();
_joy_axis.clear();
for (KeyValue<StringName, Input::ActionState> &E : action_states) {
if (E.value.cache.pressed) {
action_release(E.key);
}
}
for (int device : get_connected_joypads()) {
stop_joy_vibration(device);
}
} else {
for (KeyValue<StringName, Input::ActionState> &E : action_states) {
if (E.value.cache.pressed) {
bool is_only_joypad_pressed = true;
int max_event = InputMap::get_singleton()->action_get_events(E.key)->size() + 1; // +1 comes from InputEventAction.
for (const KeyValue<int, ActionState::DeviceState> &kv : E.value.device_states) {
const ActionState::DeviceState &device_state = kv.value;
for (int i = 0; i < max_event; i++) {
if (device_state.event_type[i] != InputEventType::JOY_MOTION && device_state.event_type[i] != InputEventType::JOY_BUTTON && device_state.strength[i] > 0.0f) {
is_only_joypad_pressed = false;
action_release(E.key);
break;
}
}
if (!is_only_joypad_pressed) {
break;
}
}
}
for (KeyValue<StringName, Input::ActionState> &E : action_states) {
if (E.value.cache.pressed) {
action_release(E.key);
}
}
}
@ -1651,11 +1332,6 @@ void Input::set_event_dispatch_function(EventDispatchFunc p_function) {
void Input::joy_button(int p_device, JoyButton p_button, bool p_pressed) {
_THREAD_SAFE_METHOD_;
if (_should_ignore_joypad_events()) {
return;
}
Joypad &joy = joy_names[p_device];
ERR_FAIL_INDEX((int)p_button, (int)JoyButton::MAX);
@ -1684,10 +1360,6 @@ void Input::joy_button(int p_device, JoyButton p_button, bool p_pressed) {
void Input::joy_axis(int p_device, JoyAxis p_axis, float p_value) {
_THREAD_SAFE_METHOD_;
if (_should_ignore_joypad_events()) {
return;
}
ERR_FAIL_INDEX((int)p_axis, (int)JoyAxis::MAX);
Joypad &joy = joy_names[p_device];
@ -1757,11 +1429,6 @@ void Input::joy_axis(int p_device, JoyAxis p_axis, float p_value) {
void Input::joy_hat(int p_device, BitField<HatMask> p_val) {
_THREAD_SAFE_METHOD_;
if (_should_ignore_joypad_events()) {
return;
}
const Joypad &joy = joy_names[p_device];
JoyEvent map[(size_t)HatDir::MAX];
@ -1802,27 +1469,6 @@ void Input::joy_hat(int p_device, BitField<HatMask> p_val) {
joy_names[p_device].hat_current = (int)p_val;
}
void Input::joy_motion_sensors(int p_device, const Vector3 &p_accelerometer, const Vector3 &p_gyroscope) {
_THREAD_SAFE_METHOD_
if (_should_ignore_joypad_events()) {
return;
}
// TODO: events
MotionInfo *motion = joy_motion.getptr(p_device);
if (motion == nullptr) {
return;
}
Vector3 gyro_degrees = p_gyroscope * 180.0 / M_PI;
Vector3 accel_g = -p_accelerometer / STANDARD_GRAVITY;
uint64_t new_timestamp = OS::get_singleton()->get_ticks_msec();
float delta_time = (new_timestamp - motion->last_timestamp) / 1000.0f;
motion->last_timestamp = new_timestamp;
motion->gamepad_motion->ProcessMotion(gyro_degrees.x, gyro_degrees.y, gyro_degrees.z, accel_g.x, accel_g.y, accel_g.z, delta_time);
}
void Input::_button_event(int p_device, JoyButton p_index, bool p_pressed) {
Ref<InputEventJoypadButton> ievent;
ievent.instantiate();
@ -1871,22 +1517,9 @@ void Input::_update_joypad_features(int p_device) {
if (!joypad || joypad->features == nullptr) {
return;
}
if (joypad->features->has_joy_vibration()) {
joypad->has_vibration = true;
}
if (joypad->features->has_joy_light()) {
joypad->has_light = true;
}
if (joypad->features->has_joy_motion_sensors()) {
MotionInfo &motion = joy_motion[p_device];
if (!motion.gamepad_motion) {
motion.gamepad_motion = new GamepadMotion();
} else {
motion.gamepad_motion->Reset();
}
motion.last_timestamp = OS::get_singleton()->get_ticks_msec();
}
}
Input::JoyEvent Input::_get_mapped_button_event(const JoyDeviceMapping &mapping, JoyButton p_button) {
@ -2371,7 +2004,6 @@ Input::Input() {
gravity_enabled = GLOBAL_DEF_RST_BASIC("input_devices/sensors/enable_gravity", false);
gyroscope_enabled = GLOBAL_DEF_RST_BASIC("input_devices/sensors/enable_gyroscope", false);
magnetometer_enabled = GLOBAL_DEF_RST_BASIC("input_devices/sensors/enable_magnetometer", false);
ignore_joypad_on_unfocused_application = GLOBAL_DEF_RST_BASIC("input_devices/joypads/ignore_joypad_on_unfocused_application", false);
}
Input::~Input() {

View file

@ -38,43 +38,6 @@
#include "core/templates/rb_set.h"
#include "core/variant/typed_array.h"
class GamepadMotion;
namespace InputClassEnums {
// Keep synced with DisplayServerEnums::MouseMode enum.
enum MouseMode : int {
MOUSE_MODE_VISIBLE,
MOUSE_MODE_HIDDEN,
MOUSE_MODE_CAPTURED,
MOUSE_MODE_CONFINED,
MOUSE_MODE_CONFINED_HIDDEN,
MOUSE_MODE_MAX,
};
// Keep synced with DisplayServerEnums and Control enums.
#undef CursorShape
enum CursorShape : int {
CURSOR_ARROW,
CURSOR_IBEAM,
CURSOR_POINTING_HAND,
CURSOR_CROSS,
CURSOR_WAIT,
CURSOR_BUSY,
CURSOR_DRAG,
CURSOR_CAN_DROP,
CURSOR_FORBIDDEN,
CURSOR_VSIZE,
CURSOR_HSIZE,
CURSOR_BDIAGSIZE,
CURSOR_FDIAGSIZE,
CURSOR_MOVE,
CURSOR_VSPLIT,
CURSOR_HSPLIT,
CURSOR_HELP,
CURSOR_MAX
};
} //namespace InputClassEnums
class Input : public Object {
GDCLASS(Input, Object);
_THREAD_SAFE_CLASS_
@ -84,21 +47,44 @@ class Input : public Object {
static constexpr uint64_t MAX_EVENT = 32;
public:
// TODO: When we migrate to C++20, replace these with "using enum" and skip prefixing MouseMode and CursorShape in other files.
using MouseMode = InputClassEnums::MouseMode;
using CursorShape = InputClassEnums::CursorShape;
// Keep synced with "DisplayServer::MouseMode" enum.
enum MouseMode {
MOUSE_MODE_VISIBLE,
MOUSE_MODE_HIDDEN,
MOUSE_MODE_CAPTURED,
MOUSE_MODE_CONFINED,
MOUSE_MODE_CONFINED_HIDDEN,
MOUSE_MODE_MAX,
};
#undef CursorShape
enum CursorShape {
CURSOR_ARROW,
CURSOR_IBEAM,
CURSOR_POINTING_HAND,
CURSOR_CROSS,
CURSOR_WAIT,
CURSOR_BUSY,
CURSOR_DRAG,
CURSOR_CAN_DROP,
CURSOR_FORBIDDEN,
CURSOR_VSIZE,
CURSOR_HSIZE,
CURSOR_BDIAGSIZE,
CURSOR_FDIAGSIZE,
CURSOR_MOVE,
CURSOR_VSPLIT,
CURSOR_HSPLIT,
CURSOR_HELP,
CURSOR_MAX
};
class JoypadFeatures {
public:
virtual ~JoypadFeatures() {}
virtual bool has_joy_vibration() const { return false; }
virtual bool has_joy_light() const { return false; }
virtual void set_joy_light(const Color &p_color) {}
virtual bool has_joy_motion_sensors() const { return false; }
virtual void set_joy_motion_sensors_enabled(bool p_enable) {}
};
static constexpr int32_t JOYPADS_MAX = 16;
@ -126,9 +112,6 @@ private:
int64_t mouse_window = 0;
bool legacy_just_pressed_behavior = false;
bool disable_input = false;
bool ignore_joypad_on_unfocused_application = false;
bool application_focused = true;
bool embedder_focused = false;
struct ActionState {
uint64_t pressed_physics_frame = UINT64_MAX;
@ -143,7 +126,6 @@ private:
bool pressed[MAX_EVENT] = { false };
float strength[MAX_EVENT] = { 0.0 };
float raw_strength[MAX_EVENT] = { 0.0 };
InputEventType event_type[MAX_EVENT] = { InputEventType::INVALID };
};
bool api_pressed = false;
float api_strength = 0.0;
@ -175,23 +157,6 @@ private:
HashMap<int, VibrationInfo> joy_vibration;
struct MotionInfo {
bool sensors_enabled : 1;
bool calibrating : 1;
bool calibrated : 1;
float sensor_data_rate = 0.0f;
uint64_t last_timestamp = 0;
GamepadMotion *gamepad_motion = nullptr;
MotionInfo() {
sensors_enabled = false;
calibrating = false;
calibrated = false;
}
};
HashMap<int, MotionInfo> joy_motion;
struct VelocityTrack {
uint64_t last_tick = 0;
Vector2 velocity;
@ -219,7 +184,6 @@ private:
int hat_current = 0;
Dictionary info;
bool has_light = false;
bool has_vibration = false;
Input::JoypadFeatures *features = nullptr;
};
@ -231,7 +195,7 @@ private:
int fallback_mapping = -1; // Index of the guid in map_db.
CursorShape default_shape = CursorShape::CURSOR_ARROW;
CursorShape default_shape = CURSOR_ARROW;
enum JoyType {
TYPE_BUTTON,
@ -311,8 +275,6 @@ private:
#endif
friend class DisplayServer;
friend class SceneTree;
friend class SceneDebugger;
static void (*set_mouse_mode_func)(MouseMode);
static MouseMode (*get_mouse_mode_func)();
@ -327,8 +289,6 @@ private:
EventDispatchFunc event_dispatch_function = nullptr;
bool _should_ignore_joypad_events() const;
#ifndef DISABLE_DEPRECATED
void _vibrate_handheld_bind_compat_91143(int p_duration_ms = 500);
static void _bind_compatibility_methods();
@ -352,7 +312,7 @@ public:
static Input *get_singleton();
bool is_anything_pressed() const;
bool is_any_key_pressed() const;
bool is_anything_pressed_except_mouse() const;
bool is_key_pressed(Key p_keycode) const;
bool is_physical_key_pressed(Key p_keycode) const;
bool is_key_label_pressed(Key p_keycode) const;
@ -374,10 +334,7 @@ public:
TypedArray<int> get_connected_joypads();
Vector2 get_joy_vibration_strength(int p_device);
float get_joy_vibration_duration(int p_device);
float get_joy_vibration_remaining_duration(int p_device);
uint64_t get_joy_vibration_timestamp(int p_device);
bool is_joy_vibrating(int p_device);
bool has_joy_vibration(int p_device) const;
void joy_connection_changed(int p_idx, bool p_connected, const String &p_name, const String &p_guid = "", const Dictionary &p_joypad_info = Dictionary());
Vector3 get_gravity() const;
@ -406,35 +363,10 @@ public:
void set_joy_light(int p_device, const Color &p_color);
bool has_joy_light(int p_device) const;
Vector3 get_joy_accelerometer(int p_device) const;
Vector3 get_joy_gravity(int p_device) const;
Vector3 get_joy_gyroscope(int p_device) const;
void set_joy_motion_sensors_enabled(int p_device, bool p_enable);
bool is_joy_motion_sensors_enabled(int p_device) const;
bool has_joy_motion_sensors(int p_device) const;
float get_joy_motion_sensors_rate(int p_device) const;
void start_joy_motion_sensors_calibration(int p_device);
void stop_joy_motion_sensors_calibration(int p_device);
void clear_joy_motion_sensors_calibration(int p_device);
Dictionary get_joy_motion_sensors_calibration(int p_device) const;
void set_joy_motion_sensors_calibration(int p_device, const Dictionary &p_calibration_info);
bool is_joy_motion_sensors_calibrating(int p_device) const;
bool is_joy_motion_sensors_calibrated(int p_device) const;
void set_joy_motion_sensors_rate(int p_device, float p_rate);
void start_joy_vibration(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration = 0);
void stop_joy_vibration(int p_device);
void vibrate_handheld(int p_duration_ms = 500, float p_amplitude = -1.0);
void set_ignore_joypad_on_unfocused_application(bool p_ignore);
bool is_ignoring_joypad_on_unfocused_application() const;
void set_mouse_position(const Point2 &p_posf);
void action_press(const StringName &p_action, float p_strength = 1.f);
@ -450,13 +382,12 @@ public:
CursorShape get_default_cursor_shape() const;
void set_default_cursor_shape(CursorShape p_shape);
CursorShape get_current_cursor_shape() const;
void set_custom_mouse_cursor(const Ref<Resource> &p_cursor, CursorShape p_shape = Input::CursorShape::CURSOR_ARROW, const Vector2 &p_hotspot = Vector2());
void set_custom_mouse_cursor(const Ref<Resource> &p_cursor, CursorShape p_shape = Input::CURSOR_ARROW, const Vector2 &p_hotspot = Vector2());
void parse_mapping(const String &p_mapping);
void joy_button(int p_device, JoyButton p_button, bool p_pressed);
void joy_axis(int p_device, JoyAxis p_axis, float p_value);
void joy_hat(int p_device, BitField<HatMask> p_val);
void joy_motion_sensors(int p_device, const Vector3 &p_accelerometer, const Vector3 &p_gyroscope);
void add_joy_mapping(const String &p_mapping, bool p_update_existing = false);
void remove_joy_mapping(const String &p_guid);

View file

@ -100,12 +100,7 @@ enum class JoyButton {
PADDLE3 = 18,
PADDLE4 = 19,
TOUCHPAD = 20,
MISC2 = 21,
MISC3 = 22,
MISC4 = 23,
MISC5 = 24,
MISC6 = 25,
SDL_MAX = 26,
SDL_MAX = 21,
MAX = 128, // Android supports up to 36 buttons. DirectInput supports up to 128 buttons.
};

View file

@ -32,11 +32,8 @@
#include "core/input/input_map.h"
#include "core/input/shortcut.h"
#include "core/math/transform_2d.h"
#include "core/object/class_db.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/string/ustring.h"
void InputEvent::set_device(int p_device) {
device = p_device;
@ -134,8 +131,6 @@ void InputEvent::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "device"), "set_device", "get_device");
BIND_CONSTANT(DEVICE_ID_EMULATION);
BIND_CONSTANT(DEVICE_ID_KEYBOARD);
BIND_CONSTANT(DEVICE_ID_MOUSE);
}
///////////////////////////////////
@ -319,7 +314,8 @@ void InputEventWithModifiers::_validate_property(PropertyInfo &p_property) const
if (p_property.name == "meta_pressed") {
p_property.usage ^= PROPERTY_USAGE_STORAGE;
p_property.usage ^= PROPERTY_USAGE_EDITOR;
} else if (p_property.name == "ctrl_pressed") {
}
if (p_property.name == "ctrl_pressed") {
p_property.usage ^= PROPERTY_USAGE_STORAGE;
p_property.usage ^= PROPERTY_USAGE_EDITOR;
}
@ -666,10 +662,6 @@ void InputEventKey::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "echo"), "set_echo", "is_echo");
}
InputEventKey::InputEventKey() {
set_device(DEVICE_ID_KEYBOARD);
}
///////////////////////////////////
void InputEventMouse::set_button_mask(BitField<MouseButtonMask> p_mask) {
@ -712,10 +704,6 @@ void InputEventMouse::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "global_position", PROPERTY_HINT_NONE, "suffix:px"), "set_global_position", "get_global_position");
}
InputEventMouse::InputEventMouse() {
set_device(DEVICE_ID_MOUSE);
}
///////////////////////////////////
void InputEventMouseButton::set_factor(float p_factor) {
@ -1932,7 +1920,7 @@ void InputEventShortcut::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_shortcut", "shortcut"), &InputEventShortcut::set_shortcut);
ClassDB::bind_method(D_METHOD("get_shortcut"), &InputEventShortcut::get_shortcut);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut", PROPERTY_HINT_RESOURCE_TYPE, Shortcut::get_class_static()), "set_shortcut", "get_shortcut");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut", PROPERTY_HINT_RESOURCE_TYPE, "Shortcut"), "set_shortcut", "get_shortcut");
}
String InputEventShortcut::as_text() const {

View file

@ -32,7 +32,9 @@
#include "core/input/input_enums.h"
#include "core/io/resource.h"
#include "core/math/transform_2d.h"
#include "core/os/keyboard.h"
#include "core/string/ustring.h"
#include "core/typedefs.h"
/**
@ -41,8 +43,6 @@
*/
class Shortcut;
class String;
struct Transform2D;
/**
* Input Modifier Status
@ -63,8 +63,6 @@ protected:
public:
static constexpr int DEVICE_ID_EMULATION = -1;
static constexpr int DEVICE_ID_INTERNAL = -2;
static constexpr int DEVICE_ID_KEYBOARD = 16; // IDs 0-15 are reserved for joypads.
static constexpr int DEVICE_ID_MOUSE = 32; // IDs 17-31 are reserved for multiple keyboard support in the future.
void set_device(int p_device);
int get_device() const;
@ -201,8 +199,6 @@ public:
static Ref<InputEventKey> create_reference(Key p_keycode_with_modifier_masks, bool p_physical = false);
InputEventType get_type() const final override { return InputEventType::KEY; }
InputEventKey();
};
class InputEventMouse : public InputEventWithModifiers {
@ -225,8 +221,6 @@ public:
void set_global_position(const Vector2 &p_global_pos);
Vector2 get_global_position() const;
InputEventMouse();
};
class InputEventMouseButton : public InputEventMouse {

View file

@ -32,6 +32,7 @@
#include "core/input/input.h"
#include "core/io/marshalls.h"
#include "core/os/os.h"
enum class BoolShift : uint8_t {
SHIFT = 0,

View file

@ -30,10 +30,6 @@
#ifndef DISABLE_DEPRECATED
#include "input_map.h"
#include "core/object/class_db.h"
void InputMap::_add_action_bind_compat_97281(const StringName &p_action, float p_deadzone) {
add_action(p_action, p_deadzone);
}

View file

@ -33,7 +33,6 @@
#include "core/config/project_settings.h"
#include "core/input/input.h"
#include "core/object/class_db.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/variant/typed_array.h"
@ -206,22 +205,6 @@ void InputMap::action_add_event(const StringName &p_action, RequiredParam<InputE
return; // Already added.
}
// Normalize legacy device IDs: before the device ID change,
// keyboard and mouse events defaulted to device=0.
if (p_event->get_device() == 0) {
switch (p_event->get_type()) {
case InputEventType::KEY:
p_event->set_device(InputEvent::DEVICE_ID_KEYBOARD);
break;
case InputEventType::MOUSE_BUTTON:
case InputEventType::MOUSE_MOTION:
p_event->set_device(InputEvent::DEVICE_ID_MOUSE);
break;
default:
break;
}
}
input_map[p_action].inputs.push_back(p_event);
}
@ -336,11 +319,6 @@ void InputMap::load_from_project_settings() {
String name = pi.name.substr(pi.name.find_char('/') + 1);
Dictionary action = GLOBAL_GET(pi.name);
if (!action.has("events")) {
continue;
}
float deadzone = action.has("deadzone") ? (float)action["deadzone"] : DEFAULT_DEADZONE;
Array events = action["events"];
@ -926,7 +904,7 @@ const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins_with_featur
}
void InputMap::load_default() {
HashMap<String, List<Ref<InputEvent>>> builtins(get_builtins_with_feature_overrides_applied());
HashMap<String, List<Ref<InputEvent>>> builtins = get_builtins_with_feature_overrides_applied();
for (const KeyValue<String, List<Ref<InputEvent>>> &E : builtins) {
String name = E.key;

View file

@ -30,8 +30,6 @@
#include "shortcut.h"
#include "core/object/class_db.h"
void Shortcut::set_events(const Array &p_events) {
for (int i = 0; i < p_events.size(); i++) {
Ref<InputEventShortcut> ies = p_events[i];

View file

@ -30,9 +30,10 @@
#include "compression.h"
#include "core/config/project_settings.h"
#include "core/io/zip_io.h"
#include <thirdparty/misc/fastlz.h>
#include "thirdparty/misc/fastlz.h"
#include <zstd.h>

View file

@ -31,7 +31,6 @@
#include "config_file.h"
#include "core/io/file_access_encrypted.h"
#include "core/object/class_db.h"
#include "core/string/string_builder.h"
#include "core/variant/variant_parser.h"

View file

@ -30,10 +30,6 @@
#include "delta_encoding.h"
#include "core/error/error_list.h"
#include "core/templates/vector.h"
#include "core/variant/variant.h" // vformat
#include <zstd.h>
#define ERR_FAIL_ZSTD_V_MSG(m_result, m_retval, m_msg) \

View file

@ -30,12 +30,7 @@
#pragma once
#include "core/templates/span.h"
#include <cstdint>
template <typename T>
class Vector;
#include "core/io/file_access.h"
class DeltaEncoding {
public:

View file

@ -32,7 +32,6 @@
#include "core/config/project_settings.h"
#include "core/io/file_access.h"
#include "core/object/class_db.h"
#include "core/os/os.h"
#include "core/os/time.h"
#include "core/templates/local_vector.h"
@ -265,16 +264,11 @@ int DirAccess::_get_drive_count() {
return d->get_drive_count();
}
String DirAccess::_get_drive_name(int p_idx) {
String DirAccess::get_drive_name(int p_idx) {
Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
return d->get_drive(p_idx);
}
String DirAccess::_get_drive_label(int p_idx) {
Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
return d->get_drive_label(p_idx);
}
Error DirAccess::make_dir_absolute(const String &p_dir) {
Ref<DirAccess> d = DirAccess::create_for_path(p_dir);
return d->make_dir(p_dir);
@ -651,8 +645,7 @@ void DirAccess::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_directories"), &DirAccess::get_directories);
ClassDB::bind_static_method("DirAccess", D_METHOD("get_directories_at", "path"), &DirAccess::get_directories_at);
ClassDB::bind_static_method("DirAccess", D_METHOD("get_drive_count"), &DirAccess::_get_drive_count);
ClassDB::bind_static_method("DirAccess", D_METHOD("get_drive_name", "idx"), &DirAccess::_get_drive_name);
ClassDB::bind_static_method("DirAccess", D_METHOD("get_drive_label", "idx"), &DirAccess::_get_drive_label);
ClassDB::bind_static_method("DirAccess", D_METHOD("get_drive_name", "idx"), &DirAccess::get_drive_name);
ClassDB::bind_method(D_METHOD("get_current_drive"), &DirAccess::get_current_drive);
ClassDB::bind_method(D_METHOD("change_dir", "to_dir"), &DirAccess::change_dir);
ClassDB::bind_method(D_METHOD("get_current_dir", "include_drive"), &DirAccess::get_current_dir, DEFVAL(true));

View file

@ -91,7 +91,6 @@ public:
virtual int get_drive_count() = 0;
virtual String get_drive(int p_drive) = 0;
virtual String get_drive_label(int p_drive) { return String(); }
virtual int get_current_drive();
virtual bool drives_are_shortcuts();
@ -146,8 +145,7 @@ public:
static Ref<DirAccess> create_temp(const String &p_prefix = "", bool p_keep = false, Error *r_error = nullptr);
static int _get_drive_count();
static String _get_drive_name(int p_idx);
static String _get_drive_label(int p_idx);
static String get_drive_name(int p_idx);
static Error make_dir_absolute(const String &p_dir);
static Error make_dir_recursive_absolute(const String &p_dir);

View file

@ -30,8 +30,6 @@
#include "dtls_server.h"
#include "core/object/class_db.h"
DTLSServer *DTLSServer::create(bool p_notify_postinitialize) {
if (_create) {
return _create(p_notify_postinitialize);

View file

@ -30,6 +30,7 @@
#pragma once
#include "core/io/net_socket.h"
#include "core/io/packet_peer_dtls.h"
class DTLSServer : public RefCounted {

View file

@ -30,10 +30,6 @@
#ifndef DISABLE_DEPRECATED
#include "file_access.h"
#include "core/object/class_db.h"
Ref<FileAccess> FileAccess::_open_encrypted_bind_compat_98918(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key) {
return open_encrypted(p_path, p_mode_flags, p_key, Vector<uint8_t>());
}
@ -127,4 +123,4 @@ void FileAccess::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("get_as_text", "skip_cr"), &FileAccess::get_as_text_bind_compat_110867, DEFVAL(false));
}
#endif // DISABLE_DEPRECATED
#endif

View file

@ -38,7 +38,6 @@
#include "core/io/file_access_pack.h"
#include "core/io/marshalls.h"
#include "core/io/resource_uid.h"
#include "core/object/class_db.h"
#include "core/os/os.h"
#include "core/os/time.h"
@ -426,7 +425,7 @@ class CharBuffer {
int64_t written = 0;
bool grow() {
if (vector.resize(Math::next_power_of_2((uint64_t)1 + (uint64_t)written)) != OK) {
if (vector.resize(next_power_of_2((uint64_t)1 + (uint64_t)written)) != OK) {
return false;
}

View file

@ -36,7 +36,6 @@
#include "core/os/memory.h"
#include "core/string/ustring.h"
#include "core/typedefs.h"
#include "core/variant/type_info.h"
/**
* Multi-Platform abstraction for accessing to files.

View file

@ -30,8 +30,6 @@
#include "file_access_compressed.h"
#include "core/math/math_funcs_binary.h"
void FileAccessCompressed::configure(const String &p_magic, Compression::Mode p_mode, uint32_t p_block_size) {
magic = p_magic.ascii().get_data();
magic = (magic + " ").substr(0, 4);
@ -322,7 +320,7 @@ bool FileAccessCompressed::store_buffer(const uint8_t *p_src, uint64_t p_length)
write_max = write_pos + (p_length);
}
if (write_max > write_buffer_size) {
write_buffer_size = Math::next_power_of_2(write_max);
write_buffer_size = next_power_of_2(write_max);
ERR_FAIL_COND_V(buffer.resize(write_buffer_size) != OK, false);
write_ptr = buffer.ptrw();
}

View file

@ -36,9 +36,9 @@
#include "core/os/os.h"
#include "core/version.h"
Error PackedData::add_pack(const String &p_path, bool p_replace_files, uint64_t p_offset, const Vector<uint8_t> &p_decryption_key) {
Error PackedData::add_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) {
for (int i = 0; i < sources.size(); i++) {
if (sources[i]->try_open_pack(p_path, p_replace_files, p_offset, p_decryption_key)) {
if (sources[i]->try_open_pack(p_path, p_replace_files, p_offset)) {
return OK;
}
}
@ -46,7 +46,7 @@ Error PackedData::add_pack(const String &p_path, bool p_replace_files, uint64_t
return ERR_FILE_UNRECOGNIZED;
}
void PackedData::add_path(const String &p_pkg_path, const String &p_path, uint64_t p_ofs, uint64_t p_size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted, bool p_bundle, bool p_delta, const String &p_salt) {
void PackedData::add_path(const String &p_pkg_path, const String &p_path, uint64_t p_ofs, uint64_t p_size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted, bool p_bundle, bool p_delta) {
String simplified_path = p_path.simplify_path().trim_prefix("res://");
PathMD5 pmd5(simplified_path.md5_buffer());
@ -57,7 +57,6 @@ void PackedData::add_path(const String &p_pkg_path, const String &p_path, uint64
pf.bundle = p_bundle;
pf.delta = p_delta;
pf.pack = p_pkg_path;
pf.salt = p_salt;
pf.offset = p_ofs;
pf.size = p_size;
for (int i = 0; i < 16; i++) {
@ -215,7 +214,7 @@ PackedData::~PackedData() {
//////////////////////////////////////////////////////////////////
bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset, const Vector<uint8_t> &p_decryption_key) {
bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) {
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
if (f.is_null()) {
return false;
@ -292,28 +291,22 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
uint32_t ver_minor = f->get_32();
uint32_t ver_patch = f->get_32(); // Not used for validation.
ERR_FAIL_COND_V_MSG(version != PACK_FORMAT_VERSION_V4 && version != PACK_FORMAT_VERSION_V3 && version != PACK_FORMAT_VERSION_V2, false, vformat("Pack version unsupported: %d.", version));
ERR_FAIL_COND_V_MSG(version != PACK_FORMAT_VERSION_V3 && version != PACK_FORMAT_VERSION_V2, false, vformat("Pack version unsupported: %d.", version));
ERR_FAIL_COND_V_MSG(ver_major > GODOT_VERSION_MAJOR || (ver_major == GODOT_VERSION_MAJOR && ver_minor > GODOT_VERSION_MINOR), false, vformat("Pack created with a newer version of the engine: %d.%d.%d.", ver_major, ver_minor, ver_patch));
uint32_t pack_flags = f->get_32();
bool enc_directory = (pack_flags & PACK_DIR_ENCRYPTED);
bool rel_filebase = (pack_flags & PACK_REL_FILEBASE); // Note: Always enabled for V3.
bool sparse_bundle = (pack_flags & PACK_SPARSE_BUNDLE);
String salt;
uint64_t file_base = f->get_64();
if ((version == PACK_FORMAT_VERSION_V4) || (version == PACK_FORMAT_VERSION_V3) || (version == PACK_FORMAT_VERSION_V2 && rel_filebase)) {
if ((version == PACK_FORMAT_VERSION_V3) || (version == PACK_FORMAT_VERSION_V2 && rel_filebase)) {
file_base += pck_start_pos;
}
if (version == PACK_FORMAT_VERSION_V3 || version == PACK_FORMAT_VERSION_V4) {
// V3/V4: Read directory offset and skip reserved part of the header.
if (version == PACK_FORMAT_VERSION_V3) {
// V3: Read directory offset and skip reserved part of the header.
uint64_t dir_offset = f->get_64() + pck_start_pos;
if (sparse_bundle && enc_directory && version == PACK_FORMAT_VERSION_V4) {
// V4: Read encrypted directory salt.
Vector<uint8_t> salt_data = f->get_buffer(32);
salt.append_latin1(Span((const char *)salt_data.ptr(), salt_data.size()));
}
f->seek(dir_offset);
} else if (version == PACK_FORMAT_VERSION_V2) {
// V2: Directory directly after the header.
@ -330,18 +323,9 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
ERR_FAIL_COND_V_MSG(fae.is_null(), false, "Can't open encrypted pack directory.");
Vector<uint8_t> key;
#ifdef TOOLS_ENABLED
if (!p_decryption_key.is_empty()) {
ERR_FAIL_COND_V_MSG(p_decryption_key.size() != 32, false, "Decryption key must be 256-bit.");
constexpr uint8_t empty_key[32] = {};
if (memcmp(script_encryption_key, empty_key, sizeof(empty_key)) == 0) {
key = p_decryption_key;
}
} else
#endif
{
key.resize(32);
memcpy(key.ptrw(), script_encryption_key, 32);
key.resize(32);
for (int i = 0; i < key.size(); i++) {
key.write[i] = script_encryption_key[i];
}
Error err = fae->open_and_parse(f, key, FileAccessEncrypted::MODE_READ, false);
@ -366,15 +350,15 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
if (flags & PACK_FILE_REMOVAL) { // The file was removed.
PackedData::get_singleton()->remove_path(path);
} else {
PackedData::get_singleton()->add_path(p_path, path, file_base + ofs, size, md5, this, p_replace_files, (flags & PACK_FILE_ENCRYPTED), sparse_bundle, (flags & PACK_FILE_DELTA), salt);
PackedData::get_singleton()->add_path(p_path, path, file_base + ofs, size, md5, this, p_replace_files, (flags & PACK_FILE_ENCRYPTED), sparse_bundle, (flags & PACK_FILE_DELTA));
}
}
return true;
}
Ref<FileAccess> PackedSourcePCK::get_file(const String &p_path, PackedData::PackedFile *p_file, const Vector<uint8_t> &p_decryption_key) {
Ref<FileAccess> file(memnew(FileAccessPack(p_path, *p_file, p_decryption_key)));
Ref<FileAccess> PackedSourcePCK::get_file(const String &p_path, PackedData::PackedFile *p_file) {
Ref<FileAccess> file(memnew(FileAccessPack(p_path, *p_file)));
if (PackedData::get_singleton()->has_delta_patches(p_path)) {
Ref<FileAccessPatched> file_patched;
@ -389,7 +373,7 @@ Ref<FileAccess> PackedSourcePCK::get_file(const String &p_path, PackedData::Pack
//////////////////////////////////////////////////////////////////
bool PackedSourceDirectory::try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset, const Vector<uint8_t> &p_decryption_key) {
bool PackedSourceDirectory::try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) {
// Load with offset feature only supported for PCK files.
ERR_FAIL_COND_V_MSG(p_offset != 0, false, "Invalid PCK data. Note that loading files with a non-zero offset isn't supported with directories.");
@ -400,7 +384,7 @@ bool PackedSourceDirectory::try_open_pack(const String &p_path, bool p_replace_f
return true;
}
Ref<FileAccess> PackedSourceDirectory::get_file(const String &p_path, PackedData::PackedFile *p_file, const Vector<uint8_t> &p_decryption_key) {
Ref<FileAccess> PackedSourceDirectory::get_file(const String &p_path, PackedData::PackedFile *p_file) {
Ref<FileAccess> ret = FileAccess::create_for_path(p_path);
ret->reopen(p_path, FileAccess::READ);
return ret;
@ -523,24 +507,12 @@ void FileAccessPack::close() {
f = Ref<FileAccess>();
}
FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file, const Vector<uint8_t> &p_decryption_key) {
FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file) {
path = p_path;
pf = p_file;
if (pf.bundle) {
String simplified_path = p_path.simplify_path();
String path_to_load = simplified_path;
#ifdef TOOLS_ENABLED
if (!pf.salt.is_empty()) {
path_to_load = pf.pack.get_base_dir().path_join((simplified_path + pf.salt).sha256_text());
} else {
path_to_load = pf.pack.get_base_dir().path_join(simplified_path.replace("res://", ""));
}
#else
if (!pf.salt.is_empty()) {
path_to_load = "res://" + (simplified_path + pf.salt).sha256_text();
}
#endif
f = FileAccess::open(path_to_load, FileAccess::READ | FileAccess::SKIP_PACK);
f = FileAccess::open(simplified_path, FileAccess::READ | FileAccess::SKIP_PACK);
ERR_FAIL_COND_MSG(f.is_null(), vformat(R"(Can't open pack-referenced file "%s" from sparse pack "%s".)", simplified_path, pf.pack));
off = 0; // For the sparse pack offset is always zero.
} else {
@ -556,18 +528,9 @@ FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFil
ERR_FAIL_COND_MSG(fae.is_null(), vformat(R"(Can't open encrypted pack-referenced file "%s" from pack "%s".)", p_path, pf.pack));
Vector<uint8_t> key;
#ifdef TOOLS_ENABLED
if (!p_decryption_key.is_empty()) {
ERR_FAIL_COND_MSG(p_decryption_key.size() != 32, "Decryption key must be 256-bit.");
constexpr uint8_t empty_key[32] = {};
if (memcmp(script_encryption_key, empty_key, sizeof(empty_key)) == 0) {
key = p_decryption_key;
}
} else
#endif
{
key.resize(32);
memcpy(key.ptrw(), script_encryption_key, 32);
key.resize(32);
for (int i = 0; i < key.size(); i++) {
key.write[i] = script_encryption_key[i];
}
Error err = fae->open_and_parse(f, key, FileAccessEncrypted::MODE_READ, false);

View file

@ -32,7 +32,6 @@
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
#include "core/io/resource_uid.h"
#include "core/string/print_string.h"
#include "core/templates/hash_set.h"
#include "core/templates/list.h"
@ -42,10 +41,9 @@
#define PACK_FORMAT_VERSION_V2 2
#define PACK_FORMAT_VERSION_V3 3
#define PACK_FORMAT_VERSION_V4 4
// The current packed file format version number.
#define PACK_FORMAT_VERSION PACK_FORMAT_VERSION_V4
#define PACK_FORMAT_VERSION PACK_FORMAT_VERSION_V3
enum PackFlags {
PACK_DIR_ENCRYPTED = 1 << 0,
@ -76,7 +74,6 @@ public:
bool encrypted;
bool bundle;
bool delta;
String salt;
};
private:
@ -120,18 +117,9 @@ private:
void _free_packed_dirs(PackedDir *p_dir);
void _get_file_paths(PackedDir *p_dir, const String &p_parent_dir, HashSet<String> &r_paths) const;
_FORCE_INLINE_ PathMD5 _get_simplified_path(const String &p_path) {
String simplified_path = p_path;
if (simplified_path.begins_with("uid://")) {
simplified_path = ResourceUID::uid_to_path(simplified_path);
}
simplified_path = simplified_path.simplify_path().trim_prefix("res://");
return PathMD5(simplified_path.md5_buffer());
}
public:
void add_pack_source(PackSource *p_source);
void add_path(const String &p_pkg_path, const String &p_path, uint64_t p_ofs, uint64_t p_size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted = false, bool p_bundle = false, bool p_delta = false, const String &p_salt = String()); // for PackSource
void add_path(const String &p_pkg_path, const String &p_path, uint64_t p_ofs, uint64_t p_size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted = false, bool p_bundle = false, bool p_delta = false); // for PackSource
void remove_path(const String &p_path);
uint8_t *get_file_hash(const String &p_path);
Vector<PackedFile> get_delta_patches(const String &p_path) const;
@ -142,11 +130,11 @@ public:
_FORCE_INLINE_ bool is_disabled() const { return disabled; }
static PackedData *get_singleton() { return singleton; }
Error add_pack(const String &p_path, bool p_replace_files, uint64_t p_offset, const Vector<uint8_t> &p_decryption_key = Vector<uint8_t>());
Error add_pack(const String &p_path, bool p_replace_files, uint64_t p_offset);
void clear();
_FORCE_INLINE_ Ref<FileAccess> try_open_path(const String &p_path, const Vector<uint8_t> &p_decryption_key = Vector<uint8_t>());
_FORCE_INLINE_ Ref<FileAccess> try_open_path(const String &p_path);
_FORCE_INLINE_ bool has_path(const String &p_path);
_FORCE_INLINE_ int64_t get_size(const String &p_path);
@ -160,23 +148,23 @@ public:
class PackSource {
public:
virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset, const Vector<uint8_t> &p_decryption_key = Vector<uint8_t>()) = 0;
virtual Ref<FileAccess> get_file(const String &p_path, PackedData::PackedFile *p_file, const Vector<uint8_t> &p_decryption_key = Vector<uint8_t>()) = 0;
virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) = 0;
virtual Ref<FileAccess> get_file(const String &p_path, PackedData::PackedFile *p_file) = 0;
virtual ~PackSource() {}
};
class PackedSourcePCK : public PackSource {
public:
virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset, const Vector<uint8_t> &p_decryption_key = Vector<uint8_t>()) override;
virtual Ref<FileAccess> get_file(const String &p_path, PackedData::PackedFile *p_file, const Vector<uint8_t> &p_decryption_key = Vector<uint8_t>()) override;
virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) override;
virtual Ref<FileAccess> get_file(const String &p_path, PackedData::PackedFile *p_file) override;
};
class PackedSourceDirectory : public PackSource {
void add_directory(const String &p_path, bool p_replace_files);
public:
virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset, const Vector<uint8_t> &p_decryption_key = Vector<uint8_t>()) override;
virtual Ref<FileAccess> get_file(const String &p_path, PackedData::PackedFile *p_file, const Vector<uint8_t> &p_decryption_key = Vector<uint8_t>()) override;
virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) override;
virtual Ref<FileAccess> get_file(const String &p_path, PackedData::PackedFile *p_file) override;
};
class FileAccessPack : public FileAccess {
@ -228,11 +216,13 @@ public:
virtual void close() override;
FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file, const Vector<uint8_t> &p_decryption_key = Vector<uint8_t>());
FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file);
};
int64_t PackedData::get_size(const String &p_path) {
HashMap<PathMD5, PackedFile, PathMD5>::Iterator E = files.find(_get_simplified_path(p_path));
String simplified_path = p_path.simplify_path();
PathMD5 pmd5(simplified_path.md5_buffer());
HashMap<PathMD5, PackedFile, PathMD5>::Iterator E = files.find(pmd5);
if (!E) {
return -1; // File not found.
}
@ -242,17 +232,19 @@ int64_t PackedData::get_size(const String &p_path) {
return E->value.size;
}
Ref<FileAccess> PackedData::try_open_path(const String &p_path, const Vector<uint8_t> &p_decryption_key) {
HashMap<PathMD5, PackedFile, PathMD5>::Iterator E = files.find(_get_simplified_path(p_path));
Ref<FileAccess> PackedData::try_open_path(const String &p_path) {
String simplified_path = p_path.simplify_path().trim_prefix("res://");
PathMD5 pmd5(simplified_path.md5_buffer());
HashMap<PathMD5, PackedFile, PathMD5>::Iterator E = files.find(pmd5);
if (!E) {
return nullptr; // Not found.
}
return E->value.src->get_file(p_path, &E->value, p_decryption_key);
return E->value.src->get_file(p_path, &E->value);
}
bool PackedData::has_path(const String &p_path) {
return files.has(_get_simplified_path(p_path));
return files.has(PathMD5(p_path.simplify_path().trim_prefix("res://").md5_buffer()));
}
bool PackedData::has_directory(const String &p_path) {

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