mirror of
https://github.com/godotengine/godot-cpp.git
synced 2026-01-08 18:10:02 +03:00
Compare commits
91 Commits
godot-4.4.
...
godot-4.1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b0ee13327 | ||
|
|
e4978558e6 | ||
|
|
30ebe5fdf9 | ||
|
|
e897dbe58a | ||
|
|
28a6609c0b | ||
|
|
7f3e725a8a | ||
|
|
8e5d7c9268 | ||
|
|
974e6c6f86 | ||
|
|
c8fa4c0fd0 | ||
|
|
594a93f8ac | ||
|
|
9e48c45bfc | ||
|
|
76d6ce7136 | ||
|
|
e99d7b3b7e | ||
|
|
07e245e3e4 | ||
|
|
ed576f8318 | ||
|
|
f7a9d32f32 | ||
|
|
08da55cd0b | ||
|
|
670c4d0eac | ||
|
|
bab62a4d72 | ||
|
|
1ac8627b2e | ||
|
|
6202bf141e | ||
|
|
4b63d795e4 | ||
|
|
2cc967787a | ||
|
|
6884ca9be0 | ||
|
|
dde0bbb93d | ||
|
|
1c03aa7746 | ||
|
|
82475b215b | ||
|
|
49098fbdc7 | ||
|
|
756190705e | ||
|
|
2e42c7020e | ||
|
|
e9273e8528 | ||
|
|
b1bd58d7da | ||
|
|
d5a2e8e797 | ||
|
|
6bb4b1d321 | ||
|
|
51aeda7437 | ||
|
|
cd904155a8 | ||
|
|
b622b11df3 | ||
|
|
92449b46e1 | ||
|
|
e8b6887b36 | ||
|
|
631cd5fe37 | ||
|
|
731a10a4ea | ||
|
|
a1ae58448c | ||
|
|
805cdde0b7 | ||
|
|
29335d8f5c | ||
|
|
c5f47b2a4e | ||
|
|
df5b1a9a69 | ||
|
|
04b34077d8 | ||
|
|
9d813310bb | ||
|
|
ef8a499eac | ||
|
|
698da13d66 | ||
|
|
8295486fdb | ||
|
|
7704a9d054 | ||
|
|
f7ffc4fe4d | ||
|
|
62cb5eac47 | ||
|
|
03ea717742 | ||
|
|
e389f7a50c | ||
|
|
0b1c8bcac3 | ||
|
|
857d8e3a56 | ||
|
|
ec6e51b3a4 | ||
|
|
f8054cca80 | ||
|
|
59ebcfd744 | ||
|
|
205beacc5b | ||
|
|
3b3f357de9 | ||
|
|
48b92acf8c | ||
|
|
4eed2d7be0 | ||
|
|
bc82ae8b0b | ||
|
|
590e267902 | ||
|
|
3be7ec4162 | ||
|
|
dd8e1def67 | ||
|
|
dcd7a69512 | ||
|
|
354ed1e79d | ||
|
|
014132d4c0 | ||
|
|
bc980b59ff | ||
|
|
c3771fb065 | ||
|
|
63755b2a32 | ||
|
|
ce5dd378d9 | ||
|
|
c6fe6533f9 | ||
|
|
170a691a7e | ||
|
|
738ef9baf8 | ||
|
|
c7afd0f89a | ||
|
|
6789b29b72 | ||
|
|
960c906da1 | ||
|
|
0f2d3652e5 | ||
|
|
28494f0bd5 | ||
|
|
4fb9af7fb2 | ||
|
|
6fa6b8b178 | ||
|
|
784c3dc012 | ||
|
|
7a9b323931 | ||
|
|
e75ec636db | ||
|
|
5dda0212f6 | ||
|
|
011965d864 |
@@ -1,16 +0,0 @@
|
||||
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,2 +1,6 @@
|
||||
# Normalize EOL for all files that Git considers text files
|
||||
* text=auto eol=lf
|
||||
*.c eol=lf
|
||||
*.cpp eol=lf
|
||||
*.gd eol=lf
|
||||
*.tscn eol=lf
|
||||
*.cfg eol=lf
|
||||
*.godot eol=lf
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -9,7 +9,7 @@ body:
|
||||
- Write a descriptive issue title above.
|
||||
- The golden rule is to **always open *one* issue for *one* bug**. If you notice several bugs and want to report them, make sure to create one new issue for each of them.
|
||||
- Search [open](https://github.com/godotengine/godot-cpp/issues) and [closed](https://github.com/godotengine/godot-cpp/issues?q=is%3Aissue+is%3Aclosed) issues to ensure it has not already been reported. If you don't find a relevant match or if you're unsure, don't hesitate to **open a new issue**. The bugsquad will handle it from there if it's a duplicate.
|
||||
- Verify that you are using a [supported Godot version](https://docs.godotengine.org/en/latest/about/release_policy.html).
|
||||
- Verify that you are using a [supported Godot version](https://docs.godotengine.org/en/stable/about/release_policy.html).
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
|
||||
24
.github/actions/godot-cache-restore/action.yml
vendored
24
.github/actions/godot-cache-restore/action.yml
vendored
@@ -1,24 +0,0 @@
|
||||
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
18
.github/actions/godot-cache-save/action.yml
vendored
@@ -1,18 +0,0 @@
|
||||
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
Normal file
22
.github/actions/godot-cache/action.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
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
62
.github/actions/setup-godot-cpp/action.yml
vendored
@@ -1,62 +0,0 @@
|
||||
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
|
||||
139
.github/workflows/ci.yml
vendored
139
.github/workflows/ci.yml
vendored
@@ -1,18 +1,12 @@
|
||||
name: Continuous integration
|
||||
on:
|
||||
workflow_call:
|
||||
on: [push, pull_request]
|
||||
|
||||
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: master
|
||||
# Use UTF-8 on Linux.
|
||||
LANG: en_US.UTF-8
|
||||
LC_ALL: en_US.UTF-8
|
||||
|
||||
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:
|
||||
@@ -24,7 +18,7 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- name: 🐧 Linux (GCC)
|
||||
os: ubuntu-22.04
|
||||
os: ubuntu-20.04
|
||||
platform: linux
|
||||
artifact-name: godot-cpp-linux-glibc2.27-x86_64-release
|
||||
artifact-path: bin/libgodot-cpp.linux.template_release.x86_64.a
|
||||
@@ -32,7 +26,7 @@ jobs:
|
||||
cache-name: linux-x86_64
|
||||
|
||||
- name: 🐧 Linux (GCC, Double Precision)
|
||||
os: ubuntu-22.04
|
||||
os: ubuntu-20.04
|
||||
platform: linux
|
||||
artifact-name: godot-cpp-linux-glibc2.27-x86_64-double-release
|
||||
artifact-path: bin/libgodot-cpp.linux.template_release.double.x86_64.a
|
||||
@@ -58,7 +52,7 @@ jobs:
|
||||
cache-name: windows-x86_64-mingw
|
||||
|
||||
- name: 🍎 macOS (universal)
|
||||
os: macos-latest
|
||||
os: macos-11
|
||||
platform: macos
|
||||
artifact-name: godot-cpp-macos-universal-release
|
||||
artifact-path: bin/libgodot-cpp.macos.template_release.universal.a
|
||||
@@ -67,7 +61,7 @@ jobs:
|
||||
cache-name: macos-universal
|
||||
|
||||
- name: 🤖 Android (arm64)
|
||||
os: ubuntu-22.04
|
||||
os: ubuntu-20.04
|
||||
platform: android
|
||||
artifact-name: godot-cpp-android-arm64-release
|
||||
artifact-path: bin/libgodot-cpp.android.template_release.arm64.a
|
||||
@@ -76,7 +70,7 @@ jobs:
|
||||
cache-name: android-arm64
|
||||
|
||||
- name: 🍏 iOS (arm64)
|
||||
os: macos-latest
|
||||
os: macos-11
|
||||
platform: ios
|
||||
artifact-name: godot-cpp-ios-arm64-release
|
||||
artifact-path: bin/libgodot-cpp.ios.template_release.arm64.a
|
||||
@@ -85,7 +79,7 @@ jobs:
|
||||
cache-name: ios-arm64
|
||||
|
||||
- name: 🌐 Web (wasm32)
|
||||
os: ubuntu-22.04
|
||||
os: ubuntu-20.04
|
||||
platform: web
|
||||
artifact-name: godot-cpp-web-wasm32-release
|
||||
artifact-path: bin/libgodot-cpp.web.template_release.wasm32.a
|
||||
@@ -95,6 +89,7 @@ jobs:
|
||||
env:
|
||||
SCONS_CACHE: ${{ github.workspace }}/.scons-cache/
|
||||
EM_VERSION: 3.1.39
|
||||
EM_CACHE_FOLDER: "emsdk-cache"
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -102,17 +97,40 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Restore Godot build cache
|
||||
uses: ./.github/actions/godot-cache-restore
|
||||
- name: Setup Godot build cache
|
||||
uses: ./.github/actions/godot-cache
|
||||
with:
|
||||
cache-name: ${{ matrix.cache-name }}
|
||||
continue-on-error: true
|
||||
|
||||
- name: Setup godot-cpp
|
||||
uses: ./.github/actions/setup-godot-cpp
|
||||
- name: Set up Python (for SCons)
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
platform: ${{ matrix.platform }}
|
||||
windows-compiler: ${{ contains(matrix.flags, 'use_mingw=yes') && 'mingw' || 'msvc' }}
|
||||
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@v14
|
||||
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
|
||||
|
||||
- name: Generate godot-cpp sources only
|
||||
run: |
|
||||
@@ -133,15 +151,9 @@ jobs:
|
||||
cd test
|
||||
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 && env.GODOT_TEST_VERSION == 'master'
|
||||
if: ${{ matrix.run-tests }}
|
||||
with:
|
||||
repo: godotengine/godot
|
||||
branch: master
|
||||
@@ -154,39 +166,50 @@ jobs:
|
||||
ensure_latest: true
|
||||
path: godot-artifacts
|
||||
|
||||
- name: Prepare Godot artifacts for testing
|
||||
if: matrix.run-tests && env.GODOT_TEST_VERSION == 'master'
|
||||
- name: Run tests
|
||||
if: ${{ matrix.run-tests }}
|
||||
run: |
|
||||
chmod +x ./godot-artifacts/godot.linuxbsd.editor.x86_64.mono
|
||||
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
|
||||
./godot-artifacts/godot.linuxbsd.editor.x86_64.mono --headless --version
|
||||
cd test
|
||||
# Need to run the editor so .godot is generated... but it crashes! Ignore that :-)
|
||||
(cd project && (timeout 30 $GODOT --import --headless >/dev/null 2>&1 || true))
|
||||
./run-tests.sh
|
||||
(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
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ matrix.artifact-name }}
|
||||
path: ${{ matrix.artifact-path }}
|
||||
if-no-files-found: error
|
||||
|
||||
linux-cmake:
|
||||
name: 🐧 Build (Linux, GCC, CMake)
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -qqq build-essential pkg-config cmake
|
||||
|
||||
- name: Build godot-cpp
|
||||
run: |
|
||||
cmake -DCMAKE_BUILD_TYPE=Release .
|
||||
make -j $(nproc) VERBOSE=1
|
||||
|
||||
- name: Build test GDExtension library
|
||||
run: |
|
||||
cd test && cmake -DCMAKE_BUILD_TYPE=Release -DGODOT_HEADERS_PATH="../godot-headers" -DCPP_BINDINGS_PATH=".." .
|
||||
make -j $(nproc) VERBOSE=1
|
||||
|
||||
linux-cmake-ninja:
|
||||
name: 🐧 Build (Linux, GCC, CMake Ninja)
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -198,12 +221,15 @@ jobs:
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -qqq build-essential pkg-config cmake ninja-build
|
||||
|
||||
- name: Build godot-cpp
|
||||
run: |
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -GNinja .
|
||||
cmake --build . -j $(nproc) --verbose
|
||||
|
||||
- name: Build test GDExtension library
|
||||
run: |
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
cmake ../ -DGODOTCPP_ENABLE_TESTING=YES -DGODOTCPP_TARGET=template_release
|
||||
cmake --build . --verbose -j $(nproc) --target godot-cpp-test --config Release
|
||||
cd test && cmake -DCMAKE_BUILD_TYPE=Release -DGODOT_HEADERS_PATH="../godot-headers" -DCPP_BINDINGS_PATH=".." -GNinja .
|
||||
cmake --build . -j $(nproc) --verbose
|
||||
|
||||
windows-msvc-cmake:
|
||||
name: 🏁 Build (Windows, MSVC, CMake)
|
||||
@@ -214,9 +240,12 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Build godot-cpp
|
||||
run: |
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -G"Visual Studio 16 2019" .
|
||||
cmake --build . --verbose
|
||||
|
||||
- name: Build test GDExtension library
|
||||
run: |
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
cmake ../ -DGODOTCPP_ENABLE_TESTING=YES -DGODOTCPP_TARGET=template_release
|
||||
cmake --build . --verbose --target godot-cpp-test --config Release
|
||||
cd test && cmake -DCMAKE_BUILD_TYPE=Release -DGODOT_HEADERS_PATH="../godot-headers" -DCPP_BINDINGS_PATH=".." -G"Visual Studio 16 2019" .
|
||||
cmake --build . --verbose
|
||||
|
||||
21
.github/workflows/runner.yml
vendored
21
.github/workflows/runner.yml
vendored
@@ -1,21 +0,0 @@
|
||||
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,38 +1,54 @@
|
||||
name: 📊 Static Checks
|
||||
on:
|
||||
workflow_call:
|
||||
on: [push, pull_request]
|
||||
|
||||
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, ruff format, file format)
|
||||
runs-on: ubuntu-22.04
|
||||
name: Format (clang-format, black format, file format)
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Get changed files
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# Azure repositories are not reliable, we need to prevent Azure giving us packages.
|
||||
- name: Make apt sources.list use the default Ubuntu repositories
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" == "pull_request" ]; then
|
||||
files=$(git diff-tree --no-commit-id --name-only -r HEAD^1..HEAD 2> /dev/null || true)
|
||||
elif [ "${{ github.event_name }}" == "push" -a "${{ github.event.forced }}" == "false" -a "${{ github.event.created }}" == "false" ]; then
|
||||
files=$(git diff-tree --no-commit-id --name-only -r ${{ github.event.before }}..${{ github.event.after }} 2> /dev/null || true)
|
||||
fi
|
||||
files=$(echo "$files" | grep -v 'thirdparty' | xargs -I {} sh -c 'echo "\"./{}\""' | tr '\n' ' ')
|
||||
echo "CHANGED_FILES=$files" >> $GITHUB_ENV
|
||||
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
|
||||
|
||||
- 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: 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: Check generated files consistency
|
||||
run:
|
||||
python misc/scripts/check_get_file_list.py
|
||||
- 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
|
||||
|
||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -8,7 +8,7 @@
|
||||
include/gen
|
||||
src/gen
|
||||
|
||||
# Build configuration.
|
||||
# Build configuarion.
|
||||
/custom.py
|
||||
|
||||
# Misc
|
||||
@@ -195,10 +195,3 @@ compile_commands.json
|
||||
# Python development
|
||||
.venv
|
||||
venv
|
||||
|
||||
# Clion Configuration
|
||||
.idea/
|
||||
cmake-build*/
|
||||
|
||||
# CMake related
|
||||
CMakeUserPresets.json
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
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: https://github.com/BlankSpruce/gersemi
|
||||
rev: 0.18.2
|
||||
hooks:
|
||||
- id: gersemi
|
||||
args: ["-i", "--no-warn-about-unknown-commands", "-l", "120"]
|
||||
|
||||
- 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]
|
||||
266
CMakeLists.txt
266
CMakeLists.txt
@@ -1,74 +1,216 @@
|
||||
cmake_minimum_required(VERSION 3.17)
|
||||
# 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.
|
||||
|
||||
#[=======================================================================[.rst:
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
project(godot-cpp LANGUAGES CXX)
|
||||
|
||||
CMake Version requirements
|
||||
--------------------------
|
||||
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)
|
||||
|
||||
To enable use of the emscripten emsdk hack for pseudo shared library support
|
||||
without polluting options for consumers we need to use the
|
||||
CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE which was introduced in version 3.17
|
||||
# Add path to modules
|
||||
list( APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" )
|
||||
|
||||
For more information check cmake/emsdkHack.cmake
|
||||
# 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>" )
|
||||
|
||||
SCons Compatibility
|
||||
-------------------
|
||||
|
||||
There is an understandable conflict between build systems as they define
|
||||
similar concepts in different ways. When there isn't a 1:1 relationship,
|
||||
compromises need to be made to resolve those differences.
|
||||
|
||||
As we are attempting to maintain feature parity, and ease of maintenance, these
|
||||
CMake scripts are built to resemble the SCons build system wherever possible.
|
||||
Where they are not, we will attempt to document common difference in
|
||||
doc/cmake.rst and platform specific differences in their respective
|
||||
cmake/<platform>.cmake file.
|
||||
|
||||
The file structure and file content are made to match, if not in content then
|
||||
in spirit. The closer the two build systems look the easier they will be to
|
||||
maintain.
|
||||
|
||||
Where the SCons additional scripts in the tools directory, The CMake scripts
|
||||
are in the cmake directory.
|
||||
|
||||
For example; the tools/godotcpp.py is matched by the cmake/godotcpp.cmake file
|
||||
|
||||
.. highlight:: python
|
||||
|
||||
cpp_tool = Tool("godotcpp", toolpath=["tools"])
|
||||
cpp_tool.options(opts, env)
|
||||
|
||||
The CMake equivalent is below.
|
||||
]=======================================================================]
|
||||
include(cmake/godotcpp.cmake)
|
||||
|
||||
godotcpp_options()
|
||||
|
||||
#[[ People are compiling godot by itself and expecting template_debug
|
||||
Replace this with PROJECT_IS_TOP_LEVEL, <PROJECT-NAME>_IS_TOP_LEVEL when minimum reaches 3.21
|
||||
]]
|
||||
if(NOT PROJECT_NAME)
|
||||
set(GODOTCPP_IS_TOP_LEVEL ON)
|
||||
# Default build type is Debug in the SConstruct
|
||||
if("${CMAKE_BUILD_TYPE}" STREQUAL "")
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
endif()
|
||||
|
||||
# Define our project.
|
||||
project(
|
||||
godot-cpp
|
||||
VERSION 4.4
|
||||
DESCRIPTION "C++ bindings for the Godot Engine's GDExtensions API."
|
||||
HOMEPAGE_URL "https://github.com/godotengine/godot-cpp"
|
||||
LANGUAGES CXX
|
||||
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 OFF "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
|
||||
)
|
||||
|
||||
compiler_detection()
|
||||
godotcpp_generate()
|
||||
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"
|
||||
)
|
||||
|
||||
# Conditionally enable the godot-cpp.test.<target> integration testing targets
|
||||
if(GODOTCPP_ENABLE_TESTING)
|
||||
add_subdirectory(test)
|
||||
# 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)
|
||||
|
||||
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)
|
||||
endif ()
|
||||
|
||||
target_include_directories(${PROJECT_NAME} ${GODOT_CPP_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()
|
||||
|
||||
#[[ If this is the top level CMakeLists.txt, Generators which honor the
|
||||
USE_FOLDERS flag will organize godot-cpp targets under a subfolder named
|
||||
'godot-cpp'. This is enable by default from CMake version 3.26 ]]
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
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}"
|
||||
)
|
||||
|
||||
32
README.md
32
README.md
@@ -1,15 +1,14 @@
|
||||
# godot-cpp
|
||||
|
||||
> [!WARNING]
|
||||
> **Warning**
|
||||
>
|
||||
> This repository's `master` branch is only usable with
|
||||
> [GDExtension](https://godotengine.org/article/introducing-gd-extensions)
|
||||
> from Godot's `master` branch.
|
||||
>
|
||||
> For users of stable branches, switch to the branch matching your target Godot version:
|
||||
> - [`4.2`](https://github.com/godotengine/godot-cpp/tree/4.2)
|
||||
> - [`4.1`](https://github.com/godotengine/godot-cpp/tree/4.1)
|
||||
> - [`4.0`](https://github.com/godotengine/godot-cpp/tree/4.0)
|
||||
> - [`4.1`](https://github.com/godotengine/godot-cpp/tree/4.1)
|
||||
>
|
||||
> Or check out the Git tag matching your Godot version (e.g. `godot-4.1.1-stable`).
|
||||
>
|
||||
@@ -22,7 +21,7 @@ This repository contains the *C++ bindings* for the [**Godot Engine**](https://
|
||||
- [**Compatibility**](#compatibility)
|
||||
- [**Contributing**](#contributing)
|
||||
- [**Getting started**](#getting-started)
|
||||
- [**Examples and templates**](#examples-and-templates)
|
||||
- [**Included example**](#included-example)
|
||||
|
||||
## Versioning
|
||||
|
||||
@@ -49,20 +48,18 @@ Godot version.**
|
||||
|
||||
## Compatibility
|
||||
|
||||
> [!WARNING]
|
||||
>
|
||||
> The GDExtension API is brand new in Godot 4.0, and is still
|
||||
**Warning:** The GDExtension API is brand new in Godot 4.0, and is still
|
||||
considered in **beta** stage, despite Godot 4.0 itself being released.
|
||||
>
|
||||
> This applies to both the GDExtension interface header, the API JSON, and this
|
||||
|
||||
This applies to both the GDExtension interface header, the API JSON, and this
|
||||
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-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.
|
||||
|
||||
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-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.
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -71,7 +68,8 @@ 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 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.
|
||||
Please install clang-format and copy the files in `misc/hooks` into `.git/hooks`
|
||||
so formatting is done before your changes are submitted.
|
||||
|
||||
## Getting started
|
||||
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
#!/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 Exception:
|
||||
except:
|
||||
# Default tools with no platform defaults to gnu toolchain.
|
||||
# We apply platform specific toolchains via our custom tools.
|
||||
env = Environment(tools=["default"], PLATFORM="")
|
||||
@@ -18,7 +23,7 @@ env.PrependENVPath("PATH", os.getenv("PATH"))
|
||||
customs = ["custom.py"]
|
||||
try:
|
||||
customs += Import("customs")
|
||||
except Exception:
|
||||
except:
|
||||
pass
|
||||
profile = ARGUMENTS.get("profile", "")
|
||||
if profile:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
183
build_profile.py
183
build_profile.py
@@ -1,183 +0,0 @@
|
||||
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)
|
||||
@@ -1,176 +0,0 @@
|
||||
#[=======================================================================[.rst:
|
||||
GodotCPPModule.cmake
|
||||
---------------------
|
||||
|
||||
This file contains functions and tests which may be needed by consumers.
|
||||
|
||||
* Generate Trimmed API
|
||||
* Generate File List
|
||||
* Generate Bindings
|
||||
|
||||
If you want to use these functions in your project extend the CMAKE_MODULE_PATH
|
||||
by adding these two lines into your CMakeLists.txt after the inclusion
|
||||
godot-cpp
|
||||
|
||||
.. highlight:: cmake
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${godot-cpp_SOURCE_DIR}/cmake")
|
||||
include( GodotCPPModule )
|
||||
|
||||
]=======================================================================]
|
||||
find_package(Python3 3.4 REQUIRED) # pathlib should be present
|
||||
|
||||
#[[ Generate Trimmed API
|
||||
|
||||
The build_profile.py has a __main__ and is used as a tool
|
||||
Its usage is listed as:
|
||||
$ python build_profile.py BUILD_PROFILE INPUT_JSON [OUTPUT_JSON]
|
||||
]]
|
||||
function(build_profile_generate_trimmed_api BUILD_PROFILE INPUT_JSON OUTPUT_JSON)
|
||||
execute_process(
|
||||
COMMAND
|
||||
"${Python3_EXECUTABLE}" "${godot-cpp_SOURCE_DIR}/build_profile.py" "${BUILD_PROFILE}" "${INPUT_JSON}"
|
||||
"${OUTPUT_JSON}"
|
||||
WORKING_DIRECTORY ${godot-cpp_SOURCE_DIR}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
#[[ Generate File List
|
||||
|
||||
Use the binding_generator.py Python script to determine the list of files that
|
||||
will be passed to the code generator using extension_api.json.
|
||||
NOTE: This happens for every configure.]]
|
||||
function(binding_generator_get_file_list OUT_VAR_NAME API_FILEPATH OUTPUT_DIR)
|
||||
# This code snippet will be squashed into a single line
|
||||
# The two strings make this a list, in CMake lists are semicolon delimited strings.
|
||||
set(PYTHON_SCRIPT
|
||||
"from binding_generator import print_file_list"
|
||||
"print_file_list( api_filepath='${API_FILEPATH}',
|
||||
output_dir='${OUTPUT_DIR}',
|
||||
headers=True,
|
||||
sources=True)"
|
||||
)
|
||||
message(DEBUG "Python:\n${PYTHON_SCRIPT}")
|
||||
|
||||
# Strip newlines and whitespace to make it a one-liner.
|
||||
string(REGEX REPLACE "\n *" " " PYTHON_SCRIPT "${PYTHON_SCRIPT}")
|
||||
|
||||
execute_process(
|
||||
COMMAND "${Python3_EXECUTABLE}" "-c" "${PYTHON_SCRIPT}"
|
||||
WORKING_DIRECTORY "${godot-cpp_SOURCE_DIR}"
|
||||
OUTPUT_VARIABLE GENERATED_FILES_LIST
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
# Debug output
|
||||
message(DEBUG "FileList-Begin")
|
||||
foreach(PATH ${GENERATED_FILES_LIST})
|
||||
message(DEBUG ${PATH})
|
||||
endforeach()
|
||||
|
||||
# Error out if the file list generator returned no files.
|
||||
list(LENGTH GENERATED_FILES_LIST LIST_LENGTH)
|
||||
if(NOT LIST_LENGTH GREATER 0)
|
||||
message(FATAL_ERROR "File List Generation Failed")
|
||||
endif()
|
||||
message(STATUS "There are ${LIST_LENGTH} Files to generate")
|
||||
|
||||
set(${OUT_VAR_NAME} ${GENERATED_FILES_LIST} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
#[[ Generate Bindings
|
||||
|
||||
Using the generated file list, use the binding_generator.py to generate the
|
||||
godot-cpp bindings. This will run at build time only if there are files
|
||||
missing. ]]
|
||||
function(
|
||||
binding_generator_generate_bindings
|
||||
API_FILE
|
||||
USE_TEMPLATE_GET_NODE,
|
||||
BITS,
|
||||
PRECISION,
|
||||
OUTPUT_DIR
|
||||
)
|
||||
# This code snippet will be squashed into a single line
|
||||
set(PYTHON_SCRIPT
|
||||
"from binding_generator import generate_bindings"
|
||||
"generate_bindings(
|
||||
api_filepath='${API_FILE}',
|
||||
use_template_get_node='${USE_TEMPLATE_GET_NODE}',
|
||||
bits='${BITS}',
|
||||
precision='${PRECISION}',
|
||||
output_dir='${OUTPUT_DIR}')"
|
||||
)
|
||||
|
||||
message(DEBUG "Python:\n${PYTHON_SCRIPT}")
|
||||
|
||||
# Strip newlines and whitespace to make it a one-liner.
|
||||
string(REGEX REPLACE "\n *" " " PYTHON_SCRIPT "${PYTHON_SCRIPT}")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${GENERATED_FILES_LIST}
|
||||
COMMAND "${Python3_EXECUTABLE}" "-c" "${PYTHON_SCRIPT}"
|
||||
VERBATIM
|
||||
WORKING_DIRECTORY ${godot-cpp_SOURCE_DIR}
|
||||
MAIN_DEPENDENCY ${GODOTCPP_GDEXTENSION_API_FILE}
|
||||
DEPENDS ${godot-cpp_SOURCE_DIR}/binding_generator.py
|
||||
COMMENT "Generating bindings"
|
||||
)
|
||||
add_custom_target(generate_bindings DEPENDS ${GENERATED_FILES_LIST})
|
||||
set_target_properties(generate_bindings PROPERTIES FOLDER "godot-cpp")
|
||||
endfunction()
|
||||
|
||||
#[[ Generate doc_data.cpp
|
||||
The documentation displayed in the Godot editor is compiled into the extension.
|
||||
It takes a list of XML source files, and transforms them into a cpp file that
|
||||
is added to the sources list.]]
|
||||
function(generate_doc_source OUTPUT_PATH SOURCES)
|
||||
# Transform SOURCES CMake LIST
|
||||
# quote each path with ''
|
||||
# join with , to transform into a python list minus the surrounding []
|
||||
set(PYTHON_LIST "${SOURCES}")
|
||||
list(TRANSFORM PYTHON_LIST REPLACE "(.*\.xml)" "'\\1'")
|
||||
list(JOIN PYTHON_LIST "," PYTHON_LIST)
|
||||
|
||||
get_filename_component(OUTPUT_DIR "${OUTPUT_PATH}" DIRECTORY)
|
||||
file(MAKE_DIRECTORY ${OUTPUT_DIR})
|
||||
|
||||
# Python one-liner to run our command
|
||||
# lists in CMake are just strings delimited by ';', so this works.
|
||||
set(PYTHON_SCRIPT
|
||||
"from doc_source_generator import generate_doc_source"
|
||||
"generate_doc_source( '${OUTPUT_PATH}', [${PYTHON_LIST}] )"
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${OUTPUT_PATH}"
|
||||
COMMAND "${Python3_EXECUTABLE}" "-c" "${PYTHON_SCRIPT}"
|
||||
VERBATIM
|
||||
WORKING_DIRECTORY "${godot-cpp_SOURCE_DIR}"
|
||||
DEPENDS #
|
||||
"${godot-cpp_SOURCE_DIR}/doc_source_generator.py"
|
||||
"${SOURCES}"
|
||||
COMMENT "Generating: ${OUTPUT_PATH}"
|
||||
)
|
||||
add_custom_target(generate_doc_source DEPENDS "${OUTPUT_PATH}")
|
||||
set_target_properties(generate_doc_source PROPERTIES FOLDER "godot-cpp")
|
||||
endfunction()
|
||||
|
||||
#[[ target_doc_sources
|
||||
A simpler interface to add xml files as doc source to a output target.
|
||||
TARGET: The gdexension library target
|
||||
SOURCES: a list of xml files to use for source generation and inclusion.]]
|
||||
function(target_doc_sources TARGET SOURCES)
|
||||
# set the generated file name
|
||||
set(DOC_SOURCE_FILE "${CMAKE_CURRENT_BINARY_DIR}/gen/doc_source.cpp")
|
||||
|
||||
# Create the file generation target, this won't be triggered unless a target
|
||||
# that depends on DOC_SOURCE_FILE is built
|
||||
generate_doc_source( "${DOC_SOURCE_FILE}" ${SOURCES} )
|
||||
|
||||
# Add DOC_SOURCE_FILE as a dependency to TARGET
|
||||
target_sources(${TARGET} PRIVATE "${DOC_SOURCE_FILE}")
|
||||
|
||||
# Without adding this dependency to the doc_source_generator, XCode will complain.
|
||||
add_dependencies(${TARGET} generate_doc_source)
|
||||
endfunction()
|
||||
94
cmake/GodotCompilerWarnings.cmake
Normal file
94
cmake/GodotCompilerWarnings.cmake
Normal file
@@ -0,0 +1,94 @@
|
||||
# Add warnings based on compiler & version
|
||||
# Set some helper variables for readability
|
||||
set( compiler_less_than_v8 "$<VERSION_LESS:$<CXX_COMPILER_VERSION>,8>" )
|
||||
set( compiler_greater_than_or_equal_v9 "$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,9>" )
|
||||
set( compiler_greater_than_or_equal_v11 "$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,11>" )
|
||||
set( compiler_less_than_v11 "$<VERSION_LESS:$<CXX_COMPILER_VERSION>,11>" )
|
||||
set( compiler_greater_than_or_equal_v12 "$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,12>" )
|
||||
|
||||
# These compiler options reflect what is in godot/SConstruct.
|
||||
target_compile_options( ${PROJECT_NAME} PRIVATE
|
||||
# MSVC only
|
||||
$<${compiler_is_msvc}:
|
||||
/W4
|
||||
|
||||
# Disable warnings which we don't plan to fix.
|
||||
/wd4100 # C4100 (unreferenced formal parameter): Doesn't play nice with polymorphism.
|
||||
/wd4127 # C4127 (conditional expression is constant)
|
||||
/wd4201 # C4201 (non-standard nameless struct/union): Only relevant for C89.
|
||||
/wd4244 # C4244 C4245 C4267 (narrowing conversions): Unavoidable at this scale.
|
||||
/wd4245
|
||||
/wd4267
|
||||
/wd4305 # C4305 (truncation): double to float or real_t, too hard to avoid.
|
||||
/wd4514 # C4514 (unreferenced inline function has been removed)
|
||||
/wd4714 # C4714 (function marked as __forceinline not inlined)
|
||||
/wd4820 # C4820 (padding added after construct)
|
||||
>
|
||||
|
||||
# Clang and GNU common options
|
||||
$<$<OR:${compiler_is_clang},${compiler_is_gnu}>:
|
||||
-Wall
|
||||
-Wctor-dtor-privacy
|
||||
-Wextra
|
||||
-Wno-unused-parameter
|
||||
-Wnon-virtual-dtor
|
||||
-Wwrite-strings
|
||||
>
|
||||
|
||||
# Clang only
|
||||
$<${compiler_is_clang}:
|
||||
-Wimplicit-fallthrough
|
||||
-Wno-ordered-compare-function-pointers
|
||||
>
|
||||
|
||||
# GNU only
|
||||
$<${compiler_is_gnu}:
|
||||
-Walloc-zero
|
||||
-Wduplicated-branches
|
||||
-Wduplicated-cond
|
||||
-Wno-misleading-indentation
|
||||
-Wplacement-new=1
|
||||
-Wshadow-local
|
||||
-Wstringop-overflow=4
|
||||
>
|
||||
$<$<AND:${compiler_is_gnu},${compiler_less_than_v8}>:
|
||||
# Bogus warning fixed in 8+.
|
||||
-Wno-strict-overflow
|
||||
>
|
||||
$<$<AND:${compiler_is_gnu},${compiler_greater_than_or_equal_v9}>:
|
||||
-Wattribute-alias=2
|
||||
>
|
||||
$<$<AND:${compiler_is_gnu},${compiler_greater_than_or_equal_v11}>:
|
||||
# Broke on MethodBind templates before GCC 11.
|
||||
-Wlogical-op
|
||||
>
|
||||
$<$<AND:${compiler_is_gnu},${compiler_less_than_v11}>:
|
||||
# Regression in GCC 9/10, spams so much in our variadic templates that we need to outright disable it.
|
||||
-Wno-type-limits
|
||||
>
|
||||
$<$<AND:${compiler_is_gnu},${compiler_greater_than_or_equal_v12}>:
|
||||
# False positives in our error macros, see GH-58747.
|
||||
-Wno-return-type
|
||||
>
|
||||
)
|
||||
|
||||
# Treat warnings as errors
|
||||
function( set_warning_as_error )
|
||||
message( STATUS "[${PROJECT_NAME}] Treating warnings as errors")
|
||||
if ( CMAKE_VERSION VERSION_GREATER_EQUAL "3.24" )
|
||||
set_target_properties( ${PROJECT_NAME}
|
||||
PROPERTIES
|
||||
COMPILE_WARNING_AS_ERROR ON
|
||||
)
|
||||
else()
|
||||
target_compile_options( ${PROJECT_NAME}
|
||||
PRIVATE
|
||||
$<${compiler_is_msvc}:/WX>
|
||||
$<$<OR:${compiler_is_clang},${compiler_is_gnu}>:-Werror>
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
if ( GODOT_CPP_WARNING_AS_ERROR )
|
||||
set_warning_as_error()
|
||||
endif()
|
||||
@@ -1,49 +0,0 @@
|
||||
#[=======================================================================[.rst:
|
||||
Android
|
||||
-------
|
||||
|
||||
This file contains functions for options and configuration for targeting the
|
||||
Android platform
|
||||
|
||||
Configuration of the Android toolchain is done using toolchain files,
|
||||
CMakePresets, or variables on the command line.
|
||||
|
||||
The `Android SDK`_ provides toolchain files to help with configuration.
|
||||
|
||||
CMake has its own `built-in support`_ for cross compiling to the
|
||||
Android platforms.
|
||||
|
||||
.. warning::
|
||||
|
||||
Android does not support or test the CMake built-in workflow, recommend
|
||||
using their toolchain file.
|
||||
|
||||
.. _Android SDK:https://developer.android.com/ndk/guides/cmake
|
||||
|
||||
.. _built-in support:https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-android
|
||||
|
||||
There is further information and examples in the doc/cmake.rst file.
|
||||
|
||||
]=======================================================================]
|
||||
|
||||
#[============================[ Android Options ]============================]
|
||||
function(android_options)
|
||||
#[[ Options from SCons
|
||||
|
||||
The options below are managed by CMake toolchain files, doc.cmake.rst has
|
||||
more information
|
||||
|
||||
android_api_level : Target Android API level.
|
||||
Default = 21
|
||||
|
||||
ANDROID_HOME : Path to your Android SDK installation.
|
||||
Default = os.environ.get("ANDROID_HOME", os.environ.get("ANDROID_SDK_ROOT")
|
||||
]]
|
||||
endfunction()
|
||||
|
||||
#[===========================[ Target Generation ]===========================]
|
||||
function(android_generate)
|
||||
target_compile_definitions(godot-cpp PUBLIC ANDROID_ENABLED UNIX_ENABLED)
|
||||
|
||||
common_compiler_flags()
|
||||
endfunction()
|
||||
@@ -1,192 +0,0 @@
|
||||
#[=======================================================================[.rst:
|
||||
Common Compiler Flags
|
||||
---------------------
|
||||
|
||||
This file contains host platform toolchain and target platform agnostic
|
||||
configuration. It includes flags like optimization levels, warnings, and
|
||||
features. For target platform specific flags look to each of the
|
||||
``cmake/<platform>.cmake`` files.
|
||||
|
||||
The default compile and link options CMake adds can be found in the
|
||||
platform modules_. When a project is created it initializes its variables from
|
||||
the ``CMAKE_*`` values. The cleanest way I have found to alter these defaults
|
||||
is the use of the ``CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE`` as demonstrated by
|
||||
the emsdkHack.cmake to overcome the limitation on shared library creation.
|
||||
|
||||
So far the emsdkHack is the only modification to the defaults we have made.
|
||||
|
||||
.. _modules: https://github.com/Kitware/CMake/blob/master/Modules/Platform/
|
||||
|
||||
]=======================================================================]
|
||||
|
||||
#[[ Compiler Configuration, not to be confused with build targets ]]
|
||||
set(DEBUG_SYMBOLS "$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>")
|
||||
|
||||
#[[ Compiler Identification ]]
|
||||
set(IS_CLANG "$<CXX_COMPILER_ID:Clang>")
|
||||
set(IS_APPLECLANG "$<CXX_COMPILER_ID:AppleClang>")
|
||||
set(IS_GNU "$<CXX_COMPILER_ID:GNU>")
|
||||
set(IS_MSVC "$<CXX_COMPILER_ID:MSVC>")
|
||||
set(NOT_MSVC "$<NOT:$<CXX_COMPILER_ID:MSVC>>")
|
||||
|
||||
set(LT_V8 "$<VERSION_LESS:$<CXX_COMPILER_VERSION>,8>")
|
||||
set(GE_V9 "$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,9>")
|
||||
set(GT_V11 "$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,11>")
|
||||
set(LT_V11 "$<VERSION_LESS:$<CXX_COMPILER_VERSION>,11>")
|
||||
set(GE_V12 "$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,12>")
|
||||
|
||||
#[===========================[ compiler_detection ]===========================]
|
||||
#[[ Check for clang-cl with MSVC frontend
|
||||
The compiler is tested and set when the project command is called.
|
||||
The variable CXX_COMPILER_FRONTEND_VARIANT was introduced in 3.14
|
||||
The generator expression $<CXX_COMPILER_FRONTEND_VARIANT> wasn't introduced
|
||||
until CMake 3.30 so we can't use it yet.
|
||||
|
||||
So to support clang downloaded from llvm.org which uses the MSVC frontend
|
||||
by default, we need to test for it. ]]
|
||||
function(compiler_detection)
|
||||
if(${CMAKE_CXX_COMPILER_ID} STREQUAL Clang)
|
||||
if(${CMAKE_CXX_COMPILER_FRONTEND_VARIANT} STREQUAL MSVC)
|
||||
message("Using clang-cl")
|
||||
set(IS_CLANG "0" PARENT_SCOPE)
|
||||
set(IS_MSVC "1" PARENT_SCOPE)
|
||||
set(NOT_MSVC "0" PARENT_SCOPE)
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
#[=========================[ common_compiler_flags ]=========================]
|
||||
#[[ This function assumes it is being called from within one of the platform
|
||||
generate functions, with all the variables from lower scopes defined. ]]
|
||||
function(common_compiler_flags)
|
||||
# gersemi: off
|
||||
# These compiler options reflect what is in godot/SConstruct.
|
||||
target_compile_options(
|
||||
godot-cpp
|
||||
# The public flag tells CMake that the following options are transient,
|
||||
# and will propagate to consumers.
|
||||
PUBLIC
|
||||
# Disable exception handling. Godot doesn't use exceptions anywhere, and this
|
||||
# saves around 20% of binary size and very significant build time.
|
||||
$<${DISABLE_EXCEPTIONS}:$<${NOT_MSVC}:-fno-exceptions>>
|
||||
|
||||
# Enabling Debug Symbols
|
||||
$<${DEBUG_SYMBOLS}:
|
||||
# Adding dwarf-4 explicitly makes stacktraces work with clang builds,
|
||||
# otherwise addr2line doesn't understand them.
|
||||
$<${NOT_MSVC}:
|
||||
-gdwarf-4
|
||||
$<IF:${IS_DEV_BUILD},-g3,-g2>
|
||||
>
|
||||
>
|
||||
|
||||
$<${IS_DEV_BUILD}:$<${NOT_MSVC}:-fno-omit-frame-pointer -O0>>
|
||||
|
||||
$<${HOT_RELOAD}:$<${IS_GNU}:-fno-gnu-unique>>
|
||||
|
||||
# MSVC only
|
||||
$<${IS_MSVC}:
|
||||
# /MP isn't valid for clang-cl with msvc frontend
|
||||
$<$<CXX_COMPILER_ID:MSVC>:/MP${PROC_N}>
|
||||
|
||||
# Interpret source files as utf-8
|
||||
/utf-8
|
||||
>
|
||||
|
||||
# Warnings below, these do not need to propagate to consumers.
|
||||
PRIVATE
|
||||
$<${IS_MSVC}:
|
||||
/W4 # Warning level 4 (informational) warnings that aren't off by default.
|
||||
|
||||
# Disable warnings which we don't plan to fix.
|
||||
/wd4100 # C4100 (unreferenced formal parameter): Doesn't play nice with polymorphism.
|
||||
/wd4127 # C4127 (conditional expression is constant)
|
||||
/wd4201 # C4201 (non-standard nameless struct/union): Only relevant for C89.
|
||||
/wd4244 # C4244 C4245 C4267 (narrowing conversions): Unavoidable at this scale.
|
||||
/wd4245
|
||||
/wd4267
|
||||
/wd4305 # C4305 (truncation): double to float or real_t, too hard to avoid.
|
||||
/wd4514 # C4514 (unreferenced inline function has been removed)
|
||||
/wd4714 # C4714 (function marked as __forceinline not inlined)
|
||||
/wd4820 # C4820 (padding added after construct)
|
||||
>
|
||||
|
||||
# Clang and GNU common options
|
||||
$<$<OR:${IS_CLANG},${IS_GNU}>:
|
||||
-Wall
|
||||
-Wctor-dtor-privacy
|
||||
-Wextra
|
||||
-Wno-unused-parameter
|
||||
-Wnon-virtual-dtor
|
||||
-Wwrite-strings
|
||||
>
|
||||
|
||||
# Clang only
|
||||
$<${IS_CLANG}:
|
||||
-Wimplicit-fallthrough
|
||||
-Wno-ordered-compare-function-pointers
|
||||
>
|
||||
|
||||
# GNU only
|
||||
$<${IS_GNU}:
|
||||
-Walloc-zero
|
||||
-Wduplicated-branches
|
||||
-Wduplicated-cond
|
||||
-Wno-misleading-indentation
|
||||
-Wplacement-new=1
|
||||
-Wshadow-local
|
||||
-Wstringop-overflow=4
|
||||
|
||||
# Bogus warning fixed in 8+.
|
||||
$<${LT_V8}:-Wno-strict-overflow>
|
||||
|
||||
$<${GE_V9}:-Wattribute-alias=2>
|
||||
|
||||
# Broke on MethodBind templates before GCC 11.
|
||||
$<${GT_V11}:-Wlogical-op>
|
||||
|
||||
# Regression in GCC 9/10, spams so much in our variadic templates that we need to outright disable it.
|
||||
$<${LT_V11}:-Wno-type-limits>
|
||||
|
||||
# False positives in our error macros, see GH-58747.
|
||||
$<${GE_V12}:-Wno-return-type>
|
||||
>
|
||||
)
|
||||
|
||||
target_compile_definitions(
|
||||
godot-cpp
|
||||
PUBLIC
|
||||
GDEXTENSION
|
||||
|
||||
# features
|
||||
$<${DEBUG_FEATURES}:DEBUG_ENABLED DEBUG_METHODS_ENABLED>
|
||||
|
||||
$<${IS_DEV_BUILD}:DEV_ENABLED>
|
||||
|
||||
$<${HOT_RELOAD}:HOT_RELOAD_ENABLED>
|
||||
|
||||
$<$<STREQUAL:${GODOTCPP_PRECISION},double>:REAL_T_IS_DOUBLE>
|
||||
|
||||
$<${IS_MSVC}:$<${DISABLE_EXCEPTIONS}:_HAS_EXCEPTIONS=0>>
|
||||
|
||||
$<${THREADS_ENABLED}:THREADS_ENABLED>
|
||||
)
|
||||
|
||||
target_link_options(
|
||||
godot-cpp
|
||||
PUBLIC
|
||||
$<${DEBUG_SYMBOLS}:$<${IS_MSVC}:/DEBUG:FULL>>
|
||||
|
||||
$<$<NOT:${DEBUG_SYMBOLS}>:
|
||||
$<${IS_GNU}:-s>
|
||||
$<${IS_CLANG}:-s>
|
||||
$<${IS_APPLECLANG}:-Wl,-S -Wl,-x -Wl,-dead_strip>
|
||||
>
|
||||
PRIVATE
|
||||
$<${IS_MSVC}:
|
||||
/WX # treat link warnings as errors.
|
||||
/MANIFEST:NO # We dont need a manifest
|
||||
>
|
||||
)
|
||||
# gersemi: on
|
||||
endfunction()
|
||||
@@ -1,40 +0,0 @@
|
||||
#[=======================================================================[.rst:
|
||||
emsdkHack
|
||||
---------
|
||||
|
||||
The Emscripten platform doesn't support the use of shared libraries as known by cmake.
|
||||
|
||||
* https://github.com/emscripten-core/emscripten/issues/15276
|
||||
* https://github.com/emscripten-core/emscripten/issues/17804
|
||||
|
||||
This workaround only works due to the way the cmake scripts are loaded.
|
||||
|
||||
Prior to the use of ``project( ... )`` directive we need to set
|
||||
``CMAKE_PROJECT_INCLUDE=cmake/emscripten.cmake``.
|
||||
This file will be loaded after the toolchain overriding the settings that
|
||||
prevent shared library building.
|
||||
|
||||
CMAKE_PROJECT_INCLUDE was Added in version 3.15.
|
||||
``CMAKE_PROJECT_<projectName>_INCLUDE`` was Added in version 3.17:
|
||||
|
||||
More information on cmake's `code injection`_
|
||||
|
||||
.. _code injection:https://cmake.org/cmake/help/latest/command/project.html#code-injection
|
||||
|
||||
Overwrite Shared Library Properties to allow shared libs to be generated.
|
||||
]=======================================================================]
|
||||
if(EMSCRIPTEN)
|
||||
set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE)
|
||||
set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-sSIDE_MODULE=1")
|
||||
set(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "-sSIDE_MODULE=1")
|
||||
set(CMAKE_SHARED_LIBRARY_SUFFIX) # remove the suffix from the shared lib
|
||||
set(CMAKE_STRIP FALSE) # used by default in pybind11 on .so modules
|
||||
|
||||
# The Emscripten toolchain sets the default value for EMSCRIPTEN_SYSTEM_PROCESSOR to x86
|
||||
# and copies that to CMAKE_SYSTEM_PROCESSOR. We don't want that.
|
||||
set(CMAKE_SYSTEM_PROCESSOR "wasm32")
|
||||
# the above prevents the need for logic like:
|
||||
#if( ${CMAKE_SYSTEM_NAME} STREQUAL Emscripten )
|
||||
# set( SYSTEM_ARCH wasm32 )
|
||||
#endif ()
|
||||
endif()
|
||||
@@ -1,390 +0,0 @@
|
||||
#[=======================================================================[.rst:
|
||||
godotcpp.cmake
|
||||
--------------
|
||||
|
||||
As godot-cpp is a C++ project, there are no C files, and detection of a C
|
||||
compiler is unnecessary. When CMake performs the configure process, if a
|
||||
C compiler is specified, like in a toolchain, or from an IDE, then it will
|
||||
print a warning stating that the CMAKE_C_COMPILER compiler is unused.
|
||||
This if statement simply silences that warning.
|
||||
]=======================================================================]
|
||||
if(CMAKE_C_COMPILER)
|
||||
endif()
|
||||
|
||||
#[[ Include Platform Files
|
||||
Because these files are included into the top level CMakeLists.txt before the
|
||||
project directive, it means that
|
||||
|
||||
CMAKE_CURRENT_SOURCE_DIR is the location of godot-cpp's CMakeLists.txt
|
||||
CMAKE_SOURCE_DIR is the location where any prior project() directive was ]]
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/GodotCPPModule.cmake)
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/common_compiler_flags.cmake)
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/android.cmake)
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/ios.cmake)
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/linux.cmake)
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/macos.cmake)
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/web.cmake)
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/windows.cmake)
|
||||
|
||||
# Detect number of processors
|
||||
include(ProcessorCount)
|
||||
ProcessorCount(PROC_MAX)
|
||||
message("Auto-detected ${PROC_MAX} CPU cores available for build parallelism.")
|
||||
|
||||
# List of known platforms
|
||||
set(PLATFORM_LIST
|
||||
linux
|
||||
macos
|
||||
windows
|
||||
android
|
||||
ios
|
||||
web
|
||||
)
|
||||
|
||||
# List of known architectures
|
||||
set(ARCH_LIST
|
||||
x86_32
|
||||
x86_64
|
||||
arm32
|
||||
arm64
|
||||
rv64
|
||||
ppc32
|
||||
ppc64
|
||||
wasm32
|
||||
)
|
||||
|
||||
#[=============================[ godot_arch_name ]=============================]
|
||||
#[[ Function to map CMAKE_SYSTEM_PROCESSOR names to godot arch equivalents ]]
|
||||
function(godot_arch_name OUTVAR)
|
||||
# Special case for macos universal builds that target both x86_64 and arm64
|
||||
if(DEFINED CMAKE_OSX_ARCHITECTURES)
|
||||
if("x86_64" IN_LIST CMAKE_OSX_ARCHITECTURES AND "arm64" IN_LIST CMAKE_OSX_ARCHITECTURES)
|
||||
set(${OUTVAR} "universal" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Direct match early out.
|
||||
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" ARCH)
|
||||
if(ARCH IN_LIST ARCH_LIST)
|
||||
set(${OUTVAR} "${ARCH}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Known aliases
|
||||
set(x86_64 "w64;amd64;x86-64")
|
||||
set(arm32 "armv7;armv7-a")
|
||||
set(arm64 "armv8;arm64v8;aarch64;armv8-a")
|
||||
set(rv64 "rv;riscv;riscv64")
|
||||
set(ppc32 "ppcle;ppc")
|
||||
set(ppc64 "ppc64le")
|
||||
|
||||
if(ARCH IN_LIST x86_64)
|
||||
set(${OUTVAR} "x86_64" PARENT_SCOPE)
|
||||
elseif(ARCH IN_LIST arm32)
|
||||
set(${OUTVAR} "arm32" PARENT_SCOPE)
|
||||
elseif(ARCH IN_LIST arm64)
|
||||
set(${OUTVAR} "arm64" PARENT_SCOPE)
|
||||
elseif(ARCH IN_LIST rv64)
|
||||
set(${OUTVAR} "rv64" PARENT_SCOPE)
|
||||
elseif(ARCH IN_LIST ppc32)
|
||||
set(${OUTVAR} "ppc32" PARENT_SCOPE)
|
||||
elseif(ARCH IN_LIST ppc64)
|
||||
set(${OUTVAR} "ppc64" PARENT_SCOPE)
|
||||
elseif(ARCH MATCHES "86")
|
||||
# Catches x86, i386, i486, i586, i686, etc.
|
||||
set(${OUTVAR} "x86_32" PARENT_SCOPE)
|
||||
else()
|
||||
# Default value is whatever the processor is.
|
||||
set(${OUTVAR} ${CMAKE_SYSTEM_PROCESSOR} PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Function to define all the options.
|
||||
function(godotcpp_options)
|
||||
#NOTE: platform is managed using toolchain files.
|
||||
#NOTE: arch is managed by using toolchain files.
|
||||
# To create a universal build for macos, set CMAKE_OSX_ARCHITECTURES
|
||||
|
||||
set(GODOTCPP_TARGET
|
||||
"template_debug"
|
||||
CACHE STRING
|
||||
"Which target to generate. valid values are: template_debug, template_release, and editor"
|
||||
)
|
||||
set_property(CACHE GODOTCPP_TARGET PROPERTY STRINGS "template_debug;template_release;editor")
|
||||
|
||||
# Input from user for GDExtension interface header and the API JSON file
|
||||
set(GODOTCPP_GDEXTENSION_DIR
|
||||
"gdextension"
|
||||
CACHE PATH
|
||||
"Path to a custom directory containing GDExtension interface header and API JSON file ( /path/to/gdextension_dir )"
|
||||
)
|
||||
set(GODOTCPP_CUSTOM_API_FILE
|
||||
""
|
||||
CACHE FILEPATH
|
||||
"Path to a custom GDExtension API JSON file (takes precedence over `GODOTCPP_GDEXTENSION_DIR`) ( /path/to/custom_api_file )"
|
||||
)
|
||||
|
||||
#TODO generate_bindings
|
||||
|
||||
option(GODOTCPP_GENERATE_TEMPLATE_GET_NODE "Generate a template version of the Node class's get_node. (ON|OFF)" ON)
|
||||
|
||||
#TODO build_library
|
||||
|
||||
set(GODOTCPP_PRECISION "single" CACHE STRING "Set the floating-point precision level (single|double)")
|
||||
|
||||
set(GODOTCPP_THREADS ON CACHE BOOL "Enable threading support")
|
||||
|
||||
#TODO compiledb
|
||||
#TODO compiledb_file
|
||||
|
||||
set(GODOTCPP_BUILD_PROFILE "" CACHE PATH "Path to a file containing a feature build profile")
|
||||
|
||||
set(GODOTCPP_USE_HOT_RELOAD "" CACHE BOOL "Enable the extra accounting required to support hot reload. (ON|OFF)")
|
||||
|
||||
# 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(GODOTCPP_DISABLE_EXCEPTIONS "Force disabling exception handling code (ON|OFF)" ON)
|
||||
|
||||
set(GODOTCPP_SYMBOL_VISIBILITY
|
||||
"hidden"
|
||||
CACHE STRING
|
||||
"Symbols visibility on GNU platforms. Use 'auto' to apply the default value. (auto|visible|hidden)"
|
||||
)
|
||||
set_property(CACHE GODOTCPP_SYMBOL_VISIBILITY PROPERTY STRINGS "auto;visible;hidden")
|
||||
|
||||
#TODO optimize
|
||||
|
||||
option(GODOTCPP_DEV_BUILD "Developer build with dev-only debugging code (DEV_ENABLED)" OFF)
|
||||
|
||||
#[[ debug_symbols
|
||||
Debug symbols are enabled by using the Debug or RelWithDebInfo build configurations.
|
||||
Single Config Generator is set at configure time
|
||||
|
||||
cmake ../ -DCMAKE_BUILD_TYPE=Debug
|
||||
|
||||
Multi-Config Generator is set at build time
|
||||
|
||||
cmake --build . --config Debug
|
||||
|
||||
]]
|
||||
|
||||
# FIXME These options are not present in SCons, and perhaps should be added there.
|
||||
option(GODOTCPP_SYSTEM_HEADERS "Expose headers as SYSTEM." OFF)
|
||||
option(GODOTCPP_WARNING_AS_ERROR "Treat warnings as errors" OFF)
|
||||
|
||||
# Enable Testing
|
||||
option(GODOTCPP_ENABLE_TESTING "Enable the godot-cpp.test.<target> integration testing targets" OFF)
|
||||
|
||||
#[[ Target Platform Options ]]
|
||||
android_options()
|
||||
ios_options()
|
||||
linux_options()
|
||||
macos_options()
|
||||
web_options()
|
||||
windows_options()
|
||||
endfunction()
|
||||
|
||||
#[===========================[ Target Generation ]===========================]
|
||||
function(godotcpp_generate)
|
||||
#[[ Multi-Threaded MSVC Compilation
|
||||
When using the MSVC compiler the build command -j <n> only specifies
|
||||
parallel jobs or targets, and not multi-threaded compilation To speed up
|
||||
compile times on msvc, the /MP <n> flag can be set. But we need to set it
|
||||
at configure time.
|
||||
|
||||
MSVC is true when the compiler is some version of Microsoft Visual C++ or
|
||||
another compiler simulating the Visual C++ cl command-line syntax. ]]
|
||||
if(MSVC)
|
||||
math(EXPR PROC_N "(${PROC_MAX}-1) | (${X}-2)>>31 & 1")
|
||||
message("Using ${PROC_N} cores for multi-threaded compilation.")
|
||||
# TODO You can override it at configure time with ...." )
|
||||
else()
|
||||
message(
|
||||
"Using ${CMAKE_BUILD_PARALLEL_LEVEL} cores, You can override"
|
||||
" it at configure time by using -j <n> or --parallel <n> on the build"
|
||||
" command."
|
||||
)
|
||||
message(" eg. cmake --build . -j 7 ...")
|
||||
endif()
|
||||
|
||||
#[[ GODOTCPP_SYMBOL_VISIBLITY
|
||||
To match the SCons options, the allowed values are "auto", "visible", and "hidden"
|
||||
This effects the compiler flag_ -fvisibility=[default|internal|hidden|protected]
|
||||
The corresponding target option CXX_VISIBILITY_PRESET accepts the compiler values.
|
||||
|
||||
TODO: It is probably worth a pull request which changes both to use the compiler values
|
||||
.. _flag:https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-fvisibility
|
||||
]]
|
||||
if(${GODOTCPP_SYMBOL_VISIBILITY} STREQUAL "auto" OR ${GODOTCPP_SYMBOL_VISIBILITY} STREQUAL "visible")
|
||||
set(GODOTCPP_SYMBOL_VISIBILITY "default")
|
||||
endif()
|
||||
|
||||
# Setup variable to optionally mark headers as SYSTEM
|
||||
set(GODOTCPP_SYSTEM_HEADERS_ATTRIBUTE "")
|
||||
if(GODOTCPP_SYSTEM_HEADERS)
|
||||
set(GODOTCPP_SYSTEM_HEADERS_ATTRIBUTE SYSTEM)
|
||||
endif()
|
||||
|
||||
#[[ Configure Binding Variables ]]
|
||||
# Generate Binding Parameters (True|False)
|
||||
set(USE_TEMPLATE_GET_NODE "False")
|
||||
if(GODOTCPP_GENERATE_TEMPLATE_GET_NODE)
|
||||
set(USE_TEMPLATE_GET_NODE "True")
|
||||
endif()
|
||||
|
||||
# Bits (32|64)
|
||||
math(EXPR BITS "${CMAKE_SIZEOF_VOID_P} * 8") # CMAKE_SIZEOF_VOID_P refers to target architecture.
|
||||
|
||||
# API json File
|
||||
set(GODOTCPP_GDEXTENSION_API_FILE "${GODOTCPP_GDEXTENSION_DIR}/extension_api.json")
|
||||
if(GODOTCPP_CUSTOM_API_FILE) # User-defined override.
|
||||
set(GODOTCPP_GDEXTENSION_API_FILE "${GODOTCPP_CUSTOM_API_FILE}")
|
||||
endif()
|
||||
|
||||
# Build Profile
|
||||
if(GODOTCPP_BUILD_PROFILE)
|
||||
message(STATUS "Using build profile to trim api file")
|
||||
message("\tBUILD_PROFILE = '${GODOTCPP_BUILD_PROFILE}'")
|
||||
message("\tAPI_SOURCE = '${GODOTCPP_GDEXTENSION_API_FILE}'")
|
||||
build_profile_generate_trimmed_api(
|
||||
"${GODOTCPP_BUILD_PROFILE}"
|
||||
"${GODOTCPP_GDEXTENSION_API_FILE}"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/extension_api.json"
|
||||
)
|
||||
set(GODOTCPP_GDEXTENSION_API_FILE "${CMAKE_CURRENT_BINARY_DIR}/extension_api.json")
|
||||
endif()
|
||||
|
||||
message(STATUS "GODOTCPP_GDEXTENSION_API_FILE = '${GODOTCPP_GDEXTENSION_API_FILE}'")
|
||||
|
||||
# generate the file list to use
|
||||
binding_generator_get_file_list( GENERATED_FILES_LIST
|
||||
"${GODOTCPP_GDEXTENSION_API_FILE}"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||
)
|
||||
|
||||
binding_generator_generate_bindings(
|
||||
"${GODOTCPP_GDEXTENSION_API_FILE}"
|
||||
"${USE_TEMPLATE_GET_NODE}"
|
||||
"${BITS}"
|
||||
"${GODOTCPP_PRECISION}"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||
)
|
||||
|
||||
### Platform is derived from the toolchain target
|
||||
# See GeneratorExpressions PLATFORM_ID and CMAKE_SYSTEM_NAME
|
||||
string(
|
||||
CONCAT
|
||||
SYSTEM_NAME
|
||||
"$<$<PLATFORM_ID:Android>:android.${ANDROID_ABI}>"
|
||||
"$<$<PLATFORM_ID:iOS>:ios>"
|
||||
"$<$<PLATFORM_ID:Linux>:linux>"
|
||||
"$<$<PLATFORM_ID:Darwin>:macos>"
|
||||
"$<$<PLATFORM_ID:Emscripten>:web>"
|
||||
"$<$<PLATFORM_ID:Windows>:windows>"
|
||||
"$<$<PLATFORM_ID:Msys>:windows>"
|
||||
)
|
||||
|
||||
# Process CPU architecture argument.
|
||||
godot_arch_name( ARCH_NAME )
|
||||
|
||||
# Transform options into generator expressions
|
||||
set(HOT_RELOAD-UNSET "$<STREQUAL:${GODOTCPP_USE_HOT_RELOAD},>")
|
||||
|
||||
set(DISABLE_EXCEPTIONS "$<BOOL:${GODOTCPP_DISABLE_EXCEPTIONS}>")
|
||||
|
||||
set(THREADS_ENABLED "$<BOOL:${GODOTCPP_THREADS}>")
|
||||
|
||||
# GODOTCPP_DEV_BUILD
|
||||
set(RELEASE_TYPES "Release;MinSizeRel")
|
||||
get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
if(IS_MULTI_CONFIG)
|
||||
message(NOTICE "=> Default build type is Debug. For other build types add --config <type> to build command")
|
||||
elseif(GODOTCPP_DEV_BUILD AND CMAKE_BUILD_TYPE IN_LIST RELEASE_TYPES)
|
||||
message(
|
||||
WARNING
|
||||
"=> GODOTCPP_DEV_BUILD implies a Debug-like build but CMAKE_BUILD_TYPE is '${CMAKE_BUILD_TYPE}'"
|
||||
)
|
||||
endif()
|
||||
set(IS_DEV_BUILD "$<BOOL:${GODOTCPP_DEV_BUILD}>")
|
||||
|
||||
### Define our godot-cpp library targets
|
||||
# Generator Expressions that rely on the target
|
||||
set(DEBUG_FEATURES "$<NOT:$<STREQUAL:${GODOTCPP_TARGET},template_release>>")
|
||||
set(HOT_RELOAD "$<IF:${HOT_RELOAD-UNSET},${DEBUG_FEATURES},$<BOOL:${GODOTCPP_USE_HOT_RELOAD}>>")
|
||||
|
||||
# Suffix
|
||||
string(
|
||||
CONCAT
|
||||
GODOTCPP_SUFFIX
|
||||
"$<1:.${SYSTEM_NAME}>"
|
||||
"$<1:.${GODOTCPP_TARGET}>"
|
||||
"$<${IS_DEV_BUILD}:.dev>"
|
||||
"$<$<STREQUAL:${GODOTCPP_PRECISION},double>:.double>"
|
||||
"$<1:.${ARCH_NAME}>"
|
||||
# TODO IOS_SIMULATOR
|
||||
"$<$<NOT:${THREADS_ENABLED}>:.nothreads>"
|
||||
)
|
||||
|
||||
# the godot-cpp.* library targets
|
||||
add_library(godot-cpp STATIC)
|
||||
|
||||
# Without adding this dependency to the binding generator, XCode will complain.
|
||||
add_dependencies(godot-cpp generate_bindings)
|
||||
|
||||
# Added for backwards compatibility with prior cmake solution so that builds dont immediately break
|
||||
# from a missing target.
|
||||
add_library(godot::cpp ALIAS godot-cpp)
|
||||
|
||||
file(GLOB_RECURSE GODOTCPP_SOURCES LIST_DIRECTORIES NO CONFIGURE_DEPENDS src/*.cpp)
|
||||
|
||||
target_sources(godot-cpp PRIVATE ${GODOTCPP_SOURCES} ${GENERATED_FILES_LIST})
|
||||
|
||||
target_include_directories(
|
||||
godot-cpp
|
||||
${GODOTCPP_SYSTEM_HEADERS_ATTRIBUTE}
|
||||
PUBLIC include ${CMAKE_CURRENT_BINARY_DIR}/gen/include ${GODOTCPP_GDEXTENSION_DIR}
|
||||
)
|
||||
|
||||
# gersemi: off
|
||||
set_target_properties(
|
||||
godot-cpp
|
||||
PROPERTIES
|
||||
CXX_STANDARD 17
|
||||
CXX_EXTENSIONS OFF
|
||||
CXX_VISIBILITY_PRESET ${GODOTCPP_SYMBOL_VISIBILITY}
|
||||
|
||||
COMPILE_WARNING_AS_ERROR ${GODOTCPP_WARNING_AS_ERROR}
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
BUILD_RPATH_USE_ORIGIN ON
|
||||
|
||||
PREFIX "lib"
|
||||
OUTPUT_NAME "${PROJECT_NAME}${GODOTCPP_SUFFIX}"
|
||||
|
||||
ARCHIVE_OUTPUT_DIRECTORY "$<1:${CMAKE_BINARY_DIR}/bin>"
|
||||
|
||||
# Things that are handy to know for dependent targets
|
||||
GODOTCPP_PLATFORM "${SYSTEM_NAME}"
|
||||
GODOTCPP_TARGET "${GODOTCPP_TARGET}"
|
||||
GODOTCPP_ARCH "${ARCH_NAME}"
|
||||
GODOTCPP_PRECISION "${GODOTCPP_PRECISION}"
|
||||
GODOTCPP_SUFFIX "${GODOTCPP_SUFFIX}"
|
||||
|
||||
# Some IDE's respect this property to logically group targets
|
||||
FOLDER "godot-cpp"
|
||||
)
|
||||
# gersemi: on
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL Android)
|
||||
android_generate()
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL iOS)
|
||||
ios_generate()
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL Linux)
|
||||
linux_generate()
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL Darwin)
|
||||
macos_generate()
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL Emscripten)
|
||||
web_generate()
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL Windows)
|
||||
windows_generate()
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -1,36 +0,0 @@
|
||||
#[=======================================================================[.rst:
|
||||
iOS
|
||||
---
|
||||
|
||||
This file contains functions for options and configuration for targeting the
|
||||
iOS platform
|
||||
|
||||
]=======================================================================]
|
||||
|
||||
#[==============================[ iOS Options ]==============================]
|
||||
function(ios_options)
|
||||
#[[ Options from SCons
|
||||
|
||||
TODO ios_simulator: Target iOS Simulator
|
||||
Default: False
|
||||
|
||||
TODO ios_min_version: Target minimum iphoneos/iphonesimulator version
|
||||
Default: 12.0
|
||||
|
||||
TODO IOS_TOOLCHAIN_PATH: Path to iOS toolchain
|
||||
Default: "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain",
|
||||
|
||||
TODO IOS_SDK_PATH: Path to the iOS SDK
|
||||
Default: ''
|
||||
|
||||
TODO ios_triple: Triple for ios toolchain
|
||||
Default: if has_ios_osxcross(): 'ios_triple' else ''
|
||||
]]
|
||||
endfunction()
|
||||
|
||||
#[===========================[ Target Generation ]===========================]
|
||||
function(ios_generate)
|
||||
target_compile_definitions(godot-cpp PUBLIC IOS_ENABLED UNIX_ENABLED)
|
||||
|
||||
common_compiler_flags()
|
||||
endfunction()
|
||||
@@ -1,24 +0,0 @@
|
||||
#[=======================================================================[.rst:
|
||||
Linux
|
||||
-----
|
||||
|
||||
This file contains functions for options and configuration for targeting the
|
||||
Linux platform
|
||||
|
||||
]=======================================================================]
|
||||
|
||||
#[=============================[ Linux Options ]=============================]
|
||||
function(linux_options)
|
||||
#[[ Options from SCons
|
||||
use_llvm : Use the LLVM compiler
|
||||
Not implemented as compiler selection is managed by CMake. Look to
|
||||
doc/cmake.rst for examples.
|
||||
]]
|
||||
endfunction()
|
||||
|
||||
#[===========================[ Target Generation ]===========================]
|
||||
function(linux_generate)
|
||||
target_compile_definitions(godot-cpp PUBLIC LINUX_ENABLED UNIX_ENABLED)
|
||||
|
||||
common_compiler_flags()
|
||||
endfunction()
|
||||
@@ -1,53 +0,0 @@
|
||||
#[=======================================================================[.rst:
|
||||
MacOS
|
||||
-----
|
||||
|
||||
This file contains functions for options and configuration for targeting the
|
||||
MacOS platform
|
||||
|
||||
Universal Builds
|
||||
----------------
|
||||
|
||||
To build universal binaries, ie targeting both x86_64 and arm64, use
|
||||
the CMAKE_OSX_ARCHITECTURES variable prior to any project calls.
|
||||
https://cmake.org/cmake/help/latest/variable/CMAKE_OSX_ARCHITECTURES.html
|
||||
|
||||
]=======================================================================]
|
||||
|
||||
# Find Requirements
|
||||
if(APPLE)
|
||||
set(CMAKE_OSX_SYSROOT $ENV{SDKROOT})
|
||||
find_library(
|
||||
COCOA_LIBRARY
|
||||
REQUIRED
|
||||
NAMES Cocoa
|
||||
PATHS ${CMAKE_OSX_SYSROOT}/System/Library
|
||||
PATH_SUFFIXES Frameworks
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
endif(APPLE)
|
||||
|
||||
#[=============================[ MacOS Options ]=============================]
|
||||
function(macos_options)
|
||||
#[[ Options from SCons
|
||||
TODO macos_deployment_target: macOS deployment target
|
||||
Default: 'default'
|
||||
|
||||
TODO macos_sdk_path: macOS SDK path
|
||||
Default: ''
|
||||
|
||||
TODO osxcross_sdk: OSXCross SDK version
|
||||
Default: if has_osxcross(): "darwin16" else None
|
||||
]]
|
||||
endfunction()
|
||||
|
||||
#[===========================[ Target Generation ]===========================]
|
||||
function(macos_generate)
|
||||
target_compile_definitions(godot-cpp PUBLIC MACOS_ENABLED UNIX_ENABLED)
|
||||
|
||||
target_link_options(godot-cpp PUBLIC -Wl,-undefined,dynamic_lookup)
|
||||
|
||||
target_link_libraries(godot-cpp INTERFACE ${COCOA_LIBRARY})
|
||||
|
||||
common_compiler_flags()
|
||||
endfunction()
|
||||
@@ -1,39 +0,0 @@
|
||||
#[=======================================================================[.rst:
|
||||
Web
|
||||
---
|
||||
|
||||
This file contains functions for options and configuration for targeting the
|
||||
Web platform
|
||||
|
||||
]=======================================================================]
|
||||
|
||||
# Emscripten requires this hack for use of the SHARED option
|
||||
set(CMAKE_PROJECT_godot-cpp_INCLUDE cmake/emsdkHack.cmake)
|
||||
|
||||
#[==============================[ Web Options ]==============================]
|
||||
function(web_options)
|
||||
endfunction()
|
||||
|
||||
#[===========================[ Target Generation ]===========================]
|
||||
function(web_generate)
|
||||
target_compile_definitions(godot-cpp PUBLIC WEB_ENABLED UNIX_ENABLED)
|
||||
|
||||
target_compile_options(
|
||||
godot-cpp
|
||||
PUBLIC #
|
||||
-sSIDE_MODULE
|
||||
-sSUPPORT_LONGJMP=wasm
|
||||
$<${THREADS_ENABLED}:-sUSE_PTHREADS=1>
|
||||
)
|
||||
|
||||
target_link_options(
|
||||
godot-cpp
|
||||
INTERFACE #
|
||||
-sWASM_BIGINT
|
||||
-sSUPPORT_LONGJMP=wasm
|
||||
-fvisibility=hidden
|
||||
-shared
|
||||
)
|
||||
|
||||
common_compiler_flags()
|
||||
endfunction()
|
||||
@@ -1,116 +0,0 @@
|
||||
#[=======================================================================[.rst:
|
||||
Windows
|
||||
-------
|
||||
This file contains functions for options and configuration for targeting the
|
||||
Windows platform
|
||||
|
||||
Because this file is included into the top level CMakelists.txt before the
|
||||
project directive, it means that
|
||||
|
||||
* ``CMAKE_CURRENT_SOURCE_DIR`` is the location of godot-cpp's CMakeLists.txt
|
||||
* ``CMAKE_SOURCE_DIR`` is the location where any prior ``project(...)``
|
||||
directive was
|
||||
|
||||
MSVC Runtime Selection
|
||||
----------------------
|
||||
|
||||
There are two main ways to set the msvc runtime library;
|
||||
Using ``target_compile_options()`` to add the flags
|
||||
or using the ``CMAKE_MSVC_RUNTIME_LIBRARY`` property_ abstraction, introduced
|
||||
in CMake version 3.15 with the policy CMP0091_ to remove the flags from
|
||||
``CMAKE_<LANG>_FLAGS_<CONFIG>``.
|
||||
|
||||
Default: ``CMAKE_MSVC_RUNTIME_LIBRARY="MultiThreaded$<$<CONFIG:Debug>:Debug>DLL"``
|
||||
|
||||
This initializes each target's ``MSVC_RUNTIME_LIBRARY`` property at the time of
|
||||
target creation.
|
||||
|
||||
it is stated in the msvc_ documentation that: "All modules passed to a given
|
||||
invocation of the linker must have been compiled with the same runtime library
|
||||
compiler option (/MD, /MT, /LD)."
|
||||
|
||||
This creates a conundrum for us, the ``CMAKE_MSVC_RUNTIME_LIBRARY`` needs to be
|
||||
correct at the time the target is created, but we have no control over the
|
||||
consumers CMake scripts, and the per-target ``MSVC_RUNTIME_LIBRARY`` property
|
||||
is not transient.
|
||||
|
||||
It has been raised that not using ``CMAKE_MSVC_RUNTIME_LIBRARY`` can also cause
|
||||
issues_ when a dependency( independent to godot-cpp ) that doesn't set any
|
||||
runtime flags, which relies purely on the ``CMAKE_MSVC_RUNTIME_LIBRARY``
|
||||
variable will very likely not have the correct msvc runtime flags set.
|
||||
|
||||
So we'll set ``CMAKE_MSVC_RUNTIME_LIBRARY`` as CACHE STRING so that it will be
|
||||
available for consumer target definitions, but also be able to be overridden if
|
||||
needed.
|
||||
|
||||
Additionally we message consumers notifying them and pointing to this
|
||||
documentation.
|
||||
|
||||
.. _CMP0091:https://cmake.org/cmake/help/latest/policy/CMP0091.html
|
||||
.. _property:https://cmake.org/cmake/help/latest/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html
|
||||
.. https://discourse.cmake.org/t/mt-staticrelease-doesnt-match-value-md-dynamicrelease/5428/4
|
||||
.. _msvc: https://learn.microsoft.com/en-us/cpp/build/reference/md-mt-ld-use-run-time-library
|
||||
.. _issues: https://github.com/godotengine/godot-cpp/issues/1699
|
||||
|
||||
]=======================================================================]
|
||||
|
||||
#[============================[ Windows Options ]============================]
|
||||
function(windows_options)
|
||||
#[[ Options from SCons
|
||||
|
||||
TODO silence_msvc: Silence MSVC's cl/link stdout bloat, redirecting errors to stderr
|
||||
Default: True
|
||||
|
||||
These three options will not implemented as compiler selection is managed
|
||||
by CMake toolchain files. Look to doc/cmake.rst for examples.
|
||||
use_mingw: Use the MinGW compiler instead of MSVC - only effective on Windows
|
||||
use_llvm: Use the LLVM compiler (MVSC or MinGW depending on the use_mingw flag
|
||||
mingw_prefix: MinGW prefix
|
||||
]]
|
||||
|
||||
option(GODOTCPP_USE_STATIC_CPP "Link MinGW/MSVC C++ runtime libraries statically" ON)
|
||||
option(GODOTCPP_DEBUG_CRT "Compile with MSVC's debug CRT (/MDd)" OFF)
|
||||
|
||||
message(
|
||||
STATUS
|
||||
"If not already cached, setting CMAKE_MSVC_RUNTIME_LIBRARY.\n"
|
||||
"\tFor more information please read godot-cpp/cmake/windows.cmake"
|
||||
)
|
||||
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY
|
||||
"MultiThreaded$<IF:$<BOOL:${GODOTCPP_DEBUG_CRT}>,DebugDLL,$<$<NOT:$<BOOL:${GODOTCPP_USE_STATIC_CPP}>>:DLL>>"
|
||||
CACHE STRING
|
||||
"Select the MSVC runtime library for use by compilers targeting the MSVC ABI."
|
||||
)
|
||||
endfunction()
|
||||
|
||||
#[===========================[ Target Generation ]===========================]
|
||||
function(windows_generate)
|
||||
set(STATIC_CPP "$<BOOL:${GODOTCPP_USE_STATIC_CPP}>")
|
||||
|
||||
set_target_properties(godot-cpp PROPERTIES PDB_OUTPUT_DIRECTORY "$<1:${CMAKE_SOURCE_DIR}/bin>")
|
||||
|
||||
target_compile_definitions(
|
||||
godot-cpp
|
||||
PUBLIC WINDOWS_ENABLED $<${IS_MSVC}: TYPED_METHOD_BIND NOMINMAX >
|
||||
)
|
||||
|
||||
# gersemi: off
|
||||
target_link_options(
|
||||
godot-cpp
|
||||
PUBLIC
|
||||
$<${NOT_MSVC}:
|
||||
-Wl,--no-undefined
|
||||
$<${STATIC_CPP}:
|
||||
-static
|
||||
-static-libgcc
|
||||
-static-libstdc++
|
||||
>
|
||||
>
|
||||
|
||||
$<${IS_CLANG}:-lstdc++>
|
||||
)
|
||||
# gersemi: on
|
||||
|
||||
common_compiler_flags()
|
||||
endfunction()
|
||||
353
doc/cmake.rst
353
doc/cmake.rst
@@ -1,353 +0,0 @@
|
||||
CMake
|
||||
=====
|
||||
|
||||
.. warning::
|
||||
|
||||
The CMake scripts do not have feature parity with the SCons ones at this
|
||||
stage and are still a work in progress. There are a number of people who
|
||||
have been working on alternative CMake solutions that are frequently
|
||||
referenced in the discord chats: Ivan's cmake-rewrite_ branch and
|
||||
Vorlac's godot-roguelite_ Project
|
||||
|
||||
.. _cmake-rewrite: https://github.com/IvanInventor/godot-cpp/tree/cmake-rewrite
|
||||
.. _godot-roguelite: https://github.com/vorlac/godot-roguelite
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Compiling godot-cpp independently of an extension project is mainly for
|
||||
godot-cpp developers, package maintainers, and CI/CD. Look to the
|
||||
godot-cpp-template_ for a practical example on how to consume the godot-cpp
|
||||
library as part of a Godot extension.
|
||||
|
||||
Configuration examples are listed at the bottom of the page.
|
||||
|
||||
.. _godot-cpp-template: https://github.com/godotengine/godot-cpp-template
|
||||
|
||||
Debug vs template_debug
|
||||
-----------------------
|
||||
|
||||
Something I've seen come up many times is the conflation of a compilation of c++
|
||||
source code with debug symbols enabled, and compiling a Godot extension with
|
||||
debug features enabled. The two concepts are not mutually inclusive.
|
||||
|
||||
- debug_features
|
||||
Enables a pre-processor definition to selectively compile code to help
|
||||
users of a Godot extension with their own project.
|
||||
|
||||
debug features are enabled in editor and template_debug builds, which can be specified during the configure phase like so
|
||||
|
||||
``cmake -S . -B cmake-build -DGODOTCPP_TARGET=<target choice>``
|
||||
|
||||
- Debug
|
||||
Sets compiler flags so that debug symbols are generated to help godot
|
||||
extension developers debug their extension.
|
||||
|
||||
``Debug`` is the default build type for CMake projects, to select another it depends on the generator used
|
||||
|
||||
For single configuration generators, add to the configure command:
|
||||
|
||||
``-DCMAKE_BUILD_TYPE=<type>``
|
||||
|
||||
For multi-config generators add to the build command:
|
||||
|
||||
``--config <type>``
|
||||
|
||||
where ``<type>`` is one of ``Debug``, ``Release``, ``RelWithDebInfo``, ``MinSizeRel``
|
||||
|
||||
|
||||
SCons Deviations
|
||||
----------------
|
||||
|
||||
Not everything from SCons can be perfectly representable in CMake, here are
|
||||
the notable differences.
|
||||
|
||||
- debug_symbols
|
||||
No longer has an explicit option, and is enabled via Debug-like CMake
|
||||
build configurations; ``Debug``, ``RelWithDebInfo``.
|
||||
|
||||
- dev_build
|
||||
Does not define ``NDEBUG`` when disabled, ``NDEBUG`` is set via Release-like
|
||||
CMake build configurations; ``Release``, ``MinSizeRel``.
|
||||
|
||||
- arch
|
||||
CMake sets the architecture via the toolchain files, macos universal is controlled vua the ``CMAKE_OSX_ARCHITECTURES``
|
||||
property which is copied to targets when they are defined.
|
||||
|
||||
- debug_crt
|
||||
CMake controls linking to windows runtime libraries by copying the value of ``CMAKE_MSVC_RUNTIME_LIBRARIES`` to targets as they are defined.
|
||||
godot-cpp will set this variable if it isn't already set. so include it before other dependencies to have the value propagate across the projects.
|
||||
|
||||
Testing Integration
|
||||
-------------------
|
||||
The testing target ``godot-cpp-test`` is guarded by ``GODOTCPP_ENABLE_TESTING`` which is off by default.
|
||||
|
||||
To configure and build the godot-cpp project to enable the integration
|
||||
testing targets the command will look something like:
|
||||
|
||||
.. code-block::
|
||||
|
||||
# Assuming our current directory is the godot-cpp source root
|
||||
cmake -S . -B cmake-build -DGODOTCPP_ENABLE_TESTING=YES
|
||||
cmake --build cmake-build --target godot-cpp-test
|
||||
|
||||
Basic walkthrough
|
||||
-----------------
|
||||
|
||||
.. topic:: Clone the git repository
|
||||
|
||||
.. code-block::
|
||||
|
||||
git clone https://github.com/godotengine/godot-cpp.git
|
||||
Cloning into 'godot-cpp'...
|
||||
...
|
||||
cd godot-cpp
|
||||
|
||||
.. topic:: Options
|
||||
|
||||
To list the available options CMake use the ``-L[AH]`` option. ``A`` is for
|
||||
advanced, and ``H`` is for help strings.
|
||||
|
||||
.. code-block::
|
||||
|
||||
cmake .. -LH
|
||||
|
||||
Options are specified on the command line when configuring eg.
|
||||
|
||||
.. code-block::
|
||||
|
||||
cmake .. -DGODOTCPP_USE_HOT_RELOAD:BOOL=ON \
|
||||
-DGODOTCPP_PRECISION:STRING=double \
|
||||
-DCMAKE_BUILD_TYPE:STRING=Debug
|
||||
|
||||
Review setting-build-variables_ and build-configurations_ for more information.
|
||||
|
||||
.. _setting-build-variables: https://cmake.org/cmake/help/latest/guide/user-interaction/index.html#setting-build-variables
|
||||
.. _build-configurations: https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#build-configurations
|
||||
|
||||
A non-exhaustive list of options:
|
||||
|
||||
.. code-block::
|
||||
|
||||
// Path to a custom GDExtension API JSON file (takes precedence over `GODOTCPP_GDEXTENSION_DIR`) ( /path/to/custom_api_file )
|
||||
`GODOTCPP_CUSTOM_API_FILE:FILEPATH=`
|
||||
|
||||
// Force disabling exception handling code (ON|OFF)
|
||||
GODOTCPP_DISABLE_EXCEPTIONS:BOOL=ON
|
||||
|
||||
// Path to a custom directory containing GDExtension interface header and API JSON file ( /path/to/gdextension_dir )
|
||||
GODOTCPP_GDEXTENSION_DIR:PATH=gdextension
|
||||
|
||||
// Set the floating-point precision level (single|double)
|
||||
GODOTCPP_PRECISION:STRING=single
|
||||
|
||||
// Enable the extra accounting required to support hot reload. (ON|OFF)
|
||||
GODOTCPP_USE_HOT_RELOAD:BOOL=
|
||||
|
||||
.. topic:: Configure the build
|
||||
|
||||
.. code-block::
|
||||
|
||||
cmake -S . -B cmake-build -G Ninja
|
||||
|
||||
``-S .`` Specifies the source directory
|
||||
|
||||
``-B cmake-build`` Specifies the build directory
|
||||
|
||||
``-G Ninja`` Specifies the Generator
|
||||
|
||||
The source directory in this example is the source code for godot-cpp.
|
||||
The build directory is so that generated files do not clutter up the source tree.
|
||||
CMake doesn't build the code, it generates the files that another tool uses
|
||||
to build the code, in this case Ninja.
|
||||
To see the list of generators run ``cmake --help``.
|
||||
|
||||
.. topic:: Compiling
|
||||
|
||||
Tell cmake to invoke the build system it generated in the specified directory.
|
||||
The default target is template_debug and the default build configuration is Debug.
|
||||
|
||||
.. code-block::
|
||||
|
||||
cmake --build cmake-build
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Windows and MSVC - Release
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
So long as CMake is installed from the `CMake Downloads`_ page and in the PATH,
|
||||
and Microsoft Visual Studio is installed with c++ support, CMake will detect
|
||||
the MSVC compiler.
|
||||
|
||||
Note that Visual Studio is a Multi-Config Generator so the build configuration
|
||||
needs to be specified at build time ie ``--config Release``
|
||||
|
||||
.. _CMake downloads: https://cmake.org/download/
|
||||
|
||||
.. code-block::
|
||||
|
||||
# Assuming our current directory is the godot-cpp source root
|
||||
cmake -S . -B cmake-build -DGODOTCPP_ENABLE_TESTING=YES
|
||||
cmake --build cmake-build -t godot-cpp-test --config Release
|
||||
|
||||
|
||||
MSys2/clang64, "Ninja" - Debug
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Assumes the ming-w64-clang-x86_64-toolchain is installed
|
||||
|
||||
Note that Ninja is a Single-Config Generator so the build type
|
||||
needs to be specified at Configure time.
|
||||
|
||||
Using the msys2/clang64 shell
|
||||
|
||||
.. code-block::
|
||||
|
||||
# Assuming our current directory is the godot-cpp source root
|
||||
cmake -S . -B cmake-build -G"Ninja" -DGODOTCPP_ENABLE_TESTING=YES -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build cmake-build -t godot-cpp-test
|
||||
|
||||
MSys2/clang64, "Ninja Multi-Config" - dev_build, Debug Symbols
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Assumes the ming-w64-clang-x86_64-toolchain is installed
|
||||
|
||||
This time we are choosing the 'Ninja Multi-Config' generator, so the build
|
||||
type is specified at build time.
|
||||
|
||||
Using the msys2/clang64 shell
|
||||
|
||||
.. code-block::
|
||||
|
||||
# Assuming our current directory is the godot-cpp source root
|
||||
cmake -S . -B cmake-build -G"Ninja Multi-Config" -DGODOTCPP_ENABLE_TESTING=YES -DGODOTCPP_DEV_BUILD:BOOL=ON
|
||||
cmake --build cmake-build -t godot-cpp-test --config Debug
|
||||
|
||||
Emscripten for web platform
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
I've only tested this on windows so far.
|
||||
|
||||
I cloned and installed the latest Emscripten tools to ``c:\emsdk``
|
||||
At the time of writing that was v3.1.69
|
||||
|
||||
I've been using ``C:\emsdk\emsdk.ps1 activate latest`` to enable the
|
||||
environment from powershell in the current shell.
|
||||
|
||||
The ``emcmake.bat`` utility adds the emscripten toolchain to the CMake command
|
||||
It can also be added manually, the location is listed inside the emcmake.bat file
|
||||
|
||||
.. code-block::
|
||||
|
||||
# Assuming our current directory is the godot-cpp source root
|
||||
C:\emsdk\emsdk.ps1 activate latest
|
||||
emcmake.bat cmake -S . -B cmake-build-web -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build cmake-build-web
|
||||
|
||||
Android Cross Compile from Windows
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
There are two separate paths you can choose when configuring for android.
|
||||
|
||||
Use the ``CMAKE_ANDROID_*`` variables specified on the commandline or in your
|
||||
own toolchain file as listed in the cmake-toolchains_ documentation
|
||||
|
||||
.. _cmake-toolchains: https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-android-with-the-ndk
|
||||
|
||||
Or use the toolchain and scripts provided by the Android SDK and make changes
|
||||
using the ``ANDROID_*`` variables listed there. Where ``<version>`` is whatever
|
||||
ndk version you have installed (tested with `23.2.8568313`) and ``<platform>``
|
||||
is for android sdk platform, (tested with ``android-29``)
|
||||
|
||||
.. warning::
|
||||
|
||||
The Android SDK website explicitly states that they do not support using
|
||||
the CMake built-in method, and recommends you stick with their toolchain
|
||||
files.
|
||||
|
||||
.. topic:: Using your own toolchain file as described in the CMake documentation
|
||||
|
||||
.. code-block::
|
||||
|
||||
# Assuming our current directory is the godot-cpp source root
|
||||
cmake -S . -B cmake-build --toolchain my_toolchain.cmake
|
||||
cmake --build cmake-build -t template_release
|
||||
|
||||
Doing the equivalent on just using the command line
|
||||
|
||||
.. code-block::
|
||||
|
||||
# Assuming our current directory is the godot-cpp source root
|
||||
cmake -S . -B cmake-build \
|
||||
-DCMAKE_SYSTEM_NAME=Android \
|
||||
-DCMAKE_SYSTEM_VERSION=<platform> \
|
||||
-DCMAKE_ANDROID_ARCH_ABI=<arch> \
|
||||
-DCMAKE_ANDROID_NDK=/path/to/android-ndk
|
||||
cmake --build cmake-build
|
||||
|
||||
.. topic:: Using the toolchain file from the Android SDK
|
||||
|
||||
Defaults to minimum supported version( android-16 in my case) and armv7-a.
|
||||
|
||||
.. code-block::
|
||||
|
||||
# Assuming our current directory is the godot-cpp source root
|
||||
cmake -S . -B cmake-build --toolchain $ANDROID_HOME/ndk/<version>/build/cmake/android.toolchain.cmake
|
||||
cmake --build cmake-build
|
||||
|
||||
Specify Android platform and ABI
|
||||
|
||||
.. code-block::
|
||||
|
||||
# Assuming our current directory is the godot-cpp source root
|
||||
cmake -S . -B cmake-build --toolchain $ANDROID_HOME/ndk/<version>/build/cmake/android.toolchain.cmake \
|
||||
-DANDROID_PLATFORM:STRING=android-29 \
|
||||
-DANDROID_ABI:STRING=armeabi-v7a
|
||||
cmake --build cmake-build
|
||||
|
||||
|
||||
Toolchains
|
||||
----------
|
||||
This section attempts to list the host and target combinations that have been
|
||||
at tested.
|
||||
|
||||
Linux Host
|
||||
~~~~~~~~~~
|
||||
|
||||
Macos Host
|
||||
~~~~~~~~~~
|
||||
|
||||
:System: Mac Mini
|
||||
:OS Name: Sequoia 15.0.1
|
||||
:Processor: Apple M2
|
||||
|
||||
* AppleClang
|
||||
|
||||
Windows Host
|
||||
~~~~~~~~~~~~
|
||||
|
||||
:OS Name: Windows 11
|
||||
:Processor: AMD Ryzen 7 6800HS Creator Edition
|
||||
|
||||
|
||||
* `Microsoft Visual Studio 17 2022 <https://visualstudio.microsoft.com/vs/>`_
|
||||
* `LLVM <https://llvm.org/>`_
|
||||
* `LLVM-MinGW <https://github.com/mstorsjo/llvm-mingw/releases>`_
|
||||
|
||||
* aarch64-w64-mingw32
|
||||
* armv7-w64-mingw32
|
||||
* i686-w64-mingw32
|
||||
* x86_64-w64-mingw32
|
||||
|
||||
* `AndroidSDK <https://developer.android.com/studio/#command-tools>`_
|
||||
* `Emscripten <https://emscripten.org/>`_
|
||||
* `MinGW-W64-builds <https://github.com/niXman/mingw-builds-binaries/releases>`_
|
||||
* `Jetbrains-CLion <https://www.jetbrains.com/clion/>`_
|
||||
|
||||
Jetbrains builtin compiler is just the MingW64 above.
|
||||
|
||||
* `MSYS2 <https://www.msys2.org/>`_
|
||||
Necessary reading about MSYS2 `environments <https://www.msys2.org/docs/environments/>`_
|
||||
|
||||
* ucrt64
|
||||
* clang64
|
||||
* mingw32
|
||||
* mingw64
|
||||
* clangarm64
|
||||
@@ -1,55 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import glob
|
||||
import os
|
||||
import zlib
|
||||
|
||||
|
||||
def generate_doc_source(dst, source):
|
||||
g = open(dst, "w", encoding="utf-8")
|
||||
buf = ""
|
||||
docbegin = ""
|
||||
docend = ""
|
||||
for src in source:
|
||||
src_path = str(src)
|
||||
if not src_path.endswith(".xml"):
|
||||
continue
|
||||
with open(src_path, "r", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
buf += content
|
||||
|
||||
buf = (docbegin + buf + docend).encode("utf-8")
|
||||
decomp_size = len(buf)
|
||||
|
||||
# Use maximum zlib compression level to further reduce file size
|
||||
# (at the cost of initial build times).
|
||||
buf = zlib.compress(buf, zlib.Z_BEST_COMPRESSION)
|
||||
|
||||
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
|
||||
g.write("\n")
|
||||
g.write("#include <godot_cpp/godot.hpp>\n")
|
||||
g.write("\n")
|
||||
|
||||
g.write('static const char *_doc_data_hash = "' + str(hash(buf)) + '";\n')
|
||||
g.write("static const int _doc_data_uncompressed_size = " + str(decomp_size) + ";\n")
|
||||
g.write("static const int _doc_data_compressed_size = " + str(len(buf)) + ";\n")
|
||||
g.write("static const unsigned char _doc_data_compressed[] = {\n")
|
||||
for i in range(len(buf)):
|
||||
g.write("\t" + str(buf[i]) + ",\n")
|
||||
g.write("};\n")
|
||||
g.write("\n")
|
||||
|
||||
g.write(
|
||||
"static godot::internal::DocDataRegistration _doc_data_registration(_doc_data_hash, _doc_data_uncompressed_size, _doc_data_compressed_size, _doc_data_compressed);\n"
|
||||
)
|
||||
g.write("\n")
|
||||
|
||||
g.close()
|
||||
|
||||
|
||||
def scons_generate_doc_source(target, source, env):
|
||||
generate_doc_source(str(target[0]), source)
|
||||
|
||||
|
||||
def generate_doc_source_from_directory(target, directory):
|
||||
generate_doc_source(target, glob.glob(os.path.join(directory, "*.xml")))
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -230,9 +230,7 @@ template <typename T>
|
||||
struct PtrToArg<Ref<T>> {
|
||||
_FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
|
||||
GDExtensionRefPtr ref = (GDExtensionRefPtr)p_ptr;
|
||||
if (unlikely(!p_ptr)) {
|
||||
return Ref<T>();
|
||||
}
|
||||
ERR_FAIL_NULL_V(p_ptr, Ref<T>());
|
||||
return Ref<T>(reinterpret_cast<T *>(godot::internal::get_object_instance_binding(godot::internal::gdextension_interface_ref_get_object(ref))));
|
||||
}
|
||||
|
||||
@@ -256,17 +254,15 @@ struct PtrToArg<const Ref<T> &> {
|
||||
|
||||
_FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
|
||||
GDExtensionRefPtr ref = const_cast<GDExtensionRefPtr>(p_ptr);
|
||||
if (unlikely(!p_ptr)) {
|
||||
return Ref<T>();
|
||||
}
|
||||
ERR_FAIL_NULL_V(p_ptr, Ref<T>());
|
||||
return Ref<T>(reinterpret_cast<T *>(godot::internal::get_object_instance_binding(godot::internal::gdextension_interface_ref_get_object(ref))));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct GetTypeInfo<Ref<T>, typename EnableIf<TypeInherits<RefCounted, T>::value>::type> {
|
||||
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
|
||||
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
|
||||
static const GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
|
||||
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
|
||||
|
||||
static inline PropertyInfo get_class_info() {
|
||||
return make_property_info(Variant::Type::OBJECT, "", PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static());
|
||||
@@ -275,8 +271,8 @@ struct GetTypeInfo<Ref<T>, typename EnableIf<TypeInherits<RefCounted, T>::value>
|
||||
|
||||
template <typename T>
|
||||
struct GetTypeInfo<const Ref<T> &, typename EnableIf<TypeInherits<RefCounted, T>::value>::type> {
|
||||
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
|
||||
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
|
||||
static const GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
|
||||
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
|
||||
|
||||
static inline PropertyInfo get_class_info() {
|
||||
return make_property_info(Variant::Type::OBJECT, "", PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static());
|
||||
|
||||
@@ -36,56 +36,23 @@
|
||||
#include <godot_cpp/core/property_info.hpp>
|
||||
|
||||
#include <godot_cpp/templates/list.hpp>
|
||||
#include <godot_cpp/templates/vector.hpp>
|
||||
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
#if defined(MACOS_ENABLED) && defined(HOT_RELOAD_ENABLED)
|
||||
#include <mutex>
|
||||
#define _GODOT_CPP_AVOID_THREAD_LOCAL
|
||||
#define _GODOT_CPP_THREAD_LOCAL
|
||||
#else
|
||||
#define _GODOT_CPP_THREAD_LOCAL thread_local
|
||||
#endif
|
||||
|
||||
namespace godot {
|
||||
|
||||
class ClassDB;
|
||||
|
||||
typedef void GodotObject;
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_base_of<::godot::Wrapped, T>::value, bool> = true>
|
||||
_ALWAYS_INLINE_ void _pre_initialize();
|
||||
|
||||
// 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 *);
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_base_of<::godot::Wrapped, T>::value, bool>>
|
||||
friend _ALWAYS_INLINE_ void _pre_initialize();
|
||||
|
||||
#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
|
||||
static std::recursive_mutex _constructing_mutex;
|
||||
#endif
|
||||
|
||||
_GODOT_CPP_THREAD_LOCAL static const StringName *_constructing_extension_class_name;
|
||||
_GODOT_CPP_THREAD_LOCAL static const GDExtensionInstanceBindingCallbacks *_constructing_class_binding_callbacks;
|
||||
|
||||
#ifdef HOT_RELOAD_ENABLED
|
||||
_GODOT_CPP_THREAD_LOCAL static GDExtensionObjectPtr _constructing_recreate_owner;
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
_ALWAYS_INLINE_ static void _set_construct_info() {
|
||||
_constructing_extension_class_name = T::_get_extension_class_name();
|
||||
_constructing_class_binding_callbacks = &T::_gde_binding_callbacks;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool _is_extension_class() const { return false; }
|
||||
static const StringName *_get_extension_class_name(); // This is needed to retrieve the class name before the godot object has its _extension and _extension_instance members assigned.
|
||||
virtual const StringName *_get_extension_class_name() const; // This is needed to retrieve the class name before the godot object has its _extension and _extension_instance members assigned.
|
||||
virtual const GDExtensionInstanceBindingCallbacks *_get_bindings_callbacks() const = 0;
|
||||
|
||||
void _notification(int p_what) {}
|
||||
bool _set(const StringName &p_name, const Variant &p_property) { return false; }
|
||||
@@ -93,22 +60,20 @@ protected:
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const {}
|
||||
bool _property_can_revert(const StringName &p_name) const { return false; }
|
||||
bool _property_get_revert(const StringName &p_name, Variant &r_property) const { return false; }
|
||||
void _validate_property(PropertyInfo &p_property) const {}
|
||||
String _to_string() const { return "[" + String(get_class_static()) + ":" + itos(get_instance_id()) + "]"; }
|
||||
|
||||
static void notification_bind(GDExtensionClassInstancePtr p_instance, int32_t p_what, GDExtensionBool p_reversed) {}
|
||||
static void notification_bind(GDExtensionClassInstancePtr p_instance, int32_t p_what) {}
|
||||
static GDExtensionBool set_bind(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionConstVariantPtr p_value) { return false; }
|
||||
static GDExtensionBool get_bind(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret) { return false; }
|
||||
static const GDExtensionPropertyInfo *get_property_list_bind(GDExtensionClassInstancePtr p_instance, uint32_t *r_count) { return nullptr; }
|
||||
static void free_property_list_bind(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list, uint32_t p_count) {}
|
||||
static void free_property_list_bind(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list) {}
|
||||
static GDExtensionBool property_can_revert_bind(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name) { return false; }
|
||||
static GDExtensionBool property_get_revert_bind(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret) { return false; }
|
||||
static GDExtensionBool validate_property_bind(GDExtensionClassInstancePtr p_instance, GDExtensionPropertyInfo *p_property) { return false; }
|
||||
static void to_string_bind(GDExtensionClassInstancePtr p_instance, GDExtensionBool *r_is_valid, GDExtensionStringPtr r_out) {}
|
||||
|
||||
// The only reason this has to be held here, is when we return results of `_get_property_list` to Godot, we pass
|
||||
// pointers to strings in this list. They have to remain valid to pass the bridge, until the list is freed by Godot...
|
||||
::godot::List<::godot::PropertyInfo> plist_owned;
|
||||
GDExtensionPropertyInfo *plist = nullptr;
|
||||
uint32_t plist_size = 0;
|
||||
|
||||
void _postinitialize();
|
||||
|
||||
@@ -117,8 +82,8 @@ protected:
|
||||
virtual ~Wrapped() {}
|
||||
|
||||
public:
|
||||
static const StringName &get_class_static() {
|
||||
static const StringName string_name = StringName("Wrapped");
|
||||
static StringName &get_class_static() {
|
||||
static StringName string_name = StringName("Wrapped");
|
||||
return string_name;
|
||||
}
|
||||
|
||||
@@ -130,39 +95,8 @@ public:
|
||||
GodotObject *_owner = nullptr;
|
||||
};
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_base_of<::godot::Wrapped, T>::value, bool>>
|
||||
_ALWAYS_INLINE_ void _pre_initialize() {
|
||||
#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
|
||||
Wrapped::_constructing_mutex.lock();
|
||||
#endif
|
||||
Wrapped::_set_construct_info<T>();
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ void snarray_add_str(Vector<StringName> &arr) {
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ void snarray_add_str(Vector<StringName> &arr, const StringName &p_str) {
|
||||
arr.push_back(p_str);
|
||||
}
|
||||
|
||||
template <typename... P>
|
||||
_FORCE_INLINE_ void snarray_add_str(Vector<StringName> &arr, const StringName &p_str, P... p_args) {
|
||||
arr.push_back(p_str);
|
||||
snarray_add_str(arr, p_args...);
|
||||
}
|
||||
|
||||
template <typename... P>
|
||||
_FORCE_INLINE_ Vector<StringName> snarray(P... p_args) {
|
||||
Vector<StringName> arr;
|
||||
snarray_add_str(arr, p_args...);
|
||||
return arr;
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
GDExtensionPropertyInfo *create_c_property_list(const ::godot::List<::godot::PropertyInfo> &plist_cpp, uint32_t *r_size);
|
||||
void free_c_property_list(GDExtensionPropertyInfo *plist);
|
||||
|
||||
typedef void (*EngineClassRegistrationCallback)();
|
||||
void add_engine_class_registration_callback(EngineClassRegistrationCallback p_callback);
|
||||
void register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks);
|
||||
@@ -183,23 +117,21 @@ struct EngineClassRegistration {
|
||||
|
||||
} // namespace godot
|
||||
|
||||
// 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) /***********************************************************************************************************************************************/ \
|
||||
#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; \
|
||||
friend class ::godot::Wrapped; \
|
||||
\
|
||||
protected: \
|
||||
virtual bool _is_extension_class() const override { return true; } \
|
||||
\
|
||||
static const ::godot::StringName *_get_extension_class_name() { \
|
||||
const ::godot::StringName &string_name = get_class_static(); \
|
||||
virtual const ::godot::StringName *_get_extension_class_name() const override { \
|
||||
static ::godot::StringName string_name = get_class_static(); \
|
||||
return &string_name; \
|
||||
} \
|
||||
\
|
||||
virtual const GDExtensionInstanceBindingCallbacks *_get_bindings_callbacks() const override { \
|
||||
return &_gde_binding_callbacks; \
|
||||
} \
|
||||
\
|
||||
static void (*_get_bind_methods())() { \
|
||||
return &m_class::_bind_methods; \
|
||||
} \
|
||||
@@ -228,10 +160,6 @@ protected:
|
||||
return (bool(::godot::Wrapped::*)(const ::godot::StringName &p_name, ::godot::Variant &) const) & m_class::_property_get_revert; \
|
||||
} \
|
||||
\
|
||||
static void (::godot::Wrapped::*_get_validate_property())(::godot::PropertyInfo & p_property) const { \
|
||||
return (void(::godot::Wrapped::*)(::godot::PropertyInfo & p_property) const) & m_class::_validate_property; \
|
||||
} \
|
||||
\
|
||||
static ::godot::String (::godot::Wrapped::*_get_to_string())() const { \
|
||||
return (::godot::String(::godot::Wrapped::*)() const) & m_class::_to_string; \
|
||||
} \
|
||||
@@ -243,7 +171,6 @@ protected:
|
||||
\
|
||||
public: \
|
||||
typedef m_class self_type; \
|
||||
typedef m_inherits parent_type; \
|
||||
\
|
||||
static void initialize_class() { \
|
||||
static bool initialized = false; \
|
||||
@@ -258,78 +185,86 @@ public:
|
||||
initialized = true; \
|
||||
} \
|
||||
\
|
||||
static const ::godot::StringName &get_class_static() { \
|
||||
static const ::godot::StringName string_name = ::godot::StringName(U## #m_class); \
|
||||
static ::godot::StringName &get_class_static() { \
|
||||
static ::godot::StringName string_name = ::godot::StringName(#m_class); \
|
||||
return string_name; \
|
||||
} \
|
||||
\
|
||||
static const ::godot::StringName &get_parent_class_static() { \
|
||||
static ::godot::StringName &get_parent_class_static() { \
|
||||
return m_inherits::get_class_static(); \
|
||||
} \
|
||||
\
|
||||
static void notification_bind(GDExtensionClassInstancePtr p_instance, int32_t p_what, GDExtensionBool p_reversed) { \
|
||||
static GDExtensionObjectPtr create(void *data) { \
|
||||
m_class *new_object = memnew(m_class); \
|
||||
return new_object->_owner; \
|
||||
} \
|
||||
\
|
||||
static void notification_bind(GDExtensionClassInstancePtr p_instance, int32_t p_what) { \
|
||||
if (p_instance && m_class::_get_notification()) { \
|
||||
if (!p_reversed) { \
|
||||
m_inherits::notification_bind(p_instance, p_what, p_reversed); \
|
||||
} \
|
||||
m_inherits::notification_bind(p_instance, p_what); \
|
||||
if (m_class::_get_notification() != m_inherits::_get_notification()) { \
|
||||
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
|
||||
cls->_notification(p_what); \
|
||||
} \
|
||||
if (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) { \
|
||||
if (m_inherits::set_bind(p_instance, p_name, p_value)) { \
|
||||
return true; \
|
||||
} \
|
||||
if (p_instance && m_class::_get_set()) { \
|
||||
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) { \
|
||||
if (m_inherits::get_bind(p_instance, p_name, r_ret)) { \
|
||||
return true; \
|
||||
} \
|
||||
if (p_instance && m_class::_get_get()) { \
|
||||
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; \
|
||||
} \
|
||||
\
|
||||
static inline bool has_get_property_list() { \
|
||||
return m_class::_get_get_property_list() && m_class::_get_get_property_list() != m_inherits::_get_get_property_list(); \
|
||||
} \
|
||||
\
|
||||
static const GDExtensionPropertyInfo *get_property_list_bind(GDExtensionClassInstancePtr p_instance, uint32_t *r_count) { \
|
||||
if (!p_instance) { \
|
||||
if (r_count) \
|
||||
*r_count = 0; \
|
||||
return nullptr; \
|
||||
if (p_instance && m_class::_get_get_property_list()) { \
|
||||
if (m_class::_get_get_property_list() != m_inherits::_get_get_property_list()) { \
|
||||
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
|
||||
ERR_FAIL_COND_V_MSG(!cls->plist_owned.is_empty() || cls->plist != nullptr || cls->plist_size != 0, nullptr, "Internal error, property list was not freed by engine!"); \
|
||||
cls->_get_property_list(&cls->plist_owned); \
|
||||
cls->plist = reinterpret_cast<GDExtensionPropertyInfo *>(memalloc(sizeof(GDExtensionPropertyInfo) * cls->plist_owned.size())); \
|
||||
cls->plist_size = 0; \
|
||||
for (const ::godot::PropertyInfo &E : cls->plist_owned) { \
|
||||
cls->plist[cls->plist_size].type = static_cast<GDExtensionVariantType>(E.type); \
|
||||
cls->plist[cls->plist_size].name = E.name._native_ptr(); \
|
||||
cls->plist[cls->plist_size].hint = E.hint; \
|
||||
cls->plist[cls->plist_size].hint_string = E.hint_string._native_ptr(); \
|
||||
cls->plist[cls->plist_size].class_name = E.class_name._native_ptr(); \
|
||||
cls->plist[cls->plist_size].usage = E.usage; \
|
||||
cls->plist_size++; \
|
||||
} \
|
||||
if (r_count) \
|
||||
*r_count = cls->plist_size; \
|
||||
return cls->plist; \
|
||||
} \
|
||||
return m_inherits::get_property_list_bind(p_instance, r_count); \
|
||||
} \
|
||||
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
|
||||
::godot::List<::godot::PropertyInfo> &plist_cpp = cls->plist_owned; \
|
||||
ERR_FAIL_COND_V_MSG(!plist_cpp.is_empty(), nullptr, "Internal error, property list was not freed by engine!"); \
|
||||
cls->_get_property_list(&plist_cpp); \
|
||||
return ::godot::internal::create_c_property_list(plist_cpp, r_count); \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
static void free_property_list_bind(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list, uint32_t /*p_count*/) { \
|
||||
static void free_property_list_bind(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list) { \
|
||||
if (p_instance) { \
|
||||
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
|
||||
ERR_FAIL_COND_MSG(cls->plist == nullptr, "Internal error, property list double free!"); \
|
||||
memfree(cls->plist); \
|
||||
cls->plist = nullptr; \
|
||||
cls->plist_size = 0; \
|
||||
cls->plist_owned.clear(); \
|
||||
::godot::internal::free_c_property_list(const_cast<GDExtensionPropertyInfo *>(p_list)); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
@@ -355,21 +290,6 @@ public:
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
static GDExtensionBool validate_property_bind(GDExtensionClassInstancePtr p_instance, GDExtensionPropertyInfo *p_property) { \
|
||||
bool ret = false; \
|
||||
if (p_instance && m_class::_get_validate_property()) { \
|
||||
ret = m_inherits::validate_property_bind(p_instance, p_property); \
|
||||
if (m_class::_get_validate_property() != m_inherits::_get_validate_property()) { \
|
||||
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
|
||||
::godot::PropertyInfo info(p_property); \
|
||||
cls->_validate_property(info); \
|
||||
info._update(p_property); \
|
||||
return true; \
|
||||
} \
|
||||
} \
|
||||
return ret; \
|
||||
} \
|
||||
\
|
||||
static void to_string_bind(GDExtensionClassInstancePtr p_instance, GDExtensionBool *r_is_valid, GDExtensionStringPtr r_out) { \
|
||||
if (p_instance && m_class::_get_to_string()) { \
|
||||
if (m_class::_get_to_string() != m_inherits::_get_to_string()) { \
|
||||
@@ -382,7 +302,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(); \
|
||||
@@ -390,14 +310,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; \
|
||||
} \
|
||||
\
|
||||
@@ -414,15 +334,15 @@ 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; \
|
||||
friend class ::godot::Wrapped; \
|
||||
\
|
||||
protected: \
|
||||
virtual const GDExtensionInstanceBindingCallbacks *_get_bindings_callbacks() const override { \
|
||||
return &_gde_binding_callbacks; \
|
||||
} \
|
||||
\
|
||||
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; \
|
||||
} \
|
||||
@@ -465,25 +385,28 @@ protected:
|
||||
\
|
||||
public: \
|
||||
typedef m_class self_type; \
|
||||
typedef m_inherits parent_type; \
|
||||
\
|
||||
static void initialize_class() {} \
|
||||
\
|
||||
static const ::godot::StringName &get_class_static() { \
|
||||
static const ::godot::StringName string_name = ::godot::StringName(#m_alias_for); \
|
||||
static ::godot::StringName &get_class_static() { \
|
||||
static ::godot::StringName string_name = ::godot::StringName(#m_alias_for); \
|
||||
return string_name; \
|
||||
} \
|
||||
\
|
||||
static const ::godot::StringName &get_parent_class_static() { \
|
||||
static ::godot::StringName &get_parent_class_static() { \
|
||||
return m_inherits::get_class_static(); \
|
||||
} \
|
||||
\
|
||||
static GDExtensionObjectPtr create(void *data) { \
|
||||
return nullptr; \
|
||||
} \
|
||||
\
|
||||
static void free(void *data, GDExtensionClassInstancePtr ptr) { \
|
||||
} \
|
||||
\
|
||||
static void *_gde_binding_create_callback(void *p_token, void *p_instance) { \
|
||||
/* Do not call memnew here, we don't want the post-initializer to be called */ \
|
||||
return new ("", "") m_class((GodotObject *)p_instance); \
|
||||
return new ("") m_class((GodotObject *)p_instance); \
|
||||
} \
|
||||
static void _gde_binding_free_callback(void *p_token, void *p_instance, void *p_binding) { \
|
||||
/* Explicitly call the deconstructor to ensure proper lifecycle for non-trivial members */ \
|
||||
@@ -505,11 +428,4 @@ private:
|
||||
// Don't use this for your classes, use GDCLASS() instead.
|
||||
#define GDEXTENSION_CLASS(m_class, m_inherits) GDEXTENSION_CLASS_ALIAS(m_class, m_class, m_inherits)
|
||||
|
||||
#define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call(__VA_ARGS__)
|
||||
#define GDVIRTUAL_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call(__VA_ARGS__)
|
||||
|
||||
#define GDVIRTUAL_BIND(m_name, ...) ::godot::ClassDB::add_virtual_method(get_class_static(), _gdvirtual_##m_name##_get_method_info(), ::godot::snarray(__VA_ARGS__));
|
||||
#define GDVIRTUAL_IS_OVERRIDDEN(m_name) _gdvirtual_##m_name##_overridden()
|
||||
#define GDVIRTUAL_IS_OVERRIDDEN_PTR(m_obj, m_name) m_obj->_gdvirtual_##m_name##_overridden()
|
||||
|
||||
#endif // GODOT_WRAPPED_HPP
|
||||
|
||||
@@ -276,66 +276,12 @@ void call_with_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) co
|
||||
(void)p_args;
|
||||
}
|
||||
|
||||
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.expected = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((size_t)p_argcount < sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
|
||||
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 <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.expected = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((size_t)p_argcount < sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
|
||||
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 <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.expected = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((size_t)p_argcount < sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
|
||||
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 <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.expected = (int32_t)sizeof...(P);
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -346,7 +292,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.expected = (int32_t)sizeof...(P);
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -370,7 +316,7 @@ void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const,
|
||||
#ifdef DEBUG_ENABLED
|
||||
if ((size_t)p_argcount > sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
|
||||
r_error.expected = (int32_t)sizeof...(P);
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -381,7 +327,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.expected = (int32_t)sizeof...(P);
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -405,7 +351,7 @@ void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), const
|
||||
#ifdef DEBUG_ENABLED
|
||||
if ((size_t)p_argcount > sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
|
||||
r_error.expected = (int32_t)sizeof...(P);
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -416,7 +362,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.expected = (int32_t)sizeof...(P);
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -440,7 +386,7 @@ void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const,
|
||||
#ifdef DEBUG_ENABLED
|
||||
if ((size_t)p_argcount > sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
|
||||
r_error.expected = (int32_t)sizeof...(P);
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -451,7 +397,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.expected = (int32_t)sizeof...(P);
|
||||
r_error.argument = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -552,7 +498,7 @@ void call_with_variant_args_static_dv(void (*p_method)(P...), const GDExtensionC
|
||||
#ifdef DEBUG_ENABLED
|
||||
if ((size_t)p_argcount > sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
|
||||
r_error.expected = sizeof...(P);
|
||||
r_error.argument = sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -563,7 +509,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.expected = sizeof...(P);
|
||||
r_error.argument = sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -592,42 +538,6 @@ void call_with_ptr_args_static_method(void (*p_method)(P...), const GDExtensionC
|
||||
call_with_ptr_args_static_method_helper<P...>(p_method, p_args, BuildIndexSequence<sizeof...(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.expected = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((size_t)p_argcount < sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
|
||||
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 <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.expected = (int32_t)sizeof...(P);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((size_t)p_argcount < sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
|
||||
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 <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;
|
||||
@@ -644,7 +554,7 @@ void call_with_variant_args_static_ret_dv(R (*p_method)(P...), const GDExtension
|
||||
#ifdef DEBUG_ENABLED
|
||||
if ((size_t)p_argcount > sizeof...(P)) {
|
||||
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
|
||||
r_error.expected = sizeof...(P);
|
||||
r_error.argument = sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -655,7 +565,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.expected = sizeof...(P);
|
||||
r_error.argument = sizeof...(P);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -37,16 +37,10 @@
|
||||
#include <godot_cpp/core/error_macros.hpp>
|
||||
#include <godot_cpp/core/method_bind.hpp>
|
||||
#include <godot_cpp/core/object.hpp>
|
||||
#include <godot_cpp/core/print_string.hpp>
|
||||
|
||||
#include <godot_cpp/classes/class_db_singleton.hpp>
|
||||
|
||||
// Makes callable_mp readily available in all classes connecting signals.
|
||||
// Needs to come after method_bind and object have been included.
|
||||
#include <godot_cpp/variant/callable_method_pointer.hpp>
|
||||
|
||||
#include <list>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
@@ -87,18 +81,22 @@ class ClassDB {
|
||||
friend class godot::GDExtensionBinding;
|
||||
|
||||
public:
|
||||
struct ClassInfo {
|
||||
struct VirtualMethod {
|
||||
GDExtensionClassCallVirtual func;
|
||||
uint32_t hash;
|
||||
};
|
||||
struct PropertySetGet {
|
||||
int index;
|
||||
StringName setter;
|
||||
StringName getter;
|
||||
MethodBind *_setptr;
|
||||
MethodBind *_getptr;
|
||||
Variant::Type type;
|
||||
};
|
||||
|
||||
struct ClassInfo {
|
||||
StringName name;
|
||||
StringName parent_name;
|
||||
GDExtensionInitializationLevel level = GDEXTENSION_INITIALIZATION_SCENE;
|
||||
std::unordered_map<StringName, MethodBind *> method_map;
|
||||
std::set<StringName> signal_names;
|
||||
std::unordered_map<StringName, VirtualMethod> virtual_methods;
|
||||
std::unordered_map<StringName, GDExtensionClassCallVirtual> virtual_methods;
|
||||
std::set<StringName> property_names;
|
||||
std::set<StringName> constant_names;
|
||||
// Pointer to the parent custom class, if any. Will be null if the parent class is a Godot class.
|
||||
@@ -111,78 +109,24 @@ 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 <typename T, bool is_abstract>
|
||||
static void _register_class(bool p_virtual = false, bool p_exposed = true, bool p_runtime = false);
|
||||
|
||||
template <typename T>
|
||||
static GDExtensionObjectPtr _create_instance_func(void *data, GDExtensionBool p_notify_postinitialize) {
|
||||
if constexpr (!std::is_abstract_v<T>) {
|
||||
Wrapped::_set_construct_info<T>();
|
||||
T *new_object = new ("", "") T;
|
||||
if (p_notify_postinitialize) {
|
||||
new_object->_postinitialize();
|
||||
}
|
||||
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
|
||||
#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
|
||||
std::lock_guard<std::recursive_mutex> lk(Wrapped::_constructing_mutex);
|
||||
#endif
|
||||
Wrapped::_constructing_recreate_owner = obj;
|
||||
T *new_instance = (T *)memalloc(sizeof(T));
|
||||
memnew_placement(new_instance, T);
|
||||
return new_instance;
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
static void _register_class(bool p_virtual = false);
|
||||
|
||||
public:
|
||||
template <typename T>
|
||||
static void register_class(bool p_virtual = false);
|
||||
template <typename T>
|
||||
static void register_abstract_class();
|
||||
template <typename T>
|
||||
static void register_internal_class();
|
||||
template <typename T>
|
||||
static void register_runtime_class();
|
||||
|
||||
_FORCE_INLINE_ static void _register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks) {
|
||||
instance_binding_callbacks[p_name] = p_callbacks;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -197,14 +141,11 @@ public:
|
||||
static void add_property(const StringName &p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1);
|
||||
static void add_signal(const StringName &p_class, const MethodInfo &p_signal);
|
||||
static void bind_integer_constant(const StringName &p_class_name, const StringName &p_enum_name, const StringName &p_constant_name, GDExtensionInt p_constant_value, bool p_is_bitfield = false);
|
||||
// Binds an implementation of a virtual method defined in Godot.
|
||||
static void bind_virtual_method(const StringName &p_class, const StringName &p_method, GDExtensionClassCallVirtual p_call, uint32_t p_hash);
|
||||
// Add a new virtual method that can be implemented by scripts.
|
||||
static void add_virtual_method(const StringName &p_class, const MethodInfo &p_method, const Vector<StringName> &p_arg_names = Vector<StringName>());
|
||||
static void bind_virtual_method(const StringName &p_class, const StringName &p_method, GDExtensionClassCallVirtual p_call);
|
||||
|
||||
static MethodBind *get_method(const StringName &p_class, const StringName &p_method);
|
||||
|
||||
static GDExtensionClassCallVirtual get_virtual_func(void *p_userdata, GDExtensionConstStringNamePtr p_name, uint32_t p_hash);
|
||||
static GDExtensionClassCallVirtual get_virtual_func(void *p_userdata, GDExtensionConstStringNamePtr p_name);
|
||||
static const GDExtensionInstanceBindingCallbacks *get_instance_binding_callbacks(const StringName &p_class);
|
||||
|
||||
static void initialize(GDExtensionInitializationLevel p_level);
|
||||
@@ -222,19 +163,17 @@ public:
|
||||
#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);
|
||||
|
||||
#define BIND_VIRTUAL_METHOD(m_class, m_method, m_hash) \
|
||||
#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, m_hash); \
|
||||
::godot::ClassDB::bind_virtual_method(m_class::get_class_static(), #m_method, _call##m_method); \
|
||||
}
|
||||
|
||||
template <typename T, bool is_abstract>
|
||||
void ClassDB::_register_class(bool p_virtual, bool p_exposed, bool p_runtime) {
|
||||
void ClassDB::_register_class(bool p_virtual) {
|
||||
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
|
||||
@@ -251,33 +190,27 @@ void ClassDB::_register_class(bool p_virtual, bool p_exposed, bool p_runtime) {
|
||||
class_register_order.push_back(cl.name);
|
||||
|
||||
// Register this class with Godot
|
||||
GDExtensionClassCreationInfo4 class_info = {
|
||||
GDExtensionClassCreationInfo class_info = {
|
||||
p_virtual, // GDExtensionBool is_virtual;
|
||||
is_abstract, // GDExtensionBool is_abstract;
|
||||
p_exposed, // GDExtensionBool is_exposed;
|
||||
p_runtime, // GDExtensionBool is_runtime;
|
||||
nullptr, // GDExtensionConstStringPtr icon_path;
|
||||
T::set_bind, // GDExtensionClassSet set_func;
|
||||
T::get_bind, // GDExtensionClassGet get_func;
|
||||
T::has_get_property_list() ? T::get_property_list_bind : nullptr, // GDExtensionClassGetPropertyList get_property_list_func;
|
||||
T::free_property_list_bind, // GDExtensionClassFreePropertyList2 free_property_list_func;
|
||||
T::get_property_list_bind, // GDExtensionClassGetPropertyList get_property_list_func;
|
||||
T::free_property_list_bind, // GDExtensionClassFreePropertyList free_property_list_func;
|
||||
T::property_can_revert_bind, // GDExtensionClassPropertyCanRevert property_can_revert_func;
|
||||
T::property_get_revert_bind, // GDExtensionClassPropertyGetRevert property_get_revert_func;
|
||||
T::validate_property_bind, // GDExtensionClassValidateProperty validate_property_func;
|
||||
T::notification_bind, // GDExtensionClassNotification2 notification_func;
|
||||
T::notification_bind, // GDExtensionClassNotification notification_func;
|
||||
T::to_string_bind, // GDExtensionClassToString to_string_func;
|
||||
nullptr, // GDExtensionClassReference reference_func;
|
||||
nullptr, // GDExtensionClassUnreference unreference_func;
|
||||
&_create_instance_func<T>, // GDExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
|
||||
T::create, // GDExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
|
||||
T::free, // GDExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
|
||||
&_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;
|
||||
nullptr, // GDExtensionClassGetRID get_rid;
|
||||
(void *)&T::get_class_static(), // void *class_userdata;
|
||||
};
|
||||
|
||||
internal::gdextension_interface_classdb_register_extension_class4(internal::library, cl.name._native_ptr(), cl.parent_name._native_ptr(), &class_info);
|
||||
internal::gdextension_interface_classdb_register_extension_class(internal::library, cl.name._native_ptr(), cl.parent_name._native_ptr(), &class_info);
|
||||
|
||||
// call bind_methods etc. to register all members of the class
|
||||
T::initialize_class();
|
||||
@@ -296,16 +229,6 @@ void ClassDB::register_abstract_class() {
|
||||
ClassDB::_register_class<T, true>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ClassDB::register_internal_class() {
|
||||
ClassDB::_register_class<T, false>(false, false);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ClassDB::register_runtime_class() {
|
||||
ClassDB::_register_class<T, false>(false, true, true);
|
||||
}
|
||||
|
||||
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.
|
||||
@@ -361,14 +284,10 @@ MethodBind *ClassDB::bind_vararg_method(uint32_t p_flags, StringName p_name, M p
|
||||
return bind;
|
||||
}
|
||||
|
||||
#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>();
|
||||
#define GDREGISTER_RUNTIME_CLASS(m_class) ::godot::ClassDB::register_runtime_class<m_class>();
|
||||
#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>();
|
||||
|
||||
} // namespace godot
|
||||
|
||||
CLASSDB_SINGLETON_VARIANT_CAST;
|
||||
|
||||
#endif // GODOT_CLASS_DB_HPP
|
||||
|
||||
@@ -35,8 +35,6 @@
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
namespace godot {
|
||||
|
||||
#if !defined(GDE_EXPORT)
|
||||
#if defined(_WIN32)
|
||||
#define GDE_EXPORT __declspec(dllexport)
|
||||
@@ -74,6 +72,10 @@ namespace godot {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _NO_DISCARD_
|
||||
#define _NO_DISCARD_ [[nodiscard]]
|
||||
#endif
|
||||
|
||||
// Windows badly defines a lot of stuff we'll never use. Undefine it.
|
||||
#ifdef _WIN32
|
||||
#undef min // override standard definition
|
||||
@@ -125,10 +127,4 @@ 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
|
||||
|
||||
@@ -613,14 +613,6 @@ 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,21 +40,20 @@
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
// 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
|
||||
void *operator new(size_t p_size, const char *p_dummy, void *p_pointer, size_t check, const char *p_description); ///< operator new that takes a description and uses a pointer to the preallocated memory
|
||||
void *operator new(size_t p_size, const char *p_description); ///< operator new that takes a description and uses MemoryStaticPool
|
||||
void *operator new(size_t p_size, void *(*p_allocfunc)(size_t p_size)); ///< operator new that takes a description and uses MemoryStaticPool
|
||||
void *operator new(size_t p_size, void *p_pointer, size_t check, const char *p_description); ///< operator new that takes a description and uses a pointer to the preallocated memory
|
||||
|
||||
_ALWAYS_INLINE_ void *operator new(size_t p_size, const char *p_dummy, void *p_pointer, size_t check, const char *p_description) {
|
||||
_ALWAYS_INLINE_ void *operator new(size_t p_size, void *p_pointer, size_t check, const char *p_description) {
|
||||
return p_pointer;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// When compiling with VC++ 2017, the above declarations of placement new generate many irrelevant warnings (C4291).
|
||||
// The purpose of the following definitions is to muffle these warnings, not to provide a usable implementation of placement delete.
|
||||
void operator delete(void *p_mem, const char *p_dummy, const char *p_description);
|
||||
void operator delete(void *p_mem, const char *p_dummy, void *(*p_allocfunc)(size_t p_size));
|
||||
void operator delete(void *p_mem, const char *p_dummy, void *p_pointer, size_t check, const char *p_description);
|
||||
void operator delete(void *p_mem, const char *p_description);
|
||||
void operator delete(void *p_mem, void *(*p_allocfunc)(size_t p_size));
|
||||
void operator delete(void *p_mem, void *p_pointer, size_t check, const char *p_description);
|
||||
#endif
|
||||
|
||||
namespace godot {
|
||||
@@ -82,9 +81,6 @@ public:
|
||||
static void free_static(void *p_ptr, bool p_pad_align = false);
|
||||
};
|
||||
|
||||
template <typename T, std::enable_if_t<!std::is_base_of<::godot::Wrapped, T>::value, bool> = true>
|
||||
_ALWAYS_INLINE_ void _pre_initialize() {}
|
||||
|
||||
_ALWAYS_INLINE_ void postinitialize_handler(void *) {}
|
||||
|
||||
template <typename T>
|
||||
@@ -97,10 +93,10 @@ _ALWAYS_INLINE_ T *_post_initialize(T *p_obj) {
|
||||
#define memrealloc(m_mem, m_size) ::godot::Memory::realloc_static(m_mem, m_size)
|
||||
#define memfree(m_mem) ::godot::Memory::free_static(m_mem)
|
||||
|
||||
#define memnew(m_class) (::godot::_pre_initialize<std::remove_pointer_t<decltype(new ("", "") m_class)>>(), ::godot::_post_initialize(new ("", "") m_class))
|
||||
#define memnew(m_class) ::godot::_post_initialize(new ("") m_class)
|
||||
|
||||
#define memnew_allocator(m_class, m_allocator) (::godot::_pre_initialize<std::remove_pointer_t<decltype(new ("", "") m_class)>>(), ::godot::_post_initialize(new ("", m_allocator::alloc) m_class))
|
||||
#define memnew_placement(m_placement, m_class) (::godot::_pre_initialize<std::remove_pointer_t<decltype(new ("", "") m_class)>>(), ::godot::_post_initialize(new ("", m_placement, sizeof(m_class), "") m_class))
|
||||
#define memnew_allocator(m_class, m_allocator) ::godot::_post_initialize(new (m_allocator::alloc) m_class)
|
||||
#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 <typename T>
|
||||
@@ -172,7 +168,7 @@ T *memnew_arr_template(size_t p_elements, const char *p_descr = "") {
|
||||
|
||||
/* call operator new */
|
||||
for (size_t i = 0; i < p_elements; i++) {
|
||||
new ("", &elems[i], sizeof(T), p_descr) T;
|
||||
new (&elems[i], sizeof(T), p_descr) 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 + 1; i++) {
|
||||
for (int i = 0; i < argument_count; i++) {
|
||||
vec.push_back(get_argument_metadata(i - 1));
|
||||
}
|
||||
return vec;
|
||||
@@ -412,7 +412,6 @@ public:
|
||||
method = p_method;
|
||||
generate_argument_types(sizeof...(P));
|
||||
set_argument_count(sizeof...(P));
|
||||
set_const(true);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -579,7 +578,6 @@ public:
|
||||
generate_argument_types(sizeof...(P));
|
||||
set_argument_count(sizeof...(P));
|
||||
set_return(true);
|
||||
set_const(true);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -161,7 +161,6 @@ MAKE_PTRARG(PackedFloat64Array);
|
||||
MAKE_PTRARG(PackedStringArray);
|
||||
MAKE_PTRARG(PackedVector2Array);
|
||||
MAKE_PTRARG(PackedVector3Array);
|
||||
MAKE_PTRARG(PackedVector4Array);
|
||||
MAKE_PTRARG(PackedColorArray);
|
||||
MAKE_PTRARG_BY_REFERENCE(Variant);
|
||||
|
||||
@@ -171,11 +170,11 @@ 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 likely(p_ptr) ? reinterpret_cast<T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr)))) : nullptr;
|
||||
return reinterpret_cast<T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr))));
|
||||
}
|
||||
typedef Object *EncodeT;
|
||||
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
|
||||
*reinterpret_cast<const void **>(p_ptr) = likely(p_var) ? p_var->_owner : nullptr;
|
||||
*reinterpret_cast<const void **>(p_ptr) = p_var ? p_var->_owner : nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -183,11 +182,11 @@ 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 likely(p_ptr) ? reinterpret_cast<const T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr)))) : nullptr;
|
||||
return reinterpret_cast<const T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr))));
|
||||
}
|
||||
typedef const Object *EncodeT;
|
||||
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
|
||||
*reinterpret_cast<const void **>(p_ptr) = likely(p_var) ? p_var->_owner : nullptr;
|
||||
*reinterpret_cast<const void **>(p_ptr) = p_var ? p_var->_owner : nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -33,8 +33,6 @@
|
||||
|
||||
#include <godot_cpp/core/defs.hpp>
|
||||
|
||||
#include <godot_cpp/core/object_id.hpp>
|
||||
|
||||
#include <godot_cpp/core/property_info.hpp>
|
||||
|
||||
#include <godot_cpp/variant/variant.hpp>
|
||||
@@ -51,7 +49,6 @@
|
||||
#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 {
|
||||
|
||||
@@ -68,8 +65,6 @@ struct MethodInfo {
|
||||
int id = 0;
|
||||
std::vector<PropertyInfo> arguments;
|
||||
std::vector<Variant> default_arguments;
|
||||
GDExtensionClassMethodArgumentMetadata return_val_metadata;
|
||||
std::vector<GDExtensionClassMethodArgumentMetadata> arguments_metadata;
|
||||
|
||||
inline bool operator==(const MethodInfo &p_method) const { return id == p_method.id; }
|
||||
inline bool operator<(const MethodInfo &p_method) const { return id == p_method.id ? (name < p_method.name) : (id < p_method.id); }
|
||||
@@ -110,6 +105,28 @@ MethodInfo::MethodInfo(const PropertyInfo &p_ret, StringName p_name, const Args
|
||||
arguments = { args... };
|
||||
}
|
||||
|
||||
class ObjectID {
|
||||
uint64_t id = 0;
|
||||
|
||||
public:
|
||||
_FORCE_INLINE_ bool is_ref_counted() const { return (id & (uint64_t(1) << 63)) != 0; }
|
||||
_FORCE_INLINE_ bool is_valid() const { return id != 0; }
|
||||
_FORCE_INLINE_ bool is_null() const { return id == 0; }
|
||||
_FORCE_INLINE_ operator uint64_t() const { return id; }
|
||||
_FORCE_INLINE_ operator int64_t() const { return id; }
|
||||
|
||||
_FORCE_INLINE_ bool operator==(const ObjectID &p_id) const { return id == p_id.id; }
|
||||
_FORCE_INLINE_ bool operator!=(const ObjectID &p_id) const { return id != p_id.id; }
|
||||
_FORCE_INLINE_ bool operator<(const ObjectID &p_id) const { return id < p_id.id; }
|
||||
|
||||
_FORCE_INLINE_ void operator=(int64_t p_int64) { id = p_int64; }
|
||||
_FORCE_INLINE_ void operator=(uint64_t p_uint64) { id = p_uint64; }
|
||||
|
||||
_FORCE_INLINE_ ObjectID() {}
|
||||
_FORCE_INLINE_ explicit ObjectID(const uint64_t p_id) { id = p_id; }
|
||||
_FORCE_INLINE_ explicit ObjectID(const int64_t p_id) { id = p_id; }
|
||||
};
|
||||
|
||||
class ObjectDB {
|
||||
public:
|
||||
static Object *get_instance(uint64_t p_object_id) {
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* object_id.hpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef GODOT_OBJECT_ID_HPP
|
||||
#define GODOT_OBJECT_ID_HPP
|
||||
|
||||
#include <godot_cpp/core/defs.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
class ObjectID {
|
||||
uint64_t id = 0;
|
||||
|
||||
public:
|
||||
_FORCE_INLINE_ bool is_ref_counted() const { return (id & (uint64_t(1) << 63)) != 0; }
|
||||
_FORCE_INLINE_ bool is_valid() const { return id != 0; }
|
||||
_FORCE_INLINE_ bool is_null() const { return id == 0; }
|
||||
_FORCE_INLINE_ operator uint64_t() const { return id; }
|
||||
_FORCE_INLINE_ operator int64_t() const { return id; }
|
||||
|
||||
_FORCE_INLINE_ bool operator==(const ObjectID &p_id) const { return id == p_id.id; }
|
||||
_FORCE_INLINE_ bool operator!=(const ObjectID &p_id) const { return id != p_id.id; }
|
||||
_FORCE_INLINE_ bool operator<(const ObjectID &p_id) const { return id < p_id.id; }
|
||||
|
||||
_FORCE_INLINE_ void operator=(int64_t p_int64) { id = p_int64; }
|
||||
_FORCE_INLINE_ void operator=(uint64_t p_uint64) { id = p_uint64; }
|
||||
|
||||
_FORCE_INLINE_ ObjectID() {}
|
||||
_FORCE_INLINE_ explicit ObjectID(const uint64_t p_id) { id = p_id; }
|
||||
_FORCE_INLINE_ explicit ObjectID(const int64_t p_id) { id = p_id; }
|
||||
};
|
||||
|
||||
} // namespace godot
|
||||
|
||||
#endif // GODOT_OBJECT_ID_HPP
|
||||
@@ -1,73 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* print_string.hpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef GODOT_PRINT_STRING_HPP
|
||||
#define GODOT_PRINT_STRING_HPP
|
||||
|
||||
#include <godot_cpp/variant/utility_functions.hpp>
|
||||
|
||||
namespace godot {
|
||||
inline void print_error(const Variant &p_variant) {
|
||||
UtilityFunctions::printerr(p_variant);
|
||||
}
|
||||
|
||||
inline void print_line(const Variant &p_variant) {
|
||||
UtilityFunctions::print(p_variant);
|
||||
}
|
||||
|
||||
inline void print_line_rich(const Variant &p_variant) {
|
||||
UtilityFunctions::print_rich(p_variant);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void print_error(const Variant &p_variant, Args... p_args) {
|
||||
UtilityFunctions::printerr(p_variant, p_args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void print_line(const Variant &p_variant, Args... p_args) {
|
||||
UtilityFunctions::print(p_variant, p_args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void print_line_rich(const Variant &p_variant, Args... p_args) {
|
||||
UtilityFunctions::print_rich(p_variant, p_args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void print_verbose(const Variant &p_variant, Args... p_args) {
|
||||
UtilityFunctions::print_verbose(p_variant, p_args...);
|
||||
}
|
||||
|
||||
bool is_print_verbose_enabled();
|
||||
|
||||
} // namespace godot
|
||||
|
||||
#endif // GODOT_PRINT_STRING_HPP
|
||||
@@ -68,63 +68,6 @@ struct PropertyInfo {
|
||||
|
||||
PropertyInfo(GDExtensionVariantType p_type, const StringName &p_name, PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT, const StringName &p_class_name = "") :
|
||||
PropertyInfo((Variant::Type)p_type, p_name, p_hint, p_hint_string, p_usage, p_class_name) {}
|
||||
|
||||
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;
|
||||
p_info->hint = hint;
|
||||
*(reinterpret_cast<String *>(p_info->hint_string)) = hint_string;
|
||||
p_info->usage = usage;
|
||||
*(reinterpret_cast<StringName *>(p_info->class_name)) = class_name;
|
||||
}
|
||||
|
||||
GDExtensionPropertyInfo _to_gdextension() const {
|
||||
return {
|
||||
(GDExtensionVariantType)type,
|
||||
name._native_ptr(),
|
||||
class_name._native_ptr(),
|
||||
hint,
|
||||
hint_string._native_ptr(),
|
||||
usage,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace godot
|
||||
|
||||
@@ -58,16 +58,6 @@ 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();
|
||||
@@ -148,8 +138,8 @@ MAKE_TYPE_INFO_WITH_META(uint32_t, GDEXTENSION_VARIANT_TYPE_INT, GDEXTENSION_MET
|
||||
MAKE_TYPE_INFO_WITH_META(int32_t, GDEXTENSION_VARIANT_TYPE_INT, GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT32)
|
||||
MAKE_TYPE_INFO_WITH_META(uint64_t, GDEXTENSION_VARIANT_TYPE_INT, GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT64)
|
||||
MAKE_TYPE_INFO_WITH_META(int64_t, GDEXTENSION_VARIANT_TYPE_INT, GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT64)
|
||||
MAKE_TYPE_INFO_WITH_META(char16_t, GDEXTENSION_VARIANT_TYPE_INT, GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_CHAR16)
|
||||
MAKE_TYPE_INFO_WITH_META(char32_t, GDEXTENSION_VARIANT_TYPE_INT, GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_CHAR32)
|
||||
MAKE_TYPE_INFO(char16_t, GDEXTENSION_VARIANT_TYPE_INT)
|
||||
MAKE_TYPE_INFO(char32_t, GDEXTENSION_VARIANT_TYPE_INT)
|
||||
MAKE_TYPE_INFO_WITH_META(float, GDEXTENSION_VARIANT_TYPE_FLOAT, GDEXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_FLOAT)
|
||||
MAKE_TYPE_INFO_WITH_META(double, GDEXTENSION_VARIANT_TYPE_FLOAT, GDEXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_DOUBLE)
|
||||
|
||||
@@ -185,7 +175,6 @@ MAKE_TYPE_INFO(PackedFloat64Array, GDEXTENSION_VARIANT_TYPE_PACKED_FLOAT64_ARRAY
|
||||
MAKE_TYPE_INFO(PackedStringArray, GDEXTENSION_VARIANT_TYPE_PACKED_STRING_ARRAY)
|
||||
MAKE_TYPE_INFO(PackedVector2Array, GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR2_ARRAY)
|
||||
MAKE_TYPE_INFO(PackedVector3Array, GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR3_ARRAY)
|
||||
MAKE_TYPE_INFO(PackedVector4Array, GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR4_ARRAY)
|
||||
MAKE_TYPE_INFO(PackedColorArray, GDEXTENSION_VARIANT_TYPE_PACKED_COLOR_ARRAY)
|
||||
|
||||
// For variant.
|
||||
@@ -209,8 +198,8 @@ struct GetTypeInfo<const Variant &> {
|
||||
|
||||
template <typename T>
|
||||
struct GetTypeInfo<T *, typename EnableIf<TypeInherits<Object, T>::value>::type> {
|
||||
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
|
||||
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
|
||||
static const GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
|
||||
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
|
||||
static inline PropertyInfo get_class_info() {
|
||||
return make_property_info(Variant::Type::OBJECT, "", PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static());
|
||||
}
|
||||
@@ -218,8 +207,8 @@ struct GetTypeInfo<T *, typename EnableIf<TypeInherits<Object, T>::value>::type>
|
||||
|
||||
template <typename T>
|
||||
struct GetTypeInfo<const T *, typename EnableIf<TypeInherits<Object, T>::value>::type> {
|
||||
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
|
||||
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
|
||||
static const GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
|
||||
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
|
||||
static inline PropertyInfo get_class_info() {
|
||||
return make_property_info(Variant::Type::OBJECT, "", PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static());
|
||||
}
|
||||
@@ -237,8 +226,8 @@ inline String enum_qualified_name_to_class_info_name(const String &p_qualified_n
|
||||
#define TEMPL_MAKE_ENUM_TYPE_INFO(m_enum, m_impl) \
|
||||
template <> \
|
||||
struct GetTypeInfo<m_impl> { \
|
||||
static constexpr Variant::Type VARIANT_TYPE = Variant::INT; \
|
||||
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
|
||||
static const Variant::Type VARIANT_TYPE = Variant::INT; \
|
||||
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
|
||||
static inline PropertyInfo get_class_info() { \
|
||||
return make_property_info(Variant::Type::INT, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_ENUM, \
|
||||
enum_qualified_name_to_class_info_name(#m_enum)); \
|
||||
@@ -275,8 +264,8 @@ public:
|
||||
#define TEMPL_MAKE_BITFIELD_TYPE_INFO(m_enum, m_impl) \
|
||||
template <> \
|
||||
struct GetTypeInfo<m_impl> { \
|
||||
static constexpr Variant::Type VARIANT_TYPE = Variant::INT; \
|
||||
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
|
||||
static const Variant::Type VARIANT_TYPE = Variant::INT; \
|
||||
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
|
||||
static inline PropertyInfo get_class_info() { \
|
||||
return make_property_info(Variant::Type::INT, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_BITFIELD, \
|
||||
enum_qualified_name_to_class_info_name(#m_enum)); \
|
||||
@@ -284,8 +273,8 @@ public:
|
||||
}; \
|
||||
template <> \
|
||||
struct GetTypeInfo<BitField<m_impl>> { \
|
||||
static constexpr Variant::Type VARIANT_TYPE = Variant::INT; \
|
||||
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
|
||||
static const Variant::Type VARIANT_TYPE = Variant::INT; \
|
||||
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
|
||||
static inline PropertyInfo get_class_info() { \
|
||||
return make_property_info(Variant::Type::INT, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_BITFIELD, \
|
||||
enum_qualified_name_to_class_info_name(#m_enum)); \
|
||||
@@ -381,14 +370,11 @@ MAKE_TYPED_ARRAY_INFO(Rect2i, Variant::RECT2I)
|
||||
MAKE_TYPED_ARRAY_INFO(Vector3, Variant::VECTOR3)
|
||||
MAKE_TYPED_ARRAY_INFO(Vector3i, Variant::VECTOR3I)
|
||||
MAKE_TYPED_ARRAY_INFO(Transform2D, Variant::TRANSFORM2D)
|
||||
MAKE_TYPED_ARRAY_INFO(Vector4, Variant::VECTOR4)
|
||||
MAKE_TYPED_ARRAY_INFO(Vector4i, Variant::VECTOR4I)
|
||||
MAKE_TYPED_ARRAY_INFO(Plane, Variant::PLANE)
|
||||
MAKE_TYPED_ARRAY_INFO(Quaternion, Variant::QUATERNION)
|
||||
MAKE_TYPED_ARRAY_INFO(AABB, Variant::AABB)
|
||||
MAKE_TYPED_ARRAY_INFO(Basis, Variant::BASIS)
|
||||
MAKE_TYPED_ARRAY_INFO(Transform3D, Variant::TRANSFORM3D)
|
||||
MAKE_TYPED_ARRAY_INFO(Projection, Variant::PROJECTION)
|
||||
MAKE_TYPED_ARRAY_INFO(Color, Variant::COLOR)
|
||||
MAKE_TYPED_ARRAY_INFO(StringName, Variant::STRING_NAME)
|
||||
MAKE_TYPED_ARRAY_INFO(NodePath, Variant::NODE_PATH)
|
||||
@@ -397,22 +383,18 @@ 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(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(PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY)
|
||||
MAKE_TYPED_ARRAY_INFO(PackedColorArray, Variant::PACKED_COLOR_ARRAY)
|
||||
/*
|
||||
MAKE_TYPED_ARRAY_INFO(IPAddress, Variant::STRING)
|
||||
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)
|
||||
*/
|
||||
|
||||
#undef MAKE_TYPED_ARRAY_INFO
|
||||
|
||||
#define CLASS_INFO(m_type) (GetTypeInfo<m_type *>::get_class_info())
|
||||
|
||||
} // namespace godot
|
||||
|
||||
@@ -82,13 +82,11 @@ extern "C" GDExtensionInterfaceVariantGetType gdextension_interface_variant_get_
|
||||
extern "C" GDExtensionInterfaceVariantHasMethod gdextension_interface_variant_has_method;
|
||||
extern "C" GDExtensionInterfaceVariantHasMember gdextension_interface_variant_has_member;
|
||||
extern "C" GDExtensionInterfaceVariantHasKey gdextension_interface_variant_has_key;
|
||||
extern "C" GDExtensionInterfaceVariantGetObjectInstanceId gdextension_interface_variant_get_object_instance_id;
|
||||
extern "C" GDExtensionInterfaceVariantGetTypeName gdextension_interface_variant_get_type_name;
|
||||
extern "C" GDExtensionInterfaceVariantCanConvert gdextension_interface_variant_can_convert;
|
||||
extern "C" GDExtensionInterfaceVariantCanConvertStrict gdextension_interface_variant_can_convert_strict;
|
||||
extern "C" GDExtensionInterfaceGetVariantFromTypeConstructor gdextension_interface_get_variant_from_type_constructor;
|
||||
extern "C" GDExtensionInterfaceGetVariantToTypeConstructor gdextension_interface_get_variant_to_type_constructor;
|
||||
extern "C" GDExtensionInterfaceGetVariantGetInternalPtrFunc gdextension_interface_variant_get_ptr_internal_getter;
|
||||
extern "C" GDExtensionInterfaceVariantGetPtrOperatorEvaluator gdextension_interface_variant_get_ptr_operator_evaluator;
|
||||
extern "C" GDExtensionInterfaceVariantGetPtrBuiltinMethod gdextension_interface_variant_get_ptr_builtin_method;
|
||||
extern "C" GDExtensionInterfaceVariantGetPtrConstructor gdextension_interface_variant_get_ptr_constructor;
|
||||
@@ -110,9 +108,7 @@ extern "C" GDExtensionInterfaceStringNewWithUtf32Chars gdextension_interface_str
|
||||
extern "C" GDExtensionInterfaceStringNewWithWideChars gdextension_interface_string_new_with_wide_chars;
|
||||
extern "C" GDExtensionInterfaceStringNewWithLatin1CharsAndLen gdextension_interface_string_new_with_latin1_chars_and_len;
|
||||
extern "C" GDExtensionInterfaceStringNewWithUtf8CharsAndLen gdextension_interface_string_new_with_utf8_chars_and_len;
|
||||
extern "C" GDExtensionInterfaceStringNewWithUtf8CharsAndLen2 gdextension_interface_string_new_with_utf8_chars_and_len2;
|
||||
extern "C" GDExtensionInterfaceStringNewWithUtf16CharsAndLen gdextension_interface_string_new_with_utf16_chars_and_len;
|
||||
extern "C" GDExtensionInterfaceStringNewWithUtf16CharsAndLen2 gdextension_interface_string_new_with_utf16_chars_and_len2;
|
||||
extern "C" GDExtensionInterfaceStringNewWithUtf32CharsAndLen gdextension_interface_string_new_with_utf32_chars_and_len;
|
||||
extern "C" GDExtensionInterfaceStringNewWithWideCharsAndLen gdextension_interface_string_new_with_wide_chars_and_len;
|
||||
extern "C" GDExtensionInterfaceStringToLatin1Chars gdextension_interface_string_to_latin1_chars;
|
||||
@@ -127,8 +123,6 @@ extern "C" GDExtensionInterfaceStringOperatorPlusEqChar gdextension_interface_st
|
||||
extern "C" GDExtensionInterfaceStringOperatorPlusEqCstr gdextension_interface_string_operator_plus_eq_cstr;
|
||||
extern "C" GDExtensionInterfaceStringOperatorPlusEqWcstr gdextension_interface_string_operator_plus_eq_wcstr;
|
||||
extern "C" GDExtensionInterfaceStringOperatorPlusEqC32str gdextension_interface_string_operator_plus_eq_c32str;
|
||||
extern "C" GDExtensionInterfaceStringResize gdextension_interface_string_resize;
|
||||
extern "C" GDExtensionInterfaceStringNameNewWithLatin1Chars gdextension_interface_string_name_new_with_latin1_chars;
|
||||
extern "C" GDExtensionInterfaceXmlParserOpenBuffer gdextension_interface_xml_parser_open_buffer;
|
||||
extern "C" GDExtensionInterfaceFileAccessStoreBuffer gdextension_interface_file_access_store_buffer;
|
||||
extern "C" GDExtensionInterfaceFileAccessGetBuffer gdextension_interface_file_access_get_buffer;
|
||||
@@ -152,45 +146,33 @@ extern "C" GDExtensionInterfacePackedVector2ArrayOperatorIndex gdextension_inter
|
||||
extern "C" GDExtensionInterfacePackedVector2ArrayOperatorIndexConst gdextension_interface_packed_vector2_array_operator_index_const;
|
||||
extern "C" GDExtensionInterfacePackedVector3ArrayOperatorIndex gdextension_interface_packed_vector3_array_operator_index;
|
||||
extern "C" GDExtensionInterfacePackedVector3ArrayOperatorIndexConst gdextension_interface_packed_vector3_array_operator_index_const;
|
||||
extern "C" GDExtensionInterfacePackedVector4ArrayOperatorIndex gdextension_interface_packed_vector4_array_operator_index;
|
||||
extern "C" GDExtensionInterfacePackedVector4ArrayOperatorIndexConst gdextension_interface_packed_vector4_array_operator_index_const;
|
||||
extern "C" GDExtensionInterfaceArrayOperatorIndex gdextension_interface_array_operator_index;
|
||||
extern "C" GDExtensionInterfaceArrayOperatorIndexConst gdextension_interface_array_operator_index_const;
|
||||
extern "C" GDExtensionInterfaceArrayRef gdextension_interface_array_ref;
|
||||
extern "C" GDExtensionInterfaceArraySetTyped gdextension_interface_array_set_typed;
|
||||
extern "C" GDExtensionInterfaceDictionaryOperatorIndex gdextension_interface_dictionary_operator_index;
|
||||
extern "C" GDExtensionInterfaceDictionaryOperatorIndexConst gdextension_interface_dictionary_operator_index_const;
|
||||
extern "C" GDExtensionInterfaceDictionarySetTyped gdextension_interface_dictionary_set_typed;
|
||||
extern "C" GDExtensionInterfaceObjectMethodBindCall gdextension_interface_object_method_bind_call;
|
||||
extern "C" GDExtensionInterfaceObjectMethodBindPtrcall gdextension_interface_object_method_bind_ptrcall;
|
||||
extern "C" GDExtensionInterfaceObjectDestroy gdextension_interface_object_destroy;
|
||||
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;
|
||||
extern "C" GDExtensionInterfaceObjectGetInstanceFromId gdextension_interface_object_get_instance_from_id;
|
||||
extern "C" GDExtensionInterfaceObjectGetInstanceId gdextension_interface_object_get_instance_id;
|
||||
extern "C" GDExtensionInterfaceObjectHasScriptMethod gdextension_interface_object_has_script_method;
|
||||
extern "C" GDExtensionInterfaceObjectCallScriptMethod gdextension_interface_object_call_script_method;
|
||||
extern "C" GDExtensionInterfaceCallableCustomCreate2 gdextension_interface_callable_custom_create2;
|
||||
extern "C" GDExtensionInterfaceCallableCustomGetUserData gdextension_interface_callable_custom_get_userdata;
|
||||
extern "C" GDExtensionInterfaceRefGetObject gdextension_interface_ref_get_object;
|
||||
extern "C" GDExtensionInterfaceRefSetObject gdextension_interface_ref_set_object;
|
||||
extern "C" GDExtensionInterfaceScriptInstanceCreate3 gdextension_interface_script_instance_create3;
|
||||
extern "C" GDExtensionInterfacePlaceHolderScriptInstanceCreate gdextension_interface_placeholder_script_instance_create;
|
||||
extern "C" GDExtensionInterfacePlaceHolderScriptInstanceUpdate gdextension_interface_placeholder_script_instance_update;
|
||||
extern "C" GDExtensionInterfaceClassdbConstructObject2 gdextension_interface_classdb_construct_object2;
|
||||
extern "C" GDExtensionInterfaceScriptInstanceCreate gdextension_interface_script_instance_create;
|
||||
extern "C" GDExtensionInterfaceClassdbConstructObject gdextension_interface_classdb_construct_object;
|
||||
extern "C" GDExtensionInterfaceClassdbGetMethodBind gdextension_interface_classdb_get_method_bind;
|
||||
extern "C" GDExtensionInterfaceClassdbGetClassTag gdextension_interface_classdb_get_class_tag;
|
||||
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClass4 gdextension_interface_classdb_register_extension_class4;
|
||||
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClass gdextension_interface_classdb_register_extension_class;
|
||||
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassMethod gdextension_interface_classdb_register_extension_class_method;
|
||||
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassVirtualMethod gdextension_interface_classdb_register_extension_class_virtual_method;
|
||||
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant gdextension_interface_classdb_register_extension_class_integer_constant;
|
||||
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassProperty gdextension_interface_classdb_register_extension_class_property;
|
||||
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassPropertyIndexed gdextension_interface_classdb_register_extension_class_property_indexed;
|
||||
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassPropertyGroup gdextension_interface_classdb_register_extension_class_property_group;
|
||||
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassPropertySubgroup gdextension_interface_classdb_register_extension_class_property_subgroup;
|
||||
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassSignal gdextension_interface_classdb_register_extension_class_signal;
|
||||
@@ -198,15 +180,6 @@ extern "C" GDExtensionInterfaceClassdbUnregisterExtensionClass gdextension_inter
|
||||
extern "C" GDExtensionInterfaceGetLibraryPath gdextension_interface_get_library_path;
|
||||
extern "C" GDExtensionInterfaceEditorAddPlugin gdextension_interface_editor_add_plugin;
|
||||
extern "C" GDExtensionInterfaceEditorRemovePlugin gdextension_interface_editor_remove_plugin;
|
||||
extern "C" GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars gdextension_interface_editor_help_load_xml_from_utf8_chars;
|
||||
extern "C" GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen gdextension_interface_editor_help_load_xml_from_utf8_chars_and_len;
|
||||
extern "C" GDExtensionInterfaceImagePtrw gdextension_interface_image_ptrw;
|
||||
extern "C" GDExtensionInterfaceImagePtr gdextension_interface_image_ptr;
|
||||
|
||||
class DocDataRegistration {
|
||||
public:
|
||||
DocDataRegistration(const char *p_hash, int p_uncompressed_size, int p_compressed_size, const unsigned char *p_data);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
|
||||
@@ -139,6 +139,31 @@ public:
|
||||
|
||||
typedef T ValueType;
|
||||
|
||||
struct Iterator {
|
||||
_FORCE_INLINE_ T &operator*() const {
|
||||
return E->get();
|
||||
}
|
||||
_FORCE_INLINE_ T *operator->() const { return &E->get(); }
|
||||
_FORCE_INLINE_ Iterator &operator++() {
|
||||
E = E->next();
|
||||
return *this;
|
||||
}
|
||||
_FORCE_INLINE_ Iterator &operator--() {
|
||||
E = E->prev();
|
||||
return *this;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; }
|
||||
_FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; }
|
||||
|
||||
Iterator(Element *p_E) { E = p_E; }
|
||||
Iterator() {}
|
||||
Iterator(const Iterator &p_it) { E = p_it.E; }
|
||||
|
||||
private:
|
||||
Element *E = nullptr;
|
||||
};
|
||||
|
||||
struct ConstIterator {
|
||||
_FORCE_INLINE_ const T &operator*() const {
|
||||
return E->get();
|
||||
@@ -164,35 +189,6 @@ public:
|
||||
const Element *E = nullptr;
|
||||
};
|
||||
|
||||
struct Iterator {
|
||||
_FORCE_INLINE_ T &operator*() const {
|
||||
return E->get();
|
||||
}
|
||||
_FORCE_INLINE_ T *operator->() const { return &E->get(); }
|
||||
_FORCE_INLINE_ Iterator &operator++() {
|
||||
E = E->next();
|
||||
return *this;
|
||||
}
|
||||
_FORCE_INLINE_ Iterator &operator--() {
|
||||
E = E->prev();
|
||||
return *this;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; }
|
||||
_FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; }
|
||||
|
||||
Iterator(Element *p_E) { E = p_E; }
|
||||
Iterator() {}
|
||||
Iterator(const Iterator &p_it) { E = p_it.E; }
|
||||
|
||||
operator ConstIterator() const {
|
||||
return ConstIterator(E);
|
||||
}
|
||||
|
||||
private:
|
||||
Element *E = nullptr;
|
||||
};
|
||||
|
||||
_FORCE_INLINE_ Iterator begin() {
|
||||
return Iterator(front());
|
||||
}
|
||||
@@ -523,14 +519,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// Index operator, kept for compatibility.
|
||||
_FORCE_INLINE_ T &operator[](int p_index) {
|
||||
return get(p_index);
|
||||
}
|
||||
|
||||
// Random access to elements, use with care,
|
||||
// do not use for iteration.
|
||||
T &get(int p_index) {
|
||||
T &operator[](int p_index) {
|
||||
CRASH_BAD_INDEX(p_index, size());
|
||||
|
||||
Element *I = front();
|
||||
@@ -543,14 +532,7 @@ public:
|
||||
return I->get();
|
||||
}
|
||||
|
||||
// Index operator, kept for compatibility.
|
||||
_FORCE_INLINE_ const T &operator[](int p_index) const {
|
||||
return get(p_index);
|
||||
}
|
||||
|
||||
// Random access to elements, use with care,
|
||||
// do not use for iteration.
|
||||
const T &get(int p_index) const {
|
||||
const T &operator[](int p_index) const {
|
||||
CRASH_BAD_INDEX(p_index, size());
|
||||
|
||||
const Element *I = front();
|
||||
|
||||
@@ -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>
|
||||
@@ -257,10 +257,6 @@ public:
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool has(const T &p_val) const {
|
||||
return find(p_val) != -1;
|
||||
}
|
||||
|
||||
template <typename C>
|
||||
void sort_custom() {
|
||||
U len = count;
|
||||
|
||||
@@ -132,7 +132,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
_ALWAYS_INLINE_ explicit SafeNumeric(T p_value = static_cast<T>(0)) {
|
||||
_ALWAYS_INLINE_ explicit SafeNumeric<T>(T p_value = static_cast<T>(0)) {
|
||||
set(p_value);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace godot {
|
||||
|
||||
class Variant;
|
||||
|
||||
struct [[nodiscard]] AABB {
|
||||
struct _NO_DISCARD_ AABB {
|
||||
Vector3 position;
|
||||
Vector3 size;
|
||||
|
||||
@@ -65,7 +65,6 @@ struct [[nodiscard]] 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
|
||||
@@ -103,7 +102,7 @@ struct [[nodiscard]] AABB {
|
||||
_FORCE_INLINE_ void expand_to(const Vector3 &p_vector); /** expand to contain a point if necessary */
|
||||
|
||||
_FORCE_INLINE_ AABB abs() const {
|
||||
return AABB(position + size.minf(0), size.abs());
|
||||
return AABB(Vector3(position.x + MIN(size.x, (real_t)0), position.y + MIN(size.y, (real_t)0), position.z + MIN(size.z, (real_t)0)), size.abs());
|
||||
}
|
||||
|
||||
Variant intersects_segment_bind(const Vector3 &p_from, const Vector3 &p_to) const;
|
||||
@@ -202,11 +201,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,9 +28,6 @@
|
||||
/* 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>
|
||||
@@ -51,5 +48,3 @@ T append_all(T appendable) {
|
||||
}
|
||||
} // namespace helpers
|
||||
} // namespace godot
|
||||
|
||||
#endif // GODOT_ARRAY_HELPERS_HPP
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
namespace godot {
|
||||
|
||||
struct [[nodiscard]] Basis {
|
||||
struct _NO_DISCARD_ Basis {
|
||||
Vector3 rows[3] = {
|
||||
Vector3(1, 0, 0),
|
||||
Vector3(0, 1, 0),
|
||||
@@ -128,7 +128,6 @@ struct [[nodiscard]] 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;
|
||||
@@ -224,7 +223,7 @@ struct [[nodiscard]] Basis {
|
||||
|
||||
operator Quaternion() const { return get_quaternion(); }
|
||||
|
||||
static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false);
|
||||
static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0));
|
||||
|
||||
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); }
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* callable_custom.hpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef GODOT_CALLABLE_CUSTOM_HPP
|
||||
#define GODOT_CALLABLE_CUSTOM_HPP
|
||||
|
||||
#include <godot_cpp/core/object_id.hpp>
|
||||
#include <godot_cpp/variant/string_name.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
class Object;
|
||||
|
||||
class CallableCustomBase {
|
||||
public:
|
||||
virtual ObjectID get_object() const = 0;
|
||||
virtual int get_argument_count(bool &r_is_valid) const;
|
||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const = 0;
|
||||
virtual ~CallableCustomBase() {}
|
||||
};
|
||||
|
||||
class CallableCustom : public CallableCustomBase {
|
||||
public:
|
||||
typedef bool (*CompareEqualFunc)(const CallableCustom *p_a, const CallableCustom *p_b);
|
||||
typedef bool (*CompareLessFunc)(const CallableCustom *p_a, const CallableCustom *p_b);
|
||||
|
||||
virtual uint32_t hash() const = 0;
|
||||
virtual String get_as_text() const = 0;
|
||||
virtual CompareEqualFunc get_compare_equal_func() const = 0;
|
||||
virtual CompareLessFunc get_compare_less_func() const = 0;
|
||||
virtual bool is_valid() const;
|
||||
virtual ObjectID get_object() const = 0;
|
||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const = 0;
|
||||
};
|
||||
|
||||
} // namespace godot
|
||||
|
||||
#endif // GODOT_CALLABLE_CUSTOM_HPP
|
||||
@@ -1,273 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* callable_method_pointer.hpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef GODOT_CALLABLE_METHOD_POINTER_HPP
|
||||
#define GODOT_CALLABLE_METHOD_POINTER_HPP
|
||||
|
||||
#include <godot_cpp/core/binder_common.hpp>
|
||||
#include <godot_cpp/variant/variant.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
class CallableCustomMethodPointerBase : public CallableCustomBase {
|
||||
uint32_t *comp_ptr = nullptr;
|
||||
uint32_t comp_size;
|
||||
uint32_t h;
|
||||
|
||||
protected:
|
||||
void _setup(uint32_t *p_base_ptr, uint32_t p_ptr_size);
|
||||
|
||||
public:
|
||||
_FORCE_INLINE_ const uint32_t *get_comp_ptr() const { return comp_ptr; }
|
||||
_FORCE_INLINE_ uint32_t get_comp_size() const { return comp_size; }
|
||||
_FORCE_INLINE_ uint32_t get_hash() const { return h; }
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
Callable create_callable_from_ccmp(CallableCustomMethodPointerBase *p_callable_method_pointer);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
//
|
||||
// No return value.
|
||||
//
|
||||
|
||||
template <typename T, typename... P>
|
||||
class CallableCustomMethodPointer : public CallableCustomMethodPointerBase {
|
||||
struct Data {
|
||||
T *instance;
|
||||
void (T::*method)(P...);
|
||||
} data;
|
||||
static_assert(sizeof(Data) % 4 == 0);
|
||||
|
||||
public:
|
||||
virtual ObjectID get_object() const override {
|
||||
return ObjectID(data.instance->get_instance_id());
|
||||
}
|
||||
|
||||
virtual int get_argument_count(bool &r_is_valid) const override {
|
||||
r_is_valid = true;
|
||||
return sizeof...(P);
|
||||
}
|
||||
|
||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
|
||||
call_with_variant_args(data.instance, data.method, p_arguments, p_argcount, r_call_error);
|
||||
}
|
||||
|
||||
CallableCustomMethodPointer(T *p_instance, void (T::*p_method)(P...)) {
|
||||
memset(&data, 0, sizeof(Data));
|
||||
data.instance = p_instance;
|
||||
data.method = p_method;
|
||||
_setup((uint32_t *)&data, sizeof(Data));
|
||||
}
|
||||
};
|
||||
|
||||
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));
|
||||
return ::godot::internal::create_callable_from_ccmp(ccmp);
|
||||
}
|
||||
|
||||
//
|
||||
// With return value.
|
||||
//
|
||||
|
||||
template <typename T, typename R, typename... P>
|
||||
class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase {
|
||||
struct Data {
|
||||
T *instance;
|
||||
R(T::*method)
|
||||
(P...);
|
||||
} data;
|
||||
static_assert(sizeof(Data) % 4 == 0);
|
||||
|
||||
public:
|
||||
virtual ObjectID get_object() const override {
|
||||
return ObjectID(data.instance->get_instance_id());
|
||||
}
|
||||
|
||||
virtual int get_argument_count(bool &r_is_valid) const override {
|
||||
r_is_valid = true;
|
||||
return sizeof...(P);
|
||||
}
|
||||
|
||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
|
||||
call_with_variant_args_ret(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
|
||||
}
|
||||
|
||||
CallableCustomMethodPointerRet(T *p_instance, R (T::*p_method)(P...)) {
|
||||
memset(&data, 0, sizeof(Data));
|
||||
data.instance = p_instance;
|
||||
data.method = p_method;
|
||||
_setup((uint32_t *)&data, sizeof(Data));
|
||||
}
|
||||
};
|
||||
|
||||
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));
|
||||
return ::godot::internal::create_callable_from_ccmp(ccmp);
|
||||
}
|
||||
|
||||
//
|
||||
// Const with return value.
|
||||
//
|
||||
|
||||
template <typename T, typename R, typename... P>
|
||||
class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase {
|
||||
struct Data {
|
||||
T *instance;
|
||||
R(T::*method)
|
||||
(P...) const;
|
||||
} data;
|
||||
static_assert(sizeof(Data) % 4 == 0);
|
||||
|
||||
public:
|
||||
virtual ObjectID get_object() const override {
|
||||
return ObjectID(data.instance->get_instance_id());
|
||||
}
|
||||
|
||||
virtual int get_argument_count(bool &r_is_valid) const override {
|
||||
r_is_valid = true;
|
||||
return sizeof...(P);
|
||||
}
|
||||
|
||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
|
||||
call_with_variant_args_retc(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
|
||||
}
|
||||
|
||||
CallableCustomMethodPointerRetC(const T *p_instance, R (T::*p_method)(P...) const) {
|
||||
memset(&data, 0, sizeof(Data));
|
||||
data.instance = const_cast<T *>(p_instance);
|
||||
data.method = p_method;
|
||||
_setup((uint32_t *)&data, sizeof(Data));
|
||||
}
|
||||
};
|
||||
|
||||
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));
|
||||
return ::godot::internal::create_callable_from_ccmp(ccmp);
|
||||
}
|
||||
|
||||
//
|
||||
// Static method with no return value.
|
||||
//
|
||||
|
||||
template <typename... P>
|
||||
class CallableCustomStaticMethodPointer : public CallableCustomMethodPointerBase {
|
||||
struct Data {
|
||||
void (*method)(P...);
|
||||
} data;
|
||||
static_assert(sizeof(Data) % 4 == 0);
|
||||
|
||||
public:
|
||||
virtual ObjectID get_object() const override {
|
||||
return ObjectID();
|
||||
}
|
||||
|
||||
virtual int get_argument_count(bool &r_is_valid) const override {
|
||||
r_is_valid = true;
|
||||
return sizeof...(P);
|
||||
}
|
||||
|
||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
|
||||
call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error);
|
||||
r_return_value = Variant();
|
||||
}
|
||||
|
||||
CallableCustomStaticMethodPointer(void (*p_method)(P...)) {
|
||||
memset(&data, 0, sizeof(Data));
|
||||
data.method = p_method;
|
||||
_setup((uint32_t *)&data, sizeof(Data));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... P>
|
||||
Callable create_custom_callable_static_function_pointer(void (*p_method)(P...)) {
|
||||
typedef CallableCustomStaticMethodPointer<P...> CCMP;
|
||||
CCMP *ccmp = memnew(CCMP(p_method));
|
||||
return ::godot::internal::create_callable_from_ccmp(ccmp);
|
||||
}
|
||||
|
||||
//
|
||||
// Static method with return value.
|
||||
//
|
||||
|
||||
template <typename R, typename... P>
|
||||
class CallableCustomStaticMethodPointerRet : public CallableCustomMethodPointerBase {
|
||||
struct Data {
|
||||
R(*method)
|
||||
(P...);
|
||||
} data;
|
||||
static_assert(sizeof(Data) % 4 == 0);
|
||||
|
||||
public:
|
||||
virtual ObjectID get_object() const override {
|
||||
return ObjectID();
|
||||
}
|
||||
|
||||
virtual int get_argument_count(bool &r_is_valid) const override {
|
||||
r_is_valid = true;
|
||||
return sizeof...(P);
|
||||
}
|
||||
|
||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
|
||||
call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error);
|
||||
}
|
||||
|
||||
CallableCustomStaticMethodPointerRet(R (*p_method)(P...)) {
|
||||
memset(&data, 0, sizeof(Data));
|
||||
data.method = p_method;
|
||||
_setup((uint32_t *)&data, sizeof(Data));
|
||||
}
|
||||
};
|
||||
|
||||
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));
|
||||
return ::godot::internal::create_callable_from_ccmp(ccmp);
|
||||
}
|
||||
|
||||
//
|
||||
// The API:
|
||||
//
|
||||
|
||||
#define callable_mp(I, M) ::godot::create_custom_callable_function_pointer(I, M)
|
||||
#define callable_mp_static(M) ::godot::create_custom_callable_static_function_pointer(M)
|
||||
|
||||
} // namespace godot
|
||||
|
||||
#endif // GODOT_CALLABLE_METHOD_POINTER_HPP
|
||||
@@ -37,7 +37,7 @@ namespace godot {
|
||||
|
||||
class String;
|
||||
|
||||
struct [[nodiscard]] Color {
|
||||
struct _NO_DISCARD_ Color {
|
||||
union {
|
||||
struct {
|
||||
float r;
|
||||
|
||||
@@ -28,9 +28,6 @@
|
||||
/* 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
|
||||
@@ -192,5 +189,3 @@ static NamedColor named_colors[] = {
|
||||
};
|
||||
|
||||
} // namespace godot
|
||||
|
||||
#endif // GODOT_COLOR_NAMES_INC_HPP
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace godot {
|
||||
|
||||
class Variant;
|
||||
|
||||
struct [[nodiscard]] Plane {
|
||||
struct _NO_DISCARD_ Plane {
|
||||
Vector3 normal;
|
||||
real_t d = 0;
|
||||
|
||||
@@ -77,7 +77,6 @@ struct [[nodiscard]] 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;
|
||||
|
||||
@@ -44,7 +44,7 @@ struct Rect2;
|
||||
struct Transform3D;
|
||||
struct Vector2;
|
||||
|
||||
struct [[nodiscard]] Projection {
|
||||
struct _NO_DISCARD_ Projection {
|
||||
enum Planes {
|
||||
PLANE_NEAR,
|
||||
PLANE_FAR,
|
||||
|
||||
@@ -31,13 +31,12 @@
|
||||
#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>
|
||||
|
||||
namespace godot {
|
||||
|
||||
struct [[nodiscard]] Quaternion {
|
||||
struct _NO_DISCARD_ Quaternion {
|
||||
union {
|
||||
struct {
|
||||
real_t x;
|
||||
@@ -48,15 +47,14 @@ struct [[nodiscard]] Quaternion {
|
||||
real_t components[4] = { 0, 0, 0, 1.0 };
|
||||
};
|
||||
|
||||
_FORCE_INLINE_ real_t &operator[](int p_idx) {
|
||||
return components[p_idx];
|
||||
_FORCE_INLINE_ real_t &operator[](int idx) {
|
||||
return components[idx];
|
||||
}
|
||||
_FORCE_INLINE_ const real_t &operator[](int p_idx) const {
|
||||
return components[p_idx];
|
||||
_FORCE_INLINE_ const real_t &operator[](int idx) const {
|
||||
return components[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;
|
||||
@@ -67,13 +65,14 @@ struct [[nodiscard]] Quaternion {
|
||||
_FORCE_INLINE_ real_t dot(const Quaternion &p_q) const;
|
||||
real_t angle_to(const Quaternion &p_to) const;
|
||||
|
||||
Vector3 get_euler(EulerOrder p_order = EulerOrder::EULER_ORDER_YXZ) const;
|
||||
static Quaternion from_euler(const Vector3 &p_euler);
|
||||
Vector3 get_euler_xyz() const;
|
||||
Vector3 get_euler_yxz() const;
|
||||
Vector3 get_euler() const { return get_euler_yxz(); }
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
Vector3 get_axis() const;
|
||||
real_t get_angle() const;
|
||||
@@ -89,28 +88,28 @@ struct [[nodiscard]] Quaternion {
|
||||
void operator*=(const Quaternion &p_q);
|
||||
Quaternion operator*(const Quaternion &p_q) const;
|
||||
|
||||
_FORCE_INLINE_ Vector3 xform(const Vector3 &p_v) const {
|
||||
_FORCE_INLINE_ Vector3 xform(const Vector3 &v) const {
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND_V_MSG(!is_normalized(), p_v, "The quaternion " + operator String() + " must be normalized.");
|
||||
ERR_FAIL_COND_V_MSG(!is_normalized(), v, "The quaternion must be normalized.");
|
||||
#endif
|
||||
Vector3 u(x, y, z);
|
||||
Vector3 uv = u.cross(p_v);
|
||||
return p_v + ((uv * w) + u.cross(uv)) * ((real_t)2);
|
||||
Vector3 uv = u.cross(v);
|
||||
return v + ((uv * w) + u.cross(uv)) * ((real_t)2);
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ Vector3 xform_inv(const Vector3 &p_v) const {
|
||||
return inverse().xform(p_v);
|
||||
_FORCE_INLINE_ Vector3 xform_inv(const Vector3 &v) const {
|
||||
return inverse().xform(v);
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ void operator+=(const Quaternion &p_q);
|
||||
_FORCE_INLINE_ void operator-=(const Quaternion &p_q);
|
||||
_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_ 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_ Quaternion operator-() const;
|
||||
_FORCE_INLINE_ Quaternion operator*(real_t p_s) const;
|
||||
_FORCE_INLINE_ Quaternion operator/(real_t p_s) const;
|
||||
_FORCE_INLINE_ Quaternion operator*(const real_t &s) const;
|
||||
_FORCE_INLINE_ Quaternion operator/(const real_t &s) const;
|
||||
|
||||
_FORCE_INLINE_ bool operator==(const Quaternion &p_quaternion) const;
|
||||
_FORCE_INLINE_ bool operator!=(const Quaternion &p_quaternion) const;
|
||||
@@ -128,6 +127,8 @@ struct [[nodiscard]] 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),
|
||||
@@ -142,9 +143,9 @@ struct [[nodiscard]] Quaternion {
|
||||
w = p_q.w;
|
||||
}
|
||||
|
||||
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);
|
||||
Quaternion(const Vector3 &v0, const Vector3 &v1) { // Shortest arc.
|
||||
Vector3 c = v0.cross(v1);
|
||||
real_t d = v0.dot(v1);
|
||||
|
||||
if (d < -1.0f + (real_t)CMP_EPSILON) {
|
||||
x = 0;
|
||||
@@ -185,25 +186,25 @@ void Quaternion::operator-=(const Quaternion &p_q) {
|
||||
w -= p_q.w;
|
||||
}
|
||||
|
||||
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) {
|
||||
x *= s;
|
||||
y *= s;
|
||||
z *= s;
|
||||
w *= s;
|
||||
}
|
||||
|
||||
void Quaternion::operator/=(real_t p_s) {
|
||||
*this *= 1.0f / p_s;
|
||||
void Quaternion::operator/=(const real_t &s) {
|
||||
*this *= 1.0f / s;
|
||||
}
|
||||
|
||||
Quaternion Quaternion::operator+(const Quaternion &p_q2) const {
|
||||
Quaternion Quaternion::operator+(const Quaternion &q2) const {
|
||||
const Quaternion &q1 = *this;
|
||||
return Quaternion(q1.x + p_q2.x, q1.y + p_q2.y, q1.z + p_q2.z, q1.w + p_q2.w);
|
||||
return Quaternion(q1.x + q2.x, q1.y + q2.y, q1.z + q2.z, q1.w + q2.w);
|
||||
}
|
||||
|
||||
Quaternion Quaternion::operator-(const Quaternion &p_q2) const {
|
||||
Quaternion Quaternion::operator-(const Quaternion &q2) const {
|
||||
const Quaternion &q1 = *this;
|
||||
return Quaternion(q1.x - p_q2.x, q1.y - p_q2.y, q1.z - p_q2.z, q1.w - p_q2.w);
|
||||
return Quaternion(q1.x - q2.x, q1.y - q2.y, q1.z - q2.z, q1.w - q2.w);
|
||||
}
|
||||
|
||||
Quaternion Quaternion::operator-() const {
|
||||
@@ -211,12 +212,12 @@ Quaternion Quaternion::operator-() const {
|
||||
return Quaternion(-q2.x, -q2.y, -q2.z, -q2.w);
|
||||
}
|
||||
|
||||
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 Quaternion(x * s, y * s, z * s, w * s);
|
||||
}
|
||||
|
||||
Quaternion Quaternion::operator/(real_t p_s) const {
|
||||
return *this * (1.0f / p_s);
|
||||
Quaternion Quaternion::operator/(const real_t &s) const {
|
||||
return *this * (1.0f / s);
|
||||
}
|
||||
|
||||
bool Quaternion::operator==(const Quaternion &p_quaternion) const {
|
||||
@@ -227,7 +228,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*(real_t p_real, const Quaternion &p_quaternion) {
|
||||
_FORCE_INLINE_ Quaternion operator*(const real_t &p_real, const Quaternion &p_quaternion) {
|
||||
return p_quaternion * p_real;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ class String;
|
||||
struct Rect2i;
|
||||
struct Transform2D;
|
||||
|
||||
struct [[nodiscard]] Rect2 {
|
||||
struct _NO_DISCARD_ Rect2 {
|
||||
Point2 position;
|
||||
Size2 size;
|
||||
|
||||
@@ -146,7 +146,7 @@ struct [[nodiscard]] Rect2 {
|
||||
return size.x > 0.0f && size.y > 0.0f;
|
||||
}
|
||||
|
||||
// Returns the intersection between two Rect2s or an empty Rect2 if there is no intersection
|
||||
// Returns the instersection 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;
|
||||
|
||||
@@ -154,12 +154,14 @@ struct [[nodiscard]] Rect2 {
|
||||
return Rect2();
|
||||
}
|
||||
|
||||
new_rect.position = p_rect.position.max(position);
|
||||
new_rect.position.x = Math::max(p_rect.position.x, position.x);
|
||||
new_rect.position.y = Math::max(p_rect.position.y, position.y);
|
||||
|
||||
Point2 p_rect_end = p_rect.position + p_rect.size;
|
||||
Point2 end = position + size;
|
||||
|
||||
new_rect.size = p_rect_end.min(end) - new_rect.position;
|
||||
new_rect.size.x = Math::min(p_rect_end.x, end.x) - new_rect.position.x;
|
||||
new_rect.size.y = Math::min(p_rect_end.y, end.y) - new_rect.position.y;
|
||||
|
||||
return new_rect;
|
||||
}
|
||||
@@ -172,9 +174,11 @@ struct [[nodiscard]] Rect2 {
|
||||
#endif
|
||||
Rect2 new_rect;
|
||||
|
||||
new_rect.position = p_rect.position.min(position);
|
||||
new_rect.position.x = Math::min(p_rect.position.x, position.x);
|
||||
new_rect.position.y = Math::min(p_rect.position.y, position.y);
|
||||
|
||||
new_rect.size = (p_rect.position + p_rect.size).max(position + size);
|
||||
new_rect.size.x = Math::max(p_rect.position.x + p_rect.size.x, position.x + size.x);
|
||||
new_rect.size.y = Math::max(p_rect.position.y + p_rect.size.y, position.y + size.y);
|
||||
|
||||
new_rect.size = new_rect.size - new_rect.position; // Make relative again.
|
||||
|
||||
@@ -205,7 +209,6 @@ struct [[nodiscard]] 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; }
|
||||
@@ -280,7 +283,7 @@ struct [[nodiscard]] Rect2 {
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ Rect2 abs() const {
|
||||
return Rect2(position + size.minf(0), size.abs());
|
||||
return Rect2(Point2(position.x + Math::min(size.x, (real_t)0), position.y + Math::min(size.y, (real_t)0)), size.abs());
|
||||
}
|
||||
|
||||
Vector2 get_support(const Vector2 &p_normal) const {
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace godot {
|
||||
class String;
|
||||
struct Rect2;
|
||||
|
||||
struct [[nodiscard]] Rect2i {
|
||||
struct _NO_DISCARD_ Rect2i {
|
||||
Point2i position;
|
||||
Size2i size;
|
||||
|
||||
@@ -89,7 +89,7 @@ struct [[nodiscard]] Rect2i {
|
||||
return size.x > 0 && size.y > 0;
|
||||
}
|
||||
|
||||
// Returns the intersection between two Rect2is or an empty Rect2i if there is no intersection
|
||||
// Returns the instersection 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;
|
||||
|
||||
@@ -97,12 +97,14 @@ struct [[nodiscard]] Rect2i {
|
||||
return Rect2i();
|
||||
}
|
||||
|
||||
new_rect.position = p_rect.position.max(position);
|
||||
new_rect.position.x = Math::max(p_rect.position.x, position.x);
|
||||
new_rect.position.y = Math::max(p_rect.position.y, position.y);
|
||||
|
||||
Point2i p_rect_end = p_rect.position + p_rect.size;
|
||||
Point2i end = position + size;
|
||||
|
||||
new_rect.size = p_rect_end.min(end) - new_rect.position;
|
||||
new_rect.size.x = Math::min(p_rect_end.x, end.x) - new_rect.position.x;
|
||||
new_rect.size.y = Math::min(p_rect_end.y, end.y) - new_rect.position.y;
|
||||
|
||||
return new_rect;
|
||||
}
|
||||
@@ -115,9 +117,11 @@ struct [[nodiscard]] Rect2i {
|
||||
#endif
|
||||
Rect2i new_rect;
|
||||
|
||||
new_rect.position = p_rect.position.min(position);
|
||||
new_rect.position.x = Math::min(p_rect.position.x, position.x);
|
||||
new_rect.position.y = Math::min(p_rect.position.y, position.y);
|
||||
|
||||
new_rect.size = (p_rect.position + p_rect.size).max(position + size);
|
||||
new_rect.size.x = Math::max(p_rect.position.x + p_rect.size.x, position.x + size.x);
|
||||
new_rect.size.y = Math::max(p_rect.position.y + p_rect.size.y, position.y + size.y);
|
||||
|
||||
new_rect.size = new_rect.size - new_rect.position; // Make relative again.
|
||||
|
||||
@@ -215,7 +219,7 @@ struct [[nodiscard]] Rect2i {
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ Rect2i abs() const {
|
||||
return Rect2i(position + size.mini(0), size.abs());
|
||||
return Rect2i(Point2i(position.x + Math::min(size.x, 0), position.y + Math::min(size.y, 0)), size.abs());
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ void set_end(const Vector2i &p_end) {
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace godot {
|
||||
|
||||
class String;
|
||||
|
||||
struct [[nodiscard]] Transform2D {
|
||||
struct _NO_DISCARD_ Transform2D {
|
||||
// Warning #1: basis of Transform2D is stored differently from Basis. In terms of columns array, the basis matrix looks like "on paper":
|
||||
// M = (columns[0][0] columns[1][0])
|
||||
// (columns[0][1] columns[1][1])
|
||||
@@ -99,7 +99,6 @@ struct [[nodiscard]] 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;
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
namespace godot {
|
||||
|
||||
struct [[nodiscard]] Transform3D {
|
||||
struct _NO_DISCARD_ Transform3D {
|
||||
Basis basis;
|
||||
Vector3 origin;
|
||||
|
||||
@@ -78,7 +78,6 @@ struct [[nodiscard]] 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;
|
||||
|
||||
@@ -44,15 +44,10 @@ public:
|
||||
_ref(p_array);
|
||||
}
|
||||
_FORCE_INLINE_ TypedArray(const Variant &p_variant) :
|
||||
TypedArray(Array(p_variant)) {
|
||||
Array(p_variant.operator 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(const Array &p_array) :
|
||||
Array(p_array, Variant::OBJECT, T::get_class_static(), Variant()) {
|
||||
}
|
||||
_FORCE_INLINE_ TypedArray() {
|
||||
set_typed(Variant::OBJECT, T::get_class_static(), Variant());
|
||||
@@ -70,23 +65,16 @@ public:
|
||||
_ref(p_array); \
|
||||
} \
|
||||
_FORCE_INLINE_ TypedArray(const Variant &p_variant) : \
|
||||
TypedArray(Array(p_variant)) { \
|
||||
Array(p_variant.operator 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(const Array &p_array) : \
|
||||
Array(p_array, m_variant_type, StringName(), Variant()) { \
|
||||
} \
|
||||
_FORCE_INLINE_ TypedArray() { \
|
||||
set_typed(m_variant_type, StringName(), Variant()); \
|
||||
} \
|
||||
};
|
||||
|
||||
// All Variant::OBJECT types are intentionally omitted from this list because they are handled by
|
||||
// the unspecialized TypedArray definition.
|
||||
MAKE_TYPED_ARRAY(bool, Variant::BOOL)
|
||||
MAKE_TYPED_ARRAY(uint8_t, Variant::INT)
|
||||
MAKE_TYPED_ARRAY(int8_t, Variant::INT)
|
||||
@@ -106,14 +94,11 @@ MAKE_TYPED_ARRAY(Rect2i, Variant::RECT2I)
|
||||
MAKE_TYPED_ARRAY(Vector3, Variant::VECTOR3)
|
||||
MAKE_TYPED_ARRAY(Vector3i, Variant::VECTOR3I)
|
||||
MAKE_TYPED_ARRAY(Transform2D, Variant::TRANSFORM2D)
|
||||
MAKE_TYPED_ARRAY(Vector4, Variant::VECTOR4)
|
||||
MAKE_TYPED_ARRAY(Vector4i, Variant::VECTOR4I)
|
||||
MAKE_TYPED_ARRAY(Plane, Variant::PLANE)
|
||||
MAKE_TYPED_ARRAY(Quaternion, Variant::QUATERNION)
|
||||
MAKE_TYPED_ARRAY(AABB, Variant::AABB)
|
||||
MAKE_TYPED_ARRAY(Basis, Variant::BASIS)
|
||||
MAKE_TYPED_ARRAY(Transform3D, Variant::TRANSFORM3D)
|
||||
MAKE_TYPED_ARRAY(Projection, Variant::PROJECTION)
|
||||
MAKE_TYPED_ARRAY(Color, Variant::COLOR)
|
||||
MAKE_TYPED_ARRAY(StringName, Variant::STRING_NAME)
|
||||
MAKE_TYPED_ARRAY(NodePath, Variant::NODE_PATH)
|
||||
@@ -130,12 +115,7 @@ MAKE_TYPED_ARRAY(PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY)
|
||||
MAKE_TYPED_ARRAY(PackedStringArray, Variant::PACKED_STRING_ARRAY)
|
||||
MAKE_TYPED_ARRAY(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY)
|
||||
MAKE_TYPED_ARRAY(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY)
|
||||
MAKE_TYPED_ARRAY(PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY)
|
||||
MAKE_TYPED_ARRAY(PackedColorArray, Variant::PACKED_COLOR_ARRAY)
|
||||
// If the IPAddress struct is added to godot-cpp, the following could also be added:
|
||||
//MAKE_TYPED_ARRAY(IPAddress, Variant::STRING)
|
||||
|
||||
#undef MAKE_TYPED_ARRAY
|
||||
|
||||
} // namespace godot
|
||||
|
||||
|
||||
@@ -1,439 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* typed_dictionary.hpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef GODOT_TYPED_DICTIONARY_HPP
|
||||
#define GODOT_TYPED_DICTIONARY_HPP
|
||||
|
||||
#include <godot_cpp/core/type_info.hpp>
|
||||
#include <godot_cpp/variant/dictionary.hpp>
|
||||
#include <godot_cpp/variant/variant.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
template <typename K, typename V>
|
||||
class TypedDictionary : public Dictionary {
|
||||
public:
|
||||
_FORCE_INLINE_ void operator=(const Dictionary &p_dictionary) {
|
||||
ERR_FAIL_COND_MSG(!is_same_typed(p_dictionary), "Cannot assign a dictionary with a different element type.");
|
||||
Dictionary::operator=(p_dictionary);
|
||||
}
|
||||
_FORCE_INLINE_ TypedDictionary(const Variant &p_variant) :
|
||||
TypedDictionary(Dictionary(p_variant)) {
|
||||
}
|
||||
_FORCE_INLINE_ TypedDictionary(const Dictionary &p_dictionary) {
|
||||
set_typed(Variant::OBJECT, K::get_class_static(), Variant(), Variant::OBJECT, V::get_class_static(), Variant());
|
||||
if (is_same_typed(p_dictionary)) {
|
||||
Dictionary::operator=(p_dictionary);
|
||||
} else {
|
||||
assign(p_dictionary);
|
||||
}
|
||||
}
|
||||
_FORCE_INLINE_ TypedDictionary() {
|
||||
set_typed(Variant::OBJECT, K::get_class_static(), Variant(), Variant::OBJECT, V::get_class_static(), Variant());
|
||||
}
|
||||
};
|
||||
|
||||
//specialization for the rest of variant types
|
||||
|
||||
#define MAKE_TYPED_DICTIONARY_WITH_OBJECT(m_type, m_variant_type) \
|
||||
template <typename T> \
|
||||
class TypedDictionary<T, m_type> : public Dictionary { \
|
||||
public: \
|
||||
_FORCE_INLINE_ void operator=(const Dictionary &p_dictionary) { \
|
||||
ERR_FAIL_COND_MSG(!is_same_typed(p_dictionary), "Cannot assign an dictionary with a different element type."); \
|
||||
Dictionary::operator=(p_dictionary); \
|
||||
} \
|
||||
_FORCE_INLINE_ TypedDictionary(const Variant &p_variant) : \
|
||||
TypedDictionary(Dictionary(p_variant)) { \
|
||||
} \
|
||||
_FORCE_INLINE_ TypedDictionary(const Dictionary &p_dictionary) { \
|
||||
set_typed(Variant::OBJECT, T::get_class_static(), Variant(), m_variant_type, StringName(), Variant()); \
|
||||
if (is_same_typed(p_dictionary)) { \
|
||||
Dictionary::operator=(p_dictionary); \
|
||||
} else { \
|
||||
assign(p_dictionary); \
|
||||
} \
|
||||
} \
|
||||
_FORCE_INLINE_ TypedDictionary() { \
|
||||
set_typed(Variant::OBJECT, T::get_class_static(), Variant(), m_variant_type, StringName(), Variant()); \
|
||||
} \
|
||||
}; \
|
||||
template <typename T> \
|
||||
class TypedDictionary<m_type, T> : public Dictionary { \
|
||||
public: \
|
||||
_FORCE_INLINE_ void operator=(const Dictionary &p_dictionary) { \
|
||||
ERR_FAIL_COND_MSG(!is_same_typed(p_dictionary), "Cannot assign an dictionary with a different element type."); \
|
||||
Dictionary::operator=(p_dictionary); \
|
||||
} \
|
||||
_FORCE_INLINE_ TypedDictionary(const Variant &p_variant) : \
|
||||
TypedDictionary(Dictionary(p_variant)) { \
|
||||
} \
|
||||
_FORCE_INLINE_ TypedDictionary(const Dictionary &p_dictionary) { \
|
||||
set_typed(m_variant_type, StringName(), Variant(), Variant::OBJECT, T::get_class_static(), Variant()); \
|
||||
if (is_same_typed(p_dictionary)) { \
|
||||
Dictionary::operator=(p_dictionary); \
|
||||
} else { \
|
||||
assign(p_dictionary); \
|
||||
} \
|
||||
} \
|
||||
_FORCE_INLINE_ TypedDictionary() { \
|
||||
set_typed(m_variant_type, StringName(), Variant(), Variant::OBJECT, T::get_class_static(), Variant()); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define MAKE_TYPED_DICTIONARY_EXPANDED(m_type_key, m_variant_type_key, m_type_value, m_variant_type_value) \
|
||||
template <> \
|
||||
class TypedDictionary<m_type_key, m_type_value> : public Dictionary { \
|
||||
public: \
|
||||
_FORCE_INLINE_ void operator=(const Dictionary &p_dictionary) { \
|
||||
ERR_FAIL_COND_MSG(!is_same_typed(p_dictionary), "Cannot assign an dictionary with a different element type."); \
|
||||
Dictionary::operator=(p_dictionary); \
|
||||
} \
|
||||
_FORCE_INLINE_ TypedDictionary(const Variant &p_variant) : \
|
||||
TypedDictionary(Dictionary(p_variant)) { \
|
||||
} \
|
||||
_FORCE_INLINE_ TypedDictionary(const Dictionary &p_dictionary) { \
|
||||
set_typed(m_variant_type_key, StringName(), Variant(), m_variant_type_value, StringName(), Variant()); \
|
||||
if (is_same_typed(p_dictionary)) { \
|
||||
Dictionary::operator=(p_dictionary); \
|
||||
} else { \
|
||||
assign(p_dictionary); \
|
||||
} \
|
||||
} \
|
||||
_FORCE_INLINE_ TypedDictionary() { \
|
||||
set_typed(m_variant_type_key, StringName(), Variant(), m_variant_type_value, StringName(), Variant()); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define MAKE_TYPED_DICTIONARY_NIL(m_type, m_variant_type) \
|
||||
MAKE_TYPED_DICTIONARY_WITH_OBJECT(m_type, m_variant_type) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, bool, Variant::BOOL) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, uint8_t, Variant::INT) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, int8_t, Variant::INT) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, uint16_t, Variant::INT) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, int16_t, Variant::INT) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, uint32_t, Variant::INT) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, int32_t, Variant::INT) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, uint64_t, Variant::INT) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, int64_t, Variant::INT) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, float, Variant::FLOAT) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, double, Variant::FLOAT) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, String, Variant::STRING) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Vector2, Variant::VECTOR2) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Vector2i, Variant::VECTOR2I) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Rect2, Variant::RECT2) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Rect2i, Variant::RECT2I) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Vector3, Variant::VECTOR3) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Vector3i, Variant::VECTOR3I) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Transform2D, Variant::TRANSFORM2D) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Plane, Variant::PLANE) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Quaternion, Variant::QUATERNION) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, AABB, Variant::AABB) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Basis, Variant::BASIS) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Transform3D, Variant::TRANSFORM3D) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Color, Variant::COLOR) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, StringName, Variant::STRING_NAME) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, NodePath, Variant::NODE_PATH) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, RID, Variant::RID) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Callable, Variant::CALLABLE) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Signal, Variant::SIGNAL) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Dictionary, Variant::DICTIONARY) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Array, Variant::ARRAY) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedByteArray, Variant::PACKED_BYTE_ARRAY) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedInt32Array, Variant::PACKED_INT32_ARRAY) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedInt64Array, Variant::PACKED_INT64_ARRAY) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedFloat32Array, Variant::PACKED_FLOAT32_ARRAY) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedStringArray, Variant::PACKED_STRING_ARRAY) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedColorArray, Variant::PACKED_COLOR_ARRAY) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY) \
|
||||
/*MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, IPAddress, Variant::STRING)*/
|
||||
|
||||
#define MAKE_TYPED_DICTIONARY(m_type, m_variant_type) \
|
||||
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Variant, Variant::NIL) \
|
||||
MAKE_TYPED_DICTIONARY_NIL(m_type, m_variant_type)
|
||||
|
||||
MAKE_TYPED_DICTIONARY_NIL(Variant, Variant::NIL)
|
||||
MAKE_TYPED_DICTIONARY(bool, Variant::BOOL)
|
||||
MAKE_TYPED_DICTIONARY(uint8_t, Variant::INT)
|
||||
MAKE_TYPED_DICTIONARY(int8_t, Variant::INT)
|
||||
MAKE_TYPED_DICTIONARY(uint16_t, Variant::INT)
|
||||
MAKE_TYPED_DICTIONARY(int16_t, Variant::INT)
|
||||
MAKE_TYPED_DICTIONARY(uint32_t, Variant::INT)
|
||||
MAKE_TYPED_DICTIONARY(int32_t, Variant::INT)
|
||||
MAKE_TYPED_DICTIONARY(uint64_t, Variant::INT)
|
||||
MAKE_TYPED_DICTIONARY(int64_t, Variant::INT)
|
||||
MAKE_TYPED_DICTIONARY(float, Variant::FLOAT)
|
||||
MAKE_TYPED_DICTIONARY(double, Variant::FLOAT)
|
||||
MAKE_TYPED_DICTIONARY(String, Variant::STRING)
|
||||
MAKE_TYPED_DICTIONARY(Vector2, Variant::VECTOR2)
|
||||
MAKE_TYPED_DICTIONARY(Vector2i, Variant::VECTOR2I)
|
||||
MAKE_TYPED_DICTIONARY(Rect2, Variant::RECT2)
|
||||
MAKE_TYPED_DICTIONARY(Rect2i, Variant::RECT2I)
|
||||
MAKE_TYPED_DICTIONARY(Vector3, Variant::VECTOR3)
|
||||
MAKE_TYPED_DICTIONARY(Vector3i, Variant::VECTOR3I)
|
||||
MAKE_TYPED_DICTIONARY(Transform2D, Variant::TRANSFORM2D)
|
||||
MAKE_TYPED_DICTIONARY(Plane, Variant::PLANE)
|
||||
MAKE_TYPED_DICTIONARY(Quaternion, Variant::QUATERNION)
|
||||
MAKE_TYPED_DICTIONARY(AABB, Variant::AABB)
|
||||
MAKE_TYPED_DICTIONARY(Basis, Variant::BASIS)
|
||||
MAKE_TYPED_DICTIONARY(Transform3D, Variant::TRANSFORM3D)
|
||||
MAKE_TYPED_DICTIONARY(Color, Variant::COLOR)
|
||||
MAKE_TYPED_DICTIONARY(StringName, Variant::STRING_NAME)
|
||||
MAKE_TYPED_DICTIONARY(NodePath, Variant::NODE_PATH)
|
||||
MAKE_TYPED_DICTIONARY(RID, Variant::RID)
|
||||
MAKE_TYPED_DICTIONARY(Callable, Variant::CALLABLE)
|
||||
MAKE_TYPED_DICTIONARY(Signal, Variant::SIGNAL)
|
||||
MAKE_TYPED_DICTIONARY(Dictionary, Variant::DICTIONARY)
|
||||
MAKE_TYPED_DICTIONARY(Array, Variant::ARRAY)
|
||||
MAKE_TYPED_DICTIONARY(PackedByteArray, Variant::PACKED_BYTE_ARRAY)
|
||||
MAKE_TYPED_DICTIONARY(PackedInt32Array, Variant::PACKED_INT32_ARRAY)
|
||||
MAKE_TYPED_DICTIONARY(PackedInt64Array, Variant::PACKED_INT64_ARRAY)
|
||||
MAKE_TYPED_DICTIONARY(PackedFloat32Array, Variant::PACKED_FLOAT32_ARRAY)
|
||||
MAKE_TYPED_DICTIONARY(PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY)
|
||||
MAKE_TYPED_DICTIONARY(PackedStringArray, Variant::PACKED_STRING_ARRAY)
|
||||
MAKE_TYPED_DICTIONARY(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY)
|
||||
MAKE_TYPED_DICTIONARY(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY)
|
||||
MAKE_TYPED_DICTIONARY(PackedColorArray, Variant::PACKED_COLOR_ARRAY)
|
||||
MAKE_TYPED_DICTIONARY(PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY)
|
||||
/*
|
||||
MAKE_TYPED_DICTIONARY(IPAddress, Variant::STRING)
|
||||
*/
|
||||
|
||||
#undef MAKE_TYPED_DICTIONARY
|
||||
#undef MAKE_TYPED_DICTIONARY_NIL
|
||||
#undef MAKE_TYPED_DICTIONARY_EXPANDED
|
||||
#undef MAKE_TYPED_DICTIONARY_WITH_OBJECT
|
||||
|
||||
template <typename K, typename V>
|
||||
struct PtrToArg<TypedDictionary<K, V>> {
|
||||
_FORCE_INLINE_ static TypedDictionary<K, V> convert(const void *p_ptr) {
|
||||
return TypedDictionary<K, V>(*reinterpret_cast<const Dictionary *>(p_ptr));
|
||||
}
|
||||
typedef Dictionary EncodeT;
|
||||
_FORCE_INLINE_ static void encode(TypedDictionary<K, V> p_val, void *p_ptr) {
|
||||
*(Dictionary *)p_ptr = p_val;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename K, typename V>
|
||||
struct PtrToArg<const TypedDictionary<K, V> &> {
|
||||
typedef Dictionary EncodeT;
|
||||
_FORCE_INLINE_ static TypedDictionary<K, V>
|
||||
convert(const void *p_ptr) {
|
||||
return TypedDictionary<K, V>(*reinterpret_cast<const Dictionary *>(p_ptr));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename K, typename V>
|
||||
struct GetTypeInfo<TypedDictionary<K, V>> {
|
||||
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY;
|
||||
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
|
||||
static inline PropertyInfo get_class_info() {
|
||||
return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE, vformat("%s;%s", K::get_class_static(), V::get_class_static()));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename K, typename V>
|
||||
struct GetTypeInfo<const TypedDictionary<K, V> &> {
|
||||
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY;
|
||||
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
|
||||
static inline PropertyInfo get_class_info() {
|
||||
return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE, vformat("%s;%s", K::get_class_static(), V::get_class_static()));
|
||||
}
|
||||
};
|
||||
|
||||
#define MAKE_TYPED_DICTIONARY_INFO_WITH_OBJECT(m_type, m_variant_type) \
|
||||
template <typename T> \
|
||||
struct GetTypeInfo<TypedDictionary<T, m_type>> { \
|
||||
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY; \
|
||||
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
|
||||
static inline PropertyInfo get_class_info() { \
|
||||
return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE, \
|
||||
vformat("%s;%s", T::get_class_static(), m_variant_type == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type).utf8().get_data())); \
|
||||
} \
|
||||
}; \
|
||||
template <typename T> \
|
||||
struct GetTypeInfo<const TypedDictionary<T, m_type> &> { \
|
||||
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY; \
|
||||
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
|
||||
static inline PropertyInfo get_class_info() { \
|
||||
return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE, \
|
||||
vformat("%s;%s", T::get_class_static(), m_variant_type == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type).utf8().get_data())); \
|
||||
} \
|
||||
}; \
|
||||
template <typename T> \
|
||||
struct GetTypeInfo<TypedDictionary<m_type, T>> { \
|
||||
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY; \
|
||||
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
|
||||
static inline PropertyInfo get_class_info() { \
|
||||
return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE, \
|
||||
vformat("%s;%s", m_variant_type == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type).utf8().get_data(), T::get_class_static())); \
|
||||
} \
|
||||
}; \
|
||||
template <typename T> \
|
||||
struct GetTypeInfo<const TypedDictionary<m_type, T> &> { \
|
||||
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY; \
|
||||
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
|
||||
static inline PropertyInfo get_class_info() { \
|
||||
return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE, \
|
||||
vformat("%s;%s", m_variant_type == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type).utf8().get_data(), T::get_class_static())); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type_key, m_variant_type_key, m_type_value, m_variant_type_value) \
|
||||
template <> \
|
||||
struct GetTypeInfo<TypedDictionary<m_type_key, m_type_value>> { \
|
||||
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY; \
|
||||
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
|
||||
static inline PropertyInfo get_class_info() { \
|
||||
return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE, \
|
||||
vformat("%s;%s", m_variant_type_key == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type_key).utf8().get_data(), \
|
||||
m_variant_type_value == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type_value).utf8().get_data())); \
|
||||
} \
|
||||
}; \
|
||||
template <> \
|
||||
struct GetTypeInfo<const TypedDictionary<m_type_key, m_type_value> &> { \
|
||||
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY; \
|
||||
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
|
||||
static inline PropertyInfo get_class_info() { \
|
||||
return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE, \
|
||||
vformat("%s;%s", m_variant_type_key == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type_key).utf8().get_data(), \
|
||||
m_variant_type_value == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type_value).utf8().get_data())); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define MAKE_TYPED_DICTIONARY_INFO_NIL(m_type, m_variant_type) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_WITH_OBJECT(m_type, m_variant_type) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, bool, Variant::BOOL) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, uint8_t, Variant::INT) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, int8_t, Variant::INT) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, uint16_t, Variant::INT) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, int16_t, Variant::INT) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, uint32_t, Variant::INT) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, int32_t, Variant::INT) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, uint64_t, Variant::INT) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, int64_t, Variant::INT) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, float, Variant::FLOAT) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, double, Variant::FLOAT) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, String, Variant::STRING) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Vector2, Variant::VECTOR2) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Vector2i, Variant::VECTOR2I) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Rect2, Variant::RECT2) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Rect2i, Variant::RECT2I) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Vector3, Variant::VECTOR3) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Vector3i, Variant::VECTOR3I) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Transform2D, Variant::TRANSFORM2D) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Plane, Variant::PLANE) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Quaternion, Variant::QUATERNION) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, AABB, Variant::AABB) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Basis, Variant::BASIS) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Transform3D, Variant::TRANSFORM3D) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Color, Variant::COLOR) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, StringName, Variant::STRING_NAME) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, NodePath, Variant::NODE_PATH) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, RID, Variant::RID) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Callable, Variant::CALLABLE) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Signal, Variant::SIGNAL) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Dictionary, Variant::DICTIONARY) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Array, Variant::ARRAY) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedByteArray, Variant::PACKED_BYTE_ARRAY) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedInt32Array, Variant::PACKED_INT32_ARRAY) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedInt64Array, Variant::PACKED_INT64_ARRAY) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedFloat32Array, Variant::PACKED_FLOAT32_ARRAY) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedStringArray, Variant::PACKED_STRING_ARRAY) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedColorArray, Variant::PACKED_COLOR_ARRAY) \
|
||||
/* MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, IPAddress, Variant::STRING) */
|
||||
|
||||
#define MAKE_TYPED_DICTIONARY_INFO(m_type, m_variant_type) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Variant, Variant::NIL) \
|
||||
MAKE_TYPED_DICTIONARY_INFO_NIL(m_type, m_variant_type)
|
||||
|
||||
MAKE_TYPED_DICTIONARY_INFO_NIL(Variant, Variant::NIL)
|
||||
MAKE_TYPED_DICTIONARY_INFO(bool, Variant::BOOL)
|
||||
MAKE_TYPED_DICTIONARY_INFO(uint8_t, Variant::INT)
|
||||
MAKE_TYPED_DICTIONARY_INFO(int8_t, Variant::INT)
|
||||
MAKE_TYPED_DICTIONARY_INFO(uint16_t, Variant::INT)
|
||||
MAKE_TYPED_DICTIONARY_INFO(int16_t, Variant::INT)
|
||||
MAKE_TYPED_DICTIONARY_INFO(uint32_t, Variant::INT)
|
||||
MAKE_TYPED_DICTIONARY_INFO(int32_t, Variant::INT)
|
||||
MAKE_TYPED_DICTIONARY_INFO(uint64_t, Variant::INT)
|
||||
MAKE_TYPED_DICTIONARY_INFO(int64_t, Variant::INT)
|
||||
MAKE_TYPED_DICTIONARY_INFO(float, Variant::FLOAT)
|
||||
MAKE_TYPED_DICTIONARY_INFO(double, Variant::FLOAT)
|
||||
MAKE_TYPED_DICTIONARY_INFO(String, Variant::STRING)
|
||||
MAKE_TYPED_DICTIONARY_INFO(Vector2, Variant::VECTOR2)
|
||||
MAKE_TYPED_DICTIONARY_INFO(Vector2i, Variant::VECTOR2I)
|
||||
MAKE_TYPED_DICTIONARY_INFO(Rect2, Variant::RECT2)
|
||||
MAKE_TYPED_DICTIONARY_INFO(Rect2i, Variant::RECT2I)
|
||||
MAKE_TYPED_DICTIONARY_INFO(Vector3, Variant::VECTOR3)
|
||||
MAKE_TYPED_DICTIONARY_INFO(Vector3i, Variant::VECTOR3I)
|
||||
MAKE_TYPED_DICTIONARY_INFO(Transform2D, Variant::TRANSFORM2D)
|
||||
MAKE_TYPED_DICTIONARY_INFO(Plane, Variant::PLANE)
|
||||
MAKE_TYPED_DICTIONARY_INFO(Quaternion, Variant::QUATERNION)
|
||||
MAKE_TYPED_DICTIONARY_INFO(AABB, Variant::AABB)
|
||||
MAKE_TYPED_DICTIONARY_INFO(Basis, Variant::BASIS)
|
||||
MAKE_TYPED_DICTIONARY_INFO(Transform3D, Variant::TRANSFORM3D)
|
||||
MAKE_TYPED_DICTIONARY_INFO(Color, Variant::COLOR)
|
||||
MAKE_TYPED_DICTIONARY_INFO(StringName, Variant::STRING_NAME)
|
||||
MAKE_TYPED_DICTIONARY_INFO(NodePath, Variant::NODE_PATH)
|
||||
MAKE_TYPED_DICTIONARY_INFO(RID, Variant::RID)
|
||||
MAKE_TYPED_DICTIONARY_INFO(Callable, Variant::CALLABLE)
|
||||
MAKE_TYPED_DICTIONARY_INFO(Signal, Variant::SIGNAL)
|
||||
MAKE_TYPED_DICTIONARY_INFO(Dictionary, Variant::DICTIONARY)
|
||||
MAKE_TYPED_DICTIONARY_INFO(Array, Variant::ARRAY)
|
||||
MAKE_TYPED_DICTIONARY_INFO(PackedByteArray, Variant::PACKED_BYTE_ARRAY)
|
||||
MAKE_TYPED_DICTIONARY_INFO(PackedInt32Array, Variant::PACKED_INT32_ARRAY)
|
||||
MAKE_TYPED_DICTIONARY_INFO(PackedInt64Array, Variant::PACKED_INT64_ARRAY)
|
||||
MAKE_TYPED_DICTIONARY_INFO(PackedFloat32Array, Variant::PACKED_FLOAT32_ARRAY)
|
||||
MAKE_TYPED_DICTIONARY_INFO(PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY)
|
||||
MAKE_TYPED_DICTIONARY_INFO(PackedStringArray, Variant::PACKED_STRING_ARRAY)
|
||||
MAKE_TYPED_DICTIONARY_INFO(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY)
|
||||
MAKE_TYPED_DICTIONARY_INFO(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY)
|
||||
MAKE_TYPED_DICTIONARY_INFO(PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY)
|
||||
MAKE_TYPED_DICTIONARY_INFO(PackedColorArray, Variant::PACKED_COLOR_ARRAY)
|
||||
/*
|
||||
MAKE_TYPED_DICTIONARY_INFO(IPAddress, Variant::STRING)
|
||||
*/
|
||||
|
||||
#undef MAKE_TYPED_DICTIONARY_INFO
|
||||
#undef MAKE_TYPED_DICTIONARY_INFO_NIL
|
||||
#undef MAKE_TYPED_DICTIONARY_INFO_EXPANDED
|
||||
#undef MAKE_TYPED_DICTIONARY_INFO_WITH_OBJECT
|
||||
|
||||
} // namespace godot
|
||||
|
||||
#endif // GODOT_TYPED_DICTIONARY_HPP
|
||||
@@ -49,7 +49,6 @@ class Variant {
|
||||
|
||||
friend class GDExtensionBinding;
|
||||
friend class MethodBind;
|
||||
friend class VariantInternal;
|
||||
|
||||
static void init_bindings();
|
||||
|
||||
@@ -101,7 +100,6 @@ public:
|
||||
PACKED_VECTOR2_ARRAY,
|
||||
PACKED_VECTOR3_ARRAY,
|
||||
PACKED_COLOR_ARRAY,
|
||||
PACKED_VECTOR4_ARRAY,
|
||||
|
||||
VARIANT_MAX
|
||||
};
|
||||
@@ -214,7 +212,6 @@ public:
|
||||
Variant(const PackedVector2Array &v);
|
||||
Variant(const PackedVector3Array &v);
|
||||
Variant(const PackedColorArray &v);
|
||||
Variant(const PackedVector4Array &v);
|
||||
~Variant();
|
||||
|
||||
operator bool() const;
|
||||
@@ -263,9 +260,6 @@ public:
|
||||
operator PackedVector2Array() const;
|
||||
operator PackedVector3Array() const;
|
||||
operator PackedColorArray() const;
|
||||
operator PackedVector4Array() const;
|
||||
|
||||
Object *get_validated_object() const;
|
||||
|
||||
Variant &operator=(const Variant &other);
|
||||
Variant &operator=(Variant &&other);
|
||||
@@ -330,6 +324,8 @@ 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);
|
||||
@@ -358,14 +354,6 @@ String vformat(const String &p_text, const VarArgs... p_args) {
|
||||
return p_text % args_array;
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
@@ -1,509 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* variant_internal.hpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef GODOT_VARIANT_INTERNAL_HPP
|
||||
#define GODOT_VARIANT_INTERNAL_HPP
|
||||
|
||||
#include <gdextension_interface.h>
|
||||
#include <godot_cpp/variant/variant.hpp>
|
||||
|
||||
namespace godot {
|
||||
// For use when you want to access the internal pointer of a Variant directly.
|
||||
// Use with caution. You need to be sure that the type is correct.
|
||||
|
||||
namespace internal {
|
||||
template <typename T>
|
||||
struct VariantInternalType {};
|
||||
|
||||
template <>
|
||||
struct VariantInternalType<bool> {
|
||||
static constexpr Variant::Type type = Variant::BOOL;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<int64_t> {
|
||||
static constexpr Variant::Type type = Variant::INT;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<double> {
|
||||
static constexpr Variant::Type type = Variant::FLOAT;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<String> {
|
||||
static constexpr Variant::Type type = Variant::STRING;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<Vector2> {
|
||||
static constexpr Variant::Type type = Variant::VECTOR2;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<Vector2i> {
|
||||
static constexpr Variant::Type type = Variant::VECTOR2I;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<Rect2> {
|
||||
static constexpr Variant::Type type = Variant::RECT2;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<Rect2i> {
|
||||
static constexpr Variant::Type type = Variant::RECT2I;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<Vector3> {
|
||||
static constexpr Variant::Type type = Variant::VECTOR3;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<Vector3i> {
|
||||
static constexpr Variant::Type type = Variant::VECTOR3I;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<Transform2D> {
|
||||
static constexpr Variant::Type type = Variant::TRANSFORM2D;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<Vector4> {
|
||||
static constexpr Variant::Type type = Variant::VECTOR4;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<Vector4i> {
|
||||
static constexpr Variant::Type type = Variant::VECTOR4I;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<Plane> {
|
||||
static constexpr Variant::Type type = Variant::PLANE;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<Quaternion> {
|
||||
static constexpr Variant::Type type = Variant::QUATERNION;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<AABB> {
|
||||
static constexpr Variant::Type type = Variant::AABB;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<Basis> {
|
||||
static constexpr Variant::Type type = Variant::BASIS;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<Transform3D> {
|
||||
static constexpr Variant::Type type = Variant::TRANSFORM3D;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<Projection> {
|
||||
static constexpr Variant::Type type = Variant::PROJECTION;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<Color> {
|
||||
static constexpr Variant::Type type = Variant::COLOR;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<StringName> {
|
||||
static constexpr Variant::Type type = Variant::STRING_NAME;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<NodePath> {
|
||||
static constexpr Variant::Type type = Variant::NODE_PATH;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<RID> {
|
||||
static constexpr Variant::Type type = Variant::RID;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<Object *> {
|
||||
static constexpr Variant::Type type = Variant::OBJECT;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<Callable> {
|
||||
static constexpr Variant::Type type = Variant::CALLABLE;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<Signal> {
|
||||
static constexpr Variant::Type type = Variant::SIGNAL;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<Dictionary> {
|
||||
static constexpr Variant::Type type = Variant::DICTIONARY;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<Array> {
|
||||
static constexpr Variant::Type type = Variant::ARRAY;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<PackedByteArray> {
|
||||
static constexpr Variant::Type type = Variant::PACKED_BYTE_ARRAY;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<PackedInt32Array> {
|
||||
static constexpr Variant::Type type = Variant::PACKED_INT32_ARRAY;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<PackedInt64Array> {
|
||||
static constexpr Variant::Type type = Variant::PACKED_INT64_ARRAY;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<PackedFloat32Array> {
|
||||
static constexpr Variant::Type type = Variant::PACKED_FLOAT32_ARRAY;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<PackedFloat64Array> {
|
||||
static constexpr Variant::Type type = Variant::PACKED_FLOAT64_ARRAY;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<PackedStringArray> {
|
||||
static constexpr Variant::Type type = Variant::PACKED_STRING_ARRAY;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<PackedVector2Array> {
|
||||
static constexpr Variant::Type type = Variant::PACKED_VECTOR2_ARRAY;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<PackedVector3Array> {
|
||||
static constexpr Variant::Type type = Variant::PACKED_VECTOR3_ARRAY;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<PackedColorArray> {
|
||||
static constexpr Variant::Type type = Variant::PACKED_COLOR_ARRAY;
|
||||
};
|
||||
template <>
|
||||
struct VariantInternalType<PackedVector4Array> {
|
||||
static constexpr Variant::Type type = Variant::PACKED_VECTOR4_ARRAY;
|
||||
};
|
||||
} //namespace internal
|
||||
|
||||
class VariantInternal {
|
||||
friend class Variant;
|
||||
|
||||
static GDExtensionVariantGetInternalPtrFunc get_internal_func[Variant::VARIANT_MAX];
|
||||
|
||||
static void init_bindings();
|
||||
|
||||
public:
|
||||
template <typename T>
|
||||
_FORCE_INLINE_ static T *get_internal_value(Variant *v) {
|
||||
return static_cast<T *>(get_internal_func[internal::VariantInternalType<T>::type](v));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
_FORCE_INLINE_ static const T *get_internal_value(const Variant *v) {
|
||||
return static_cast<const T *>(get_internal_func[internal::VariantInternalType<T>::type](const_cast<Variant *>(v)));
|
||||
}
|
||||
|
||||
// Atomic types.
|
||||
_FORCE_INLINE_ static bool *get_bool(Variant *v) { return get_internal_value<bool>(v); }
|
||||
_FORCE_INLINE_ static const bool *get_bool(const Variant *v) { return get_internal_value<bool>(v); }
|
||||
_FORCE_INLINE_ static int64_t *get_int(Variant *v) { return get_internal_value<int64_t>(v); }
|
||||
_FORCE_INLINE_ static const int64_t *get_int(const Variant *v) { return get_internal_value<int64_t>(v); }
|
||||
_FORCE_INLINE_ static double *get_float(Variant *v) { return get_internal_value<double>(v); }
|
||||
_FORCE_INLINE_ static const double *get_float(const Variant *v) { return get_internal_value<double>(v); }
|
||||
_FORCE_INLINE_ static String *get_string(Variant *v) { return get_internal_value<String>(v); }
|
||||
_FORCE_INLINE_ static const String *get_string(const Variant *v) { return get_internal_value<String>(v); }
|
||||
|
||||
// Math types.
|
||||
_FORCE_INLINE_ static Vector2 *get_vector2(Variant *v) { return get_internal_value<Vector2>(v); }
|
||||
_FORCE_INLINE_ static const Vector2 *get_vector2(const Variant *v) { return get_internal_value<Vector2>(v); }
|
||||
_FORCE_INLINE_ static Vector2i *get_vector2i(Variant *v) { return get_internal_value<Vector2i>(v); }
|
||||
_FORCE_INLINE_ static const Vector2i *get_vector2i(const Variant *v) { return get_internal_value<Vector2i>(v); }
|
||||
_FORCE_INLINE_ static Rect2 *get_rect2(Variant *v) { return get_internal_value<Rect2>(v); }
|
||||
_FORCE_INLINE_ static const Rect2 *get_rect2(const Variant *v) { return get_internal_value<Rect2>(v); }
|
||||
_FORCE_INLINE_ static Rect2i *get_rect2i(Variant *v) { return get_internal_value<Rect2i>(v); }
|
||||
_FORCE_INLINE_ static const Rect2i *get_rect2i(const Variant *v) { return get_internal_value<Rect2i>(v); }
|
||||
_FORCE_INLINE_ static Vector3 *get_vector3(Variant *v) { return get_internal_value<Vector3>(v); }
|
||||
_FORCE_INLINE_ static const Vector3 *get_vector3(const Variant *v) { return get_internal_value<Vector3>(v); }
|
||||
_FORCE_INLINE_ static Vector3i *get_vector3i(Variant *v) { return get_internal_value<Vector3i>(v); }
|
||||
_FORCE_INLINE_ static const Vector3i *get_vector3i(const Variant *v) { return get_internal_value<Vector3i>(v); }
|
||||
_FORCE_INLINE_ static Vector4 *get_vector4(Variant *v) { return get_internal_value<Vector4>(v); }
|
||||
_FORCE_INLINE_ static const Vector4 *get_vector4(const Variant *v) { return get_internal_value<Vector4>(v); }
|
||||
_FORCE_INLINE_ static Vector4i *get_vector4i(Variant *v) { return get_internal_value<Vector4i>(v); }
|
||||
_FORCE_INLINE_ static const Vector4i *get_vector4i(const Variant *v) { return get_internal_value<Vector4i>(v); }
|
||||
_FORCE_INLINE_ static Transform2D *get_transform2d(Variant *v) { return get_internal_value<Transform2D>(v); }
|
||||
_FORCE_INLINE_ static const Transform2D *get_transform2d(const Variant *v) { return get_internal_value<Transform2D>(v); }
|
||||
_FORCE_INLINE_ static Plane *get_plane(Variant *v) { return get_internal_value<Plane>(v); }
|
||||
_FORCE_INLINE_ static const Plane *get_plane(const Variant *v) { return get_internal_value<Plane>(v); }
|
||||
_FORCE_INLINE_ static Quaternion *get_quaternion(Variant *v) { return get_internal_value<Quaternion>(v); }
|
||||
_FORCE_INLINE_ static const Quaternion *get_quaternion(const Variant *v) { return get_internal_value<Quaternion>(v); }
|
||||
_FORCE_INLINE_ static AABB *get_aabb(Variant *v) { return get_internal_value<AABB>(v); }
|
||||
_FORCE_INLINE_ static const AABB *get_aabb(const Variant *v) { return get_internal_value<AABB>(v); }
|
||||
_FORCE_INLINE_ static Basis *get_basis(Variant *v) { return get_internal_value<Basis>(v); }
|
||||
_FORCE_INLINE_ static const Basis *get_basis(const Variant *v) { return get_internal_value<Basis>(v); }
|
||||
_FORCE_INLINE_ static Transform3D *get_transform(Variant *v) { return get_internal_value<Transform3D>(v); }
|
||||
_FORCE_INLINE_ static const Transform3D *get_transform(const Variant *v) { return get_internal_value<Transform3D>(v); }
|
||||
_FORCE_INLINE_ static Projection *get_projection(Variant *v) { return get_internal_value<Projection>(v); }
|
||||
_FORCE_INLINE_ static const Projection *get_projection(const Variant *v) { return get_internal_value<Projection>(v); }
|
||||
|
||||
// Misc types.
|
||||
_FORCE_INLINE_ static Color *get_color(Variant *v) { return get_internal_value<Color>(v); }
|
||||
_FORCE_INLINE_ static const Color *get_color(const Variant *v) { return get_internal_value<Color>(v); }
|
||||
_FORCE_INLINE_ static StringName *get_string_name(Variant *v) { return get_internal_value<StringName>(v); }
|
||||
_FORCE_INLINE_ static const StringName *get_string_name(const Variant *v) { return get_internal_value<StringName>(v); }
|
||||
_FORCE_INLINE_ static NodePath *get_node_path(Variant *v) { return get_internal_value<NodePath>(v); }
|
||||
_FORCE_INLINE_ static const NodePath *get_node_path(const Variant *v) { return get_internal_value<NodePath>(v); }
|
||||
_FORCE_INLINE_ static RID *get_rid(Variant *v) { return get_internal_value<RID>(v); }
|
||||
_FORCE_INLINE_ static const RID *get_rid(const Variant *v) { return get_internal_value<RID>(v); }
|
||||
_FORCE_INLINE_ static Callable *get_callable(Variant *v) { return get_internal_value<Callable>(v); }
|
||||
_FORCE_INLINE_ static const Callable *get_callable(const Variant *v) { return get_internal_value<Callable>(v); }
|
||||
_FORCE_INLINE_ static Signal *get_signal(Variant *v) { return get_internal_value<Signal>(v); }
|
||||
_FORCE_INLINE_ static const Signal *get_signal(const Variant *v) { return get_internal_value<Signal>(v); }
|
||||
_FORCE_INLINE_ static Dictionary *get_dictionary(Variant *v) { return get_internal_value<Dictionary>(v); }
|
||||
_FORCE_INLINE_ static const Dictionary *get_dictionary(const Variant *v) { return get_internal_value<Dictionary>(v); }
|
||||
_FORCE_INLINE_ static Array *get_array(Variant *v) { return get_internal_value<Array>(v); }
|
||||
_FORCE_INLINE_ static const Array *get_array(const Variant *v) { return get_internal_value<Array>(v); }
|
||||
|
||||
// Typed arrays.
|
||||
_FORCE_INLINE_ static PackedByteArray *get_byte_array(Variant *v) { return get_internal_value<PackedByteArray>(v); }
|
||||
_FORCE_INLINE_ static const PackedByteArray *get_byte_array(const Variant *v) { return get_internal_value<PackedByteArray>(v); }
|
||||
_FORCE_INLINE_ static PackedInt32Array *get_int32_array(Variant *v) { return get_internal_value<PackedInt32Array>(v); }
|
||||
_FORCE_INLINE_ static const PackedInt32Array *get_int32_array(const Variant *v) { return get_internal_value<PackedInt32Array>(v); }
|
||||
_FORCE_INLINE_ static PackedInt64Array *get_int64_array(Variant *v) { return get_internal_value<PackedInt64Array>(v); }
|
||||
_FORCE_INLINE_ static const PackedInt64Array *get_int64_array(const Variant *v) { return get_internal_value<PackedInt64Array>(v); }
|
||||
_FORCE_INLINE_ static PackedFloat32Array *get_float32_array(Variant *v) { return get_internal_value<PackedFloat32Array>(v); }
|
||||
_FORCE_INLINE_ static const PackedFloat32Array *get_float32_array(const Variant *v) { return get_internal_value<PackedFloat32Array>(v); }
|
||||
_FORCE_INLINE_ static PackedFloat64Array *get_float64_array(Variant *v) { return get_internal_value<PackedFloat64Array>(v); }
|
||||
_FORCE_INLINE_ static const PackedFloat64Array *get_float64_array(const Variant *v) { return get_internal_value<PackedFloat64Array>(v); }
|
||||
_FORCE_INLINE_ static PackedStringArray *get_string_array(Variant *v) { return get_internal_value<PackedStringArray>(v); }
|
||||
_FORCE_INLINE_ static const PackedStringArray *get_string_array(const Variant *v) { return get_internal_value<PackedStringArray>(v); }
|
||||
_FORCE_INLINE_ static PackedVector2Array *get_vector2_array(Variant *v) { return get_internal_value<PackedVector2Array>(v); }
|
||||
_FORCE_INLINE_ static const PackedVector2Array *get_vector2_array(const Variant *v) { return get_internal_value<PackedVector2Array>(v); }
|
||||
_FORCE_INLINE_ static PackedVector3Array *get_vector3_array(Variant *v) { return get_internal_value<PackedVector3Array>(v); }
|
||||
_FORCE_INLINE_ static const PackedVector3Array *get_vector3_array(const Variant *v) { return get_internal_value<PackedVector3Array>(v); }
|
||||
_FORCE_INLINE_ static PackedColorArray *get_color_array(Variant *v) { return get_internal_value<PackedColorArray>(v); }
|
||||
_FORCE_INLINE_ static const PackedColorArray *get_color_array(const Variant *v) { return get_internal_value<PackedColorArray>(v); }
|
||||
_FORCE_INLINE_ static PackedVector4Array *get_vector4_array(Variant *v) { return get_internal_value<PackedVector4Array>(v); }
|
||||
_FORCE_INLINE_ static const PackedVector4Array *get_vector4_array(const Variant *v) { return get_internal_value<PackedVector4Array>(v); }
|
||||
|
||||
_FORCE_INLINE_ static Object **get_object(Variant *v) { return get_internal_value<Object *>(v); }
|
||||
_FORCE_INLINE_ static const Object **get_object(const Variant *v) { return (const Object **)get_internal_value<Object *>(v); }
|
||||
|
||||
_FORCE_INLINE_ static void *get_opaque_pointer(Variant *v) {
|
||||
switch (v->get_type()) {
|
||||
case Variant::NIL:
|
||||
return nullptr;
|
||||
case Variant::BOOL:
|
||||
return get_bool(v);
|
||||
case Variant::INT:
|
||||
return get_int(v);
|
||||
case Variant::FLOAT:
|
||||
return get_float(v);
|
||||
case Variant::STRING:
|
||||
return get_string(v);
|
||||
case Variant::VECTOR2:
|
||||
return get_vector2(v);
|
||||
case Variant::VECTOR2I:
|
||||
return get_vector2i(v);
|
||||
case Variant::VECTOR3:
|
||||
return get_vector3(v);
|
||||
case Variant::VECTOR3I:
|
||||
return get_vector3i(v);
|
||||
case Variant::VECTOR4:
|
||||
return get_vector4(v);
|
||||
case Variant::VECTOR4I:
|
||||
return get_vector4i(v);
|
||||
case Variant::RECT2:
|
||||
return get_rect2(v);
|
||||
case Variant::RECT2I:
|
||||
return get_rect2i(v);
|
||||
case Variant::TRANSFORM3D:
|
||||
return get_transform(v);
|
||||
case Variant::PROJECTION:
|
||||
return get_projection(v);
|
||||
case Variant::TRANSFORM2D:
|
||||
return get_transform2d(v);
|
||||
case Variant::QUATERNION:
|
||||
return get_quaternion(v);
|
||||
case Variant::PLANE:
|
||||
return get_plane(v);
|
||||
case Variant::BASIS:
|
||||
return get_basis(v);
|
||||
case Variant::AABB:
|
||||
return get_aabb(v);
|
||||
case Variant::COLOR:
|
||||
return get_color(v);
|
||||
case Variant::STRING_NAME:
|
||||
return get_string_name(v);
|
||||
case Variant::NODE_PATH:
|
||||
return get_node_path(v);
|
||||
case Variant::RID:
|
||||
return get_rid(v);
|
||||
case Variant::CALLABLE:
|
||||
return get_callable(v);
|
||||
case Variant::SIGNAL:
|
||||
return get_signal(v);
|
||||
case Variant::DICTIONARY:
|
||||
return get_dictionary(v);
|
||||
case Variant::ARRAY:
|
||||
return get_array(v);
|
||||
case Variant::PACKED_BYTE_ARRAY:
|
||||
return get_byte_array(v);
|
||||
case Variant::PACKED_INT32_ARRAY:
|
||||
return get_int32_array(v);
|
||||
case Variant::PACKED_INT64_ARRAY:
|
||||
return get_int64_array(v);
|
||||
case Variant::PACKED_FLOAT32_ARRAY:
|
||||
return get_float32_array(v);
|
||||
case Variant::PACKED_FLOAT64_ARRAY:
|
||||
return get_float64_array(v);
|
||||
case Variant::PACKED_STRING_ARRAY:
|
||||
return get_string_array(v);
|
||||
case Variant::PACKED_VECTOR2_ARRAY:
|
||||
return get_vector2_array(v);
|
||||
case Variant::PACKED_VECTOR3_ARRAY:
|
||||
return get_vector3_array(v);
|
||||
case Variant::PACKED_COLOR_ARRAY:
|
||||
return get_color_array(v);
|
||||
case Variant::PACKED_VECTOR4_ARRAY:
|
||||
return get_vector4_array(v);
|
||||
case Variant::OBJECT:
|
||||
return get_object(v);
|
||||
case Variant::VARIANT_MAX:
|
||||
ERR_FAIL_V(nullptr);
|
||||
}
|
||||
ERR_FAIL_V(nullptr);
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ static const void *get_opaque_pointer(const Variant *v) {
|
||||
switch (v->get_type()) {
|
||||
case Variant::NIL:
|
||||
return nullptr;
|
||||
case Variant::BOOL:
|
||||
return get_bool(v);
|
||||
case Variant::INT:
|
||||
return get_int(v);
|
||||
case Variant::FLOAT:
|
||||
return get_float(v);
|
||||
case Variant::STRING:
|
||||
return get_string(v);
|
||||
case Variant::VECTOR2:
|
||||
return get_vector2(v);
|
||||
case Variant::VECTOR2I:
|
||||
return get_vector2i(v);
|
||||
case Variant::VECTOR3:
|
||||
return get_vector3(v);
|
||||
case Variant::VECTOR3I:
|
||||
return get_vector3i(v);
|
||||
case Variant::VECTOR4:
|
||||
return get_vector4(v);
|
||||
case Variant::VECTOR4I:
|
||||
return get_vector4i(v);
|
||||
case Variant::RECT2:
|
||||
return get_rect2(v);
|
||||
case Variant::RECT2I:
|
||||
return get_rect2i(v);
|
||||
case Variant::TRANSFORM3D:
|
||||
return get_transform(v);
|
||||
case Variant::PROJECTION:
|
||||
return get_projection(v);
|
||||
case Variant::TRANSFORM2D:
|
||||
return get_transform2d(v);
|
||||
case Variant::QUATERNION:
|
||||
return get_quaternion(v);
|
||||
case Variant::PLANE:
|
||||
return get_plane(v);
|
||||
case Variant::BASIS:
|
||||
return get_basis(v);
|
||||
case Variant::AABB:
|
||||
return get_aabb(v);
|
||||
case Variant::COLOR:
|
||||
return get_color(v);
|
||||
case Variant::STRING_NAME:
|
||||
return get_string_name(v);
|
||||
case Variant::NODE_PATH:
|
||||
return get_node_path(v);
|
||||
case Variant::RID:
|
||||
return get_rid(v);
|
||||
case Variant::CALLABLE:
|
||||
return get_callable(v);
|
||||
case Variant::SIGNAL:
|
||||
return get_signal(v);
|
||||
case Variant::DICTIONARY:
|
||||
return get_dictionary(v);
|
||||
case Variant::ARRAY:
|
||||
return get_array(v);
|
||||
case Variant::PACKED_BYTE_ARRAY:
|
||||
return get_byte_array(v);
|
||||
case Variant::PACKED_INT32_ARRAY:
|
||||
return get_int32_array(v);
|
||||
case Variant::PACKED_INT64_ARRAY:
|
||||
return get_int64_array(v);
|
||||
case Variant::PACKED_FLOAT32_ARRAY:
|
||||
return get_float32_array(v);
|
||||
case Variant::PACKED_FLOAT64_ARRAY:
|
||||
return get_float64_array(v);
|
||||
case Variant::PACKED_STRING_ARRAY:
|
||||
return get_string_array(v);
|
||||
case Variant::PACKED_VECTOR2_ARRAY:
|
||||
return get_vector2_array(v);
|
||||
case Variant::PACKED_VECTOR3_ARRAY:
|
||||
return get_vector3_array(v);
|
||||
case Variant::PACKED_COLOR_ARRAY:
|
||||
return get_color_array(v);
|
||||
case Variant::PACKED_VECTOR4_ARRAY:
|
||||
return get_vector4_array(v);
|
||||
case Variant::OBJECT:
|
||||
return get_object(v);
|
||||
case Variant::VARIANT_MAX:
|
||||
ERR_FAIL_V(nullptr);
|
||||
}
|
||||
ERR_FAIL_V(nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct VariantGetInternalPtr {
|
||||
static internal::VariantInternalType<T> *get_ptr(Variant *v) { return VariantInternal::get_internal_value<T>(v); }
|
||||
static const internal::VariantInternalType<T> *get_ptr(const Variant *v) { return VariantInternal::get_internal_value<T>(v); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct can_set_variant_internal_value {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct can_set_variant_internal_value<Object *> {
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct VariantInternalAccessor {
|
||||
static _FORCE_INLINE_ const T &get(const Variant *v) { return *VariantInternal::get_internal_value<T>(v); }
|
||||
|
||||
// Enable set() only for those types where we can set (all but Object *).
|
||||
template <typename U = T, typename = std::enable_if_t<can_set_variant_internal_value<U>::value>>
|
||||
static _FORCE_INLINE_ void set(Variant *v, const internal::VariantInternalType<U> &p_value) {
|
||||
*VariantInternal::get_internal_value<U>(v) = p_value;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, std::enable_if_t<can_set_variant_internal_value<T>::value>>
|
||||
struct VariantDefaultInitializer {
|
||||
static _FORCE_INLINE_ void init(Variant *v) { *VariantInternal::get_internal_value<T>(v) = T(); }
|
||||
};
|
||||
|
||||
} // namespace godot
|
||||
|
||||
#endif // GODOT_VARIANT_INTERNAL_HPP
|
||||
@@ -39,7 +39,7 @@ namespace godot {
|
||||
class String;
|
||||
struct Vector2i;
|
||||
|
||||
struct [[nodiscard]] Vector2 {
|
||||
struct _NO_DISCARD_ Vector2 {
|
||||
static const int AXIS_COUNT = 2;
|
||||
|
||||
enum Axis {
|
||||
@@ -91,18 +91,10 @@ struct [[nodiscard]] Vector2 {
|
||||
return Vector2(MIN(x, p_vector2.x), MIN(y, p_vector2.y));
|
||||
}
|
||||
|
||||
Vector2 minf(real_t p_scalar) const {
|
||||
return Vector2(MIN(x, p_scalar), MIN(y, p_scalar));
|
||||
}
|
||||
|
||||
Vector2 max(const Vector2 &p_vector2) const {
|
||||
return Vector2(MAX(x, p_vector2.x), MAX(y, p_vector2.y));
|
||||
}
|
||||
|
||||
Vector2 maxf(real_t p_scalar) const {
|
||||
return Vector2(MAX(x, p_scalar), MAX(y, p_scalar));
|
||||
}
|
||||
|
||||
real_t distance_to(const Vector2 &p_vector2) const;
|
||||
real_t distance_squared_to(const Vector2 &p_vector2) const;
|
||||
real_t angle_to(const Vector2 &p_vector2) const;
|
||||
@@ -131,7 +123,6 @@ struct [[nodiscard]] 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);
|
||||
@@ -177,9 +168,7 @@ struct [[nodiscard]] Vector2 {
|
||||
Vector2 ceil() const;
|
||||
Vector2 round() const;
|
||||
Vector2 snapped(const Vector2 &p_by) const;
|
||||
Vector2 snappedf(real_t p_by) const;
|
||||
Vector2 clamp(const Vector2 &p_min, const Vector2 &p_max) const;
|
||||
Vector2 clampf(real_t p_min, real_t p_max) const;
|
||||
real_t aspect() const { return width / height; }
|
||||
|
||||
operator String() const;
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace godot {
|
||||
class String;
|
||||
struct Vector2;
|
||||
|
||||
struct [[nodiscard]] Vector2i {
|
||||
struct _NO_DISCARD_ Vector2i {
|
||||
static const int AXIS_COUNT = 2;
|
||||
|
||||
enum Axis {
|
||||
@@ -83,18 +83,10 @@ struct [[nodiscard]] Vector2i {
|
||||
return Vector2i(MIN(x, p_vector2i.x), MIN(y, p_vector2i.y));
|
||||
}
|
||||
|
||||
Vector2i mini(int32_t p_scalar) const {
|
||||
return Vector2i(MIN(x, p_scalar), MIN(y, p_scalar));
|
||||
}
|
||||
|
||||
Vector2i max(const Vector2i &p_vector2i) const {
|
||||
return Vector2i(MAX(x, p_vector2i.x), MAX(y, p_vector2i.y));
|
||||
}
|
||||
|
||||
Vector2i maxi(int32_t p_scalar) const {
|
||||
return Vector2i(MAX(x, p_scalar), MAX(y, p_scalar));
|
||||
}
|
||||
|
||||
Vector2i operator+(const Vector2i &p_v) const;
|
||||
void operator+=(const Vector2i &p_v);
|
||||
Vector2i operator-(const Vector2i &p_v) const;
|
||||
@@ -125,16 +117,10 @@ struct [[nodiscard]] Vector2i {
|
||||
int64_t length_squared() const;
|
||||
double length() const;
|
||||
|
||||
int64_t distance_squared_to(const Vector2i &p_to) const;
|
||||
double distance_to(const Vector2i &p_to) const;
|
||||
|
||||
real_t aspect() const { return width / (real_t)height; }
|
||||
Vector2i sign() const { return Vector2i(SIGN(x), SIGN(y)); }
|
||||
Vector2i abs() const { return Vector2i(Math::abs(x), Math::abs(y)); }
|
||||
Vector2i snapped(const Vector2i &p_step) const;
|
||||
Vector2i snappedi(int32_t p_step) const;
|
||||
Vector2i clamp(const Vector2i &p_min, const Vector2i &p_max) const;
|
||||
Vector2i clampi(int32_t p_min, int32_t p_max) const;
|
||||
|
||||
operator String() const;
|
||||
operator Vector2() const;
|
||||
|
||||
@@ -41,7 +41,7 @@ struct Basis;
|
||||
struct Vector2;
|
||||
struct Vector3i;
|
||||
|
||||
struct [[nodiscard]] Vector3 {
|
||||
struct _NO_DISCARD_ Vector3 {
|
||||
static const int AXIS_COUNT = 3;
|
||||
|
||||
enum Axis {
|
||||
@@ -82,18 +82,10 @@ struct [[nodiscard]] Vector3 {
|
||||
return Vector3(MIN(x, p_vector3.x), MIN(y, p_vector3.y), MIN(z, p_vector3.z));
|
||||
}
|
||||
|
||||
Vector3 minf(real_t p_scalar) const {
|
||||
return Vector3(MIN(x, p_scalar), MIN(y, p_scalar), MIN(z, p_scalar));
|
||||
}
|
||||
|
||||
Vector3 max(const Vector3 &p_vector3) const {
|
||||
return Vector3(MAX(x, p_vector3.x), MAX(y, p_vector3.y), MAX(z, p_vector3.z));
|
||||
}
|
||||
|
||||
Vector3 maxf(real_t p_scalar) const {
|
||||
return Vector3(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar));
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ real_t length() const;
|
||||
_FORCE_INLINE_ real_t length_squared() const;
|
||||
|
||||
@@ -106,9 +98,7 @@ struct [[nodiscard]] Vector3 {
|
||||
_FORCE_INLINE_ void zero();
|
||||
|
||||
void snap(const Vector3 p_val);
|
||||
void snapf(real_t p_val);
|
||||
Vector3 snapped(const Vector3 p_val) const;
|
||||
Vector3 snappedf(real_t p_val) const;
|
||||
|
||||
void rotate(const Vector3 &p_axis, const real_t p_angle);
|
||||
Vector3 rotated(const Vector3 &p_axis, const real_t p_angle) const;
|
||||
@@ -138,7 +128,6 @@ struct [[nodiscard]] Vector3 {
|
||||
_FORCE_INLINE_ Vector3 ceil() const;
|
||||
_FORCE_INLINE_ Vector3 round() const;
|
||||
Vector3 clamp(const Vector3 &p_min, const Vector3 &p_max) const;
|
||||
Vector3 clampf(real_t p_min, real_t p_max) const;
|
||||
|
||||
_FORCE_INLINE_ real_t distance_to(const Vector3 &p_to) const;
|
||||
_FORCE_INLINE_ real_t distance_squared_to(const Vector3 &p_to) const;
|
||||
@@ -157,7 +146,6 @@ struct [[nodiscard]] Vector3 {
|
||||
|
||||
bool is_equal_approx(const Vector3 &p_v) const;
|
||||
bool is_zero_approx() const;
|
||||
bool is_finite() const;
|
||||
|
||||
/* Operators */
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace godot {
|
||||
class String;
|
||||
struct Vector3;
|
||||
|
||||
struct [[nodiscard]] Vector3i {
|
||||
struct _NO_DISCARD_ Vector3i {
|
||||
static const int AXIS_COUNT = 3;
|
||||
|
||||
enum Axis {
|
||||
@@ -75,32 +75,18 @@ struct [[nodiscard]] Vector3i {
|
||||
return Vector3i(MIN(x, p_vector3i.x), MIN(y, p_vector3i.y), MIN(z, p_vector3i.z));
|
||||
}
|
||||
|
||||
Vector3i mini(int32_t p_scalar) const {
|
||||
return Vector3i(MIN(x, p_scalar), MIN(y, p_scalar), MIN(z, p_scalar));
|
||||
}
|
||||
|
||||
Vector3i max(const Vector3i &p_vector3i) const {
|
||||
return Vector3i(MAX(x, p_vector3i.x), MAX(y, p_vector3i.y), MAX(z, p_vector3i.z));
|
||||
}
|
||||
|
||||
Vector3i maxi(int32_t p_scalar) const {
|
||||
return Vector3i(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar));
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ int64_t length_squared() const;
|
||||
_FORCE_INLINE_ double length() const;
|
||||
|
||||
_FORCE_INLINE_ int64_t distance_squared_to(const Vector3i &p_to) const;
|
||||
_FORCE_INLINE_ double distance_to(const Vector3i &p_to) const;
|
||||
|
||||
_FORCE_INLINE_ void zero();
|
||||
|
||||
_FORCE_INLINE_ Vector3i abs() const;
|
||||
_FORCE_INLINE_ Vector3i sign() const;
|
||||
Vector3i snapped(const Vector3i &p_step) const;
|
||||
Vector3i snappedi(int32_t p_step) const;
|
||||
Vector3i clamp(const Vector3i &p_min, const Vector3i &p_max) const;
|
||||
Vector3i clampi(int32_t p_min, int32_t p_max) const;
|
||||
|
||||
/* Operators */
|
||||
|
||||
@@ -150,14 +136,6 @@ double Vector3i::length() const {
|
||||
return Math::sqrt((double)length_squared());
|
||||
}
|
||||
|
||||
int64_t Vector3i::distance_squared_to(const Vector3i &p_to) const {
|
||||
return (p_to - *this).length_squared();
|
||||
}
|
||||
|
||||
double Vector3i::distance_to(const Vector3i &p_to) const {
|
||||
return (p_to - *this).length();
|
||||
}
|
||||
|
||||
Vector3i Vector3i::abs() const {
|
||||
return Vector3i(Math::abs(x), Math::abs(y), Math::abs(z));
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace godot {
|
||||
|
||||
class String;
|
||||
|
||||
struct [[nodiscard]] Vector4 {
|
||||
struct _NO_DISCARD_ Vector4 {
|
||||
static const int AXIS_COUNT = 4;
|
||||
|
||||
enum Axis {
|
||||
@@ -55,17 +55,16 @@ struct [[nodiscard]] Vector4 {
|
||||
real_t z;
|
||||
real_t w;
|
||||
};
|
||||
[[deprecated("Use coord instead")]] real_t components[4];
|
||||
real_t coord[4] = { 0, 0, 0, 0 };
|
||||
real_t components[4] = { 0, 0, 0, 0 };
|
||||
};
|
||||
|
||||
_FORCE_INLINE_ real_t &operator[](const int p_axis) {
|
||||
DEV_ASSERT((unsigned int)p_axis < 4);
|
||||
return coord[p_axis];
|
||||
return components[p_axis];
|
||||
}
|
||||
_FORCE_INLINE_ const real_t &operator[](const int p_axis) const {
|
||||
DEV_ASSERT((unsigned int)p_axis < 4);
|
||||
return coord[p_axis];
|
||||
return components[p_axis];
|
||||
}
|
||||
|
||||
Vector4::Axis min_axis_index() const;
|
||||
@@ -75,22 +74,13 @@ struct [[nodiscard]] Vector4 {
|
||||
return Vector4(MIN(x, p_vector4.x), MIN(y, p_vector4.y), MIN(z, p_vector4.z), MIN(w, p_vector4.w));
|
||||
}
|
||||
|
||||
Vector4 minf(real_t p_scalar) const {
|
||||
return Vector4(MIN(x, p_scalar), MIN(y, p_scalar), MIN(z, p_scalar), MIN(w, p_scalar));
|
||||
}
|
||||
|
||||
Vector4 max(const Vector4 &p_vector4) const {
|
||||
return Vector4(MAX(x, p_vector4.x), MAX(y, p_vector4.y), MAX(z, p_vector4.z), MAX(w, p_vector4.w));
|
||||
}
|
||||
|
||||
Vector4 maxf(real_t p_scalar) const {
|
||||
return Vector4(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar), MAX(w, p_scalar));
|
||||
}
|
||||
|
||||
_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;
|
||||
@@ -112,11 +102,8 @@ struct [[nodiscard]] Vector4 {
|
||||
Vector4 posmod(const real_t p_mod) const;
|
||||
Vector4 posmodv(const Vector4 &p_modv) const;
|
||||
void snap(const Vector4 &p_step);
|
||||
void snapf(real_t p_step);
|
||||
Vector4 snapped(const Vector4 &p_step) const;
|
||||
Vector4 snappedf(real_t p_step) const;
|
||||
Vector4 clamp(const Vector4 &p_min, const Vector4 &p_max) const;
|
||||
Vector4 clampf(real_t p_min, real_t p_max) const;
|
||||
|
||||
Vector4 inverse() const;
|
||||
_FORCE_INLINE_ real_t dot(const Vector4 &p_vec4) const;
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace godot {
|
||||
class String;
|
||||
struct Vector4;
|
||||
|
||||
struct [[nodiscard]] Vector4i {
|
||||
struct _NO_DISCARD_ Vector4i {
|
||||
static const int AXIS_COUNT = 4;
|
||||
|
||||
enum Axis {
|
||||
@@ -77,32 +77,18 @@ struct [[nodiscard]] Vector4i {
|
||||
return Vector4i(MIN(x, p_vector4i.x), MIN(y, p_vector4i.y), MIN(z, p_vector4i.z), MIN(w, p_vector4i.w));
|
||||
}
|
||||
|
||||
Vector4i mini(int32_t p_scalar) const {
|
||||
return Vector4i(MIN(x, p_scalar), MIN(y, p_scalar), MIN(z, p_scalar), MIN(w, p_scalar));
|
||||
}
|
||||
|
||||
Vector4i max(const Vector4i &p_vector4i) const {
|
||||
return Vector4i(MAX(x, p_vector4i.x), MAX(y, p_vector4i.y), MAX(z, p_vector4i.z), MAX(w, p_vector4i.w));
|
||||
}
|
||||
|
||||
Vector4i maxi(int32_t p_scalar) const {
|
||||
return Vector4i(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar), MAX(w, p_scalar));
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ int64_t length_squared() const;
|
||||
_FORCE_INLINE_ double length() const;
|
||||
|
||||
_FORCE_INLINE_ int64_t distance_squared_to(const Vector4i &p_to) const;
|
||||
_FORCE_INLINE_ double distance_to(const Vector4i &p_to) const;
|
||||
|
||||
_FORCE_INLINE_ void zero();
|
||||
|
||||
_FORCE_INLINE_ Vector4i abs() const;
|
||||
_FORCE_INLINE_ Vector4i sign() const;
|
||||
Vector4i snapped(const Vector4i &p_step) const;
|
||||
Vector4i snappedi(int32_t p_step) const;
|
||||
Vector4i clamp(const Vector4i &p_min, const Vector4i &p_max) const;
|
||||
Vector4i clampi(int32_t p_min, int32_t p_max) const;
|
||||
|
||||
/* Operators */
|
||||
|
||||
@@ -154,14 +140,6 @@ double Vector4i::length() const {
|
||||
return Math::sqrt((double)length_squared());
|
||||
}
|
||||
|
||||
int64_t Vector4i::distance_squared_to(const Vector4i &p_to) const {
|
||||
return (p_to - *this).length_squared();
|
||||
}
|
||||
|
||||
double Vector4i::distance_to(const Vector4i &p_to) const {
|
||||
return (p_to - *this).length();
|
||||
}
|
||||
|
||||
Vector4i Vector4i::abs() const {
|
||||
return Vector4i(Math::abs(x), Math::abs(y), Math::abs(z), Math::abs(w));
|
||||
}
|
||||
|
||||
37
misc/hooks/README.md
Normal file
37
misc/hooks/README.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# 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`
|
||||
48
misc/hooks/canonicalize_filename.sh
Executable file
48
misc/hooks/canonicalize_filename.sh
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/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"
|
||||
}
|
||||
50
misc/hooks/pre-commit
Executable file
50
misc/hooks/pre-commit
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/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
|
||||
202
misc/hooks/pre-commit-black
Executable file
202
misc/hooks/pre-commit-black
Executable file
@@ -0,0 +1,202 @@
|
||||
#!/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
|
||||
242
misc/hooks/pre-commit-clang-format
Executable file
242
misc/hooks/pre-commit-clang-format
Executable file
@@ -0,0 +1,242 @@
|
||||
#!/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
|
||||
103
misc/hooks/winmessage.ps1
Normal file
103
misc/hooks/winmessage.ps1
Normal file
@@ -0,0 +1,103 @@
|
||||
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)
|
||||
25
misc/scripts/black_format.sh
Executable file
25
misc/scripts/black_format.sh
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/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]
|
||||
|
||||
with open(fname.strip(), "r", encoding="utf-8") as fileread:
|
||||
file_contents = fileread.read()
|
||||
fileread = open(fname.strip(), "r")
|
||||
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,8 +25,6 @@ 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,46 +1,31 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import sys
|
||||
import os, sys
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(1, os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
|
||||
from binding_generator import _generate_bindings, _get_file_list
|
||||
from build_profile import generate_trimmed_api
|
||||
from binding_generator import get_file_list, generate_bindings
|
||||
|
||||
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)
|
||||
|
||||
def test(profile_filepath=""):
|
||||
api = generate_trimmed_api(api_filepath, profile_filepath)
|
||||
_generate_bindings(
|
||||
api,
|
||||
api_filepath,
|
||||
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")
|
||||
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!")
|
||||
|
||||
38
misc/scripts/clang_format.sh
Executable file
38
misc/scripts/clang_format.sh
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/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
|
||||
5
misc/scripts/codespell.sh
Normal file
5
misc/scripts/codespell.sh
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/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,7 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
header = """\
|
||||
@@ -36,61 +35,61 @@ header = """\
|
||||
/**************************************************************************/
|
||||
"""
|
||||
|
||||
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)
|
||||
fname = sys.argv[1]
|
||||
|
||||
for f in sys.argv[1:]:
|
||||
fname = f
|
||||
# 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"
|
||||
|
||||
# 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"
|
||||
# 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).
|
||||
|
||||
# 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).
|
||||
fileread = open(fname.strip(), "r")
|
||||
line = fileread.readline()
|
||||
header_done = False
|
||||
|
||||
with open(fname.strip(), "r", encoding="utf-8") as fileread:
|
||||
line = fileread.readline()
|
||||
header_done = False
|
||||
while line.strip() == "": # Skip empty lines at the top
|
||||
line = fileread.readline()
|
||||
|
||||
while line.strip() == "" and line != "": # Skip empty lines at the top
|
||||
line = fileread.readline()
|
||||
if line.find("/**********") == -1: # Godot header starts this way
|
||||
# Maybe starting with a non-Godot comment, abort header magic
|
||||
header_done = True
|
||||
|
||||
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
|
||||
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()
|
||||
line = fileread.readline()
|
||||
|
||||
# Write
|
||||
with open(fname.strip(), "w", encoding="utf-8", newline="\n") as filewrite:
|
||||
filewrite.write(text)
|
||||
while line != "": # Dump everything until EOF
|
||||
text += line
|
||||
line = fileread.readline()
|
||||
|
||||
fileread.close()
|
||||
|
||||
# Write
|
||||
filewrite = open(fname.strip(), "w")
|
||||
filewrite.write(text)
|
||||
filewrite.close()
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
#!/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)
|
||||
41
misc/scripts/file_format.sh
Executable file
41
misc/scripts/file_format.sh
Executable file
@@ -0,0 +1,41 @@
|
||||
#!/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
|
||||
@@ -1,127 +0,0 @@
|
||||
#!/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)
|
||||
60
misc/scripts/header_guards.sh
Executable file
60
misc/scripts/header_guards.sh
Executable file
@@ -0,0 +1,60 @@
|
||||
#!/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
|
||||
11
misc/scripts/mypy.ini
Normal file
11
misc/scripts/mypy.ini
Normal file
@@ -0,0 +1,11 @@
|
||||
[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
|
||||
6
misc/scripts/mypy_check.sh
Executable file
6
misc/scripts/mypy_check.sh
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
echo -e "Python: mypy static analysis..."
|
||||
mypy --config-file=./misc/scripts/mypy.ini .
|
||||
@@ -1,58 +0,0 @@
|
||||
[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
|
||||
"""
|
||||
@@ -29,7 +29,6 @@
|
||||
/**************************************************************************/
|
||||
|
||||
#include <godot_cpp/classes/file_access.hpp>
|
||||
#include <godot_cpp/classes/image.hpp>
|
||||
#include <godot_cpp/classes/worker_thread_pool.hpp>
|
||||
#include <godot_cpp/classes/xml_parser.hpp>
|
||||
|
||||
@@ -56,12 +55,4 @@ WorkerThreadPool::GroupID WorkerThreadPool::add_native_group_task(void (*p_func)
|
||||
return (GroupID)internal::gdextension_interface_worker_thread_pool_add_native_group_task(_owner, p_func, p_userdata, p_elements, p_tasks, p_high_priority, (GDExtensionConstStringPtr)&p_description);
|
||||
}
|
||||
|
||||
uint8_t *Image::ptrw() {
|
||||
return internal::gdextension_interface_image_ptrw(_owner);
|
||||
}
|
||||
|
||||
const uint8_t *Image::ptr() {
|
||||
return internal::gdextension_interface_image_ptr(_owner);
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
|
||||
@@ -40,54 +40,26 @@
|
||||
|
||||
namespace godot {
|
||||
|
||||
#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
|
||||
std::recursive_mutex Wrapped::_constructing_mutex;
|
||||
#endif
|
||||
|
||||
_GODOT_CPP_THREAD_LOCAL const StringName *Wrapped::_constructing_extension_class_name = nullptr;
|
||||
_GODOT_CPP_THREAD_LOCAL const GDExtensionInstanceBindingCallbacks *Wrapped::_constructing_class_binding_callbacks = nullptr;
|
||||
|
||||
#ifdef HOT_RELOAD_ENABLED
|
||||
_GODOT_CPP_THREAD_LOCAL GDExtensionObjectPtr Wrapped::_constructing_recreate_owner = nullptr;
|
||||
#endif
|
||||
|
||||
const StringName *Wrapped::_get_extension_class_name() {
|
||||
const StringName *Wrapped::_get_extension_class_name() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Wrapped::_postinitialize() {
|
||||
#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
|
||||
Wrapped::_constructing_mutex.unlock();
|
||||
#endif
|
||||
|
||||
Object *obj = dynamic_cast<Object *>(this);
|
||||
if (obj) {
|
||||
obj->notification(Object::NOTIFICATION_POSTINITIALIZE);
|
||||
const StringName *extension_class = _get_extension_class_name();
|
||||
if (extension_class) {
|
||||
godot::internal::gdextension_interface_object_set_instance(_owner, reinterpret_cast<GDExtensionConstStringNamePtr>(extension_class), this);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Wrapped::Wrapped(const StringName p_godot_class) {
|
||||
#ifdef HOT_RELOAD_ENABLED
|
||||
if (unlikely(Wrapped::_constructing_recreate_owner)) {
|
||||
_owner = Wrapped::_constructing_recreate_owner;
|
||||
Wrapped::_constructing_recreate_owner = nullptr;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
_owner = godot::internal::gdextension_interface_classdb_construct_object2(reinterpret_cast<GDExtensionConstStringNamePtr>(p_godot_class._native_ptr()));
|
||||
}
|
||||
|
||||
if (_constructing_extension_class_name) {
|
||||
godot::internal::gdextension_interface_object_set_instance(_owner, reinterpret_cast<GDExtensionConstStringNamePtr>(_constructing_extension_class_name), this);
|
||||
_constructing_extension_class_name = nullptr;
|
||||
}
|
||||
|
||||
if (likely(_constructing_class_binding_callbacks)) {
|
||||
godot::internal::gdextension_interface_object_set_instance_binding(_owner, godot::internal::token, this, _constructing_class_binding_callbacks);
|
||||
_constructing_class_binding_callbacks = nullptr;
|
||||
} else {
|
||||
CRASH_NOW_MSG("BUG: Godot Object created without binding callbacks. Did you forget to use memnew()?");
|
||||
}
|
||||
_owner = godot::internal::gdextension_interface_classdb_construct_object(reinterpret_cast<GDExtensionConstStringNamePtr>(p_godot_class._native_ptr()));
|
||||
}
|
||||
|
||||
Wrapped::Wrapped(GodotObject *p_godot_object) {
|
||||
@@ -105,31 +77,6 @@ std::vector<EngineClassRegistrationCallback> &get_engine_class_registration_call
|
||||
return engine_class_registration_callbacks;
|
||||
}
|
||||
|
||||
GDExtensionPropertyInfo *create_c_property_list(const ::godot::List<::godot::PropertyInfo> &plist_cpp, uint32_t *r_size) {
|
||||
GDExtensionPropertyInfo *plist = nullptr;
|
||||
// Linked list size can be expensive to get so we cache it
|
||||
const uint32_t plist_size = plist_cpp.size();
|
||||
if (r_size != nullptr) {
|
||||
*r_size = plist_size;
|
||||
}
|
||||
plist = reinterpret_cast<GDExtensionPropertyInfo *>(memalloc(sizeof(GDExtensionPropertyInfo) * plist_size));
|
||||
unsigned int i = 0;
|
||||
for (const ::godot::PropertyInfo &E : plist_cpp) {
|
||||
plist[i].type = static_cast<GDExtensionVariantType>(E.type);
|
||||
plist[i].name = E.name._native_ptr();
|
||||
plist[i].hint = E.hint;
|
||||
plist[i].hint_string = E.hint_string._native_ptr();
|
||||
plist[i].class_name = E.class_name._native_ptr();
|
||||
plist[i].usage = E.usage;
|
||||
++i;
|
||||
}
|
||||
return plist;
|
||||
}
|
||||
|
||||
void free_c_property_list(GDExtensionPropertyInfo *plist) {
|
||||
memfree(plist);
|
||||
}
|
||||
|
||||
void add_engine_class_registration_callback(EngineClassRegistrationCallback p_callback) {
|
||||
get_engine_class_registration_callbacks().push_back(p_callback);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
|
||||
#include <godot_cpp/core/error_macros.hpp>
|
||||
#include <godot_cpp/godot.hpp>
|
||||
#include <godot_cpp/templates/vector.hpp>
|
||||
|
||||
#include <godot_cpp/core/memory.hpp>
|
||||
|
||||
@@ -43,8 +42,6 @@ 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) {
|
||||
@@ -108,7 +105,15 @@ void ClassDB::add_property(const StringName &p_class, const PropertyInfo &p_pinf
|
||||
p_pinfo.usage, // DEFAULT //uint32_t usage;
|
||||
};
|
||||
|
||||
internal::gdextension_interface_classdb_register_extension_class_property_indexed(internal::library, info.name._native_ptr(), &prop_info, p_setter._native_ptr(), p_getter._native_ptr(), p_index);
|
||||
PropertySetGet setget;
|
||||
setget.setter = p_setter;
|
||||
setget.getter = p_getter;
|
||||
setget._setptr = setter;
|
||||
setget._getptr = getter;
|
||||
setget.index = p_index;
|
||||
setget.type = p_pinfo.type;
|
||||
|
||||
internal::gdextension_interface_classdb_register_extension_class_property(internal::library, info.name._native_ptr(), &prop_info, setget.setter._native_ptr(), setget.getter._native_ptr());
|
||||
}
|
||||
|
||||
MethodBind *ClassDB::get_method(const StringName &p_class, const StringName &p_method) {
|
||||
@@ -285,7 +290,7 @@ void ClassDB::bind_integer_constant(const StringName &p_class_name, const String
|
||||
// Register it with Godot
|
||||
internal::gdextension_interface_classdb_register_extension_class_integer_constant(internal::library, p_class_name._native_ptr(), p_enum_name._native_ptr(), p_constant_name._native_ptr(), p_constant_value, p_is_bitfield);
|
||||
}
|
||||
GDExtensionClassCallVirtual ClassDB::get_virtual_func(void *p_userdata, GDExtensionConstStringNamePtr p_name, uint32_t p_hash) {
|
||||
GDExtensionClassCallVirtual ClassDB::get_virtual_func(void *p_userdata, GDExtensionConstStringNamePtr p_name) {
|
||||
// This is called by Godot the first time it calls a virtual function, and it caches the result, per object instance.
|
||||
// Because of this, it can happen from different threads at once.
|
||||
// It should be ok not using any mutex as long as we only READ data.
|
||||
@@ -299,10 +304,10 @@ GDExtensionClassCallVirtual ClassDB::get_virtual_func(void *p_userdata, GDExtens
|
||||
|
||||
// Find method in current class, or any of its parent classes (Godot classes not included)
|
||||
while (type != nullptr) {
|
||||
std::unordered_map<StringName, ClassInfo::VirtualMethod>::const_iterator method_it = type->virtual_methods.find(*name);
|
||||
std::unordered_map<StringName, GDExtensionClassCallVirtual>::const_iterator method_it = type->virtual_methods.find(*name);
|
||||
|
||||
if (method_it != type->virtual_methods.end() && method_it->second.hash == p_hash) {
|
||||
return method_it->second.func;
|
||||
if (method_it != type->virtual_methods.end()) {
|
||||
return method_it->second;
|
||||
}
|
||||
|
||||
type = type->parent_ptr;
|
||||
@@ -328,7 +333,7 @@ const GDExtensionInstanceBindingCallbacks *ClassDB::get_instance_binding_callbac
|
||||
return callbacks_it->second;
|
||||
}
|
||||
|
||||
void ClassDB::bind_virtual_method(const StringName &p_class, const StringName &p_method, GDExtensionClassCallVirtual p_call, uint32_t p_hash) {
|
||||
void ClassDB::bind_virtual_method(const StringName &p_class, const StringName &p_method, GDExtensionClassCallVirtual p_call) {
|
||||
std::unordered_map<StringName, ClassInfo>::iterator type_it = classes.find(p_class);
|
||||
ERR_FAIL_COND_MSG(type_it == classes.end(), String("Class '{0}' doesn't exist.").format(Array::make(p_class)));
|
||||
|
||||
@@ -337,55 +342,7 @@ void ClassDB::bind_virtual_method(const StringName &p_class, const StringName &p
|
||||
ERR_FAIL_COND_MSG(type.method_map.find(p_method) != type.method_map.end(), String("Method '{0}::{1}()' already registered as non-virtual.").format(Array::make(p_class, p_method)));
|
||||
ERR_FAIL_COND_MSG(type.virtual_methods.find(p_method) != type.virtual_methods.end(), String("Virtual '{0}::{1}()' method already registered.").format(Array::make(p_class, p_method)));
|
||||
|
||||
type.virtual_methods[p_method] = ClassInfo::VirtualMethod{
|
||||
p_call,
|
||||
p_hash,
|
||||
};
|
||||
}
|
||||
|
||||
void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_method, const Vector<StringName> &p_arg_names) {
|
||||
std::unordered_map<StringName, ClassInfo>::iterator type_it = classes.find(p_class);
|
||||
ERR_FAIL_COND_MSG(type_it == classes.end(), String("Class '{0}' doesn't exist.").format(Array::make(p_class)));
|
||||
|
||||
GDExtensionClassVirtualMethodInfo mi;
|
||||
mi.name = (GDExtensionStringNamePtr)&p_method.name;
|
||||
mi.method_flags = p_method.flags;
|
||||
mi.return_value = p_method.return_val._to_gdextension();
|
||||
mi.return_value_metadata = p_method.return_val_metadata;
|
||||
mi.argument_count = p_method.arguments.size();
|
||||
if (mi.argument_count > 0) {
|
||||
mi.arguments = (GDExtensionPropertyInfo *)memalloc(sizeof(GDExtensionPropertyInfo) * mi.argument_count);
|
||||
mi.arguments_metadata = (GDExtensionClassMethodArgumentMetadata *)memalloc(sizeof(GDExtensionClassMethodArgumentMetadata) * mi.argument_count);
|
||||
if (mi.argument_count != p_method.arguments_metadata.size()) {
|
||||
WARN_PRINT("Mismatch argument metadata count for virtual method: " + String(p_class) + "::" + p_method.name);
|
||||
}
|
||||
for (uint32_t i = 0; i < mi.argument_count; i++) {
|
||||
mi.arguments[i] = p_method.arguments[i]._to_gdextension();
|
||||
if (i < p_method.arguments_metadata.size()) {
|
||||
mi.arguments_metadata[i] = p_method.arguments_metadata[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mi.arguments = nullptr;
|
||||
mi.arguments_metadata = nullptr;
|
||||
}
|
||||
|
||||
if (p_arg_names.size() != mi.argument_count) {
|
||||
WARN_PRINT("Mismatch argument name count for virtual method: " + String(p_class) + "::" + p_method.name);
|
||||
} else {
|
||||
for (int i = 0; i < p_arg_names.size(); i++) {
|
||||
mi.arguments[i].name = (GDExtensionStringNamePtr)&p_arg_names[i];
|
||||
}
|
||||
}
|
||||
|
||||
internal::gdextension_interface_classdb_register_extension_class_virtual_method(internal::library, &p_class, &mi);
|
||||
|
||||
if (mi.arguments) {
|
||||
memfree(mi.arguments);
|
||||
}
|
||||
if (mi.arguments_metadata) {
|
||||
memfree(mi.arguments_metadata);
|
||||
}
|
||||
type.virtual_methods[p_method] = p_call;
|
||||
}
|
||||
|
||||
void ClassDB::initialize_class(const ClassInfo &p_cl) {
|
||||
@@ -403,7 +360,6 @@ void ClassDB::initialize(GDExtensionInitializationLevel p_level) {
|
||||
}
|
||||
|
||||
void ClassDB::deinitialize(GDExtensionInitializationLevel p_level) {
|
||||
std::set<StringName> to_erase;
|
||||
for (std::vector<StringName>::reverse_iterator i = class_register_order.rbegin(); i != class_register_order.rend(); ++i) {
|
||||
const StringName &name = *i;
|
||||
const ClassInfo &cl = classes[name];
|
||||
@@ -414,36 +370,9 @@ void ClassDB::deinitialize(GDExtensionInitializationLevel p_level) {
|
||||
|
||||
internal::gdextension_interface_classdb_unregister_extension_class(internal::library, name._native_ptr());
|
||||
|
||||
for (const std::pair<const StringName, MethodBind *> &method : cl.method_map) {
|
||||
for (auto method : cl.method_map) {
|
||||
memdelete(method.second);
|
||||
}
|
||||
|
||||
classes.erase(name);
|
||||
to_erase.insert(name);
|
||||
}
|
||||
|
||||
{
|
||||
// The following is equivalent to c++20 `std::erase_if(class_register_order, [&](const StringName& name){ return to_erase.contains(name); });`
|
||||
std::vector<StringName>::iterator it = std::remove_if(class_register_order.begin(), class_register_order.end(), [&](const StringName &p_name) {
|
||||
return to_erase.count(p_name) > 0;
|
||||
});
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace godot {
|
||||
|
||||
void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
bool prepad = false; // Already pre paded in the engine.
|
||||
bool prepad = false; // Alredy pre paded in the engine.
|
||||
#else
|
||||
bool prepad = p_pad_align;
|
||||
#endif
|
||||
@@ -63,7 +63,7 @@ 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; // Already pre paded in the engine.
|
||||
bool prepad = false; // Alredy pre paded in the engine.
|
||||
#else
|
||||
bool prepad = p_pad_align;
|
||||
#endif
|
||||
@@ -82,7 +82,7 @@ void Memory::free_static(void *p_ptr, bool p_pad_align) {
|
||||
uint8_t *mem = (uint8_t *)p_ptr;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
bool prepad = false; // Already pre paded in the engine.
|
||||
bool prepad = false; // Alredy pre paded in the engine.
|
||||
#else
|
||||
bool prepad = p_pad_align;
|
||||
#endif
|
||||
@@ -103,29 +103,28 @@ _GlobalNil _GlobalNilClass::_nil;
|
||||
|
||||
} // namespace godot
|
||||
|
||||
// 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) {
|
||||
void *operator new(size_t p_size, const char *p_description) {
|
||||
return godot::Memory::alloc_static(p_size);
|
||||
}
|
||||
|
||||
void *operator new(size_t p_size, const char *p_dummy, void *(*p_allocfunc)(size_t p_size)) {
|
||||
void *operator new(size_t p_size, void *(*p_allocfunc)(size_t p_size)) {
|
||||
return p_allocfunc(p_size);
|
||||
}
|
||||
|
||||
using namespace godot;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
void operator delete(void *p_mem, const char *p_dummy, const char *p_description) {
|
||||
void operator delete(void *p_mem, const char *p_description) {
|
||||
ERR_PRINT("Call to placement delete should not happen.");
|
||||
CRASH_NOW();
|
||||
}
|
||||
|
||||
void operator delete(void *p_mem, const char *p_dummy, void *(*p_allocfunc)(size_t p_size)) {
|
||||
void operator delete(void *p_mem, void *(*p_allocfunc)(size_t p_size)) {
|
||||
ERR_PRINT("Call to placement delete should not happen.");
|
||||
CRASH_NOW();
|
||||
}
|
||||
|
||||
void operator delete(void *p_mem, const char *p_dummy, void *p_pointer, size_t check, const char *p_description) {
|
||||
void operator delete(void *p_mem, void *p_pointer, size_t check, const char *p_description) {
|
||||
ERR_PRINT("Call to placement delete should not happen.");
|
||||
CRASH_NOW();
|
||||
}
|
||||
|
||||
@@ -60,66 +60,8 @@ 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) {}
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* print_string.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include <godot_cpp/core/print_string.hpp>
|
||||
|
||||
#include <godot_cpp/classes/os.hpp>
|
||||
|
||||
namespace godot {
|
||||
bool is_print_verbose_enabled() {
|
||||
return OS::get_singleton()->is_stdout_verbose();
|
||||
}
|
||||
} // namespace godot
|
||||
104
src/godot.cpp
104
src/godot.cpp
@@ -88,13 +88,11 @@ GDExtensionInterfaceVariantGetType gdextension_interface_variant_get_type = null
|
||||
GDExtensionInterfaceVariantHasMethod gdextension_interface_variant_has_method = nullptr;
|
||||
GDExtensionInterfaceVariantHasMember gdextension_interface_variant_has_member = nullptr;
|
||||
GDExtensionInterfaceVariantHasKey gdextension_interface_variant_has_key = nullptr;
|
||||
GDExtensionInterfaceVariantGetObjectInstanceId gdextension_interface_variant_get_object_instance_id = nullptr;
|
||||
GDExtensionInterfaceVariantGetTypeName gdextension_interface_variant_get_type_name = nullptr;
|
||||
GDExtensionInterfaceVariantCanConvert gdextension_interface_variant_can_convert = nullptr;
|
||||
GDExtensionInterfaceVariantCanConvertStrict gdextension_interface_variant_can_convert_strict = nullptr;
|
||||
GDExtensionInterfaceGetVariantFromTypeConstructor gdextension_interface_get_variant_from_type_constructor = nullptr;
|
||||
GDExtensionInterfaceGetVariantToTypeConstructor gdextension_interface_get_variant_to_type_constructor = nullptr;
|
||||
GDExtensionInterfaceGetVariantGetInternalPtrFunc gdextension_interface_variant_get_ptr_internal_getter = nullptr;
|
||||
GDExtensionInterfaceVariantGetPtrOperatorEvaluator gdextension_interface_variant_get_ptr_operator_evaluator = nullptr;
|
||||
GDExtensionInterfaceVariantGetPtrBuiltinMethod gdextension_interface_variant_get_ptr_builtin_method = nullptr;
|
||||
GDExtensionInterfaceVariantGetPtrConstructor gdextension_interface_variant_get_ptr_constructor = nullptr;
|
||||
@@ -116,9 +114,7 @@ GDExtensionInterfaceStringNewWithUtf32Chars gdextension_interface_string_new_wit
|
||||
GDExtensionInterfaceStringNewWithWideChars gdextension_interface_string_new_with_wide_chars = nullptr;
|
||||
GDExtensionInterfaceStringNewWithLatin1CharsAndLen gdextension_interface_string_new_with_latin1_chars_and_len = nullptr;
|
||||
GDExtensionInterfaceStringNewWithUtf8CharsAndLen gdextension_interface_string_new_with_utf8_chars_and_len = nullptr;
|
||||
GDExtensionInterfaceStringNewWithUtf8CharsAndLen2 gdextension_interface_string_new_with_utf8_chars_and_len2 = nullptr;
|
||||
GDExtensionInterfaceStringNewWithUtf16CharsAndLen gdextension_interface_string_new_with_utf16_chars_and_len = nullptr;
|
||||
GDExtensionInterfaceStringNewWithUtf16CharsAndLen2 gdextension_interface_string_new_with_utf16_chars_and_len2 = nullptr;
|
||||
GDExtensionInterfaceStringNewWithUtf32CharsAndLen gdextension_interface_string_new_with_utf32_chars_and_len = nullptr;
|
||||
GDExtensionInterfaceStringNewWithWideCharsAndLen gdextension_interface_string_new_with_wide_chars_and_len = nullptr;
|
||||
GDExtensionInterfaceStringToLatin1Chars gdextension_interface_string_to_latin1_chars = nullptr;
|
||||
@@ -133,8 +129,6 @@ GDExtensionInterfaceStringOperatorPlusEqChar gdextension_interface_string_operat
|
||||
GDExtensionInterfaceStringOperatorPlusEqCstr gdextension_interface_string_operator_plus_eq_cstr = nullptr;
|
||||
GDExtensionInterfaceStringOperatorPlusEqWcstr gdextension_interface_string_operator_plus_eq_wcstr = nullptr;
|
||||
GDExtensionInterfaceStringOperatorPlusEqC32str gdextension_interface_string_operator_plus_eq_c32str = nullptr;
|
||||
GDExtensionInterfaceStringResize gdextension_interface_string_resize = nullptr;
|
||||
GDExtensionInterfaceStringNameNewWithLatin1Chars gdextension_interface_string_name_new_with_latin1_chars = nullptr;
|
||||
GDExtensionInterfaceXmlParserOpenBuffer gdextension_interface_xml_parser_open_buffer = nullptr;
|
||||
GDExtensionInterfaceFileAccessStoreBuffer gdextension_interface_file_access_store_buffer = nullptr;
|
||||
GDExtensionInterfaceFileAccessGetBuffer gdextension_interface_file_access_get_buffer = nullptr;
|
||||
@@ -158,45 +152,33 @@ GDExtensionInterfacePackedVector2ArrayOperatorIndex gdextension_interface_packed
|
||||
GDExtensionInterfacePackedVector2ArrayOperatorIndexConst gdextension_interface_packed_vector2_array_operator_index_const = nullptr;
|
||||
GDExtensionInterfacePackedVector3ArrayOperatorIndex gdextension_interface_packed_vector3_array_operator_index = nullptr;
|
||||
GDExtensionInterfacePackedVector3ArrayOperatorIndexConst gdextension_interface_packed_vector3_array_operator_index_const = nullptr;
|
||||
GDExtensionInterfacePackedVector4ArrayOperatorIndex gdextension_interface_packed_vector4_array_operator_index = nullptr;
|
||||
GDExtensionInterfacePackedVector4ArrayOperatorIndexConst gdextension_interface_packed_vector4_array_operator_index_const = nullptr;
|
||||
GDExtensionInterfaceArrayOperatorIndex gdextension_interface_array_operator_index = nullptr;
|
||||
GDExtensionInterfaceArrayOperatorIndexConst gdextension_interface_array_operator_index_const = nullptr;
|
||||
GDExtensionInterfaceArrayRef gdextension_interface_array_ref = nullptr;
|
||||
GDExtensionInterfaceArraySetTyped gdextension_interface_array_set_typed = nullptr;
|
||||
GDExtensionInterfaceDictionaryOperatorIndex gdextension_interface_dictionary_operator_index = nullptr;
|
||||
GDExtensionInterfaceDictionaryOperatorIndexConst gdextension_interface_dictionary_operator_index_const = nullptr;
|
||||
GDExtensionInterfaceDictionarySetTyped gdextension_interface_dictionary_set_typed = nullptr;
|
||||
GDExtensionInterfaceObjectMethodBindCall gdextension_interface_object_method_bind_call = nullptr;
|
||||
GDExtensionInterfaceObjectMethodBindPtrcall gdextension_interface_object_method_bind_ptrcall = nullptr;
|
||||
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;
|
||||
GDExtensionInterfaceObjectGetInstanceFromId gdextension_interface_object_get_instance_from_id = nullptr;
|
||||
GDExtensionInterfaceObjectGetInstanceId gdextension_interface_object_get_instance_id = nullptr;
|
||||
GDExtensionInterfaceObjectHasScriptMethod gdextension_interface_object_has_script_method = nullptr;
|
||||
GDExtensionInterfaceObjectCallScriptMethod gdextension_interface_object_call_script_method = nullptr;
|
||||
GDExtensionInterfaceCallableCustomCreate2 gdextension_interface_callable_custom_create2 = nullptr;
|
||||
GDExtensionInterfaceCallableCustomGetUserData gdextension_interface_callable_custom_get_userdata = nullptr;
|
||||
GDExtensionInterfaceRefGetObject gdextension_interface_ref_get_object = nullptr;
|
||||
GDExtensionInterfaceRefSetObject gdextension_interface_ref_set_object = nullptr;
|
||||
GDExtensionInterfaceScriptInstanceCreate3 gdextension_interface_script_instance_create3 = nullptr;
|
||||
GDExtensionInterfacePlaceHolderScriptInstanceCreate gdextension_interface_placeholder_script_instance_create = nullptr;
|
||||
GDExtensionInterfacePlaceHolderScriptInstanceUpdate gdextension_interface_placeholder_script_instance_update = nullptr;
|
||||
GDExtensionInterfaceClassdbConstructObject2 gdextension_interface_classdb_construct_object2 = nullptr;
|
||||
GDExtensionInterfaceScriptInstanceCreate gdextension_interface_script_instance_create = nullptr;
|
||||
GDExtensionInterfaceClassdbConstructObject gdextension_interface_classdb_construct_object = nullptr;
|
||||
GDExtensionInterfaceClassdbGetMethodBind gdextension_interface_classdb_get_method_bind = nullptr;
|
||||
GDExtensionInterfaceClassdbGetClassTag gdextension_interface_classdb_get_class_tag = nullptr;
|
||||
GDExtensionInterfaceClassdbRegisterExtensionClass4 gdextension_interface_classdb_register_extension_class4 = nullptr;
|
||||
GDExtensionInterfaceClassdbRegisterExtensionClass gdextension_interface_classdb_register_extension_class = nullptr;
|
||||
GDExtensionInterfaceClassdbRegisterExtensionClassMethod gdextension_interface_classdb_register_extension_class_method = nullptr;
|
||||
GDExtensionInterfaceClassdbRegisterExtensionClassVirtualMethod gdextension_interface_classdb_register_extension_class_virtual_method = nullptr;
|
||||
GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant gdextension_interface_classdb_register_extension_class_integer_constant = nullptr;
|
||||
GDExtensionInterfaceClassdbRegisterExtensionClassProperty gdextension_interface_classdb_register_extension_class_property = nullptr;
|
||||
GDExtensionInterfaceClassdbRegisterExtensionClassPropertyIndexed gdextension_interface_classdb_register_extension_class_property_indexed = nullptr;
|
||||
GDExtensionInterfaceClassdbRegisterExtensionClassPropertyGroup gdextension_interface_classdb_register_extension_class_property_group = nullptr;
|
||||
GDExtensionInterfaceClassdbRegisterExtensionClassPropertySubgroup gdextension_interface_classdb_register_extension_class_property_subgroup = nullptr;
|
||||
GDExtensionInterfaceClassdbRegisterExtensionClassSignal gdextension_interface_classdb_register_extension_class_signal = nullptr;
|
||||
@@ -204,40 +186,6 @@ GDExtensionInterfaceClassdbUnregisterExtensionClass gdextension_interface_classd
|
||||
GDExtensionInterfaceGetLibraryPath gdextension_interface_get_library_path = nullptr;
|
||||
GDExtensionInterfaceEditorAddPlugin gdextension_interface_editor_add_plugin = nullptr;
|
||||
GDExtensionInterfaceEditorRemovePlugin gdextension_interface_editor_remove_plugin = nullptr;
|
||||
GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars gdextension_interface_editor_help_load_xml_from_utf8_chars = nullptr;
|
||||
GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen gdextension_interface_editor_help_load_xml_from_utf8_chars_and_len = nullptr;
|
||||
GDExtensionInterfaceImagePtrw gdextension_interface_image_ptrw = nullptr;
|
||||
GDExtensionInterfaceImagePtr gdextension_interface_image_ptr = nullptr;
|
||||
|
||||
struct DocData {
|
||||
const char *hash = nullptr;
|
||||
int uncompressed_size = 0;
|
||||
int compressed_size = 0;
|
||||
const unsigned char *data = nullptr;
|
||||
|
||||
inline bool is_valid() const {
|
||||
return hash != nullptr && uncompressed_size > 0 && compressed_size > 0 && data != nullptr;
|
||||
}
|
||||
|
||||
void load_data() const;
|
||||
};
|
||||
|
||||
static DocData &get_doc_data() {
|
||||
static DocData doc_data;
|
||||
return doc_data;
|
||||
}
|
||||
|
||||
DocDataRegistration::DocDataRegistration(const char *p_hash, int p_uncompressed_size, int p_compressed_size, const unsigned char *p_data) {
|
||||
DocData &doc_data = get_doc_data();
|
||||
if (doc_data.is_valid()) {
|
||||
printf("ERROR: Attempting to register documentation data when we already have some - discarding.\n");
|
||||
return;
|
||||
}
|
||||
doc_data.hash = p_hash;
|
||||
doc_data.uncompressed_size = p_uncompressed_size;
|
||||
doc_data.compressed_size = p_compressed_size;
|
||||
doc_data.data = p_data;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
@@ -370,13 +318,11 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
|
||||
LOAD_PROC_ADDRESS(variant_has_method, GDExtensionInterfaceVariantHasMethod);
|
||||
LOAD_PROC_ADDRESS(variant_has_member, GDExtensionInterfaceVariantHasMember);
|
||||
LOAD_PROC_ADDRESS(variant_has_key, GDExtensionInterfaceVariantHasKey);
|
||||
LOAD_PROC_ADDRESS(variant_get_object_instance_id, GDExtensionInterfaceVariantGetObjectInstanceId);
|
||||
LOAD_PROC_ADDRESS(variant_get_type_name, GDExtensionInterfaceVariantGetTypeName);
|
||||
LOAD_PROC_ADDRESS(variant_can_convert, GDExtensionInterfaceVariantCanConvert);
|
||||
LOAD_PROC_ADDRESS(variant_can_convert_strict, GDExtensionInterfaceVariantCanConvertStrict);
|
||||
LOAD_PROC_ADDRESS(get_variant_from_type_constructor, GDExtensionInterfaceGetVariantFromTypeConstructor);
|
||||
LOAD_PROC_ADDRESS(get_variant_to_type_constructor, GDExtensionInterfaceGetVariantToTypeConstructor);
|
||||
LOAD_PROC_ADDRESS(variant_get_ptr_internal_getter, GDExtensionInterfaceGetVariantGetInternalPtrFunc);
|
||||
LOAD_PROC_ADDRESS(variant_get_ptr_operator_evaluator, GDExtensionInterfaceVariantGetPtrOperatorEvaluator);
|
||||
LOAD_PROC_ADDRESS(variant_get_ptr_builtin_method, GDExtensionInterfaceVariantGetPtrBuiltinMethod);
|
||||
LOAD_PROC_ADDRESS(variant_get_ptr_constructor, GDExtensionInterfaceVariantGetPtrConstructor);
|
||||
@@ -398,9 +344,7 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
|
||||
LOAD_PROC_ADDRESS(string_new_with_wide_chars, GDExtensionInterfaceStringNewWithWideChars);
|
||||
LOAD_PROC_ADDRESS(string_new_with_latin1_chars_and_len, GDExtensionInterfaceStringNewWithLatin1CharsAndLen);
|
||||
LOAD_PROC_ADDRESS(string_new_with_utf8_chars_and_len, GDExtensionInterfaceStringNewWithUtf8CharsAndLen);
|
||||
LOAD_PROC_ADDRESS(string_new_with_utf8_chars_and_len2, GDExtensionInterfaceStringNewWithUtf8CharsAndLen2);
|
||||
LOAD_PROC_ADDRESS(string_new_with_utf16_chars_and_len, GDExtensionInterfaceStringNewWithUtf16CharsAndLen);
|
||||
LOAD_PROC_ADDRESS(string_new_with_utf16_chars_and_len2, GDExtensionInterfaceStringNewWithUtf16CharsAndLen2);
|
||||
LOAD_PROC_ADDRESS(string_new_with_utf32_chars_and_len, GDExtensionInterfaceStringNewWithUtf32CharsAndLen);
|
||||
LOAD_PROC_ADDRESS(string_new_with_wide_chars_and_len, GDExtensionInterfaceStringNewWithWideCharsAndLen);
|
||||
LOAD_PROC_ADDRESS(string_to_latin1_chars, GDExtensionInterfaceStringToLatin1Chars);
|
||||
@@ -415,8 +359,6 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
|
||||
LOAD_PROC_ADDRESS(string_operator_plus_eq_cstr, GDExtensionInterfaceStringOperatorPlusEqCstr);
|
||||
LOAD_PROC_ADDRESS(string_operator_plus_eq_wcstr, GDExtensionInterfaceStringOperatorPlusEqWcstr);
|
||||
LOAD_PROC_ADDRESS(string_operator_plus_eq_c32str, GDExtensionInterfaceStringOperatorPlusEqC32str);
|
||||
LOAD_PROC_ADDRESS(string_resize, GDExtensionInterfaceStringResize);
|
||||
LOAD_PROC_ADDRESS(string_name_new_with_latin1_chars, GDExtensionInterfaceStringNameNewWithLatin1Chars);
|
||||
LOAD_PROC_ADDRESS(xml_parser_open_buffer, GDExtensionInterfaceXmlParserOpenBuffer);
|
||||
LOAD_PROC_ADDRESS(file_access_store_buffer, GDExtensionInterfaceFileAccessStoreBuffer);
|
||||
LOAD_PROC_ADDRESS(file_access_get_buffer, GDExtensionInterfaceFileAccessGetBuffer);
|
||||
@@ -440,45 +382,33 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
|
||||
LOAD_PROC_ADDRESS(packed_vector2_array_operator_index_const, GDExtensionInterfacePackedVector2ArrayOperatorIndexConst);
|
||||
LOAD_PROC_ADDRESS(packed_vector3_array_operator_index, GDExtensionInterfacePackedVector3ArrayOperatorIndex);
|
||||
LOAD_PROC_ADDRESS(packed_vector3_array_operator_index_const, GDExtensionInterfacePackedVector3ArrayOperatorIndexConst);
|
||||
LOAD_PROC_ADDRESS(packed_vector4_array_operator_index, GDExtensionInterfacePackedVector4ArrayOperatorIndex);
|
||||
LOAD_PROC_ADDRESS(packed_vector4_array_operator_index_const, GDExtensionInterfacePackedVector4ArrayOperatorIndexConst);
|
||||
LOAD_PROC_ADDRESS(array_operator_index, GDExtensionInterfaceArrayOperatorIndex);
|
||||
LOAD_PROC_ADDRESS(array_operator_index_const, GDExtensionInterfaceArrayOperatorIndexConst);
|
||||
LOAD_PROC_ADDRESS(array_ref, GDExtensionInterfaceArrayRef);
|
||||
LOAD_PROC_ADDRESS(array_set_typed, GDExtensionInterfaceArraySetTyped);
|
||||
LOAD_PROC_ADDRESS(dictionary_operator_index, GDExtensionInterfaceDictionaryOperatorIndex);
|
||||
LOAD_PROC_ADDRESS(dictionary_operator_index_const, GDExtensionInterfaceDictionaryOperatorIndexConst);
|
||||
LOAD_PROC_ADDRESS(dictionary_set_typed, GDExtensionInterfaceDictionarySetTyped);
|
||||
LOAD_PROC_ADDRESS(object_method_bind_call, GDExtensionInterfaceObjectMethodBindCall);
|
||||
LOAD_PROC_ADDRESS(object_method_bind_ptrcall, GDExtensionInterfaceObjectMethodBindPtrcall);
|
||||
LOAD_PROC_ADDRESS(object_destroy, GDExtensionInterfaceObjectDestroy);
|
||||
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);
|
||||
LOAD_PROC_ADDRESS(object_get_instance_from_id, GDExtensionInterfaceObjectGetInstanceFromId);
|
||||
LOAD_PROC_ADDRESS(object_get_instance_id, GDExtensionInterfaceObjectGetInstanceId);
|
||||
LOAD_PROC_ADDRESS(object_has_script_method, GDExtensionInterfaceObjectHasScriptMethod);
|
||||
LOAD_PROC_ADDRESS(object_call_script_method, GDExtensionInterfaceObjectCallScriptMethod);
|
||||
LOAD_PROC_ADDRESS(callable_custom_create2, GDExtensionInterfaceCallableCustomCreate2);
|
||||
LOAD_PROC_ADDRESS(callable_custom_get_userdata, GDExtensionInterfaceCallableCustomGetUserData);
|
||||
LOAD_PROC_ADDRESS(ref_get_object, GDExtensionInterfaceRefGetObject);
|
||||
LOAD_PROC_ADDRESS(ref_set_object, GDExtensionInterfaceRefSetObject);
|
||||
LOAD_PROC_ADDRESS(script_instance_create3, GDExtensionInterfaceScriptInstanceCreate3);
|
||||
LOAD_PROC_ADDRESS(placeholder_script_instance_create, GDExtensionInterfacePlaceHolderScriptInstanceCreate);
|
||||
LOAD_PROC_ADDRESS(placeholder_script_instance_update, GDExtensionInterfacePlaceHolderScriptInstanceUpdate);
|
||||
LOAD_PROC_ADDRESS(classdb_construct_object2, GDExtensionInterfaceClassdbConstructObject2);
|
||||
LOAD_PROC_ADDRESS(script_instance_create, GDExtensionInterfaceScriptInstanceCreate);
|
||||
LOAD_PROC_ADDRESS(classdb_construct_object, GDExtensionInterfaceClassdbConstructObject);
|
||||
LOAD_PROC_ADDRESS(classdb_get_method_bind, GDExtensionInterfaceClassdbGetMethodBind);
|
||||
LOAD_PROC_ADDRESS(classdb_get_class_tag, GDExtensionInterfaceClassdbGetClassTag);
|
||||
LOAD_PROC_ADDRESS(classdb_register_extension_class4, GDExtensionInterfaceClassdbRegisterExtensionClass4);
|
||||
LOAD_PROC_ADDRESS(classdb_register_extension_class, GDExtensionInterfaceClassdbRegisterExtensionClass);
|
||||
LOAD_PROC_ADDRESS(classdb_register_extension_class_method, GDExtensionInterfaceClassdbRegisterExtensionClassMethod);
|
||||
LOAD_PROC_ADDRESS(classdb_register_extension_class_virtual_method, GDExtensionInterfaceClassdbRegisterExtensionClassVirtualMethod);
|
||||
LOAD_PROC_ADDRESS(classdb_register_extension_class_integer_constant, GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant);
|
||||
LOAD_PROC_ADDRESS(classdb_register_extension_class_property, GDExtensionInterfaceClassdbRegisterExtensionClassProperty);
|
||||
LOAD_PROC_ADDRESS(classdb_register_extension_class_property_indexed, GDExtensionInterfaceClassdbRegisterExtensionClassPropertyIndexed);
|
||||
LOAD_PROC_ADDRESS(classdb_register_extension_class_property_group, GDExtensionInterfaceClassdbRegisterExtensionClassPropertyGroup);
|
||||
LOAD_PROC_ADDRESS(classdb_register_extension_class_property_subgroup, GDExtensionInterfaceClassdbRegisterExtensionClassPropertySubgroup);
|
||||
LOAD_PROC_ADDRESS(classdb_register_extension_class_signal, GDExtensionInterfaceClassdbRegisterExtensionClassSignal);
|
||||
@@ -486,10 +416,6 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
|
||||
LOAD_PROC_ADDRESS(get_library_path, GDExtensionInterfaceGetLibraryPath);
|
||||
LOAD_PROC_ADDRESS(editor_add_plugin, GDExtensionInterfaceEditorAddPlugin);
|
||||
LOAD_PROC_ADDRESS(editor_remove_plugin, GDExtensionInterfaceEditorRemovePlugin);
|
||||
LOAD_PROC_ADDRESS(editor_help_load_xml_from_utf8_chars, GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars);
|
||||
LOAD_PROC_ADDRESS(editor_help_load_xml_from_utf8_chars_and_len, GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen);
|
||||
LOAD_PROC_ADDRESS(image_ptrw, GDExtensionInterfaceImagePtrw);
|
||||
LOAD_PROC_ADDRESS(image_ptr, GDExtensionInterfaceImagePtr);
|
||||
|
||||
r_initialization->initialize = initialize_level;
|
||||
r_initialization->deinitialize = deinitialize_level;
|
||||
@@ -519,13 +445,6 @@ void GDExtensionBinding::initialize_level(void *p_userdata, GDExtensionInitializ
|
||||
ClassDB::initialize(p_level);
|
||||
}
|
||||
level_initialized[p_level]++;
|
||||
|
||||
if ((ModuleInitializationLevel)p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) {
|
||||
const internal::DocData &doc_data = internal::get_doc_data();
|
||||
if (doc_data.is_valid()) {
|
||||
doc_data.load_data();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GDExtensionBinding::deinitialize_level(void *p_userdata, GDExtensionInitializationLevel p_level) {
|
||||
@@ -592,15 +511,4 @@ GDExtensionBool GDExtensionBinding::InitObject::init() const {
|
||||
return GDExtensionBinding::init(get_proc_address, library, init_data, initialization);
|
||||
}
|
||||
|
||||
void internal::DocData::load_data() const {
|
||||
PackedByteArray compressed;
|
||||
compressed.resize(compressed_size);
|
||||
memcpy(compressed.ptrw(), data, compressed_size);
|
||||
|
||||
// FileAccess::COMPRESSION_DEFLATE = 1
|
||||
PackedByteArray decompressed = compressed.decompress(uncompressed_size, 1);
|
||||
|
||||
internal::gdextension_interface_editor_help_load_xml_from_utf8_chars_and_len(reinterpret_cast<const char *>(decompressed.ptr()), uncompressed_size);
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user