mirror of
https://github.com/godotengine/godot-cpp.git
synced 2026-01-01 05:48:37 +03:00
Compare commits
110 Commits
godot-4.3-
...
4.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4bc6e67d51 | ||
|
|
b889fc3ce8 | ||
|
|
ef4c38418e | ||
|
|
9445595df2 | ||
|
|
71b5b84fb1 | ||
|
|
95a29550a7 | ||
|
|
f5fa712138 | ||
|
|
142e5d4302 | ||
|
|
c532b919df | ||
|
|
d42d913edd | ||
|
|
cb41b472f4 | ||
|
|
d8b46e3426 | ||
|
|
397669a3f6 | ||
|
|
17818534d9 | ||
|
|
549f5d6550 | ||
|
|
5f3a66a326 | ||
|
|
810b0ce13e | ||
|
|
a2a336546a | ||
|
|
5e7d2472dd | ||
|
|
6cb5eb9bca | ||
|
|
43c66817ea | ||
|
|
f8c258b3fe | ||
|
|
d06b0283c2 | ||
|
|
463a0feb28 | ||
|
|
4109e14f1b | ||
|
|
5d745add13 | ||
|
|
67e84c04f2 | ||
|
|
5921734784 | ||
|
|
fd31fabcfc | ||
|
|
9d26e3418c | ||
|
|
42d9ac3b08 | ||
|
|
f9095a5552 | ||
|
|
63c67a9977 | ||
|
|
12f6eecf65 | ||
|
|
deaf37120f | ||
|
|
cc70884db3 | ||
|
|
90e0c1515d | ||
|
|
13299e810b | ||
|
|
18321318bb | ||
|
|
806c38e189 | ||
|
|
aeb8be98ed | ||
|
|
1f9a0b7171 | ||
|
|
a0d56336c3 | ||
|
|
d6e5286cc1 | ||
|
|
80aec184df | ||
|
|
18c31e3e31 | ||
|
|
52ea8f9101 | ||
|
|
c35e7545b7 | ||
|
|
1a22e43075 | ||
|
|
121ae8d116 | ||
|
|
3bea67ce6c | ||
|
|
19f56af1be | ||
|
|
7f3e914c6d | ||
|
|
528b7801d2 | ||
|
|
9da6ecd144 | ||
|
|
c5204a2e84 | ||
|
|
a6e5caacf8 | ||
|
|
246fd4718c | ||
|
|
b81b0599f9 | ||
|
|
07b6a03d77 | ||
|
|
7e72c8bf0a | ||
|
|
f88b6a2f00 | ||
|
|
2b6eb6832e | ||
|
|
a246aaaaf6 | ||
|
|
e8e424ade8 | ||
|
|
18354f9b9b | ||
|
|
acee69a3f6 | ||
|
|
ddfcca62a8 | ||
|
|
8aef77a64d | ||
|
|
897280444b | ||
|
|
3d814f6e87 | ||
|
|
8f8ea90088 | ||
|
|
b28098e76b | ||
|
|
9afbdb9cf6 | ||
|
|
98c143a483 | ||
|
|
28d43fb99a | ||
|
|
77f1d228cd | ||
|
|
ab5b9f2ceb | ||
|
|
ef4d771444 | ||
|
|
66ced64c1e | ||
|
|
fc5366c026 | ||
|
|
7e5fa8e7a9 | ||
|
|
f8477fb9f2 | ||
|
|
ef723ca9ec | ||
|
|
7473b984cb | ||
|
|
98ad839827 | ||
|
|
a07b1f6e07 | ||
|
|
f002ca18c7 | ||
|
|
3fe7c2e87b | ||
|
|
7ddd278dea | ||
|
|
cae4bf58ac | ||
|
|
1517a24f72 | ||
|
|
1b8cfaab71 | ||
|
|
dc19986497 | ||
|
|
c2d4ccd592 | ||
|
|
51c752c46b | ||
|
|
45dc04f2cf | ||
|
|
dc76664cea | ||
|
|
97214ecd7a | ||
|
|
300e74364b | ||
|
|
3129672a4f | ||
|
|
c0b2d85ffc | ||
|
|
62eed50524 | ||
|
|
f9b66e3c72 | ||
|
|
81a72ff06b | ||
|
|
0472b6bdd4 | ||
|
|
aaffda23a5 | ||
|
|
78ffea5b13 | ||
|
|
f93a6c5a5b | ||
|
|
b03e56922d |
16
.editorconfig
Normal file
16
.editorconfig
Normal file
@@ -0,0 +1,16 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 4
|
||||
indent_style = tab
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[{*.py,SConstruct}]
|
||||
indent_style = space
|
||||
|
||||
[*.{yml,yaml}]
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
8
.gitattributes
vendored
8
.gitattributes
vendored
@@ -1,6 +1,2 @@
|
||||
*.c eol=lf
|
||||
*.cpp eol=lf
|
||||
*.gd eol=lf
|
||||
*.tscn eol=lf
|
||||
*.cfg eol=lf
|
||||
*.godot eol=lf
|
||||
# Normalize EOL for all files that Git considers text files
|
||||
* text=auto eol=lf
|
||||
|
||||
24
.github/actions/godot-cache-restore/action.yml
vendored
Normal file
24
.github/actions/godot-cache-restore/action.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
name: Restore Godot build cache
|
||||
description: Restore Godot build cache.
|
||||
inputs:
|
||||
cache-name:
|
||||
description: The cache base name (job name by default).
|
||||
default: ${{ github.job }}
|
||||
scons-cache:
|
||||
description: The SCons cache path.
|
||||
default: ${{ github.workspace }}/.scons-cache/
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Restore SCons cache directory
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ${{ inputs.scons-cache }}
|
||||
key: ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}-${{ github.sha }}
|
||||
|
||||
restore-keys: |
|
||||
${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}-${{ github.sha }}
|
||||
${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}
|
||||
${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-refs/heads/${{ env.GODOT_BASE_BRANCH }}
|
||||
${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}
|
||||
18
.github/actions/godot-cache-save/action.yml
vendored
Normal file
18
.github/actions/godot-cache-save/action.yml
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
name: Save Godot build cache
|
||||
description: Save Godot build cache.
|
||||
inputs:
|
||||
cache-name:
|
||||
description: The cache base name (job name by default).
|
||||
default: ${{ github.job }}
|
||||
scons-cache:
|
||||
description: The SCons cache path.
|
||||
default: ${{ github.workspace }}/.scons-cache/
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Save SCons cache directory
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ${{ inputs.scons-cache }}
|
||||
key: ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}-${{ github.sha }}
|
||||
22
.github/actions/godot-cache/action.yml
vendored
22
.github/actions/godot-cache/action.yml
vendored
@@ -1,22 +0,0 @@
|
||||
name: Setup Godot build cache
|
||||
description: Setup Godot build cache.
|
||||
inputs:
|
||||
cache-name:
|
||||
description: The cache base name (job name by default).
|
||||
default: "${{github.job}}"
|
||||
scons-cache:
|
||||
description: The scons cache path.
|
||||
default: "${{github.workspace}}/.scons-cache/"
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
# Upload cache on completion and check it out now
|
||||
- name: Load .scons_cache directory
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{inputs.scons-cache}}
|
||||
key: ${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}}
|
||||
restore-keys: |
|
||||
${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}}
|
||||
${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}
|
||||
${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}
|
||||
62
.github/actions/setup-godot-cpp/action.yml
vendored
Normal file
62
.github/actions/setup-godot-cpp/action.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
name: Setup godot-cpp
|
||||
description: Setup build dependencies for godot-cpp.
|
||||
|
||||
inputs:
|
||||
platform:
|
||||
required: true
|
||||
description: Target platform.
|
||||
em-version:
|
||||
default: 3.1.62
|
||||
description: Emscripten version.
|
||||
windows-compiler:
|
||||
required: true
|
||||
description: The compiler toolchain to use on Windows ('mingw' or 'msvc').
|
||||
type: choice
|
||||
options:
|
||||
- mingw
|
||||
- msvc
|
||||
default: mingw
|
||||
mingw-version:
|
||||
default: 12.2.0
|
||||
description: MinGW version.
|
||||
ndk-version:
|
||||
default: r23c
|
||||
description: Android NDK version.
|
||||
scons-version:
|
||||
default: 4.4.0
|
||||
description: SCons version.
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Setup Python (for SCons)
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- name: Setup Android dependencies
|
||||
if: inputs.platform == 'android'
|
||||
uses: nttld/setup-ndk@v1
|
||||
with:
|
||||
ndk-version: ${{ inputs.ndk-version }}
|
||||
link-to-sdk: true
|
||||
|
||||
- name: Setup Web dependencies
|
||||
if: inputs.platform == 'web'
|
||||
uses: mymindstorm/setup-emsdk@v14
|
||||
with:
|
||||
version: ${{ inputs.em-version }}
|
||||
no-cache: true
|
||||
|
||||
- name: Setup MinGW for Windows/MinGW build
|
||||
if: inputs.platform == 'windows' && inputs.windows-compiler == 'mingw'
|
||||
uses: egor-tensin/setup-mingw@v2
|
||||
with:
|
||||
version: ${{ inputs.mingw-version }}
|
||||
|
||||
- name: Setup SCons
|
||||
shell: bash
|
||||
run: |
|
||||
python -c "import sys; print(sys.version)"
|
||||
python -m pip install scons==${{ inputs.scons-version }}
|
||||
scons --version
|
||||
90
.github/workflows/ci.yml
vendored
90
.github/workflows/ci.yml
vendored
@@ -1,12 +1,15 @@
|
||||
name: Continuous integration
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
# Only used for the cache key. Increment version to force clean build.
|
||||
GODOT_BASE_BRANCH: master
|
||||
# Used to select the version of Godot to run the tests with.
|
||||
GODOT_TEST_VERSION: 4.2.2-stable
|
||||
|
||||
concurrency:
|
||||
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}
|
||||
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
@@ -52,7 +55,7 @@ jobs:
|
||||
cache-name: windows-x86_64-mingw
|
||||
|
||||
- name: 🍎 macOS (universal)
|
||||
os: macos-11
|
||||
os: macos-latest
|
||||
platform: macos
|
||||
artifact-name: godot-cpp-macos-universal-release
|
||||
artifact-path: bin/libgodot-cpp.macos.template_release.universal.a
|
||||
@@ -70,7 +73,7 @@ jobs:
|
||||
cache-name: android-arm64
|
||||
|
||||
- name: 🍏 iOS (arm64)
|
||||
os: macos-11
|
||||
os: macos-latest
|
||||
platform: ios
|
||||
artifact-name: godot-cpp-ios-arm64-release
|
||||
artifact-path: bin/libgodot-cpp.ios.template_release.arm64.a
|
||||
@@ -89,7 +92,6 @@ jobs:
|
||||
env:
|
||||
SCONS_CACHE: ${{ github.workspace }}/.scons-cache/
|
||||
EM_VERSION: 3.1.39
|
||||
EM_CACHE_FOLDER: "emsdk-cache"
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -97,63 +99,46 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup Godot build cache
|
||||
uses: ./.github/actions/godot-cache
|
||||
- name: Restore Godot build cache
|
||||
uses: ./.github/actions/godot-cache-restore
|
||||
with:
|
||||
cache-name: ${{ matrix.cache-name }}
|
||||
continue-on-error: true
|
||||
|
||||
- name: Set up Python (for SCons)
|
||||
uses: actions/setup-python@v4
|
||||
- name: Setup godot-cpp
|
||||
uses: ./.github/actions/setup-godot-cpp
|
||||
with:
|
||||
python-version: '3.x'
|
||||
|
||||
- name: Android dependencies
|
||||
if: ${{ matrix.platform == 'android' }}
|
||||
uses: nttld/setup-ndk@v1
|
||||
with:
|
||||
ndk-version: r23c
|
||||
link-to-sdk: true
|
||||
|
||||
- name: Web dependencies
|
||||
if: ${{ matrix.platform == 'web' }}
|
||||
uses: mymindstorm/setup-emsdk@v13
|
||||
with:
|
||||
version: ${{env.EM_VERSION}}
|
||||
actions-cache-folder: ${{env.EM_CACHE_FOLDER}}
|
||||
|
||||
- name: Setup MinGW for Windows/MinGW build
|
||||
if: ${{ matrix.platform == 'windows' && matrix.flags == 'use_mingw=yes' }}
|
||||
uses: egor-tensin/setup-mingw@v2
|
||||
with:
|
||||
version: 12.2.0
|
||||
|
||||
- name: Install scons
|
||||
run: |
|
||||
python -m pip install scons==4.0.0
|
||||
platform: ${{ matrix.platform }}
|
||||
windows-compiler: ${{ contains(matrix.flags, 'use_mingw=yes') && 'mingw' || 'msvc' }}
|
||||
|
||||
- name: Generate godot-cpp sources only
|
||||
run: |
|
||||
scons platform=${{ matrix.platform }} build_library=no ${{ matrix.flags }}
|
||||
scons platform=${{ matrix.platform }} verbose=yes build_library=no ${{ matrix.flags }}
|
||||
scons -c
|
||||
|
||||
- name: Build godot-cpp (debug)
|
||||
run: |
|
||||
scons platform=${{ matrix.platform }} target=template_debug ${{ matrix.flags }}
|
||||
scons platform=${{ matrix.platform }} verbose=yes target=template_debug ${{ matrix.flags }}
|
||||
|
||||
- name: Build test without rebuilding godot-cpp (debug)
|
||||
run: |
|
||||
cd test
|
||||
scons platform=${{ matrix.platform }} target=template_debug ${{ matrix.flags }} build_library=no
|
||||
scons platform=${{ matrix.platform }} verbose=yes target=template_debug ${{ matrix.flags }} build_library=no
|
||||
|
||||
- name: Build test and godot-cpp (release)
|
||||
run: |
|
||||
cd test
|
||||
scons platform=${{ matrix.platform }} target=template_release ${{ matrix.flags }}
|
||||
scons platform=${{ matrix.platform }} verbose=yes target=template_release ${{ matrix.flags }}
|
||||
|
||||
- name: Save Godot build cache
|
||||
uses: ./.github/actions/godot-cache-save
|
||||
with:
|
||||
cache-name: ${{ matrix.cache-name }}
|
||||
continue-on-error: true
|
||||
|
||||
- name: Download latest Godot artifacts
|
||||
uses: dsnopek/action-download-artifact@1322f74e2dac9feed2ee76a32d9ae1ca3b4cf4e9
|
||||
if: ${{ matrix.run-tests }}
|
||||
if: matrix.run-tests && env.GODOT_TEST_VERSION == 'master'
|
||||
with:
|
||||
repo: godotengine/godot
|
||||
branch: master
|
||||
@@ -166,15 +151,28 @@ jobs:
|
||||
ensure_latest: true
|
||||
path: godot-artifacts
|
||||
|
||||
- name: Run tests
|
||||
if: ${{ matrix.run-tests }}
|
||||
- name: Prepare Godot artifacts for testing
|
||||
if: matrix.run-tests && env.GODOT_TEST_VERSION == 'master'
|
||||
run: |
|
||||
chmod +x ./godot-artifacts/godot.linuxbsd.editor.x86_64.mono
|
||||
./godot-artifacts/godot.linuxbsd.editor.x86_64.mono --headless --version
|
||||
echo "GODOT=$(pwd)/godot-artifacts/godot.linuxbsd.editor.x86_64.mono" >> $GITHUB_ENV
|
||||
|
||||
- name: Download requested Godot version for testing
|
||||
if: matrix.run-tests && env.GODOT_TEST_VERSION != 'master'
|
||||
run: |
|
||||
wget "https://github.com/godotengine/godot-builds/releases/download/${GODOT_TEST_VERSION}/Godot_v${GODOT_TEST_VERSION}_linux.x86_64.zip" -O Godot.zip
|
||||
unzip -a Godot.zip
|
||||
chmod +x "Godot_v${GODOT_TEST_VERSION}_linux.x86_64"
|
||||
echo "GODOT=$(pwd)/Godot_v${GODOT_TEST_VERSION}_linux.x86_64" >> $GITHUB_ENV
|
||||
|
||||
- name: Run tests
|
||||
if: matrix.run-tests
|
||||
run: |
|
||||
$GODOT --headless --version
|
||||
cd test
|
||||
# Need to run the editor so .godot is generated... but it crashes! Ignore that :-)
|
||||
(cd project && (timeout 10 ../../godot-artifacts/godot.linuxbsd.editor.x86_64.mono --editor --headless --quit >/dev/null 2>&1 || true))
|
||||
GODOT=../godot-artifacts/godot.linuxbsd.editor.x86_64.mono ./run-tests.sh
|
||||
(cd project && (timeout 30 $GODOT --editor --headless --quit >/dev/null 2>&1 || true))
|
||||
./run-tests.sh
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
@@ -243,9 +241,9 @@ jobs:
|
||||
- name: Build godot-cpp
|
||||
run: |
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -G"Visual Studio 16 2019" .
|
||||
cmake --build . --verbose
|
||||
cmake --build . --verbose --config Release
|
||||
|
||||
- name: Build test GDExtension library
|
||||
run: |
|
||||
cd test && cmake -DCMAKE_BUILD_TYPE=Release -DGODOT_HEADERS_PATH="../godot-headers" -DCPP_BINDINGS_PATH=".." -G"Visual Studio 16 2019" .
|
||||
cmake --build . --verbose
|
||||
cmake --build . --verbose --config Release
|
||||
|
||||
21
.github/workflows/runner.yml
vendored
Normal file
21
.github/workflows/runner.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
name: 🔗 GHA
|
||||
on: [push, pull_request, merge_group]
|
||||
|
||||
concurrency:
|
||||
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-runner
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
# First stage: Only static checks, fast and prevent expensive builds from running.
|
||||
|
||||
static-checks:
|
||||
if: '!vars.DISABLE_GODOT_CI'
|
||||
name: 📊 Static Checks
|
||||
uses: ./.github/workflows/static_checks.yml
|
||||
|
||||
# Second stage: Run all the builds and some of the tests.
|
||||
|
||||
ci:
|
||||
name: 🛠️ Continuous Integration
|
||||
needs: static-checks
|
||||
uses: ./.github/workflows/ci.yml
|
||||
64
.github/workflows/static_checks.yml
vendored
64
.github/workflows/static_checks.yml
vendored
@@ -1,54 +1,38 @@
|
||||
name: 📊 Static Checks
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
concurrency:
|
||||
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-static
|
||||
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-static
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
static-checks:
|
||||
name: Format (clang-format, black format, file format)
|
||||
runs-on: ubuntu-20.04
|
||||
name: Format (clang-format, ruff format, file format)
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
# Azure repositories are not reliable, we need to prevent Azure giving us packages.
|
||||
- name: Make apt sources.list use the default Ubuntu repositories
|
||||
- name: Get changed files
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
sudo rm -f /etc/apt/sources.list.d/*
|
||||
sudo cp -f misc/ci/sources.list /etc/apt/sources.list
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo apt-add-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-15 main"
|
||||
sudo apt-get update
|
||||
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" | grep -v 'thirdparty' | xargs -I {} sh -c 'echo "\"./{}\""' | tr '\n' ' ')
|
||||
echo "CHANGED_FILES=$files" >> $GITHUB_ENV
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get install -qq dos2unix recode clang-format-15 libxml2-utils python3-pip moreutils
|
||||
sudo update-alternatives --remove-all clang-format || true
|
||||
sudo update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-15 100
|
||||
sudo pip3 install black==22.3.0 pygments pytest==7.1.2 mypy==0.971
|
||||
- name: Style checks via pre-commit
|
||||
uses: pre-commit/action@v3.0.1
|
||||
with:
|
||||
extra_args: --verbose --hook-stage manual --files ${{ env.CHANGED_FILES }}
|
||||
|
||||
- name: File formatting checks (file_format.sh)
|
||||
run: |
|
||||
bash ./misc/scripts/file_format.sh
|
||||
|
||||
- name: Header guards formatting checks (header_guards.sh)
|
||||
run: |
|
||||
bash ./misc/scripts/header_guards.sh
|
||||
|
||||
- name: Python style checks via black (black_format.sh)
|
||||
run: |
|
||||
bash ./misc/scripts/black_format.sh
|
||||
|
||||
- name: Python scripts static analysis (mypy_check.sh)
|
||||
run: |
|
||||
bash ./misc/scripts/mypy_check.sh
|
||||
|
||||
- name: Bindings generation checks (ensures get_file_list returns all generated files)
|
||||
run: |
|
||||
python ./misc/scripts/check_get_file_list.py
|
||||
|
||||
- name: Style checks via clang-format (clang_format.sh)
|
||||
run: |
|
||||
bash ./misc/scripts/clang_format.sh
|
||||
- name: Check generated files consistency
|
||||
run:
|
||||
python misc/scripts/check_get_file_list.py
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -8,7 +8,7 @@
|
||||
include/gen
|
||||
src/gen
|
||||
|
||||
# Build configuarion.
|
||||
# Build configuration.
|
||||
/custom.py
|
||||
|
||||
# Misc
|
||||
@@ -195,3 +195,7 @@ compile_commands.json
|
||||
# Python development
|
||||
.venv
|
||||
venv
|
||||
|
||||
# Clion Configuration
|
||||
.idea/
|
||||
cmake-build-*
|
||||
|
||||
64
.pre-commit-config.yaml
Normal file
64
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,64 @@
|
||||
default_language_version:
|
||||
python: python3
|
||||
|
||||
exclude: |
|
||||
(?x)^(
|
||||
gdextension/extension_api\.json|
|
||||
gdextension/gdextension_interface\.h
|
||||
)$
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: v17.0.6
|
||||
hooks:
|
||||
- id: clang-format
|
||||
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.4.4
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: [--fix]
|
||||
- id: ruff-format
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v0.971
|
||||
hooks:
|
||||
- id: mypy
|
||||
files: \.py$
|
||||
types_or: [text]
|
||||
|
||||
- repo: https://github.com/codespell-project/codespell
|
||||
rev: v2.3.0
|
||||
hooks:
|
||||
- id: codespell
|
||||
additional_dependencies: [tomli]
|
||||
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: copyright-headers
|
||||
name: copyright-headers
|
||||
language: python
|
||||
entry: python misc/scripts/copyright_headers.py
|
||||
files: \.(c|h)pp$
|
||||
exclude: ^test/
|
||||
|
||||
- id: header-guards
|
||||
name: header-guards
|
||||
language: python
|
||||
entry: python misc/scripts/header_guards.py
|
||||
files: \.hpp$
|
||||
exclude: ^test/
|
||||
|
||||
- id: file-format
|
||||
name: file-format
|
||||
language: python
|
||||
entry: python misc/scripts/file_format.py
|
||||
types_or: [text]
|
||||
|
||||
- id: check-get-file-list
|
||||
name: check-get-file-list
|
||||
language: python
|
||||
entry: python misc/scripts/check_get_file_list.py
|
||||
pass_filenames: false
|
||||
always_run: true
|
||||
stages: [manual]
|
||||
235
CMakeLists.txt
235
CMakeLists.txt
@@ -1,227 +1,24 @@
|
||||
# cmake arguments
|
||||
# CMAKE_BUILD_TYPE: Compilation target (Debug or Release defaults to Debug)
|
||||
#
|
||||
# godot-cpp cmake arguments
|
||||
# GODOT_GDEXTENSION_DIR: Path to the directory containing GDExtension interface header and API JSON file
|
||||
# GODOT_CPP_SYSTEM_HEADERS Mark the header files as SYSTEM. This may be useful to supress warnings in projects including this one.
|
||||
# GODOT_CPP_WARNING_AS_ERROR Treat any warnings as errors
|
||||
# GODOT_CUSTOM_API_FILE: Path to a custom GDExtension API JSON file (takes precedence over `gdextension_dir`)
|
||||
# FLOAT_PRECISION: Floating-point precision level ("single", "double")
|
||||
#
|
||||
# Android cmake arguments
|
||||
# CMAKE_TOOLCHAIN_FILE: The path to the android cmake toolchain ($ANDROID_NDK/build/cmake/android.toolchain.cmake)
|
||||
# ANDROID_NDK: The path to the android ndk root folder
|
||||
# ANDROID_TOOLCHAIN_NAME: The android toolchain (arm-linux-androideabi-4.9 or aarch64-linux-android-4.9 or x86-4.9 or x86_64-4.9)
|
||||
# ANDROID_PLATFORM: The android platform version (android-23)
|
||||
# More info here: https://godot.readthedocs.io/en/latest/development/compiling/compiling_for_android.html
|
||||
#
|
||||
# Examples
|
||||
#
|
||||
# Builds a debug version:
|
||||
# cmake .
|
||||
# cmake --build .
|
||||
#
|
||||
# Builds a release version with clang
|
||||
# CC=/usr/bin/clang CXX=/usr/bin/clang++ cmake -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" .
|
||||
# cmake --build .
|
||||
#
|
||||
# Builds an android armeabi-v7a debug version:
|
||||
# cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake -DANDROID_NDK=$ANDROID_NDK \
|
||||
# -DANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.9 -DANDROID_PLATFORM=android-23 -DCMAKE_BUILD_TYPE=Debug .
|
||||
# cmake --build .
|
||||
#
|
||||
# Protip
|
||||
# Generate the buildfiles in a sub directory to not clutter the root directory with build files:
|
||||
# mkdir build && cd build && cmake -G "Unix Makefiles" .. && cmake --build .
|
||||
#
|
||||
# Todo
|
||||
# Test build for Windows, Mac and mingw.
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
project(godot-cpp LANGUAGES CXX)
|
||||
|
||||
option(GENERATE_TEMPLATE_GET_NODE "Generate a template version of the Node class's get_node." ON)
|
||||
option(GODOT_CPP_SYSTEM_HEADERS "Expose headers as SYSTEM." ON)
|
||||
option(GODOT_CPP_WARNING_AS_ERROR "Treat warnings as errors" OFF)
|
||||
|
||||
# Add path to modules
|
||||
list( APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" )
|
||||
|
||||
# Check if we are building ourself or being included
|
||||
if(${PROJECT_NAME} STREQUAL ${CMAKE_PROJECT_NAME})
|
||||
set(GODOT_CPP_BUILDING_SELF ON)
|
||||
endif()
|
||||
|
||||
# Set some helper variables for readability
|
||||
set( compiler_is_clang "$<OR:$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:Clang>>" )
|
||||
set( compiler_is_gnu "$<CXX_COMPILER_ID:GNU>" )
|
||||
set( compiler_is_msvc "$<CXX_COMPILER_ID:MSVC>" )
|
||||
|
||||
# Default build type is Debug in the SConstruct
|
||||
if("${CMAKE_BUILD_TYPE}" STREQUAL "")
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED BITS)
|
||||
set(BITS 32)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(BITS 64)
|
||||
endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
endif()
|
||||
|
||||
# Input from user for GDExtension interface header and the API JSON file
|
||||
set(GODOT_GDEXTENSION_DIR "gdextension" CACHE STRING "")
|
||||
set(GODOT_CUSTOM_API_FILE "" CACHE STRING "")
|
||||
|
||||
set(GODOT_GDEXTENSION_API_FILE "${GODOT_GDEXTENSION_DIR}/extension_api.json")
|
||||
if (NOT "${GODOT_CUSTOM_API_FILE}" STREQUAL "") # User-defined override.
|
||||
set(GODOT_GDEXTENSION_API_FILE "${GODOT_CUSTOM_API_FILE}")
|
||||
endif()
|
||||
|
||||
set(FLOAT_PRECISION "single" CACHE STRING "")
|
||||
if ("${FLOAT_PRECISION}" STREQUAL "double")
|
||||
add_definitions(-DREAL_T_IS_DOUBLE)
|
||||
endif()
|
||||
|
||||
set(GODOT_COMPILE_FLAGS )
|
||||
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
# using Visual Studio C++
|
||||
set(GODOT_COMPILE_FLAGS "/utf-8") # /GF /MP
|
||||
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /MDd") # /Od /RTC1 /Zi
|
||||
else()
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /MD /O2") # /Oy /GL /Gy
|
||||
STRING(REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
|
||||
endif(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
|
||||
add_definitions(-DNOMINMAX)
|
||||
else() # GCC/Clang
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0 -g")
|
||||
else()
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -O3")
|
||||
endif(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
endif()
|
||||
|
||||
# Disable exception handling. Godot doesn't use exceptions anywhere, and this
|
||||
# saves around 20% of binary size and very significant build time (GH-80513).
|
||||
option(GODOT_DISABLE_EXCEPTIONS ON "Force disabling exception handling code")
|
||||
if (GODOT_DISABLE_EXCEPTIONS)
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -D_HAS_EXCEPTIONS=0")
|
||||
else()
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-exceptions")
|
||||
endif()
|
||||
else()
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /EHsc")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Generate source from the bindings file
|
||||
find_package(Python3 3.4 REQUIRED) # pathlib should be present
|
||||
if(GENERATE_TEMPLATE_GET_NODE)
|
||||
set(GENERATE_BINDING_PARAMETERS "True")
|
||||
else()
|
||||
set(GENERATE_BINDING_PARAMETERS "False")
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.print_file_list(\"${GODOT_GDEXTENSION_API_FILE}\", \"${CMAKE_CURRENT_BINARY_DIR}\", headers=True, sources=True)"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GENERATED_FILES_LIST
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
add_custom_command(OUTPUT ${GENERATED_FILES_LIST}
|
||||
COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.generate_bindings(\"${GODOT_GDEXTENSION_API_FILE}\", \"${GENERATE_BINDING_PARAMETERS}\", \"${BITS}\", \"${FLOAT_PRECISION}\", \"${CMAKE_CURRENT_BINARY_DIR}\")"
|
||||
VERBATIM
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
MAIN_DEPENDENCY ${GODOT_GDEXTENSION_API_FILE}
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/binding_generator.py
|
||||
COMMENT "Generating bindings"
|
||||
)
|
||||
|
||||
# Get Sources
|
||||
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS src/*.c**)
|
||||
file(GLOB_RECURSE HEADERS CONFIGURE_DEPENDS include/*.h**)
|
||||
|
||||
# Define our godot-cpp library
|
||||
add_library(${PROJECT_NAME} STATIC
|
||||
${SOURCES}
|
||||
${HEADERS}
|
||||
${GENERATED_FILES_LIST}
|
||||
)
|
||||
add_library(godot::cpp ALIAS ${PROJECT_NAME})
|
||||
|
||||
include(GodotCompilerWarnings)
|
||||
|
||||
# Treat warnings as errors if we are building ourself
|
||||
if(GODOT_CPP_BUILDING_SELF)
|
||||
unset( GODOT_CPP_WARNING_AS_ERROR CACHE )
|
||||
set_warning_as_error()
|
||||
endif()
|
||||
|
||||
target_compile_features(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
cxx_std_17
|
||||
)
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC
|
||||
$<$<CONFIG:Debug>:
|
||||
DEBUG_ENABLED
|
||||
DEBUG_METHODS_ENABLED
|
||||
>
|
||||
$<${compiler_is_msvc}:
|
||||
TYPED_METHOD_BIND
|
||||
>
|
||||
)
|
||||
|
||||
target_link_options(${PROJECT_NAME} PRIVATE
|
||||
$<$<NOT:${compiler_is_msvc}>:
|
||||
-static-libgcc
|
||||
-static-libstdc++
|
||||
-Wl,-R,'$$ORIGIN'
|
||||
>
|
||||
)
|
||||
|
||||
# Optionally mark headers as SYSTEM
|
||||
set(GODOT_CPP_SYSTEM_HEADERS_ATTRIBUTE "")
|
||||
if (GODOT_CPP_SYSTEM_HEADERS)
|
||||
set(GODOT_CPP_SYSTEM_HEADERS_ATTRIBUTE SYSTEM)
|
||||
# Configure CMake
|
||||
# https://discourse.cmake.org/t/how-do-i-remove-compile-options-from-target/5965
|
||||
# https://stackoverflow.com/questions/74426638/how-to-remove-rtc1-from-specific-target-or-file-in-cmake
|
||||
if(${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
|
||||
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
STRING(REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
target_include_directories(${PROJECT_NAME} ${GODOT_CPP_SYSTEM_HEADERS_ATTRIBUTE} PUBLIC
|
||||
include
|
||||
${CMAKE_CURRENT_BINARY_DIR}/gen/include
|
||||
${GODOT_GDEXTENSION_DIR}
|
||||
)
|
||||
include( ${PROJECT_SOURCE_DIR}/cmake/godotcpp.cmake )
|
||||
|
||||
# Add the compile flags
|
||||
set_property(TARGET ${PROJECT_NAME} APPEND_STRING PROPERTY COMPILE_FLAGS ${GODOT_COMPILE_FLAGS})
|
||||
# I know this doesn't look like a typical CMakeLists.txt, but as we are
|
||||
# attempting mostly feature parity with SCons, and easy maintenance, the closer
|
||||
# the two build systems look the easier they will be to keep in lockstep.
|
||||
|
||||
# Create the correct name (godot.os.build_type.system_bits)
|
||||
string(TOLOWER "${CMAKE_SYSTEM_NAME}" SYSTEM_NAME)
|
||||
string(TOLOWER "${CMAKE_BUILD_TYPE}" BUILD_TYPE)
|
||||
# The typical target definitions are in ${PROJECT_SOURCE_DIR}/cmake/godotcpp.cmake
|
||||
|
||||
if(ANDROID)
|
||||
# Added the android abi after system name
|
||||
set(SYSTEM_NAME ${SYSTEM_NAME}.${ANDROID_ABI})
|
||||
godotcpp_options()
|
||||
|
||||
# Android does not have the bits at the end if you look at the main godot repo build
|
||||
set(OUTPUT_NAME "godot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}")
|
||||
else()
|
||||
set(OUTPUT_NAME "godot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}.${BITS}")
|
||||
endif()
|
||||
|
||||
set_target_properties(${PROJECT_NAME}
|
||||
PROPERTIES
|
||||
CXX_EXTENSIONS OFF
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin"
|
||||
OUTPUT_NAME "${OUTPUT_NAME}"
|
||||
)
|
||||
godotcpp_generate()
|
||||
|
||||
12
README.md
12
README.md
@@ -58,7 +58,7 @@ first-party `godot-cpp` extension.
|
||||
Some compatibility breakage is to be expected as GDExtension and `godot-cpp`
|
||||
get more used, documented, and critical issues get resolved. See the
|
||||
[Godot issue tracker](https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aopen+label%3Atopic%3Agdextension)
|
||||
and the [godot-cpp issue tracker](https://github.com/godotengine/godot/issues)
|
||||
and the [godot-cpp issue tracker](https://github.com/godotengine/godot-cpp/issues)
|
||||
for a list of known issues, and be sure to provide feedback on issues and PRs
|
||||
which affect your use of this extension.
|
||||
|
||||
@@ -69,12 +69,14 @@ wish to help out, ensure you have an account on GitHub and create a "fork" of
|
||||
this repository. See [Pull request workflow](https://docs.godotengine.org/en/stable/community/contributing/pr_workflow.html)
|
||||
for instructions.
|
||||
|
||||
Please install clang-format and copy the files in `misc/hooks` into `.git/hooks`
|
||||
so formatting is done before your changes are submitted.
|
||||
Please install clang-format and the [pre-commit](https://pre-commit.com/) Python framework so formatting is done before your changes are submitted. See the [code style guidelines](https://docs.godotengine.org/en/latest/contributing/development/code_style_guidelines.html#pre-commit-hook) for instructions.
|
||||
|
||||
## Getting started
|
||||
|
||||
It's a bit similar to what it was for 3.x but also a bit different.
|
||||
You need the same C++ pre-requisites installed that are required for the `godot` repository. Follow the [official build instructions for your target platform](https://docs.godotengine.org/en/latest/contributing/development/compiling/index.html#building-for-target-platforms).
|
||||
|
||||
Getting started with GDExtensions is a bit similar to what it was for 3.x but also a bit different.
|
||||
|
||||
This new approach is much more akin to how core Godot modules are structured.
|
||||
|
||||
Compiling this repository generates a static library to be linked with your shared lib,
|
||||
@@ -129,7 +131,7 @@ void initialize_example_module(ModuleInitializationLevel p_level) {
|
||||
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||
return;
|
||||
}
|
||||
ClassDB::register_class<Example>();
|
||||
GDREGISTER_CLASS(Example);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
import subprocess
|
||||
from binding_generator import scons_generate_bindings, scons_emit_files
|
||||
|
||||
|
||||
EnsureSConsVersion(4, 0)
|
||||
|
||||
|
||||
try:
|
||||
Import("env")
|
||||
except:
|
||||
except Exception:
|
||||
# Default tools with no platform defaults to gnu toolchain.
|
||||
# We apply platform specific toolchains via our custom tools.
|
||||
env = Environment(tools=["default"], PLATFORM="")
|
||||
@@ -23,7 +18,7 @@ env.PrependENVPath("PATH", os.getenv("PATH"))
|
||||
customs = ["custom.py"]
|
||||
try:
|
||||
customs += Import("customs")
|
||||
except:
|
||||
except Exception:
|
||||
pass
|
||||
profile = ARGUMENTS.get("profile", "")
|
||||
if profile:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
183
build_profile.py
Normal file
183
build_profile.py
Normal file
@@ -0,0 +1,183 @@
|
||||
import json
|
||||
import sys
|
||||
|
||||
|
||||
def parse_build_profile(profile_filepath, api):
|
||||
if profile_filepath == "":
|
||||
return {}
|
||||
|
||||
with open(profile_filepath, encoding="utf-8") as profile_file:
|
||||
profile = json.load(profile_file)
|
||||
|
||||
api_dict = {}
|
||||
parents = {}
|
||||
children = {}
|
||||
for engine_class in api["classes"]:
|
||||
api_dict[engine_class["name"]] = engine_class
|
||||
parent = engine_class.get("inherits", "")
|
||||
child = engine_class["name"]
|
||||
parents[child] = parent
|
||||
if parent == "":
|
||||
continue
|
||||
children[parent] = children.get(parent, [])
|
||||
children[parent].append(child)
|
||||
|
||||
included = []
|
||||
front = list(profile.get("enabled_classes", []))
|
||||
if front:
|
||||
# These must always be included
|
||||
front.append("WorkerThreadPool")
|
||||
front.append("ClassDB")
|
||||
front.append("ClassDBSingleton")
|
||||
# In src/classes/low_level.cpp
|
||||
front.append("FileAccess")
|
||||
front.append("Image")
|
||||
front.append("XMLParser")
|
||||
# In include/godot_cpp/templates/thread_work_pool.hpp
|
||||
front.append("Semaphore")
|
||||
while front:
|
||||
cls = front.pop()
|
||||
if cls in included:
|
||||
continue
|
||||
included.append(cls)
|
||||
parent = parents.get(cls, "")
|
||||
if parent:
|
||||
front.append(parent)
|
||||
|
||||
excluded = []
|
||||
front = list(profile.get("disabled_classes", []))
|
||||
while front:
|
||||
cls = front.pop()
|
||||
if cls in excluded:
|
||||
continue
|
||||
excluded.append(cls)
|
||||
front += children.get(cls, [])
|
||||
|
||||
if included and excluded:
|
||||
print(
|
||||
"WARNING: Cannot specify both 'enabled_classes' and 'disabled_classes' in build profile. 'disabled_classes' will be ignored."
|
||||
)
|
||||
|
||||
return {
|
||||
"enabled_classes": included,
|
||||
"disabled_classes": excluded,
|
||||
}
|
||||
|
||||
|
||||
def generate_trimmed_api(source_api_filepath, profile_filepath):
|
||||
with open(source_api_filepath, encoding="utf-8") as api_file:
|
||||
api = json.load(api_file)
|
||||
|
||||
if profile_filepath == "":
|
||||
return api
|
||||
|
||||
build_profile = parse_build_profile(profile_filepath, api)
|
||||
|
||||
engine_classes = {}
|
||||
for class_api in api["classes"]:
|
||||
engine_classes[class_api["name"]] = class_api["is_refcounted"]
|
||||
for native_struct in api["native_structures"]:
|
||||
if native_struct["name"] == "ObjectID":
|
||||
continue
|
||||
engine_classes[native_struct["name"]] = False
|
||||
|
||||
classes = []
|
||||
for class_api in api["classes"]:
|
||||
if not is_class_included(class_api["name"], build_profile):
|
||||
continue
|
||||
if "methods" in class_api:
|
||||
methods = []
|
||||
for method in class_api["methods"]:
|
||||
if not is_method_included(method, build_profile, engine_classes):
|
||||
continue
|
||||
methods.append(method)
|
||||
class_api["methods"] = methods
|
||||
classes.append(class_api)
|
||||
api["classes"] = classes
|
||||
|
||||
return api
|
||||
|
||||
|
||||
def is_class_included(class_name, build_profile):
|
||||
"""
|
||||
Check if an engine class should be included.
|
||||
This removes classes according to a build profile of enabled or disabled classes.
|
||||
"""
|
||||
included = build_profile.get("enabled_classes", [])
|
||||
excluded = build_profile.get("disabled_classes", [])
|
||||
if included:
|
||||
return class_name in included
|
||||
if excluded:
|
||||
return class_name not in excluded
|
||||
return True
|
||||
|
||||
|
||||
def is_method_included(method, build_profile, engine_classes):
|
||||
"""
|
||||
Check if an engine class method should be included.
|
||||
This removes methods according to a build profile of enabled or disabled classes.
|
||||
"""
|
||||
included = build_profile.get("enabled_classes", [])
|
||||
excluded = build_profile.get("disabled_classes", [])
|
||||
ref_cls = set()
|
||||
rtype = get_base_type(method.get("return_value", {}).get("type", ""))
|
||||
args = [get_base_type(a["type"]) for a in method.get("arguments", [])]
|
||||
if rtype in engine_classes:
|
||||
ref_cls.add(rtype)
|
||||
elif is_enum(rtype) and get_enum_class(rtype) in engine_classes:
|
||||
ref_cls.add(get_enum_class(rtype))
|
||||
for arg in args:
|
||||
if arg in engine_classes:
|
||||
ref_cls.add(arg)
|
||||
elif is_enum(arg) and get_enum_class(arg) in engine_classes:
|
||||
ref_cls.add(get_enum_class(arg))
|
||||
for acls in ref_cls:
|
||||
if len(included) > 0 and acls not in included:
|
||||
return False
|
||||
elif len(excluded) > 0 and acls in excluded:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def is_enum(type_name):
|
||||
return type_name.startswith("enum::") or type_name.startswith("bitfield::")
|
||||
|
||||
|
||||
def get_enum_class(enum_name: str):
|
||||
if "." in enum_name:
|
||||
if is_bitfield(enum_name):
|
||||
return enum_name.replace("bitfield::", "").split(".")[0]
|
||||
else:
|
||||
return enum_name.replace("enum::", "").split(".")[0]
|
||||
else:
|
||||
return "GlobalConstants"
|
||||
|
||||
|
||||
def get_base_type(type_name):
|
||||
if type_name.startswith("const "):
|
||||
type_name = type_name[6:]
|
||||
if type_name.endswith("*"):
|
||||
type_name = type_name[:-1]
|
||||
if type_name.startswith("typedarray::"):
|
||||
type_name = type_name.replace("typedarray::", "")
|
||||
return type_name
|
||||
|
||||
|
||||
def is_bitfield(type_name):
|
||||
return type_name.startswith("bitfield::")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 3 or len(sys.argv) > 4:
|
||||
print("Usage: %s BUILD_PROFILE INPUT_JSON [OUTPUT_JSON]" % (sys.argv[0]))
|
||||
sys.exit(1)
|
||||
profile = sys.argv[1]
|
||||
infile = sys.argv[2]
|
||||
outfile = sys.argv[3] if len(sys.argv) > 3 else ""
|
||||
api = generate_trimmed_api(infile, profile)
|
||||
|
||||
if outfile:
|
||||
with open(outfile, "w", encoding="utf-8") as f:
|
||||
json.dump(api, f)
|
||||
else:
|
||||
json.dump(api, sys.stdout)
|
||||
@@ -89,6 +89,6 @@ function( set_warning_as_error )
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
if ( GODOT_CPP_WARNING_AS_ERROR )
|
||||
if ( GODOT_WARNING_AS_ERROR )
|
||||
set_warning_as_error()
|
||||
endif()
|
||||
240
cmake/godotcpp.cmake
Normal file
240
cmake/godotcpp.cmake
Normal file
@@ -0,0 +1,240 @@
|
||||
function( godotcpp_options )
|
||||
|
||||
#TODO platform
|
||||
#TODO target
|
||||
|
||||
# Input from user for GDExtension interface header and the API JSON file
|
||||
set(GODOT_GDEXTENSION_DIR "gdextension" CACHE PATH
|
||||
"Path to a custom directory containing GDExtension interface header and API JSON file ( /path/to/gdextension_dir )" )
|
||||
set(GODOT_CUSTOM_API_FILE "" CACHE FILEPATH
|
||||
"Path to a custom GDExtension API JSON file (takes precedence over `gdextension_dir`) ( /path/to/custom_api_file )")
|
||||
|
||||
#TODO generate_bindings
|
||||
|
||||
option(GODOT_GENERATE_TEMPLATE_GET_NODE
|
||||
"Generate a template version of the Node class's get_node. (ON|OFF)" ON)
|
||||
|
||||
#TODO build_library
|
||||
|
||||
set(GODOT_PRECISION "single" CACHE STRING
|
||||
"Set the floating-point precision level (single|double)")
|
||||
|
||||
#TODO arch
|
||||
#TODO threads
|
||||
#TODO compiledb
|
||||
#TODO compiledb_file
|
||||
#TODO build_profile aka cmake preset
|
||||
|
||||
set(GODOT_USE_HOT_RELOAD "" CACHE BOOL
|
||||
"Enable the extra accounting required to support hot reload. (ON|OFF)")
|
||||
|
||||
option(GODOT_DISABLE_EXCEPTIONS "Force disabling exception handling code (ON|OFF)" ON )
|
||||
|
||||
set( GODOT_SYMBOL_VISIBILITY "hidden" CACHE STRING
|
||||
"Symbols visibility on GNU platforms. Use 'auto' to apply the default value. (auto|visible|hidden)")
|
||||
set_property( CACHE GODOT_SYMBOL_VISIBILITY PROPERTY STRINGS "auto;visible;hidden" )
|
||||
|
||||
#TODO optimize
|
||||
#TODO debug_symbols
|
||||
#TODO dev_build
|
||||
|
||||
# FIXME These options are not present in SCons, and perhaps should be added there.
|
||||
option(GODOT_SYSTEM_HEADERS "Expose headers as SYSTEM." ON)
|
||||
option(GODOT_WARNING_AS_ERROR "Treat warnings as errors" OFF)
|
||||
|
||||
# Run options commands on the following to populate cache for all platforms.
|
||||
# This type of thing is typically done conditionally
|
||||
# But as scons shows all options so shall we.
|
||||
#TODO ios_options()
|
||||
#TODO linux_options()
|
||||
#TODO macos_options()
|
||||
#TODO web_options()
|
||||
#TODO windows_options()
|
||||
endfunction()
|
||||
|
||||
|
||||
function( godotcpp_generate )
|
||||
# Set some helper variables for readability
|
||||
set( compiler_is_clang "$<OR:$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:Clang>>" )
|
||||
set( compiler_is_gnu "$<CXX_COMPILER_ID:GNU>" )
|
||||
set( compiler_is_msvc "$<CXX_COMPILER_ID:MSVC>" )
|
||||
|
||||
# CXX_VISIBILITY_PRESET supported values are: default, hidden, protected, and internal
|
||||
# which is inline with the gcc -fvisibility=
|
||||
# https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html
|
||||
# To match the scons options we need to change the text to match the -fvisibility flag
|
||||
# it is probably worth another PR which changes both to use the flag options
|
||||
if( ${GODOT_SYMBOL_VISIBILITY} STREQUAL "auto" OR ${GODOT_SYMBOL_VISIBILITY} STREQUAL "visible" )
|
||||
set( GODOT_SYMBOL_VISIBILITY "default" )
|
||||
endif ()
|
||||
|
||||
# Default build type is Debug in the SConstruct
|
||||
if("${CMAKE_BUILD_TYPE}" STREQUAL "")
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
endif()
|
||||
|
||||
# Hot reload is enabled by default in Debug-builds
|
||||
if( GODOT_USE_HOT_RELOAD STREQUAL "" AND NOT CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
set(GODOT_USE_HOT_RELOAD ON)
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED BITS)
|
||||
set(BITS 32)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(BITS 64)
|
||||
endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
endif()
|
||||
|
||||
|
||||
set(GODOT_GDEXTENSION_API_FILE "${GODOT_GDEXTENSION_DIR}/extension_api.json")
|
||||
if (NOT "${GODOT_CUSTOM_API_FILE}" STREQUAL "") # User-defined override.
|
||||
set(GODOT_GDEXTENSION_API_FILE "${GODOT_CUSTOM_API_FILE}")
|
||||
endif()
|
||||
|
||||
if ("${GODOT_PRECISION}" STREQUAL "double")
|
||||
add_definitions(-DREAL_T_IS_DOUBLE)
|
||||
endif()
|
||||
|
||||
set( GODOT_COMPILE_FLAGS )
|
||||
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
# using Visual Studio C++
|
||||
set(GODOT_COMPILE_FLAGS "/utf-8") # /GF /MP
|
||||
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /MDd") # /Od /RTC1 /Zi
|
||||
else()
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /MD /O2") # /Oy /GL /Gy
|
||||
endif(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
|
||||
add_definitions(-DNOMINMAX)
|
||||
else() # GCC/Clang
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0 -g")
|
||||
else()
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -O3")
|
||||
endif(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
endif()
|
||||
|
||||
# Disable exception handling. Godot doesn't use exceptions anywhere, and this
|
||||
# saves around 20% of binary size and very significant build time (GH-80513).
|
||||
if (GODOT_DISABLE_EXCEPTIONS)
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -D_HAS_EXCEPTIONS=0")
|
||||
else()
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-exceptions")
|
||||
endif()
|
||||
else()
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /EHsc")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Generate source from the bindings file
|
||||
find_package(Python3 3.4 REQUIRED) # pathlib should be present
|
||||
if(GODOT_GENERATE_TEMPLATE_GET_NODE)
|
||||
set(GENERATE_BINDING_PARAMETERS "True")
|
||||
else()
|
||||
set(GENERATE_BINDING_PARAMETERS "False")
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.print_file_list(\"${GODOT_GDEXTENSION_API_FILE}\", \"${CMAKE_CURRENT_BINARY_DIR}\", headers=True, sources=True)"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GENERATED_FILES_LIST
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
add_custom_command(OUTPUT ${GENERATED_FILES_LIST}
|
||||
COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.generate_bindings(\"${GODOT_GDEXTENSION_API_FILE}\", \"${GENERATE_BINDING_PARAMETERS}\", \"${BITS}\", \"${GODOT_PRECISION}\", \"${CMAKE_CURRENT_BINARY_DIR}\")"
|
||||
VERBATIM
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
MAIN_DEPENDENCY ${GODOT_GDEXTENSION_API_FILE}
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/binding_generator.py
|
||||
COMMENT "Generating bindings"
|
||||
)
|
||||
|
||||
# Get Sources
|
||||
# As this cmake file was added using 'include(godotcpp)' from the root CMakeLists.txt,
|
||||
# the ${CMAKE_CURRENT_SOURCE_DIR} is still the root dir.
|
||||
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS src/*.c**)
|
||||
file(GLOB_RECURSE HEADERS CONFIGURE_DEPENDS include/*.h**)
|
||||
|
||||
# Define our godot-cpp library
|
||||
add_library(${PROJECT_NAME} STATIC
|
||||
${SOURCES}
|
||||
${HEADERS}
|
||||
${GENERATED_FILES_LIST}
|
||||
)
|
||||
add_library(godot::cpp ALIAS ${PROJECT_NAME})
|
||||
|
||||
include(${PROJECT_SOURCE_DIR}/cmake/common_compiler_flags.cmake)
|
||||
|
||||
target_compile_features(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
cxx_std_17
|
||||
)
|
||||
|
||||
if(GODOT_USE_HOT_RELOAD)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC HOT_RELOAD_ENABLED)
|
||||
target_compile_options(${PROJECT_NAME} PUBLIC $<${compiler_is_gnu}:-fno-gnu-unique>)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC
|
||||
$<$<CONFIG:Debug>:
|
||||
DEBUG_ENABLED
|
||||
DEBUG_METHODS_ENABLED
|
||||
>
|
||||
$<${compiler_is_msvc}:
|
||||
TYPED_METHOD_BIND
|
||||
>
|
||||
)
|
||||
|
||||
target_link_options(${PROJECT_NAME} PRIVATE
|
||||
$<$<NOT:${compiler_is_msvc}>:
|
||||
-static-libgcc
|
||||
-static-libstdc++
|
||||
-Wl,-R,'$$ORIGIN'
|
||||
>
|
||||
)
|
||||
|
||||
# Optionally mark headers as SYSTEM
|
||||
set(GODOT_SYSTEM_HEADERS_ATTRIBUTE "")
|
||||
if (GODOT_SYSTEM_HEADERS)
|
||||
set(GODOT_SYSTEM_HEADERS_ATTRIBUTE SYSTEM)
|
||||
endif ()
|
||||
|
||||
target_include_directories(${PROJECT_NAME} ${GODOT_SYSTEM_HEADERS_ATTRIBUTE} PUBLIC
|
||||
include
|
||||
${CMAKE_CURRENT_BINARY_DIR}/gen/include
|
||||
${GODOT_GDEXTENSION_DIR}
|
||||
)
|
||||
|
||||
# Add the compile flags
|
||||
set_property(TARGET ${PROJECT_NAME} APPEND_STRING PROPERTY COMPILE_FLAGS ${GODOT_COMPILE_FLAGS})
|
||||
|
||||
# Create the correct name (godot.os.build_type.system_bits)
|
||||
string(TOLOWER "${CMAKE_SYSTEM_NAME}" SYSTEM_NAME)
|
||||
string(TOLOWER "${CMAKE_BUILD_TYPE}" BUILD_TYPE)
|
||||
|
||||
if(ANDROID)
|
||||
# Added the android abi after system name
|
||||
set(SYSTEM_NAME ${SYSTEM_NAME}.${ANDROID_ABI})
|
||||
|
||||
# Android does not have the bits at the end if you look at the main godot repo build
|
||||
set(OUTPUT_NAME "godot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}")
|
||||
else()
|
||||
set(OUTPUT_NAME "godot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}.${BITS}")
|
||||
endif()
|
||||
|
||||
set_target_properties(${PROJECT_NAME}
|
||||
PROPERTIES
|
||||
CXX_EXTENSIONS OFF
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
CXX_VISIBILITY_PRESET ${GODOT_SYMBOL_VISIBILITY}
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin"
|
||||
OUTPUT_NAME "${OUTPUT_NAME}"
|
||||
)
|
||||
|
||||
endfunction()
|
||||
57
doc/cmake.md
Normal file
57
doc/cmake.md
Normal file
@@ -0,0 +1,57 @@
|
||||
## CMake
|
||||
|
||||
### cmake arguments
|
||||
|
||||
`CMAKE_BUILD_TYPE`: Compilation target (Debug or Release defaults to Debug)
|
||||
|
||||
### godot-cpp cmake arguments
|
||||
- `GODOT_GDEXTENSION_DIR`: Path to the directory containing GDExtension interface header and API JSON file
|
||||
- `GODOT_SYSTEM_HEADERS`: Mark the header files as SYSTEM. This may be useful to suppress warnings in projects including this one.
|
||||
- `GODOT_WARNING_AS_ERROR`: Treat any warnings as errors
|
||||
- `GODOT_USE_HOT_RELOAD`: Build with hot reload support. Defaults to YES for Debug-builds and NO for Release-builds.
|
||||
- `GODOT_CUSTOM_API_FILE`: Path to a custom GDExtension API JSON file (takes precedence over `gdextension_dir`)
|
||||
- `GODOT_PRECISION`: Floating-point precision level ("single", "double")
|
||||
|
||||
### Android cmake arguments
|
||||
- `CMAKE_TOOLCHAIN_FILE`: The path to the android cmake toolchain ($ANDROID_NDK/build/cmake/android.toolchain.cmake)
|
||||
- `ANDROID_NDK`: The path to the android ndk root folder
|
||||
- `ANDROID_TOOLCHAIN_NAME`: The android toolchain (arm-linux-androideabi-4.9 or aarch64-linux-android-4.9 or x86-4.9 or x86_64-4.9)
|
||||
- `ANDROID_PLATFORM`: The android platform version (android-23)
|
||||
|
||||
- More info [here](https://godot.readthedocs.io/en/latest/development/compiling/compiling_for_android.html)
|
||||
|
||||
## Examples
|
||||
```shell
|
||||
Builds a debug version:
|
||||
cmake .
|
||||
cmake --build .
|
||||
```
|
||||
Builds a release version with clang
|
||||
|
||||
```shell
|
||||
CC=/usr/bin/clang CXX=/usr/bin/clang++ cmake -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" .
|
||||
cmake --build .
|
||||
```
|
||||
Builds an android armeabi-v7a debug version:
|
||||
|
||||
``` shell
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake -DANDROID_NDK=$ANDROID_NDK \
|
||||
-DANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.9 -DANDROID_PLATFORM=android-23 -DCMAKE_BUILD_TYPE=Debug .
|
||||
cmake --build .
|
||||
```
|
||||
|
||||
## Protip
|
||||
Generate the buildfiles in a sub directory to not clutter the root directory with build files:
|
||||
|
||||
```shell
|
||||
mkdir build && cd build && cmake -G "Unix Makefiles" .. && cmake --build .
|
||||
```
|
||||
|
||||
Ensure that you avoid exposing godot-cpp symbols - this might lead to hard to debug errors if you ever load multiple
|
||||
plugins using difference godot-cpp versions. Use visibility hidden whenever possible:
|
||||
```cmake
|
||||
set_target_properties(<all-my-plugin-related-targets> PROPERTIES CXX_VISIBILITY_PRESET hidden)
|
||||
```
|
||||
|
||||
## Todo
|
||||
Test build for Windows, Mac and mingw.
|
||||
@@ -2,10 +2,10 @@
|
||||
"header": {
|
||||
"version_major": 4,
|
||||
"version_minor": 2,
|
||||
"version_patch": 0,
|
||||
"version_patch": 2,
|
||||
"version_status": "stable",
|
||||
"version_build": "official",
|
||||
"version_full_name": "Godot Engine v4.2.stable.official"
|
||||
"version_full_name": "Godot Engine v4.2.2.stable.official"
|
||||
},
|
||||
"builtin_class_sizes": [
|
||||
{
|
||||
@@ -82143,6 +82143,24 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "_begin_handle_action",
|
||||
"is_const": false,
|
||||
"is_static": false,
|
||||
"is_vararg": false,
|
||||
"is_virtual": true,
|
||||
"arguments": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "int",
|
||||
"meta": "int32"
|
||||
},
|
||||
{
|
||||
"name": "secondary",
|
||||
"type": "bool"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "_set_handle",
|
||||
"is_const": false,
|
||||
@@ -82700,6 +82718,28 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "_begin_handle_action",
|
||||
"is_const": false,
|
||||
"is_static": false,
|
||||
"is_vararg": false,
|
||||
"is_virtual": true,
|
||||
"arguments": [
|
||||
{
|
||||
"name": "gizmo",
|
||||
"type": "EditorNode3DGizmo"
|
||||
},
|
||||
{
|
||||
"name": "handle_id",
|
||||
"type": "int",
|
||||
"meta": "int32"
|
||||
},
|
||||
{
|
||||
"name": "secondary",
|
||||
"type": "bool"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "_set_handle",
|
||||
"is_const": false,
|
||||
@@ -136403,6 +136443,17 @@
|
||||
"inherits": "Node2D",
|
||||
"api_type": "core",
|
||||
"methods": [
|
||||
{
|
||||
"name": "get_rid",
|
||||
"is_const": true,
|
||||
"is_vararg": false,
|
||||
"is_static": false,
|
||||
"is_virtual": false,
|
||||
"hash": 2944877500,
|
||||
"return_value": {
|
||||
"type": "RID"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "set_enabled",
|
||||
"is_const": false,
|
||||
@@ -136724,6 +136775,17 @@
|
||||
"inherits": "Node3D",
|
||||
"api_type": "core",
|
||||
"methods": [
|
||||
{
|
||||
"name": "get_rid",
|
||||
"is_const": true,
|
||||
"is_vararg": false,
|
||||
"is_static": false,
|
||||
"is_virtual": false,
|
||||
"hash": 2944877500,
|
||||
"return_value": {
|
||||
"type": "RID"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "set_enabled",
|
||||
"is_const": false,
|
||||
@@ -140321,6 +140383,17 @@
|
||||
"inherits": "Node2D",
|
||||
"api_type": "core",
|
||||
"methods": [
|
||||
{
|
||||
"name": "get_rid",
|
||||
"is_const": true,
|
||||
"is_vararg": false,
|
||||
"is_static": false,
|
||||
"is_virtual": false,
|
||||
"hash": 2944877500,
|
||||
"return_value": {
|
||||
"type": "RID"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "set_navigation_polygon",
|
||||
"is_const": false,
|
||||
@@ -140721,6 +140794,17 @@
|
||||
"inherits": "Node3D",
|
||||
"api_type": "core",
|
||||
"methods": [
|
||||
{
|
||||
"name": "get_rid",
|
||||
"is_const": true,
|
||||
"is_vararg": false,
|
||||
"is_static": false,
|
||||
"is_virtual": false,
|
||||
"hash": 2944877500,
|
||||
"return_value": {
|
||||
"type": "RID"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "set_navigation_mesh",
|
||||
"is_const": false,
|
||||
@@ -150997,6 +151081,10 @@
|
||||
{
|
||||
"name": "NOTIFICATION_PREDELETE",
|
||||
"value": 1
|
||||
},
|
||||
{
|
||||
"name": "NOTIFICATION_EXTENSION_RELOADED",
|
||||
"value": 2
|
||||
}
|
||||
],
|
||||
"enums": [
|
||||
@@ -205939,6 +206027,23 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "debug_canvas_item_get_rect",
|
||||
"is_const": false,
|
||||
"is_vararg": false,
|
||||
"is_static": false,
|
||||
"is_virtual": false,
|
||||
"hash": 624227424,
|
||||
"return_value": {
|
||||
"type": "Rect2"
|
||||
},
|
||||
"arguments": [
|
||||
{
|
||||
"name": "item",
|
||||
"type": "RID"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "canvas_light_create",
|
||||
"is_const": false,
|
||||
@@ -207596,7 +207701,7 @@
|
||||
"is_refcounted": true,
|
||||
"is_instantiable": true,
|
||||
"inherits": "ResourceImporter",
|
||||
"api_type": "core"
|
||||
"api_type": "editor"
|
||||
},
|
||||
{
|
||||
"name": "ResourceImporterOBJ",
|
||||
@@ -207610,7 +207715,7 @@
|
||||
"is_refcounted": true,
|
||||
"is_instantiable": true,
|
||||
"inherits": "ResourceImporter",
|
||||
"api_type": "core",
|
||||
"api_type": "editor",
|
||||
"methods": [
|
||||
{
|
||||
"name": "load_from_buffer",
|
||||
|
||||
@@ -47,11 +47,11 @@ public:
|
||||
static void remove_plugin_class(const StringName &p_class_name);
|
||||
static void deinitialize(GDExtensionInitializationLevel p_level);
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
static void add_by_type() {
|
||||
add_plugin_class(T::get_class_static());
|
||||
}
|
||||
template <class T>
|
||||
template <typename T>
|
||||
static void remove_by_type() {
|
||||
remove_plugin_class(T::get_class_static());
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace godot {
|
||||
|
||||
class RefCounted;
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
class Ref {
|
||||
T *reference = nullptr;
|
||||
|
||||
@@ -108,7 +108,7 @@ public:
|
||||
ref(p_from);
|
||||
}
|
||||
|
||||
template <class T_Other>
|
||||
template <typename T_Other>
|
||||
void operator=(const Ref<T_Other> &p_from) {
|
||||
RefCounted *refb = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_from.ptr()));
|
||||
if (!refb) {
|
||||
@@ -144,7 +144,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
template <class T_Other>
|
||||
template <typename T_Other>
|
||||
void reference_ptr(T_Other *p_ptr) {
|
||||
if (reference == p_ptr) {
|
||||
return;
|
||||
@@ -161,7 +161,7 @@ public:
|
||||
ref(p_from);
|
||||
}
|
||||
|
||||
template <class T_Other>
|
||||
template <typename T_Other>
|
||||
Ref(const Ref<T_Other> &p_from) {
|
||||
RefCounted *refb = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_from.ptr()));
|
||||
if (!refb) {
|
||||
@@ -226,11 +226,13 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
struct PtrToArg<Ref<T>> {
|
||||
_FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
|
||||
GDExtensionRefPtr ref = (GDExtensionRefPtr)p_ptr;
|
||||
ERR_FAIL_NULL_V(p_ptr, Ref<T>());
|
||||
if (unlikely(!p_ptr)) {
|
||||
return Ref<T>();
|
||||
}
|
||||
return Ref<T>(reinterpret_cast<T *>(godot::internal::get_object_instance_binding(godot::internal::gdextension_interface_ref_get_object(ref))));
|
||||
}
|
||||
|
||||
@@ -248,18 +250,20 @@ struct PtrToArg<Ref<T>> {
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
struct PtrToArg<const Ref<T> &> {
|
||||
typedef Ref<T> EncodeT;
|
||||
|
||||
_FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
|
||||
GDExtensionRefPtr ref = const_cast<GDExtensionRefPtr>(p_ptr);
|
||||
ERR_FAIL_NULL_V(p_ptr, Ref<T>());
|
||||
if (unlikely(!p_ptr)) {
|
||||
return Ref<T>();
|
||||
}
|
||||
return Ref<T>(reinterpret_cast<T *>(godot::internal::get_object_instance_binding(godot::internal::gdextension_interface_ref_get_object(ref))));
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
struct GetTypeInfo<Ref<T>, typename EnableIf<TypeInherits<RefCounted, T>::value>::type> {
|
||||
static const GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
|
||||
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
|
||||
@@ -269,7 +273,7 @@ struct GetTypeInfo<Ref<T>, typename EnableIf<TypeInherits<RefCounted, T>::value>
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
struct GetTypeInfo<const Ref<T> &, typename EnableIf<TypeInherits<RefCounted, T>::value>::type> {
|
||||
static const GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
|
||||
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
|
||||
|
||||
@@ -48,6 +48,7 @@ typedef void GodotObject;
|
||||
// Base for all engine classes, to contain the pointer to the engine instance.
|
||||
class Wrapped {
|
||||
friend class GDExtensionBinding;
|
||||
friend class ClassDB;
|
||||
friend void postinitialize_handler(Wrapped *);
|
||||
|
||||
protected:
|
||||
@@ -87,14 +88,15 @@ protected:
|
||||
::godot::List<::godot::PropertyInfo> plist_owned;
|
||||
|
||||
void _postinitialize();
|
||||
virtual void _notificationv(int32_t p_what, bool p_reversed = false) {}
|
||||
|
||||
Wrapped(const StringName p_godot_class);
|
||||
Wrapped(GodotObject *p_godot_object);
|
||||
virtual ~Wrapped() {}
|
||||
|
||||
public:
|
||||
static StringName &get_class_static() {
|
||||
static StringName string_name = StringName("Wrapped");
|
||||
static const StringName &get_class_static() {
|
||||
static const StringName string_name = StringName("Wrapped");
|
||||
return string_name;
|
||||
}
|
||||
|
||||
@@ -116,7 +118,7 @@ void add_engine_class_registration_callback(EngineClassRegistrationCallback p_ca
|
||||
void register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks);
|
||||
void register_engine_classes();
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
struct EngineClassRegistration {
|
||||
EngineClassRegistration() {
|
||||
add_engine_class_registration_callback(&EngineClassRegistration<T>::callback);
|
||||
@@ -131,23 +133,12 @@ struct EngineClassRegistration {
|
||||
|
||||
} // namespace godot
|
||||
|
||||
#ifdef HOT_RELOAD_ENABLED
|
||||
#define _GDCLASS_RECREATE(m_class, m_inherits) \
|
||||
m_class *new_instance = (m_class *)memalloc(sizeof(m_class)); \
|
||||
Wrapped::RecreateInstance recreate_data = { new_instance, obj, Wrapped::recreate_instance }; \
|
||||
Wrapped::recreate_instance = &recreate_data; \
|
||||
memnew_placement(new_instance, m_class); \
|
||||
return new_instance;
|
||||
#else
|
||||
#define _GDCLASS_RECREATE(m_class, m_inherits) return nullptr;
|
||||
#endif
|
||||
|
||||
// Use this on top of your own classes.
|
||||
// Note: the trail of `***` is to keep sane diffs in PRs, because clang-format otherwise moves every `\` which makes
|
||||
// every line of the macro different
|
||||
#define GDCLASS(m_class, m_inherits) /***********************************************************************************************************************************************/ \
|
||||
private: \
|
||||
void operator=(const m_class &p_rval) {} \
|
||||
void operator=(const m_class & /*p_rval*/) {} \
|
||||
friend class ::godot::ClassDB; \
|
||||
\
|
||||
protected: \
|
||||
@@ -196,13 +187,14 @@ protected:
|
||||
return (::godot::String(::godot::Wrapped::*)() const) & m_class::_to_string; \
|
||||
} \
|
||||
\
|
||||
template <class T, class B> \
|
||||
template <typename T, typename B> \
|
||||
static void register_virtuals() { \
|
||||
m_inherits::register_virtuals<T, B>(); \
|
||||
} \
|
||||
\
|
||||
public: \
|
||||
typedef m_class self_type; \
|
||||
typedef m_inherits parent_type; \
|
||||
\
|
||||
static void initialize_class() { \
|
||||
static bool initialized = false; \
|
||||
@@ -217,52 +209,52 @@ public:
|
||||
initialized = true; \
|
||||
} \
|
||||
\
|
||||
static ::godot::StringName &get_class_static() { \
|
||||
static ::godot::StringName string_name = ::godot::StringName(#m_class); \
|
||||
static const ::godot::StringName &get_class_static() { \
|
||||
static const ::godot::StringName string_name = ::godot::StringName(#m_class); \
|
||||
return string_name; \
|
||||
} \
|
||||
\
|
||||
static ::godot::StringName &get_parent_class_static() { \
|
||||
static const ::godot::StringName &get_parent_class_static() { \
|
||||
return m_inherits::get_class_static(); \
|
||||
} \
|
||||
\
|
||||
static GDExtensionObjectPtr create(void *data) { \
|
||||
m_class *new_object = memnew(m_class); \
|
||||
return new_object->_owner; \
|
||||
} \
|
||||
\
|
||||
static GDExtensionClassInstancePtr recreate(void *data, GDExtensionObjectPtr obj) { \
|
||||
_GDCLASS_RECREATE(m_class, m_inherits); \
|
||||
} \
|
||||
\
|
||||
static void notification_bind(GDExtensionClassInstancePtr p_instance, int32_t p_what, GDExtensionBool p_reversed) { \
|
||||
if (p_instance && m_class::_get_notification()) { \
|
||||
if (!p_reversed) { \
|
||||
m_inherits::notification_bind(p_instance, p_what, p_reversed); \
|
||||
} \
|
||||
if (m_class::_get_notification() != m_inherits::_get_notification()) { \
|
||||
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
|
||||
return cls->_notification(p_what); \
|
||||
cls->_notification(p_what); \
|
||||
} \
|
||||
if (p_reversed) { \
|
||||
m_inherits::notification_bind(p_instance, p_what, p_reversed); \
|
||||
} \
|
||||
m_inherits::notification_bind(p_instance, p_what, p_reversed); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
static GDExtensionBool set_bind(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionConstVariantPtr p_value) { \
|
||||
if (p_instance && m_class::_get_set()) { \
|
||||
if (p_instance) { \
|
||||
if (m_inherits::set_bind(p_instance, p_name, p_value)) { \
|
||||
return true; \
|
||||
} \
|
||||
if (m_class::_get_set() != m_inherits::_get_set()) { \
|
||||
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
|
||||
return cls->_set(*reinterpret_cast<const ::godot::StringName *>(p_name), *reinterpret_cast<const ::godot::Variant *>(p_value)); \
|
||||
} \
|
||||
return m_inherits::set_bind(p_instance, p_name, p_value); \
|
||||
} \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
static GDExtensionBool get_bind(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret) { \
|
||||
if (p_instance && m_class::_get_get()) { \
|
||||
if (p_instance) { \
|
||||
if (m_inherits::get_bind(p_instance, p_name, r_ret)) { \
|
||||
return true; \
|
||||
} \
|
||||
if (m_class::_get_get() != m_inherits::_get_get()) { \
|
||||
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
|
||||
return cls->_get(*reinterpret_cast<const ::godot::StringName *>(p_name), *reinterpret_cast<::godot::Variant *>(r_ret)); \
|
||||
} \
|
||||
return m_inherits::get_bind(p_instance, p_name, r_ret); \
|
||||
} \
|
||||
return false; \
|
||||
} \
|
||||
@@ -288,7 +280,6 @@ public:
|
||||
if (p_instance) { \
|
||||
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
|
||||
cls->plist_owned.clear(); \
|
||||
/* TODO `GDExtensionClassFreePropertyList` is ill-defined, we need a non-const pointer to free this. */ \
|
||||
::godot::internal::free_c_property_list(const_cast<GDExtensionPropertyInfo *>(p_list)); \
|
||||
} \
|
||||
} \
|
||||
@@ -342,7 +333,7 @@ public:
|
||||
} \
|
||||
} \
|
||||
\
|
||||
static void free(void *data, GDExtensionClassInstancePtr ptr) { \
|
||||
static void free(void * /*data*/, GDExtensionClassInstancePtr ptr) { \
|
||||
if (ptr) { \
|
||||
m_class *cls = reinterpret_cast<m_class *>(ptr); \
|
||||
cls->~m_class(); \
|
||||
@@ -350,14 +341,14 @@ public:
|
||||
} \
|
||||
} \
|
||||
\
|
||||
static void *_gde_binding_create_callback(void *p_token, void *p_instance) { \
|
||||
static void *_gde_binding_create_callback(void * /*p_token*/, void * /*p_instance*/) { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
static void _gde_binding_free_callback(void *p_token, void *p_instance, void *p_binding) { \
|
||||
static void _gde_binding_free_callback(void * /*p_token*/, void * /*p_instance*/, void * /*p_binding*/) { \
|
||||
} \
|
||||
\
|
||||
static GDExtensionBool _gde_binding_reference_callback(void *p_token, void *p_instance, GDExtensionBool p_reference) { \
|
||||
static GDExtensionBool _gde_binding_reference_callback(void * /*p_token*/, void * /*p_instance*/, GDExtensionBool /*p_reference*/) { \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
@@ -367,6 +358,11 @@ public:
|
||||
_gde_binding_reference_callback, \
|
||||
}; \
|
||||
\
|
||||
protected: \
|
||||
virtual void _notificationv(int32_t p_what, bool p_reversed = false) override { \
|
||||
m_class::notification_bind(this, p_what, p_reversed); \
|
||||
} \
|
||||
\
|
||||
private:
|
||||
|
||||
// Don't use this for your classes, use GDCLASS() instead.
|
||||
@@ -374,6 +370,7 @@ private:
|
||||
private: \
|
||||
inline static ::godot::internal::EngineClassRegistration<m_class> _gde_engine_class_registration_helper; \
|
||||
void operator=(const m_class &p_rval) {} \
|
||||
friend class ::godot::ClassDB; \
|
||||
\
|
||||
protected: \
|
||||
virtual const GDExtensionInstanceBindingCallbacks *_get_bindings_callbacks() const override { \
|
||||
@@ -383,6 +380,8 @@ protected:
|
||||
m_class(const char *p_godot_class) : m_inherits(p_godot_class) {} \
|
||||
m_class(GodotObject *p_godot_object) : m_inherits(p_godot_object) {} \
|
||||
\
|
||||
static void _bind_methods() {} \
|
||||
\
|
||||
static void (*_get_bind_methods())() { \
|
||||
return nullptr; \
|
||||
} \
|
||||
@@ -425,26 +424,19 @@ protected:
|
||||
\
|
||||
public: \
|
||||
typedef m_class self_type; \
|
||||
typedef m_inherits parent_type; \
|
||||
\
|
||||
static void initialize_class() {} \
|
||||
\
|
||||
static ::godot::StringName &get_class_static() { \
|
||||
static ::godot::StringName string_name = ::godot::StringName(#m_alias_for); \
|
||||
static const ::godot::StringName &get_class_static() { \
|
||||
static const ::godot::StringName string_name = ::godot::StringName(#m_alias_for); \
|
||||
return string_name; \
|
||||
} \
|
||||
\
|
||||
static ::godot::StringName &get_parent_class_static() { \
|
||||
static const ::godot::StringName &get_parent_class_static() { \
|
||||
return m_inherits::get_class_static(); \
|
||||
} \
|
||||
\
|
||||
static GDExtensionObjectPtr create(void *data) { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
static GDExtensionClassInstancePtr recreate(void *data, GDExtensionObjectPtr obj) { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
static void free(void *data, GDExtensionClassInstancePtr ptr) { \
|
||||
} \
|
||||
\
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace godot {
|
||||
}; \
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
struct VariantCaster {
|
||||
static _FORCE_INLINE_ T cast(const Variant &p_variant) {
|
||||
using TStripped = std::remove_pointer_t<T>;
|
||||
@@ -95,7 +95,7 @@ struct VariantCaster {
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
struct VariantCaster<T &> {
|
||||
static _FORCE_INLINE_ T cast(const Variant &p_variant) {
|
||||
using TStripped = std::remove_pointer_t<T>;
|
||||
@@ -107,7 +107,7 @@ struct VariantCaster<T &> {
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
struct VariantCaster<const T &> {
|
||||
static _FORCE_INLINE_ T cast(const Variant &p_variant) {
|
||||
using TStripped = std::remove_pointer_t<T>;
|
||||
@@ -144,7 +144,7 @@ struct VariantObjectClassChecker<const Ref<T> &> {
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
struct VariantCasterAndValidate {
|
||||
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDExtensionCallError &r_error) {
|
||||
GDExtensionVariantType argtype = GDExtensionVariantType(GetTypeInfo<T>::VARIANT_TYPE);
|
||||
@@ -159,7 +159,7 @@ struct VariantCasterAndValidate {
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
struct VariantCasterAndValidate<T &> {
|
||||
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDExtensionCallError &r_error) {
|
||||
GDExtensionVariantType argtype = GDExtensionVariantType(GetTypeInfo<T>::VARIANT_TYPE);
|
||||
@@ -174,7 +174,7 @@ struct VariantCasterAndValidate<T &> {
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
struct VariantCasterAndValidate<const T &> {
|
||||
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDExtensionCallError &r_error) {
|
||||
GDExtensionVariantType argtype = GDExtensionVariantType(GetTypeInfo<T>::VARIANT_TYPE);
|
||||
@@ -189,47 +189,47 @@ struct VariantCasterAndValidate<const T &> {
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class... P, size_t... Is>
|
||||
template <typename T, typename... P, size_t... Is>
|
||||
void call_with_ptr_args_helper(T *p_instance, void (T::*p_method)(P...), const GDExtensionConstTypePtr *p_args, IndexSequence<Is...>) {
|
||||
(p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...);
|
||||
}
|
||||
|
||||
template <class T, class... P, size_t... Is>
|
||||
template <typename T, typename... P, size_t... Is>
|
||||
void call_with_ptr_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const GDExtensionConstTypePtr *p_args, IndexSequence<Is...>) {
|
||||
(p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...);
|
||||
}
|
||||
|
||||
template <class T, class R, class... P, size_t... Is>
|
||||
template <typename T, typename R, typename... P, size_t... Is>
|
||||
void call_with_ptr_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const GDExtensionConstTypePtr *p_args, void *r_ret, IndexSequence<Is...>) {
|
||||
PtrToArg<R>::encode((p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...), r_ret);
|
||||
}
|
||||
|
||||
template <class T, class R, class... P, size_t... Is>
|
||||
template <typename T, typename R, typename... P, size_t... Is>
|
||||
void call_with_ptr_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const GDExtensionConstTypePtr *p_args, void *r_ret, IndexSequence<Is...>) {
|
||||
PtrToArg<R>::encode((p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...), r_ret);
|
||||
}
|
||||
|
||||
template <class T, class... P>
|
||||
template <typename T, typename... P>
|
||||
void call_with_ptr_args(T *p_instance, void (T::*p_method)(P...), const GDExtensionConstTypePtr *p_args, void * /*ret*/) {
|
||||
call_with_ptr_args_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
template <class T, class... P>
|
||||
template <typename T, typename... P>
|
||||
void call_with_ptr_args(T *p_instance, void (T::*p_method)(P...) const, const GDExtensionConstTypePtr *p_args, void * /*ret*/) {
|
||||
call_with_ptr_argsc_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
template <class T, class R, class... P>
|
||||
template <typename T, typename R, typename... P>
|
||||
void call_with_ptr_args(T *p_instance, R (T::*p_method)(P...), const GDExtensionConstTypePtr *p_args, void *r_ret) {
|
||||
call_with_ptr_args_ret_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
template <class T, class R, class... P>
|
||||
template <typename T, typename R, typename... P>
|
||||
void call_with_ptr_args(T *p_instance, R (T::*p_method)(P...) const, const GDExtensionConstTypePtr *p_args, void *r_ret) {
|
||||
call_with_ptr_args_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
template <class T, class... P, size_t... Is>
|
||||
template <typename T, typename... P, size_t... Is>
|
||||
void call_with_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, GDExtensionCallError &r_error, IndexSequence<Is...>) {
|
||||
r_error.error = GDEXTENSION_CALL_OK;
|
||||
|
||||
@@ -241,7 +241,7 @@ void call_with_variant_args_helper(T *p_instance, void (T::*p_method)(P...), con
|
||||
(void)(p_args); // Avoid warning.
|
||||
}
|
||||
|
||||
template <class T, class... P, size_t... Is>
|
||||
template <typename T, typename... P, size_t... Is>
|
||||
void call_with_variant_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, GDExtensionCallError &r_error, IndexSequence<Is...>) {
|
||||
r_error.error = GDEXTENSION_CALL_OK;
|
||||
|
||||
@@ -253,7 +253,7 @@ void call_with_variant_argsc_helper(T *p_instance, void (T::*p_method)(P...) con
|
||||
(void)(p_args); // Avoid warning.
|
||||
}
|
||||
|
||||
template <class T, class R, class... P, size_t... Is>
|
||||
template <typename T, typename R, typename... P, size_t... Is>
|
||||
void call_with_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, Variant &r_ret, GDExtensionCallError &r_error, IndexSequence<Is...>) {
|
||||
r_error.error = GDEXTENSION_CALL_OK;
|
||||
|
||||
@@ -264,7 +264,7 @@ void call_with_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), co
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T, class R, class... P, size_t... Is>
|
||||
template <typename T, typename R, typename... P, size_t... Is>
|
||||
void call_with_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, Variant &r_ret, GDExtensionCallError &r_error, IndexSequence<Is...>) {
|
||||
r_error.error = GDEXTENSION_CALL_OK;
|
||||
|
||||
@@ -276,66 +276,66 @@ void call_with_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) co
|
||||
(void)p_args;
|
||||
}
|
||||
|
||||
template <class T, class... P>
|
||||
template <typename T, typename... P>
|
||||
void call_with_variant_args(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, int p_argcount, GDExtensionCallError &r_error) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if ((size_t)p_argcount > sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
r_error.expected = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((size_t)p_argcount < sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
r_error.expected = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
call_with_variant_args_helper<T, P...>(p_instance, p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
template <class T, class R, class... P>
|
||||
template <typename T, typename R, typename... P>
|
||||
void call_with_variant_args_ret(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if ((size_t)p_argcount > sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
r_error.expected = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((size_t)p_argcount < sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
r_error.expected = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
call_with_variant_args_ret_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
template <class T, class R, class... P>
|
||||
template <typename T, typename R, typename... P>
|
||||
void call_with_variant_args_retc(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if ((size_t)p_argcount > sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
r_error.expected = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((size_t)p_argcount < sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
r_error.expected = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
call_with_variant_args_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
template <class T, class... P>
|
||||
template <typename T, typename... P>
|
||||
void call_with_variant_args_dv(T *p_instance, void (T::*p_method)(P...), const GDExtensionConstVariantPtr *p_args, int p_argcount, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if ((size_t)p_argcount > sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
r_error.expected = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -346,7 +346,7 @@ void call_with_variant_args_dv(T *p_instance, void (T::*p_method)(P...), const G
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (missing > dvs) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
r_error.expected = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -365,12 +365,12 @@ void call_with_variant_args_dv(T *p_instance, void (T::*p_method)(P...), const G
|
||||
call_with_variant_args_helper(p_instance, p_method, argsp.data(), r_error, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
template <class T, class... P>
|
||||
template <typename T, typename... P>
|
||||
void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const, const GDExtensionConstVariantPtr *p_args, int p_argcount, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if ((size_t)p_argcount > sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
r_error.expected = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -381,7 +381,7 @@ void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const,
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (missing > dvs) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
r_error.expected = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -400,12 +400,12 @@ void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const,
|
||||
call_with_variant_argsc_helper(p_instance, p_method, argsp.data(), r_error, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
template <class T, class R, class... P>
|
||||
template <typename T, typename R, typename... P>
|
||||
void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), const GDExtensionConstVariantPtr *p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if ((size_t)p_argcount > sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
r_error.expected = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -416,7 +416,7 @@ void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), const
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (missing > dvs) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
r_error.expected = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -435,12 +435,12 @@ void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), const
|
||||
call_with_variant_args_ret_helper(p_instance, p_method, argsp.data(), r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
template <class T, class R, class... P>
|
||||
template <typename T, typename R, typename... P>
|
||||
void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const, const GDExtensionConstVariantPtr *p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if ((size_t)p_argcount > sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
r_error.expected = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -451,7 +451,7 @@ void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const,
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (missing > dvs) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
r_error.expected = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -477,7 +477,7 @@ void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const,
|
||||
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
|
||||
#endif
|
||||
|
||||
template <class Q>
|
||||
template <typename Q>
|
||||
void call_get_argument_type_helper(int p_arg, int &index, GDExtensionVariantType &type) {
|
||||
if (p_arg == index) {
|
||||
type = GDExtensionVariantType(GetTypeInfo<Q>::VARIANT_TYPE);
|
||||
@@ -485,7 +485,7 @@ void call_get_argument_type_helper(int p_arg, int &index, GDExtensionVariantType
|
||||
index++;
|
||||
}
|
||||
|
||||
template <class... P>
|
||||
template <typename... P>
|
||||
GDExtensionVariantType call_get_argument_type(int p_arg) {
|
||||
GDExtensionVariantType type = GDEXTENSION_VARIANT_TYPE_NIL;
|
||||
int index = 0;
|
||||
@@ -497,7 +497,7 @@ GDExtensionVariantType call_get_argument_type(int p_arg) {
|
||||
return type;
|
||||
}
|
||||
|
||||
template <class Q>
|
||||
template <typename Q>
|
||||
void call_get_argument_type_info_helper(int p_arg, int &index, PropertyInfo &info) {
|
||||
if (p_arg == index) {
|
||||
info = GetTypeInfo<Q>::get_class_info();
|
||||
@@ -505,7 +505,7 @@ void call_get_argument_type_info_helper(int p_arg, int &index, PropertyInfo &inf
|
||||
index++;
|
||||
}
|
||||
|
||||
template <class... P>
|
||||
template <typename... P>
|
||||
void call_get_argument_type_info(int p_arg, PropertyInfo &info) {
|
||||
int index = 0;
|
||||
// I think rocket science is simpler than modern C++.
|
||||
@@ -515,7 +515,7 @@ void call_get_argument_type_info(int p_arg, PropertyInfo &info) {
|
||||
(void)index; // Suppress GCC warning.
|
||||
}
|
||||
|
||||
template <class Q>
|
||||
template <typename Q>
|
||||
void call_get_argument_metadata_helper(int p_arg, int &index, GDExtensionClassMethodArgumentMetadata &md) {
|
||||
if (p_arg == index) {
|
||||
md = GetTypeInfo<Q>::METADATA;
|
||||
@@ -523,7 +523,7 @@ void call_get_argument_metadata_helper(int p_arg, int &index, GDExtensionClassMe
|
||||
index++;
|
||||
}
|
||||
|
||||
template <class... P>
|
||||
template <typename... P>
|
||||
GDExtensionClassMethodArgumentMetadata call_get_argument_metadata(int p_arg) {
|
||||
GDExtensionClassMethodArgumentMetadata md = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
|
||||
|
||||
@@ -536,7 +536,7 @@ GDExtensionClassMethodArgumentMetadata call_get_argument_metadata(int p_arg) {
|
||||
return md;
|
||||
}
|
||||
|
||||
template <class... P, size_t... Is>
|
||||
template <typename... P, size_t... Is>
|
||||
void call_with_variant_args_static(void (*p_method)(P...), const Variant **p_args, GDExtensionCallError &r_error, IndexSequence<Is...>) {
|
||||
r_error.error = GDEXTENSION_CALL_OK;
|
||||
|
||||
@@ -547,12 +547,12 @@ void call_with_variant_args_static(void (*p_method)(P...), const Variant **p_arg
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class... P>
|
||||
template <typename... P>
|
||||
void call_with_variant_args_static_dv(void (*p_method)(P...), const GDExtensionConstVariantPtr *p_args, int p_argcount, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if ((size_t)p_argcount > sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
|
||||
r_error.argument = sizeof...(P);
|
||||
r_error.expected = sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -563,7 +563,7 @@ void call_with_variant_args_static_dv(void (*p_method)(P...), const GDExtensionC
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (missing > dvs) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
|
||||
r_error.argument = sizeof...(P);
|
||||
r_error.expected = sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -582,53 +582,53 @@ void call_with_variant_args_static_dv(void (*p_method)(P...), const GDExtensionC
|
||||
call_with_variant_args_static(p_method, argsp.data(), r_error, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
template <class... P, size_t... Is>
|
||||
template <typename... P, size_t... Is>
|
||||
void call_with_ptr_args_static_method_helper(void (*p_method)(P...), const GDExtensionConstTypePtr *p_args, IndexSequence<Is...>) {
|
||||
p_method(PtrToArg<P>::convert(p_args[Is])...);
|
||||
}
|
||||
|
||||
template <class... P>
|
||||
template <typename... P>
|
||||
void call_with_ptr_args_static_method(void (*p_method)(P...), const GDExtensionConstTypePtr *p_args) {
|
||||
call_with_ptr_args_static_method_helper<P...>(p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
template <class R, class... P>
|
||||
template <typename R, typename... P>
|
||||
void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if ((size_t)p_argcount > sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
r_error.expected = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((size_t)p_argcount < sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
r_error.expected = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
call_with_variant_args_static_ret<R, P...>(p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
template <class... P>
|
||||
template <typename... P>
|
||||
void call_with_variant_args_static_ret(void (*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if ((size_t)p_argcount > sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
r_error.expected = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((size_t)p_argcount < sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
r_error.expected = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
call_with_variant_args_static<P...>(p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
template <class R, class... P, size_t... Is>
|
||||
template <typename R, typename... P, size_t... Is>
|
||||
void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_args, Variant &r_ret, GDExtensionCallError &r_error, IndexSequence<Is...>) {
|
||||
r_error.error = GDEXTENSION_CALL_OK;
|
||||
|
||||
@@ -639,12 +639,12 @@ void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_ar
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class R, class... P>
|
||||
template <typename R, typename... P>
|
||||
void call_with_variant_args_static_ret_dv(R (*p_method)(P...), const GDExtensionConstVariantPtr *p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if ((size_t)p_argcount > sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
|
||||
r_error.argument = sizeof...(P);
|
||||
r_error.expected = sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -655,7 +655,7 @@ void call_with_variant_args_static_ret_dv(R (*p_method)(P...), const GDExtension
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (missing > dvs) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
|
||||
r_error.argument = sizeof...(P);
|
||||
r_error.expected = sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -674,12 +674,12 @@ void call_with_variant_args_static_ret_dv(R (*p_method)(P...), const GDExtension
|
||||
call_with_variant_args_static_ret(p_method, argsp.data(), r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
template <class R, class... P, size_t... Is>
|
||||
template <typename R, typename... P, size_t... Is>
|
||||
void call_with_ptr_args_static_method_ret_helper(R (*p_method)(P...), const GDExtensionConstTypePtr *p_args, void *r_ret, IndexSequence<Is...>) {
|
||||
PtrToArg<R>::encode(p_method(PtrToArg<P>::convert(p_args[Is])...), r_ret);
|
||||
}
|
||||
|
||||
template <class R, class... P>
|
||||
template <typename R, typename... P>
|
||||
void call_with_ptr_args_static_method_ret(R (*p_method)(P...), const GDExtensionConstTypePtr *p_args, void *r_ret) {
|
||||
call_with_ptr_args_static_method_ret_helper<R, P...>(p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#define GODOT_BUILTIN_PTRCALL_HPP
|
||||
|
||||
#include <gdextension_interface.h>
|
||||
#include <godot_cpp/core/object.hpp>
|
||||
|
||||
#include <array>
|
||||
|
||||
@@ -39,13 +40,24 @@ namespace godot {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <class... Args>
|
||||
template <typename O, typename... Args>
|
||||
O *_call_builtin_method_ptr_ret_obj(const GDExtensionPtrBuiltInMethod method, GDExtensionTypePtr base, const Args &...args) {
|
||||
GodotObject *ret = nullptr;
|
||||
std::array<GDExtensionConstTypePtr, sizeof...(Args)> call_args = { { (GDExtensionConstTypePtr)args... } };
|
||||
method(base, call_args.data(), &ret, sizeof...(Args));
|
||||
if (ret == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<O *>(internal::get_object_instance_binding(ret));
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void _call_builtin_constructor(const GDExtensionPtrConstructor constructor, GDExtensionTypePtr base, Args... args) {
|
||||
std::array<GDExtensionConstTypePtr, sizeof...(Args)> call_args = { { (GDExtensionConstTypePtr)args... } };
|
||||
constructor(base, call_args.data());
|
||||
}
|
||||
|
||||
template <class T, class... Args>
|
||||
template <typename T, typename... Args>
|
||||
T _call_builtin_method_ptr_ret(const GDExtensionPtrBuiltInMethod method, GDExtensionTypePtr base, Args... args) {
|
||||
T ret;
|
||||
std::array<GDExtensionConstTypePtr, sizeof...(Args)> call_args = { { (GDExtensionConstTypePtr)args... } };
|
||||
@@ -53,20 +65,20 @@ T _call_builtin_method_ptr_ret(const GDExtensionPtrBuiltInMethod method, GDExten
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
template <typename... Args>
|
||||
void _call_builtin_method_ptr_no_ret(const GDExtensionPtrBuiltInMethod method, GDExtensionTypePtr base, Args... args) {
|
||||
std::array<GDExtensionConstTypePtr, sizeof...(Args)> call_args = { { (GDExtensionConstTypePtr)args... } };
|
||||
method(base, call_args.data(), nullptr, sizeof...(Args));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
T _call_builtin_operator_ptr(const GDExtensionPtrOperatorEvaluator op, GDExtensionConstTypePtr left, GDExtensionConstTypePtr right) {
|
||||
T ret;
|
||||
op(left, right, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
T _call_builtin_ptr_getter(const GDExtensionPtrGetter getter, GDExtensionConstTypePtr base) {
|
||||
T ret;
|
||||
getter(base, &ret);
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <godot_cpp/variant/callable_method_pointer.hpp>
|
||||
|
||||
#include <list>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
@@ -104,33 +105,77 @@ private:
|
||||
static std::unordered_map<StringName, const GDExtensionInstanceBindingCallbacks *> instance_binding_callbacks;
|
||||
// Used to remember the custom class registration order.
|
||||
static std::vector<StringName> class_register_order;
|
||||
static std::unordered_map<StringName, Object *> engine_singletons;
|
||||
static std::mutex engine_singletons_mutex;
|
||||
|
||||
static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const void **p_defs, int p_defcount);
|
||||
static void initialize_class(const ClassInfo &cl);
|
||||
static void bind_method_godot(const StringName &p_class_name, MethodBind *p_method);
|
||||
|
||||
template <class T, bool is_abstract>
|
||||
template <typename T, bool is_abstract>
|
||||
static void _register_class(bool p_virtual = false, bool p_exposed = true);
|
||||
|
||||
template <typename T>
|
||||
static GDExtensionObjectPtr _create_instance_func(void *data) {
|
||||
if constexpr (!std::is_abstract_v<T>) {
|
||||
T *new_object = memnew(T);
|
||||
return new_object->_owner;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static GDExtensionClassInstancePtr _recreate_instance_func(void *data, GDExtensionObjectPtr obj) {
|
||||
if constexpr (!std::is_abstract_v<T>) {
|
||||
#ifdef HOT_RELOAD_ENABLED
|
||||
T *new_instance = (T *)memalloc(sizeof(T));
|
||||
Wrapped::RecreateInstance recreate_data = { new_instance, obj, Wrapped::recreate_instance };
|
||||
Wrapped::recreate_instance = &recreate_data;
|
||||
memnew_placement(new_instance, T);
|
||||
return new_instance;
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
template <class T>
|
||||
template <typename T>
|
||||
static void register_class(bool p_virtual = false);
|
||||
template <class T>
|
||||
template <typename T>
|
||||
static void register_abstract_class();
|
||||
template <class T>
|
||||
template <typename T>
|
||||
static void register_internal_class();
|
||||
|
||||
_FORCE_INLINE_ static void _register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks) {
|
||||
instance_binding_callbacks[p_name] = p_callbacks;
|
||||
}
|
||||
|
||||
template <class N, class M, typename... VarArgs>
|
||||
static void _register_engine_singleton(const StringName &p_class_name, Object *p_singleton) {
|
||||
std::lock_guard<std::mutex> lock(engine_singletons_mutex);
|
||||
std::unordered_map<StringName, Object *>::const_iterator i = engine_singletons.find(p_class_name);
|
||||
if (i != engine_singletons.end()) {
|
||||
ERR_FAIL_COND((*i).second != p_singleton);
|
||||
return;
|
||||
}
|
||||
engine_singletons[p_class_name] = p_singleton;
|
||||
}
|
||||
|
||||
static void _unregister_engine_singleton(const StringName &p_class_name) {
|
||||
std::lock_guard<std::mutex> lock(engine_singletons_mutex);
|
||||
engine_singletons.erase(p_class_name);
|
||||
}
|
||||
|
||||
template <typename N, typename M, typename... VarArgs>
|
||||
static MethodBind *bind_method(N p_method_name, M p_method, VarArgs... p_args);
|
||||
|
||||
template <class N, class M, typename... VarArgs>
|
||||
template <typename N, typename M, typename... VarArgs>
|
||||
static MethodBind *bind_static_method(StringName p_class, N p_method_name, M p_method, VarArgs... p_args);
|
||||
|
||||
template <class M>
|
||||
template <typename M>
|
||||
static MethodBind *bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const std::vector<Variant> &p_default_args = std::vector<Variant>{}, bool p_return_nil_is_variant = true);
|
||||
|
||||
static void add_property_group(const StringName &p_class, const String &p_name, const String &p_prefix);
|
||||
@@ -152,25 +197,27 @@ public:
|
||||
};
|
||||
|
||||
#define BIND_CONSTANT(m_constant) \
|
||||
godot::ClassDB::bind_integer_constant(get_class_static(), "", #m_constant, m_constant);
|
||||
::godot::ClassDB::bind_integer_constant(get_class_static(), "", #m_constant, m_constant);
|
||||
|
||||
#define BIND_ENUM_CONSTANT(m_constant) \
|
||||
godot::ClassDB::bind_integer_constant(get_class_static(), godot::_gde_constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant);
|
||||
::godot::ClassDB::bind_integer_constant(get_class_static(), ::godot::_gde_constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant);
|
||||
|
||||
#define BIND_BITFIELD_FLAG(m_constant) \
|
||||
godot::ClassDB::bind_integer_constant(get_class_static(), godot::_gde_constant_get_bitfield_name(m_constant, #m_constant), #m_constant, m_constant, true);
|
||||
::godot::ClassDB::bind_integer_constant(get_class_static(), ::godot::_gde_constant_get_bitfield_name(m_constant, #m_constant), #m_constant, m_constant, true);
|
||||
|
||||
#define BIND_VIRTUAL_METHOD(m_class, m_method) \
|
||||
{ \
|
||||
auto _call##m_method = [](GDExtensionObjectPtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr p_ret) -> void { \
|
||||
call_with_ptr_args(reinterpret_cast<m_class *>(p_instance), &m_class::m_method, p_args, p_ret); \
|
||||
}; \
|
||||
godot::ClassDB::bind_virtual_method(m_class::get_class_static(), #m_method, _call##m_method); \
|
||||
::godot::ClassDB::bind_virtual_method(m_class::get_class_static(), #m_method, _call##m_method); \
|
||||
}
|
||||
|
||||
template <class T, bool is_abstract>
|
||||
template <typename T, bool is_abstract>
|
||||
void ClassDB::_register_class(bool p_virtual, bool p_exposed) {
|
||||
static_assert(TypesAreSame<typename T::self_type, T>::value, "Class not declared properly, please use GDCLASS.");
|
||||
static_assert(!FunctionsAreSame<T::self_type::_bind_methods, T::parent_type::_bind_methods>::value, "Class must declare 'static void _bind_methods'.");
|
||||
static_assert(!std::is_abstract_v<T> || is_abstract, "Class is abstract, please use GDREGISTER_ABSTRACT_CLASS.");
|
||||
instance_binding_callbacks[T::get_class_static()] = &T::_gde_binding_callbacks;
|
||||
|
||||
// Register this class within our plugin
|
||||
@@ -202,9 +249,9 @@ void ClassDB::_register_class(bool p_virtual, bool p_exposed) {
|
||||
T::to_string_bind, // GDExtensionClassToString to_string_func;
|
||||
nullptr, // GDExtensionClassReference reference_func;
|
||||
nullptr, // GDExtensionClassUnreference unreference_func;
|
||||
T::create, // GDExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
|
||||
&_create_instance_func<T>, // GDExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
|
||||
T::free, // GDExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
|
||||
T::recreate, // GDExtensionClassRecreateInstance recreate_instance_func;
|
||||
&_recreate_instance_func<T>, // GDExtensionClassRecreateInstance recreate_instance_func;
|
||||
&ClassDB::get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func;
|
||||
nullptr, // GDExtensionClassGetVirtualCallData get_virtual_call_data_func;
|
||||
nullptr, // GDExtensionClassCallVirtualWithData call_virtual_func;
|
||||
@@ -221,22 +268,22 @@ void ClassDB::_register_class(bool p_virtual, bool p_exposed) {
|
||||
initialize_class(classes[cl.name]);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
void ClassDB::register_class(bool p_virtual) {
|
||||
ClassDB::_register_class<T, false>(p_virtual);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
void ClassDB::register_abstract_class() {
|
||||
ClassDB::_register_class<T, true>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
void ClassDB::register_internal_class() {
|
||||
ClassDB::_register_class<T, false>(false, false);
|
||||
}
|
||||
|
||||
template <class N, class M, typename... VarArgs>
|
||||
template <typename N, typename M, typename... VarArgs>
|
||||
MethodBind *ClassDB::bind_method(N p_method_name, M p_method, VarArgs... p_args) {
|
||||
Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
|
||||
const Variant *argptrs[sizeof...(p_args) + 1];
|
||||
@@ -247,7 +294,7 @@ MethodBind *ClassDB::bind_method(N p_method_name, M p_method, VarArgs... p_args)
|
||||
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const void **)argptrs, sizeof...(p_args));
|
||||
}
|
||||
|
||||
template <class N, class M, typename... VarArgs>
|
||||
template <typename N, typename M, typename... VarArgs>
|
||||
MethodBind *ClassDB::bind_static_method(StringName p_class, N p_method_name, M p_method, VarArgs... p_args) {
|
||||
Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
|
||||
const Variant *argptrs[sizeof...(p_args) + 1];
|
||||
@@ -259,7 +306,7 @@ MethodBind *ClassDB::bind_static_method(StringName p_class, N p_method_name, M p
|
||||
return bind_methodfi(0, bind, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const void **)argptrs, sizeof...(p_args));
|
||||
}
|
||||
|
||||
template <class M>
|
||||
template <typename M>
|
||||
MethodBind *ClassDB::bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method, const MethodInfo &p_info, const std::vector<Variant> &p_default_args, bool p_return_nil_is_variant) {
|
||||
MethodBind *bind = create_vararg_method_bind(p_method, p_info, p_return_nil_is_variant);
|
||||
ERR_FAIL_NULL_V(bind, nullptr);
|
||||
@@ -291,11 +338,13 @@ MethodBind *ClassDB::bind_vararg_method(uint32_t p_flags, StringName p_name, M p
|
||||
return bind;
|
||||
}
|
||||
|
||||
#define GDREGISTER_CLASS(m_class) ClassDB::register_class<m_class>();
|
||||
#define GDREGISTER_VIRTUAL_CLASS(m_class) ClassDB::register_class<m_class>(true);
|
||||
#define GDREGISTER_ABSTRACT_CLASS(m_class) ClassDB::register_abstract_class<m_class>();
|
||||
#define GDREGISTER_INTERNAL_CLASS(m_class) ClassDB::register_internal_class<m_class>();
|
||||
#define GDREGISTER_CLASS(m_class) ::godot::ClassDB::register_class<m_class>();
|
||||
#define GDREGISTER_VIRTUAL_CLASS(m_class) ::godot::ClassDB::register_class<m_class>(true);
|
||||
#define GDREGISTER_ABSTRACT_CLASS(m_class) ::godot::ClassDB::register_abstract_class<m_class>();
|
||||
#define GDREGISTER_INTERNAL_CLASS(m_class) ::godot::ClassDB::register_internal_class<m_class>();
|
||||
|
||||
} // namespace godot
|
||||
|
||||
CLASSDB_SINGLETON_VARIANT_CAST;
|
||||
|
||||
#endif // GODOT_CLASS_DB_HPP
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
namespace godot {
|
||||
|
||||
#if !defined(GDE_EXPORT)
|
||||
#if defined(_WIN32)
|
||||
#define GDE_EXPORT __declspec(dllexport)
|
||||
@@ -108,7 +110,7 @@ typedef float real_t;
|
||||
// Generic swap template.
|
||||
#ifndef SWAP
|
||||
#define SWAP(m_x, m_y) __swap_tmpl((m_x), (m_y))
|
||||
template <class T>
|
||||
template <typename T>
|
||||
inline void __swap_tmpl(T &x, T &y) {
|
||||
T aux = x;
|
||||
x = y;
|
||||
@@ -127,4 +129,10 @@ struct BuildIndexSequence : BuildIndexSequence<N - 1, N - 1, Is...> {};
|
||||
template <size_t... Is>
|
||||
struct BuildIndexSequence<0, Is...> : IndexSequence<Is...> {};
|
||||
|
||||
} //namespace godot
|
||||
|
||||
// To maintain compatibility an alias is defined outside the namespace.
|
||||
// Consider it deprecated.
|
||||
using real_t = godot::real_t;
|
||||
|
||||
#endif // GODOT_DEFS_HPP
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace godot {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <class O, class... Args>
|
||||
template <typename O, typename... Args>
|
||||
O *_call_native_mb_ret_obj(const GDExtensionMethodBindPtr mb, void *instance, const Args &...args) {
|
||||
GodotObject *ret = nullptr;
|
||||
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
|
||||
@@ -54,7 +54,7 @@ O *_call_native_mb_ret_obj(const GDExtensionMethodBindPtr mb, void *instance, co
|
||||
return reinterpret_cast<O *>(internal::get_object_instance_binding(ret));
|
||||
}
|
||||
|
||||
template <class R, class... Args>
|
||||
template <typename R, typename... Args>
|
||||
R _call_native_mb_ret(const GDExtensionMethodBindPtr mb, void *instance, const Args &...args) {
|
||||
R ret;
|
||||
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
|
||||
@@ -62,13 +62,13 @@ R _call_native_mb_ret(const GDExtensionMethodBindPtr mb, void *instance, const A
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
template <typename... Args>
|
||||
void _call_native_mb_no_ret(const GDExtensionMethodBindPtr mb, void *instance, const Args &...args) {
|
||||
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
|
||||
internal::gdextension_interface_object_method_bind_ptrcall(mb, instance, mb_args.data(), nullptr);
|
||||
}
|
||||
|
||||
template <class R, class... Args>
|
||||
template <typename R, typename... Args>
|
||||
R _call_utility_ret(GDExtensionPtrUtilityFunction func, const Args &...args) {
|
||||
R ret;
|
||||
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
|
||||
@@ -76,15 +76,15 @@ R _call_utility_ret(GDExtensionPtrUtilityFunction func, const Args &...args) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
Object *_call_utility_ret_obj(const GDExtensionPtrUtilityFunction func, void *instance, const Args &...args) {
|
||||
template <typename... Args>
|
||||
Object *_call_utility_ret_obj(const GDExtensionPtrUtilityFunction func, const Args &...args) {
|
||||
GodotObject *ret = nullptr;
|
||||
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
|
||||
func(&ret, mb_args.data(), mb_args.size());
|
||||
return (Object *)internal::get_object_instance_binding(ret);
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
template <typename... Args>
|
||||
void _call_utility_no_ret(const GDExtensionPtrUtilityFunction func, const Args &...args) {
|
||||
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
|
||||
func(nullptr, mb_args.data(), mb_args.size());
|
||||
|
||||
@@ -84,7 +84,7 @@ constexpr auto CLAMP(const T m_a, const T2 m_min, const T3 m_max) {
|
||||
// Generic swap template.
|
||||
#ifndef SWAP
|
||||
#define SWAP(m_x, m_y) __swap_tmpl((m_x), (m_y))
|
||||
template <class T>
|
||||
template <typename T>
|
||||
inline void __swap_tmpl(T &x, T &y) {
|
||||
T aux = x;
|
||||
x = y;
|
||||
@@ -138,7 +138,7 @@ static inline int get_shift_from_power_of_2(unsigned int p_bits) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
static _FORCE_INLINE_ T nearest_power_of_2_templated(T x) {
|
||||
--x;
|
||||
|
||||
@@ -613,6 +613,14 @@ inline bool is_inf(double p_val) {
|
||||
return std::isinf(p_val);
|
||||
}
|
||||
|
||||
inline bool is_finite(float p_val) {
|
||||
return std::isfinite(p_val);
|
||||
}
|
||||
|
||||
inline bool is_finite(double p_val) {
|
||||
return std::isfinite(p_val);
|
||||
}
|
||||
|
||||
inline bool is_equal_approx(float a, float b) {
|
||||
// Check for exact equality first, required to handle "infinity" values.
|
||||
if (a == b) {
|
||||
|
||||
@@ -40,10 +40,6 @@
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#ifndef PAD_ALIGN
|
||||
#define PAD_ALIGN 16 //must always be greater than this at much
|
||||
#endif
|
||||
|
||||
// p_dummy argument is added to avoid conflicts with the engine functions when both engine and GDExtension are built as a static library on iOS.
|
||||
void *operator new(size_t p_size, const char *p_dummy, const char *p_description); ///< operator new that takes a description and uses MemoryStaticPool
|
||||
void *operator new(size_t p_size, const char *p_dummy, void *(*p_allocfunc)(size_t p_size)); ///< operator new that takes a description and uses MemoryStaticPool
|
||||
@@ -69,6 +65,18 @@ class Memory {
|
||||
Memory();
|
||||
|
||||
public:
|
||||
// Alignment: ↓ max_align_t ↓ uint64_t ↓ max_align_t
|
||||
// ┌─────────────────┬──┬────────────────┬──┬───────────...
|
||||
// │ uint64_t │░░│ uint64_t │░░│ T[]
|
||||
// │ alloc size │░░│ element count │░░│ data
|
||||
// └─────────────────┴──┴────────────────┴──┴───────────...
|
||||
// Offset: ↑ SIZE_OFFSET ↑ ELEMENT_OFFSET ↑ DATA_OFFSET
|
||||
// Note: "alloc size" is used and set by the engine and is never accessed or changed for the extension.
|
||||
|
||||
static constexpr size_t SIZE_OFFSET = 0;
|
||||
static constexpr size_t ELEMENT_OFFSET = ((SIZE_OFFSET + sizeof(uint64_t)) % alignof(uint64_t) == 0) ? (SIZE_OFFSET + sizeof(uint64_t)) : ((SIZE_OFFSET + sizeof(uint64_t)) + alignof(uint64_t) - ((SIZE_OFFSET + sizeof(uint64_t)) % alignof(uint64_t)));
|
||||
static constexpr size_t DATA_OFFSET = ((ELEMENT_OFFSET + sizeof(uint64_t)) % alignof(max_align_t) == 0) ? (ELEMENT_OFFSET + sizeof(uint64_t)) : ((ELEMENT_OFFSET + sizeof(uint64_t)) + alignof(max_align_t) - ((ELEMENT_OFFSET + sizeof(uint64_t)) % alignof(max_align_t)));
|
||||
|
||||
static void *alloc_static(size_t p_bytes, bool p_pad_align = false);
|
||||
static void *realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align = false);
|
||||
static void free_static(void *p_ptr, bool p_pad_align = false);
|
||||
@@ -76,7 +84,7 @@ public:
|
||||
|
||||
_ALWAYS_INLINE_ void postinitialize_handler(void *) {}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
_ALWAYS_INLINE_ T *_post_initialize(T *p_obj) {
|
||||
postinitialize_handler(p_obj);
|
||||
return p_obj;
|
||||
@@ -92,28 +100,28 @@ _ALWAYS_INLINE_ T *_post_initialize(T *p_obj) {
|
||||
#define memnew_placement(m_placement, m_class) ::godot::_post_initialize(new ("", m_placement, sizeof(m_class), "") m_class)
|
||||
|
||||
// Generic comparator used in Map, List, etc.
|
||||
template <class T>
|
||||
template <typename T>
|
||||
struct Comparator {
|
||||
_ALWAYS_INLINE_ bool operator()(const T &p_a, const T &p_b) const { return (p_a < p_b); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
void memdelete(T *p_class, typename std::enable_if<!std::is_base_of_v<godot::Wrapped, T>>::type * = nullptr) {
|
||||
if (!std::is_trivially_destructible<T>::value) {
|
||||
if constexpr (!std::is_trivially_destructible_v<T>) {
|
||||
p_class->~T();
|
||||
}
|
||||
|
||||
Memory::free_static(p_class);
|
||||
}
|
||||
|
||||
template <class T, std::enable_if_t<std::is_base_of_v<godot::Wrapped, T>, bool> = true>
|
||||
template <typename T, std::enable_if_t<std::is_base_of_v<godot::Wrapped, T>, bool> = true>
|
||||
void memdelete(T *p_class) {
|
||||
godot::internal::gdextension_interface_object_destroy(p_class->_owner);
|
||||
}
|
||||
|
||||
template <class T, class A>
|
||||
template <typename T, typename A>
|
||||
void memdelete_allocator(T *p_class) {
|
||||
if (!std::is_trivially_destructible<T>::value) {
|
||||
if constexpr (!std::is_trivially_destructible_v<T>) {
|
||||
p_class->~T();
|
||||
}
|
||||
|
||||
@@ -126,16 +134,20 @@ public:
|
||||
_ALWAYS_INLINE_ static void free(void *p_ptr) { Memory::free_static(p_ptr); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
class DefaultTypedAllocator {
|
||||
public:
|
||||
template <class... Args>
|
||||
template <typename... Args>
|
||||
_ALWAYS_INLINE_ T *new_allocation(const Args &&...p_args) { return memnew(T(p_args...)); }
|
||||
_ALWAYS_INLINE_ void delete_allocation(T *p_allocation) { memdelete(p_allocation); }
|
||||
};
|
||||
|
||||
#define memnew_arr(m_class, m_count) memnew_arr_template<m_class>(m_count)
|
||||
|
||||
_FORCE_INLINE_ uint64_t *_get_element_count_ptr(uint8_t *p_ptr) {
|
||||
return (uint64_t *)(p_ptr - Memory::DATA_OFFSET + Memory::ELEMENT_OFFSET);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *memnew_arr_template(size_t p_elements, const char *p_descr = "") {
|
||||
if (p_elements == 0) {
|
||||
@@ -145,12 +157,14 @@ T *memnew_arr_template(size_t p_elements, const char *p_descr = "") {
|
||||
same strategy used by std::vector, and the Vector class, so it should be safe.*/
|
||||
|
||||
size_t len = sizeof(T) * p_elements;
|
||||
uint64_t *mem = (uint64_t *)Memory::alloc_static(len, true);
|
||||
uint8_t *mem = (uint8_t *)Memory::alloc_static(len, true);
|
||||
T *failptr = nullptr; // Get rid of a warning.
|
||||
ERR_FAIL_NULL_V(mem, failptr);
|
||||
*(mem - 1) = p_elements;
|
||||
|
||||
if (!std::is_trivially_destructible<T>::value) {
|
||||
uint64_t *_elem_count_ptr = _get_element_count_ptr(mem);
|
||||
*(_elem_count_ptr) = p_elements;
|
||||
|
||||
if constexpr (!std::is_trivially_destructible_v<T>) {
|
||||
T *elems = (T *)mem;
|
||||
|
||||
/* call operator new */
|
||||
@@ -163,11 +177,19 @@ T *memnew_arr_template(size_t p_elements, const char *p_descr = "") {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void memdelete_arr(T *p_class) {
|
||||
uint64_t *ptr = (uint64_t *)p_class;
|
||||
size_t memarr_len(const T *p_class) {
|
||||
uint8_t *ptr = (uint8_t *)p_class;
|
||||
uint64_t *_elem_count_ptr = _get_element_count_ptr(ptr);
|
||||
return *(_elem_count_ptr);
|
||||
}
|
||||
|
||||
if (!std::is_trivially_destructible<T>::value) {
|
||||
uint64_t elem_count = *(ptr - 1);
|
||||
template <typename T>
|
||||
void memdelete_arr(T *p_class) {
|
||||
uint8_t *ptr = (uint8_t *)p_class;
|
||||
|
||||
if constexpr (!std::is_trivially_destructible_v<T>) {
|
||||
uint64_t *_elem_count_ptr = _get_element_count_ptr(ptr);
|
||||
uint64_t elem_count = *(_elem_count_ptr);
|
||||
|
||||
for (uint64_t i = 0; i < elem_count; i++) {
|
||||
p_class[i].~T();
|
||||
|
||||
@@ -132,7 +132,7 @@ public:
|
||||
std::vector<GDExtensionClassMethodArgumentMetadata> vec;
|
||||
// First element is return value
|
||||
vec.reserve(argument_count + 1);
|
||||
for (int i = 0; i < argument_count; i++) {
|
||||
for (int i = 0; i < argument_count + 1; i++) {
|
||||
vec.push_back(get_argument_metadata(i - 1));
|
||||
}
|
||||
return vec;
|
||||
@@ -147,7 +147,7 @@ public:
|
||||
virtual ~MethodBind();
|
||||
};
|
||||
|
||||
template <class Derived, class T, class R, bool should_returns>
|
||||
template <typename Derived, typename T, typename R, bool should_returns>
|
||||
class MethodBindVarArgBase : public MethodBind {
|
||||
protected:
|
||||
R(T::*method)
|
||||
@@ -208,7 +208,7 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
class MethodBindVarArgT : public MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false> {
|
||||
friend class MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>;
|
||||
|
||||
@@ -231,14 +231,14 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
MethodBind *create_vararg_method_bind(void (T::*p_method)(const Variant **, GDExtensionInt, GDExtensionCallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) {
|
||||
MethodBind *a = memnew((MethodBindVarArgT<T>)(p_method, p_info, p_return_nil_is_variant));
|
||||
a->set_instance_class(T::get_class_static());
|
||||
return a;
|
||||
}
|
||||
|
||||
template <class T, class R>
|
||||
template <typename T, typename R>
|
||||
class MethodBindVarArgTR : public MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true> {
|
||||
friend class MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>;
|
||||
|
||||
@@ -260,7 +260,7 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class R>
|
||||
template <typename T, typename R>
|
||||
MethodBind *create_vararg_method_bind(R (T::*p_method)(const Variant **, GDExtensionInt, GDExtensionCallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) {
|
||||
MethodBind *a = memnew((MethodBindVarArgTR<T, R>)(p_method, p_info, p_return_nil_is_variant));
|
||||
a->set_instance_class(T::get_class_static());
|
||||
@@ -277,9 +277,9 @@ class _gde_UnexistingClass;
|
||||
// No return, not const.
|
||||
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
template <class T, class... P>
|
||||
template <typename T, typename... P>
|
||||
#else
|
||||
template <class... P>
|
||||
template <typename... P>
|
||||
#endif // TYPED_METHOD_BIND
|
||||
class MethodBindT : public MethodBind {
|
||||
void (MB_T::*method)(P...);
|
||||
@@ -339,7 +339,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class... P>
|
||||
template <typename T, typename... P>
|
||||
MethodBind *create_method_bind(void (T::*p_method)(P...)) {
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
MethodBind *a = memnew((MethodBindT<T, P...>)(p_method));
|
||||
@@ -353,9 +353,9 @@ MethodBind *create_method_bind(void (T::*p_method)(P...)) {
|
||||
// No return, const.
|
||||
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
template <class T, class... P>
|
||||
template <typename T, typename... P>
|
||||
#else
|
||||
template <class... P>
|
||||
template <typename... P>
|
||||
#endif // TYPED_METHOD_BIND
|
||||
class MethodBindTC : public MethodBind {
|
||||
void (MB_T::*method)(P...) const;
|
||||
@@ -412,10 +412,11 @@ public:
|
||||
method = p_method;
|
||||
generate_argument_types(sizeof...(P));
|
||||
set_argument_count(sizeof...(P));
|
||||
set_const(true);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class... P>
|
||||
template <typename T, typename... P>
|
||||
MethodBind *create_method_bind(void (T::*p_method)(P...) const) {
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
MethodBind *a = memnew((MethodBindTC<T, P...>)(p_method));
|
||||
@@ -429,9 +430,9 @@ MethodBind *create_method_bind(void (T::*p_method)(P...) const) {
|
||||
// Return, not const.
|
||||
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
template <class T, class R, class... P>
|
||||
template <typename T, typename R, typename... P>
|
||||
#else
|
||||
template <class R, class... P>
|
||||
template <typename R, typename... P>
|
||||
#endif // TYPED_METHOD_BIND
|
||||
class MethodBindTR : public MethodBind {
|
||||
R(MB_T::*method)
|
||||
@@ -498,7 +499,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class R, class... P>
|
||||
template <typename T, typename R, typename... P>
|
||||
MethodBind *create_method_bind(R (T::*p_method)(P...)) {
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
MethodBind *a = memnew((MethodBindTR<T, R, P...>)(p_method));
|
||||
@@ -512,9 +513,9 @@ MethodBind *create_method_bind(R (T::*p_method)(P...)) {
|
||||
// Return, const.
|
||||
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
template <class T, class R, class... P>
|
||||
template <typename T, typename R, typename... P>
|
||||
#else
|
||||
template <class R, class... P>
|
||||
template <typename R, typename... P>
|
||||
#endif // TYPED_METHOD_BIND
|
||||
class MethodBindTRC : public MethodBind {
|
||||
R(MB_T::*method)
|
||||
@@ -578,10 +579,11 @@ public:
|
||||
generate_argument_types(sizeof...(P));
|
||||
set_argument_count(sizeof...(P));
|
||||
set_return(true);
|
||||
set_const(true);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class R, class... P>
|
||||
template <typename T, typename R, typename... P>
|
||||
MethodBind *create_method_bind(R (T::*p_method)(P...) const) {
|
||||
#ifdef TYPED_METHOD_BIND
|
||||
MethodBind *a = memnew((MethodBindTRC<T, R, P...>)(p_method));
|
||||
@@ -596,7 +598,7 @@ MethodBind *create_method_bind(R (T::*p_method)(P...) const) {
|
||||
|
||||
// no return
|
||||
|
||||
template <class... P>
|
||||
template <typename... P>
|
||||
class MethodBindTS : public MethodBind {
|
||||
void (*function)(P...);
|
||||
|
||||
@@ -652,7 +654,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <class... P>
|
||||
template <typename... P>
|
||||
MethodBind *create_static_method_bind(void (*p_method)(P...)) {
|
||||
MethodBind *a = memnew((MethodBindTS<P...>)(p_method));
|
||||
return a;
|
||||
@@ -660,7 +662,7 @@ MethodBind *create_static_method_bind(void (*p_method)(P...)) {
|
||||
|
||||
// return
|
||||
|
||||
template <class R, class... P>
|
||||
template <typename R, typename... P>
|
||||
class MethodBindTRS : public MethodBind {
|
||||
R(*function)
|
||||
(P...);
|
||||
@@ -722,7 +724,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <class R, class... P>
|
||||
template <typename R, typename... P>
|
||||
MethodBind *create_static_method_bind(R (*p_method)(P...)) {
|
||||
MethodBind *a = memnew((MethodBindTRS<R, P...>)(p_method));
|
||||
return a;
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
namespace godot {
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
struct PtrToArg {};
|
||||
|
||||
#define MAKE_PTRARG(m_type) \
|
||||
@@ -166,27 +166,27 @@ MAKE_PTRARG_BY_REFERENCE(Variant);
|
||||
|
||||
// This is for Object.
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
struct PtrToArg<T *> {
|
||||
static_assert(std::is_base_of<Object, T>::value, "Cannot encode non-Object value as an Object");
|
||||
_FORCE_INLINE_ static T *convert(const void *p_ptr) {
|
||||
return reinterpret_cast<T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr))));
|
||||
return likely(p_ptr) ? reinterpret_cast<T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr)))) : nullptr;
|
||||
}
|
||||
typedef Object *EncodeT;
|
||||
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
|
||||
*reinterpret_cast<const void **>(p_ptr) = p_var ? p_var->_owner : nullptr;
|
||||
*reinterpret_cast<const void **>(p_ptr) = likely(p_var) ? p_var->_owner : nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
struct PtrToArg<const T *> {
|
||||
static_assert(std::is_base_of<Object, T>::value, "Cannot encode non-Object value as an Object");
|
||||
_FORCE_INLINE_ static const T *convert(const void *p_ptr) {
|
||||
return reinterpret_cast<const T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr))));
|
||||
return likely(p_ptr) ? reinterpret_cast<const T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr)))) : nullptr;
|
||||
}
|
||||
typedef const Object *EncodeT;
|
||||
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
|
||||
*reinterpret_cast<const void **>(p_ptr) = p_var ? p_var->_owner : nullptr;
|
||||
*reinterpret_cast<const void **>(p_ptr) = likely(p_var) ? p_var->_owner : nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -47,11 +47,11 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#define ADD_SIGNAL(m_signal) godot::ClassDB::add_signal(get_class_static(), m_signal)
|
||||
#define ADD_GROUP(m_name, m_prefix) godot::ClassDB::add_property_group(get_class_static(), m_name, m_prefix)
|
||||
#define ADD_SUBGROUP(m_name, m_prefix) godot::ClassDB::add_property_subgroup(get_class_static(), m_name, m_prefix)
|
||||
#define ADD_PROPERTY(m_property, m_setter, m_getter) godot::ClassDB::add_property(get_class_static(), m_property, m_setter, m_getter)
|
||||
#define ADD_PROPERTYI(m_property, m_setter, m_getter, m_index) godot::ClassDB::add_property(get_class_static(), m_property, m_setter, m_getter, m_index)
|
||||
#define ADD_SIGNAL(m_signal) ::godot::ClassDB::add_signal(get_class_static(), m_signal)
|
||||
#define ADD_GROUP(m_name, m_prefix) ::godot::ClassDB::add_property_group(get_class_static(), m_name, m_prefix)
|
||||
#define ADD_SUBGROUP(m_name, m_prefix) ::godot::ClassDB::add_property_subgroup(get_class_static(), m_name, m_prefix)
|
||||
#define ADD_PROPERTY(m_property, m_setter, m_getter) ::godot::ClassDB::add_property(get_class_static(), m_property, m_setter, m_getter)
|
||||
#define ADD_PROPERTYI(m_property, m_setter, m_getter, m_index) ::godot::ClassDB::add_property(get_class_static(), m_property, m_setter, m_getter, m_index)
|
||||
|
||||
namespace godot {
|
||||
|
||||
@@ -78,31 +78,31 @@ struct MethodInfo {
|
||||
|
||||
MethodInfo();
|
||||
MethodInfo(StringName p_name);
|
||||
template <class... Args>
|
||||
template <typename... Args>
|
||||
MethodInfo(StringName p_name, const Args &...args);
|
||||
MethodInfo(Variant::Type ret);
|
||||
MethodInfo(Variant::Type ret, StringName p_name);
|
||||
template <class... Args>
|
||||
template <typename... Args>
|
||||
MethodInfo(Variant::Type ret, StringName p_name, const Args &...args);
|
||||
MethodInfo(const PropertyInfo &p_ret, StringName p_name);
|
||||
template <class... Args>
|
||||
template <typename... Args>
|
||||
MethodInfo(const PropertyInfo &p_ret, StringName p_name, const Args &...);
|
||||
};
|
||||
|
||||
template <class... Args>
|
||||
template <typename... Args>
|
||||
MethodInfo::MethodInfo(StringName p_name, const Args &...args) :
|
||||
name(p_name), flags(GDEXTENSION_METHOD_FLAG_NORMAL) {
|
||||
arguments = { args... };
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
template <typename... Args>
|
||||
MethodInfo::MethodInfo(Variant::Type ret, StringName p_name, const Args &...args) :
|
||||
name(p_name), flags(GDEXTENSION_METHOD_FLAG_NORMAL) {
|
||||
return_val.type = ret;
|
||||
arguments = { args... };
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
template <typename... Args>
|
||||
MethodInfo::MethodInfo(const PropertyInfo &p_ret, StringName p_name, const Args &...args) :
|
||||
name(p_name), return_val(p_ret), flags(GDEXTENSION_METHOD_FLAG_NORMAL) {
|
||||
arguments = { args... };
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
T *Object::cast_to(Object *p_object) {
|
||||
if (p_object == nullptr) {
|
||||
return nullptr;
|
||||
@@ -132,7 +132,7 @@ T *Object::cast_to(Object *p_object) {
|
||||
return dynamic_cast<T *>(internal::get_object_instance_binding(casted));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
const T *Object::cast_to(const Object *p_object) {
|
||||
if (p_object == nullptr) {
|
||||
return nullptr;
|
||||
|
||||
@@ -47,9 +47,9 @@ struct PropertyInfo {
|
||||
Variant::Type type = Variant::NIL;
|
||||
StringName name;
|
||||
StringName class_name;
|
||||
uint32_t hint = 0;
|
||||
uint32_t hint = PROPERTY_HINT_NONE;
|
||||
String hint_string;
|
||||
uint32_t usage = 7;
|
||||
uint32_t usage = PROPERTY_USAGE_DEFAULT;
|
||||
|
||||
PropertyInfo() = default;
|
||||
|
||||
@@ -72,6 +72,40 @@ struct PropertyInfo {
|
||||
PropertyInfo(const GDExtensionPropertyInfo *p_info) :
|
||||
PropertyInfo(p_info->type, *reinterpret_cast<StringName *>(p_info->name), (PropertyHint)p_info->hint, *reinterpret_cast<String *>(p_info->hint_string), p_info->usage, *reinterpret_cast<StringName *>(p_info->class_name)) {}
|
||||
|
||||
operator Dictionary() const {
|
||||
Dictionary dict;
|
||||
dict["name"] = name;
|
||||
dict["class_name"] = class_name;
|
||||
dict["type"] = type;
|
||||
dict["hint"] = hint;
|
||||
dict["hint_string"] = hint_string;
|
||||
dict["usage"] = usage;
|
||||
return dict;
|
||||
}
|
||||
|
||||
static PropertyInfo from_dict(const Dictionary &p_dict) {
|
||||
PropertyInfo pi;
|
||||
if (p_dict.has("type")) {
|
||||
pi.type = Variant::Type(int(p_dict["type"]));
|
||||
}
|
||||
if (p_dict.has("name")) {
|
||||
pi.name = p_dict["name"];
|
||||
}
|
||||
if (p_dict.has("class_name")) {
|
||||
pi.class_name = p_dict["class_name"];
|
||||
}
|
||||
if (p_dict.has("hint")) {
|
||||
pi.hint = PropertyHint(int(p_dict["hint"]));
|
||||
}
|
||||
if (p_dict.has("hint_string")) {
|
||||
pi.hint_string = p_dict["hint_string"];
|
||||
}
|
||||
if (p_dict.has("usage")) {
|
||||
pi.usage = p_dict["usage"];
|
||||
}
|
||||
return pi;
|
||||
}
|
||||
|
||||
void _update(GDExtensionPropertyInfo *p_info) {
|
||||
p_info->type = (GDExtensionVariantType)type;
|
||||
*(reinterpret_cast<StringName *>(p_info->name)) = name;
|
||||
|
||||
@@ -58,6 +58,16 @@ struct TypesAreSame<A, A> {
|
||||
static bool const value = true;
|
||||
};
|
||||
|
||||
template <auto A, auto B>
|
||||
struct FunctionsAreSame {
|
||||
static bool const value = false;
|
||||
};
|
||||
|
||||
template <auto A>
|
||||
struct FunctionsAreSame<A, A> {
|
||||
static bool const value = true;
|
||||
};
|
||||
|
||||
template <typename B, typename D>
|
||||
struct TypeInherits {
|
||||
static D *get_d();
|
||||
@@ -90,7 +100,7 @@ static PropertyInfo make_property_info(Variant::Type p_type, const StringName &p
|
||||
// instead of a forward declaration. You can always forward declare 'T' in a header file, and then
|
||||
// include the actual declaration of 'T' in the source file where 'GetTypeInfo<T>' is instantiated.
|
||||
|
||||
template <class T, typename = void>
|
||||
template <typename T, typename = void>
|
||||
struct GetTypeInfo;
|
||||
|
||||
#define MAKE_TYPE_INFO(m_type, m_var_type) \
|
||||
@@ -248,14 +258,14 @@ inline StringName _gde_constant_get_enum_name(T param, StringName p_constant) {
|
||||
return GetTypeInfo<T>::get_class_info().class_name;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
class BitField {
|
||||
int64_t value = 0;
|
||||
|
||||
public:
|
||||
_FORCE_INLINE_ void set_flag(T p_flag) { value |= p_flag; }
|
||||
_FORCE_INLINE_ bool has_flag(T p_flag) const { return value & p_flag; }
|
||||
_FORCE_INLINE_ void clear_flag(T p_flag) { return value &= ~p_flag; }
|
||||
_FORCE_INLINE_ void clear_flag(T p_flag) { value &= ~p_flag; }
|
||||
_FORCE_INLINE_ BitField(int64_t p_value) { value = p_value; }
|
||||
_FORCE_INLINE_ operator int64_t() const { return value; }
|
||||
_FORCE_INLINE_ operator Variant() const { return value; }
|
||||
@@ -295,7 +305,7 @@ inline StringName _gde_constant_get_bitfield_name(T param, StringName p_constant
|
||||
return GetTypeInfo<BitField<T>>::get_class_info().class_name;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
struct PtrToArg<TypedArray<T>> {
|
||||
_FORCE_INLINE_ static TypedArray<T> convert(const void *p_ptr) {
|
||||
return TypedArray<T>(*reinterpret_cast<const Array *>(p_ptr));
|
||||
@@ -306,7 +316,7 @@ struct PtrToArg<TypedArray<T>> {
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
struct PtrToArg<const TypedArray<T> &> {
|
||||
typedef Array EncodeT;
|
||||
_FORCE_INLINE_ static TypedArray<T>
|
||||
@@ -383,17 +393,15 @@ MAKE_TYPED_ARRAY_INFO(Callable, Variant::CALLABLE)
|
||||
MAKE_TYPED_ARRAY_INFO(Signal, Variant::SIGNAL)
|
||||
MAKE_TYPED_ARRAY_INFO(Dictionary, Variant::DICTIONARY)
|
||||
MAKE_TYPED_ARRAY_INFO(Array, Variant::ARRAY)
|
||||
/*
|
||||
MAKE_TYPED_ARRAY_INFO(Vector<uint8_t>, Variant::PACKED_BYTE_ARRAY)
|
||||
MAKE_TYPED_ARRAY_INFO(Vector<int32_t>, Variant::PACKED_INT32_ARRAY)
|
||||
MAKE_TYPED_ARRAY_INFO(Vector<int64_t>, Variant::PACKED_INT64_ARRAY)
|
||||
MAKE_TYPED_ARRAY_INFO(Vector<float>, Variant::PACKED_FLOAT32_ARRAY)
|
||||
MAKE_TYPED_ARRAY_INFO(Vector<double>, Variant::PACKED_FLOAT64_ARRAY)
|
||||
MAKE_TYPED_ARRAY_INFO(Vector<String>, Variant::PACKED_STRING_ARRAY)
|
||||
MAKE_TYPED_ARRAY_INFO(Vector<Vector2>, Variant::PACKED_VECTOR2_ARRAY)
|
||||
MAKE_TYPED_ARRAY_INFO(Vector<Vector3>, Variant::PACKED_VECTOR3_ARRAY)
|
||||
MAKE_TYPED_ARRAY_INFO(Vector<Color>, Variant::PACKED_COLOR_ARRAY)
|
||||
*/
|
||||
MAKE_TYPED_ARRAY_INFO(PackedByteArray, Variant::PACKED_BYTE_ARRAY)
|
||||
MAKE_TYPED_ARRAY_INFO(PackedInt32Array, Variant::PACKED_INT32_ARRAY)
|
||||
MAKE_TYPED_ARRAY_INFO(PackedInt64Array, Variant::PACKED_INT64_ARRAY)
|
||||
MAKE_TYPED_ARRAY_INFO(PackedFloat32Array, Variant::PACKED_FLOAT32_ARRAY)
|
||||
MAKE_TYPED_ARRAY_INFO(PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY)
|
||||
MAKE_TYPED_ARRAY_INFO(PackedStringArray, Variant::PACKED_STRING_ARRAY)
|
||||
MAKE_TYPED_ARRAY_INFO(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY)
|
||||
MAKE_TYPED_ARRAY_INFO(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY)
|
||||
MAKE_TYPED_ARRAY_INFO(PackedColorArray, Variant::PACKED_COLOR_ARRAY)
|
||||
|
||||
#define CLASS_INFO(m_type) (GetTypeInfo<m_type *>::get_class_info())
|
||||
|
||||
|
||||
@@ -160,6 +160,7 @@ extern "C" GDExtensionInterfaceObjectDestroy gdextension_interface_object_destro
|
||||
extern "C" GDExtensionInterfaceGlobalGetSingleton gdextension_interface_global_get_singleton;
|
||||
extern "C" GDExtensionInterfaceObjectGetInstanceBinding gdextension_interface_object_get_instance_binding;
|
||||
extern "C" GDExtensionInterfaceObjectSetInstanceBinding gdextension_interface_object_set_instance_binding;
|
||||
extern "C" GDExtensionInterfaceObjectFreeInstanceBinding gdextension_interface_object_free_instance_binding;
|
||||
extern "C" GDExtensionInterfaceObjectSetInstance gdextension_interface_object_set_instance;
|
||||
extern "C" GDExtensionInterfaceObjectGetClassName gdextension_interface_object_get_class_name;
|
||||
extern "C" GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to;
|
||||
|
||||
@@ -43,78 +43,120 @@
|
||||
|
||||
namespace godot {
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
class Vector;
|
||||
|
||||
template <class T, class V>
|
||||
template <typename T, typename V>
|
||||
class VMap;
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
class CharStringT;
|
||||
|
||||
static_assert(std::is_trivially_destructible_v<std::atomic<uint64_t>>);
|
||||
|
||||
// Silence a false positive warning (see GH-52119).
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wplacement-new"
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
class CowData {
|
||||
template <class TV>
|
||||
template <typename TV>
|
||||
friend class Vector;
|
||||
|
||||
template <class TV, class VV>
|
||||
template <typename TV, typename VV>
|
||||
friend class VMap;
|
||||
|
||||
template <class TS>
|
||||
template <typename TS>
|
||||
friend class CharStringT;
|
||||
|
||||
public:
|
||||
typedef int64_t Size;
|
||||
typedef uint64_t USize;
|
||||
static constexpr USize MAX_INT = INT64_MAX;
|
||||
|
||||
private:
|
||||
// Function to find the next power of 2 to an integer.
|
||||
static _FORCE_INLINE_ USize next_po2(USize x) {
|
||||
if (x == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
--x;
|
||||
x |= x >> 1;
|
||||
x |= x >> 2;
|
||||
x |= x >> 4;
|
||||
x |= x >> 8;
|
||||
x |= x >> 16;
|
||||
if (sizeof(USize) == 8) {
|
||||
x |= x >> 32;
|
||||
}
|
||||
|
||||
return ++x;
|
||||
}
|
||||
|
||||
// Alignment: ↓ max_align_t ↓ USize ↓ max_align_t
|
||||
// ┌────────────────────┬──┬─────────────┬──┬───────────...
|
||||
// │ SafeNumeric<USize> │░░│ USize │░░│ T[]
|
||||
// │ ref. count │░░│ data size │░░│ data
|
||||
// └────────────────────┴──┴─────────────┴──┴───────────...
|
||||
// Offset: ↑ REF_COUNT_OFFSET ↑ SIZE_OFFSET ↑ DATA_OFFSET
|
||||
|
||||
static constexpr size_t REF_COUNT_OFFSET = 0;
|
||||
static constexpr size_t SIZE_OFFSET = ((REF_COUNT_OFFSET + sizeof(SafeNumeric<USize>)) % alignof(USize) == 0) ? (REF_COUNT_OFFSET + sizeof(SafeNumeric<USize>)) : ((REF_COUNT_OFFSET + sizeof(SafeNumeric<USize>)) + alignof(USize) - ((REF_COUNT_OFFSET + sizeof(SafeNumeric<USize>)) % alignof(USize)));
|
||||
static constexpr size_t DATA_OFFSET = ((SIZE_OFFSET + sizeof(USize)) % alignof(max_align_t) == 0) ? (SIZE_OFFSET + sizeof(USize)) : ((SIZE_OFFSET + sizeof(USize)) + alignof(max_align_t) - ((SIZE_OFFSET + sizeof(USize)) % alignof(max_align_t)));
|
||||
|
||||
mutable T *_ptr = nullptr;
|
||||
|
||||
// internal helpers
|
||||
|
||||
_FORCE_INLINE_ SafeNumeric<uint32_t> *_get_refcount() const {
|
||||
static _FORCE_INLINE_ SafeNumeric<USize> *_get_refcount_ptr(uint8_t *p_ptr) {
|
||||
return (SafeNumeric<USize> *)(p_ptr + REF_COUNT_OFFSET);
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ USize *_get_size_ptr(uint8_t *p_ptr) {
|
||||
return (USize *)(p_ptr + SIZE_OFFSET);
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ T *_get_data_ptr(uint8_t *p_ptr) {
|
||||
return (T *)(p_ptr + DATA_OFFSET);
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ SafeNumeric<USize> *_get_refcount() const {
|
||||
if (!_ptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return reinterpret_cast<SafeNumeric<uint32_t> *>(_ptr) - 2;
|
||||
return (SafeNumeric<USize> *)((uint8_t *)_ptr - DATA_OFFSET + REF_COUNT_OFFSET);
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ uint32_t *_get_size() const {
|
||||
_FORCE_INLINE_ USize *_get_size() const {
|
||||
if (!_ptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return reinterpret_cast<uint32_t *>(_ptr) - 1;
|
||||
return (USize *)((uint8_t *)_ptr - DATA_OFFSET + SIZE_OFFSET);
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ T *_get_data() const {
|
||||
if (!_ptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<T *>(_ptr);
|
||||
_FORCE_INLINE_ USize _get_alloc_size(USize p_elements) const {
|
||||
return next_po2(p_elements * sizeof(T));
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ size_t _get_alloc_size(size_t p_elements) const {
|
||||
return next_power_of_2(p_elements * sizeof(T));
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool _get_alloc_size_checked(size_t p_elements, size_t *out) const {
|
||||
_FORCE_INLINE_ bool _get_alloc_size_checked(USize p_elements, USize *out) const {
|
||||
if (unlikely(p_elements == 0)) {
|
||||
*out = 0;
|
||||
return true;
|
||||
}
|
||||
#if defined(__GNUC__)
|
||||
size_t o;
|
||||
size_t p;
|
||||
#if defined(__GNUC__) && defined(IS_32_BIT)
|
||||
USize o;
|
||||
USize p;
|
||||
if (__builtin_mul_overflow(p_elements, sizeof(T), &o)) {
|
||||
*out = 0;
|
||||
return false;
|
||||
}
|
||||
*out = next_power_of_2(o);
|
||||
if (__builtin_add_overflow(o, static_cast<size_t>(32), &p)) {
|
||||
*out = next_po2(o);
|
||||
if (__builtin_add_overflow(o, static_cast<USize>(32), &p)) {
|
||||
return false; // No longer allocated here.
|
||||
}
|
||||
#else
|
||||
@@ -128,22 +170,22 @@ private:
|
||||
void _unref(void *p_data);
|
||||
void _ref(const CowData *p_from);
|
||||
void _ref(const CowData &p_from);
|
||||
uint32_t _copy_on_write();
|
||||
USize _copy_on_write();
|
||||
|
||||
public:
|
||||
void operator=(const CowData<T> &p_from) { _ref(p_from); }
|
||||
|
||||
_FORCE_INLINE_ T *ptrw() {
|
||||
_copy_on_write();
|
||||
return (T *)_get_data();
|
||||
return _ptr;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ const T *ptr() const {
|
||||
return _get_data();
|
||||
return _ptr;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ int size() const {
|
||||
uint32_t *size = (uint32_t *)_get_size();
|
||||
_FORCE_INLINE_ Size size() const {
|
||||
USize *size = (USize *)_get_size();
|
||||
if (size) {
|
||||
return *size;
|
||||
} else {
|
||||
@@ -154,41 +196,42 @@ public:
|
||||
_FORCE_INLINE_ void clear() { resize(0); }
|
||||
_FORCE_INLINE_ bool is_empty() const { return _ptr == nullptr; }
|
||||
|
||||
_FORCE_INLINE_ void set(int p_index, const T &p_elem) {
|
||||
_FORCE_INLINE_ void set(Size p_index, const T &p_elem) {
|
||||
ERR_FAIL_INDEX(p_index, size());
|
||||
_copy_on_write();
|
||||
_get_data()[p_index] = p_elem;
|
||||
_ptr[p_index] = p_elem;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ T &get_m(int p_index) {
|
||||
_FORCE_INLINE_ T &get_m(Size p_index) {
|
||||
CRASH_BAD_INDEX(p_index, size());
|
||||
_copy_on_write();
|
||||
return _get_data()[p_index];
|
||||
return _ptr[p_index];
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ const T &get(int p_index) const {
|
||||
_FORCE_INLINE_ const T &get(Size p_index) const {
|
||||
CRASH_BAD_INDEX(p_index, size());
|
||||
|
||||
return _get_data()[p_index];
|
||||
return _ptr[p_index];
|
||||
}
|
||||
|
||||
Error resize(int p_size);
|
||||
template <bool p_ensure_zero = false>
|
||||
Error resize(Size p_size);
|
||||
|
||||
_FORCE_INLINE_ void remove_at(int p_index) {
|
||||
_FORCE_INLINE_ void remove_at(Size p_index) {
|
||||
ERR_FAIL_INDEX(p_index, size());
|
||||
T *p = ptrw();
|
||||
int len = size();
|
||||
for (int i = p_index; i < len - 1; i++) {
|
||||
Size len = size();
|
||||
for (Size i = p_index; i < len - 1; i++) {
|
||||
p[i] = p[i + 1];
|
||||
}
|
||||
|
||||
resize(len - 1);
|
||||
}
|
||||
|
||||
Error insert(int p_pos, const T &p_val) {
|
||||
Error insert(Size p_pos, const T &p_val) {
|
||||
ERR_FAIL_INDEX_V(p_pos, size() + 1, ERR_INVALID_PARAMETER);
|
||||
resize(size() + 1);
|
||||
for (int i = (size() - 1); i > p_pos; i--) {
|
||||
for (Size i = (size() - 1); i > p_pos; i--) {
|
||||
set(i, get(i - 1));
|
||||
}
|
||||
set(p_pos, p_val);
|
||||
@@ -196,83 +239,88 @@ public:
|
||||
return OK;
|
||||
}
|
||||
|
||||
int find(const T &p_val, int p_from = 0) const;
|
||||
Size find(const T &p_val, Size p_from = 0) const;
|
||||
Size rfind(const T &p_val, Size p_from = -1) const;
|
||||
Size count(const T &p_val) const;
|
||||
|
||||
_FORCE_INLINE_ CowData() {}
|
||||
_FORCE_INLINE_ ~CowData();
|
||||
_FORCE_INLINE_ CowData(CowData<T> &p_from) { _ref(p_from); }
|
||||
_FORCE_INLINE_ CowData(CowData<T> &p_from) { _ref(p_from); };
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
void CowData<T>::_unref(void *p_data) {
|
||||
if (!p_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
SafeNumeric<uint32_t> *refc = _get_refcount();
|
||||
SafeNumeric<USize> *refc = _get_refcount();
|
||||
|
||||
if (refc->decrement() > 0) {
|
||||
return; // still in use
|
||||
}
|
||||
|
||||
// clean up
|
||||
if (!std::is_trivially_destructible<T>::value) {
|
||||
uint32_t *count = _get_size();
|
||||
|
||||
if constexpr (!std::is_trivially_destructible_v<T>) {
|
||||
USize *count = _get_size();
|
||||
T *data = (T *)(count + 1);
|
||||
|
||||
for (uint32_t i = 0; i < *count; ++i) {
|
||||
for (USize i = 0; i < *count; ++i) {
|
||||
// call destructors
|
||||
data[i].~T();
|
||||
}
|
||||
}
|
||||
|
||||
// free mem
|
||||
Memory::free_static((uint8_t *)p_data, true);
|
||||
Memory::free_static(((uint8_t *)p_data) - DATA_OFFSET, false);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
uint32_t CowData<T>::_copy_on_write() {
|
||||
template <typename T>
|
||||
typename CowData<T>::USize CowData<T>::_copy_on_write() {
|
||||
if (!_ptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
SafeNumeric<uint32_t> *refc = _get_refcount();
|
||||
SafeNumeric<USize> *refc = _get_refcount();
|
||||
|
||||
uint32_t rc = refc->get();
|
||||
USize rc = refc->get();
|
||||
if (unlikely(rc > 1)) {
|
||||
/* in use by more than me */
|
||||
uint32_t current_size = *_get_size();
|
||||
USize current_size = *_get_size();
|
||||
|
||||
uint32_t *mem_new = (uint32_t *)Memory::alloc_static(_get_alloc_size(current_size), true);
|
||||
uint8_t *mem_new = (uint8_t *)Memory::alloc_static(_get_alloc_size(current_size) + DATA_OFFSET, false);
|
||||
ERR_FAIL_NULL_V(mem_new, 0);
|
||||
|
||||
new (mem_new - 2) SafeNumeric<uint32_t>(1); // refcount
|
||||
*(mem_new - 1) = current_size; // size
|
||||
SafeNumeric<USize> *_refc_ptr = _get_refcount_ptr(mem_new);
|
||||
USize *_size_ptr = _get_size_ptr(mem_new);
|
||||
T *_data_ptr = _get_data_ptr(mem_new);
|
||||
|
||||
T *_data = (T *)(mem_new);
|
||||
new (_refc_ptr) SafeNumeric<USize>(1); //refcount
|
||||
*(_size_ptr) = current_size; //size
|
||||
|
||||
// initialize new elements
|
||||
if (std::is_trivially_copyable<T>::value) {
|
||||
memcpy(mem_new, _ptr, current_size * sizeof(T));
|
||||
|
||||
if constexpr (std::is_trivially_copyable_v<T>) {
|
||||
memcpy((uint8_t *)_data_ptr, _ptr, current_size * sizeof(T));
|
||||
} else {
|
||||
for (uint32_t i = 0; i < current_size; i++) {
|
||||
memnew_placement(&_data[i], T(_get_data()[i]));
|
||||
for (USize i = 0; i < current_size; i++) {
|
||||
memnew_placement(&_data_ptr[i], T(_ptr[i]));
|
||||
}
|
||||
}
|
||||
|
||||
_unref(_ptr);
|
||||
_ptr = _data;
|
||||
_ptr = _data_ptr;
|
||||
|
||||
rc = 1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
Error CowData<T>::resize(int p_size) {
|
||||
template <typename T>
|
||||
template <bool p_ensure_zero>
|
||||
Error CowData<T>::resize(Size p_size) {
|
||||
ERR_FAIL_COND_V(p_size < 0, ERR_INVALID_PARAMETER);
|
||||
|
||||
int current_size = size();
|
||||
Size current_size = size();
|
||||
|
||||
if (p_size == current_size) {
|
||||
return OK;
|
||||
@@ -286,59 +334,71 @@ Error CowData<T>::resize(int p_size) {
|
||||
}
|
||||
|
||||
// possibly changing size, copy on write
|
||||
uint32_t rc = _copy_on_write();
|
||||
USize rc = _copy_on_write();
|
||||
|
||||
size_t current_alloc_size = _get_alloc_size(current_size);
|
||||
size_t alloc_size;
|
||||
USize current_alloc_size = _get_alloc_size(current_size);
|
||||
USize alloc_size;
|
||||
ERR_FAIL_COND_V(!_get_alloc_size_checked(p_size, &alloc_size), ERR_OUT_OF_MEMORY);
|
||||
|
||||
if (p_size > current_size) {
|
||||
if (alloc_size != current_alloc_size) {
|
||||
if (current_size == 0) {
|
||||
// alloc from scratch
|
||||
uint32_t *ptr = (uint32_t *)Memory::alloc_static(alloc_size, true);
|
||||
ERR_FAIL_NULL_V(ptr, ERR_OUT_OF_MEMORY);
|
||||
*(ptr - 1) = 0; // size, currently none
|
||||
new (ptr - 2) SafeNumeric<uint32_t>(1); // refcount
|
||||
uint8_t *mem_new = (uint8_t *)Memory::alloc_static(alloc_size + DATA_OFFSET, false);
|
||||
ERR_FAIL_NULL_V(mem_new, ERR_OUT_OF_MEMORY);
|
||||
|
||||
_ptr = (T *)ptr;
|
||||
SafeNumeric<USize> *_refc_ptr = _get_refcount_ptr(mem_new);
|
||||
USize *_size_ptr = _get_size_ptr(mem_new);
|
||||
T *_data_ptr = _get_data_ptr(mem_new);
|
||||
|
||||
new (_refc_ptr) SafeNumeric<USize>(1); //refcount
|
||||
*(_size_ptr) = 0; //size, currently none
|
||||
|
||||
_ptr = _data_ptr;
|
||||
} else {
|
||||
uint32_t *_ptrnew = (uint32_t *)Memory::realloc_static(_ptr, alloc_size, true);
|
||||
ERR_FAIL_NULL_V(_ptrnew, ERR_OUT_OF_MEMORY);
|
||||
new (_ptrnew - 2) SafeNumeric<uint32_t>(rc); // refcount
|
||||
uint8_t *mem_new = (uint8_t *)Memory::realloc_static(((uint8_t *)_ptr) - DATA_OFFSET, alloc_size + DATA_OFFSET, false);
|
||||
ERR_FAIL_NULL_V(mem_new, ERR_OUT_OF_MEMORY);
|
||||
|
||||
_ptr = (T *)(_ptrnew);
|
||||
SafeNumeric<USize> *_refc_ptr = _get_refcount_ptr(mem_new);
|
||||
T *_data_ptr = _get_data_ptr(mem_new);
|
||||
|
||||
new (_refc_ptr) SafeNumeric<USize>(rc); //refcount
|
||||
|
||||
_ptr = _data_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
// construct the newly created elements
|
||||
|
||||
if (!std::is_trivially_constructible<T>::value) {
|
||||
T *elems = _get_data();
|
||||
|
||||
for (int i = *_get_size(); i < p_size; i++) {
|
||||
memnew_placement(&elems[i], T);
|
||||
if constexpr (!std::is_trivially_constructible_v<T>) {
|
||||
for (Size i = *_get_size(); i < p_size; i++) {
|
||||
memnew_placement(&_ptr[i], T);
|
||||
}
|
||||
} else if (p_ensure_zero) {
|
||||
memset((void *)(_ptr + current_size), 0, (p_size - current_size) * sizeof(T));
|
||||
}
|
||||
|
||||
*_get_size() = p_size;
|
||||
|
||||
} else if (p_size < current_size) {
|
||||
if (!std::is_trivially_destructible<T>::value) {
|
||||
if constexpr (!std::is_trivially_destructible_v<T>) {
|
||||
// deinitialize no longer needed elements
|
||||
for (uint32_t i = p_size; i < *_get_size(); i++) {
|
||||
T *t = &_get_data()[i];
|
||||
for (USize i = p_size; i < *_get_size(); i++) {
|
||||
T *t = &_ptr[i];
|
||||
t->~T();
|
||||
}
|
||||
}
|
||||
|
||||
if (alloc_size != current_alloc_size) {
|
||||
uint32_t *_ptrnew = (uint32_t *)Memory::realloc_static(_ptr, alloc_size, true);
|
||||
ERR_FAIL_NULL_V(_ptrnew, ERR_OUT_OF_MEMORY);
|
||||
new (_ptrnew - 2) SafeNumeric<uint32_t>(rc); // refcount
|
||||
uint8_t *mem_new = (uint8_t *)Memory::realloc_static(((uint8_t *)_ptr) - DATA_OFFSET, alloc_size + DATA_OFFSET, false);
|
||||
ERR_FAIL_NULL_V(mem_new, ERR_OUT_OF_MEMORY);
|
||||
|
||||
_ptr = (T *)(_ptrnew);
|
||||
SafeNumeric<USize> *_refc_ptr = _get_refcount_ptr(mem_new);
|
||||
T *_data_ptr = _get_data_ptr(mem_new);
|
||||
|
||||
new (_refc_ptr) SafeNumeric<USize>(rc); //refcount
|
||||
|
||||
_ptr = _data_ptr;
|
||||
}
|
||||
|
||||
*_get_size() = p_size;
|
||||
@@ -347,15 +407,15 @@ Error CowData<T>::resize(int p_size) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
int CowData<T>::find(const T &p_val, int p_from) const {
|
||||
int ret = -1;
|
||||
template <typename T>
|
||||
typename CowData<T>::Size CowData<T>::find(const T &p_val, Size p_from) const {
|
||||
Size ret = -1;
|
||||
|
||||
if (p_from < 0 || size() == 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (int i = p_from; i < size(); i++) {
|
||||
for (Size i = p_from; i < size(); i++) {
|
||||
if (get(i) == p_val) {
|
||||
ret = i;
|
||||
break;
|
||||
@@ -365,12 +425,42 @@ int CowData<T>::find(const T &p_val, int p_from) const {
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
typename CowData<T>::Size CowData<T>::rfind(const T &p_val, Size p_from) const {
|
||||
const Size s = size();
|
||||
|
||||
if (p_from < 0) {
|
||||
p_from = s + p_from;
|
||||
}
|
||||
if (p_from < 0 || p_from >= s) {
|
||||
p_from = s - 1;
|
||||
}
|
||||
|
||||
for (Size i = p_from; i >= 0; i--) {
|
||||
if (get(i) == p_val) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename CowData<T>::Size CowData<T>::count(const T &p_val) const {
|
||||
Size amount = 0;
|
||||
for (Size i = 0; i < size(); i++) {
|
||||
if (get(i) == p_val) {
|
||||
amount++;
|
||||
}
|
||||
}
|
||||
return amount;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void CowData<T>::_ref(const CowData *p_from) {
|
||||
_ref(*p_from);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
void CowData<T>::_ref(const CowData &p_from) {
|
||||
if (_ptr == p_from._ptr) {
|
||||
return; // self assign, do nothing.
|
||||
@@ -388,7 +478,7 @@ void CowData<T>::_ref(const CowData &p_from) {
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
CowData<T>::~CowData() {
|
||||
_unref(_ptr);
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace godot {
|
||||
* The assignment operator copy the pairs from one map to the other.
|
||||
*/
|
||||
|
||||
template <class TKey, class TValue>
|
||||
template <typename TKey, typename TValue>
|
||||
struct HashMapElement {
|
||||
HashMapElement *next = nullptr;
|
||||
HashMapElement *prev = nullptr;
|
||||
@@ -62,10 +62,10 @@ struct HashMapElement {
|
||||
data(p_key, p_value) {}
|
||||
};
|
||||
|
||||
template <class TKey, class TValue,
|
||||
class Hasher = HashMapHasherDefault,
|
||||
class Comparator = HashMapComparatorDefault<TKey>,
|
||||
class Allocator = DefaultTypedAllocator<HashMapElement<TKey, TValue>>>
|
||||
template <typename TKey, typename TValue,
|
||||
typename Hasher = HashMapHasherDefault,
|
||||
typename Comparator = HashMapComparatorDefault<TKey>,
|
||||
typename Allocator = DefaultTypedAllocator<HashMapElement<TKey, TValue>>>
|
||||
class HashMap {
|
||||
public:
|
||||
const uint32_t MIN_CAPACITY_INDEX = 2; // Use a prime.
|
||||
|
||||
@@ -48,9 +48,9 @@ namespace godot {
|
||||
*
|
||||
*/
|
||||
|
||||
template <class TKey,
|
||||
class Hasher = HashMapHasherDefault,
|
||||
class Comparator = HashMapComparatorDefault<TKey>>
|
||||
template <typename TKey,
|
||||
typename Hasher = HashMapHasherDefault,
|
||||
typename Comparator = HashMapComparatorDefault<TKey>>
|
||||
class HashSet {
|
||||
public:
|
||||
static constexpr uint32_t MIN_CAPACITY_INDEX = 2; // Use a prime.
|
||||
|
||||
@@ -253,7 +253,7 @@ static _FORCE_INLINE_ uint32_t hash_djb2_one_float(double p_in, uint32_t p_prev
|
||||
return ((p_prev << 5) + p_prev) + hash_one_uint64(u.i);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
static _FORCE_INLINE_ uint32_t hash_make_uint32_t(T p_in) {
|
||||
union {
|
||||
T t;
|
||||
@@ -286,7 +286,7 @@ static _FORCE_INLINE_ uint64_t hash_djb2_one_64(uint64_t p_in, uint64_t p_prev =
|
||||
return ((p_prev << 5) + p_prev) ^ p_in;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
static _FORCE_INLINE_ uint64_t hash_make_uint64_t(T p_in) {
|
||||
union {
|
||||
T t;
|
||||
@@ -298,15 +298,15 @@ static _FORCE_INLINE_ uint64_t hash_make_uint64_t(T p_in) {
|
||||
return _u._u64;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
class Ref;
|
||||
|
||||
struct HashMapHasherDefault {
|
||||
// Generic hash function for any type.
|
||||
template <class T>
|
||||
template <typename T>
|
||||
static _FORCE_INLINE_ uint32_t hash(const T *p_pointer) { return hash_one_uint64((uint64_t)p_pointer); }
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
static _FORCE_INLINE_ uint32_t hash(const Ref<T> &p_ref) { return hash_one_uint64((uint64_t)p_ref.operator->()); }
|
||||
|
||||
static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); }
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
namespace godot {
|
||||
|
||||
template <class T, class A = DefaultAllocator>
|
||||
template <typename T, typename A = DefaultAllocator>
|
||||
class List {
|
||||
struct _Data;
|
||||
|
||||
@@ -410,7 +410,7 @@ public:
|
||||
/**
|
||||
* find an element in the list,
|
||||
*/
|
||||
template <class T_v>
|
||||
template <typename T_v>
|
||||
Element *find(const T_v &p_val) {
|
||||
Element *it = front();
|
||||
while (it) {
|
||||
@@ -646,7 +646,7 @@ public:
|
||||
sort_custom<Comparator<T>>();
|
||||
}
|
||||
|
||||
template <class C>
|
||||
template <typename C>
|
||||
void sort_custom_inplace() {
|
||||
if (size() < 2) {
|
||||
return;
|
||||
@@ -693,7 +693,7 @@ public:
|
||||
_data->last = to;
|
||||
}
|
||||
|
||||
template <class C>
|
||||
template <typename C>
|
||||
struct AuxiliaryComparator {
|
||||
C compare;
|
||||
_FORCE_INLINE_ bool operator()(const Element *a, const Element *b) const {
|
||||
@@ -701,7 +701,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <class C>
|
||||
template <typename C>
|
||||
void sort_custom() {
|
||||
// this version uses auxiliary memory for speed.
|
||||
// if you don't want to use auxiliary memory, use the in_place version
|
||||
|
||||
@@ -31,10 +31,10 @@
|
||||
#ifndef GODOT_LOCAL_VECTOR_HPP
|
||||
#define GODOT_LOCAL_VECTOR_HPP
|
||||
|
||||
#include "godot_cpp/core/error_macros.hpp"
|
||||
#include "godot_cpp/core/memory.hpp"
|
||||
#include "godot_cpp/templates/sort_array.hpp"
|
||||
#include "godot_cpp/templates/vector.hpp"
|
||||
#include <godot_cpp/core/error_macros.hpp>
|
||||
#include <godot_cpp/core/memory.hpp>
|
||||
#include <godot_cpp/templates/sort_array.hpp>
|
||||
#include <godot_cpp/templates/vector.hpp>
|
||||
|
||||
#include <initializer_list>
|
||||
#include <type_traits>
|
||||
@@ -43,7 +43,7 @@ namespace godot {
|
||||
|
||||
// If tight, it grows strictly as much as needed.
|
||||
// Otherwise, it grows exponentially (the default and what you want in most cases).
|
||||
template <class T, class U = uint32_t, bool force_trivial = false, bool tight = false>
|
||||
template <typename T, typename U = uint32_t, bool force_trivial = false, bool tight = false>
|
||||
class LocalVector {
|
||||
private:
|
||||
U count = 0;
|
||||
@@ -257,7 +257,7 @@ public:
|
||||
return -1;
|
||||
}
|
||||
|
||||
template <class C>
|
||||
template <typename C>
|
||||
void sort_custom() {
|
||||
U len = count;
|
||||
if (len == 0) {
|
||||
@@ -331,7 +331,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class U = uint32_t, bool force_trivial = false>
|
||||
template <typename T, typename U = uint32_t, bool force_trivial = false>
|
||||
using TightLocalVector = LocalVector<T, U, force_trivial, true>;
|
||||
|
||||
} // namespace godot
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
namespace godot {
|
||||
|
||||
template <class F, class S>
|
||||
template <typename F, typename S>
|
||||
struct Pair {
|
||||
F first;
|
||||
S second;
|
||||
@@ -49,17 +49,17 @@ struct Pair {
|
||||
}
|
||||
};
|
||||
|
||||
template <class F, class S>
|
||||
template <typename F, typename S>
|
||||
bool operator==(const Pair<F, S> &pair, const Pair<F, S> &other) {
|
||||
return (pair.first == other.first) && (pair.second == other.second);
|
||||
}
|
||||
|
||||
template <class F, class S>
|
||||
template <typename F, typename S>
|
||||
bool operator!=(const Pair<F, S> &pair, const Pair<F, S> &other) {
|
||||
return (pair.first != other.first) || (pair.second != other.second);
|
||||
}
|
||||
|
||||
template <class F, class S>
|
||||
template <typename F, typename S>
|
||||
struct PairSort {
|
||||
bool operator()(const Pair<F, S> &A, const Pair<F, S> &B) const {
|
||||
if (A.first != B.first) {
|
||||
@@ -69,7 +69,7 @@ struct PairSort {
|
||||
}
|
||||
};
|
||||
|
||||
template <class K, class V>
|
||||
template <typename K, typename V>
|
||||
struct KeyValue {
|
||||
const K key;
|
||||
V value;
|
||||
@@ -85,17 +85,17 @@ struct KeyValue {
|
||||
}
|
||||
};
|
||||
|
||||
template <class K, class V>
|
||||
template <typename K, typename V>
|
||||
bool operator==(const KeyValue<K, V> &pair, const KeyValue<K, V> &other) {
|
||||
return (pair.key == other.key) && (pair.value == other.value);
|
||||
}
|
||||
|
||||
template <class K, class V>
|
||||
template <typename K, typename V>
|
||||
bool operator!=(const KeyValue<K, V> &pair, const KeyValue<K, V> &other) {
|
||||
return (pair.key != other.key) || (pair.value != other.value);
|
||||
}
|
||||
|
||||
template <class K, class V>
|
||||
template <typename K, typename V>
|
||||
struct KeyValueSort {
|
||||
bool operator()(const KeyValue<K, V> &A, const KeyValue<K, V> &B) const {
|
||||
return A.key < B.key;
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace godot {
|
||||
// based on the very nice implementation of rb-trees by:
|
||||
// https://web.archive.org/web/20120507164830/https://web.mit.edu/~emin/www/source_code/red_black_tree/index.html
|
||||
|
||||
template <class K, class V, class C = Comparator<K>, class A = DefaultAllocator>
|
||||
template <typename K, typename V, typename C = Comparator<K>, typename A = DefaultAllocator>
|
||||
class RBMap {
|
||||
enum Color {
|
||||
RED,
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
namespace godot {
|
||||
|
||||
template <class T, class C = Comparator<T>, class A = DefaultAllocator>
|
||||
template <typename T, typename C = Comparator<T>, typename A = DefaultAllocator>
|
||||
class RBSet {
|
||||
enum Color {
|
||||
RED,
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
namespace godot {
|
||||
|
||||
template <class T, bool THREAD_SAFE = false>
|
||||
template <typename T, bool THREAD_SAFE = false>
|
||||
class RID_Alloc {
|
||||
T **chunks = nullptr;
|
||||
uint32_t **free_list_chunks = nullptr;
|
||||
@@ -347,7 +347,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, bool THREAD_SAFE = false>
|
||||
template <typename T, bool THREAD_SAFE = false>
|
||||
class RID_PtrOwner {
|
||||
RID_Alloc<T *, THREAD_SAFE> alloc;
|
||||
|
||||
@@ -406,7 +406,7 @@ public:
|
||||
alloc(p_target_chunk_byte_size) {}
|
||||
};
|
||||
|
||||
template <class T, bool THREAD_SAFE = false>
|
||||
template <typename T, bool THREAD_SAFE = false>
|
||||
class RID_Owner {
|
||||
RID_Alloc<T, THREAD_SAFE> alloc;
|
||||
|
||||
|
||||
@@ -48,7 +48,16 @@ namespace godot {
|
||||
// value and, as an important benefit, you can be sure the value is properly synchronized
|
||||
// even with threads that are already running.
|
||||
|
||||
template <class T>
|
||||
// These are used in very specific areas of the engine where it's critical that these guarantees are held
|
||||
#define SAFE_NUMERIC_TYPE_PUN_GUARANTEES(m_type) \
|
||||
static_assert(sizeof(SafeNumeric<m_type>) == sizeof(m_type)); \
|
||||
static_assert(alignof(SafeNumeric<m_type>) == alignof(m_type)); \
|
||||
static_assert(std::is_trivially_destructible<std::atomic<m_type>>::value);
|
||||
#define SAFE_FLAG_TYPE_PUN_GUARANTEES \
|
||||
static_assert(sizeof(SafeFlag) == sizeof(bool)); \
|
||||
static_assert(alignof(SafeFlag) == alignof(bool));
|
||||
|
||||
template <typename T>
|
||||
class SafeNumeric {
|
||||
std::atomic<T> value;
|
||||
|
||||
@@ -123,7 +132,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
_ALWAYS_INLINE_ explicit SafeNumeric<T>(T p_value = static_cast<T>(0)) {
|
||||
_ALWAYS_INLINE_ explicit SafeNumeric(T p_value = static_cast<T>(0)) {
|
||||
set(p_value);
|
||||
}
|
||||
};
|
||||
@@ -186,7 +195,7 @@ public:
|
||||
|
||||
#else
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
class SafeNumeric {
|
||||
protected:
|
||||
T value;
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
namespace godot {
|
||||
|
||||
template <class T, class Comparator = _DefaultComparator<T>>
|
||||
template <typename T, typename Comparator = _DefaultComparator<T>>
|
||||
class SearchArray {
|
||||
public:
|
||||
Comparator compare;
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
namespace godot {
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
class SelfList {
|
||||
public:
|
||||
class List {
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace godot {
|
||||
break; \
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
struct _DefaultComparator {
|
||||
_FORCE_INLINE_ bool operator()(const T &a, const T &b) const { return (a < b); }
|
||||
};
|
||||
@@ -52,7 +52,7 @@ struct _DefaultComparator {
|
||||
#define SORT_ARRAY_VALIDATE_ENABLED false
|
||||
#endif
|
||||
|
||||
template <class T, class Comparator = _DefaultComparator<T>, bool Validate = SORT_ARRAY_VALIDATE_ENABLED>
|
||||
template <typename T, typename Comparator = _DefaultComparator<T>, bool Validate = SORT_ARRAY_VALIDATE_ENABLED>
|
||||
class SortArray {
|
||||
enum {
|
||||
INTROSORT_THRESHOLD = 16
|
||||
|
||||
@@ -52,7 +52,7 @@ class ThreadWorkPool {
|
||||
virtual ~BaseWork() = default;
|
||||
};
|
||||
|
||||
template <class C, class M, class U>
|
||||
template <typename C, typename M, typename U>
|
||||
struct Work : public BaseWork {
|
||||
C *instance;
|
||||
M method;
|
||||
@@ -94,7 +94,7 @@ class ThreadWorkPool {
|
||||
}
|
||||
|
||||
public:
|
||||
template <class C, class M, class U>
|
||||
template <typename C, typename M, typename U>
|
||||
void begin_work(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) {
|
||||
ERR_FAIL_NULL(threads); // Never initialized.
|
||||
ERR_FAIL_COND(current_work != nullptr);
|
||||
@@ -145,7 +145,7 @@ public:
|
||||
current_work = nullptr;
|
||||
}
|
||||
|
||||
template <class C, class M, class U>
|
||||
template <typename C, typename M, typename U>
|
||||
void do_work(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) {
|
||||
switch (p_elements) {
|
||||
case 0:
|
||||
|
||||
@@ -47,38 +47,42 @@
|
||||
|
||||
namespace godot {
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
class VectorWriteProxy {
|
||||
public:
|
||||
_FORCE_INLINE_ T &operator[](int p_index) {
|
||||
_FORCE_INLINE_ T &operator[](typename CowData<T>::Size p_index) {
|
||||
CRASH_BAD_INDEX(p_index, ((Vector<T> *)(this))->_cowdata.size());
|
||||
|
||||
return ((Vector<T> *)(this))->_cowdata.ptrw()[p_index];
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
class Vector {
|
||||
friend class VectorWriteProxy<T>;
|
||||
|
||||
public:
|
||||
VectorWriteProxy<T> write;
|
||||
typedef typename CowData<T>::Size Size;
|
||||
|
||||
private:
|
||||
CowData<T> _cowdata;
|
||||
|
||||
public:
|
||||
bool push_back(T p_elem);
|
||||
_FORCE_INLINE_ bool append(const T &p_elem) { return push_back(p_elem); } // alias
|
||||
_FORCE_INLINE_ bool append(const T &p_elem) { return push_back(p_elem); } //alias
|
||||
void fill(T p_elem);
|
||||
|
||||
void remove_at(int p_index) { _cowdata.remove_at(p_index); }
|
||||
void erase(const T &p_val) {
|
||||
int idx = find(p_val);
|
||||
void remove_at(Size p_index) { _cowdata.remove_at(p_index); }
|
||||
_FORCE_INLINE_ bool erase(const T &p_val) {
|
||||
Size idx = find(p_val);
|
||||
if (idx >= 0) {
|
||||
remove_at(idx);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void reverse();
|
||||
|
||||
_FORCE_INLINE_ T *ptrw() { return _cowdata.ptrw(); }
|
||||
@@ -86,37 +90,45 @@ public:
|
||||
_FORCE_INLINE_ void clear() { resize(0); }
|
||||
_FORCE_INLINE_ bool is_empty() const { return _cowdata.is_empty(); }
|
||||
|
||||
_FORCE_INLINE_ T get(int p_index) { return _cowdata.get(p_index); }
|
||||
_FORCE_INLINE_ const T &get(int p_index) const { return _cowdata.get(p_index); }
|
||||
_FORCE_INLINE_ void set(int p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); }
|
||||
_FORCE_INLINE_ int size() const { return _cowdata.size(); }
|
||||
Error resize(int p_size) { return _cowdata.resize(p_size); }
|
||||
_FORCE_INLINE_ const T &operator[](int p_index) const { return _cowdata.get(p_index); }
|
||||
Error insert(int p_pos, T p_val) { return _cowdata.insert(p_pos, p_val); }
|
||||
int find(const T &p_val, int p_from = 0) const { return _cowdata.find(p_val, p_from); }
|
||||
_FORCE_INLINE_ T get(Size p_index) { return _cowdata.get(p_index); }
|
||||
_FORCE_INLINE_ const T &get(Size p_index) const { return _cowdata.get(p_index); }
|
||||
_FORCE_INLINE_ void set(Size p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); }
|
||||
_FORCE_INLINE_ Size size() const { return _cowdata.size(); }
|
||||
Error resize(Size p_size) { return _cowdata.resize(p_size); }
|
||||
Error resize_zeroed(Size p_size) { return _cowdata.template resize<true>(p_size); }
|
||||
_FORCE_INLINE_ const T &operator[](Size p_index) const { return _cowdata.get(p_index); }
|
||||
Error insert(Size p_pos, T p_val) { return _cowdata.insert(p_pos, p_val); }
|
||||
Size find(const T &p_val, Size p_from = 0) const { return _cowdata.find(p_val, p_from); }
|
||||
Size rfind(const T &p_val, Size p_from = -1) const { return _cowdata.rfind(p_val, p_from); }
|
||||
Size count(const T &p_val) const { return _cowdata.count(p_val); }
|
||||
|
||||
void append_array(Vector<T> p_other);
|
||||
|
||||
_FORCE_INLINE_ bool has(const T &p_val) const { return find(p_val) != -1; }
|
||||
|
||||
template <class C>
|
||||
void sort_custom() {
|
||||
int len = _cowdata.size();
|
||||
void sort() {
|
||||
sort_custom<_DefaultComparator<T>>();
|
||||
}
|
||||
|
||||
template <typename Comparator, bool Validate = SORT_ARRAY_VALIDATE_ENABLED, typename... Args>
|
||||
void sort_custom(Args &&...args) {
|
||||
Size len = _cowdata.size();
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
T *data = ptrw();
|
||||
SortArray<T, C> sorter;
|
||||
SortArray<T, Comparator, Validate> sorter{ args... };
|
||||
sorter.sort(data, len);
|
||||
}
|
||||
|
||||
void sort() {
|
||||
sort_custom<_DefaultComparator<T>>();
|
||||
Size bsearch(const T &p_value, bool p_before) {
|
||||
return bsearch_custom<_DefaultComparator<T>>(p_value, p_before);
|
||||
}
|
||||
|
||||
int bsearch(const T &p_value, bool p_before) {
|
||||
SearchArray<T> search;
|
||||
template <typename Comparator, typename Value, typename... Args>
|
||||
Size bsearch_custom(const Value &p_value, bool p_before, Args &&...args) {
|
||||
SearchArray<T, Comparator> search{ args... };
|
||||
return search.bisect(ptrw(), size(), p_value, p_before);
|
||||
}
|
||||
|
||||
@@ -125,7 +137,7 @@ public:
|
||||
}
|
||||
|
||||
void ordered_insert(const T &p_val) {
|
||||
int i;
|
||||
Size i;
|
||||
for (i = 0; i < _cowdata.size(); i++) {
|
||||
if (p_val < operator[](i)) {
|
||||
break;
|
||||
@@ -140,33 +152,36 @@ public:
|
||||
|
||||
Vector<uint8_t> to_byte_array() const {
|
||||
Vector<uint8_t> ret;
|
||||
if (is_empty()) {
|
||||
return ret;
|
||||
}
|
||||
ret.resize(size() * sizeof(T));
|
||||
memcpy(ret.ptrw(), ptr(), sizeof(T) * size());
|
||||
return ret;
|
||||
}
|
||||
|
||||
Vector<T> slice(int p_begin, int p_end = INT_MAX) const {
|
||||
Vector<T> slice(Size p_begin, Size p_end = CowData<T>::MAX_INT) const {
|
||||
Vector<T> result;
|
||||
|
||||
const int s = size();
|
||||
const Size s = size();
|
||||
|
||||
int begin = Math::clamp(p_begin, -s, s);
|
||||
Size begin = CLAMP(p_begin, -s, s);
|
||||
if (begin < 0) {
|
||||
begin += s;
|
||||
}
|
||||
int end = Math::clamp(p_end, -s, s);
|
||||
Size end = CLAMP(p_end, -s, s);
|
||||
if (end < 0) {
|
||||
end += s;
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V(begin > end, result);
|
||||
|
||||
int result_size = end - begin;
|
||||
Size result_size = end - begin;
|
||||
result.resize(result_size);
|
||||
|
||||
const T *const r = ptr();
|
||||
T *const w = result.ptrw();
|
||||
for (int i = 0; i < result_size; ++i) {
|
||||
for (Size i = 0; i < result_size; ++i) {
|
||||
w[i] = r[begin + i];
|
||||
}
|
||||
|
||||
@@ -174,11 +189,11 @@ public:
|
||||
}
|
||||
|
||||
bool operator==(const Vector<T> &p_arr) const {
|
||||
int s = size();
|
||||
Size s = size();
|
||||
if (s != p_arr.size()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < s; i++) {
|
||||
for (Size i = 0; i < s; i++) {
|
||||
if (operator[](i) != p_arr[i]) {
|
||||
return false;
|
||||
}
|
||||
@@ -187,11 +202,11 @@ public:
|
||||
}
|
||||
|
||||
bool operator!=(const Vector<T> &p_arr) const {
|
||||
int s = size();
|
||||
Size s = size();
|
||||
if (s != p_arr.size()) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < s; i++) {
|
||||
for (Size i = 0; i < s; i++) {
|
||||
if (operator[](i) != p_arr[i]) {
|
||||
return true;
|
||||
}
|
||||
@@ -268,7 +283,7 @@ public:
|
||||
Error err = _cowdata.resize(p_init.size());
|
||||
ERR_FAIL_COND(err);
|
||||
|
||||
int i = 0;
|
||||
Size i = 0;
|
||||
for (const T &element : p_init) {
|
||||
_cowdata.set(i++, element);
|
||||
}
|
||||
@@ -278,28 +293,28 @@ public:
|
||||
_FORCE_INLINE_ ~Vector() {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
void Vector<T>::reverse() {
|
||||
for (int i = 0; i < size() / 2; i++) {
|
||||
for (Size i = 0; i < size() / 2; i++) {
|
||||
T *p = ptrw();
|
||||
SWAP(p[i], p[size() - i - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
void Vector<T>::append_array(Vector<T> p_other) {
|
||||
const int ds = p_other.size();
|
||||
const Size ds = p_other.size();
|
||||
if (ds == 0) {
|
||||
return;
|
||||
}
|
||||
const int bs = size();
|
||||
const Size bs = size();
|
||||
resize(bs + ds);
|
||||
for (int i = 0; i < ds; ++i) {
|
||||
for (Size i = 0; i < ds; ++i) {
|
||||
ptrw()[bs + i] = p_other[i];
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
bool Vector<T>::push_back(T p_elem) {
|
||||
Error err = resize(size() + 1);
|
||||
ERR_FAIL_COND_V(err, true);
|
||||
@@ -308,10 +323,10 @@ bool Vector<T>::push_back(T p_elem) {
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
void Vector<T>::fill(T p_elem) {
|
||||
T *p = ptrw();
|
||||
for (int i = 0; i < size(); i++) {
|
||||
for (Size i = 0; i < size(); i++) {
|
||||
p[i] = p_elem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
namespace godot {
|
||||
|
||||
template <class T, class V>
|
||||
template <typename T, typename V>
|
||||
class VMap {
|
||||
public:
|
||||
struct Pair {
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
namespace godot {
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
class VSet {
|
||||
Vector<T> _data;
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ struct _NO_DISCARD_ AABB {
|
||||
bool operator!=(const AABB &p_rval) const;
|
||||
|
||||
bool is_equal_approx(const AABB &p_aabb) const;
|
||||
bool is_finite() const;
|
||||
_FORCE_INLINE_ bool intersects(const AABB &p_aabb) const; /// Both AABBs overlap
|
||||
_FORCE_INLINE_ bool intersects_inclusive(const AABB &p_aabb) const; /// Both AABBs (or their faces) overlap
|
||||
_FORCE_INLINE_ bool encloses(const AABB &p_aabb) const; /// p_aabb is completely inside this
|
||||
@@ -201,11 +202,11 @@ inline bool AABB::encloses(const AABB &p_aabb) const {
|
||||
|
||||
return (
|
||||
(src_min.x <= dst_min.x) &&
|
||||
(src_max.x > dst_max.x) &&
|
||||
(src_max.x >= dst_max.x) &&
|
||||
(src_min.y <= dst_min.y) &&
|
||||
(src_max.y > dst_max.y) &&
|
||||
(src_max.y >= dst_max.y) &&
|
||||
(src_min.z <= dst_min.z) &&
|
||||
(src_max.z > dst_max.z));
|
||||
(src_max.z >= dst_max.z));
|
||||
}
|
||||
|
||||
Vector3 AABB::get_support(const Vector3 &p_normal) const {
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef GODOT_ARRAY_HELPERS_HPP
|
||||
#define GODOT_ARRAY_HELPERS_HPP
|
||||
|
||||
namespace godot {
|
||||
namespace helpers {
|
||||
template <typename T, typename ValueT>
|
||||
@@ -48,3 +51,5 @@ T append_all(T appendable) {
|
||||
}
|
||||
} // namespace helpers
|
||||
} // namespace godot
|
||||
|
||||
#endif // GODOT_ARRAY_HELPERS_HPP
|
||||
|
||||
@@ -128,6 +128,7 @@ struct _NO_DISCARD_ Basis {
|
||||
}
|
||||
|
||||
bool is_equal_approx(const Basis &p_basis) const;
|
||||
bool is_finite() const;
|
||||
|
||||
bool operator==(const Basis &p_matrix) const;
|
||||
bool operator!=(const Basis &p_matrix) const;
|
||||
@@ -223,7 +224,7 @@ struct _NO_DISCARD_ Basis {
|
||||
|
||||
operator Quaternion() const { return get_quaternion(); }
|
||||
|
||||
static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0));
|
||||
static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false);
|
||||
|
||||
Basis(const Quaternion &p_quaternion) { set_quaternion(p_quaternion); }
|
||||
Basis(const Quaternion &p_quaternion, const Vector3 &p_scale) { set_quaternion_scale(p_quaternion, p_scale); }
|
||||
|
||||
@@ -60,7 +60,7 @@ Callable create_callable_from_ccmp(CallableCustomMethodPointerBase *p_callable_m
|
||||
// No return value.
|
||||
//
|
||||
|
||||
template <class T, class... P>
|
||||
template <typename T, typename... P>
|
||||
class CallableCustomMethodPointer : public CallableCustomMethodPointerBase {
|
||||
struct Data {
|
||||
T *instance;
|
||||
@@ -85,7 +85,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class... P>
|
||||
template <typename T, typename... P>
|
||||
Callable create_custom_callable_function_pointer(T *p_instance, void (T::*p_method)(P...)) {
|
||||
typedef CallableCustomMethodPointer<T, P...> CCMP;
|
||||
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
|
||||
@@ -96,7 +96,7 @@ Callable create_custom_callable_function_pointer(T *p_instance, void (T::*p_meth
|
||||
// With return value.
|
||||
//
|
||||
|
||||
template <class T, class R, class... P>
|
||||
template <typename T, typename R, typename... P>
|
||||
class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase {
|
||||
struct Data {
|
||||
T *instance;
|
||||
@@ -122,7 +122,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class R, class... P>
|
||||
template <typename T, typename R, typename... P>
|
||||
Callable create_custom_callable_function_pointer(T *p_instance, R (T::*p_method)(P...)) {
|
||||
typedef CallableCustomMethodPointerRet<T, R, P...> CCMP; // Messes with memnew otherwise.
|
||||
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
|
||||
@@ -133,7 +133,7 @@ Callable create_custom_callable_function_pointer(T *p_instance, R (T::*p_method)
|
||||
// Const with return value.
|
||||
//
|
||||
|
||||
template <class T, class R, class... P>
|
||||
template <typename T, typename R, typename... P>
|
||||
class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase {
|
||||
struct Data {
|
||||
T *instance;
|
||||
@@ -159,7 +159,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class R, class... P>
|
||||
template <typename T, typename R, typename... P>
|
||||
Callable create_custom_callable_function_pointer(const T *p_instance, R (T::*p_method)(P...) const) {
|
||||
typedef CallableCustomMethodPointerRetC<T, R, P...> CCMP; // Messes with memnew otherwise.
|
||||
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
|
||||
@@ -170,7 +170,7 @@ Callable create_custom_callable_function_pointer(const T *p_instance, R (T::*p_m
|
||||
// Static method with no return value.
|
||||
//
|
||||
|
||||
template <class... P>
|
||||
template <typename... P>
|
||||
class CallableCustomStaticMethodPointer : public CallableCustomMethodPointerBase {
|
||||
struct Data {
|
||||
void (*method)(P...);
|
||||
@@ -194,7 +194,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <class... P>
|
||||
template <typename... P>
|
||||
Callable create_custom_callable_static_function_pointer(void (*p_method)(P...)) {
|
||||
typedef CallableCustomStaticMethodPointer<P...> CCMP;
|
||||
CCMP *ccmp = memnew(CCMP(p_method));
|
||||
@@ -205,7 +205,7 @@ Callable create_custom_callable_static_function_pointer(void (*p_method)(P...))
|
||||
// Static method with return value.
|
||||
//
|
||||
|
||||
template <class R, class... P>
|
||||
template <typename R, typename... P>
|
||||
class CallableCustomStaticMethodPointerRet : public CallableCustomMethodPointerBase {
|
||||
struct Data {
|
||||
R(*method)
|
||||
@@ -229,7 +229,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <class R, class... P>
|
||||
template <typename R, typename... P>
|
||||
Callable create_custom_callable_static_function_pointer(R (*p_method)(P...)) {
|
||||
typedef CallableCustomStaticMethodPointerRet<R, P...> CCMP;
|
||||
CCMP *ccmp = memnew(CCMP(p_method));
|
||||
|
||||
@@ -38,19 +38,19 @@
|
||||
|
||||
namespace godot {
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
class CharStringT;
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
class CharProxy {
|
||||
template <class TS>
|
||||
template <typename TS>
|
||||
friend class CharStringT;
|
||||
|
||||
const int _index;
|
||||
const int64_t _index;
|
||||
CowData<T> &_cowdata;
|
||||
static inline const T _null = 0;
|
||||
|
||||
_FORCE_INLINE_ CharProxy(const int &p_index, CowData<T> &p_cowdata) :
|
||||
_FORCE_INLINE_ CharProxy(const int64_t &p_index, CowData<T> &p_cowdata) :
|
||||
_index(p_index),
|
||||
_cowdata(p_cowdata) {}
|
||||
|
||||
@@ -80,7 +80,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
class CharStringT {
|
||||
friend class String;
|
||||
|
||||
@@ -90,19 +90,19 @@ class CharStringT {
|
||||
public:
|
||||
_FORCE_INLINE_ T *ptrw() { return _cowdata.ptrw(); }
|
||||
_FORCE_INLINE_ const T *ptr() const { return _cowdata.ptr(); }
|
||||
_FORCE_INLINE_ int size() const { return _cowdata.size(); }
|
||||
Error resize(int p_size) { return _cowdata.resize(p_size); }
|
||||
_FORCE_INLINE_ int64_t size() const { return _cowdata.size(); }
|
||||
Error resize(int64_t p_size) { return _cowdata.resize(p_size); }
|
||||
|
||||
_FORCE_INLINE_ T get(int p_index) const { return _cowdata.get(p_index); }
|
||||
_FORCE_INLINE_ void set(int p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); }
|
||||
_FORCE_INLINE_ const T &operator[](int p_index) const {
|
||||
_FORCE_INLINE_ T get(int64_t p_index) const { return _cowdata.get(p_index); }
|
||||
_FORCE_INLINE_ void set(int64_t p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); }
|
||||
_FORCE_INLINE_ const T &operator[](int64_t p_index) const {
|
||||
if (unlikely(p_index == _cowdata.size())) {
|
||||
return _null;
|
||||
}
|
||||
|
||||
return _cowdata.get(p_index);
|
||||
}
|
||||
_FORCE_INLINE_ CharProxy<T> operator[](int p_index) { return CharProxy<T>(p_index, _cowdata); }
|
||||
_FORCE_INLINE_ CharProxy<T> operator[](int64_t p_index) { return CharProxy<T>(p_index, _cowdata); }
|
||||
|
||||
_FORCE_INLINE_ CharStringT() {}
|
||||
_FORCE_INLINE_ CharStringT(const CharStringT<T> &p_str) { _cowdata._ref(p_str._cowdata); }
|
||||
@@ -112,7 +112,7 @@ public:
|
||||
void operator=(const T *p_cstr);
|
||||
bool operator<(const CharStringT<T> &p_right) const;
|
||||
CharStringT<T> &operator+=(T p_char);
|
||||
int length() const { return size() ? size() - 1 : 0; }
|
||||
int64_t length() const { return size() ? size() - 1 : 0; }
|
||||
const T *get_data() const;
|
||||
operator const T *() const { return get_data(); };
|
||||
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef GODOT_COLOR_NAMES_INC_HPP
|
||||
#define GODOT_COLOR_NAMES_INC_HPP
|
||||
|
||||
namespace godot {
|
||||
|
||||
// Names from https://en.wikipedia.org/wiki/X11_color_names
|
||||
@@ -189,3 +192,5 @@ static NamedColor named_colors[] = {
|
||||
};
|
||||
|
||||
} // namespace godot
|
||||
|
||||
#endif // GODOT_COLOR_NAMES_INC_HPP
|
||||
|
||||
@@ -77,6 +77,7 @@ struct _NO_DISCARD_ Plane {
|
||||
Plane operator-() const { return Plane(-normal, -d); }
|
||||
bool is_equal_approx(const Plane &p_plane) const;
|
||||
bool is_equal_approx_any_side(const Plane &p_plane) const;
|
||||
bool is_finite() const;
|
||||
|
||||
_FORCE_INLINE_ bool operator==(const Plane &p_plane) const;
|
||||
_FORCE_INLINE_ bool operator!=(const Plane &p_plane) const;
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#ifndef GODOT_QUATERNION_HPP
|
||||
#define GODOT_QUATERNION_HPP
|
||||
|
||||
#include <godot_cpp/classes/global_constants.hpp>
|
||||
#include <godot_cpp/core/math.hpp>
|
||||
#include <godot_cpp/variant/vector3.hpp>
|
||||
|
||||
@@ -47,14 +48,15 @@ struct _NO_DISCARD_ Quaternion {
|
||||
real_t components[4] = { 0, 0, 0, 1.0 };
|
||||
};
|
||||
|
||||
_FORCE_INLINE_ real_t &operator[](int idx) {
|
||||
return components[idx];
|
||||
_FORCE_INLINE_ real_t &operator[](int p_idx) {
|
||||
return components[p_idx];
|
||||
}
|
||||
_FORCE_INLINE_ const real_t &operator[](int idx) const {
|
||||
return components[idx];
|
||||
_FORCE_INLINE_ const real_t &operator[](int p_idx) const {
|
||||
return components[p_idx];
|
||||
}
|
||||
_FORCE_INLINE_ real_t length_squared() const;
|
||||
bool is_equal_approx(const Quaternion &p_quaternion) const;
|
||||
bool is_finite() const;
|
||||
real_t length() const;
|
||||
void normalize();
|
||||
Quaternion normalized() const;
|
||||
@@ -65,14 +67,13 @@ struct _NO_DISCARD_ Quaternion {
|
||||
_FORCE_INLINE_ real_t dot(const Quaternion &p_q) const;
|
||||
real_t angle_to(const Quaternion &p_to) const;
|
||||
|
||||
Vector3 get_euler_xyz() const;
|
||||
Vector3 get_euler_yxz() const;
|
||||
Vector3 get_euler() const { return get_euler_yxz(); }
|
||||
Vector3 get_euler(EulerOrder p_order = EulerOrder::EULER_ORDER_YXZ) const;
|
||||
static Quaternion from_euler(const Vector3 &p_euler);
|
||||
|
||||
Quaternion slerp(const Quaternion &p_to, const real_t &p_weight) const;
|
||||
Quaternion slerpni(const Quaternion &p_to, const real_t &p_weight) const;
|
||||
Quaternion spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const;
|
||||
Quaternion spherical_cubic_interpolate_in_time(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const;
|
||||
Quaternion slerp(const Quaternion &p_to, real_t p_weight) const;
|
||||
Quaternion slerpni(const Quaternion &p_to, real_t p_weight) const;
|
||||
Quaternion spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, real_t p_weight) const;
|
||||
Quaternion spherical_cubic_interpolate_in_time(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, real_t p_weight, real_t p_b_t, real_t p_pre_a_t, real_t p_post_b_t) const;
|
||||
|
||||
Vector3 get_axis() const;
|
||||
real_t get_angle() const;
|
||||
@@ -88,28 +89,28 @@ struct _NO_DISCARD_ Quaternion {
|
||||
void operator*=(const Quaternion &p_q);
|
||||
Quaternion operator*(const Quaternion &p_q) const;
|
||||
|
||||
_FORCE_INLINE_ Vector3 xform(const Vector3 &v) const {
|
||||
_FORCE_INLINE_ Vector3 xform(const Vector3 &p_v) const {
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND_V_MSG(!is_normalized(), v, "The quaternion must be normalized.");
|
||||
ERR_FAIL_COND_V_MSG(!is_normalized(), p_v, "The quaternion " + operator String() + " must be normalized.");
|
||||
#endif
|
||||
Vector3 u(x, y, z);
|
||||
Vector3 uv = u.cross(v);
|
||||
return v + ((uv * w) + u.cross(uv)) * ((real_t)2);
|
||||
Vector3 uv = u.cross(p_v);
|
||||
return p_v + ((uv * w) + u.cross(uv)) * ((real_t)2);
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ Vector3 xform_inv(const Vector3 &v) const {
|
||||
return inverse().xform(v);
|
||||
_FORCE_INLINE_ Vector3 xform_inv(const Vector3 &p_v) const {
|
||||
return inverse().xform(p_v);
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ void operator+=(const Quaternion &p_q);
|
||||
_FORCE_INLINE_ void operator-=(const Quaternion &p_q);
|
||||
_FORCE_INLINE_ void operator*=(const real_t &s);
|
||||
_FORCE_INLINE_ void operator/=(const real_t &s);
|
||||
_FORCE_INLINE_ Quaternion operator+(const Quaternion &q2) const;
|
||||
_FORCE_INLINE_ Quaternion operator-(const Quaternion &q2) const;
|
||||
_FORCE_INLINE_ void operator*=(real_t p_s);
|
||||
_FORCE_INLINE_ void operator/=(real_t p_s);
|
||||
_FORCE_INLINE_ Quaternion operator+(const Quaternion &p_q2) const;
|
||||
_FORCE_INLINE_ Quaternion operator-(const Quaternion &p_q2) const;
|
||||
_FORCE_INLINE_ Quaternion operator-() const;
|
||||
_FORCE_INLINE_ Quaternion operator*(const real_t &s) const;
|
||||
_FORCE_INLINE_ Quaternion operator/(const real_t &s) const;
|
||||
_FORCE_INLINE_ Quaternion operator*(real_t p_s) const;
|
||||
_FORCE_INLINE_ Quaternion operator/(real_t p_s) const;
|
||||
|
||||
_FORCE_INLINE_ bool operator==(const Quaternion &p_quaternion) const;
|
||||
_FORCE_INLINE_ bool operator!=(const Quaternion &p_quaternion) const;
|
||||
@@ -127,8 +128,6 @@ struct _NO_DISCARD_ Quaternion {
|
||||
|
||||
Quaternion(const Vector3 &p_axis, real_t p_angle);
|
||||
|
||||
Quaternion(const Vector3 &p_euler);
|
||||
|
||||
Quaternion(const Quaternion &p_q) :
|
||||
x(p_q.x),
|
||||
y(p_q.y),
|
||||
@@ -143,9 +142,9 @@ struct _NO_DISCARD_ Quaternion {
|
||||
w = p_q.w;
|
||||
}
|
||||
|
||||
Quaternion(const Vector3 &v0, const Vector3 &v1) { // Shortest arc.
|
||||
Vector3 c = v0.cross(v1);
|
||||
real_t d = v0.dot(v1);
|
||||
Quaternion(const Vector3 &p_v0, const Vector3 &p_v1) { // Shortest arc.
|
||||
Vector3 c = p_v0.cross(p_v1);
|
||||
real_t d = p_v0.dot(p_v1);
|
||||
|
||||
if (d < -1.0f + (real_t)CMP_EPSILON) {
|
||||
x = 0;
|
||||
@@ -186,25 +185,25 @@ void Quaternion::operator-=(const Quaternion &p_q) {
|
||||
w -= p_q.w;
|
||||
}
|
||||
|
||||
void Quaternion::operator*=(const real_t &s) {
|
||||
x *= s;
|
||||
y *= s;
|
||||
z *= s;
|
||||
w *= s;
|
||||
void Quaternion::operator*=(real_t p_s) {
|
||||
x *= p_s;
|
||||
y *= p_s;
|
||||
z *= p_s;
|
||||
w *= p_s;
|
||||
}
|
||||
|
||||
void Quaternion::operator/=(const real_t &s) {
|
||||
*this *= 1.0f / s;
|
||||
void Quaternion::operator/=(real_t p_s) {
|
||||
*this *= 1.0f / p_s;
|
||||
}
|
||||
|
||||
Quaternion Quaternion::operator+(const Quaternion &q2) const {
|
||||
Quaternion Quaternion::operator+(const Quaternion &p_q2) const {
|
||||
const Quaternion &q1 = *this;
|
||||
return Quaternion(q1.x + q2.x, q1.y + q2.y, q1.z + q2.z, q1.w + q2.w);
|
||||
return Quaternion(q1.x + p_q2.x, q1.y + p_q2.y, q1.z + p_q2.z, q1.w + p_q2.w);
|
||||
}
|
||||
|
||||
Quaternion Quaternion::operator-(const Quaternion &q2) const {
|
||||
Quaternion Quaternion::operator-(const Quaternion &p_q2) const {
|
||||
const Quaternion &q1 = *this;
|
||||
return Quaternion(q1.x - q2.x, q1.y - q2.y, q1.z - q2.z, q1.w - q2.w);
|
||||
return Quaternion(q1.x - p_q2.x, q1.y - p_q2.y, q1.z - p_q2.z, q1.w - p_q2.w);
|
||||
}
|
||||
|
||||
Quaternion Quaternion::operator-() const {
|
||||
@@ -212,12 +211,12 @@ Quaternion Quaternion::operator-() const {
|
||||
return Quaternion(-q2.x, -q2.y, -q2.z, -q2.w);
|
||||
}
|
||||
|
||||
Quaternion Quaternion::operator*(const real_t &s) const {
|
||||
return Quaternion(x * s, y * s, z * s, w * s);
|
||||
Quaternion Quaternion::operator*(real_t p_s) const {
|
||||
return Quaternion(x * p_s, y * p_s, z * p_s, w * p_s);
|
||||
}
|
||||
|
||||
Quaternion Quaternion::operator/(const real_t &s) const {
|
||||
return *this * (1.0f / s);
|
||||
Quaternion Quaternion::operator/(real_t p_s) const {
|
||||
return *this * (1.0f / p_s);
|
||||
}
|
||||
|
||||
bool Quaternion::operator==(const Quaternion &p_quaternion) const {
|
||||
@@ -228,7 +227,7 @@ bool Quaternion::operator!=(const Quaternion &p_quaternion) const {
|
||||
return x != p_quaternion.x || y != p_quaternion.y || z != p_quaternion.z || w != p_quaternion.w;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ Quaternion operator*(const real_t &p_real, const Quaternion &p_quaternion) {
|
||||
_FORCE_INLINE_ Quaternion operator*(real_t p_real, const Quaternion &p_quaternion) {
|
||||
return p_quaternion * p_real;
|
||||
}
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ struct _NO_DISCARD_ Rect2 {
|
||||
return size.x > 0.0f && size.y > 0.0f;
|
||||
}
|
||||
|
||||
// Returns the instersection between two Rect2s or an empty Rect2 if there is no intersection
|
||||
// Returns the intersection between two Rect2s or an empty Rect2 if there is no intersection
|
||||
inline Rect2 intersection(const Rect2 &p_rect) const {
|
||||
Rect2 new_rect = p_rect;
|
||||
|
||||
@@ -209,6 +209,7 @@ struct _NO_DISCARD_ Rect2 {
|
||||
}
|
||||
|
||||
bool is_equal_approx(const Rect2 &p_rect) const;
|
||||
bool is_finite() const;
|
||||
|
||||
bool operator==(const Rect2 &p_rect) const { return position == p_rect.position && size == p_rect.size; }
|
||||
bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; }
|
||||
|
||||
@@ -89,7 +89,7 @@ struct _NO_DISCARD_ Rect2i {
|
||||
return size.x > 0 && size.y > 0;
|
||||
}
|
||||
|
||||
// Returns the instersection between two Rect2is or an empty Rect2i if there is no intersection
|
||||
// Returns the intersection between two Rect2is or an empty Rect2i if there is no intersection
|
||||
inline Rect2i intersection(const Rect2i &p_rect) const {
|
||||
Rect2i new_rect = p_rect;
|
||||
|
||||
|
||||
@@ -99,6 +99,7 @@ struct _NO_DISCARD_ Transform2D {
|
||||
void orthonormalize();
|
||||
Transform2D orthonormalized() const;
|
||||
bool is_equal_approx(const Transform2D &p_transform) const;
|
||||
bool is_finite() const;
|
||||
|
||||
Transform2D looking_at(const Vector2 &p_target) const;
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ struct _NO_DISCARD_ Transform3D {
|
||||
void orthogonalize();
|
||||
Transform3D orthogonalized() const;
|
||||
bool is_equal_approx(const Transform3D &p_transform) const;
|
||||
bool is_finite() const;
|
||||
|
||||
bool operator==(const Transform3D &p_transform) const;
|
||||
bool operator!=(const Transform3D &p_transform) const;
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
namespace godot {
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
class TypedArray : public Array {
|
||||
public:
|
||||
_FORCE_INLINE_ void operator=(const Array &p_array) {
|
||||
@@ -44,10 +44,15 @@ public:
|
||||
_ref(p_array);
|
||||
}
|
||||
_FORCE_INLINE_ TypedArray(const Variant &p_variant) :
|
||||
Array(p_variant.operator Array(), Variant::OBJECT, T::get_class_static(), Variant()) {
|
||||
TypedArray(Array(p_variant)) {
|
||||
}
|
||||
_FORCE_INLINE_ TypedArray(const Array &p_array) :
|
||||
Array(p_array, Variant::OBJECT, T::get_class_static(), Variant()) {
|
||||
_FORCE_INLINE_ TypedArray(const Array &p_array) {
|
||||
set_typed(Variant::OBJECT, T::get_class_static(), Variant());
|
||||
if (is_same_typed(p_array)) {
|
||||
_ref(p_array);
|
||||
} else {
|
||||
assign(p_array);
|
||||
}
|
||||
}
|
||||
_FORCE_INLINE_ TypedArray() {
|
||||
set_typed(Variant::OBJECT, T::get_class_static(), Variant());
|
||||
@@ -65,10 +70,15 @@ public:
|
||||
_ref(p_array); \
|
||||
} \
|
||||
_FORCE_INLINE_ TypedArray(const Variant &p_variant) : \
|
||||
Array(p_variant.operator Array(), m_variant_type, StringName(), Variant()) { \
|
||||
TypedArray(Array(p_variant)) { \
|
||||
} \
|
||||
_FORCE_INLINE_ TypedArray(const Array &p_array) : \
|
||||
Array(p_array, m_variant_type, StringName(), Variant()) { \
|
||||
_FORCE_INLINE_ TypedArray(const Array &p_array) { \
|
||||
set_typed(m_variant_type, StringName(), Variant()); \
|
||||
if (is_same_typed(p_array)) { \
|
||||
_ref(p_array); \
|
||||
} else { \
|
||||
assign(p_array); \
|
||||
} \
|
||||
} \
|
||||
_FORCE_INLINE_ TypedArray() { \
|
||||
set_typed(m_variant_type, StringName(), Variant()); \
|
||||
|
||||
@@ -47,8 +47,6 @@ class ObjectID;
|
||||
class Variant {
|
||||
uint8_t opaque[GODOT_CPP_VARIANT_SIZE]{ 0 };
|
||||
|
||||
_FORCE_INLINE_ GDExtensionVariantPtr _native_ptr() const { return const_cast<uint8_t(*)[GODOT_CPP_VARIANT_SIZE]>(&opaque); }
|
||||
|
||||
friend class GDExtensionBinding;
|
||||
friend class MethodBind;
|
||||
|
||||
@@ -122,6 +120,7 @@ public:
|
||||
OP_NEGATE,
|
||||
OP_POSITIVE,
|
||||
OP_MODULE,
|
||||
OP_POWER,
|
||||
// bitwise
|
||||
OP_SHIFT_LEFT,
|
||||
OP_SHIFT_RIGHT,
|
||||
@@ -144,6 +143,7 @@ private:
|
||||
static GDExtensionTypeFromVariantConstructorFunc to_type_constructor[VARIANT_MAX];
|
||||
|
||||
public:
|
||||
_FORCE_INLINE_ GDExtensionVariantPtr _native_ptr() const { return const_cast<uint8_t(*)[GODOT_CPP_VARIANT_SIZE]>(&opaque); }
|
||||
Variant();
|
||||
Variant(std::nullptr_t n) :
|
||||
Variant() {}
|
||||
@@ -269,7 +269,7 @@ public:
|
||||
|
||||
void callp(const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error);
|
||||
|
||||
template <class... Args>
|
||||
template <typename... Args>
|
||||
Variant call(const StringName &method, Args... args) {
|
||||
std::array<Variant, sizeof...(args)> vargs = { args... };
|
||||
std::array<const Variant *, sizeof...(args)> argptrs;
|
||||
@@ -284,7 +284,7 @@ public:
|
||||
|
||||
static void callp_static(Variant::Type type, const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error);
|
||||
|
||||
template <class... Args>
|
||||
template <typename... Args>
|
||||
static Variant call_static(Variant::Type type, const StringName &method, Args... args) {
|
||||
std::array<Variant, sizeof...(args)> vargs = { args... };
|
||||
std::array<const Variant *, sizeof...(args)> argptrs;
|
||||
@@ -324,8 +324,6 @@ public:
|
||||
bool booleanize() const;
|
||||
String stringify() const;
|
||||
Variant duplicate(bool deep = false) const;
|
||||
static void blend(const Variant &a, const Variant &b, float c, Variant &r_dst);
|
||||
static void interpolate(const Variant &a, const Variant &b, float c, Variant &r_dst);
|
||||
|
||||
static String get_type_name(Variant::Type type);
|
||||
static bool can_convert(Variant::Type from, Variant::Type to);
|
||||
@@ -356,6 +354,12 @@ String vformat(const String &p_text, const VarArgs... p_args) {
|
||||
|
||||
#include <godot_cpp/variant/builtin_vararg_methods.hpp>
|
||||
|
||||
#ifdef REAL_T_IS_DOUBLE
|
||||
using PackedRealArray = PackedFloat64Array;
|
||||
#else
|
||||
using PackedRealArray = PackedFloat32Array;
|
||||
#endif // REAL_T_IS_DOUBLE
|
||||
|
||||
} // namespace godot
|
||||
|
||||
#endif // GODOT_VARIANT_HPP
|
||||
|
||||
@@ -123,6 +123,7 @@ struct _NO_DISCARD_ Vector2 {
|
||||
|
||||
bool is_equal_approx(const Vector2 &p_v) const;
|
||||
bool is_zero_approx() const;
|
||||
bool is_finite() const;
|
||||
|
||||
Vector2 operator+(const Vector2 &p_v) const;
|
||||
void operator+=(const Vector2 &p_v);
|
||||
|
||||
@@ -146,6 +146,7 @@ struct _NO_DISCARD_ Vector3 {
|
||||
|
||||
bool is_equal_approx(const Vector3 &p_v) const;
|
||||
bool is_zero_approx() const;
|
||||
bool is_finite() const;
|
||||
|
||||
/* Operators */
|
||||
|
||||
|
||||
@@ -55,16 +55,17 @@ struct _NO_DISCARD_ Vector4 {
|
||||
real_t z;
|
||||
real_t w;
|
||||
};
|
||||
real_t components[4] = { 0, 0, 0, 0 };
|
||||
[[deprecated("Use coord instead")]] real_t components[4];
|
||||
real_t coord[4] = { 0, 0, 0, 0 };
|
||||
};
|
||||
|
||||
_FORCE_INLINE_ real_t &operator[](const int p_axis) {
|
||||
DEV_ASSERT((unsigned int)p_axis < 4);
|
||||
return components[p_axis];
|
||||
return coord[p_axis];
|
||||
}
|
||||
_FORCE_INLINE_ const real_t &operator[](const int p_axis) const {
|
||||
DEV_ASSERT((unsigned int)p_axis < 4);
|
||||
return components[p_axis];
|
||||
return coord[p_axis];
|
||||
}
|
||||
|
||||
Vector4::Axis min_axis_index() const;
|
||||
@@ -81,6 +82,7 @@ struct _NO_DISCARD_ Vector4 {
|
||||
_FORCE_INLINE_ real_t length_squared() const;
|
||||
bool is_equal_approx(const Vector4 &p_vec4) const;
|
||||
bool is_zero_approx() const;
|
||||
bool is_finite() const;
|
||||
real_t length() const;
|
||||
void normalize();
|
||||
Vector4 normalized() const;
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
# Git hooks for Godot Engine
|
||||
|
||||
This folder contains Git hooks meant to be installed locally by Godot Engine
|
||||
contributors to make sure they comply with our requirements.
|
||||
|
||||
## List of hooks
|
||||
|
||||
- Pre-commit hook for `clang-format`: Applies `clang-format` to the staged
|
||||
files before accepting a commit; blocks the commit and generates a patch if
|
||||
the style is not respected.
|
||||
You may need to edit the file if your `clang-format` binary is not in the
|
||||
`PATH`, or if you want to enable colored output with `pygmentize`.
|
||||
- Pre-commit hook for `black`: Applies `black` to the staged Python files
|
||||
before accepting a commit.
|
||||
- Pre-commit hook for `make_rst`: Checks the class reference syntax using
|
||||
`make_rst.py`.
|
||||
|
||||
## Installation
|
||||
|
||||
Copy all the files from this folder into your `.git/hooks` folder, and make
|
||||
sure the hooks and helper scripts are executable.
|
||||
|
||||
#### Linux/MacOS
|
||||
|
||||
The hooks rely on bash scripts and tools which should be in the system `PATH`,
|
||||
so they should work out of the box on Linux/macOS.
|
||||
|
||||
#### Windows
|
||||
|
||||
##### clang-format
|
||||
- Download LLVM for Windows (version 13 or later) from
|
||||
<https://releases.llvm.org/download.html>
|
||||
- Make sure LLVM is added to the `PATH` during installation
|
||||
|
||||
##### black
|
||||
- Python installation: make sure Python is added to the `PATH`
|
||||
- Install `black` - in any console: `pip3 install black`
|
||||
@@ -1,48 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Provide the canonicalize filename (physical filename with out any symlinks)
|
||||
# like the GNU version readlink with the -f option regardless of the version of
|
||||
# readlink (GNU or BSD).
|
||||
|
||||
# This file is part of a set of unofficial pre-commit hooks available
|
||||
# at github.
|
||||
# Link: https://github.com/githubbrowser/Pre-commit-hooks
|
||||
# Contact: David Martin, david.martin.mailbox@googlemail.com
|
||||
|
||||
###########################################################
|
||||
# There should be no need to change anything below this line.
|
||||
|
||||
# Canonicalize by recursively following every symlink in every component of the
|
||||
# specified filename. This should reproduce the results of the GNU version of
|
||||
# readlink with the -f option.
|
||||
#
|
||||
# Reference: https://stackoverflow.com/questions/1055671/how-can-i-get-the-behavior-of-gnus-readlink-f-on-a-mac
|
||||
canonicalize_filename () {
|
||||
local target_file="$1"
|
||||
local physical_directory=""
|
||||
local result=""
|
||||
|
||||
# Need to restore the working directory after work.
|
||||
local working_dir="`pwd`"
|
||||
|
||||
cd -- "$(dirname -- "$target_file")"
|
||||
target_file="$(basename -- "$target_file")"
|
||||
|
||||
# Iterate down a (possible) chain of symlinks
|
||||
while [ -L "$target_file" ]
|
||||
do
|
||||
target_file="$(readlink -- "$target_file")"
|
||||
cd -- "$(dirname -- "$target_file")"
|
||||
target_file="$(basename -- "$target_file")"
|
||||
done
|
||||
|
||||
# Compute the canonicalized name by finding the physical path
|
||||
# for the directory we're in and appending the target file.
|
||||
physical_directory="`pwd -P`"
|
||||
result="$physical_directory/$target_file"
|
||||
|
||||
# restore the working directory after work.
|
||||
cd -- "$working_dir"
|
||||
|
||||
echo "$result"
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Git pre-commit hook that runs multiple hooks specified in $HOOKS.
|
||||
# Make sure this script is executable. Bypass hooks with git commit --no-verify.
|
||||
|
||||
# This file is part of a set of unofficial pre-commit hooks available
|
||||
# at github.
|
||||
# Link: https://github.com/githubbrowser/Pre-commit-hooks
|
||||
# Contact: David Martin, david.martin.mailbox@googlemail.com
|
||||
|
||||
|
||||
###########################################################
|
||||
# CONFIGURATION:
|
||||
# pre-commit hooks to be executed. They should be in the same .git/hooks/ folder
|
||||
# as this script. Hooks should return 0 if successful and nonzero to cancel the
|
||||
# commit. They are executed in the order in which they are listed.
|
||||
#HOOKS="pre-commit-compile pre-commit-uncrustify"
|
||||
HOOKS="pre-commit-clang-format pre-commit-black"
|
||||
###########################################################
|
||||
# There should be no need to change anything below this line.
|
||||
|
||||
. "$(dirname -- "$0")/canonicalize_filename.sh"
|
||||
|
||||
# exit on error
|
||||
set -e
|
||||
|
||||
# Absolute path to this script, e.g. /home/user/bin/foo.sh
|
||||
SCRIPT="$(canonicalize_filename "$0")"
|
||||
|
||||
# Absolute path this script is in, thus /home/user/bin
|
||||
SCRIPTPATH="$(dirname -- "$SCRIPT")"
|
||||
|
||||
|
||||
for hook in $HOOKS
|
||||
do
|
||||
echo "Running hook: $hook"
|
||||
# run hook if it exists
|
||||
# if it returns with nonzero exit with 1 and thus abort the commit
|
||||
if [ -f "$SCRIPTPATH/$hook" ]; then
|
||||
"$SCRIPTPATH/$hook"
|
||||
if [ $? != 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Error: file $hook not found."
|
||||
echo "Aborting commit. Make sure the hook is in $SCRIPTPATH and executable."
|
||||
echo "You can disable it by removing it from the list in $SCRIPT."
|
||||
echo "You can skip all pre-commit hooks with --no-verify (not recommended)."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
@@ -1,202 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# git pre-commit hook that runs a black stylecheck.
|
||||
# Based on pre-commit-clang-format.
|
||||
|
||||
##################################################################
|
||||
# SETTINGS
|
||||
# Set path to black binary.
|
||||
BLACK=`which black 2>/dev/null`
|
||||
BLACK_OPTIONS="-l 120"
|
||||
|
||||
# Remove any older patches from previous commits. Set to true or false.
|
||||
DELETE_OLD_PATCHES=false
|
||||
|
||||
# File types to parse.
|
||||
FILE_NAMES="SConstruct SCsub"
|
||||
FILE_EXTS=".py"
|
||||
|
||||
# Use pygmentize instead of cat to parse diff with highlighting.
|
||||
# Install it with `pip install pygments` (Linux) or `easy_install Pygments` (Mac)
|
||||
PYGMENTIZE=`which pygmentize 2>/dev/null`
|
||||
if [ ! -z "$PYGMENTIZE" ]; then
|
||||
READER="pygmentize -l diff"
|
||||
else
|
||||
READER=cat
|
||||
fi
|
||||
|
||||
# Path to zenity
|
||||
ZENITY=`which zenity 2>/dev/null`
|
||||
|
||||
# Path to xmessage
|
||||
XMSG=`which xmessage 2>/dev/null`
|
||||
|
||||
# Path to powershell (Windows only)
|
||||
PWSH=`which powershell 2>/dev/null`
|
||||
|
||||
##################################################################
|
||||
# There should be no need to change anything below this line.
|
||||
|
||||
. "$(dirname -- "$0")/canonicalize_filename.sh"
|
||||
|
||||
# exit on error
|
||||
set -e
|
||||
|
||||
# check whether the given file matches any of the set extensions
|
||||
matches_name_or_extension() {
|
||||
local filename=$(basename "$1")
|
||||
local extension=".${filename##*.}"
|
||||
|
||||
for name in $FILE_NAMES; do [[ "$name" == "$filename" ]] && return 0; done
|
||||
for ext in $FILE_EXTS; do [[ "$ext" == "$extension" ]] && return 0; done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# necessary check for initial commit
|
||||
if git rev-parse --verify HEAD >/dev/null 2>&1 ; then
|
||||
against=HEAD
|
||||
else
|
||||
# Initial commit: diff against an empty tree object
|
||||
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
|
||||
fi
|
||||
|
||||
if [ ! -x "$BLACK" ] ; then
|
||||
if [ ! -t 1 ] ; then
|
||||
if [ -x "$ZENITY" ] ; then
|
||||
$ZENITY --error --title="Error" --text="Error: black executable not found."
|
||||
exit 1
|
||||
elif [ -x "$XMSG" ] ; then
|
||||
$XMSG -center -title "Error" "Error: black executable not found."
|
||||
exit 1
|
||||
elif [ \( \( "$OSTYPE" = "msys" \) -o \( "$OSTYPE" = "win32" \) \) -a \( -x "$PWSH" \) ]; then
|
||||
winmessage="$(canonicalize_filename "./.git/hooks/winmessage.ps1")"
|
||||
$PWSH -noprofile -executionpolicy bypass -file "$winmessage" -center -title "Error" --text "Error: black executable not found."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
printf "Error: black executable not found.\n"
|
||||
printf "Set the correct path in $(canonicalize_filename "$0").\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# create a random filename to store our generated patch
|
||||
prefix="pre-commit-black"
|
||||
suffix="$(date +%s)"
|
||||
patch="/tmp/$prefix-$suffix.patch"
|
||||
|
||||
# clean up any older black patches
|
||||
$DELETE_OLD_PATCHES && rm -f /tmp/$prefix*.patch
|
||||
|
||||
# create one patch containing all changes to the files
|
||||
git diff-index --cached --diff-filter=ACMR --name-only $against -- | while read file;
|
||||
do
|
||||
# ignore thirdparty files
|
||||
if grep -q "thirdparty" <<< $file; then
|
||||
continue;
|
||||
fi
|
||||
|
||||
# ignore file if not one of the names or extensions we handle
|
||||
if ! matches_name_or_extension "$file"; then
|
||||
continue;
|
||||
fi
|
||||
|
||||
# format our file with black, create a patch with diff and append it to our $patch
|
||||
# The sed call is necessary to transform the patch from
|
||||
# --- $file timestamp
|
||||
# +++ $file timestamp
|
||||
# to both lines working on the same file and having a/ and b/ prefix.
|
||||
# Else it can not be applied with 'git apply'.
|
||||
"$BLACK" "$BLACK_OPTIONS" --diff "$file" | \
|
||||
sed -e "1s|--- |--- a/|" -e "2s|+++ |+++ b/|" >> "$patch"
|
||||
done
|
||||
|
||||
# if no patch has been generated all is ok, clean up the file stub and exit
|
||||
if [ ! -s "$patch" ] ; then
|
||||
printf "Files in this commit comply with the black formatter rules.\n"
|
||||
rm -f "$patch"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# a patch has been created, notify the user and exit
|
||||
printf "\nThe following differences were found between the code to commit "
|
||||
printf "and the black formatter rules:\n\n"
|
||||
|
||||
if [ -t 1 ] ; then
|
||||
$READER "$patch"
|
||||
printf "\n"
|
||||
# Allows us to read user input below, assigns stdin to keyboard
|
||||
exec < /dev/tty
|
||||
terminal="1"
|
||||
else
|
||||
cat "$patch"
|
||||
printf "\n"
|
||||
# Allows non zero zenity/powershell output
|
||||
set +e
|
||||
terminal="0"
|
||||
fi
|
||||
|
||||
while true; do
|
||||
if [ $terminal = "0" ] ; then
|
||||
if [ -x "$ZENITY" ] ; then
|
||||
choice=$($ZENITY --text-info --filename="$patch" --width=800 --height=600 --title="Do you want to apply that patch?" --ok-label="Apply" --cancel-label="Do not apply" --extra-button="Apply and stage")
|
||||
if [ "$?" = "0" ] ; then
|
||||
yn="Y"
|
||||
else
|
||||
if [ "$choice" = "Apply and stage" ] ; then
|
||||
yn="S"
|
||||
else
|
||||
yn="N"
|
||||
fi
|
||||
fi
|
||||
elif [ -x "$XMSG" ] ; then
|
||||
$XMSG -file "$patch" -buttons "Apply":100,"Apply and stage":200,"Do not apply":0 -center -default "Do not apply" -geometry 800x600 -title "Do you want to apply that patch?"
|
||||
choice=$?
|
||||
if [ "$choice" = "100" ] ; then
|
||||
yn="Y"
|
||||
elif [ "$choice" = "200" ] ; then
|
||||
yn="S"
|
||||
else
|
||||
yn="N"
|
||||
fi
|
||||
elif [ \( \( "$OSTYPE" = "msys" \) -o \( "$OSTYPE" = "win32" \) \) -a \( -x "$PWSH" \) ]; then
|
||||
winmessage="$(canonicalize_filename "./.git/hooks/winmessage.ps1")"
|
||||
$PWSH -noprofile -executionpolicy bypass -file "$winmessage" -file "$patch" -buttons "Apply":100,"Apply and stage":200,"Do not apply":0 -center -default "Do not apply" -geometry 800x600 -title "Do you want to apply that patch?"
|
||||
choice=$?
|
||||
if [ "$choice" = "100" ] ; then
|
||||
yn="Y"
|
||||
elif [ "$choice" = "200" ] ; then
|
||||
yn="S"
|
||||
else
|
||||
yn="N"
|
||||
fi
|
||||
else
|
||||
printf "Error: zenity, xmessage, or powershell executable not found.\n"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
read -p "Do you want to apply that patch (Y - Apply, N - Do not apply, S - Apply and stage files)? [Y/N/S] " yn
|
||||
fi
|
||||
case $yn in
|
||||
[Yy] ) git apply $patch;
|
||||
printf "The patch was applied. You can now stage the changes and commit again.\n\n";
|
||||
break
|
||||
;;
|
||||
[Nn] ) printf "\nYou can apply these changes with:\n git apply $patch\n";
|
||||
printf "(may need to be called from the root directory of your repository)\n";
|
||||
printf "Aborting commit. Apply changes and commit again or skip checking with";
|
||||
printf " --no-verify (not recommended).\n\n";
|
||||
break
|
||||
;;
|
||||
[Ss] ) git apply $patch;
|
||||
git diff-index --cached --diff-filter=ACMR --name-only $against -- | while read file;
|
||||
do git add $file;
|
||||
done
|
||||
printf "The patch was applied and the changed files staged. You can now commit.\n\n";
|
||||
break
|
||||
;;
|
||||
* ) echo "Please answer yes or no."
|
||||
;;
|
||||
esac
|
||||
done
|
||||
exit 1 # we don't commit in any case
|
||||
@@ -1,242 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# git pre-commit hook that runs a clang-format stylecheck.
|
||||
# Features:
|
||||
# - abort commit when commit does not comply with the style guidelines
|
||||
# - create a patch of the proposed style changes
|
||||
# Modifications for clang-format by rene.milk@wwu.de
|
||||
|
||||
# This file is part of a set of unofficial pre-commit hooks available
|
||||
# at github.
|
||||
# Link: https://github.com/githubbrowser/Pre-commit-hooks
|
||||
# Contact: David Martin, david.martin.mailbox@googlemail.com
|
||||
|
||||
# Some quality of life modifications made for Godot Engine.
|
||||
|
||||
##################################################################
|
||||
# SETTINGS
|
||||
# Set path to clang-format binary.
|
||||
CLANG_FORMAT=`which clang-format 2>/dev/null`
|
||||
|
||||
# Remove any older patches from previous commits. Set to true or false.
|
||||
DELETE_OLD_PATCHES=false
|
||||
|
||||
# Only parse files with the extensions in FILE_EXTS. Set to true or false.
|
||||
# If false every changed file in the commit will be parsed with clang-format.
|
||||
# If true only files matching one of the extensions are parsed with clang-format.
|
||||
PARSE_EXTS=true
|
||||
|
||||
# File types to parse. Only effective when PARSE_EXTS is true.
|
||||
FILE_EXTS=".c .h .cpp .hpp .cc .hh .cxx .m .mm .inc .java .glsl"
|
||||
|
||||
# Use pygmentize instead of cat to parse diff with highlighting.
|
||||
# Install it with `pip install pygments` (Linux) or `easy_install Pygments` (Mac)
|
||||
PYGMENTIZE=`which pygmentize 2>/dev/null`
|
||||
if [ ! -z "$PYGMENTIZE" ]; then
|
||||
READER="pygmentize -l diff"
|
||||
else
|
||||
READER=cat
|
||||
fi
|
||||
|
||||
# Path to zenity
|
||||
ZENITY=`which zenity 2>/dev/null`
|
||||
|
||||
# Path to xmessage
|
||||
XMSG=`which xmessage 2>/dev/null`
|
||||
|
||||
# Path to powershell (Windows only)
|
||||
PWSH=`which powershell 2>/dev/null`
|
||||
|
||||
##################################################################
|
||||
# There should be no need to change anything below this line.
|
||||
|
||||
. "$(dirname -- "$0")/canonicalize_filename.sh"
|
||||
|
||||
# exit on error
|
||||
set -e
|
||||
|
||||
# check whether the given file matches any of the set extensions
|
||||
matches_extension() {
|
||||
local filename=$(basename "$1")
|
||||
local extension=".${filename##*.}"
|
||||
local ext
|
||||
|
||||
for ext in $FILE_EXTS; do [[ "$ext" == "$extension" ]] && return 0; done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# necessary check for initial commit
|
||||
if git rev-parse --verify HEAD >/dev/null 2>&1 ; then
|
||||
against=HEAD
|
||||
else
|
||||
# Initial commit: diff against an empty tree object
|
||||
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
|
||||
fi
|
||||
|
||||
# To get consistent formatting, we recommend contributors to use the same
|
||||
# clang-format version as CI.
|
||||
RECOMMENDED_CLANG_FORMAT_MAJOR_MIN="12"
|
||||
RECOMMENDED_CLANG_FORMAT_MAJOR_MAX="13"
|
||||
|
||||
if [ ! -x "$CLANG_FORMAT" ] ; then
|
||||
message="Error: clang-format executable not found. Please install clang-format $RECOMMENDED_CLANG_FORMAT_MAJOR_MAX."
|
||||
|
||||
if [ ! -t 1 ] ; then
|
||||
if [ -x "$ZENITY" ] ; then
|
||||
$ZENITY --error --title="Error" --text="$message"
|
||||
exit 1
|
||||
elif [ -x "$XMSG" ] ; then
|
||||
$XMSG -center -title "Error" "$message"
|
||||
exit 1
|
||||
elif [ \( \( "$OSTYPE" = "msys" \) -o \( "$OSTYPE" = "win32" \) \) -a \( -x "$PWSH" \) ]; then
|
||||
winmessage="$(canonicalize_filename "./.git/hooks/winmessage.ps1")"
|
||||
$PWSH -noprofile -executionpolicy bypass -file "$winmessage" -center -title "Error" --text "$message"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
printf "$message\n"
|
||||
printf "Set the correct path in $(canonicalize_filename "$0").\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# The returned string can be inconsistent depending on where clang-format comes from.
|
||||
# Example output strings reported by `clang-format --version`:
|
||||
# - Ubuntu: "Ubuntu clang-format version 11.0.0-2"
|
||||
# - Fedora: "clang-format version 11.0.0 (Fedora 11.0.0-2.fc33)"
|
||||
CLANG_FORMAT_VERSION="$(clang-format --version | sed "s/[^0-9\.]*\([0-9\.]*\).*/\1/")"
|
||||
CLANG_FORMAT_MAJOR="$(echo "$CLANG_FORMAT_VERSION" | cut -d. -f1)"
|
||||
|
||||
if [[ "$CLANG_FORMAT_MAJOR" -lt "$RECOMMENDED_CLANG_FORMAT_MAJOR_MIN" || "$CLANG_FORMAT_MAJOR" -gt "$RECOMMENDED_CLANG_FORMAT_MAJOR_MAX" ]]; then
|
||||
echo "Warning: Your clang-format binary is the wrong version ($CLANG_FORMAT_VERSION, expected between $RECOMMENDED_CLANG_FORMAT_MAJOR_MIN and $RECOMMENDED_CLANG_FORMAT_MAJOR_MAX)."
|
||||
echo " Consider upgrading or downgrading clang-format as formatting may not be applied correctly."
|
||||
fi
|
||||
|
||||
# create a random filename to store our generated patch
|
||||
prefix="pre-commit-clang-format"
|
||||
suffix="$(date +%s)"
|
||||
patch="/tmp/$prefix-$suffix.patch"
|
||||
|
||||
# clean up any older clang-format patches
|
||||
$DELETE_OLD_PATCHES && rm -f /tmp/$prefix*.patch
|
||||
|
||||
# create one patch containing all changes to the files
|
||||
git diff-index --cached --diff-filter=ACMR --name-only $against -- | while read file;
|
||||
do
|
||||
# ignore thirdparty files
|
||||
if grep -q "thirdparty" <<< $file; then
|
||||
continue;
|
||||
fi
|
||||
if grep -q "platform/android/java/lib/src/com" <<< $file; then
|
||||
continue;
|
||||
fi
|
||||
if grep -q "\-so_wrap." <<< $file; then
|
||||
continue;
|
||||
fi
|
||||
|
||||
# ignore file if we do check for file extensions and the file
|
||||
# does not match any of the extensions specified in $FILE_EXTS
|
||||
if $PARSE_EXTS && ! matches_extension "$file"; then
|
||||
continue;
|
||||
fi
|
||||
|
||||
# clang-format our sourcefile, create a patch with diff and append it to our $patch
|
||||
# The sed call is necessary to transform the patch from
|
||||
# --- $file timestamp
|
||||
# +++ - timestamp
|
||||
# to both lines working on the same file and having a/ and b/ prefix.
|
||||
# Else it can not be applied with 'git apply'.
|
||||
"$CLANG_FORMAT" -style=file "$file" --Wno-error=unknown | \
|
||||
diff -u "$file" - | \
|
||||
sed -e "1s|--- |--- a/|" -e "2s|+++ -|+++ b/$file|" >> "$patch"
|
||||
done
|
||||
|
||||
# if no patch has been generated all is ok, clean up the file stub and exit
|
||||
if [ ! -s "$patch" ] ; then
|
||||
printf "Files in this commit comply with the clang-format rules.\n"
|
||||
rm -f "$patch"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# a patch has been created, notify the user and exit
|
||||
printf "\nThe following differences were found between the code to commit "
|
||||
printf "and the clang-format rules:\n\n"
|
||||
|
||||
if [ -t 1 ] ; then
|
||||
$READER "$patch"
|
||||
printf "\n"
|
||||
# Allows us to read user input below, assigns stdin to keyboard
|
||||
exec < /dev/tty
|
||||
terminal="1"
|
||||
else
|
||||
cat "$patch"
|
||||
printf "\n"
|
||||
# Allows non zero zenity/powershell output
|
||||
set +e
|
||||
terminal="0"
|
||||
fi
|
||||
|
||||
while true; do
|
||||
if [ $terminal = "0" ] ; then
|
||||
if [ -x "$ZENITY" ] ; then
|
||||
choice=$($ZENITY --text-info --filename="$patch" --width=800 --height=600 --title="Do you want to apply that patch?" --ok-label="Apply" --cancel-label="Do not apply" --extra-button="Apply and stage")
|
||||
if [ "$?" = "0" ] ; then
|
||||
yn="Y"
|
||||
else
|
||||
if [ "$choice" = "Apply and stage" ] ; then
|
||||
yn="S"
|
||||
else
|
||||
yn="N"
|
||||
fi
|
||||
fi
|
||||
elif [ -x "$XMSG" ] ; then
|
||||
$XMSG -file "$patch" -buttons "Apply":100,"Apply and stage":200,"Do not apply":0 -center -default "Do not apply" -geometry 800x600 -title "Do you want to apply that patch?"
|
||||
choice=$?
|
||||
if [ "$choice" = "100" ] ; then
|
||||
yn="Y"
|
||||
elif [ "$choice" = "200" ] ; then
|
||||
yn="S"
|
||||
else
|
||||
yn="N"
|
||||
fi
|
||||
elif [ \( \( "$OSTYPE" = "msys" \) -o \( "$OSTYPE" = "win32" \) \) -a \( -x "$PWSH" \) ]; then
|
||||
winmessage="$(canonicalize_filename "./.git/hooks/winmessage.ps1")"
|
||||
$PWSH -noprofile -executionpolicy bypass -file "$winmessage" -file "$patch" -buttons "Apply":100,"Apply and stage":200,"Do not apply":0 -center -default "Do not apply" -geometry 800x600 -title "Do you want to apply that patch?"
|
||||
choice=$?
|
||||
if [ "$choice" = "100" ] ; then
|
||||
yn="Y"
|
||||
elif [ "$choice" = "200" ] ; then
|
||||
yn="S"
|
||||
else
|
||||
yn="N"
|
||||
fi
|
||||
else
|
||||
printf "Error: zenity, xmessage, or powershell executable not found.\n"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
read -p "Do you want to apply that patch (Y - Apply, N - Do not apply, S - Apply and stage files)? [Y/N/S] " yn
|
||||
fi
|
||||
case $yn in
|
||||
[Yy] ) git apply $patch;
|
||||
printf "The patch was applied. You can now stage the changes and commit again.\n\n";
|
||||
break
|
||||
;;
|
||||
[Nn] ) printf "\nYou can apply these changes with:\n git apply $patch\n";
|
||||
printf "(may need to be called from the root directory of your repository)\n";
|
||||
printf "Aborting commit. Apply changes and commit again or skip checking with";
|
||||
printf " --no-verify (not recommended).\n\n";
|
||||
break
|
||||
;;
|
||||
[Ss] ) git apply $patch;
|
||||
git diff-index --cached --diff-filter=ACMR --name-only $against -- | while read file;
|
||||
do git add $file;
|
||||
done
|
||||
printf "The patch was applied and the changed files staged. You can now commit.\n\n";
|
||||
break
|
||||
;;
|
||||
* ) echo "Please answer yes or no."
|
||||
;;
|
||||
esac
|
||||
done
|
||||
exit 1 # we don't commit in any case
|
||||
@@ -1,103 +0,0 @@
|
||||
Param (
|
||||
[string]$file = "",
|
||||
[string]$text = "",
|
||||
[string]$buttons = "OK:0",
|
||||
[string]$default = "",
|
||||
[switch]$nearmouse = $false,
|
||||
[switch]$center = $false,
|
||||
[string]$geometry = "",
|
||||
[int32]$timeout = 0,
|
||||
[string]$title = "Message"
|
||||
)
|
||||
Add-Type -assembly System.Windows.Forms
|
||||
|
||||
$global:Result = 0
|
||||
|
||||
$main_form = New-Object System.Windows.Forms.Form
|
||||
$main_form.Text = $title
|
||||
|
||||
$geometry_data = $geometry.Split("+")
|
||||
if ($geometry_data.Length -ge 1) {
|
||||
$size_data = $geometry_data[0].Split("x")
|
||||
if ($size_data.Length -eq 2) {
|
||||
$main_form.Width = $size_data[0]
|
||||
$main_form.Height = $size_data[1]
|
||||
}
|
||||
}
|
||||
if ($geometry_data.Length -eq 3) {
|
||||
$main_form.StartPosition = [System.Windows.Forms.FormStartPosition]::Manual
|
||||
$main_form.Location = New-Object System.Drawing.Point($geometry_data[1], $geometry_data[2])
|
||||
}
|
||||
if ($nearmouse) {
|
||||
$main_form.StartPosition = [System.Windows.Forms.FormStartPosition]::Manual
|
||||
$main_form.Location = System.Windows.Forms.Cursor.Position
|
||||
}
|
||||
if ($center) {
|
||||
$main_form.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen
|
||||
}
|
||||
|
||||
$main_form.SuspendLayout()
|
||||
|
||||
$button_panel = New-Object System.Windows.Forms.FlowLayoutPanel
|
||||
$button_panel.SuspendLayout()
|
||||
$button_panel.FlowDirection = [System.Windows.Forms.FlowDirection]::RightToLeft
|
||||
$button_panel.Dock = [System.Windows.Forms.DockStyle]::Bottom
|
||||
$button_panel.Autosize = $true
|
||||
|
||||
if ($file -ne "") {
|
||||
$text = [IO.File]::ReadAllText($file).replace("`n", "`r`n")
|
||||
}
|
||||
|
||||
if ($text -ne "") {
|
||||
$text_box = New-Object System.Windows.Forms.TextBox
|
||||
$text_box.Multiline = $true
|
||||
$text_box.ReadOnly = $true
|
||||
$text_box.Autosize = $true
|
||||
$text_box.Text = $text
|
||||
$text_box.Select(0,0)
|
||||
$text_box.Dock = [System.Windows.Forms.DockStyle]::Fill
|
||||
$main_form.Controls.Add($text_box)
|
||||
}
|
||||
|
||||
$buttons_array = $buttons.Split(",")
|
||||
foreach ($button in $buttons_array) {
|
||||
$button_data = $button.Split(":")
|
||||
$button_ctl = New-Object System.Windows.Forms.Button
|
||||
if ($button_data.Length -eq 2) {
|
||||
$button_ctl.Tag = $button_data[1]
|
||||
} else {
|
||||
$button_ctl.Tag = 100 + $buttons_array.IndexOf($button)
|
||||
}
|
||||
if ($default -eq $button_data[0]) {
|
||||
$main_form.AcceptButton = $button_ctl
|
||||
}
|
||||
$button_ctl.Autosize = $true
|
||||
$button_ctl.Text = $button_data[0]
|
||||
$button_ctl.Add_Click(
|
||||
{
|
||||
Param($sender)
|
||||
$global:Result = $sender.Tag
|
||||
$main_form.Close()
|
||||
}
|
||||
)
|
||||
$button_panel.Controls.Add($button_ctl)
|
||||
}
|
||||
$main_form.Controls.Add($button_panel)
|
||||
|
||||
$button_panel.ResumeLayout($false)
|
||||
$main_form.ResumeLayout($false)
|
||||
|
||||
if ($timeout -gt 0) {
|
||||
$timer = New-Object System.Windows.Forms.Timer
|
||||
$timer.Add_Tick(
|
||||
{
|
||||
$global:Result = 0
|
||||
$main_form.Close()
|
||||
}
|
||||
)
|
||||
$timer.Interval = $timeout
|
||||
$timer.Start()
|
||||
}
|
||||
$dlg_res = $main_form.ShowDialog()
|
||||
|
||||
[Environment]::Exit($global:Result)
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# This script runs black on all Python files in the repo.
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
# Apply black.
|
||||
echo -e "Formatting Python files..."
|
||||
PY_FILES=$(git ls-files -- '*SConstruct' '*SCsub' '*.py' ':!:.git/*' ':!:thirdparty/*')
|
||||
black -l 120 $PY_FILES
|
||||
|
||||
diff=$(git diff --color)
|
||||
|
||||
# If no patch has been generated all is OK, clean up, and exit.
|
||||
if [ -z "$diff" ] ; then
|
||||
printf "Files in this commit comply with the black style rules.\n"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# A patch has been created, notify the user, clean up, and exit.
|
||||
printf "\n*** The following differences were found between the code "
|
||||
printf "and the formatting rules:\n\n"
|
||||
echo "$diff"
|
||||
printf "\n*** Aborting, please fix your commit(s) with 'git commit --amend' or 'git rebase -i <hash>'\n"
|
||||
exit 1
|
||||
@@ -9,8 +9,8 @@ if len(sys.argv) < 2:
|
||||
|
||||
fname = sys.argv[1]
|
||||
|
||||
fileread = open(fname.strip(), "r")
|
||||
file_contents = fileread.read()
|
||||
with open(fname.strip(), "r", encoding="utf-8") as fileread:
|
||||
file_contents = fileread.read()
|
||||
|
||||
# If find "ERROR: AddressSanitizer:", then happens invalid read or write
|
||||
# This is critical bug, so we need to fix this as fast as possible
|
||||
@@ -25,6 +25,8 @@ if (
|
||||
file_contents.find("Program crashed with signal") != -1
|
||||
or file_contents.find("Dumping the backtrace") != -1
|
||||
or file_contents.find("Segmentation fault (core dumped)") != -1
|
||||
or file_contents.find("Aborted (core dumped)") != -1
|
||||
or file_contents.find("terminate called without an active exception") != -1
|
||||
):
|
||||
print("FATAL ERROR: Godot has been crashed.")
|
||||
sys.exit(52)
|
||||
|
||||
@@ -1,31 +1,45 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os, sys
|
||||
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(1, os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
|
||||
from binding_generator import get_file_list, generate_bindings
|
||||
from binding_generator import _generate_bindings, _get_file_list
|
||||
from build_profile import generate_trimmed_api
|
||||
|
||||
api_filepath = "gdextension/extension_api.json"
|
||||
bits = "64"
|
||||
precision = "single"
|
||||
output_dir = "self_test"
|
||||
|
||||
generate_bindings(api_filepath, use_template_get_node=False, bits=bits, precision=precision, output_dir=output_dir)
|
||||
flist = get_file_list(api_filepath, output_dir, headers=True, sources=True)
|
||||
|
||||
p = Path(output_dir) / "gen"
|
||||
allfiles = [str(f.as_posix()) for f in p.glob("**/*.*")]
|
||||
missing = list(filter((lambda f: f not in flist), allfiles))
|
||||
extras = list(filter((lambda f: f not in allfiles), flist))
|
||||
if len(missing) > 0 or len(extras) > 0:
|
||||
print("Error!")
|
||||
for f in missing:
|
||||
print("MISSING: " + str(f))
|
||||
for f in extras:
|
||||
print("EXTRA: " + str(f))
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("OK!")
|
||||
def test(profile_filepath=""):
|
||||
api = generate_trimmed_api(api_filepath, profile_filepath)
|
||||
_generate_bindings(
|
||||
api,
|
||||
use_template_get_node=False,
|
||||
bits=bits,
|
||||
precision=precision,
|
||||
output_dir=output_dir,
|
||||
)
|
||||
flist = _get_file_list(api, output_dir, headers=True, sources=True)
|
||||
|
||||
p = Path(output_dir) / "gen"
|
||||
allfiles = [str(f.as_posix()) for f in p.glob("**/*.*")]
|
||||
missing = list(filter((lambda f: f not in flist), allfiles))
|
||||
extras = list(filter((lambda f: f not in allfiles), flist))
|
||||
if len(missing) > 0 or len(extras) > 0:
|
||||
print("Error!")
|
||||
for f in missing:
|
||||
print("MISSING: " + str(f))
|
||||
for f in extras:
|
||||
print("EXTRA: " + str(f))
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("OK!")
|
||||
|
||||
|
||||
test()
|
||||
test("test/build_profile.json")
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# This script runs clang-format and fixes copyright headers on all relevant files in the repo.
|
||||
# This is the primary script responsible for fixing style violations.
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
# Loops through all code files tracked by Git.
|
||||
git ls-files -- '*.c' '*.h' '*.cpp' '*.hpp' '*.cc' '*.hh' '*.cxx' '*.m' '*.mm' '*.inc' |
|
||||
while read -r f; do
|
||||
# Run clang-format.
|
||||
clang-format --Wno-error=unknown -i "$f"
|
||||
|
||||
# Fix copyright headers, but not all files get them.
|
||||
if [[ "$f" == *"inc" ]]; then
|
||||
continue
|
||||
elif [[ "$f" == *"glsl" ]]; then
|
||||
continue
|
||||
elif [[ "$f" == "test/"* ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
python misc/scripts/copyright_headers.py "$f"
|
||||
done
|
||||
|
||||
diff=$(git diff --color)
|
||||
|
||||
# If no patch has been generated all is OK, clean up, and exit.
|
||||
if [ -z "$diff" ] ; then
|
||||
printf "Files in this commit comply with the clang-tidy style rules.\n"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# A patch has been created, notify the user, clean up, and exit.
|
||||
printf "\n*** The following changes have been made to comply with the formatting rules:\n\n"
|
||||
echo "$diff"
|
||||
printf "\n*** Please fix your commit(s) with 'git commit --amend' or 'git rebase -i <hash>'\n"
|
||||
exit 1
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
SKIP_LIST="./thirdparty,*.gen.*,*.po,*.pot,package-lock.json,./core/string/locales.h,./DONORS.md,./misc/scripts/codespell.sh"
|
||||
IGNORE_LIST="ba,childs,curvelinear,expct,fave,findn,gird,inout,lod,nd,numer,ois,ro,statics,te,varn"
|
||||
|
||||
codespell -w -q 3 -S "${SKIP_LIST}" -L "${IGNORE_LIST}"
|
||||
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
header = """\
|
||||
@@ -35,61 +36,61 @@ header = """\
|
||||
/**************************************************************************/
|
||||
"""
|
||||
|
||||
fname = sys.argv[1]
|
||||
if len(sys.argv) < 2:
|
||||
print("Invalid usage of copyright_headers.py, it should be called with a path to one or multiple files.")
|
||||
sys.exit(1)
|
||||
|
||||
# Handle replacing $filename with actual filename and keep alignment
|
||||
fsingle = fname.strip()
|
||||
if fsingle.find("/") != -1:
|
||||
fsingle = fsingle[fsingle.rfind("/") + 1 :]
|
||||
rep_fl = "$filename"
|
||||
rep_fi = fsingle
|
||||
len_fl = len(rep_fl)
|
||||
len_fi = len(rep_fi)
|
||||
# Pad with spaces to keep alignment
|
||||
if len_fi < len_fl:
|
||||
for x in range(len_fl - len_fi):
|
||||
rep_fi += " "
|
||||
elif len_fl < len_fi:
|
||||
for x in range(len_fi - len_fl):
|
||||
rep_fl += " "
|
||||
if header.find(rep_fl) != -1:
|
||||
text = header.replace(rep_fl, rep_fi)
|
||||
else:
|
||||
text = header.replace("$filename", fsingle)
|
||||
text += "\n"
|
||||
for f in sys.argv[1:]:
|
||||
fname = f
|
||||
|
||||
# We now have the proper header, so we want to ignore the one in the original file
|
||||
# and potentially empty lines and badly formatted lines, while keeping comments that
|
||||
# come after the header, and then keep everything non-header unchanged.
|
||||
# To do so, we skip empty lines that may be at the top in a first pass.
|
||||
# In a second pass, we skip all consecutive comment lines starting with "/*",
|
||||
# then we can append the rest (step 2).
|
||||
# Handle replacing $filename with actual filename and keep alignment
|
||||
fsingle = os.path.basename(fname.strip())
|
||||
rep_fl = "$filename"
|
||||
rep_fi = fsingle
|
||||
len_fl = len(rep_fl)
|
||||
len_fi = len(rep_fi)
|
||||
# Pad with spaces to keep alignment
|
||||
if len_fi < len_fl:
|
||||
for x in range(len_fl - len_fi):
|
||||
rep_fi += " "
|
||||
elif len_fl < len_fi:
|
||||
for x in range(len_fi - len_fl):
|
||||
rep_fl += " "
|
||||
if header.find(rep_fl) != -1:
|
||||
text = header.replace(rep_fl, rep_fi)
|
||||
else:
|
||||
text = header.replace("$filename", fsingle)
|
||||
text += "\n"
|
||||
|
||||
fileread = open(fname.strip(), "r")
|
||||
line = fileread.readline()
|
||||
header_done = False
|
||||
# We now have the proper header, so we want to ignore the one in the original file
|
||||
# and potentially empty lines and badly formatted lines, while keeping comments that
|
||||
# come after the header, and then keep everything non-header unchanged.
|
||||
# To do so, we skip empty lines that may be at the top in a first pass.
|
||||
# In a second pass, we skip all consecutive comment lines starting with "/*",
|
||||
# then we can append the rest (step 2).
|
||||
|
||||
while line.strip() == "": # Skip empty lines at the top
|
||||
line = fileread.readline()
|
||||
with open(fname.strip(), "r", encoding="utf-8") as fileread:
|
||||
line = fileread.readline()
|
||||
header_done = False
|
||||
|
||||
if line.find("/**********") == -1: # Godot header starts this way
|
||||
# Maybe starting with a non-Godot comment, abort header magic
|
||||
header_done = True
|
||||
while line.strip() == "" and line != "": # Skip empty lines at the top
|
||||
line = fileread.readline()
|
||||
|
||||
while not header_done: # Handle header now
|
||||
if line.find("/*") != 0: # No more starting with a comment
|
||||
header_done = True
|
||||
if line.strip() != "":
|
||||
if line.find("/**********") == -1: # Godot header starts this way
|
||||
# Maybe starting with a non-Godot comment, abort header magic
|
||||
header_done = True
|
||||
|
||||
while not header_done: # Handle header now
|
||||
if line.find("/*") != 0: # No more starting with a comment
|
||||
header_done = True
|
||||
if line.strip() != "":
|
||||
text += line
|
||||
line = fileread.readline()
|
||||
|
||||
while line != "": # Dump everything until EOF
|
||||
text += line
|
||||
line = fileread.readline()
|
||||
line = fileread.readline()
|
||||
|
||||
while line != "": # Dump everything until EOF
|
||||
text += line
|
||||
line = fileread.readline()
|
||||
|
||||
fileread.close()
|
||||
|
||||
# Write
|
||||
filewrite = open(fname.strip(), "w")
|
||||
filewrite.write(text)
|
||||
filewrite.close()
|
||||
# Write
|
||||
with open(fname.strip(), "w", encoding="utf-8", newline="\n") as filewrite:
|
||||
filewrite.write(text)
|
||||
|
||||
46
misc/scripts/file_format.py
Normal file
46
misc/scripts/file_format.py
Normal file
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print("Invalid usage of file_format.py, it should be called with a path to one or multiple files.")
|
||||
sys.exit(1)
|
||||
|
||||
BOM = b"\xef\xbb\xbf"
|
||||
|
||||
changed = []
|
||||
invalid = []
|
||||
|
||||
for file in sys.argv[1:]:
|
||||
try:
|
||||
with open(file, "rt", encoding="utf-8") as f:
|
||||
original = f.read()
|
||||
except UnicodeDecodeError:
|
||||
invalid.append(file)
|
||||
continue
|
||||
|
||||
if original == "":
|
||||
continue
|
||||
|
||||
revamp = "\n".join([line.rstrip("\n\r\t ") for line in original.splitlines(True)]).rstrip("\n") + "\n"
|
||||
|
||||
new_raw = revamp.encode(encoding="utf-8")
|
||||
if new_raw.startswith(BOM):
|
||||
new_raw = new_raw[len(BOM) :]
|
||||
|
||||
with open(file, "rb") as f:
|
||||
old_raw = f.read()
|
||||
|
||||
if old_raw != new_raw:
|
||||
changed.append(file)
|
||||
with open(file, "wb") as f:
|
||||
f.write(new_raw)
|
||||
|
||||
if changed:
|
||||
for file in changed:
|
||||
print(f"FIXED: {file}")
|
||||
if invalid:
|
||||
for file in invalid:
|
||||
print(f"REQUIRES MANUAL CHANGES: {file}")
|
||||
sys.exit(1)
|
||||
@@ -1,41 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# This script ensures proper POSIX text file formatting and a few other things.
|
||||
# This is supplementary to clang_format.sh and black_format.sh, but should be
|
||||
# run before them.
|
||||
|
||||
# We need dos2unix and recode.
|
||||
if [ ! -x "$(command -v dos2unix)" -o ! -x "$(command -v recode)" ]; then
|
||||
printf "Install 'dos2unix' and 'recode' to use this script.\n"
|
||||
fi
|
||||
|
||||
set -uo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
# Loops through all text files tracked by Git.
|
||||
git grep -zIl '' |
|
||||
while IFS= read -rd '' f; do
|
||||
# Ensure that files are UTF-8 formatted.
|
||||
recode UTF-8 "$f" 2> /dev/null
|
||||
# Ensure that files have LF line endings and do not contain a BOM.
|
||||
dos2unix "$f" 2> /dev/null
|
||||
# Remove trailing space characters and ensures that files end
|
||||
# with newline characters. -l option handles newlines conveniently.
|
||||
perl -i -ple 's/\s*$//g' "$f"
|
||||
done
|
||||
|
||||
diff=$(git diff --color)
|
||||
|
||||
# If no patch has been generated all is OK, clean up, and exit.
|
||||
if [ -z "$diff" ] ; then
|
||||
printf "Files in this commit comply with the formatting rules.\n"
|
||||
rm -f patch.patch
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# A patch has been created, notify the user, clean up, and exit.
|
||||
printf "\n*** The following differences were found between the code "
|
||||
printf "and the formatting rules:\n\n"
|
||||
echo "$diff"
|
||||
printf "\n*** Aborting, please fix your commit(s) with 'git commit --amend' or 'git rebase -i <hash>'\n"
|
||||
exit 1
|
||||
127
misc/scripts/header_guards.py
Normal file
127
misc/scripts/header_guards.py
Normal file
@@ -0,0 +1,127 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print("Invalid usage of header_guards.py, it should be called with a path to one or multiple files.")
|
||||
sys.exit(1)
|
||||
|
||||
HEADER_CHECK_OFFSET = 30
|
||||
HEADER_BEGIN_OFFSET = 31
|
||||
HEADER_END_OFFSET = -1
|
||||
|
||||
changed = []
|
||||
invalid = []
|
||||
|
||||
for file in sys.argv[1:]:
|
||||
with open(file, "rt", encoding="utf-8", newline="\n") as f:
|
||||
lines = f.readlines()
|
||||
|
||||
if len(lines) <= HEADER_BEGIN_OFFSET:
|
||||
continue # Most likely a dummy file.
|
||||
|
||||
if lines[HEADER_CHECK_OFFSET].startswith("#import"):
|
||||
continue # Early catch obj-c file.
|
||||
|
||||
name = f"GODOT_{Path(file).name}".upper().replace(".", "_").replace("-", "_").replace(" ", "_")
|
||||
|
||||
HEADER_CHECK = f"#ifndef {name}\n"
|
||||
HEADER_BEGIN = f"#define {name}\n"
|
||||
HEADER_END = f"#endif // {name}\n"
|
||||
|
||||
if (
|
||||
lines[HEADER_CHECK_OFFSET] == HEADER_CHECK
|
||||
and lines[HEADER_BEGIN_OFFSET] == HEADER_BEGIN
|
||||
and lines[HEADER_END_OFFSET] == HEADER_END
|
||||
):
|
||||
continue
|
||||
|
||||
# Guards might exist but with the wrong names.
|
||||
if (
|
||||
lines[HEADER_CHECK_OFFSET].startswith("#ifndef")
|
||||
and lines[HEADER_BEGIN_OFFSET].startswith("#define")
|
||||
and lines[HEADER_END_OFFSET].startswith("#endif")
|
||||
):
|
||||
lines[HEADER_CHECK_OFFSET] = HEADER_CHECK
|
||||
lines[HEADER_BEGIN_OFFSET] = HEADER_BEGIN
|
||||
lines[HEADER_END_OFFSET] = HEADER_END
|
||||
with open(file, "wt", encoding="utf-8", newline="\n") as f:
|
||||
f.writelines(lines)
|
||||
changed.append(file)
|
||||
continue
|
||||
|
||||
header_check = -1
|
||||
header_begin = -1
|
||||
header_end = -1
|
||||
pragma_once = -1
|
||||
objc = False
|
||||
|
||||
for idx, line in enumerate(lines):
|
||||
if not line.startswith("#"):
|
||||
continue
|
||||
elif line.startswith("#ifndef") and header_check == -1:
|
||||
header_check = idx
|
||||
elif line.startswith("#define") and header_begin == -1:
|
||||
header_begin = idx
|
||||
elif line.startswith("#endif") and header_end == -1:
|
||||
header_end = idx
|
||||
elif line.startswith("#pragma once"):
|
||||
pragma_once = idx
|
||||
break
|
||||
elif line.startswith("#import"):
|
||||
objc = True
|
||||
break
|
||||
|
||||
if objc:
|
||||
continue
|
||||
|
||||
if pragma_once != -1:
|
||||
lines.pop(pragma_once)
|
||||
lines.insert(HEADER_CHECK_OFFSET, HEADER_CHECK)
|
||||
lines.insert(HEADER_BEGIN_OFFSET, HEADER_BEGIN)
|
||||
lines.append("\n")
|
||||
lines.append(HEADER_END)
|
||||
with open(file, "wt", encoding="utf-8", newline="\n") as f:
|
||||
f.writelines(lines)
|
||||
changed.append(file)
|
||||
continue
|
||||
|
||||
if header_check == -1 and header_begin == -1 and header_end == -1:
|
||||
# Guards simply didn't exist
|
||||
lines.insert(HEADER_CHECK_OFFSET, HEADER_CHECK)
|
||||
lines.insert(HEADER_BEGIN_OFFSET, HEADER_BEGIN)
|
||||
lines.append("\n")
|
||||
lines.append(HEADER_END)
|
||||
with open(file, "wt", encoding="utf-8", newline="\n") as f:
|
||||
f.writelines(lines)
|
||||
changed.append(file)
|
||||
continue
|
||||
|
||||
if header_check != -1 and header_begin != -1 and header_end != -1:
|
||||
# All prepends "found", see if we can salvage this.
|
||||
if header_check == header_begin - 1 and header_begin < header_end:
|
||||
lines.pop(header_check)
|
||||
lines.pop(header_begin - 1)
|
||||
lines.pop(header_end - 2)
|
||||
if lines[header_end - 3] == "\n":
|
||||
lines.pop(header_end - 3)
|
||||
lines.insert(HEADER_CHECK_OFFSET, HEADER_CHECK)
|
||||
lines.insert(HEADER_BEGIN_OFFSET, HEADER_BEGIN)
|
||||
lines.append("\n")
|
||||
lines.append(HEADER_END)
|
||||
with open(file, "wt", encoding="utf-8", newline="\n") as f:
|
||||
f.writelines(lines)
|
||||
changed.append(file)
|
||||
continue
|
||||
|
||||
invalid.append(file)
|
||||
|
||||
if changed:
|
||||
for file in changed:
|
||||
print(f"FIXED: {file}")
|
||||
if invalid:
|
||||
for file in invalid:
|
||||
print(f"REQUIRES MANUAL CHANGES: {file}")
|
||||
sys.exit(1)
|
||||
@@ -1,60 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ ! -f "SConstruct" ]; then
|
||||
echo "Warning: This script is intended to be run from the root of the Godot repository."
|
||||
echo "Some of the paths checks may not work as intended from a different folder."
|
||||
fi
|
||||
|
||||
files_invalid_guard=""
|
||||
|
||||
for file in $(find . -name "*.hpp" -print); do
|
||||
# Skip generated files.
|
||||
if [[ "$file" == "./gen/"* || "$file" == "./include/gen/"* ]]; then continue; fi
|
||||
# Skip the test project.
|
||||
if [[ "$file" == "./test/"* ]]; then continue; fi
|
||||
|
||||
bname=$(basename $file .hpp)
|
||||
|
||||
# NOTE: The "GODOT_CPP_" prefix is already used by the generated
|
||||
# bindings, so we can't use that. We'll use "GODOT_" instead.
|
||||
prefix="GODOT_"
|
||||
|
||||
# ^^ is bash builtin for UPPERCASE.
|
||||
guard="${prefix}${bname^^}_HPP"
|
||||
|
||||
# Replaces guards to use computed name.
|
||||
# We also add some \n to make sure there's a proper separation.
|
||||
sed -i $file -e "0,/ifndef/s/#ifndef.*/\n#ifndef $guard/"
|
||||
sed -i $file -e "0,/define/s/#define.*/#define $guard\n/"
|
||||
sed -i $file -e "$ s/#endif.*/\n#endif \/\/ $guard/"
|
||||
# Removes redundant \n added before, if they weren't needed.
|
||||
sed -i $file -e "/^$/N;/^\n$/D"
|
||||
|
||||
# Check that first ifndef (should be header guard) is at the expected position.
|
||||
# If not it can mean we have some code before the guard that should be after.
|
||||
# "31" is the expected line with the copyright header.
|
||||
first_ifndef=$(grep -n -m 1 "ifndef" $file | sed 's/\([0-9]*\).*/\1/')
|
||||
if [[ "$first_ifndef" != "31" ]]; then
|
||||
files_invalid_guard+="$file\n"
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ! -z "$files_invalid_guard" ]]; then
|
||||
echo -e "The following files were found to have potentially invalid header guard:\n"
|
||||
echo -e "$files_invalid_guard"
|
||||
fi
|
||||
|
||||
diff=$(git diff --color)
|
||||
|
||||
# If no diff has been generated all is OK, clean up, and exit.
|
||||
if [ -z "$diff" ] ; then
|
||||
printf "Files in this commit comply with the header guards formatting rules.\n"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# A diff has been created, notify the user, clean up, and exit.
|
||||
printf "\n*** The following differences were found between the code "
|
||||
printf "and the header guards formatting rules:\n\n"
|
||||
echo "$diff"
|
||||
printf "\n*** Aborting, please fix your commit(s) with 'git commit --amend' or 'git rebase -i <hash>'\n"
|
||||
exit 1
|
||||
@@ -1,11 +0,0 @@
|
||||
[mypy]
|
||||
ignore_missing_imports = true
|
||||
disallow_any_generics = True
|
||||
pretty = True
|
||||
show_column_numbers = True
|
||||
warn_redundant_casts = True
|
||||
warn_return_any = True
|
||||
warn_unreachable = True
|
||||
|
||||
namespace_packages = True
|
||||
explicit_package_bases = True
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
echo -e "Python: mypy static analysis..."
|
||||
mypy --config-file=./misc/scripts/mypy.ini .
|
||||
58
pyproject.toml
Normal file
58
pyproject.toml
Normal file
@@ -0,0 +1,58 @@
|
||||
[tool.mypy]
|
||||
disallow_any_generics = true
|
||||
explicit_package_bases = true
|
||||
ignore_missing_imports = true
|
||||
namespace_packages = true
|
||||
no_implicit_optional = true
|
||||
pretty = true
|
||||
scripts_are_modules = true
|
||||
show_column_numbers = true
|
||||
warn_redundant_casts = true
|
||||
warn_return_any = true
|
||||
warn_unreachable = true
|
||||
|
||||
[tool.ruff]
|
||||
extend-include = ["SConstruct"]
|
||||
line-length = 120
|
||||
target-version = "py37"
|
||||
|
||||
[tool.ruff.lint]
|
||||
extend-select = [
|
||||
"I", # isort
|
||||
]
|
||||
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"SConstruct" = [
|
||||
"F821", # Undefined name
|
||||
]
|
||||
|
||||
[tool.codespell]
|
||||
enable-colors = ""
|
||||
write-changes = ""
|
||||
check-hidden = ""
|
||||
quiet-level = 3
|
||||
builtin = "clear,rare,en-GB_to_en-US"
|
||||
ignore-words-list = """\
|
||||
breaked,
|
||||
cancelled,
|
||||
checkin,
|
||||
curvelinear,
|
||||
doubleclick,
|
||||
expct,
|
||||
findn,
|
||||
gird,
|
||||
hel,
|
||||
inout,
|
||||
labelin,
|
||||
lod,
|
||||
mis,
|
||||
nd,
|
||||
numer,
|
||||
ot,
|
||||
outin,
|
||||
requestor,
|
||||
te,
|
||||
textin,
|
||||
thirdparty,
|
||||
vai
|
||||
"""
|
||||
@@ -51,10 +51,7 @@ void Wrapped::_postinitialize() {
|
||||
}
|
||||
godot::internal::gdextension_interface_object_set_instance_binding(_owner, godot::internal::token, this, _get_bindings_callbacks());
|
||||
if (extension_class) {
|
||||
Object *obj = dynamic_cast<Object *>(this);
|
||||
if (obj) {
|
||||
obj->notification(Object::NOTIFICATION_POSTINITIALIZE);
|
||||
}
|
||||
_notificationv(Object::NOTIFICATION_POSTINITIALIZE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@ namespace godot {
|
||||
std::unordered_map<StringName, ClassDB::ClassInfo> ClassDB::classes;
|
||||
std::unordered_map<StringName, const GDExtensionInstanceBindingCallbacks *> ClassDB::instance_binding_callbacks;
|
||||
std::vector<StringName> ClassDB::class_register_order;
|
||||
std::unordered_map<StringName, Object *> ClassDB::engine_singletons;
|
||||
std::mutex ClassDB::engine_singletons_mutex;
|
||||
GDExtensionInitializationLevel ClassDB::current_level = GDEXTENSION_INITIALIZATION_CORE;
|
||||
|
||||
MethodDefinition D_METHOD(StringName p_name) {
|
||||
@@ -378,6 +380,22 @@ void ClassDB::deinitialize(GDExtensionInitializationLevel p_level) {
|
||||
});
|
||||
class_register_order.erase(it, class_register_order.end());
|
||||
}
|
||||
|
||||
if (p_level == GDEXTENSION_INITIALIZATION_CORE) {
|
||||
// Make a new list of the singleton objects, since freeing the instance bindings will lead to
|
||||
// elements getting removed from engine_singletons.
|
||||
std::vector<Object *> singleton_objects;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(engine_singletons_mutex);
|
||||
singleton_objects.reserve(engine_singletons.size());
|
||||
for (const std::pair<const StringName, Object *> &pair : engine_singletons) {
|
||||
singleton_objects.push_back(pair.second);
|
||||
}
|
||||
}
|
||||
for (std::vector<Object *>::iterator i = singleton_objects.begin(); i != singleton_objects.end(); i++) {
|
||||
internal::gdextension_interface_object_free_instance_binding((*i)->_owner, internal::token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
|
||||
@@ -36,17 +36,17 @@ namespace godot {
|
||||
|
||||
void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
bool prepad = false; // Alredy pre paded in the engine.
|
||||
bool prepad = false; // Already pre paded in the engine.
|
||||
#else
|
||||
bool prepad = p_pad_align;
|
||||
#endif
|
||||
|
||||
void *mem = internal::gdextension_interface_mem_alloc(p_bytes + (prepad ? PAD_ALIGN : 0));
|
||||
void *mem = internal::gdextension_interface_mem_alloc(p_bytes + (prepad ? DATA_OFFSET : 0));
|
||||
ERR_FAIL_NULL_V(mem, nullptr);
|
||||
|
||||
if (prepad) {
|
||||
uint8_t *s8 = (uint8_t *)mem;
|
||||
return s8 + PAD_ALIGN;
|
||||
return s8 + DATA_OFFSET;
|
||||
} else {
|
||||
return mem;
|
||||
}
|
||||
@@ -63,16 +63,16 @@ void *Memory::realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align) {
|
||||
uint8_t *mem = (uint8_t *)p_memory;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
bool prepad = false; // Alredy pre paded in the engine.
|
||||
bool prepad = false; // Already pre paded in the engine.
|
||||
#else
|
||||
bool prepad = p_pad_align;
|
||||
#endif
|
||||
|
||||
if (prepad) {
|
||||
mem -= PAD_ALIGN;
|
||||
mem = (uint8_t *)internal::gdextension_interface_mem_realloc(mem, p_bytes + PAD_ALIGN);
|
||||
mem -= DATA_OFFSET;
|
||||
mem = (uint8_t *)internal::gdextension_interface_mem_realloc(mem, p_bytes + DATA_OFFSET);
|
||||
ERR_FAIL_NULL_V(mem, nullptr);
|
||||
return mem + PAD_ALIGN;
|
||||
return mem + DATA_OFFSET;
|
||||
} else {
|
||||
return (uint8_t *)internal::gdextension_interface_mem_realloc(mem, p_bytes);
|
||||
}
|
||||
@@ -82,13 +82,13 @@ void Memory::free_static(void *p_ptr, bool p_pad_align) {
|
||||
uint8_t *mem = (uint8_t *)p_ptr;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
bool prepad = false; // Alredy pre paded in the engine.
|
||||
bool prepad = false; // Already pre paded in the engine.
|
||||
#else
|
||||
bool prepad = p_pad_align;
|
||||
#endif
|
||||
|
||||
if (prepad) {
|
||||
mem -= PAD_ALIGN;
|
||||
mem -= DATA_OFFSET;
|
||||
}
|
||||
internal::gdextension_interface_mem_free(mem);
|
||||
}
|
||||
|
||||
@@ -60,8 +60,66 @@ Object *get_object_instance_binding(GodotObject *p_engine_object) {
|
||||
return reinterpret_cast<Object *>(gdextension_interface_object_get_instance_binding(p_engine_object, token, binding_callbacks));
|
||||
}
|
||||
|
||||
TypedArray<Dictionary> convert_property_list(const std::vector<PropertyInfo> &p_list) {
|
||||
TypedArray<Dictionary> va;
|
||||
for (const PropertyInfo &pi : p_list) {
|
||||
va.push_back(Dictionary(pi));
|
||||
}
|
||||
return va;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
MethodInfo::operator Dictionary() const {
|
||||
Dictionary dict;
|
||||
dict["name"] = name;
|
||||
dict["args"] = internal::convert_property_list(arguments);
|
||||
Array da;
|
||||
for (size_t i = 0; i < default_arguments.size(); i++) {
|
||||
da.push_back(default_arguments[i]);
|
||||
}
|
||||
dict["default_args"] = da;
|
||||
dict["flags"] = flags;
|
||||
dict["id"] = id;
|
||||
Dictionary r = return_val;
|
||||
dict["return"] = r;
|
||||
return dict;
|
||||
}
|
||||
|
||||
MethodInfo MethodInfo::from_dict(const Dictionary &p_dict) {
|
||||
MethodInfo mi;
|
||||
|
||||
if (p_dict.has("name")) {
|
||||
mi.name = p_dict["name"];
|
||||
}
|
||||
Array args;
|
||||
if (p_dict.has("args")) {
|
||||
args = p_dict["args"];
|
||||
}
|
||||
|
||||
for (int i = 0; i < args.size(); i++) {
|
||||
Dictionary d = args[i];
|
||||
mi.arguments.push_back(PropertyInfo::from_dict(d));
|
||||
}
|
||||
Array defargs;
|
||||
if (p_dict.has("default_args")) {
|
||||
defargs = p_dict["default_args"];
|
||||
}
|
||||
for (int i = 0; i < defargs.size(); i++) {
|
||||
mi.default_arguments.push_back(defargs[i]);
|
||||
}
|
||||
|
||||
if (p_dict.has("return")) {
|
||||
mi.return_val = PropertyInfo::from_dict(p_dict["return"]);
|
||||
}
|
||||
|
||||
if (p_dict.has("flags")) {
|
||||
mi.flags = p_dict["flags"];
|
||||
}
|
||||
|
||||
return mi;
|
||||
}
|
||||
|
||||
MethodInfo::MethodInfo() :
|
||||
flags(GDEXTENSION_METHOD_FLAG_NORMAL) {}
|
||||
|
||||
|
||||
@@ -166,6 +166,7 @@ GDExtensionInterfaceObjectDestroy gdextension_interface_object_destroy = nullptr
|
||||
GDExtensionInterfaceGlobalGetSingleton gdextension_interface_global_get_singleton = nullptr;
|
||||
GDExtensionInterfaceObjectGetInstanceBinding gdextension_interface_object_get_instance_binding = nullptr;
|
||||
GDExtensionInterfaceObjectSetInstanceBinding gdextension_interface_object_set_instance_binding = nullptr;
|
||||
GDExtensionInterfaceObjectFreeInstanceBinding gdextension_interface_object_free_instance_binding = nullptr;
|
||||
GDExtensionInterfaceObjectSetInstance gdextension_interface_object_set_instance = nullptr;
|
||||
GDExtensionInterfaceObjectGetClassName gdextension_interface_object_get_class_name = nullptr;
|
||||
GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to = nullptr;
|
||||
@@ -271,7 +272,12 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
|
||||
} else if (internal::godot_version.minor != GODOT_VERSION_MINOR) {
|
||||
compatible = internal::godot_version.minor > GODOT_VERSION_MINOR;
|
||||
} else {
|
||||
#if GODOT_VERSION_PATCH > 0
|
||||
compatible = internal::godot_version.patch >= GODOT_VERSION_PATCH;
|
||||
#else
|
||||
// Prevent -Wtype-limits warning due to unsigned comparison.
|
||||
compatible = true;
|
||||
#endif
|
||||
}
|
||||
if (!compatible) {
|
||||
// We need to use snprintf() here because vformat() uses Variant, and we haven't loaded
|
||||
@@ -398,6 +404,7 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
|
||||
LOAD_PROC_ADDRESS(global_get_singleton, GDExtensionInterfaceGlobalGetSingleton);
|
||||
LOAD_PROC_ADDRESS(object_get_instance_binding, GDExtensionInterfaceObjectGetInstanceBinding);
|
||||
LOAD_PROC_ADDRESS(object_set_instance_binding, GDExtensionInterfaceObjectSetInstanceBinding);
|
||||
LOAD_PROC_ADDRESS(object_free_instance_binding, GDExtensionInterfaceObjectFreeInstanceBinding);
|
||||
LOAD_PROC_ADDRESS(object_set_instance, GDExtensionInterfaceObjectSetInstance);
|
||||
LOAD_PROC_ADDRESS(object_get_class_name, GDExtensionInterfaceObjectGetClassName);
|
||||
LOAD_PROC_ADDRESS(object_cast_to, GDExtensionInterfaceObjectCastTo);
|
||||
|
||||
@@ -78,6 +78,10 @@ bool AABB::is_equal_approx(const AABB &p_aabb) const {
|
||||
return position.is_equal_approx(p_aabb.position) && size.is_equal_approx(p_aabb.size);
|
||||
}
|
||||
|
||||
bool AABB::is_finite() const {
|
||||
return position.is_finite() && size.is_finite();
|
||||
}
|
||||
|
||||
AABB AABB::intersection(const AABB &p_aabb) const {
|
||||
#ifdef MATH_CHECKS
|
||||
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0 || p_aabb.size.x < 0 || p_aabb.size.y < 0 || p_aabb.size.z < 0)) {
|
||||
|
||||
@@ -692,6 +692,10 @@ bool Basis::is_equal_approx(const Basis &p_basis) const {
|
||||
return rows[0].is_equal_approx(p_basis.rows[0]) && rows[1].is_equal_approx(p_basis.rows[1]) && rows[2].is_equal_approx(p_basis.rows[2]);
|
||||
}
|
||||
|
||||
bool Basis::is_finite() const {
|
||||
return rows[0].is_finite() && rows[1].is_finite() && rows[2].is_finite();
|
||||
}
|
||||
|
||||
bool Basis::operator==(const Basis &p_matrix) const {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
@@ -812,7 +816,7 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
|
||||
return;
|
||||
}
|
||||
// As we have reached here there are no singularities so we can handle normally.
|
||||
double s = Math::sqrt((rows[2][1] - rows[1][2]) * (rows[2][1] - rows[1][2]) + (rows[0][2] - rows[2][0]) * (rows[0][2] - rows[2][0]) + (rows[1][0] - rows[0][1]) * (rows[1][0] - rows[0][1])); // Used to normalise.
|
||||
double s = Math::sqrt((rows[2][1] - rows[1][2]) * (rows[2][1] - rows[1][2]) + (rows[0][2] - rows[2][0]) * (rows[0][2] - rows[2][0]) + (rows[1][0] - rows[0][1]) * (rows[1][0] - rows[0][1])); // Used to normalize.
|
||||
|
||||
if (Math::abs(s) < CMP_EPSILON) {
|
||||
// Prevent divide by zero, should not happen if matrix is orthogonal and should be caught by singularity test above.
|
||||
@@ -1033,12 +1037,15 @@ void Basis::rotate_sh(real_t *p_values) {
|
||||
p_values[8] = d4 * s_scale_dst4;
|
||||
}
|
||||
|
||||
Basis Basis::looking_at(const Vector3 &p_target, const Vector3 &p_up) {
|
||||
Basis Basis::looking_at(const Vector3 &p_target, const Vector3 &p_up, bool p_use_model_front) {
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND_V_MSG(p_target.is_zero_approx(), Basis(), "The target vector can't be zero.");
|
||||
ERR_FAIL_COND_V_MSG(p_up.is_zero_approx(), Basis(), "The up vector can't be zero.");
|
||||
#endif
|
||||
Vector3 v_z = -p_target.normalized();
|
||||
Vector3 v_z = p_target.normalized();
|
||||
if (!p_use_model_front) {
|
||||
v_z = -v_z;
|
||||
}
|
||||
Vector3 v_x = p_up.cross(v_z);
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND_V_MSG(v_x.is_zero_approx(), Basis(), "The target vector and up vector can't be parallel to each other.");
|
||||
|
||||
@@ -65,7 +65,7 @@ _FORCE_INLINE_ bool is_str_less(const L *l_ptr, const R *r_ptr) {
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
bool CharStringT<T>::operator<(const CharStringT<T> &p_right) const {
|
||||
if (length() == 0) {
|
||||
return p_right.length() != 0;
|
||||
@@ -74,9 +74,9 @@ bool CharStringT<T>::operator<(const CharStringT<T> &p_right) const {
|
||||
return is_str_less(get_data(), p_right.get_data());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
CharStringT<T> &CharStringT<T>::operator+=(T p_char) {
|
||||
const int lhs_len = length();
|
||||
const int64_t lhs_len = length();
|
||||
resize(lhs_len + 2);
|
||||
|
||||
T *dst = ptrw();
|
||||
@@ -86,7 +86,7 @@ CharStringT<T> &CharStringT<T>::operator+=(T p_char) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
void CharStringT<T>::operator=(const T *p_cstr) {
|
||||
copy_from(p_cstr);
|
||||
}
|
||||
@@ -127,7 +127,7 @@ const wchar_t *CharStringT<wchar_t>::get_data() const {
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename T>
|
||||
void CharStringT<T>::copy_from(const T *p_cstr) {
|
||||
if (!p_cstr) {
|
||||
resize(0);
|
||||
@@ -172,23 +172,23 @@ String::String(const char32_t *from) {
|
||||
internal::gdextension_interface_string_new_with_utf32_chars(_native_ptr(), from);
|
||||
}
|
||||
|
||||
String String::utf8(const char *from, int len) {
|
||||
String String::utf8(const char *from, int64_t len) {
|
||||
String ret;
|
||||
ret.parse_utf8(from, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void String::parse_utf8(const char *from, int len) {
|
||||
void String::parse_utf8(const char *from, int64_t len) {
|
||||
internal::gdextension_interface_string_new_with_utf8_chars_and_len(_native_ptr(), from, len);
|
||||
}
|
||||
|
||||
String String::utf16(const char16_t *from, int len) {
|
||||
String String::utf16(const char16_t *from, int64_t len) {
|
||||
String ret;
|
||||
ret.parse_utf16(from, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void String::parse_utf16(const char16_t *from, int len) {
|
||||
void String::parse_utf16(const char16_t *from, int64_t len) {
|
||||
internal::gdextension_interface_string_new_with_utf16_chars_and_len(_native_ptr(), from, len);
|
||||
}
|
||||
|
||||
@@ -230,8 +230,8 @@ String rtoss(double p_val) {
|
||||
}
|
||||
|
||||
CharString String::utf8() const {
|
||||
int length = internal::gdextension_interface_string_to_utf8_chars(_native_ptr(), nullptr, 0);
|
||||
int size = length + 1;
|
||||
int64_t length = internal::gdextension_interface_string_to_utf8_chars(_native_ptr(), nullptr, 0);
|
||||
int64_t size = length + 1;
|
||||
CharString str;
|
||||
str.resize(size);
|
||||
internal::gdextension_interface_string_to_utf8_chars(_native_ptr(), str.ptrw(), length);
|
||||
@@ -242,8 +242,8 @@ CharString String::utf8() const {
|
||||
}
|
||||
|
||||
CharString String::ascii() const {
|
||||
int length = internal::gdextension_interface_string_to_latin1_chars(_native_ptr(), nullptr, 0);
|
||||
int size = length + 1;
|
||||
int64_t length = internal::gdextension_interface_string_to_latin1_chars(_native_ptr(), nullptr, 0);
|
||||
int64_t size = length + 1;
|
||||
CharString str;
|
||||
str.resize(size);
|
||||
internal::gdextension_interface_string_to_latin1_chars(_native_ptr(), str.ptrw(), length);
|
||||
@@ -254,8 +254,8 @@ CharString String::ascii() const {
|
||||
}
|
||||
|
||||
Char16String String::utf16() const {
|
||||
int length = internal::gdextension_interface_string_to_utf16_chars(_native_ptr(), nullptr, 0);
|
||||
int size = length + 1;
|
||||
int64_t length = internal::gdextension_interface_string_to_utf16_chars(_native_ptr(), nullptr, 0);
|
||||
int64_t size = length + 1;
|
||||
Char16String str;
|
||||
str.resize(size);
|
||||
internal::gdextension_interface_string_to_utf16_chars(_native_ptr(), str.ptrw(), length);
|
||||
@@ -266,8 +266,8 @@ Char16String String::utf16() const {
|
||||
}
|
||||
|
||||
Char32String String::utf32() const {
|
||||
int length = internal::gdextension_interface_string_to_utf32_chars(_native_ptr(), nullptr, 0);
|
||||
int size = length + 1;
|
||||
int64_t length = internal::gdextension_interface_string_to_utf32_chars(_native_ptr(), nullptr, 0);
|
||||
int64_t size = length + 1;
|
||||
Char32String str;
|
||||
str.resize(size);
|
||||
internal::gdextension_interface_string_to_utf32_chars(_native_ptr(), str.ptrw(), length);
|
||||
@@ -278,8 +278,8 @@ Char32String String::utf32() const {
|
||||
}
|
||||
|
||||
CharWideString String::wide_string() const {
|
||||
int length = internal::gdextension_interface_string_to_wide_chars(_native_ptr(), nullptr, 0);
|
||||
int size = length + 1;
|
||||
int64_t length = internal::gdextension_interface_string_to_wide_chars(_native_ptr(), nullptr, 0);
|
||||
int64_t size = length + 1;
|
||||
CharWideString str;
|
||||
str.resize(size);
|
||||
internal::gdextension_interface_string_to_wide_chars(_native_ptr(), str.ptrw(), length);
|
||||
@@ -289,7 +289,7 @@ CharWideString String::wide_string() const {
|
||||
return str;
|
||||
}
|
||||
|
||||
Error String::resize(int p_size) {
|
||||
Error String::resize(int64_t p_size) {
|
||||
return (Error)internal::gdextension_interface_string_resize(_native_ptr(), p_size);
|
||||
}
|
||||
|
||||
@@ -390,11 +390,11 @@ String &String::operator+=(const char32_t *p_str) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
const char32_t &String::operator[](int p_index) const {
|
||||
const char32_t &String::operator[](int64_t p_index) const {
|
||||
return *internal::gdextension_interface_string_operator_index_const((GDExtensionStringPtr)this, p_index);
|
||||
}
|
||||
|
||||
char32_t &String::operator[](int p_index) {
|
||||
char32_t &String::operator[](int64_t p_index) {
|
||||
return *internal::gdextension_interface_string_operator_index((GDExtensionStringPtr)this, p_index);
|
||||
}
|
||||
|
||||
|
||||
@@ -192,7 +192,7 @@ void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) {
|
||||
a = p_alpha;
|
||||
|
||||
if (p_s == 0.0f) {
|
||||
// Achromatic (grey)
|
||||
// Achromatic (gray)
|
||||
r = g = b = p_v;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -46,11 +46,11 @@
|
||||
|
||||
namespace godot {
|
||||
|
||||
const uint8_t &PackedByteArray::operator[](int p_index) const {
|
||||
const uint8_t &PackedByteArray::operator[](int64_t p_index) const {
|
||||
return *internal::gdextension_interface_packed_byte_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
|
||||
}
|
||||
|
||||
uint8_t &PackedByteArray::operator[](int p_index) {
|
||||
uint8_t &PackedByteArray::operator[](int64_t p_index) {
|
||||
return *internal::gdextension_interface_packed_byte_array_operator_index((GDExtensionTypePtr *)this, p_index);
|
||||
}
|
||||
|
||||
@@ -62,12 +62,12 @@ uint8_t *PackedByteArray::ptrw() {
|
||||
return internal::gdextension_interface_packed_byte_array_operator_index((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
const Color &PackedColorArray::operator[](int p_index) const {
|
||||
const Color &PackedColorArray::operator[](int64_t p_index) const {
|
||||
const Color *color = (const Color *)internal::gdextension_interface_packed_color_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
|
||||
return *color;
|
||||
}
|
||||
|
||||
Color &PackedColorArray::operator[](int p_index) {
|
||||
Color &PackedColorArray::operator[](int64_t p_index) {
|
||||
Color *color = (Color *)internal::gdextension_interface_packed_color_array_operator_index((GDExtensionTypePtr *)this, p_index);
|
||||
return *color;
|
||||
}
|
||||
@@ -80,11 +80,11 @@ Color *PackedColorArray::ptrw() {
|
||||
return (Color *)internal::gdextension_interface_packed_color_array_operator_index((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
const float &PackedFloat32Array::operator[](int p_index) const {
|
||||
const float &PackedFloat32Array::operator[](int64_t p_index) const {
|
||||
return *internal::gdextension_interface_packed_float32_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
|
||||
}
|
||||
|
||||
float &PackedFloat32Array::operator[](int p_index) {
|
||||
float &PackedFloat32Array::operator[](int64_t p_index) {
|
||||
return *internal::gdextension_interface_packed_float32_array_operator_index((GDExtensionTypePtr *)this, p_index);
|
||||
}
|
||||
|
||||
@@ -96,11 +96,11 @@ float *PackedFloat32Array::ptrw() {
|
||||
return internal::gdextension_interface_packed_float32_array_operator_index((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
const double &PackedFloat64Array::operator[](int p_index) const {
|
||||
const double &PackedFloat64Array::operator[](int64_t p_index) const {
|
||||
return *internal::gdextension_interface_packed_float64_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
|
||||
}
|
||||
|
||||
double &PackedFloat64Array::operator[](int p_index) {
|
||||
double &PackedFloat64Array::operator[](int64_t p_index) {
|
||||
return *internal::gdextension_interface_packed_float64_array_operator_index((GDExtensionTypePtr *)this, p_index);
|
||||
}
|
||||
|
||||
@@ -112,11 +112,11 @@ double *PackedFloat64Array::ptrw() {
|
||||
return internal::gdextension_interface_packed_float64_array_operator_index((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
const int32_t &PackedInt32Array::operator[](int p_index) const {
|
||||
const int32_t &PackedInt32Array::operator[](int64_t p_index) const {
|
||||
return *internal::gdextension_interface_packed_int32_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
|
||||
}
|
||||
|
||||
int32_t &PackedInt32Array::operator[](int p_index) {
|
||||
int32_t &PackedInt32Array::operator[](int64_t p_index) {
|
||||
return *internal::gdextension_interface_packed_int32_array_operator_index((GDExtensionTypePtr *)this, p_index);
|
||||
}
|
||||
|
||||
@@ -128,11 +128,11 @@ int32_t *PackedInt32Array::ptrw() {
|
||||
return internal::gdextension_interface_packed_int32_array_operator_index((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
const int64_t &PackedInt64Array::operator[](int p_index) const {
|
||||
const int64_t &PackedInt64Array::operator[](int64_t p_index) const {
|
||||
return *internal::gdextension_interface_packed_int64_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
|
||||
}
|
||||
|
||||
int64_t &PackedInt64Array::operator[](int p_index) {
|
||||
int64_t &PackedInt64Array::operator[](int64_t p_index) {
|
||||
return *internal::gdextension_interface_packed_int64_array_operator_index((GDExtensionTypePtr *)this, p_index);
|
||||
}
|
||||
|
||||
@@ -144,12 +144,12 @@ int64_t *PackedInt64Array::ptrw() {
|
||||
return internal::gdextension_interface_packed_int64_array_operator_index((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
const String &PackedStringArray::operator[](int p_index) const {
|
||||
const String &PackedStringArray::operator[](int64_t p_index) const {
|
||||
const String *string = (const String *)internal::gdextension_interface_packed_string_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
|
||||
return *string;
|
||||
}
|
||||
|
||||
String &PackedStringArray::operator[](int p_index) {
|
||||
String &PackedStringArray::operator[](int64_t p_index) {
|
||||
String *string = (String *)internal::gdextension_interface_packed_string_array_operator_index((GDExtensionTypePtr *)this, p_index);
|
||||
return *string;
|
||||
}
|
||||
@@ -162,12 +162,12 @@ String *PackedStringArray::ptrw() {
|
||||
return (String *)internal::gdextension_interface_packed_string_array_operator_index((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
const Vector2 &PackedVector2Array::operator[](int p_index) const {
|
||||
const Vector2 &PackedVector2Array::operator[](int64_t p_index) const {
|
||||
const Vector2 *vec = (const Vector2 *)internal::gdextension_interface_packed_vector2_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
|
||||
return *vec;
|
||||
}
|
||||
|
||||
Vector2 &PackedVector2Array::operator[](int p_index) {
|
||||
Vector2 &PackedVector2Array::operator[](int64_t p_index) {
|
||||
Vector2 *vec = (Vector2 *)internal::gdextension_interface_packed_vector2_array_operator_index((GDExtensionTypePtr *)this, p_index);
|
||||
return *vec;
|
||||
}
|
||||
@@ -180,12 +180,12 @@ Vector2 *PackedVector2Array::ptrw() {
|
||||
return (Vector2 *)internal::gdextension_interface_packed_vector2_array_operator_index((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
const Vector3 &PackedVector3Array::operator[](int p_index) const {
|
||||
const Vector3 &PackedVector3Array::operator[](int64_t p_index) const {
|
||||
const Vector3 *vec = (const Vector3 *)internal::gdextension_interface_packed_vector3_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
|
||||
return *vec;
|
||||
}
|
||||
|
||||
Vector3 &PackedVector3Array::operator[](int p_index) {
|
||||
Vector3 &PackedVector3Array::operator[](int64_t p_index) {
|
||||
Vector3 *vec = (Vector3 *)internal::gdextension_interface_packed_vector3_array_operator_index((GDExtensionTypePtr *)this, p_index);
|
||||
return *vec;
|
||||
}
|
||||
@@ -198,12 +198,12 @@ Vector3 *PackedVector3Array::ptrw() {
|
||||
return (Vector3 *)internal::gdextension_interface_packed_vector3_array_operator_index((GDExtensionTypePtr *)this, 0);
|
||||
}
|
||||
|
||||
const Variant &Array::operator[](int p_index) const {
|
||||
const Variant &Array::operator[](int64_t p_index) const {
|
||||
const Variant *var = (const Variant *)internal::gdextension_interface_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
|
||||
return *var;
|
||||
}
|
||||
|
||||
Variant &Array::operator[](int p_index) {
|
||||
Variant &Array::operator[](int64_t p_index) {
|
||||
Variant *var = (Variant *)internal::gdextension_interface_array_operator_index((GDExtensionTypePtr *)this, p_index);
|
||||
return *var;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user