Compare commits

..

9 Commits

Author SHA1 Message Date
David Snopek
65dc2f1265 Merge pull request #1533 from dsnopek/4.0-cherrypicks-1
Cherry-picks for the godot-cpp 4.0 branch - 1st batch
2024-07-23 09:42:29 -05:00
Fabio Alessandrelli
469d65d951 [CI] Update macOS workers to macos-latest
GitHub actions no longer allow `macos-11` runners

(cherry picked from commit 2dd8917508)
2024-07-22 08:44:18 -05:00
dependabot[bot]
597ae98f44 Bump mymindstorm/setup-emsdk from 12 to 13
Bumps [mymindstorm/setup-emsdk](https://github.com/mymindstorm/setup-emsdk) from 12 to 13.
- [Release notes](https://github.com/mymindstorm/setup-emsdk/releases)
- [Commits](https://github.com/mymindstorm/setup-emsdk/compare/v12...v13)

---
updated-dependencies:
- dependency-name: mymindstorm/setup-emsdk
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit 78bf5a42ed)
2024-07-22 08:44:07 -05:00
Rémi Verschelde
c8096d4668 CI: Install Android NDK r23c explicitly
It has just been removed from the Ubuntu 20.04 default install,
breaking our CI setup.

Also, sets Emscripten version to 3.1.39, as done upstream.
Newer versions actually break dynamic library support.

(cherry picked from commit eea33b4133)
2024-07-22 08:43:36 -05:00
Rémi Verschelde
2fdac1c9a9 gdextension: Sync with upstream commit fc0b241c9b0be3890712c3b72248d6bd790e7889 (4.0.4-stable) 2023-11-09 13:22:17 +01:00
Rémi Verschelde
d479df19f7 CI: Fix MinGW install error by pinning to earlier version
Works around https://github.com/egor-tensin/setup-mingw/issues/14.

(cherry picked from commit 0369f6fea0)
2023-10-04 15:21:11 +02:00
Rémi Verschelde
3a9118cb0d gdextension: Sync with upstream commit 5222a99f5d38cd5346254cefed8f65315bca4fcb (4.0.3-stable) 2023-05-19 14:08:46 +02:00
Rémi Verschelde
7fb46e9ea1 gdextension: Sync with upstream commit 7a0977ce2c558fe6219f0a14f8bd4d05aea8f019 (4.0.2-stable) 2023-04-04 15:46:34 +02:00
Rémi Verschelde
4d3afc0ad0 gdextension: Sync with upstream commit cacf49999e3fb37281d66cc591ca8bebc5712d4d (4.0.1-stable) 2023-03-20 18:33:38 +01:00
67 changed files with 1873 additions and 12007 deletions

View File

@@ -1,71 +0,0 @@
name: Bug report
description: Report a bug in the godot-cpp GDExtension/GDNative integration
body:
- type: markdown
attributes:
value: |
- When reporting bugs, you'll make our life simpler (and the fix will come sooner) if you follow the guidelines in this template.
- 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/stable/about/release_policy.html).
- type: input
attributes:
label: Godot version
description: >
Specify the Git commit hash if using a development or non-official build.
If you use a custom build, please test if your issue is reproducible in official builds too.
placeholder: 3.3.stable, 4.0.dev (3041becc6)
validations:
required: true
- type: input
attributes:
label: godot-cpp version
description: >
Specify the Git commit hash if using a development build.
placeholder: 3.3.stable, 4.0.dev (3041becc6)
validations:
required: true
- type: input
attributes:
label: System information
description: |
- Specify the OS version, and when relevant hardware information.
- For issues that are likely OS-specific and/or graphics-related, please specify the CPU model and architecture.
- **Bug reports not including the required information may be closed at the maintainers' discretion.** If in doubt, always include all the requested information; it's better to include too much information than not enough information.
placeholder: Windows 10, Intel Core i5-7200U
validations:
required: true
- type: textarea
attributes:
label: Issue description
description: |
Describe your issue briefly. What doesn't work, and how do you expect it to work instead?
You can include images or videos with drag and drop, and format code blocks or logs with <code>```</code> tags.
validations:
required: true
- type: textarea
attributes:
label: Steps to reproduce
description: |
List of steps or sample code that reproduces the issue. Having reproducible issues is a prerequisite for contributors to be able to solve them.
If you include a minimal reproduction project below, you can detail how to use it here.
validations:
required: true
- type: textarea
attributes:
label: Minimal reproduction project
description: |
- A small Godot project which reproduces the issue, with no unnecessary files included. Be sure to not include the `.godot` folder in the archive (but keep `project.godot`).
- Required, unless the reproduction steps are trivial and don't require any project files to be followed. In this case, write "N/A" in the field.
- Drag and drop a ZIP archive to upload it. **Do not select another field until the project is done uploading.**
- **If you've been asked by a maintainer to upload a minimal reproduction project, you *must* do so within 7 days.** Otherwise, your bug report will be closed as it'll be considered too difficult to diagnose.
validations:
required: true

View File

@@ -1,14 +0,0 @@
blank_issues_enabled: false
contact_links:
- name: Godot proposals
url: https://github.com/godotengine/godot-proposals
about: Please submit feature proposals on the Godot proposals repository, not here.
- name: Godot documentation repository
url: https://github.com/godotengine/godot-docs
about: Please report issues with documentation on the Godot documentation repository, not here.
- name: Godot community channels
url: https://godotengine.org/community
about: Please ask for technical support on one of the other community channels, not here.

View File

@@ -22,7 +22,6 @@ jobs:
platform: linux
artifact-name: godot-cpp-linux-glibc2.27-x86_64-release
artifact-path: bin/libgodot-cpp.linux.template_release.x86_64.a
run-tests: true
cache-name: linux-x86_64
- name: 🐧 Linux (GCC, Double Precision)
@@ -31,7 +30,6 @@ jobs:
artifact-name: godot-cpp-linux-glibc2.27-x86_64-double-release
artifact-path: bin/libgodot-cpp.linux.template_release.double.x86_64.a
flags: precision=double
run-tests: false
cache-name: linux-x86_64-f64
- name: 🏁 Windows (x86_64, MSVC)
@@ -39,7 +37,6 @@ jobs:
platform: windows
artifact-name: godot-cpp-windows-msvc2019-x86_64-release
artifact-path: bin/libgodot-cpp.windows.template_release.x86_64.lib
run-tests: false
cache-name: windows-x86_64-msvc
- name: 🏁 Windows (x86_64, MinGW)
@@ -48,16 +45,14 @@ jobs:
artifact-name: godot-cpp-linux-mingw-x86_64-release
artifact-path: bin/libgodot-cpp.windows.template_release.x86_64.a
flags: use_mingw=yes
run-tests: false
cache-name: windows-x86_64-mingw
- name: 🍎 macOS (universal)
os: macos-11
os: macos-latest
platform: macos
artifact-name: godot-cpp-macos-universal-release
artifact-path: bin/libgodot-cpp.macos.template_release.universal.a
flags: arch=universal
run-tests: false
cache-name: macos-universal
- name: 🤖 Android (arm64)
@@ -65,25 +60,26 @@ jobs:
platform: android
artifact-name: godot-cpp-android-arm64-release
artifact-path: bin/libgodot-cpp.android.template_release.arm64.a
flags: ANDROID_NDK_ROOT=$ANDROID_NDK_LATEST_HOME arch=arm64
flags: arch=arm64
run-tests: false
cache-name: android-arm64
- name: 🍏 iOS (arm64)
os: macos-11
os: macos-latest
platform: ios
artifact-name: godot-cpp-ios-arm64-release
artifact-path: bin/libgodot-cpp.ios.template_release.arm64.a
flags: arch=arm64
run-tests: false
cache-name: ios-arm64
env:
SCONS_CACHE: ${{ github.workspace }}/.scons-cache/
EM_VERSION: 3.1.39
EM_CACHE_FOLDER: "emsdk-cache"
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
submodules: recursive
@@ -98,19 +94,29 @@ jobs:
with:
python-version: '3.x'
- name: Linux dependencies
if: ${{ matrix.platform == 'linux' }}
run: |
sudo apt-get update -qq
sudo apt-get install -qqq build-essential pkg-config
- name: Android dependencies
if: ${{ matrix.platform == 'android' }}
uses: nttld/setup-ndk@v1
with:
ndk-version: r23c
link-to-sdk: true
- name: Install scons
run: |
python -m pip install scons==4.0.0
- name: Web dependencies
if: ${{ matrix.platform == 'web' }}
uses: mymindstorm/setup-emsdk@v13
with:
version: ${{env.EM_VERSION}}
actions-cache-folder: ${{env.EM_CACHE_FOLDER}}
- name: Setup MinGW for Windows/MinGW build
if: ${{ matrix.platform == 'windows' && matrix.flags == 'use_mingw=yes' }}
uses: egor-tensin/setup-mingw@v2
with:
version: 12.2.0
- name: Install scons
run: |
python -m pip install scons==4.0.0
- name: Generate godot-cpp sources only
run: |
@@ -131,31 +137,6 @@ jobs:
cd test
scons platform=${{ matrix.platform }} target=template_release ${{ matrix.flags }}
- name: Download latest Godot artifacts
uses: dsnopek/action-download-artifact@1322f74e2dac9feed2ee76a32d9ae1ca3b4cf4e9
if: ${{ matrix.run-tests }}
with:
repo: godotengine/godot
branch: master
event: push
workflow: linux_builds.yml
workflow_conclusion: success
name: linux-editor-mono
search_artifacts: true
check_artifacts: true
ensure_latest: true
path: godot-artifacts
- name: Run tests
if: ${{ matrix.run-tests }}
run: |
chmod +x ./godot-artifacts/godot.linuxbsd.editor.x86_64.mono
./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 && (../../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@v3
with:
@@ -168,7 +149,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
submodules: recursive
@@ -192,7 +173,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
submodules: recursive
@@ -216,7 +197,7 @@ jobs:
runs-on: windows-2019
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
submodules: recursive

View File

@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
# Azure repositories are not reliable, we need to prevent Azure giving us packages.
- name: Make apt sources.list use the default Ubuntu repositories

2
.gitignore vendored
View File

@@ -100,7 +100,7 @@ AppPackages/
# Others
sql/
*.[Cc]ache
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*

View File

@@ -37,8 +37,8 @@
# Todo
# Test build for Windows, Mac and mingw.
cmake_minimum_required(VERSION 3.12)
project(godot-cpp LANGUAGES CXX)
cmake_minimum_required(VERSION 3.12)
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)
@@ -86,7 +86,7 @@ set(GODOT_COMPILE_FLAGS )
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# using Visual Studio C++
set(GODOT_COMPILE_FLAGS "/EHsc /utf-8") # /GF /MP
set(GODOT_COMPILE_FLAGS "/EHsc") # /GF /MP
if(CMAKE_BUILD_TYPE MATCHES Debug)
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /MDd") # /Od /RTC1 /Zi

View File

@@ -2,15 +2,8 @@
> **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.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`).
> This repository's `master` branch is only usable with Godot's ([GDExtension](https://godotengine.org/article/introducing-gd-extensions))
> API (Godot 4.0 and later).
>
> For GDNative users (Godot 3.x), switch to the [`3.x`](https://github.com/godotengine/godot-cpp/tree/3.x)
> or the [`3.5`](https://github.com/godotengine/godot-cpp/tree/3.5) branch.
@@ -56,10 +49,9 @@ first-party `godot-cpp` extension.
Some compatibility breakage is to be expected as GDExtension and `godot-cpp`
get more used, documented, and critical issues get resolved. See the
[Godot issue tracker](https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aopen+label%3Atopic%3Agdextension)
and the [godot-cpp issue tracker](https://github.com/godotengine/godot/issues)
for a list of known issues, and be sure to provide feedback on issues and PRs
which affect your use of this extension.
[issue tracker](https://github.com/godotengine/godot/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
@@ -81,22 +73,21 @@ just like before.
To use the shared lib in your Godot project you'll need a `.gdextension`
file, which replaces what was the `.gdnlib` before.
See [example.gdextension](test/project/example.gdextension) used in the test project:
Follow [the example](test/demo/example.gdextension):
```ini
[configuration]
entry_symbol = "example_library_init"
compatibility_minimum = "4.1"
[libraries]
macos.debug = "res://bin/libgdexample.macos.debug.framework"
macos.release = "res://bin/libgdexample.macos.release.framework"
windows.debug.x86_64 = "res://bin/libgdexample.windows.debug.x86_64.dll"
windows.release.x86_64 = "res://bin/libgdexample.windows.release.x86_64.dll"
linux.debug.x86_64 = "res://bin/libgdexample.linux.debug.x86_64.so"
linux.release.x86_64 = "res://bin/libgdexample.linux.release.x86_64.so"
macos.debug = "bin/libgdexample.macos.debug.framework"
macos.release = "bin/libgdexample.macos.release.framework"
windows.debug.x86_64 = "bin/libgdexample.windows.debug.x86_64.dll"
windows.release.x86_64 = "bin/libgdexample.windows.release.x86_64.dll"
linux.debug.x86_64 = "bin/libgdexample.linux.debug.x86_64.so"
linux.release.x86_64 = "bin/libgdexample.linux.release.x86_64.so"
# Repeat for other architectures to support arm64, rv64, etc.
```
@@ -108,8 +99,8 @@ extern "C" {
// Initialization.
GDExtensionBool GDE_EXPORT example_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
godot::GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization);
GDExtensionBool GDE_EXPORT example_library_init(const GDExtensionInterface *p_interface, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
godot::GDExtensionBinding::InitObject init_obj(p_interface, p_library, r_initialization);
init_obj.register_initializer(initialize_example_module);
init_obj.register_terminator(uninitialize_example_module);
@@ -134,10 +125,6 @@ void initialize_example_module(ModuleInitializationLevel p_level) {
Any node and resource you register will be available in the corresponding `Create...` dialog. Any class will be available to scripting as well.
## Examples and templates
## Included example
See the [godot-cpp-template](https://github.com/godotengine/godot-cpp-template) project for a
generic reusable template.
Or checkout the code for the [Summator example](https://github.com/paddy-exe/GDExtensionSummator)
as shown in the [official documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/gdextension/gdextension_cpp_example.html).
Check the project in the `test` folder for an example on how to use and register different things.

View File

@@ -5,19 +5,73 @@ import platform
import sys
import subprocess
from binding_generator import scons_generate_bindings, scons_emit_files
from SCons.Errors import UserError
EnsureSConsVersion(4, 0)
try:
Import("env")
except:
# Default tools with no platform defaults to gnu toolchain.
# We apply platform specific toolchains via our custom tools.
env = Environment(tools=["default"], PLATFORM="")
def add_sources(sources, dir, extension):
for f in os.listdir(dir):
if f.endswith("." + extension):
sources.append(dir + "/" + f)
env.PrependENVPath("PATH", os.getenv("PATH"))
def normalize_path(val):
return val if os.path.isabs(val) else os.path.join(env.Dir("#").abspath, val)
def validate_api_file(key, val, env):
if not os.path.isfile(normalize_path(val)):
raise UserError("GDExtension API file ('%s') does not exist: %s" % (key, val))
def validate_gdextension_dir(key, val, env):
if not os.path.isdir(normalize_path(val)):
raise UserError("GDExtension directory ('%s') does not exist: %s" % (key, val))
def get_gdextension_dir(env):
return normalize_path(env.get("gdextension_dir", env.Dir("gdextension").abspath))
def get_api_file(env):
return normalize_path(env.get("custom_api_file", os.path.join(get_gdextension_dir(env), "extension_api.json")))
# Try to detect the host platform automatically.
# This is used if no `platform` argument is passed
if sys.platform.startswith("linux"):
default_platform = "linux"
elif sys.platform == "darwin":
default_platform = "macos"
elif sys.platform == "win32" or sys.platform == "msys":
default_platform = "windows"
elif ARGUMENTS.get("platform", ""):
default_platform = ARGUMENTS.get("platform")
else:
raise ValueError("Could not detect platform automatically, please specify with platform=<platform>")
# Default tools with no platform defaults to gnu toolchain.
# We apply platform specific toolchains via our custom tools.
env = Environment(tools=["default"], PLATFORM="")
# Default num_jobs to local cpu count if not user specified.
# SCons has a peculiarity where user-specified options won't be overridden
# by SetOption, so we can rely on this to know if we should use our default.
initial_num_jobs = env.GetOption("num_jobs")
altered_num_jobs = initial_num_jobs + 1
env.SetOption("num_jobs", altered_num_jobs)
if env.GetOption("num_jobs") == altered_num_jobs:
cpu_count = os.cpu_count()
if cpu_count is None:
print("Couldn't auto-detect CPU count to configure build parallelism. Specify it with the -j argument.")
else:
safer_cpu_count = cpu_count if cpu_count <= 4 else cpu_count - 1
print(
"Auto-detected %d CPU cores available for build parallelism. Using %d cores by default. You can override it with the -j argument."
% (cpu_count, safer_cpu_count)
)
env.SetOption("num_jobs", safer_cpu_count)
# Custom options and profile flags.
customs = ["custom.py"]
@@ -28,12 +82,113 @@ if profile:
elif os.path.isfile(profile + ".py"):
customs.append(profile + ".py")
opts = Variables(customs, ARGUMENTS)
cpp_tool = Tool("godotcpp", toolpath=["tools"])
cpp_tool.options(opts, env)
opts.Update(env)
platforms = ("linux", "macos", "windows", "android", "ios", "javascript")
opts.Add(
EnumVariable(
"platform",
"Target platform",
default_platform,
allowed_values=platforms,
ignorecase=2,
)
)
# Editor and template_debug are compatible (i.e. you can use the same binary for Godot editor builds and Godot debug templates).
# Godot release templates are only compatible with "template_release" builds.
# For this reason, we default to template_debug builds, unlike Godot which defaults to editor builds.
opts.Add(
EnumVariable("target", "Compilation target", "template_debug", ("editor", "template_release", "template_debug"))
)
opts.Add(
PathVariable(
"gdextension_dir",
"Path to a custom directory containing GDExtension interface header and API JSON file",
None,
validate_gdextension_dir,
)
)
opts.Add(
PathVariable(
"custom_api_file",
"Path to a custom GDExtension API JSON file (takes precedence over `gdextension_dir`)",
None,
validate_api_file,
)
)
opts.Add(
BoolVariable("generate_bindings", "Force GDExtension API bindings generation. Auto-detected by default.", False)
)
opts.Add(BoolVariable("generate_template_get_node", "Generate a template version of the Node class's get_node.", True))
opts.Add(BoolVariable("build_library", "Build the godot-cpp library.", True))
opts.Add(EnumVariable("precision", "Set the floating-point precision level", "single", ("single", "double")))
# Add platform options
tools = {}
for pl in platforms:
tool = Tool(pl, toolpath=["tools"])
if hasattr(tool, "options"):
tool.options(opts)
tools[pl] = tool
# CPU architecture options.
architecture_array = ["", "universal", "x86_32", "x86_64", "arm32", "arm64", "rv64", "ppc32", "ppc64", "wasm32"]
architecture_aliases = {
"x64": "x86_64",
"amd64": "x86_64",
"armv7": "arm32",
"armv8": "arm64",
"arm64v8": "arm64",
"aarch64": "arm64",
"rv": "rv64",
"riscv": "rv64",
"riscv64": "rv64",
"ppcle": "ppc32",
"ppc": "ppc32",
"ppc64le": "ppc64",
}
opts.Add(EnumVariable("arch", "CPU architecture", "", architecture_array, architecture_aliases))
# Targets flags tool (optimizations, debug symbols)
target_tool = Tool("targets", toolpath=["tools"])
target_tool.options(opts)
opts.Update(env)
Help(opts.GenerateHelpText(env))
# Process CPU architecture argument.
if env["arch"] == "":
# No architecture specified. Default to arm64 if building for Android,
# universal if building for macOS or iOS, wasm32 if building for web,
# otherwise default to the host architecture.
if env["platform"] in ["macos", "ios"]:
env["arch"] = "universal"
elif env["platform"] == "android":
env["arch"] = "arm64"
elif env["platform"] == "javascript":
env["arch"] = "wasm32"
else:
host_machine = platform.machine().lower()
if host_machine in architecture_array:
env["arch"] = host_machine
elif host_machine in architecture_aliases.keys():
env["arch"] = architecture_aliases[host_machine]
elif "86" in host_machine:
# Catches x86, i386, i486, i586, i686, etc.
env["arch"] = "x86_32"
else:
print("Unsupported CPU architecture: " + host_machine)
Exit()
tool = Tool(env["platform"], toolpath=["tools"])
if tool is None or not tool.exists(env):
raise ValueError("Required toolchain not found for platform " + env["platform"])
tool.generate(env)
target_tool.generate(env)
# Detect and print a warning listing unknown SCons variables to ease troubleshooting.
unknown = opts.UnknownVariables()
if unknown:
@@ -41,12 +196,66 @@ if unknown:
for item in unknown.items():
print(" " + item[0] + "=" + item[1])
print("Building for architecture " + env["arch"] + " on platform " + env["platform"])
# Require C++17
if env.get("is_msvc", False):
env.Append(CXXFLAGS=["/std:c++17"])
else:
env.Append(CXXFLAGS=["-std=c++17"])
if env["precision"] == "double":
env.Append(CPPDEFINES=["REAL_T_IS_DOUBLE"])
# Generate bindings
env.Append(BUILDERS={"GenerateBindings": Builder(action=scons_generate_bindings, emitter=scons_emit_files)})
bindings = env.GenerateBindings(
env.Dir("."),
[get_api_file(env), os.path.join(get_gdextension_dir(env), "gdextension_interface.h"), "binding_generator.py"],
)
scons_cache_path = os.environ.get("SCONS_CACHE")
if scons_cache_path is not None:
CacheDir(scons_cache_path)
Decider("MD5")
cpp_tool.generate(env)
library = env.GodotCPP()
# Forces bindings regeneration.
if env["generate_bindings"]:
AlwaysBuild(bindings)
NoCache(bindings)
# Includes
env.Append(CPPPATH=[[env.Dir(d) for d in [get_gdextension_dir(env), "include", os.path.join("gen", "include")]]])
# Sources to compile
sources = []
add_sources(sources, "src", "cpp")
add_sources(sources, "src/classes", "cpp")
add_sources(sources, "src/core", "cpp")
add_sources(sources, "src/variant", "cpp")
sources.extend([f for f in bindings if str(f).endswith(".cpp")])
suffix = ".{}.{}".format(env["platform"], env["target"])
if env.dev_build:
suffix += ".dev"
if env["precision"] == "double":
suffix += ".double"
suffix += "." + env["arch"]
if env["ios_simulator"]:
suffix += ".simulator"
# Expose it when included from another project
env["suffix"] = suffix
library = None
env["OBJSUFFIX"] = suffix + env["OBJSUFFIX"]
library_name = "libgodot-cpp{}{}".format(suffix, env["LIBSUFFIX"])
if env["build_library"]:
library = env.StaticLibrary(target=env.File("bin/%s" % library_name), source=sources)
Default(library)
env.Append(LIBPATH=[env.Dir("bin")])
env.Append(LIBS=library_name)
Return("env")

View File

@@ -66,14 +66,14 @@ def generate_wrappers(target):
txt += "\n#endif\n"
with open(target, "w", encoding="utf-8") as f:
with open(target, "w") as f:
f.write(txt)
def get_file_list(api_filepath, output_dir, headers=False, sources=False):
api = {}
files = []
with open(api_filepath, encoding="utf-8") as api_file:
with open(api_filepath) as api_file:
api = json.load(api_file)
core_gen_folder = Path(output_dir) / "gen" / "include" / "godot_cpp" / "core"
@@ -97,10 +97,9 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False):
files.append(str(source_filename.as_posix()))
for engine_class in api["classes"]:
# Generate code for the ClassDB singleton under a different name.
# TODO: Properly setup this singleton since it conflicts with ClassDB in the bindings.
if engine_class["name"] == "ClassDB":
engine_class["name"] = "ClassDBSingleton"
engine_class["alias_for"] = "ClassDB"
continue
header_filename = include_gen_folder / "classes" / (camel_to_snake(engine_class["name"]) + ".hpp")
source_filename = source_gen_folder / "classes" / (camel_to_snake(engine_class["name"]) + ".cpp")
if headers:
@@ -124,14 +123,11 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False):
include_gen_folder / "variant" / "variant_size.hpp",
include_gen_folder / "classes" / "global_constants.hpp",
include_gen_folder / "classes" / "global_constants_binds.hpp",
include_gen_folder / "core" / "version.hpp",
]:
files.append(str(path.as_posix()))
if sources:
utility_functions_source_path = source_gen_folder / "variant" / "utility_functions.cpp"
files.append(str(utility_functions_source_path.as_posix()))
register_engine_classes_source_path = source_gen_folder / "register_engine_classes.cpp"
files.append(str(register_engine_classes_source_path.as_posix()))
return files
@@ -165,7 +161,7 @@ def generate_bindings(api_filepath, use_template_get_node, bits="64", precision=
target_dir = Path(output_dir) / "gen"
with open(api_filepath, encoding="utf-8") as api_file:
with open(api_filepath) as api_file:
api = json.load(api_file)
shutil.rmtree(target_dir, ignore_errors=True)
@@ -175,7 +171,6 @@ def generate_bindings(api_filepath, use_template_get_node, bits="64", precision=
print("Built-in type config: " + real_t + "_" + bits)
generate_global_constants(api, target_dir)
generate_version_header(api, target_dir)
generate_global_constant_binds(api, target_dir)
generate_builtin_bindings(api, target_dir, real_t + "_" + bits)
generate_engine_classes_bindings(api, target_dir, use_template_get_node)
@@ -222,7 +217,7 @@ def generate_builtin_bindings(api, output_dir, build_config):
# Create a file for Variant size, since that class isn't generated.
variant_size_filename = include_gen_folder / "variant_size.hpp"
with variant_size_filename.open("+w", encoding="utf-8") as variant_size_file:
with variant_size_filename.open("+w") as variant_size_file:
variant_size_source = []
add_header("variant_size.hpp", variant_size_source)
@@ -298,15 +293,15 @@ def generate_builtin_bindings(api, output_dir, build_config):
fully_used_classes = list(fully_used_classes)
fully_used_classes.sort()
with header_filename.open("w+", encoding="utf-8") as header_file:
with header_filename.open("w+") as header_file:
header_file.write(generate_builtin_class_header(builtin_api, size, used_classes, fully_used_classes))
with source_filename.open("w+", encoding="utf-8") as source_file:
with source_filename.open("w+") as source_file:
source_file.write(generate_builtin_class_source(builtin_api, size, used_classes, fully_used_classes))
# Create a header with all builtin types for convenience.
builtin_header_filename = include_gen_folder / "builtin_types.hpp"
with builtin_header_filename.open("w+", encoding="utf-8") as builtin_header_file:
with builtin_header_filename.open("w+") as builtin_header_file:
builtin_header = []
add_header("builtin_types.hpp", builtin_header)
@@ -326,7 +321,7 @@ def generate_builtin_bindings(api, output_dir, build_config):
# Create a header with bindings for builtin types.
builtin_binds_filename = include_gen_folder / "builtin_binds.hpp"
with builtin_binds_filename.open("w+", encoding="utf-8") as builtin_binds_file:
with builtin_binds_filename.open("w+") as builtin_binds_file:
builtin_binds = []
add_header("builtin_binds.hpp", builtin_binds)
@@ -777,12 +772,12 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl
if "constructors" in builtin_api:
for constructor in builtin_api["constructors"]:
result.append(
f'\t_method_bindings.constructor_{constructor["index"]} = internal::gdextension_interface_variant_get_ptr_constructor({enum_type_name}, {constructor["index"]});'
f'\t_method_bindings.constructor_{constructor["index"]} = internal::gde_interface->variant_get_ptr_constructor({enum_type_name}, {constructor["index"]});'
)
if builtin_api["has_destructor"]:
result.append(
f"\t_method_bindings.destructor = internal::gdextension_interface_variant_get_ptr_destructor({enum_type_name});"
f"\t_method_bindings.destructor = internal::gde_interface->variant_get_ptr_destructor({enum_type_name});"
)
result.append("}")
@@ -794,43 +789,43 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl
result.append("\tString::_init_bindings_constructors_destructor();")
result.append(f"\t{class_name}::_init_bindings_constructors_destructor();")
result.append("\tStringName _gde_name;")
result.append("\tStringName __name;")
if "methods" in builtin_api:
for method in builtin_api["methods"]:
# TODO: Add error check for hash mismatch.
result.append(f'\t_gde_name = StringName("{method["name"]}");')
result.append(f'\t__name = StringName("{method["name"]}");')
result.append(
f'\t_method_bindings.method_{method["name"]} = internal::gdextension_interface_variant_get_ptr_builtin_method({enum_type_name}, _gde_name._native_ptr(), {method["hash"]});'
f'\t_method_bindings.method_{method["name"]} = internal::gde_interface->variant_get_ptr_builtin_method({enum_type_name}, __name._native_ptr(), {method["hash"]});'
)
if "members" in builtin_api:
for member in builtin_api["members"]:
result.append(f'\t_gde_name = StringName("{member["name"]}");')
result.append(f'\t__name = StringName("{member["name"]}");')
result.append(
f'\t_method_bindings.member_{member["name"]}_setter = internal::gdextension_interface_variant_get_ptr_setter({enum_type_name}, _gde_name._native_ptr());'
f'\t_method_bindings.member_{member["name"]}_setter = internal::gde_interface->variant_get_ptr_setter({enum_type_name}, __name._native_ptr());'
)
result.append(
f'\t_method_bindings.member_{member["name"]}_getter = internal::gdextension_interface_variant_get_ptr_getter({enum_type_name}, _gde_name._native_ptr());'
f'\t_method_bindings.member_{member["name"]}_getter = internal::gde_interface->variant_get_ptr_getter({enum_type_name}, __name._native_ptr());'
)
if "indexing_return_type" in builtin_api:
result.append(
f"\t_method_bindings.indexed_setter = internal::gdextension_interface_variant_get_ptr_indexed_setter({enum_type_name});"
f"\t_method_bindings.indexed_setter = internal::gde_interface->variant_get_ptr_indexed_setter({enum_type_name});"
)
result.append(
f"\t_method_bindings.indexed_getter = internal::gdextension_interface_variant_get_ptr_indexed_getter({enum_type_name});"
f"\t_method_bindings.indexed_getter = internal::gde_interface->variant_get_ptr_indexed_getter({enum_type_name});"
)
if "is_keyed" in builtin_api and builtin_api["is_keyed"]:
result.append(
f"\t_method_bindings.keyed_setter = internal::gdextension_interface_variant_get_ptr_keyed_setter({enum_type_name});"
f"\t_method_bindings.keyed_setter = internal::gde_interface->variant_get_ptr_keyed_setter({enum_type_name});"
)
result.append(
f"\t_method_bindings.keyed_getter = internal::gdextension_interface_variant_get_ptr_keyed_getter({enum_type_name});"
f"\t_method_bindings.keyed_getter = internal::gde_interface->variant_get_ptr_keyed_getter({enum_type_name});"
)
result.append(
f"\t_method_bindings.keyed_checker = internal::gdextension_interface_variant_get_ptr_keyed_checker({enum_type_name});"
f"\t_method_bindings.keyed_checker = internal::gde_interface->variant_get_ptr_keyed_checker({enum_type_name});"
)
if "operators" in builtin_api:
@@ -843,11 +838,11 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl
f"GDEXTENSION_VARIANT_TYPE_{camel_to_snake(operator['right_type']).upper()}"
)
result.append(
f'\t_method_bindings.operator_{get_operator_id_name(operator["name"])}_{operator["right_type"]} = internal::gdextension_interface_variant_get_ptr_operator_evaluator(GDEXTENSION_VARIANT_OP_{get_operator_id_name(operator["name"]).upper()}, {enum_type_name}, {right_type_variant_type});'
f'\t_method_bindings.operator_{get_operator_id_name(operator["name"])}_{operator["right_type"]} = internal::gde_interface->variant_get_ptr_operator_evaluator(GDEXTENSION_VARIANT_OP_{get_operator_id_name(operator["name"]).upper()}, {enum_type_name}, {right_type_variant_type});'
)
else:
result.append(
f'\t_method_bindings.operator_{get_operator_id_name(operator["name"])} = internal::gdextension_interface_variant_get_ptr_operator_evaluator(GDEXTENSION_VARIANT_OP_{get_operator_id_name(operator["name"]).upper()}, {enum_type_name}, GDEXTENSION_VARIANT_TYPE_NIL);'
f'\t_method_bindings.operator_{get_operator_id_name(operator["name"])} = internal::gde_interface->variant_get_ptr_operator_evaluator(GDEXTENSION_VARIANT_OP_{get_operator_id_name(operator["name"]).upper()}, {enum_type_name}, GDEXTENSION_VARIANT_TYPE_NIL);'
)
result.append("}")
@@ -1039,23 +1034,21 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
# First create map of classes and singletons.
for class_api in api["classes"]:
# Generate code for the ClassDB singleton under a different name.
# TODO: Properly setup this singleton since it conflicts with ClassDB in the bindings.
if class_api["name"] == "ClassDB":
class_api["name"] = "ClassDBSingleton"
class_api["alias_for"] = "ClassDB"
continue
engine_classes[class_api["name"]] = class_api["is_refcounted"]
for native_struct in api["native_structures"]:
engine_classes[native_struct["name"]] = False
native_structures.append(native_struct["name"])
for singleton in api["singletons"]:
# Generate code for the ClassDB singleton under a different name.
if singleton["name"] == "ClassDB":
singleton["name"] = "ClassDBSingleton"
singleton["alias_for"] = "ClassDB"
singletons.append(singleton["name"])
for class_api in api["classes"]:
# TODO: Properly setup this singleton since it conflicts with ClassDB in the bindings.
if class_api["name"] == "ClassDB":
continue
# Check used classes for header include.
used_classes = set()
fully_used_classes = set()
@@ -1145,12 +1138,6 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
else:
fully_used_classes.add("Wrapped")
# In order to ensure that PtrToArg specializations for native structs are
# always used, let's move any of them into 'fully_used_classes'.
for type_name in used_classes:
if is_struct_type(type_name) and not is_included_struct_type(type_name):
fully_used_classes.add(type_name)
for type_name in fully_used_classes:
if type_name in used_classes:
used_classes.remove(type_name)
@@ -1160,20 +1147,16 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
fully_used_classes = list(fully_used_classes)
fully_used_classes.sort()
with header_filename.open("w+", encoding="utf-8") as header_file:
with header_filename.open("w+") as header_file:
header_file.write(
generate_engine_class_header(class_api, used_classes, fully_used_classes, use_template_get_node)
)
with source_filename.open("w+", encoding="utf-8") as source_file:
with source_filename.open("w+") as source_file:
source_file.write(
generate_engine_class_source(class_api, used_classes, fully_used_classes, use_template_get_node)
)
register_engine_classes_filename = Path(output_dir) / "src" / "register_engine_classes.cpp"
with register_engine_classes_filename.open("w+", encoding="utf-8") as source_file:
source_file.write(generate_register_engine_classes_source(api))
for native_struct in api["native_structures"]:
struct_name = native_struct["name"]
snake_struct_name = camel_to_snake(struct_name)
@@ -1200,9 +1183,8 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
for included in used_classes:
result.append(f"#include <godot_cpp/{get_include_path(included)}>")
if len(used_classes) == 0:
result.append("#include <godot_cpp/core/method_ptrcall.hpp>")
result.append("")
if len(used_classes) > 0:
result.append("")
result.append("namespace godot {")
result.append("")
@@ -1220,7 +1202,7 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
result.append("")
result.append(f"#endif // ! {header_guard}")
with header_filename.open("w+", encoding="utf-8") as header_file:
with header_filename.open("w+") as header_file:
header_file.write("\n".join(result))
@@ -1247,13 +1229,10 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
else:
result.append(f"#include <godot_cpp/{get_include_path(included)}>")
if class_name == "EditorPlugin":
result.append("#include <godot_cpp/templates/vector.hpp>")
if len(fully_used_classes) > 0:
result.append("")
if class_name != "Object" and class_name != "ClassDBSingleton":
if class_name != "Object":
result.append("#include <godot_cpp/core/class_db.hpp>")
result.append("")
result.append("#include <type_traits>")
@@ -1274,10 +1253,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
inherits = class_api["inherits"] if "inherits" in class_api else "Wrapped"
result.append(f"class {class_name} : public {inherits} {{")
if "alias_for" in class_api:
result.append(f"\tGDEXTENSION_CLASS_ALIAS({class_name}, {class_api['alias_for']}, {inherits})")
else:
result.append(f"\tGDEXTENSION_CLASS({class_name}, {inherits})")
result.append(f"\tGDEXTENSION_CLASS({class_name}, {inherits})")
result.append("")
result.append("public:")
@@ -1400,30 +1376,6 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
result.append("};")
result.append("")
if class_name == "EditorPlugin":
result.append("class EditorPlugins {")
result.append("private:")
result.append("\tstatic Vector<StringName> plugin_classes;")
result.append("")
result.append("public:")
result.append("\tstatic void add_plugin_class(const StringName &p_class_name);")
result.append("\tstatic void remove_plugin_class(const StringName &p_class_name);")
result.append("\tstatic void deinitialize(GDExtensionInitializationLevel p_level);")
result.append("")
result.append("\ttemplate <class T>")
result.append("\tstatic void add_by_type() {")
result.append("\t\tadd_plugin_class(T::get_class_static());")
result.append("\t}")
result.append("\ttemplate <class T>")
result.append("\tstatic void remove_by_type() {")
result.append("\t\tremove_plugin_class(T::get_class_static());")
result.append("\t}")
result.append("};")
result.append("")
result.append("} // namespace godot")
result.append("")
@@ -1435,51 +1387,6 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
result.append(f'VARIANT_ENUM_CAST({class_name}::{enum_api["name"]});')
result.append("")
if class_name == "ClassDBSingleton":
result.append("#define CLASSDB_SINGLETON_FORWARD_METHODS \\")
for method in class_api["methods"]:
# ClassDBSingleton shouldn't have any static or vararg methods, but if some appear later, lets skip them.
if vararg:
continue
if "is_static" in method and method["is_static"]:
continue
method_signature = "\tstatic "
if "return_type" in method:
method_signature += f'{correct_type(method["return_type"])} '
elif "return_value" in method:
method_signature += (
correct_type(method["return_value"]["type"], method["return_value"].get("meta", None)) + " "
)
else:
method_signature += "void "
method_signature += f'{method["name"]}('
method_arguments = []
if "arguments" in method:
method_arguments = method["arguments"]
method_signature += make_function_parameters(
method_arguments, include_default=True, for_builtin=True, is_vararg=False
)
method_signature += ") { \\"
result.append(method_signature)
method_body = "\t\t"
if "return_type" in method or "return_value" in method:
method_body += "return "
method_body += f'ClassDBSingleton::get_singleton()->{method["name"]}('
method_body += ", ".join(map(lambda x: escape_identifier(x["name"]), method_arguments))
method_body += "); \\"
result.append(method_body)
result.append("\t} \\")
result.append("\t;")
result.append("")
result.append(f"#endif // ! {header_guard}")
return "\n".join(result)
@@ -1512,22 +1419,16 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
if is_singleton:
result.append(f"{class_name} *{class_name}::get_singleton() {{")
# We assume multi-threaded access is OK because each assignment will assign the same value every time
result.append(f"\tstatic {class_name} *singleton = nullptr;")
result.append("\tif (unlikely(singleton == nullptr)) {")
result.append(f"\tconst StringName __class_name = {class_name}::get_class_static();")
result.append(
f"\t\tGDExtensionObjectPtr singleton_obj = internal::gdextension_interface_global_get_singleton({class_name}::get_class_static()._native_ptr());"
"\tstatic GDExtensionObjectPtr singleton_obj = internal::gde_interface->global_get_singleton(__class_name._native_ptr());"
)
result.append("#ifdef DEBUG_ENABLED")
result.append("\t\tERR_FAIL_COND_V(singleton_obj == nullptr, nullptr);")
result.append("\tERR_FAIL_COND_V(singleton_obj == nullptr, nullptr);")
result.append("#endif // DEBUG_ENABLED")
result.append(
f"\t\tsingleton = reinterpret_cast<{class_name} *>(internal::gdextension_interface_object_get_instance_binding(singleton_obj, internal::token, &{class_name}::_gde_binding_callbacks));"
f"\tstatic {class_name} *singleton = reinterpret_cast<{class_name} *>(internal::gde_interface->object_get_instance_binding(singleton_obj, internal::token, &{class_name}::___binding_callbacks));"
)
result.append("#ifdef DEBUG_ENABLED")
result.append("\t\tERR_FAIL_COND_V(singleton == nullptr, nullptr);")
result.append("#endif // DEBUG_ENABLED")
result.append("\t}")
result.append("\treturn singleton;")
result.append("}")
result.append("")
@@ -1545,18 +1446,20 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
result.append(method_signature + " {")
# Method body.
result.append(f"\tconst StringName __class_name = {class_name}::get_class_static();")
result.append(f'\tconst StringName __method_name = "{method["name"]}";')
result.append(
f'\tstatic GDExtensionMethodBindPtr _gde_method_bind = internal::gdextension_interface_classdb_get_method_bind({class_name}::get_class_static()._native_ptr(), StringName("{method["name"]}")._native_ptr(), {method["hash"]});'
f'\tstatic GDExtensionMethodBindPtr ___method_bind = internal::gde_interface->classdb_get_method_bind(__class_name._native_ptr(), __method_name._native_ptr(), {method["hash"]});'
)
method_call = "\t"
has_return = "return_value" in method and method["return_value"]["type"] != "void"
if has_return:
result.append(
f'\tCHECK_METHOD_BIND_RET(_gde_method_bind, {get_default_value_for_type(method["return_value"]["type"])});'
f'\tCHECK_METHOD_BIND_RET(___method_bind, {get_default_value_for_type(method["return_value"]["type"])});'
)
else:
result.append("\tCHECK_METHOD_BIND(_gde_method_bind);")
result.append("\tCHECK_METHOD_BIND(___method_bind);")
is_ref = False
if not vararg:
@@ -1565,34 +1468,34 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
meta_type = method["return_value"]["meta"] if "meta" in method["return_value"] else None
if is_enum(return_type):
if method["is_static"]:
method_call += f"return ({get_gdextension_type(correct_type(return_type, meta_type))})internal::_call_native_mb_ret<int64_t>(_gde_method_bind, nullptr"
method_call += f"return ({get_gdextension_type(correct_type(return_type, meta_type))})internal::_call_native_mb_ret<int64_t>(___method_bind, nullptr"
else:
method_call += f"return ({get_gdextension_type(correct_type(return_type, meta_type))})internal::_call_native_mb_ret<int64_t>(_gde_method_bind, _owner"
method_call += f"return ({get_gdextension_type(correct_type(return_type, meta_type))})internal::_call_native_mb_ret<int64_t>(___method_bind, _owner"
elif is_pod_type(return_type) or is_variant(return_type):
if method["is_static"]:
method_call += f"return internal::_call_native_mb_ret<{get_gdextension_type(correct_type(return_type, meta_type))}>(_gde_method_bind, nullptr"
method_call += f"return internal::_call_native_mb_ret<{get_gdextension_type(correct_type(return_type, meta_type))}>(___method_bind, nullptr"
else:
method_call += f"return internal::_call_native_mb_ret<{get_gdextension_type(correct_type(return_type, meta_type))}>(_gde_method_bind, _owner"
method_call += f"return internal::_call_native_mb_ret<{get_gdextension_type(correct_type(return_type, meta_type))}>(___method_bind, _owner"
elif is_refcounted(return_type):
if method["is_static"]:
method_call += f"return Ref<{return_type}>::_gde_internal_constructor(internal::_call_native_mb_ret_obj<{return_type}>(_gde_method_bind, nullptr"
method_call += f"return Ref<{return_type}>::___internal_constructor(internal::_call_native_mb_ret_obj<{return_type}>(___method_bind, nullptr"
else:
method_call += f"return Ref<{return_type}>::_gde_internal_constructor(internal::_call_native_mb_ret_obj<{return_type}>(_gde_method_bind, _owner"
method_call += f"return Ref<{return_type}>::___internal_constructor(internal::_call_native_mb_ret_obj<{return_type}>(___method_bind, _owner"
is_ref = True
else:
if method["is_static"]:
method_call += (
f"return internal::_call_native_mb_ret_obj<{return_type}>(_gde_method_bind, nullptr"
f"return internal::_call_native_mb_ret_obj<{return_type}>(___method_bind, nullptr"
)
else:
method_call += (
f"return internal::_call_native_mb_ret_obj<{return_type}>(_gde_method_bind, _owner"
f"return internal::_call_native_mb_ret_obj<{return_type}>(___method_bind, _owner"
)
else:
if method["is_static"]:
method_call += "internal::_call_native_mb_no_ret(_gde_method_bind, nullptr"
method_call += "internal::_call_native_mb_no_ret(___method_bind, nullptr"
else:
method_call += "internal::_call_native_mb_no_ret(_gde_method_bind, _owner"
method_call += "internal::_call_native_mb_no_ret(___method_bind, _owner"
if "arguments" in method:
method_call += ", "
@@ -1609,7 +1512,7 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
else: # vararg.
result.append("\tGDExtensionCallError error;")
result.append("\tVariant ret;")
method_call += "internal::gdextension_interface_object_method_bind_call(_gde_method_bind, _owner, reinterpret_cast<GDExtensionConstVariantPtr *>(args), arg_count, &ret, &error"
method_call += "internal::gde_interface->object_method_bind_call(___method_bind, _owner, reinterpret_cast<GDExtensionConstVariantPtr *>(args), arg_count, &ret, &error"
if is_ref:
method_call += ")" # Close Ref<> constructor.
@@ -1648,38 +1551,6 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
return "\n".join(result)
def generate_register_engine_classes_source(api):
includes = []
registrations = []
for class_api in api["classes"]:
if class_api["name"] == "ClassDB":
continue
class_name = class_api["name"]
snake_class_name = camel_to_snake(class_name)
includes.append(f"#include <godot_cpp/classes/{snake_class_name}.hpp>")
registrations.append(f"\tClassDB::register_engine_class<{class_name}>();")
result = []
add_header(f"register_engine_classes.cpp", result)
result.append("#include <godot_cpp/godot.hpp>")
result.append("")
result = result + includes
result.append("")
result.append("namespace godot {")
result.append("")
result.append("void GDExtensionBinding::register_engine_classes() {")
result = result + registrations
result.append("}")
result.append("")
result.append("} // namespace godot ")
return "\n".join(result)
def generate_global_constants(api, output_dir):
include_gen_folder = Path(output_dir) / "include" / "godot_cpp" / "classes"
source_gen_folder = Path(output_dir) / "src" / "classes"
@@ -1721,36 +1592,7 @@ def generate_global_constants(api, output_dir):
header.append("")
header.append(f"#endif // ! {header_guard}")
with header_filename.open("w+", encoding="utf-8") as header_file:
header_file.write("\n".join(header))
def generate_version_header(api, output_dir):
header = []
header_filename = "version.hpp"
add_header(header_filename, header)
include_gen_folder = Path(output_dir) / "include" / "godot_cpp" / "core"
include_gen_folder.mkdir(parents=True, exist_ok=True)
header_file_path = include_gen_folder / header_filename
header_guard = "GODOT_CPP_VERSION_HPP"
header.append(f"#ifndef {header_guard}")
header.append(f"#define {header_guard}")
header.append("")
header.append(f"#define GODOT_VERSION_MAJOR {api['header']['version_major']}")
header.append(f"#define GODOT_VERSION_MINOR {api['header']['version_minor']}")
header.append(f"#define GODOT_VERSION_PATCH {api['header']['version_patch']}")
header.append(f"#define GODOT_VERSION_STATUS \"{api['header']['version_status']}\"")
header.append(f"#define GODOT_VERSION_BUILD \"{api['header']['version_build']}\"")
header.append("")
header.append(f"#endif // {header_guard}")
header.append("")
with header_file_path.open("w+", encoding="utf-8") as header_file:
with header_filename.open("w+") as header_file:
header_file.write("\n".join(header))
@@ -1791,7 +1633,7 @@ def generate_global_constant_binds(api, output_dir):
header.append(f"#endif // ! {header_guard}")
with header_filename.open("w+", encoding="utf-8") as header_file:
with header_filename.open("w+") as header_file:
header_file.write("\n".join(header))
@@ -1840,7 +1682,7 @@ def generate_utility_functions(api, output_dir):
header.append("")
header.append(f"#endif // ! {header_guard}")
with header_filename.open("w+", encoding="utf-8") as header_file:
with header_filename.open("w+") as header_file:
header_file.write("\n".join(header))
# Generate source.
@@ -1865,27 +1707,28 @@ def generate_utility_functions(api, output_dir):
# Function body.
source.append(f'\tconst StringName __function_name = "{function["name"]}";')
source.append(
f'\tstatic GDExtensionPtrUtilityFunction _gde_function = internal::gdextension_interface_variant_get_ptr_utility_function(StringName("{function["name"]}")._native_ptr(), {function["hash"]});'
f'\tstatic GDExtensionPtrUtilityFunction ___function = internal::gde_interface->variant_get_ptr_utility_function(__function_name._native_ptr(), {function["hash"]});'
)
has_return = "return_type" in function and function["return_type"] != "void"
if has_return:
source.append(
f'\tCHECK_METHOD_BIND_RET(_gde_function, {get_default_value_for_type(function["return_type"])});'
f'\tCHECK_METHOD_BIND_RET(___function, {get_default_value_for_type(function["return_type"])});'
)
else:
source.append("\tCHECK_METHOD_BIND(_gde_function);")
source.append("\tCHECK_METHOD_BIND(___function);")
function_call = "\t"
if not vararg:
if has_return:
function_call += "return "
if function["return_type"] == "Object":
function_call += "internal::_call_utility_ret_obj(_gde_function"
function_call += "internal::_call_utility_ret_obj(___function"
else:
function_call += f'internal::_call_utility_ret<{get_gdextension_type(correct_type(function["return_type"]))}>(_gde_function'
function_call += f'internal::_call_utility_ret<{get_gdextension_type(correct_type(function["return_type"]))}>(___function'
else:
function_call += "internal::_call_utility_no_ret(_gde_function"
function_call += "internal::_call_utility_no_ret(___function"
if "arguments" in function:
function_call += ", "
@@ -1900,11 +1743,8 @@ def generate_utility_functions(api, output_dir):
arguments.append(arg_name)
function_call += ", ".join(arguments)
else:
if has_return:
source.append(f'\t{get_gdextension_type(correct_type(function["return_type"]))} ret;')
else:
source.append("\tVariant ret;")
function_call += "_gde_function(&ret, reinterpret_cast<GDExtensionConstVariantPtr *>(args), arg_count"
source.append("\tVariant ret;")
function_call += "___function(&ret, reinterpret_cast<GDExtensionConstVariantPtr *>(args), arg_count"
function_call += ");"
source.append(function_call)
@@ -1917,7 +1757,7 @@ def generate_utility_functions(api, output_dir):
source.append("} // namespace godot")
with source_filename.open("w+", encoding="utf-8") as source_file:
with source_filename.open("w+") as source_file:
source_file.write("\n".join(source))
@@ -1991,7 +1831,7 @@ def get_encoded_arg(arg_name, type_name, type_meta):
elif is_engine_class(type_name):
# `{name}` is a C++ wrapper, it contains a field which is the object's pointer Godot expects.
# We have to check `nullptr` because when the caller sends `nullptr`, the wrapper itself will be null.
name = f"({name} != nullptr ? &{name}->_owner : nullptr)"
name = f"({name} != nullptr ? {name}->_owner : nullptr)"
else:
name = f"&{name}"
@@ -2376,7 +2216,6 @@ def escape_identifier(id):
"operator": "_operator",
"typeof": "type_of",
"typename": "type_name",
"enum": "_enum",
}
if id in cpp_keywords_map:
return cpp_keywords_map[id]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -88,15 +88,26 @@ public:
return reference != p_r.reference;
}
_FORCE_INLINE_ T *operator*() const {
_FORCE_INLINE_ T *operator->() {
return reference;
}
_FORCE_INLINE_ T *operator->() const {
_FORCE_INLINE_ T *operator*() {
return reference;
}
_FORCE_INLINE_ T *ptr() const {
_FORCE_INLINE_ const T *operator->() const {
return reference;
}
_FORCE_INLINE_ const T *ptr() const {
return reference;
}
_FORCE_INLINE_ T *ptr() {
return reference;
}
_FORCE_INLINE_ const T *operator*() const {
return reference;
}
@@ -219,7 +230,7 @@ public:
// Used exclusively in the bindings to recreate the Ref Godot encapsulates in return values,
// without adding to the refcount.
inline static Ref<T> _gde_internal_constructor(Object *obj) {
inline static Ref<T> ___internal_constructor(Object *obj) {
Ref<T> r;
r.reference = (T *)obj;
return r;
@@ -230,8 +241,10 @@ template <class T>
struct PtrToArg<Ref<T>> {
_FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
GDExtensionRefPtr ref = (GDExtensionRefPtr)p_ptr;
ERR_FAIL_NULL_V(p_ptr, Ref<T>());
return Ref<T>(reinterpret_cast<T *>(godot::internal::get_object_instance_binding(godot::internal::gdextension_interface_ref_get_object(ref))));
ERR_FAIL_NULL_V(ref, Ref<T>());
T *obj = reinterpret_cast<T *>(godot::internal::gde_interface->object_get_instance_binding(godot::internal::gde_interface->ref_get_object(ref), godot::internal::token, &T::___binding_callbacks));
return Ref<T>(obj);
}
typedef Ref<T> EncodeT;
@@ -243,7 +256,7 @@ struct PtrToArg<Ref<T>> {
// This code assumes that p_ptr points to an unset Ref<T> variable on the Godot side
// so we only set it if we have an object to set.
if (p_val.is_valid()) {
godot::internal::gdextension_interface_ref_set_object(ref, p_val->_owner);
godot::internal::gde_interface->ref_set_object(ref, p_val->_owner);
}
}
};
@@ -253,9 +266,7 @@ struct PtrToArg<const Ref<T> &> {
typedef Ref<T> EncodeT;
_FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
GDExtensionRefPtr ref = const_cast<GDExtensionRefPtr>(p_ptr);
ERR_FAIL_NULL_V(p_ptr, Ref<T>());
return Ref<T>(reinterpret_cast<T *>(godot::internal::get_object_instance_binding(godot::internal::gdextension_interface_ref_get_object(ref))));
return Ref<T>(reinterpret_cast<T *>(godot::internal::gde_interface->object_get_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr)), godot::internal::token, &T::___binding_callbacks)));
}
};

View File

@@ -109,7 +109,7 @@ protected:
} \
\
virtual const GDExtensionInstanceBindingCallbacks *_get_bindings_callbacks() const override { \
return &_gde_binding_callbacks; \
return &___binding_callbacks; \
} \
\
static void (*_get_bind_methods())() { \
@@ -132,16 +132,16 @@ protected:
return (void(::godot::Wrapped::*)(::godot::List<::godot::PropertyInfo> * p_list) const) & m_class::_get_property_list; \
} \
\
static bool (::godot::Wrapped::*_get_property_can_revert())(const ::godot::StringName &p_name) const { \
return (bool(::godot::Wrapped::*)(const ::godot::StringName &p_name) const) & m_class::_property_can_revert; \
static bool (::godot::Wrapped::*_get_property_can_revert())(const ::godot::StringName &p_name) { \
return (bool(::godot::Wrapped::*)(const ::godot::StringName &p_name)) & m_class::_property_can_revert; \
} \
\
static bool (::godot::Wrapped::*_get_property_get_revert())(const ::godot::StringName &p_name, ::godot::Variant &) const { \
return (bool(::godot::Wrapped::*)(const ::godot::StringName &p_name, ::godot::Variant &) const) & m_class::_property_get_revert; \
static bool (::godot::Wrapped::*_get_property_get_revert())(const ::godot::StringName &p_name, ::godot::Variant &) { \
return (bool(::godot::Wrapped::*)(const ::godot::StringName &p_name, ::godot::Variant &)) & m_class::_property_get_revert; \
} \
\
static ::godot::String (::godot::Wrapped::*_get_to_string())() const { \
return (::godot::String(::godot::Wrapped::*)() const) & m_class::_to_string; \
static ::godot::String (::godot::Wrapped::*_get_to_string())() { \
return (::godot::String(::godot::Wrapped::*)()) & m_class::_to_string; \
} \
\
template <class T, class B> \
@@ -288,100 +288,97 @@ public:
} \
} \
\
static void *_gde_binding_create_callback(void *p_token, void *p_instance) { \
static void *___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 ___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 ___binding_reference_callback(void *p_token, void *p_instance, GDExtensionBool p_reference) { \
return true; \
} \
\
static constexpr GDExtensionInstanceBindingCallbacks _gde_binding_callbacks = { \
_gde_binding_create_callback, \
_gde_binding_free_callback, \
_gde_binding_reference_callback, \
static constexpr GDExtensionInstanceBindingCallbacks ___binding_callbacks = { \
___binding_create_callback, \
___binding_free_callback, \
___binding_reference_callback, \
};
// Don't use this for your classes, use GDCLASS() instead.
#define GDEXTENSION_CLASS_ALIAS(m_class, m_alias_for, m_inherits) \
private: \
void operator=(const m_class &p_rval) {} \
\
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 (*_get_bind_methods())() { \
return nullptr; \
} \
\
static void (Wrapped::*_get_notification())(int) { \
return nullptr; \
} \
\
static bool (Wrapped::*_get_set())(const ::godot::StringName &p_name, const Variant &p_property) { \
return nullptr; \
} \
\
static bool (Wrapped::*_get_get())(const ::godot::StringName &p_name, Variant &r_ret) const { \
return nullptr; \
} \
\
static void (Wrapped::*_get_get_property_list())(List<PropertyInfo> * p_list) const { \
return nullptr; \
} \
\
static bool (Wrapped::*_get_property_can_revert())(const ::godot::StringName &p_name) const { \
return nullptr; \
} \
\
static bool (Wrapped::*_get_property_get_revert())(const ::godot::StringName &p_name, Variant &) const { \
return nullptr; \
} \
\
static String (Wrapped::*_get_to_string())() const { \
return nullptr; \
} \
\
public: \
static void initialize_class() {} \
\
static ::godot::StringName &get_class_static() { \
static ::godot::StringName string_name = ::godot::StringName(#m_alias_for); \
return string_name; \
} \
\
static ::godot::StringName &get_parent_class_static() { \
return m_inherits::get_class_static(); \
} \
\
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); \
} \
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 */ \
reinterpret_cast<m_class *>(p_binding)->~m_class(); \
Memory::free_static(reinterpret_cast<m_class *>(p_binding)); \
} \
static GDExtensionBool _gde_binding_reference_callback(void *p_token, void *p_instance, GDExtensionBool p_reference) { \
return true; \
} \
static constexpr GDExtensionInstanceBindingCallbacks _gde_binding_callbacks = { \
_gde_binding_create_callback, \
_gde_binding_free_callback, \
_gde_binding_reference_callback, \
}; \
m_class() : m_class(#m_alias_for) {}
// 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 GDEXTENSION_CLASS(m_class, m_inherits) \
private: \
void operator=(const m_class &p_rval) {} \
\
protected: \
virtual const GDExtensionInstanceBindingCallbacks *_get_bindings_callbacks() const override { \
return &___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 (*_get_bind_methods())() { \
return nullptr; \
} \
\
static void (Wrapped::*_get_notification())(int) { \
return nullptr; \
} \
\
static bool (Wrapped::*_get_set())(const ::godot::StringName &p_name, const Variant &p_property) { \
return nullptr; \
} \
\
static bool (Wrapped::*_get_get())(const ::godot::StringName &p_name, Variant &r_ret) const { \
return nullptr; \
} \
\
static void (Wrapped::*_get_get_property_list())(List<PropertyInfo> * p_list) const { \
return nullptr; \
} \
\
static bool (Wrapped::*_get_property_can_revert())(const ::godot::StringName &p_name) { \
return nullptr; \
} \
\
static bool (Wrapped::*_get_property_get_revert())(const ::godot::StringName &p_name, Variant &) { \
return nullptr; \
} \
\
static String (Wrapped::*_get_to_string())() { \
return nullptr; \
} \
\
public: \
static void initialize_class() {} \
\
static ::godot::StringName &get_class_static() { \
static ::godot::StringName string_name = ::godot::StringName(#m_class); \
return string_name; \
} \
\
static ::godot::StringName &get_parent_class_static() { \
return m_inherits::get_class_static(); \
} \
\
static void *___binding_create_callback(void *p_token, void *p_instance) { \
/* Do not call memnew here, we don't want the postinitializer to be called */ \
return new ("") m_class((GodotObject *)p_instance); \
} \
static void ___binding_free_callback(void *p_token, void *p_instance, void *p_binding) { \
/* Explicitly call the deconstructor to ensure proper lifecycle for non-trivial members */ \
reinterpret_cast<m_class *>(p_binding)->~m_class(); \
Memory::free_static(reinterpret_cast<m_class *>(p_binding)); \
} \
static GDExtensionBool ___binding_reference_callback(void *p_token, void *p_instance, GDExtensionBool p_reference) { \
return true; \
} \
static constexpr GDExtensionInstanceBindingCallbacks ___binding_callbacks = { \
___binding_create_callback, \
___binding_free_callback, \
___binding_reference_callback, \
}; \
m_class() : m_class(#m_class) {}
#endif // GODOT_WRAPPED_HPP

View File

@@ -148,7 +148,7 @@ template <class T>
struct VariantCasterAndValidate {
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDExtensionCallError &r_error) {
GDExtensionVariantType argtype = GDExtensionVariantType(GetTypeInfo<T>::VARIANT_TYPE);
if (!internal::gdextension_interface_variant_can_convert_strict(static_cast<GDExtensionVariantType>(p_args[p_arg_idx]->get_type()), argtype) ||
if (!internal::gde_interface->variant_can_convert_strict(static_cast<GDExtensionVariantType>(p_args[p_arg_idx]->get_type()), argtype) ||
!VariantObjectClassChecker<T>::check(p_args[p_arg_idx])) {
r_error.error = GDEXTENSION_CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = p_arg_idx;
@@ -163,7 +163,7 @@ template <class T>
struct VariantCasterAndValidate<T &> {
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDExtensionCallError &r_error) {
GDExtensionVariantType argtype = GDExtensionVariantType(GetTypeInfo<T>::VARIANT_TYPE);
if (!internal::gdextension_interface_variant_can_convert_strict(static_cast<GDExtensionVariantType>(p_args[p_arg_idx]->get_type()), argtype) ||
if (!internal::gde_interface->variant_can_convert_strict(static_cast<GDExtensionVariantType>(p_args[p_arg_idx]->get_type()), argtype) ||
!VariantObjectClassChecker<T>::check(p_args[p_arg_idx])) {
r_error.error = GDEXTENSION_CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = p_arg_idx;
@@ -178,7 +178,7 @@ template <class T>
struct VariantCasterAndValidate<const T &> {
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDExtensionCallError &r_error) {
GDExtensionVariantType argtype = GDExtensionVariantType(GetTypeInfo<T>::VARIANT_TYPE);
if (!internal::gdextension_interface_variant_can_convert_strict(static_cast<GDExtensionVariantType>(p_args[p_arg_idx]->get_type()), argtype) ||
if (!internal::gde_interface->variant_can_convert_strict(static_cast<GDExtensionVariantType>(p_args[p_arg_idx]->get_type()), argtype) ||
!VariantObjectClassChecker<T>::check(p_args[p_arg_idx])) {
r_error.error = GDEXTENSION_CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = p_arg_idx;

View File

@@ -38,8 +38,6 @@
#include <godot_cpp/core/method_bind.hpp>
#include <godot_cpp/core/object.hpp>
#include <godot_cpp/classes/class_db_singleton.hpp>
#include <list>
#include <set>
#include <string>
@@ -106,9 +104,6 @@ public:
private:
// This may only contain custom classes, not Godot classes
static std::unordered_map<StringName, ClassInfo> classes;
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 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);
@@ -122,8 +117,6 @@ public:
static void register_class(bool p_virtual = false);
template <class T>
static void register_abstract_class();
template <class T>
static void register_engine_class();
template <class N, class M, typename... VarArgs>
static MethodBind *bind_method(N p_method_name, M p_method, VarArgs... p_args);
@@ -144,35 +137,30 @@ public:
static MethodBind *get_method(const StringName &p_class, const StringName &p_method);
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);
static void deinitialize(GDExtensionInitializationLevel p_level);
CLASSDB_SINGLETON_FORWARD_METHODS;
};
#define BIND_CONSTANT(m_constant) \
godot::ClassDB::bind_integer_constant(get_class_static(), "", #m_constant, m_constant);
#define BIND_ENUM_CONSTANT(m_constant) \
godot::ClassDB::bind_integer_constant(get_class_static(), godot::_gde_constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant);
godot::ClassDB::bind_integer_constant(get_class_static(), godot::__constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant);
#define BIND_BITFIELD_FLAG(m_constant) \
godot::ClassDB::bind_integer_constant(get_class_static(), godot::_gde_constant_get_bitfield_name(m_constant, #m_constant), #m_constant, m_constant, true);
godot::ClassDB::bind_integer_constant(get_class_static(), godot::__constant_get_bitfield_name(m_constant, #m_constant), #m_constant, m_constant, true);
#define BIND_VIRTUAL_METHOD(m_class, m_method) \
{ \
auto _call##m_method = [](GDExtensionObjectPtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr p_ret) -> void { \
call_with_ptr_args(reinterpret_cast<m_class *>(p_instance), &m_class::m_method, p_args, p_ret); \
}; \
godot::ClassDB::bind_virtual_method(m_class::get_class_static(), #m_method, _call##m_method); \
#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); \
}
template <class T, bool is_abstract>
void ClassDB::_register_class(bool p_virtual) {
instance_binding_callbacks[T::get_class_static()] = &T::_gde_binding_callbacks;
// Register this class within our plugin
ClassInfo cl;
cl.name = T::get_class_static();
@@ -184,7 +172,6 @@ void ClassDB::_register_class(bool p_virtual) {
cl.parent_ptr = &parent_it->second;
}
classes[cl.name] = cl;
class_register_order.push_back(cl.name);
// Register this class with Godot
GDExtensionClassCreationInfo class_info = {
@@ -207,7 +194,7 @@ void ClassDB::_register_class(bool p_virtual) {
(void *)&T::get_class_static(), // void *class_userdata;
};
internal::gdextension_interface_classdb_register_extension_class(internal::library, cl.name._native_ptr(), cl.parent_name._native_ptr(), &class_info);
internal::gde_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();
@@ -226,11 +213,6 @@ void ClassDB::register_abstract_class() {
ClassDB::_register_class<T, true>();
}
template <class T>
void ClassDB::register_engine_class() {
instance_binding_callbacks[T::get_class_static()] = &T::_gde_binding_callbacks;
}
template <class N, class 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.

View File

@@ -47,25 +47,25 @@ template <class O, class... Args>
O *_call_native_mb_ret_obj(const GDExtensionMethodBindPtr mb, void *instance, const Args &...args) {
GodotObject *ret = nullptr;
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
internal::gdextension_interface_object_method_bind_ptrcall(mb, instance, mb_args.data(), &ret);
internal::gde_interface->object_method_bind_ptrcall(mb, instance, mb_args.data(), &ret);
if (ret == nullptr) {
return nullptr;
}
return reinterpret_cast<O *>(internal::get_object_instance_binding(ret));
return reinterpret_cast<O *>(internal::gde_interface->object_get_instance_binding(ret, internal::token, &O::___binding_callbacks));
}
template <class R, class... Args>
R _call_native_mb_ret(const GDExtensionMethodBindPtr mb, void *instance, const Args &...args) {
R ret;
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
internal::gdextension_interface_object_method_bind_ptrcall(mb, instance, mb_args.data(), &ret);
internal::gde_interface->object_method_bind_ptrcall(mb, instance, mb_args.data(), &ret);
return ret;
}
template <class... Args>
void _call_native_mb_no_ret(const GDExtensionMethodBindPtr mb, void *instance, const Args &...args) {
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
internal::gdextension_interface_object_method_bind_ptrcall(mb, instance, mb_args.data(), nullptr);
internal::gde_interface->object_method_bind_ptrcall(mb, instance, mb_args.data(), nullptr);
}
template <class R, class... Args>
@@ -81,7 +81,7 @@ Object *_call_utility_ret_obj(const GDExtensionPtrUtilityFunction func, void *in
GodotObject *ret = nullptr;
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
func(&ret, mb_args.data(), mb_args.size());
return (Object *)internal::get_object_instance_binding(ret);
return (Object *)internal::gde_interface->object_get_instance_binding(ret, internal::token, &Object::___binding_callbacks);
}
template <class... Args>

View File

@@ -107,7 +107,7 @@ void memdelete(T *p_class, typename std::enable_if<!std::is_base_of_v<godot::Wra
template <class T, std::enable_if_t<std::is_base_of_v<godot::Wrapped, T>, bool> = true>
void memdelete(T *p_class) {
godot::internal::gdextension_interface_object_destroy(p_class->_owner);
godot::internal::gde_interface->object_destroy(p_class->_owner);
}
template <class T, class A>

View File

@@ -268,8 +268,8 @@ MethodBind *create_vararg_method_bind(R (T::*p_method)(const Variant **, GDExten
}
#ifndef TYPED_METHOD_BIND
class _gde_UnexistingClass;
#define MB_T _gde_UnexistingClass
class ___UnexistingClass;
#define MB_T ___UnexistingClass
#else
#define MB_T T
#endif

View File

@@ -33,7 +33,6 @@
#include <godot_cpp/core/defs.hpp>
#include <godot_cpp/core/object.hpp>
#include <godot_cpp/godot.hpp>
#include <godot_cpp/variant/variant.hpp>
@@ -168,9 +167,8 @@ MAKE_PTRARG_BY_REFERENCE(Variant);
template <class T>
struct PtrToArg<T *> {
static_assert(std::is_base_of<Object, T>::value, "Cannot encode non-Object value as an Object");
_FORCE_INLINE_ static T *convert(const void *p_ptr) {
return reinterpret_cast<T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr))));
return reinterpret_cast<T *>(godot::internal::gde_interface->object_get_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr)), godot::internal::token, &T::___binding_callbacks));
}
typedef Object *EncodeT;
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
@@ -180,9 +178,8 @@ struct PtrToArg<T *> {
template <class T>
struct PtrToArg<const T *> {
static_assert(std::is_base_of<Object, T>::value, "Cannot encode non-Object value as an Object");
_FORCE_INLINE_ static const T *convert(const void *p_ptr) {
return reinterpret_cast<const T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr))));
return reinterpret_cast<const T *>(godot::internal::gde_interface->object_get_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr)), godot::internal::token, &T::___binding_callbacks));
}
typedef const Object *EncodeT;
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {

View File

@@ -52,12 +52,6 @@
namespace godot {
namespace internal {
Object *get_object_instance_binding(GodotObject *);
} // namespace internal
struct MethodInfo {
StringName name;
PropertyInfo return_val;
@@ -130,11 +124,11 @@ public:
class ObjectDB {
public:
static Object *get_instance(uint64_t p_object_id) {
GDExtensionObjectPtr obj = internal::gdextension_interface_object_get_instance_from_id(p_object_id);
GDExtensionObjectPtr obj = internal::gde_interface->object_get_instance_from_id(p_object_id);
if (obj == nullptr) {
return nullptr;
}
return internal::get_object_instance_binding(obj);
return reinterpret_cast<Object *>(internal::gde_interface->object_get_instance_binding(obj, internal::token, &Object::___binding_callbacks));
}
};
@@ -144,11 +138,11 @@ T *Object::cast_to(Object *p_object) {
return nullptr;
}
StringName class_name = T::get_class_static();
GDExtensionObjectPtr casted = internal::gdextension_interface_object_cast_to(p_object->_owner, internal::gdextension_interface_classdb_get_class_tag(class_name._native_ptr()));
GDExtensionObjectPtr casted = internal::gde_interface->object_cast_to(p_object->_owner, internal::gde_interface->classdb_get_class_tag(class_name._native_ptr()));
if (casted == nullptr) {
return nullptr;
}
return dynamic_cast<T *>(internal::get_object_instance_binding(casted));
return reinterpret_cast<T *>(internal::gde_interface->object_get_instance_binding(casted, internal::token, &T::___binding_callbacks));
}
template <class T>
@@ -157,11 +151,11 @@ const T *Object::cast_to(const Object *p_object) {
return nullptr;
}
StringName class_name = T::get_class_static();
GDExtensionObjectPtr casted = internal::gdextension_interface_object_cast_to(p_object->_owner, internal::gdextension_interface_classdb_get_class_tag(class_name._native_ptr()));
GDExtensionObjectPtr casted = internal::gde_interface->object_cast_to(p_object->_owner, internal::gde_interface->classdb_get_class_tag(class_name._native_ptr()));
if (casted == nullptr) {
return nullptr;
}
return dynamic_cast<const T *>(internal::get_object_instance_binding(casted));
return reinterpret_cast<const T *>(internal::gde_interface->object_get_instance_binding(casted, internal::token, &T::___binding_callbacks));
}
} // namespace godot

View File

@@ -241,7 +241,7 @@ inline String enum_qualified_name_to_class_info_name(const String &p_qualified_n
TEMPL_MAKE_ENUM_TYPE_INFO(m_enum, const m_enum &)
template <typename T>
inline StringName _gde_constant_get_enum_name(T param, StringName p_constant) {
inline StringName __constant_get_enum_name(T param, StringName p_constant) {
if (GetTypeInfo<T>::VARIANT_TYPE == Variant::NIL) {
ERR_PRINT(("Missing VARIANT_ENUM_CAST for constant's enum: " + String(p_constant)).utf8().get_data());
}
@@ -288,7 +288,7 @@ public:
TEMPL_MAKE_BITFIELD_TYPE_INFO(m_enum, const m_enum &)
template <typename T>
inline StringName _gde_constant_get_bitfield_name(T param, StringName p_constant) {
inline StringName __constant_get_bitfield_name(T param, StringName p_constant) {
if (GetTypeInfo<T>::VARIANT_TYPE == Variant::NIL) {
ERR_PRINT(("Missing VARIANT_ENUM_CAST for constant's bitfield: " + String(p_constant)).utf8().get_data());
}

View File

@@ -37,150 +37,10 @@ namespace godot {
namespace internal {
extern "C" GDExtensionInterfaceGetProcAddress gdextension_interface_get_proc_address;
extern "C" const GDExtensionInterface *gde_interface;
extern "C" GDExtensionClassLibraryPtr library;
extern "C" void *token;
extern "C" GDExtensionGodotVersion godot_version;
// All of the GDExtension interface functions.
extern "C" GDExtensionInterfaceGetGodotVersion gdextension_interface_get_godot_version;
extern "C" GDExtensionInterfaceMemAlloc gdextension_interface_mem_alloc;
extern "C" GDExtensionInterfaceMemRealloc gdextension_interface_mem_realloc;
extern "C" GDExtensionInterfaceMemFree gdextension_interface_mem_free;
extern "C" GDExtensionInterfacePrintError gdextension_interface_print_error;
extern "C" GDExtensionInterfacePrintErrorWithMessage gdextension_interface_print_error_with_message;
extern "C" GDExtensionInterfacePrintWarning gdextension_interface_print_warning;
extern "C" GDExtensionInterfacePrintWarningWithMessage gdextension_interface_print_warning_with_message;
extern "C" GDExtensionInterfacePrintScriptError gdextension_interface_print_script_error;
extern "C" GDExtensionInterfacePrintScriptErrorWithMessage gdextension_interface_print_script_error_with_message;
extern "C" GDExtensionInterfaceGetNativeStructSize gdextension_interface_get_native_struct_size;
extern "C" GDExtensionInterfaceVariantNewCopy gdextension_interface_variant_new_copy;
extern "C" GDExtensionInterfaceVariantNewNil gdextension_interface_variant_new_nil;
extern "C" GDExtensionInterfaceVariantDestroy gdextension_interface_variant_destroy;
extern "C" GDExtensionInterfaceVariantCall gdextension_interface_variant_call;
extern "C" GDExtensionInterfaceVariantCallStatic gdextension_interface_variant_call_static;
extern "C" GDExtensionInterfaceVariantEvaluate gdextension_interface_variant_evaluate;
extern "C" GDExtensionInterfaceVariantSet gdextension_interface_variant_set;
extern "C" GDExtensionInterfaceVariantSetNamed gdextension_interface_variant_set_named;
extern "C" GDExtensionInterfaceVariantSetKeyed gdextension_interface_variant_set_keyed;
extern "C" GDExtensionInterfaceVariantSetIndexed gdextension_interface_variant_set_indexed;
extern "C" GDExtensionInterfaceVariantGet gdextension_interface_variant_get;
extern "C" GDExtensionInterfaceVariantGetNamed gdextension_interface_variant_get_named;
extern "C" GDExtensionInterfaceVariantGetKeyed gdextension_interface_variant_get_keyed;
extern "C" GDExtensionInterfaceVariantGetIndexed gdextension_interface_variant_get_indexed;
extern "C" GDExtensionInterfaceVariantIterInit gdextension_interface_variant_iter_init;
extern "C" GDExtensionInterfaceVariantIterNext gdextension_interface_variant_iter_next;
extern "C" GDExtensionInterfaceVariantIterGet gdextension_interface_variant_iter_get;
extern "C" GDExtensionInterfaceVariantHash gdextension_interface_variant_hash;
extern "C" GDExtensionInterfaceVariantRecursiveHash gdextension_interface_variant_recursive_hash;
extern "C" GDExtensionInterfaceVariantHashCompare gdextension_interface_variant_hash_compare;
extern "C" GDExtensionInterfaceVariantBooleanize gdextension_interface_variant_booleanize;
extern "C" GDExtensionInterfaceVariantDuplicate gdextension_interface_variant_duplicate;
extern "C" GDExtensionInterfaceVariantStringify gdextension_interface_variant_stringify;
extern "C" GDExtensionInterfaceVariantGetType gdextension_interface_variant_get_type;
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" 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" 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;
extern "C" GDExtensionInterfaceVariantGetPtrDestructor gdextension_interface_variant_get_ptr_destructor;
extern "C" GDExtensionInterfaceVariantConstruct gdextension_interface_variant_construct;
extern "C" GDExtensionInterfaceVariantGetPtrSetter gdextension_interface_variant_get_ptr_setter;
extern "C" GDExtensionInterfaceVariantGetPtrGetter gdextension_interface_variant_get_ptr_getter;
extern "C" GDExtensionInterfaceVariantGetPtrIndexedSetter gdextension_interface_variant_get_ptr_indexed_setter;
extern "C" GDExtensionInterfaceVariantGetPtrIndexedGetter gdextension_interface_variant_get_ptr_indexed_getter;
extern "C" GDExtensionInterfaceVariantGetPtrKeyedSetter gdextension_interface_variant_get_ptr_keyed_setter;
extern "C" GDExtensionInterfaceVariantGetPtrKeyedGetter gdextension_interface_variant_get_ptr_keyed_getter;
extern "C" GDExtensionInterfaceVariantGetPtrKeyedChecker gdextension_interface_variant_get_ptr_keyed_checker;
extern "C" GDExtensionInterfaceVariantGetConstantValue gdextension_interface_variant_get_constant_value;
extern "C" GDExtensionInterfaceVariantGetPtrUtilityFunction gdextension_interface_variant_get_ptr_utility_function;
extern "C" GDExtensionInterfaceStringNewWithLatin1Chars gdextension_interface_string_new_with_latin1_chars;
extern "C" GDExtensionInterfaceStringNewWithUtf8Chars gdextension_interface_string_new_with_utf8_chars;
extern "C" GDExtensionInterfaceStringNewWithUtf16Chars gdextension_interface_string_new_with_utf16_chars;
extern "C" GDExtensionInterfaceStringNewWithUtf32Chars gdextension_interface_string_new_with_utf32_chars;
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" GDExtensionInterfaceStringNewWithUtf16CharsAndLen gdextension_interface_string_new_with_utf16_chars_and_len;
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;
extern "C" GDExtensionInterfaceStringToUtf8Chars gdextension_interface_string_to_utf8_chars;
extern "C" GDExtensionInterfaceStringToUtf16Chars gdextension_interface_string_to_utf16_chars;
extern "C" GDExtensionInterfaceStringToUtf32Chars gdextension_interface_string_to_utf32_chars;
extern "C" GDExtensionInterfaceStringToWideChars gdextension_interface_string_to_wide_chars;
extern "C" GDExtensionInterfaceStringOperatorIndex gdextension_interface_string_operator_index;
extern "C" GDExtensionInterfaceStringOperatorIndexConst gdextension_interface_string_operator_index_const;
extern "C" GDExtensionInterfaceStringOperatorPlusEqString gdextension_interface_string_operator_plus_eq_string;
extern "C" GDExtensionInterfaceStringOperatorPlusEqChar gdextension_interface_string_operator_plus_eq_char;
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" 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;
extern "C" GDExtensionInterfaceWorkerThreadPoolAddNativeGroupTask gdextension_interface_worker_thread_pool_add_native_group_task;
extern "C" GDExtensionInterfaceWorkerThreadPoolAddNativeTask gdextension_interface_worker_thread_pool_add_native_task;
extern "C" GDExtensionInterfacePackedByteArrayOperatorIndex gdextension_interface_packed_byte_array_operator_index;
extern "C" GDExtensionInterfacePackedByteArrayOperatorIndexConst gdextension_interface_packed_byte_array_operator_index_const;
extern "C" GDExtensionInterfacePackedColorArrayOperatorIndex gdextension_interface_packed_color_array_operator_index;
extern "C" GDExtensionInterfacePackedColorArrayOperatorIndexConst gdextension_interface_packed_color_array_operator_index_const;
extern "C" GDExtensionInterfacePackedFloat32ArrayOperatorIndex gdextension_interface_packed_float32_array_operator_index;
extern "C" GDExtensionInterfacePackedFloat32ArrayOperatorIndexConst gdextension_interface_packed_float32_array_operator_index_const;
extern "C" GDExtensionInterfacePackedFloat64ArrayOperatorIndex gdextension_interface_packed_float64_array_operator_index;
extern "C" GDExtensionInterfacePackedFloat64ArrayOperatorIndexConst gdextension_interface_packed_float64_array_operator_index_const;
extern "C" GDExtensionInterfacePackedInt32ArrayOperatorIndex gdextension_interface_packed_int32_array_operator_index;
extern "C" GDExtensionInterfacePackedInt32ArrayOperatorIndexConst gdextension_interface_packed_int32_array_operator_index_const;
extern "C" GDExtensionInterfacePackedInt64ArrayOperatorIndex gdextension_interface_packed_int64_array_operator_index;
extern "C" GDExtensionInterfacePackedInt64ArrayOperatorIndexConst gdextension_interface_packed_int64_array_operator_index_const;
extern "C" GDExtensionInterfacePackedStringArrayOperatorIndex gdextension_interface_packed_string_array_operator_index;
extern "C" GDExtensionInterfacePackedStringArrayOperatorIndexConst gdextension_interface_packed_string_array_operator_index_const;
extern "C" GDExtensionInterfacePackedVector2ArrayOperatorIndex gdextension_interface_packed_vector2_array_operator_index;
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" 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" 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" 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" GDExtensionInterfaceRefGetObject gdextension_interface_ref_get_object;
extern "C" GDExtensionInterfaceRefSetObject gdextension_interface_ref_set_object;
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" GDExtensionInterfaceClassdbRegisterExtensionClass gdextension_interface_classdb_register_extension_class;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassMethod gdextension_interface_classdb_register_extension_class_method;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant gdextension_interface_classdb_register_extension_class_integer_constant;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassProperty gdextension_interface_classdb_register_extension_class_property;
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;
extern "C" GDExtensionInterfaceClassdbUnregisterExtensionClass gdextension_interface_classdb_unregister_extension_class;
extern "C" GDExtensionInterfaceGetLibraryPath gdextension_interface_get_library_path;
extern "C" GDExtensionInterfaceEditorAddPlugin gdextension_interface_editor_add_plugin;
extern "C" GDExtensionInterfaceEditorRemovePlugin gdextension_interface_editor_remove_plugin;
} // namespace internal
enum ModuleInitializationLevel {
@@ -191,28 +51,28 @@ enum ModuleInitializationLevel {
};
class GDExtensionBinding {
private:
static void register_engine_classes();
public:
using Callback = void (*)(ModuleInitializationLevel p_level);
static Callback init_callback;
static Callback terminate_callback;
static GDExtensionInitializationLevel minimum_initialization_level;
static GDExtensionBool init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization);
static GDExtensionBool init(const GDExtensionInterface *p_interface, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization);
public:
static void initialize_level(void *userdata, GDExtensionInitializationLevel p_level);
static void deinitialize_level(void *userdata, GDExtensionInitializationLevel p_level);
class InitObject {
GDExtensionInterfaceGetProcAddress get_proc_address;
const GDExtensionInterface *gde_interface;
GDExtensionClassLibraryPtr library;
GDExtensionInitialization *initialization;
public:
InitObject(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization);
InitObject(const GDExtensionInterface *p_interface, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) :
gde_interface(p_interface),
library(p_library),
initialization(r_initialization) {}
void register_initializer(Callback p_init) const;
void register_terminator(Callback p_init) const;

View File

@@ -32,14 +32,13 @@
#define GODOT_COWDATA_HPP
#include <godot_cpp/classes/global_constants.hpp>
#include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/core/error_macros.hpp>
#include <godot_cpp/core/math.hpp>
#include <godot_cpp/core/memory.hpp>
#include <godot_cpp/templates/safe_refcount.hpp>
#include <cstring>
#include <new>
#include <type_traits>
namespace godot {
@@ -49,9 +48,6 @@ class Vector;
template <class T, class V>
class VMap;
template <class T>
class CharStringT;
// Silence a false positive warning (see GH-52119).
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
@@ -66,9 +62,6 @@ class CowData {
template <class TV, class VV>
friend class VMap;
template <class TS>
friend class CharStringT;
private:
mutable T *_ptr = nullptr;
@@ -211,9 +204,9 @@ void CowData<T>::_unref(void *p_data) {
if (refc->decrement() > 0) {
return; // still in use
}
// clean up
if (!std::is_trivially_destructible<T>::value) {
if (!__has_trivial_destructor(T)) {
uint32_t *count = _get_size();
T *data = (T *)(count + 1);
@@ -248,7 +241,7 @@ uint32_t CowData<T>::_copy_on_write() {
T *_data = (T *)(mem_new);
// initialize new elements
if (std::is_trivially_copyable<T>::value) {
if (__has_trivial_copy(T)) {
memcpy(mem_new, _ptr, current_size * sizeof(T));
} else {
@@ -311,7 +304,7 @@ Error CowData<T>::resize(int p_size) {
// construct the newly created elements
if (!std::is_trivially_constructible<T>::value) {
if (!__has_trivial_constructor(T)) {
T *elems = _get_data();
for (int i = *_get_size(); i < p_size; i++) {
@@ -322,7 +315,7 @@ Error CowData<T>::resize(int p_size) {
*_get_size() = p_size;
} else if (p_size < current_size) {
if (!std::is_trivially_destructible<T>::value) {
if (!__has_trivial_destructor(T)) {
// deinitialize no longer needed elements
for (uint32_t i = p_size; i < *_get_size(); i++) {
T *t = &_get_data()[i];

View File

@@ -31,99 +31,82 @@
#ifndef GODOT_CHAR_STRING_HPP
#define GODOT_CHAR_STRING_HPP
#include <godot_cpp/templates/cowdata.hpp>
#include <cstddef>
#include <cstdint>
namespace godot {
template <class T>
class CharStringT;
template <class T>
class CharProxy {
template <class TS>
friend class CharStringT;
const int _index;
CowData<T> &_cowdata;
static inline const T _null = 0;
_FORCE_INLINE_ CharProxy(const int &p_index, CowData<T> &p_cowdata) :
_index(p_index),
_cowdata(p_cowdata) {}
public:
_FORCE_INLINE_ CharProxy(const CharProxy<T> &p_other) :
_index(p_other._index),
_cowdata(p_other._cowdata) {}
_FORCE_INLINE_ operator T() const {
if (unlikely(_index == _cowdata.size())) {
return _null;
}
return _cowdata.get(_index);
}
_FORCE_INLINE_ const T *operator&() const {
return _cowdata.ptr() + _index;
}
_FORCE_INLINE_ void operator=(const T &p_other) const {
_cowdata.set(_index, p_other);
}
_FORCE_INLINE_ void operator=(const CharProxy<T> &p_other) const {
_cowdata.set(_index, p_other.operator T());
}
};
template <class T>
class CharStringT {
class CharString {
friend class String;
CowData<T> _cowdata;
static inline const T _null = 0;
const char *_data = nullptr;
int _length = 0;
CharString(const char *str, int length);
public:
_FORCE_INLINE_ T *ptrw() { return _cowdata.ptrw(); }
_FORCE_INLINE_ const T *ptr() const { return _cowdata.ptr(); }
_FORCE_INLINE_ int size() const { return _cowdata.size(); }
Error resize(int p_size) { return _cowdata.resize(p_size); }
int length() const;
const char *get_data() const;
_FORCE_INLINE_ T get(int p_index) const { return _cowdata.get(p_index); }
_FORCE_INLINE_ void set(int p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); }
_FORCE_INLINE_ const T &operator[](int p_index) const {
if (unlikely(p_index == _cowdata.size())) {
return _null;
}
return _cowdata.get(p_index);
}
_FORCE_INLINE_ CharProxy<T> operator[](int p_index) { return CharProxy<T>(p_index, _cowdata); }
_FORCE_INLINE_ CharStringT() {}
_FORCE_INLINE_ CharStringT(const CharStringT<T> &p_str) { _cowdata._ref(p_str._cowdata); }
_FORCE_INLINE_ void operator=(const CharStringT<T> &p_str) { _cowdata._ref(p_str._cowdata); }
_FORCE_INLINE_ CharStringT(const T *p_cstr) { copy_from(p_cstr); }
void operator=(const T *p_cstr);
bool operator<(const CharStringT<T> &p_right) const;
CharStringT<T> &operator+=(T p_char);
int length() const { return size() ? size() - 1 : 0; }
const T *get_data() const;
operator const T *() const { return get_data(); };
protected:
void copy_from(const T *p_cstr);
CharString(CharString &&p_str);
void operator=(CharString &&p_str);
CharString() {}
~CharString();
};
typedef CharStringT<char> CharString;
typedef CharStringT<char16_t> Char16String;
typedef CharStringT<char32_t> Char32String;
typedef CharStringT<wchar_t> CharWideString;
class Char16String {
friend class String;
const char16_t *_data = nullptr;
int _length = 0;
Char16String(const char16_t *str, int length);
public:
int length() const;
const char16_t *get_data() const;
Char16String(Char16String &&p_str);
void operator=(Char16String &&p_str);
Char16String() {}
~Char16String();
};
class Char32String {
friend class String;
const char32_t *_data = nullptr;
int _length = 0;
Char32String(const char32_t *str, int length);
public:
int length() const;
const char32_t *get_data() const;
Char32String(Char32String &&p_str);
void operator=(Char32String &&p_str);
Char32String() {}
~Char32String();
};
class CharWideString {
friend class String;
const wchar_t *_data = nullptr;
int _length = 0;
CharWideString(const wchar_t *str, int length);
public:
int length() const;
const wchar_t *get_data() const;
CharWideString(CharWideString &&p_str);
void operator=(CharWideString &&p_str);
CharWideString() {}
~CharWideString();
};
} // namespace godot

View File

@@ -78,14 +78,6 @@ struct _NO_DISCARD_ Vector3 {
return x < y ? (y < z ? Vector3::AXIS_Z : Vector3::AXIS_Y) : (x < z ? Vector3::AXIS_Z : Vector3::AXIS_X);
}
Vector3 min(const Vector3 &p_vector3) const {
return Vector3(MIN(x, p_vector3.x), MIN(y, p_vector3.y), MIN(z, p_vector3.z));
}
Vector3 max(const Vector3 &p_vector3) const {
return Vector3(MAX(x, p_vector3.x), MAX(y, p_vector3.y), MAX(z, p_vector3.z));
}
_FORCE_INLINE_ real_t length() const;
_FORCE_INLINE_ real_t length_squared() const;

View File

@@ -71,14 +71,6 @@ struct _NO_DISCARD_ Vector3i {
Vector3i::Axis min_axis_index() const;
Vector3i::Axis max_axis_index() const;
Vector3i min(const Vector3i &p_vector3i) const {
return Vector3i(MIN(x, p_vector3i.x), MIN(y, p_vector3i.y), MIN(z, p_vector3i.z));
}
Vector3i max(const Vector3i &p_vector3i) const {
return Vector3i(MAX(x, p_vector3i.x), MAX(y, p_vector3i.y), MAX(z, p_vector3i.z));
}
_FORCE_INLINE_ int64_t length_squared() const;
_FORCE_INLINE_ double length() const;

View File

@@ -70,14 +70,6 @@ struct _NO_DISCARD_ Vector4 {
Vector4::Axis min_axis_index() const;
Vector4::Axis max_axis_index() const;
Vector4 min(const Vector4 &p_vector4) const {
return Vector4(MIN(x, p_vector4.x), MIN(y, p_vector4.y), MIN(z, p_vector4.z), MIN(w, p_vector4.w));
}
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));
}
_FORCE_INLINE_ real_t length_squared() const;
bool is_equal_approx(const Vector4 &p_vec4) const;
bool is_zero_approx() const;

View File

@@ -73,14 +73,6 @@ struct _NO_DISCARD_ Vector4i {
Vector4i::Axis min_axis_index() const;
Vector4i::Axis max_axis_index() const;
Vector4i min(const Vector4i &p_vector4i) const {
return Vector4i(MIN(x, p_vector4i.x), MIN(y, p_vector4i.y), MIN(z, p_vector4i.z), MIN(w, p_vector4i.w));
}
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));
}
_FORCE_INLINE_ int64_t length_squared() const;
_FORCE_INLINE_ double length() const;

View File

@@ -1,61 +0,0 @@
/**************************************************************************/
/* editor_plugin.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/classes/editor_plugin.hpp>
#include <godot_cpp/variant/string_name.hpp>
namespace godot {
Vector<StringName> EditorPlugins::plugin_classes;
void EditorPlugins::add_plugin_class(const StringName &p_class_name) {
ERR_FAIL_COND_MSG(plugin_classes.find(p_class_name) != -1, vformat("Editor plugin already registered: %s", p_class_name));
plugin_classes.push_back(p_class_name);
internal::gdextension_interface_editor_add_plugin(p_class_name._native_ptr());
}
void EditorPlugins::remove_plugin_class(const StringName &p_class_name) {
int index = plugin_classes.find(p_class_name);
ERR_FAIL_COND_MSG(index == -1, vformat("Editor plugin is not registered: %s", p_class_name));
plugin_classes.remove_at(index);
internal::gdextension_interface_editor_remove_plugin(p_class_name._native_ptr());
}
void EditorPlugins::deinitialize(GDExtensionInitializationLevel p_level) {
if (p_level == GDEXTENSION_INITIALIZATION_EDITOR) {
for (const StringName &class_name : plugin_classes) {
internal::gdextension_interface_editor_remove_plugin(class_name._native_ptr());
}
plugin_classes.clear();
}
}
} // namespace godot

View File

@@ -36,23 +36,23 @@
namespace godot {
Error XMLParser::_open_buffer(const uint8_t *p_buffer, size_t p_size) {
return (Error)internal::gdextension_interface_xml_parser_open_buffer(_owner, p_buffer, p_size);
return (Error)internal::gde_interface->xml_parser_open_buffer(_owner, p_buffer, p_size);
}
uint64_t FileAccess::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
return internal::gdextension_interface_file_access_get_buffer(_owner, p_dst, p_length);
return internal::gde_interface->file_access_get_buffer(_owner, p_dst, p_length);
}
void FileAccess::store_buffer(const uint8_t *p_src, uint64_t p_length) {
internal::gdextension_interface_file_access_store_buffer(_owner, p_src, p_length);
internal::gde_interface->file_access_store_buffer(_owner, p_src, p_length);
}
WorkerThreadPool::TaskID WorkerThreadPool::add_native_task(void (*p_func)(void *), void *p_userdata, bool p_high_priority, const String &p_description) {
return (TaskID)internal::gdextension_interface_worker_thread_pool_add_native_task(_owner, p_func, p_userdata, p_high_priority, (GDExtensionConstStringPtr)&p_description);
return (TaskID)internal::gde_interface->worker_thread_pool_add_native_task(_owner, p_func, p_userdata, p_high_priority, (GDExtensionConstStringPtr)&p_description);
}
WorkerThreadPool::GroupID WorkerThreadPool::add_native_group_task(void (*p_func)(void *, uint32_t), void *p_userdata, int p_elements, int p_tasks, bool p_high_priority, const String &p_description) {
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);
return (GroupID)internal::gde_interface->worker_thread_pool_add_native_group_task(_owner, p_func, p_userdata, p_elements, p_tasks, p_high_priority, (GDExtensionConstStringPtr)&p_description);
}
} // namespace godot

View File

@@ -43,13 +43,13 @@ const StringName *Wrapped::_get_extension_class_name() const {
void Wrapped::_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::gde_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());
godot::internal::gde_interface->object_set_instance_binding(_owner, godot::internal::token, this, _get_bindings_callbacks());
}
Wrapped::Wrapped(const StringName p_godot_class) {
_owner = godot::internal::gdextension_interface_classdb_construct_object(reinterpret_cast<GDExtensionConstStringNamePtr>(p_godot_class._native_ptr()));
_owner = godot::internal::gde_interface->classdb_construct_object(reinterpret_cast<GDExtensionConstStringNamePtr>(p_godot_class._native_ptr()));
}
Wrapped::Wrapped(GodotObject *p_godot_object) {

View File

@@ -40,8 +40,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;
GDExtensionInitializationLevel ClassDB::current_level = GDEXTENSION_INITIALIZATION_CORE;
MethodDefinition D_METHOD(StringName p_name) {
@@ -57,13 +55,13 @@ MethodDefinition D_METHOD(StringName p_name, StringName p_arg1) {
void ClassDB::add_property_group(const StringName &p_class, const String &p_name, const String &p_prefix) {
ERR_FAIL_COND_MSG(classes.find(p_class) == classes.end(), String("Trying to add property '{0}{1}' to non-existing class '{2}'.").format(Array::make(p_prefix, p_name, p_class)));
internal::gdextension_interface_classdb_register_extension_class_property_group(internal::library, p_class._native_ptr(), p_name._native_ptr(), p_prefix._native_ptr());
internal::gde_interface->classdb_register_extension_class_property_group(internal::library, p_class._native_ptr(), p_name._native_ptr(), p_prefix._native_ptr());
}
void ClassDB::add_property_subgroup(const StringName &p_class, const String &p_name, const String &p_prefix) {
ERR_FAIL_COND_MSG(classes.find(p_class) == classes.end(), String("Trying to add property '{0}{1}' to non-existing class '{2}'.").format(Array::make(p_prefix, p_name, p_class)));
internal::gdextension_interface_classdb_register_extension_class_property_subgroup(internal::library, p_class._native_ptr(), p_name._native_ptr(), p_prefix._native_ptr());
internal::gde_interface->classdb_register_extension_class_property_subgroup(internal::library, p_class._native_ptr(), p_name._native_ptr(), p_prefix._native_ptr());
}
void ClassDB::add_property(const StringName &p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index) {
@@ -113,7 +111,7 @@ void ClassDB::add_property(const StringName &p_class, const PropertyInfo &p_pinf
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());
internal::gde_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) {
@@ -236,7 +234,7 @@ void ClassDB::bind_method_godot(const StringName &p_class_name, MethodBind *p_me
(uint32_t)p_method->get_default_argument_count(), // uint32_t default_argument_count;
def_args.data(), // GDExtensionVariantPtr *default_arguments;
};
internal::gdextension_interface_classdb_register_extension_class_method(internal::library, p_class_name._native_ptr(), &method_info);
internal::gde_interface->classdb_register_extension_class_method(internal::library, p_class_name._native_ptr(), &method_info);
}
void ClassDB::add_signal(const StringName &p_class, const MethodInfo &p_signal) {
@@ -271,7 +269,7 @@ void ClassDB::add_signal(const StringName &p_class, const MethodInfo &p_signal)
});
}
internal::gdextension_interface_classdb_register_extension_class_signal(internal::library, cl.name._native_ptr(), p_signal.name._native_ptr(), parameters.data(), parameters.size());
internal::gde_interface->classdb_register_extension_class_signal(internal::library, cl.name._native_ptr(), p_signal.name._native_ptr(), parameters.data(), parameters.size());
}
void ClassDB::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) {
@@ -288,7 +286,7 @@ void ClassDB::bind_integer_constant(const StringName &p_class_name, const String
type.constant_names.insert(p_constant_name);
// 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);
internal::gde_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) {
// This is called by Godot the first time it calls a virtual function, and it caches the result, per object instance.
@@ -316,12 +314,6 @@ GDExtensionClassCallVirtual ClassDB::get_virtual_func(void *p_userdata, GDExtens
return nullptr;
}
const GDExtensionInstanceBindingCallbacks *ClassDB::get_instance_binding_callbacks(const StringName &p_class) {
std::unordered_map<StringName, const GDExtensionInstanceBindingCallbacks *>::iterator callbacks_it = instance_binding_callbacks.find(p_class);
ERR_FAIL_COND_V_MSG(callbacks_it == instance_binding_callbacks.end(), nullptr, String("Cannot find instance binding callbacks for class '{0}'.").format(Array::make(p_class)));
return callbacks_it->second;
}
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)));
@@ -349,15 +341,13 @@ void ClassDB::initialize(GDExtensionInitializationLevel p_level) {
}
void ClassDB::deinitialize(GDExtensionInitializationLevel p_level) {
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];
for (const std::pair<StringName, ClassInfo> pair : classes) {
const ClassInfo &cl = pair.second;
if (cl.level != p_level) {
continue;
}
internal::gdextension_interface_classdb_unregister_extension_class(internal::library, name._native_ptr());
internal::gde_interface->classdb_unregister_extension_class(internal::library, cl.name._native_ptr());
for (auto method : cl.method_map) {
memdelete(method.second);

View File

@@ -39,9 +39,9 @@ namespace godot {
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, bool p_editor_notify, bool p_is_warning) {
if (p_is_warning) {
internal::gdextension_interface_print_warning(p_error, p_function, p_file, p_line, p_editor_notify);
internal::gde_interface->print_warning(p_error, p_function, p_file, p_line, p_editor_notify);
} else {
internal::gdextension_interface_print_error(p_error, p_function, p_file, p_line, p_editor_notify);
internal::gde_interface->print_error(p_error, p_function, p_file, p_line, p_editor_notify);
}
}
@@ -51,9 +51,9 @@ void _err_print_error(const char *p_function, const char *p_file, int p_line, co
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_editor_notify, bool p_is_warning) {
if (p_is_warning) {
internal::gdextension_interface_print_warning_with_message(p_error, p_message, p_function, p_file, p_line, p_editor_notify);
internal::gde_interface->print_warning_with_message(p_error, p_message, p_function, p_file, p_line, p_editor_notify);
} else {
internal::gdextension_interface_print_error_with_message(p_error, p_message, p_function, p_file, p_line, p_editor_notify);
internal::gde_interface->print_error_with_message(p_error, p_message, p_function, p_file, p_line, p_editor_notify);
}
}

View File

@@ -41,7 +41,7 @@ void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) {
bool prepad = p_pad_align;
#endif
void *mem = internal::gdextension_interface_mem_alloc(p_bytes + (prepad ? PAD_ALIGN : 0));
void *mem = internal::gde_interface->mem_alloc(p_bytes + (prepad ? PAD_ALIGN : 0));
ERR_FAIL_COND_V(!mem, nullptr);
if (prepad) {
@@ -70,11 +70,11 @@ void *Memory::realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align) {
if (prepad) {
mem -= PAD_ALIGN;
mem = (uint8_t *)internal::gdextension_interface_mem_realloc(mem, p_bytes + PAD_ALIGN);
mem = (uint8_t *)internal::gde_interface->mem_realloc(mem, p_bytes + PAD_ALIGN);
ERR_FAIL_COND_V(!mem, nullptr);
return mem + PAD_ALIGN;
} else {
return (uint8_t *)internal::gdextension_interface_mem_realloc(mem, p_bytes);
return (uint8_t *)internal::gde_interface->mem_realloc(mem, p_bytes);
}
}
@@ -90,7 +90,7 @@ void Memory::free_static(void *p_ptr, bool p_pad_align) {
if (prepad) {
mem -= PAD_ALIGN;
}
internal::gdextension_interface_mem_free(mem);
internal::gde_interface->mem_free(mem);
}
_GlobalNil::_GlobalNil() {

View File

@@ -96,7 +96,7 @@ void MethodBind::bind_call(void *p_method_userdata, GDExtensionClassInstancePtr
Variant ret = bind->call(p_instance, p_args, p_argument_count, *r_error);
// This assumes the return value is an empty Variant, so it doesn't need to call the destructor first.
// Since only GDExtensionMethodBind calls this from the Godot side, it should always be the case.
internal::gdextension_interface_variant_new_copy(r_return, ret._native_ptr());
internal::gde_interface->variant_new_copy(r_return, ret._native_ptr());
}
void MethodBind::bind_ptrcall(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_return) {

View File

@@ -30,38 +30,8 @@
#include <godot_cpp/core/object.hpp>
#include <godot_cpp/core/class_db.hpp>
namespace godot {
namespace internal {
Object *get_object_instance_binding(GodotObject *p_engine_object) {
if (p_engine_object == nullptr) {
return nullptr;
}
// Get existing instance binding, if one already exists.
GDExtensionObjectPtr instance = gdextension_interface_object_get_instance_binding(p_engine_object, token, nullptr);
if (instance != nullptr) {
return reinterpret_cast<Object *>(instance);
}
// Otherwise, try to look up the correct binding callbacks.
const GDExtensionInstanceBindingCallbacks *binding_callbacks = nullptr;
StringName class_name;
if (gdextension_interface_object_get_class_name(p_engine_object, library, reinterpret_cast<GDExtensionStringNamePtr>(class_name._native_ptr()))) {
binding_callbacks = ClassDB::get_instance_binding_callbacks(class_name);
}
if (binding_callbacks == nullptr) {
binding_callbacks = &Object::_gde_binding_callbacks;
}
return reinterpret_cast<Object *>(gdextension_interface_object_get_instance_binding(p_engine_object, token, binding_callbacks));
}
} // namespace internal
MethodInfo::MethodInfo() :
flags(GDEXTENSION_METHOD_FLAG_NORMAL) {}

View File

@@ -30,11 +30,9 @@
#include <godot_cpp/godot.hpp>
#include <godot_cpp/classes/editor_plugin.hpp>
#include <godot_cpp/classes/wrapped.hpp>
#include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/core/memory.hpp>
#include <godot_cpp/core/version.hpp>
#include <godot_cpp/variant/variant.hpp>
#include <godot_cpp/core/error_macros.hpp>
@@ -43,362 +41,21 @@ namespace godot {
namespace internal {
GDExtensionInterfaceGetProcAddress gdextension_interface_get_proc_address = nullptr;
const GDExtensionInterface *gde_interface = nullptr;
GDExtensionClassLibraryPtr library = nullptr;
void *token = nullptr;
GDExtensionGodotVersion godot_version = { 0, 0, 0, nullptr };
// All of the GDExtension interface functions.
GDExtensionInterfaceGetGodotVersion gdextension_interface_get_godot_version = nullptr;
GDExtensionInterfaceMemAlloc gdextension_interface_mem_alloc = nullptr;
GDExtensionInterfaceMemRealloc gdextension_interface_mem_realloc = nullptr;
GDExtensionInterfaceMemFree gdextension_interface_mem_free = nullptr;
GDExtensionInterfacePrintError gdextension_interface_print_error = nullptr;
GDExtensionInterfacePrintErrorWithMessage gdextension_interface_print_error_with_message = nullptr;
GDExtensionInterfacePrintWarning gdextension_interface_print_warning = nullptr;
GDExtensionInterfacePrintWarningWithMessage gdextension_interface_print_warning_with_message = nullptr;
GDExtensionInterfacePrintScriptError gdextension_interface_print_script_error = nullptr;
GDExtensionInterfacePrintScriptErrorWithMessage gdextension_interface_print_script_error_with_message = nullptr;
GDExtensionInterfaceGetNativeStructSize gdextension_interface_get_native_struct_size = nullptr;
GDExtensionInterfaceVariantNewCopy gdextension_interface_variant_new_copy = nullptr;
GDExtensionInterfaceVariantNewNil gdextension_interface_variant_new_nil = nullptr;
GDExtensionInterfaceVariantDestroy gdextension_interface_variant_destroy = nullptr;
GDExtensionInterfaceVariantCall gdextension_interface_variant_call = nullptr;
GDExtensionInterfaceVariantCallStatic gdextension_interface_variant_call_static = nullptr;
GDExtensionInterfaceVariantEvaluate gdextension_interface_variant_evaluate = nullptr;
GDExtensionInterfaceVariantSet gdextension_interface_variant_set = nullptr;
GDExtensionInterfaceVariantSetNamed gdextension_interface_variant_set_named = nullptr;
GDExtensionInterfaceVariantSetKeyed gdextension_interface_variant_set_keyed = nullptr;
GDExtensionInterfaceVariantSetIndexed gdextension_interface_variant_set_indexed = nullptr;
GDExtensionInterfaceVariantGet gdextension_interface_variant_get = nullptr;
GDExtensionInterfaceVariantGetNamed gdextension_interface_variant_get_named = nullptr;
GDExtensionInterfaceVariantGetKeyed gdextension_interface_variant_get_keyed = nullptr;
GDExtensionInterfaceVariantGetIndexed gdextension_interface_variant_get_indexed = nullptr;
GDExtensionInterfaceVariantIterInit gdextension_interface_variant_iter_init = nullptr;
GDExtensionInterfaceVariantIterNext gdextension_interface_variant_iter_next = nullptr;
GDExtensionInterfaceVariantIterGet gdextension_interface_variant_iter_get = nullptr;
GDExtensionInterfaceVariantHash gdextension_interface_variant_hash = nullptr;
GDExtensionInterfaceVariantRecursiveHash gdextension_interface_variant_recursive_hash = nullptr;
GDExtensionInterfaceVariantHashCompare gdextension_interface_variant_hash_compare = nullptr;
GDExtensionInterfaceVariantBooleanize gdextension_interface_variant_booleanize = nullptr;
GDExtensionInterfaceVariantDuplicate gdextension_interface_variant_duplicate = nullptr;
GDExtensionInterfaceVariantStringify gdextension_interface_variant_stringify = nullptr;
GDExtensionInterfaceVariantGetType gdextension_interface_variant_get_type = nullptr;
GDExtensionInterfaceVariantHasMethod gdextension_interface_variant_has_method = nullptr;
GDExtensionInterfaceVariantHasMember gdextension_interface_variant_has_member = nullptr;
GDExtensionInterfaceVariantHasKey gdextension_interface_variant_has_key = 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;
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;
GDExtensionInterfaceVariantGetPtrDestructor gdextension_interface_variant_get_ptr_destructor = nullptr;
GDExtensionInterfaceVariantConstruct gdextension_interface_variant_construct = nullptr;
GDExtensionInterfaceVariantGetPtrSetter gdextension_interface_variant_get_ptr_setter = nullptr;
GDExtensionInterfaceVariantGetPtrGetter gdextension_interface_variant_get_ptr_getter = nullptr;
GDExtensionInterfaceVariantGetPtrIndexedSetter gdextension_interface_variant_get_ptr_indexed_setter = nullptr;
GDExtensionInterfaceVariantGetPtrIndexedGetter gdextension_interface_variant_get_ptr_indexed_getter = nullptr;
GDExtensionInterfaceVariantGetPtrKeyedSetter gdextension_interface_variant_get_ptr_keyed_setter = nullptr;
GDExtensionInterfaceVariantGetPtrKeyedGetter gdextension_interface_variant_get_ptr_keyed_getter = nullptr;
GDExtensionInterfaceVariantGetPtrKeyedChecker gdextension_interface_variant_get_ptr_keyed_checker = nullptr;
GDExtensionInterfaceVariantGetConstantValue gdextension_interface_variant_get_constant_value = nullptr;
GDExtensionInterfaceVariantGetPtrUtilityFunction gdextension_interface_variant_get_ptr_utility_function = nullptr;
GDExtensionInterfaceStringNewWithLatin1Chars gdextension_interface_string_new_with_latin1_chars = nullptr;
GDExtensionInterfaceStringNewWithUtf8Chars gdextension_interface_string_new_with_utf8_chars = nullptr;
GDExtensionInterfaceStringNewWithUtf16Chars gdextension_interface_string_new_with_utf16_chars = nullptr;
GDExtensionInterfaceStringNewWithUtf32Chars gdextension_interface_string_new_with_utf32_chars = nullptr;
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;
GDExtensionInterfaceStringNewWithUtf16CharsAndLen gdextension_interface_string_new_with_utf16_chars_and_len = 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;
GDExtensionInterfaceStringToUtf8Chars gdextension_interface_string_to_utf8_chars = nullptr;
GDExtensionInterfaceStringToUtf16Chars gdextension_interface_string_to_utf16_chars = nullptr;
GDExtensionInterfaceStringToUtf32Chars gdextension_interface_string_to_utf32_chars = nullptr;
GDExtensionInterfaceStringToWideChars gdextension_interface_string_to_wide_chars = nullptr;
GDExtensionInterfaceStringOperatorIndex gdextension_interface_string_operator_index = nullptr;
GDExtensionInterfaceStringOperatorIndexConst gdextension_interface_string_operator_index_const = nullptr;
GDExtensionInterfaceStringOperatorPlusEqString gdextension_interface_string_operator_plus_eq_string = nullptr;
GDExtensionInterfaceStringOperatorPlusEqChar gdextension_interface_string_operator_plus_eq_char = nullptr;
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;
GDExtensionInterfaceXmlParserOpenBuffer gdextension_interface_xml_parser_open_buffer = nullptr;
GDExtensionInterfaceFileAccessStoreBuffer gdextension_interface_file_access_store_buffer = nullptr;
GDExtensionInterfaceFileAccessGetBuffer gdextension_interface_file_access_get_buffer = nullptr;
GDExtensionInterfaceWorkerThreadPoolAddNativeGroupTask gdextension_interface_worker_thread_pool_add_native_group_task = nullptr;
GDExtensionInterfaceWorkerThreadPoolAddNativeTask gdextension_interface_worker_thread_pool_add_native_task = nullptr;
GDExtensionInterfacePackedByteArrayOperatorIndex gdextension_interface_packed_byte_array_operator_index = nullptr;
GDExtensionInterfacePackedByteArrayOperatorIndexConst gdextension_interface_packed_byte_array_operator_index_const = nullptr;
GDExtensionInterfacePackedColorArrayOperatorIndex gdextension_interface_packed_color_array_operator_index = nullptr;
GDExtensionInterfacePackedColorArrayOperatorIndexConst gdextension_interface_packed_color_array_operator_index_const = nullptr;
GDExtensionInterfacePackedFloat32ArrayOperatorIndex gdextension_interface_packed_float32_array_operator_index = nullptr;
GDExtensionInterfacePackedFloat32ArrayOperatorIndexConst gdextension_interface_packed_float32_array_operator_index_const = nullptr;
GDExtensionInterfacePackedFloat64ArrayOperatorIndex gdextension_interface_packed_float64_array_operator_index = nullptr;
GDExtensionInterfacePackedFloat64ArrayOperatorIndexConst gdextension_interface_packed_float64_array_operator_index_const = nullptr;
GDExtensionInterfacePackedInt32ArrayOperatorIndex gdextension_interface_packed_int32_array_operator_index = nullptr;
GDExtensionInterfacePackedInt32ArrayOperatorIndexConst gdextension_interface_packed_int32_array_operator_index_const = nullptr;
GDExtensionInterfacePackedInt64ArrayOperatorIndex gdextension_interface_packed_int64_array_operator_index = nullptr;
GDExtensionInterfacePackedInt64ArrayOperatorIndexConst gdextension_interface_packed_int64_array_operator_index_const = nullptr;
GDExtensionInterfacePackedStringArrayOperatorIndex gdextension_interface_packed_string_array_operator_index = nullptr;
GDExtensionInterfacePackedStringArrayOperatorIndexConst gdextension_interface_packed_string_array_operator_index_const = nullptr;
GDExtensionInterfacePackedVector2ArrayOperatorIndex gdextension_interface_packed_vector2_array_operator_index = nullptr;
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;
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;
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;
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;
GDExtensionInterfaceRefGetObject gdextension_interface_ref_get_object = nullptr;
GDExtensionInterfaceRefSetObject gdextension_interface_ref_set_object = 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;
GDExtensionInterfaceClassdbRegisterExtensionClass gdextension_interface_classdb_register_extension_class = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassMethod gdextension_interface_classdb_register_extension_class_method = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant gdextension_interface_classdb_register_extension_class_integer_constant = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassProperty gdextension_interface_classdb_register_extension_class_property = 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;
GDExtensionInterfaceClassdbUnregisterExtensionClass gdextension_interface_classdb_unregister_extension_class = nullptr;
GDExtensionInterfaceGetLibraryPath gdextension_interface_get_library_path = nullptr;
GDExtensionInterfaceEditorAddPlugin gdextension_interface_editor_add_plugin = nullptr;
GDExtensionInterfaceEditorRemovePlugin gdextension_interface_editor_remove_plugin = nullptr;
} // namespace internal
GDExtensionBinding::Callback GDExtensionBinding::init_callback = nullptr;
GDExtensionBinding::Callback GDExtensionBinding::terminate_callback = nullptr;
GDExtensionInitializationLevel GDExtensionBinding::minimum_initialization_level = GDEXTENSION_INITIALIZATION_CORE;
#define ERR_PRINT_EARLY(m_msg) \
internal::gdextension_interface_print_error(m_msg, FUNCTION_STR, __FILE__, __LINE__, false)
#define LOAD_PROC_ADDRESS(m_name, m_type) \
internal::gdextension_interface_##m_name = (m_type)p_get_proc_address(#m_name); \
if (!internal::gdextension_interface_##m_name) { \
ERR_PRINT_EARLY("Unable to load GDExtension interface function " #m_name "()"); \
return false; \
}
// Partial definition of the legacy interface so we can detect it and show an error.
typedef struct {
uint32_t version_major;
uint32_t version_minor;
uint32_t version_patch;
const char *version_string;
GDExtensionInterfaceFunctionPtr unused1;
GDExtensionInterfaceFunctionPtr unused2;
GDExtensionInterfaceFunctionPtr unused3;
GDExtensionInterfacePrintError print_error;
GDExtensionInterfacePrintErrorWithMessage print_error_with_message;
} LegacyGDExtensionInterface;
GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
// Make sure we weren't passed the legacy struct.
uint32_t *raw_interface = (uint32_t *)(void *)p_get_proc_address;
if (raw_interface[0] == 4 && raw_interface[1] == 0) {
// Use the legacy interface only to give a nice error.
LegacyGDExtensionInterface *legacy_interface = (LegacyGDExtensionInterface *)p_get_proc_address;
internal::gdextension_interface_print_error = (GDExtensionInterfacePrintError)legacy_interface->print_error;
ERR_PRINT_EARLY("Cannot load a GDExtension built for Godot 4.1+ in Godot 4.0.");
return false;
}
// Load the "print_error" function first (needed by the ERR_PRINT_EARLY() macro).
internal::gdextension_interface_print_error = (GDExtensionInterfacePrintError)p_get_proc_address("print_error");
if (!internal::gdextension_interface_print_error) {
printf("ERROR: Unable to load GDExtension interface function print_error().\n");
return false;
}
internal::gdextension_interface_get_proc_address = p_get_proc_address;
GDExtensionBool GDExtensionBinding::init(const GDExtensionInterface *p_interface, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
internal::gde_interface = p_interface;
internal::library = p_library;
internal::token = p_library;
LOAD_PROC_ADDRESS(get_godot_version, GDExtensionInterfaceGetGodotVersion);
internal::gdextension_interface_get_godot_version(&internal::godot_version);
// Check that godot-cpp was compiled using an extension_api.json older or at the
// same version as the Godot that is loading it.
bool compatible;
if (internal::godot_version.major != GODOT_VERSION_MAJOR) {
compatible = internal::godot_version.major > GODOT_VERSION_MAJOR;
} else if (internal::godot_version.minor != GODOT_VERSION_MINOR) {
compatible = internal::godot_version.minor > GODOT_VERSION_MINOR;
} else {
compatible = internal::godot_version.patch >= GODOT_VERSION_PATCH;
}
if (!compatible) {
// We need to use snprintf() here because vformat() uses Variant, and we haven't loaded
// the GDExtension interface far enough to use Variants yet.
char msg[128];
snprintf(msg, 128, "Cannot load a GDExtension built for Godot %d.%d.%d using an older version of Godot (%d.%d.%d).",
GODOT_VERSION_MAJOR, GODOT_VERSION_MINOR, GODOT_VERSION_PATCH,
internal::godot_version.major, internal::godot_version.minor, internal::godot_version.patch);
ERR_PRINT_EARLY(msg);
return false;
}
LOAD_PROC_ADDRESS(mem_alloc, GDExtensionInterfaceMemAlloc);
LOAD_PROC_ADDRESS(mem_realloc, GDExtensionInterfaceMemRealloc);
LOAD_PROC_ADDRESS(mem_free, GDExtensionInterfaceMemFree);
LOAD_PROC_ADDRESS(print_error_with_message, GDExtensionInterfacePrintErrorWithMessage);
LOAD_PROC_ADDRESS(print_warning, GDExtensionInterfacePrintWarning);
LOAD_PROC_ADDRESS(print_warning_with_message, GDExtensionInterfacePrintWarningWithMessage);
LOAD_PROC_ADDRESS(print_script_error, GDExtensionInterfacePrintScriptError);
LOAD_PROC_ADDRESS(print_script_error_with_message, GDExtensionInterfacePrintScriptErrorWithMessage);
LOAD_PROC_ADDRESS(get_native_struct_size, GDExtensionInterfaceGetNativeStructSize);
LOAD_PROC_ADDRESS(variant_new_copy, GDExtensionInterfaceVariantNewCopy);
LOAD_PROC_ADDRESS(variant_new_nil, GDExtensionInterfaceVariantNewNil);
LOAD_PROC_ADDRESS(variant_destroy, GDExtensionInterfaceVariantDestroy);
LOAD_PROC_ADDRESS(variant_call, GDExtensionInterfaceVariantCall);
LOAD_PROC_ADDRESS(variant_call_static, GDExtensionInterfaceVariantCallStatic);
LOAD_PROC_ADDRESS(variant_evaluate, GDExtensionInterfaceVariantEvaluate);
LOAD_PROC_ADDRESS(variant_set, GDExtensionInterfaceVariantSet);
LOAD_PROC_ADDRESS(variant_set_named, GDExtensionInterfaceVariantSetNamed);
LOAD_PROC_ADDRESS(variant_set_keyed, GDExtensionInterfaceVariantSetKeyed);
LOAD_PROC_ADDRESS(variant_set_indexed, GDExtensionInterfaceVariantSetIndexed);
LOAD_PROC_ADDRESS(variant_get, GDExtensionInterfaceVariantGet);
LOAD_PROC_ADDRESS(variant_get_named, GDExtensionInterfaceVariantGetNamed);
LOAD_PROC_ADDRESS(variant_get_keyed, GDExtensionInterfaceVariantGetKeyed);
LOAD_PROC_ADDRESS(variant_get_indexed, GDExtensionInterfaceVariantGetIndexed);
LOAD_PROC_ADDRESS(variant_iter_init, GDExtensionInterfaceVariantIterInit);
LOAD_PROC_ADDRESS(variant_iter_next, GDExtensionInterfaceVariantIterNext);
LOAD_PROC_ADDRESS(variant_iter_get, GDExtensionInterfaceVariantIterGet);
LOAD_PROC_ADDRESS(variant_hash, GDExtensionInterfaceVariantHash);
LOAD_PROC_ADDRESS(variant_recursive_hash, GDExtensionInterfaceVariantRecursiveHash);
LOAD_PROC_ADDRESS(variant_hash_compare, GDExtensionInterfaceVariantHashCompare);
LOAD_PROC_ADDRESS(variant_booleanize, GDExtensionInterfaceVariantBooleanize);
LOAD_PROC_ADDRESS(variant_duplicate, GDExtensionInterfaceVariantDuplicate);
LOAD_PROC_ADDRESS(variant_stringify, GDExtensionInterfaceVariantStringify);
LOAD_PROC_ADDRESS(variant_get_type, GDExtensionInterfaceVariantGetType);
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_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_operator_evaluator, GDExtensionInterfaceVariantGetPtrOperatorEvaluator);
LOAD_PROC_ADDRESS(variant_get_ptr_builtin_method, GDExtensionInterfaceVariantGetPtrBuiltinMethod);
LOAD_PROC_ADDRESS(variant_get_ptr_constructor, GDExtensionInterfaceVariantGetPtrConstructor);
LOAD_PROC_ADDRESS(variant_get_ptr_destructor, GDExtensionInterfaceVariantGetPtrDestructor);
LOAD_PROC_ADDRESS(variant_construct, GDExtensionInterfaceVariantConstruct);
LOAD_PROC_ADDRESS(variant_get_ptr_setter, GDExtensionInterfaceVariantGetPtrSetter);
LOAD_PROC_ADDRESS(variant_get_ptr_getter, GDExtensionInterfaceVariantGetPtrGetter);
LOAD_PROC_ADDRESS(variant_get_ptr_indexed_setter, GDExtensionInterfaceVariantGetPtrIndexedSetter);
LOAD_PROC_ADDRESS(variant_get_ptr_indexed_getter, GDExtensionInterfaceVariantGetPtrIndexedGetter);
LOAD_PROC_ADDRESS(variant_get_ptr_keyed_setter, GDExtensionInterfaceVariantGetPtrKeyedSetter);
LOAD_PROC_ADDRESS(variant_get_ptr_keyed_getter, GDExtensionInterfaceVariantGetPtrKeyedGetter);
LOAD_PROC_ADDRESS(variant_get_ptr_keyed_checker, GDExtensionInterfaceVariantGetPtrKeyedChecker);
LOAD_PROC_ADDRESS(variant_get_constant_value, GDExtensionInterfaceVariantGetConstantValue);
LOAD_PROC_ADDRESS(variant_get_ptr_utility_function, GDExtensionInterfaceVariantGetPtrUtilityFunction);
LOAD_PROC_ADDRESS(string_new_with_latin1_chars, GDExtensionInterfaceStringNewWithLatin1Chars);
LOAD_PROC_ADDRESS(string_new_with_utf8_chars, GDExtensionInterfaceStringNewWithUtf8Chars);
LOAD_PROC_ADDRESS(string_new_with_utf16_chars, GDExtensionInterfaceStringNewWithUtf16Chars);
LOAD_PROC_ADDRESS(string_new_with_utf32_chars, GDExtensionInterfaceStringNewWithUtf32Chars);
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_utf16_chars_and_len, GDExtensionInterfaceStringNewWithUtf16CharsAndLen);
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);
LOAD_PROC_ADDRESS(string_to_utf8_chars, GDExtensionInterfaceStringToUtf8Chars);
LOAD_PROC_ADDRESS(string_to_utf16_chars, GDExtensionInterfaceStringToUtf16Chars);
LOAD_PROC_ADDRESS(string_to_utf32_chars, GDExtensionInterfaceStringToUtf32Chars);
LOAD_PROC_ADDRESS(string_to_wide_chars, GDExtensionInterfaceStringToWideChars);
LOAD_PROC_ADDRESS(string_operator_index, GDExtensionInterfaceStringOperatorIndex);
LOAD_PROC_ADDRESS(string_operator_index_const, GDExtensionInterfaceStringOperatorIndexConst);
LOAD_PROC_ADDRESS(string_operator_plus_eq_string, GDExtensionInterfaceStringOperatorPlusEqString);
LOAD_PROC_ADDRESS(string_operator_plus_eq_char, GDExtensionInterfaceStringOperatorPlusEqChar);
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(xml_parser_open_buffer, GDExtensionInterfaceXmlParserOpenBuffer);
LOAD_PROC_ADDRESS(file_access_store_buffer, GDExtensionInterfaceFileAccessStoreBuffer);
LOAD_PROC_ADDRESS(file_access_get_buffer, GDExtensionInterfaceFileAccessGetBuffer);
LOAD_PROC_ADDRESS(worker_thread_pool_add_native_group_task, GDExtensionInterfaceWorkerThreadPoolAddNativeGroupTask);
LOAD_PROC_ADDRESS(worker_thread_pool_add_native_task, GDExtensionInterfaceWorkerThreadPoolAddNativeTask);
LOAD_PROC_ADDRESS(packed_byte_array_operator_index, GDExtensionInterfacePackedByteArrayOperatorIndex);
LOAD_PROC_ADDRESS(packed_byte_array_operator_index_const, GDExtensionInterfacePackedByteArrayOperatorIndexConst);
LOAD_PROC_ADDRESS(packed_color_array_operator_index, GDExtensionInterfacePackedColorArrayOperatorIndex);
LOAD_PROC_ADDRESS(packed_color_array_operator_index_const, GDExtensionInterfacePackedColorArrayOperatorIndexConst);
LOAD_PROC_ADDRESS(packed_float32_array_operator_index, GDExtensionInterfacePackedFloat32ArrayOperatorIndex);
LOAD_PROC_ADDRESS(packed_float32_array_operator_index_const, GDExtensionInterfacePackedFloat32ArrayOperatorIndexConst);
LOAD_PROC_ADDRESS(packed_float64_array_operator_index, GDExtensionInterfacePackedFloat64ArrayOperatorIndex);
LOAD_PROC_ADDRESS(packed_float64_array_operator_index_const, GDExtensionInterfacePackedFloat64ArrayOperatorIndexConst);
LOAD_PROC_ADDRESS(packed_int32_array_operator_index, GDExtensionInterfacePackedInt32ArrayOperatorIndex);
LOAD_PROC_ADDRESS(packed_int32_array_operator_index_const, GDExtensionInterfacePackedInt32ArrayOperatorIndexConst);
LOAD_PROC_ADDRESS(packed_int64_array_operator_index, GDExtensionInterfacePackedInt64ArrayOperatorIndex);
LOAD_PROC_ADDRESS(packed_int64_array_operator_index_const, GDExtensionInterfacePackedInt64ArrayOperatorIndexConst);
LOAD_PROC_ADDRESS(packed_string_array_operator_index, GDExtensionInterfacePackedStringArrayOperatorIndex);
LOAD_PROC_ADDRESS(packed_string_array_operator_index_const, GDExtensionInterfacePackedStringArrayOperatorIndexConst);
LOAD_PROC_ADDRESS(packed_vector2_array_operator_index, GDExtensionInterfacePackedVector2ArrayOperatorIndex);
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(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(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_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(ref_get_object, GDExtensionInterfaceRefGetObject);
LOAD_PROC_ADDRESS(ref_set_object, GDExtensionInterfaceRefSetObject);
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_class, GDExtensionInterfaceClassdbRegisterExtensionClass);
LOAD_PROC_ADDRESS(classdb_register_extension_class_method, GDExtensionInterfaceClassdbRegisterExtensionClassMethod);
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_group, GDExtensionInterfaceClassdbRegisterExtensionClassPropertyGroup);
LOAD_PROC_ADDRESS(classdb_register_extension_class_property_subgroup, GDExtensionInterfaceClassdbRegisterExtensionClassPropertySubgroup);
LOAD_PROC_ADDRESS(classdb_register_extension_class_signal, GDExtensionInterfaceClassdbRegisterExtensionClassSignal);
LOAD_PROC_ADDRESS(classdb_unregister_extension_class, GDExtensionInterfaceClassdbUnregisterExtensionClass);
LOAD_PROC_ADDRESS(get_library_path, GDExtensionInterfaceGetLibraryPath);
LOAD_PROC_ADDRESS(editor_add_plugin, GDExtensionInterfaceEditorAddPlugin);
LOAD_PROC_ADDRESS(editor_remove_plugin, GDExtensionInterfaceEditorRemovePlugin);
r_initialization->initialize = initialize_level;
r_initialization->deinitialize = deinitialize_level;
r_initialization->minimum_initialization_level = minimum_initialization_level;
@@ -406,14 +63,10 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
ERR_FAIL_COND_V_MSG(init_callback == nullptr, false, "Initialization callback must be defined.");
Variant::init_bindings();
register_engine_classes();
return true;
}
#undef LOAD_PROC_ADDRESS
#undef ERR_PRINT_EARLY
void GDExtensionBinding::initialize_level(void *userdata, GDExtensionInitializationLevel p_level) {
ClassDB::current_level = p_level;
@@ -431,14 +84,8 @@ void GDExtensionBinding::deinitialize_level(void *userdata, GDExtensionInitializ
terminate_callback(static_cast<ModuleInitializationLevel>(p_level));
}
EditorPlugins::deinitialize(p_level);
ClassDB::deinitialize(p_level);
}
GDExtensionBinding::InitObject::InitObject(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
get_proc_address = p_get_proc_address;
library = p_library;
initialization = r_initialization;
}
void GDExtensionBinding::InitObject::register_initializer(Callback p_init) const {
GDExtensionBinding::init_callback = p_init;
@@ -453,7 +100,18 @@ void GDExtensionBinding::InitObject::set_minimum_library_initialization_level(Mo
}
GDExtensionBool GDExtensionBinding::InitObject::init() const {
return GDExtensionBinding::init(get_proc_address, library, initialization);
return GDExtensionBinding::init(gde_interface, library, initialization);
}
} // namespace godot
extern "C" {
void GDE_EXPORT initialize_level(void *userdata, GDExtensionInitializationLevel p_level) {
godot::GDExtensionBinding::initialize_level(userdata, p_level);
}
void GDE_EXPORT deinitialize_level(void *userdata, GDExtensionInitializationLevel p_level) {
godot::GDExtensionBinding::deinitialize_level(userdata, p_level);
}
}

View File

@@ -38,138 +38,134 @@
#include <godot_cpp/godot.hpp>
#include <cmath>
#include <string>
namespace godot {
template <typename L, typename R>
_FORCE_INLINE_ bool is_str_less(const L *l_ptr, const R *r_ptr) {
while (true) {
const char32_t l = *l_ptr;
const char32_t r = *r_ptr;
int CharString::length() const {
return _length;
}
if (l == 0 && r == 0) {
return false;
} else if (l == 0) {
return true;
} else if (r == 0) {
return false;
} else if (l < r) {
return true;
} else if (l > r) {
return false;
}
const char *CharString::get_data() const {
return _data;
}
l_ptr++;
r_ptr++;
CharString::CharString(CharString &&p_str) {
SWAP(_length, p_str._length);
SWAP(_data, p_str._data);
}
void CharString::operator=(CharString &&p_str) {
SWAP(_length, p_str._length);
SWAP(_data, p_str._data);
}
CharString::CharString(const char *str, int length) :
_data(str), _length(length) {}
CharString::~CharString() {
if (_data != nullptr) {
memdelete_arr(_data);
}
}
template <class T>
bool CharStringT<T>::operator<(const CharStringT<T> &p_right) const {
if (length() == 0) {
return p_right.length() != 0;
}
return is_str_less(get_data(), p_right.get_data());
int Char16String::length() const {
return _length;
}
template <class T>
CharStringT<T> &CharStringT<T>::operator+=(T p_char) {
const int lhs_len = length();
resize(lhs_len + 2);
T *dst = ptrw();
dst[lhs_len] = p_char;
dst[lhs_len + 1] = 0;
return *this;
const char16_t *Char16String::get_data() const {
return _data;
}
template <class T>
void CharStringT<T>::operator=(const T *p_cstr) {
copy_from(p_cstr);
Char16String::Char16String(Char16String &&p_str) {
SWAP(_length, p_str._length);
SWAP(_data, p_str._data);
}
template <>
const char *CharStringT<char>::get_data() const {
if (size()) {
return &operator[](0);
} else {
return "";
void Char16String::operator=(Char16String &&p_str) {
SWAP(_length, p_str._length);
SWAP(_data, p_str._data);
}
Char16String::Char16String(const char16_t *str, int length) :
_data(str), _length(length) {}
Char16String::~Char16String() {
if (_data != nullptr) {
memdelete_arr(_data);
}
}
template <>
const char16_t *CharStringT<char16_t>::get_data() const {
if (size()) {
return &operator[](0);
} else {
return u"";
int Char32String::length() const {
return _length;
}
const char32_t *Char32String::get_data() const {
return _data;
}
Char32String::Char32String(Char32String &&p_str) {
SWAP(_length, p_str._length);
SWAP(_data, p_str._data);
}
void Char32String::operator=(Char32String &&p_str) {
SWAP(_length, p_str._length);
SWAP(_data, p_str._data);
}
Char32String::Char32String(const char32_t *str, int length) :
_data(str), _length(length) {}
Char32String::~Char32String() {
if (_data != nullptr) {
memdelete_arr(_data);
}
}
template <>
const char32_t *CharStringT<char32_t>::get_data() const {
if (size()) {
return &operator[](0);
} else {
return U"";
}
int CharWideString::length() const {
return _length;
}
template <>
const wchar_t *CharStringT<wchar_t>::get_data() const {
if (size()) {
return &operator[](0);
} else {
return L"";
}
const wchar_t *CharWideString::get_data() const {
return _data;
}
template <class T>
void CharStringT<T>::copy_from(const T *p_cstr) {
if (!p_cstr) {
resize(0);
return;
}
size_t len = std::char_traits<T>::length(p_cstr);
if (len == 0) {
resize(0);
return;
}
Error err = resize(++len); // include terminating null char
ERR_FAIL_COND_MSG(err != OK, "Failed to copy C-string.");
memcpy(ptrw(), p_cstr, len);
CharWideString::CharWideString(CharWideString &&p_str) {
SWAP(_length, p_str._length);
SWAP(_data, p_str._data);
}
template class CharStringT<char>;
template class CharStringT<char16_t>;
template class CharStringT<char32_t>;
template class CharStringT<wchar_t>;
void CharWideString::operator=(CharWideString &&p_str) {
SWAP(_length, p_str._length);
SWAP(_data, p_str._data);
}
CharWideString::CharWideString(const wchar_t *str, int length) :
_data(str), _length(length) {}
CharWideString::~CharWideString() {
if (_data != nullptr) {
memdelete_arr(_data);
}
}
// Custom String functions that are not part of bound API.
// It's easier to have them written in C++ directly than in a Python script that generates them.
String::String(const char *from) {
internal::gdextension_interface_string_new_with_latin1_chars(_native_ptr(), from);
internal::gde_interface->string_new_with_latin1_chars(_native_ptr(), from);
}
String::String(const wchar_t *from) {
internal::gdextension_interface_string_new_with_wide_chars(_native_ptr(), from);
internal::gde_interface->string_new_with_wide_chars(_native_ptr(), from);
}
String::String(const char16_t *from) {
internal::gdextension_interface_string_new_with_utf16_chars(_native_ptr(), from);
internal::gde_interface->string_new_with_utf16_chars(_native_ptr(), from);
}
String::String(const char32_t *from) {
internal::gdextension_interface_string_new_with_utf32_chars(_native_ptr(), from);
internal::gde_interface->string_new_with_utf32_chars(_native_ptr(), from);
}
String String::utf8(const char *from, int len) {
@@ -179,7 +175,7 @@ String String::utf8(const char *from, int len) {
}
void String::parse_utf8(const char *from, int len) {
internal::gdextension_interface_string_new_with_utf8_chars_and_len(_native_ptr(), from, len);
internal::gde_interface->string_new_with_utf8_chars_and_len(_native_ptr(), from, len);
}
String String::utf16(const char16_t *from, int len) {
@@ -189,7 +185,7 @@ String String::utf16(const char16_t *from, int len) {
}
void String::parse_utf16(const char16_t *from, int len) {
internal::gdextension_interface_string_new_with_utf16_chars_and_len(_native_ptr(), from, len);
internal::gde_interface->string_new_with_utf16_chars_and_len(_native_ptr(), from, len);
}
String String::num_real(double p_num, bool p_trailing) {
@@ -230,63 +226,58 @@ String rtoss(double p_val) {
}
CharString String::utf8() const {
int length = internal::gdextension_interface_string_to_utf8_chars(_native_ptr(), nullptr, 0);
int length = internal::gde_interface->string_to_utf8_chars(_native_ptr(), nullptr, 0);
int size = length + 1;
CharString str;
str.resize(size);
internal::gdextension_interface_string_to_utf8_chars(_native_ptr(), str.ptrw(), length);
char *cstr = memnew_arr(char, size);
internal::gde_interface->string_to_utf8_chars(_native_ptr(), cstr, length);
str[length] = '\0';
cstr[length] = '\0';
return str;
return CharString(cstr, length);
}
CharString String::ascii() const {
int length = internal::gdextension_interface_string_to_latin1_chars(_native_ptr(), nullptr, 0);
int length = internal::gde_interface->string_to_latin1_chars(_native_ptr(), nullptr, 0);
int size = length + 1;
CharString str;
str.resize(size);
internal::gdextension_interface_string_to_latin1_chars(_native_ptr(), str.ptrw(), length);
char *cstr = memnew_arr(char, size);
internal::gde_interface->string_to_latin1_chars(_native_ptr(), cstr, length);
str[length] = '\0';
cstr[length] = '\0';
return str;
return CharString(cstr, length);
}
Char16String String::utf16() const {
int length = internal::gdextension_interface_string_to_utf16_chars(_native_ptr(), nullptr, 0);
int length = internal::gde_interface->string_to_utf16_chars(_native_ptr(), nullptr, 0);
int size = length + 1;
Char16String str;
str.resize(size);
internal::gdextension_interface_string_to_utf16_chars(_native_ptr(), str.ptrw(), length);
char16_t *cstr = memnew_arr(char16_t, size);
internal::gde_interface->string_to_utf16_chars(_native_ptr(), cstr, length);
str[length] = '\0';
cstr[length] = '\0';
return str;
return Char16String(cstr, length);
}
Char32String String::utf32() const {
int length = internal::gdextension_interface_string_to_utf32_chars(_native_ptr(), nullptr, 0);
int length = internal::gde_interface->string_to_utf32_chars(_native_ptr(), nullptr, 0);
int size = length + 1;
Char32String str;
str.resize(size);
internal::gdextension_interface_string_to_utf32_chars(_native_ptr(), str.ptrw(), length);
char32_t *cstr = memnew_arr(char32_t, size);
internal::gde_interface->string_to_utf32_chars(_native_ptr(), cstr, length);
str[length] = '\0';
cstr[length] = '\0';
return str;
return Char32String(cstr, length);
}
CharWideString String::wide_string() const {
int length = internal::gdextension_interface_string_to_wide_chars(_native_ptr(), nullptr, 0);
int length = internal::gde_interface->string_to_wide_chars(_native_ptr(), nullptr, 0);
int size = length + 1;
CharWideString str;
str.resize(size);
internal::gdextension_interface_string_to_wide_chars(_native_ptr(), str.ptrw(), length);
wchar_t *cstr = memnew_arr(wchar_t, size);
internal::gde_interface->string_to_wide_chars(_native_ptr(), cstr, length);
str[length] = '\0';
cstr[length] = '\0';
return str;
return CharWideString(cstr, length);
}
String &String::operator=(const char *p_str) {
@@ -362,44 +353,44 @@ String String::operator+(const char32_t p_char) {
}
String &String::operator+=(const String &p_str) {
internal::gdextension_interface_string_operator_plus_eq_string((GDExtensionStringPtr)this, (GDExtensionConstStringPtr)&p_str);
internal::gde_interface->string_operator_plus_eq_string((GDExtensionStringPtr)this, (GDExtensionConstStringPtr)&p_str);
return *this;
}
String &String::operator+=(char32_t p_char) {
internal::gdextension_interface_string_operator_plus_eq_char((GDExtensionStringPtr)this, p_char);
internal::gde_interface->string_operator_plus_eq_char((GDExtensionStringPtr)this, p_char);
return *this;
}
String &String::operator+=(const char *p_str) {
internal::gdextension_interface_string_operator_plus_eq_cstr((GDExtensionStringPtr)this, p_str);
internal::gde_interface->string_operator_plus_eq_cstr((GDExtensionStringPtr)this, p_str);
return *this;
}
String &String::operator+=(const wchar_t *p_str) {
internal::gdextension_interface_string_operator_plus_eq_wcstr((GDExtensionStringPtr)this, p_str);
internal::gde_interface->string_operator_plus_eq_wcstr((GDExtensionStringPtr)this, p_str);
return *this;
}
String &String::operator+=(const char32_t *p_str) {
internal::gdextension_interface_string_operator_plus_eq_c32str((GDExtensionStringPtr)this, p_str);
internal::gde_interface->string_operator_plus_eq_c32str((GDExtensionStringPtr)this, p_str);
return *this;
}
const char32_t &String::operator[](int p_index) const {
return *internal::gdextension_interface_string_operator_index_const((GDExtensionStringPtr)this, p_index);
return *internal::gde_interface->string_operator_index_const((GDExtensionStringPtr)this, p_index);
}
char32_t &String::operator[](int p_index) {
return *internal::gdextension_interface_string_operator_index((GDExtensionStringPtr)this, p_index);
return *internal::gde_interface->string_operator_index((GDExtensionStringPtr)this, p_index);
}
const char32_t *String::ptr() const {
return internal::gdextension_interface_string_operator_index_const((GDExtensionStringPtr)this, 0);
return internal::gde_interface->string_operator_index_const((GDExtensionStringPtr)this, 0);
}
char32_t *String::ptrw() {
return internal::gdextension_interface_string_operator_index((GDExtensionStringPtr)this, 0);
return internal::gde_interface->string_operator_index((GDExtensionStringPtr)this, 0);
}
bool operator==(const char *p_chr, const String &p_str) {

View File

@@ -47,183 +47,183 @@
namespace godot {
const uint8_t &PackedByteArray::operator[](int p_index) const {
return *internal::gdextension_interface_packed_byte_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
return *internal::gde_interface->packed_byte_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
}
uint8_t &PackedByteArray::operator[](int p_index) {
return *internal::gdextension_interface_packed_byte_array_operator_index((GDExtensionTypePtr *)this, p_index);
return *internal::gde_interface->packed_byte_array_operator_index((GDExtensionTypePtr *)this, p_index);
}
const uint8_t *PackedByteArray::ptr() const {
return internal::gdextension_interface_packed_byte_array_operator_index_const((GDExtensionTypePtr *)this, 0);
return internal::gde_interface->packed_byte_array_operator_index_const((GDExtensionTypePtr *)this, 0);
}
uint8_t *PackedByteArray::ptrw() {
return internal::gdextension_interface_packed_byte_array_operator_index((GDExtensionTypePtr *)this, 0);
return internal::gde_interface->packed_byte_array_operator_index((GDExtensionTypePtr *)this, 0);
}
const Color &PackedColorArray::operator[](int p_index) const {
const Color *color = (const Color *)internal::gdextension_interface_packed_color_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
const Color *color = (const Color *)internal::gde_interface->packed_color_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
return *color;
}
Color &PackedColorArray::operator[](int p_index) {
Color *color = (Color *)internal::gdextension_interface_packed_color_array_operator_index((GDExtensionTypePtr *)this, p_index);
Color *color = (Color *)internal::gde_interface->packed_color_array_operator_index((GDExtensionTypePtr *)this, p_index);
return *color;
}
const Color *PackedColorArray::ptr() const {
return (const Color *)internal::gdextension_interface_packed_color_array_operator_index_const((GDExtensionTypePtr *)this, 0);
return (const Color *)internal::gde_interface->packed_color_array_operator_index_const((GDExtensionTypePtr *)this, 0);
}
Color *PackedColorArray::ptrw() {
return (Color *)internal::gdextension_interface_packed_color_array_operator_index((GDExtensionTypePtr *)this, 0);
return (Color *)internal::gde_interface->packed_color_array_operator_index((GDExtensionTypePtr *)this, 0);
}
const float &PackedFloat32Array::operator[](int p_index) const {
return *internal::gdextension_interface_packed_float32_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
return *internal::gde_interface->packed_float32_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
}
float &PackedFloat32Array::operator[](int p_index) {
return *internal::gdextension_interface_packed_float32_array_operator_index((GDExtensionTypePtr *)this, p_index);
return *internal::gde_interface->packed_float32_array_operator_index((GDExtensionTypePtr *)this, p_index);
}
const float *PackedFloat32Array::ptr() const {
return internal::gdextension_interface_packed_float32_array_operator_index_const((GDExtensionTypePtr *)this, 0);
return internal::gde_interface->packed_float32_array_operator_index_const((GDExtensionTypePtr *)this, 0);
}
float *PackedFloat32Array::ptrw() {
return internal::gdextension_interface_packed_float32_array_operator_index((GDExtensionTypePtr *)this, 0);
return internal::gde_interface->packed_float32_array_operator_index((GDExtensionTypePtr *)this, 0);
}
const double &PackedFloat64Array::operator[](int p_index) const {
return *internal::gdextension_interface_packed_float64_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
return *internal::gde_interface->packed_float64_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
}
double &PackedFloat64Array::operator[](int p_index) {
return *internal::gdextension_interface_packed_float64_array_operator_index((GDExtensionTypePtr *)this, p_index);
return *internal::gde_interface->packed_float64_array_operator_index((GDExtensionTypePtr *)this, p_index);
}
const double *PackedFloat64Array::ptr() const {
return internal::gdextension_interface_packed_float64_array_operator_index_const((GDExtensionTypePtr *)this, 0);
return internal::gde_interface->packed_float64_array_operator_index_const((GDExtensionTypePtr *)this, 0);
}
double *PackedFloat64Array::ptrw() {
return internal::gdextension_interface_packed_float64_array_operator_index((GDExtensionTypePtr *)this, 0);
return internal::gde_interface->packed_float64_array_operator_index((GDExtensionTypePtr *)this, 0);
}
const int32_t &PackedInt32Array::operator[](int p_index) const {
return *internal::gdextension_interface_packed_int32_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
return *internal::gde_interface->packed_int32_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
}
int32_t &PackedInt32Array::operator[](int p_index) {
return *internal::gdextension_interface_packed_int32_array_operator_index((GDExtensionTypePtr *)this, p_index);
return *internal::gde_interface->packed_int32_array_operator_index((GDExtensionTypePtr *)this, p_index);
}
const int32_t *PackedInt32Array::ptr() const {
return internal::gdextension_interface_packed_int32_array_operator_index_const((GDExtensionTypePtr *)this, 0);
return internal::gde_interface->packed_int32_array_operator_index_const((GDExtensionTypePtr *)this, 0);
}
int32_t *PackedInt32Array::ptrw() {
return internal::gdextension_interface_packed_int32_array_operator_index((GDExtensionTypePtr *)this, 0);
return internal::gde_interface->packed_int32_array_operator_index((GDExtensionTypePtr *)this, 0);
}
const int64_t &PackedInt64Array::operator[](int p_index) const {
return *internal::gdextension_interface_packed_int64_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
return *internal::gde_interface->packed_int64_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
}
int64_t &PackedInt64Array::operator[](int p_index) {
return *internal::gdextension_interface_packed_int64_array_operator_index((GDExtensionTypePtr *)this, p_index);
return *internal::gde_interface->packed_int64_array_operator_index((GDExtensionTypePtr *)this, p_index);
}
const int64_t *PackedInt64Array::ptr() const {
return internal::gdextension_interface_packed_int64_array_operator_index_const((GDExtensionTypePtr *)this, 0);
return internal::gde_interface->packed_int64_array_operator_index_const((GDExtensionTypePtr *)this, 0);
}
int64_t *PackedInt64Array::ptrw() {
return internal::gdextension_interface_packed_int64_array_operator_index((GDExtensionTypePtr *)this, 0);
return internal::gde_interface->packed_int64_array_operator_index((GDExtensionTypePtr *)this, 0);
}
const String &PackedStringArray::operator[](int p_index) const {
const String *string = (const String *)internal::gdextension_interface_packed_string_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
const String *string = (const String *)internal::gde_interface->packed_string_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
return *string;
}
String &PackedStringArray::operator[](int p_index) {
String *string = (String *)internal::gdextension_interface_packed_string_array_operator_index((GDExtensionTypePtr *)this, p_index);
String *string = (String *)internal::gde_interface->packed_string_array_operator_index((GDExtensionTypePtr *)this, p_index);
return *string;
}
const String *PackedStringArray::ptr() const {
return (const String *)internal::gdextension_interface_packed_string_array_operator_index_const((GDExtensionTypePtr *)this, 0);
return (const String *)internal::gde_interface->packed_string_array_operator_index_const((GDExtensionTypePtr *)this, 0);
}
String *PackedStringArray::ptrw() {
return (String *)internal::gdextension_interface_packed_string_array_operator_index((GDExtensionTypePtr *)this, 0);
return (String *)internal::gde_interface->packed_string_array_operator_index((GDExtensionTypePtr *)this, 0);
}
const Vector2 &PackedVector2Array::operator[](int p_index) const {
const Vector2 *vec = (const Vector2 *)internal::gdextension_interface_packed_vector2_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
const Vector2 *vec = (const Vector2 *)internal::gde_interface->packed_vector2_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
return *vec;
}
Vector2 &PackedVector2Array::operator[](int p_index) {
Vector2 *vec = (Vector2 *)internal::gdextension_interface_packed_vector2_array_operator_index((GDExtensionTypePtr *)this, p_index);
Vector2 *vec = (Vector2 *)internal::gde_interface->packed_vector2_array_operator_index((GDExtensionTypePtr *)this, p_index);
return *vec;
}
const Vector2 *PackedVector2Array::ptr() const {
return (const Vector2 *)internal::gdextension_interface_packed_vector2_array_operator_index_const((GDExtensionTypePtr *)this, 0);
return (const Vector2 *)internal::gde_interface->packed_vector2_array_operator_index_const((GDExtensionTypePtr *)this, 0);
}
Vector2 *PackedVector2Array::ptrw() {
return (Vector2 *)internal::gdextension_interface_packed_vector2_array_operator_index((GDExtensionTypePtr *)this, 0);
return (Vector2 *)internal::gde_interface->packed_vector2_array_operator_index((GDExtensionTypePtr *)this, 0);
}
const Vector3 &PackedVector3Array::operator[](int p_index) const {
const Vector3 *vec = (const Vector3 *)internal::gdextension_interface_packed_vector3_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
const Vector3 *vec = (const Vector3 *)internal::gde_interface->packed_vector3_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
return *vec;
}
Vector3 &PackedVector3Array::operator[](int p_index) {
Vector3 *vec = (Vector3 *)internal::gdextension_interface_packed_vector3_array_operator_index((GDExtensionTypePtr *)this, p_index);
Vector3 *vec = (Vector3 *)internal::gde_interface->packed_vector3_array_operator_index((GDExtensionTypePtr *)this, p_index);
return *vec;
}
const Vector3 *PackedVector3Array::ptr() const {
return (const Vector3 *)internal::gdextension_interface_packed_vector3_array_operator_index_const((GDExtensionTypePtr *)this, 0);
return (const Vector3 *)internal::gde_interface->packed_vector3_array_operator_index_const((GDExtensionTypePtr *)this, 0);
}
Vector3 *PackedVector3Array::ptrw() {
return (Vector3 *)internal::gdextension_interface_packed_vector3_array_operator_index((GDExtensionTypePtr *)this, 0);
return (Vector3 *)internal::gde_interface->packed_vector3_array_operator_index((GDExtensionTypePtr *)this, 0);
}
const Variant &Array::operator[](int p_index) const {
const Variant *var = (const Variant *)internal::gdextension_interface_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
const Variant *var = (const Variant *)internal::gde_interface->array_operator_index_const((GDExtensionTypePtr *)this, p_index);
return *var;
}
Variant &Array::operator[](int p_index) {
Variant *var = (Variant *)internal::gdextension_interface_array_operator_index((GDExtensionTypePtr *)this, p_index);
Variant *var = (Variant *)internal::gde_interface->array_operator_index((GDExtensionTypePtr *)this, p_index);
return *var;
}
void Array::set_typed(uint32_t p_type, const StringName &p_class_name, const Variant &p_script) {
// p_type is not Variant::Type so that header doesn't depend on <variant.hpp>.
internal::gdextension_interface_array_set_typed((GDExtensionTypePtr *)this, (GDExtensionVariantType)p_type, (GDExtensionConstStringNamePtr)&p_class_name, (GDExtensionConstVariantPtr)&p_script);
internal::gde_interface->array_set_typed((GDExtensionTypePtr *)this, (GDExtensionVariantType)p_type, (GDExtensionConstStringNamePtr)&p_class_name, (GDExtensionConstVariantPtr)&p_script);
}
void Array::_ref(const Array &p_from) const {
internal::gdextension_interface_array_ref((GDExtensionTypePtr *)this, (GDExtensionConstTypePtr *)&p_from);
internal::gde_interface->array_ref((GDExtensionTypePtr *)this, (GDExtensionConstTypePtr *)&p_from);
}
const Variant &Dictionary::operator[](const Variant &p_key) const {
const Variant *var = (const Variant *)internal::gdextension_interface_dictionary_operator_index_const((GDExtensionTypePtr *)this, (GDExtensionVariantPtr)&p_key);
const Variant *var = (const Variant *)internal::gde_interface->dictionary_operator_index_const((GDExtensionTypePtr *)this, (GDExtensionVariantPtr)&p_key);
return *var;
}
Variant &Dictionary::operator[](const Variant &p_key) {
Variant *var = (Variant *)internal::gdextension_interface_dictionary_operator_index((GDExtensionTypePtr *)this, (GDExtensionVariantPtr)&p_key);
Variant *var = (Variant *)internal::gde_interface->dictionary_operator_index((GDExtensionTypePtr *)this, (GDExtensionVariantPtr)&p_key);
return *var;
}

View File

@@ -33,7 +33,6 @@
#include <godot_cpp/godot.hpp>
#include <godot_cpp/core/binder_common.hpp>
#include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/core/defs.hpp>
#include <utility>
@@ -46,8 +45,8 @@ GDExtensionTypeFromVariantConstructorFunc Variant::to_type_constructor[Variant::
void Variant::init_bindings() {
// Start from 1 to skip NIL.
for (int i = 1; i < VARIANT_MAX; i++) {
from_type_constructor[i] = internal::gdextension_interface_get_variant_from_type_constructor((GDExtensionVariantType)i);
to_type_constructor[i] = internal::gdextension_interface_get_variant_to_type_constructor((GDExtensionVariantType)i);
from_type_constructor[i] = internal::gde_interface->get_variant_from_type_constructor((GDExtensionVariantType)i);
to_type_constructor[i] = internal::gde_interface->get_variant_to_type_constructor((GDExtensionVariantType)i);
}
StringName::init_bindings();
@@ -70,15 +69,15 @@ void Variant::init_bindings() {
}
Variant::Variant() {
internal::gdextension_interface_variant_new_nil(_native_ptr());
internal::gde_interface->variant_new_nil(_native_ptr());
}
Variant::Variant(GDExtensionConstVariantPtr native_ptr) {
internal::gdextension_interface_variant_new_copy(_native_ptr(), native_ptr);
internal::gde_interface->variant_new_copy(_native_ptr(), native_ptr);
}
Variant::Variant(const Variant &other) {
internal::gdextension_interface_variant_new_copy(_native_ptr(), other._native_ptr());
internal::gde_interface->variant_new_copy(_native_ptr(), other._native_ptr());
}
Variant::Variant(Variant &&other) {
@@ -249,7 +248,7 @@ Variant::Variant(const PackedColorArray &v) {
}
Variant::~Variant() {
internal::gdextension_interface_variant_destroy(_native_ptr());
internal::gde_interface->variant_destroy(_native_ptr());
}
Variant::operator bool() const {
@@ -412,7 +411,7 @@ Variant::operator Object *() const {
if (obj == nullptr) {
return nullptr;
}
return internal::get_object_instance_binding(obj);
return reinterpret_cast<Object *>(internal::gde_interface->object_get_instance_binding(obj, internal::token, &Object::___binding_callbacks));
}
Variant::operator ObjectID() const {
@@ -510,7 +509,7 @@ Variant::operator PackedColorArray() const {
Variant &Variant::operator=(const Variant &other) {
clear();
internal::gdextension_interface_variant_new_copy(_native_ptr(), other._native_ptr());
internal::gde_interface->variant_new_copy(_native_ptr(), other._native_ptr());
return *this;
}
@@ -550,22 +549,22 @@ bool Variant::operator<(const Variant &other) const {
}
void Variant::call(const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error) {
internal::gdextension_interface_variant_call(_native_ptr(), method._native_ptr(), reinterpret_cast<GDExtensionConstVariantPtr *>(args), argcount, r_ret._native_ptr(), &r_error);
internal::gde_interface->variant_call(_native_ptr(), method._native_ptr(), reinterpret_cast<GDExtensionConstVariantPtr *>(args), argcount, r_ret._native_ptr(), &r_error);
}
void Variant::call_static(Variant::Type type, const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error) {
internal::gdextension_interface_variant_call_static(static_cast<GDExtensionVariantType>(type), method._native_ptr(), reinterpret_cast<GDExtensionConstVariantPtr *>(args), argcount, r_ret._native_ptr(), &r_error);
internal::gde_interface->variant_call_static(static_cast<GDExtensionVariantType>(type), method._native_ptr(), reinterpret_cast<GDExtensionConstVariantPtr *>(args), argcount, r_ret._native_ptr(), &r_error);
}
void Variant::evaluate(const Operator &op, const Variant &a, const Variant &b, Variant &r_ret, bool &r_valid) {
GDExtensionBool valid;
internal::gdextension_interface_variant_evaluate(static_cast<GDExtensionVariantOperator>(op), a._native_ptr(), b._native_ptr(), r_ret._native_ptr(), &valid);
internal::gde_interface->variant_evaluate(static_cast<GDExtensionVariantOperator>(op), a._native_ptr(), b._native_ptr(), r_ret._native_ptr(), &valid);
r_valid = PtrToArg<bool>::convert(&valid);
}
void Variant::set(const Variant &key, const Variant &value, bool *r_valid) {
GDExtensionBool valid;
internal::gdextension_interface_variant_set(_native_ptr(), key._native_ptr(), value._native_ptr(), &valid);
internal::gde_interface->variant_set(_native_ptr(), key._native_ptr(), value._native_ptr(), &valid);
if (r_valid) {
*r_valid = PtrToArg<bool>::convert(&valid);
}
@@ -573,27 +572,27 @@ void Variant::set(const Variant &key, const Variant &value, bool *r_valid) {
void Variant::set_named(const StringName &name, const Variant &value, bool &r_valid) {
GDExtensionBool valid;
internal::gdextension_interface_variant_set_named(_native_ptr(), name._native_ptr(), value._native_ptr(), &valid);
internal::gde_interface->variant_set_named(_native_ptr(), name._native_ptr(), value._native_ptr(), &valid);
r_valid = PtrToArg<bool>::convert(&valid);
}
void Variant::set_indexed(int64_t index, const Variant &value, bool &r_valid, bool &r_oob) {
GDExtensionBool valid, oob;
internal::gdextension_interface_variant_set_indexed(_native_ptr(), index, value._native_ptr(), &valid, &oob);
internal::gde_interface->variant_set_indexed(_native_ptr(), index, value._native_ptr(), &valid, &oob);
r_valid = PtrToArg<bool>::convert(&valid);
r_oob = PtrToArg<bool>::convert(&oob);
}
void Variant::set_keyed(const Variant &key, const Variant &value, bool &r_valid) {
GDExtensionBool valid;
internal::gdextension_interface_variant_set_keyed(_native_ptr(), key._native_ptr(), value._native_ptr(), &valid);
internal::gde_interface->variant_set_keyed(_native_ptr(), key._native_ptr(), value._native_ptr(), &valid);
r_valid = PtrToArg<bool>::convert(&valid);
}
Variant Variant::get(const Variant &key, bool *r_valid) const {
Variant result;
GDExtensionBool valid;
internal::gdextension_interface_variant_get(_native_ptr(), key._native_ptr(), result._native_ptr(), &valid);
internal::gde_interface->variant_get(_native_ptr(), key._native_ptr(), result._native_ptr(), &valid);
if (r_valid) {
*r_valid = PtrToArg<bool>::convert(&valid);
}
@@ -603,7 +602,7 @@ Variant Variant::get(const Variant &key, bool *r_valid) const {
Variant Variant::get_named(const StringName &name, bool &r_valid) const {
Variant result;
GDExtensionBool valid;
internal::gdextension_interface_variant_get_named(_native_ptr(), name._native_ptr(), result._native_ptr(), &valid);
internal::gde_interface->variant_get_named(_native_ptr(), name._native_ptr(), result._native_ptr(), &valid);
r_valid = PtrToArg<bool>::convert(&valid);
return result;
}
@@ -612,7 +611,7 @@ Variant Variant::get_indexed(int64_t index, bool &r_valid, bool &r_oob) const {
Variant result;
GDExtensionBool valid;
GDExtensionBool oob;
internal::gdextension_interface_variant_get_indexed(_native_ptr(), index, result._native_ptr(), &valid, &oob);
internal::gde_interface->variant_get_indexed(_native_ptr(), index, result._native_ptr(), &valid, &oob);
r_valid = PtrToArg<bool>::convert(&valid);
r_oob = PtrToArg<bool>::convert(&oob);
return result;
@@ -621,7 +620,7 @@ Variant Variant::get_indexed(int64_t index, bool &r_valid, bool &r_oob) const {
Variant Variant::get_keyed(const Variant &key, bool &r_valid) const {
Variant result;
GDExtensionBool valid;
internal::gdextension_interface_variant_get_keyed(_native_ptr(), key._native_ptr(), result._native_ptr(), &valid);
internal::gde_interface->variant_get_keyed(_native_ptr(), key._native_ptr(), result._native_ptr(), &valid);
r_valid = PtrToArg<bool>::convert(&valid);
return result;
}
@@ -638,36 +637,36 @@ bool Variant::in(const Variant &index, bool *r_valid) const {
bool Variant::iter_init(Variant &r_iter, bool &r_valid) const {
GDExtensionBool valid;
internal::gdextension_interface_variant_iter_init(_native_ptr(), r_iter._native_ptr(), &valid);
internal::gde_interface->variant_iter_init(_native_ptr(), r_iter._native_ptr(), &valid);
return PtrToArg<bool>::convert(&valid);
}
bool Variant::iter_next(Variant &r_iter, bool &r_valid) const {
GDExtensionBool valid;
internal::gdextension_interface_variant_iter_next(_native_ptr(), r_iter._native_ptr(), &valid);
internal::gde_interface->variant_iter_next(_native_ptr(), r_iter._native_ptr(), &valid);
return PtrToArg<bool>::convert(&valid);
}
Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
Variant result;
GDExtensionBool valid;
internal::gdextension_interface_variant_iter_get(_native_ptr(), r_iter._native_ptr(), result._native_ptr(), &valid);
internal::gde_interface->variant_iter_get(_native_ptr(), r_iter._native_ptr(), result._native_ptr(), &valid);
r_valid = PtrToArg<bool>::convert(&valid);
return result;
}
Variant::Type Variant::get_type() const {
return static_cast<Variant::Type>(internal::gdextension_interface_variant_get_type(_native_ptr()));
return static_cast<Variant::Type>(internal::gde_interface->variant_get_type(_native_ptr()));
}
bool Variant::has_method(const StringName &method) const {
GDExtensionBool has = internal::gdextension_interface_variant_has_method(_native_ptr(), method._native_ptr());
GDExtensionBool has = internal::gde_interface->variant_has_method(_native_ptr(), method._native_ptr());
return PtrToArg<bool>::convert(&has);
}
bool Variant::has_key(const Variant &key, bool *r_valid) const {
GDExtensionBool valid;
GDExtensionBool has = internal::gdextension_interface_variant_has_key(_native_ptr(), key._native_ptr(), &valid);
GDExtensionBool has = internal::gde_interface->variant_has_key(_native_ptr(), key._native_ptr(), &valid);
if (r_valid) {
*r_valid = PtrToArg<bool>::convert(&valid);
}
@@ -675,33 +674,33 @@ bool Variant::has_key(const Variant &key, bool *r_valid) const {
}
bool Variant::has_member(Variant::Type type, const StringName &member) {
GDExtensionBool has = internal::gdextension_interface_variant_has_member(static_cast<GDExtensionVariantType>(type), member._native_ptr());
GDExtensionBool has = internal::gde_interface->variant_has_member(static_cast<GDExtensionVariantType>(type), member._native_ptr());
return PtrToArg<bool>::convert(&has);
}
uint32_t Variant::hash() const {
GDExtensionInt hash = internal::gdextension_interface_variant_hash(_native_ptr());
GDExtensionInt hash = internal::gde_interface->variant_hash(_native_ptr());
return PtrToArg<uint32_t>::convert(&hash);
}
uint32_t Variant::recursive_hash(int recursion_count) const {
GDExtensionInt hash = internal::gdextension_interface_variant_recursive_hash(_native_ptr(), recursion_count);
GDExtensionInt hash = internal::gde_interface->variant_recursive_hash(_native_ptr(), recursion_count);
return PtrToArg<uint32_t>::convert(&hash);
}
bool Variant::hash_compare(const Variant &variant) const {
GDExtensionBool compare = internal::gdextension_interface_variant_hash_compare(_native_ptr(), variant._native_ptr());
GDExtensionBool compare = internal::gde_interface->variant_hash_compare(_native_ptr(), variant._native_ptr());
return PtrToArg<bool>::convert(&compare);
}
bool Variant::booleanize() const {
GDExtensionBool booleanized = internal::gdextension_interface_variant_booleanize(_native_ptr());
GDExtensionBool booleanized = internal::gde_interface->variant_booleanize(_native_ptr());
return PtrToArg<bool>::convert(&booleanized);
}
String Variant::stringify() const {
String result;
internal::gdextension_interface_variant_stringify(_native_ptr(), result._native_ptr());
internal::gde_interface->variant_stringify(_native_ptr(), result._native_ptr());
return result;
}
@@ -709,23 +708,23 @@ Variant Variant::duplicate(bool deep) const {
Variant result;
GDExtensionBool _deep;
PtrToArg<bool>::encode(deep, &_deep);
internal::gdextension_interface_variant_duplicate(_native_ptr(), result._native_ptr(), _deep);
internal::gde_interface->variant_duplicate(_native_ptr(), result._native_ptr(), _deep);
return result;
}
String Variant::get_type_name(Variant::Type type) {
String result;
internal::gdextension_interface_variant_get_type_name(static_cast<GDExtensionVariantType>(type), result._native_ptr());
internal::gde_interface->variant_get_type_name(static_cast<GDExtensionVariantType>(type), result._native_ptr());
return result;
}
bool Variant::can_convert(Variant::Type from, Variant::Type to) {
GDExtensionBool can = internal::gdextension_interface_variant_can_convert(static_cast<GDExtensionVariantType>(from), static_cast<GDExtensionVariantType>(to));
GDExtensionBool can = internal::gde_interface->variant_can_convert(static_cast<GDExtensionVariantType>(from), static_cast<GDExtensionVariantType>(to));
return PtrToArg<bool>::convert(&can);
}
bool Variant::can_convert_strict(Variant::Type from, Variant::Type to) {
GDExtensionBool can = internal::gdextension_interface_variant_can_convert_strict(static_cast<GDExtensionVariantType>(from), static_cast<GDExtensionVariantType>(to));
GDExtensionBool can = internal::gde_interface->variant_can_convert_strict(static_cast<GDExtensionVariantType>(from), static_cast<GDExtensionVariantType>(to));
return PtrToArg<bool>::convert(&can);
}
@@ -776,9 +775,9 @@ void Variant::clear() {
};
if (unlikely(needs_deinit[get_type()])) { // Make it fast for types that don't need deinit.
internal::gdextension_interface_variant_destroy(_native_ptr());
internal::gde_interface->variant_destroy(_native_ptr());
}
internal::gdextension_interface_variant_new_nil(_native_ptr());
internal::gde_interface->variant_new_nil(_native_ptr());
}
} // namespace godot

View File

@@ -1,8 +1,11 @@
# godot-cpp integration test
# godot-cpp example / integration test
This project is used to perform integration testing of the godot-cpp
extension, to validate PRs and implemented APIs.
It can also be used as a quick example of how to set up a godot-cpp
project, both on the C++ side and in the Godot project itself.
## License
This is free and unencumbered software released into the public domain.

View File

@@ -18,14 +18,14 @@ sources = Glob("src/*.cpp")
if env["platform"] == "macos":
library = env.SharedLibrary(
"project/bin/libgdexample.{}.{}.framework/libgdexample.{}.{}".format(
"demo/bin/libgdexample.{}.{}.framework/libgdexample.{}.{}".format(
env["platform"], env["target"], env["platform"], env["target"]
),
source=sources,
)
else:
library = env.SharedLibrary(
"project/bin/libgdexample{}{}".format(env["suffix"], env["SHLIBSUFFIX"]),
"demo/bin/libgdexample{}{}".format(env["suffix"], env["SHLIBSUFFIX"]),
source=sources,
)

View File

@@ -4,4 +4,4 @@
[resource]
background_mode = 2
sky = SubResource("1")
sky = SubResource( "1" )

View File

@@ -1,7 +1,6 @@
[configuration]
entry_symbol = "example_library_init"
compatibility_minimum = "4.1"
[libraries]

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -16,9 +16,9 @@ dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.cte
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false

80
test/demo/main.gd Normal file
View File

@@ -0,0 +1,80 @@
extends Node
func _ready():
# Bind signals
prints("Signal bind")
$Button.button_up.connect($Example.emit_custom_signal.bind("Button", 42))
prints("")
# To string.
prints("To string")
prints(" Example --> ", $Example.to_string())
prints(" ExampleMin --> ", $Example/ExampleMin.to_string())
# Call static methods.
prints("Static method calls")
prints(" static (109)", Example.test_static(9, 100));
Example.test_static2();
# Property list.
prints("Property list")
$Example.property_from_list = Vector3(100, 200, 300)
prints(" property value ", $Example.property_from_list)
# Call methods.
prints("Instance method calls")
$Example.simple_func()
($Example as Example).simple_const_func() # Force use of ptrcall
prints(" returned", $Example.return_something("some string"))
prints(" returned const", $Example.return_something_const())
var null_ref = $Example.return_empty_ref()
prints(" returned empty ref", null_ref)
var ret_ref = $Example.return_extended_ref()
prints(" returned ref", ret_ref.get_instance_id(), ", id:", ret_ref.get_id())
prints(" returned ", $Example.get_v4())
prints(" test node argument", $Example.test_node_argument($Example))
prints("VarArg method calls")
var ref = ExampleRef.new()
prints(" sending ref: ", ref.get_instance_id(), "returned ref: ", $Example.extended_ref_checks(ref).get_instance_id())
prints(" vararg args", $Example.varargs_func("some", "arguments", "to", "test"))
prints(" vararg_nv ret", $Example.varargs_func_nv("some", "arguments", "to", "test"))
$Example.varargs_func_void("some", "arguments", "to", "test")
prints("Method calls with default values")
prints(" defval (300)", $Example.def_args())
prints(" defval (250)", $Example.def_args(50))
prints(" defval (150)", $Example.def_args(50, 100))
prints("Array and Dictionary")
prints(" test array", $Example.test_array())
prints(" test tarray", $Example.test_tarray())
prints(" test dictionary", $Example.test_dictionary())
var array: Array[int] = [1, 2, 3]
$Example.test_tarray_arg(array)
prints("String += operator")
prints(" test string +=", $Example.test_string_ops())
prints("PackedArray iterators")
prints(" test packed array iterators", $Example.test_vector_ops())
prints("Properties")
prints(" custom position is", $Example.group_subgroup_custom_position)
$Example.group_subgroup_custom_position = Vector2(50, 50)
prints(" custom position now is", $Example.group_subgroup_custom_position)
prints("Constants")
prints(" FIRST", $Example.FIRST)
prints(" ANSWER_TO_EVERYTHING", $Example.ANSWER_TO_EVERYTHING)
prints(" CONSTANT_WITHOUT_ENUM", $Example.CONSTANT_WITHOUT_ENUM)
prints("BitFields")
prints(" FLAG_ONE", Example.FLAG_ONE)
prints(" FLAG_TWO", Example.FLAG_TWO)
prints(" returned BitField", $Example.test_bitfield(0))
prints(" returned BitField", $Example.test_bitfield(Example.FLAG_ONE | Example.FLAG_TWO))
func _on_Example_custom_signal(signal_name, value):
prints("Example emitted:", signal_name, value)

View File

@@ -1,9 +1,9 @@
[gd_scene load_steps=2 format=3 uid="uid://dmx2xuigcpvt4"]
[ext_resource type="Script" path="res://main.gd" id="1_qesh5"]
[ext_resource type="Script" path="res://main.gd" id="1_c326s"]
[node name="Node" type="Node"]
script = ExtResource("1_qesh5")
script = ExtResource("1_c326s")
[node name="Example" type="Example" parent="."]

View File

@@ -12,7 +12,7 @@ config_version=5
config/name="GDExtension Test Project"
run/main_scene="res://main.tscn"
config/features=PackedStringArray("4.1")
config/features=PackedStringArray("4.0")
config/icon="res://icon.png"
[native_extensions]

View File

@@ -1,168 +0,0 @@
extends "res://test_base.gd"
var custom_signal_emitted = null
func _ready():
var example: Example = $Example
# Signal.
example.emit_custom_signal("Button", 42)
assert_equal(custom_signal_emitted, ["Button", 42])
# To string.
assert_equal(example.to_string(),'Example:[ GDExtension::Example <--> Instance ID:%s ]' % example.get_instance_id())
# It appears there's a bug with instance ids :-(
#assert_equal($Example/ExampleMin.to_string(), 'ExampleMin:[Wrapped:%s]' % $Example/ExampleMin.get_instance_id())
# Call static methods.
assert_equal(Example.test_static(9, 100), 109);
# It's void and static, so all we know is that it didn't crash.
Example.test_static2()
# Property list.
example.property_from_list = Vector3(100, 200, 300)
assert_equal(example.property_from_list, Vector3(100, 200, 300))
# Call simple methods.
example.simple_func()
assert_equal(custom_signal_emitted, ['simple_func', 3])
example.simple_const_func()
assert_equal(custom_signal_emitted, ['simple_const_func', 4])
# Pass custom reference.
assert_equal(example.custom_ref_func(null), -1)
var ref1 = ExampleRef.new()
ref1.id = 27
assert_equal(example.custom_ref_func(ref1), 27)
ref1.id += 1;
assert_equal(example.custom_const_ref_func(ref1), 28)
# Pass core reference.
assert_equal(example.image_ref_func(null), "invalid")
assert_equal(example.image_const_ref_func(null), "invalid")
var image = Image.new()
assert_equal(example.image_ref_func(image), "valid")
assert_equal(example.image_const_ref_func(image), "valid")
# Return values.
assert_equal(example.return_something("some string"), "some string42")
assert_equal(example.return_something_const(), get_viewport())
var null_ref = example.return_empty_ref()
assert_equal(null_ref, null)
var ret_ref = example.return_extended_ref()
assert_not_equal(ret_ref.get_instance_id(), 0)
assert_equal(ret_ref.get_id(), 0)
assert_equal(example.get_v4(), Vector4(1.2, 3.4, 5.6, 7.8))
assert_equal(example.test_node_argument(example), example)
# VarArg method calls.
var var_ref = ExampleRef.new()
assert_not_equal(example.extended_ref_checks(var_ref).get_instance_id(), var_ref.get_instance_id())
assert_equal(example.varargs_func("some", "arguments", "to", "test"), 4)
assert_equal(example.varargs_func_nv("some", "arguments", "to", "test"), 46)
example.varargs_func_void("some", "arguments", "to", "test")
assert_equal(custom_signal_emitted, ["varargs_func_void", 5])
# Method calls with default values.
assert_equal(example.def_args(), 300)
assert_equal(example.def_args(50), 250)
assert_equal(example.def_args(50, 100), 150)
# Array and Dictionary
assert_equal(example.test_array(), [1, 2])
assert_equal(example.test_tarray(), [ Vector2(1, 2), Vector2(2, 3) ])
assert_equal(example.test_dictionary(), {"hello": "world", "foo": "bar"})
var array: Array[int] = [1, 2, 3]
assert_equal(example.test_tarray_arg(array), 6)
# String += operator
assert_equal(example.test_string_ops(), "ABCĎE")
# UtilityFunctions::str()
assert_equal(example.test_str_utility(), "Hello, World! The answer is 42")
# Test converting string to char* and doing comparison.
assert_equal(example.test_string_is_fourty_two("blah"), false)
assert_equal(example.test_string_is_fourty_two("fourty two"), true)
# PackedArray iterators
assert_equal(example.test_vector_ops(), 105)
# Properties.
assert_equal(example.group_subgroup_custom_position, Vector2(0, 0))
example.group_subgroup_custom_position = Vector2(50, 50)
assert_equal(example.group_subgroup_custom_position, Vector2(50, 50))
# Test Object::cast_to<>() and that correct wrappers are being used.
var control = Control.new()
var sprite = Sprite2D.new()
var example_ref = ExampleRef.new()
assert_equal(example.test_object_cast_to_node(control), true)
assert_equal(example.test_object_cast_to_control(control), true)
assert_equal(example.test_object_cast_to_example(control), false)
assert_equal(example.test_object_cast_to_node(example), true)
assert_equal(example.test_object_cast_to_control(example), true)
assert_equal(example.test_object_cast_to_example(example), true)
assert_equal(example.test_object_cast_to_node(sprite), true)
assert_equal(example.test_object_cast_to_control(sprite), false)
assert_equal(example.test_object_cast_to_example(sprite), false)
assert_equal(example.test_object_cast_to_node(example_ref), false)
assert_equal(example.test_object_cast_to_control(example_ref), false)
assert_equal(example.test_object_cast_to_example(example_ref), false)
control.queue_free()
sprite.queue_free()
# Test conversions to and from Variant.
assert_equal(example.test_variant_vector2i_conversion(Vector2i(1, 1)), Vector2i(1, 1))
assert_equal(example.test_variant_vector2i_conversion(Vector2(1.0, 1.0)), Vector2i(1, 1))
assert_equal(example.test_variant_int_conversion(10), 10)
assert_equal(example.test_variant_int_conversion(10.0), 10)
assert_equal(example.test_variant_float_conversion(10.0), 10.0)
assert_equal(example.test_variant_float_conversion(10), 10.0)
# Test that ptrcalls from GDExtension to the engine are correctly encoding Object and RefCounted.
var new_node = Node.new()
example.test_add_child(new_node)
assert_equal(new_node.get_parent(), example)
var new_tileset = TileSet.new()
var new_tilemap = TileMap.new()
example.test_set_tileset(new_tilemap, new_tileset)
assert_equal(new_tilemap.tile_set, new_tileset)
new_tilemap.queue_free()
# Constants.
assert_equal(Example.FIRST, 0)
assert_equal(Example.ANSWER_TO_EVERYTHING, 42)
assert_equal(Example.CONSTANT_WITHOUT_ENUM, 314)
# BitFields.
assert_equal(Example.FLAG_ONE, 1)
assert_equal(Example.FLAG_TWO, 2)
assert_equal(example.test_bitfield(0), 0)
assert_equal(example.test_bitfield(Example.FLAG_ONE | Example.FLAG_TWO), 3)
# RPCs.
assert_equal(example.return_last_rpc_arg(), 0)
example.test_rpc(42)
assert_equal(example.return_last_rpc_arg(), 42)
example.test_send_rpc(100)
assert_equal(example.return_last_rpc_arg(), 100)
# Virtual method.
var event = InputEventKey.new()
event.key_label = KEY_H
event.unicode = 72
get_viewport().push_input(event)
assert_equal(custom_signal_emitted, ["_input: H", 72])
exit_with_status()
func _on_Example_custom_signal(signal_name, value):
custom_signal_emitted = [signal_name, value]

View File

@@ -1,59 +0,0 @@
extends Node
var test_passes := 0
var test_failures := 0
func __get_stack_frame():
var me = get_script()
for s in get_stack():
if s.source == me.resource_path:
return s
return null
func __assert_pass():
test_passes += 1
func __assert_fail():
test_failures += 1
var s = __get_stack_frame()
if s != null:
print_rich ("[color=red] == FAILURE: In function %s() from '%s' on line %s[/color]" % [s.function, s.source, s.line])
else:
print_rich ("[color=red] == FAILURE (run with --debug to get more information!) ==[/color]")
func assert_equal(actual, expected):
if actual == expected:
__assert_pass()
else:
__assert_fail()
print (" |-> Expected '%s' but got '%s'" % [expected, actual])
func assert_true(v):
assert_equal(v, true)
func assert_false(v):
assert_equal(v, false)
func assert_not_equal(actual, expected):
if actual != expected:
__assert_pass()
else:
__assert_fail()
print (" |-> Expected '%s' NOT to equal '%s'" % [expected, actual])
func exit_with_status() -> void:
var success: bool = (test_failures == 0)
print ("")
print_rich ("[color=%s] ==== TESTS FINISHED ==== [/color]" % ("green" if success else "red"))
print ("")
print_rich (" PASSES: [color=green]%s[/color]" % test_passes)
print_rich (" FAILURES: [color=red]%s[/color]" % test_failures)
print ("")
if success:
print_rich("[color=green] ******** PASSED ******** [/color]")
else:
print_rich("[color=red] ******** FAILED ********[/color]")
print("")
get_tree().quit(0 if success else 1)

View File

@@ -1,24 +0,0 @@
#!/bin/bash
GODOT=${GODOT:-godot}
END_STRING="==== TESTS FINISHED ===="
FAILURE_STRING="******** FAILED ********"
OUTPUT=$($GODOT --path project --debug --headless --quit)
ERRCODE=$?
echo "$OUTPUT"
echo
if ! echo "$OUTPUT" | grep -e "$END_STRING" >/dev/null; then
echo "ERROR: Tests failed to complete"
exit 1
fi
if echo "$OUTPUT" | grep -e "$FAILURE_STRING" >/dev/null; then
exit 1
fi
# Success!
exit 0

View File

@@ -9,32 +9,31 @@
#include <godot_cpp/classes/global_constants.hpp>
#include <godot_cpp/classes/label.hpp>
#include <godot_cpp/classes/multiplayer_api.hpp>
#include <godot_cpp/classes/multiplayer_peer.hpp>
#include <godot_cpp/variant/utility_functions.hpp>
using namespace godot;
void ExampleRef::set_id(int p_id) {
id = p_id;
}
int ExampleRef::instance_count = 0;
int ExampleRef::last_id = 0;
int ExampleRef::get_id() const {
return id;
}
void ExampleRef::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_id", "id"), &ExampleRef::set_id);
ClassDB::bind_method(D_METHOD("get_id"), &ExampleRef::get_id);
ADD_PROPERTY(PropertyInfo(Variant::INT, "id"), "set_id", "get_id");
}
ExampleRef::ExampleRef() {
id = 0;
id = ++last_id;
instance_count++;
UtilityFunctions::print("ExampleRef ", itos(id), " created, current instance count: ", itos(instance_count));
}
ExampleRef::~ExampleRef() {
instance_count--;
UtilityFunctions::print("ExampleRef ", itos(id), " destroyed, current instance count: ", itos(instance_count));
}
int Example::test_static(int p_a, int p_b) {
@@ -42,7 +41,7 @@ int Example::test_static(int p_a, int p_b) {
}
void Example::test_static2() {
//UtilityFunctions::print(" void static");
UtilityFunctions::print(" void static");
}
int Example::def_args(int p_a, int p_b) {
@@ -50,15 +49,7 @@ int Example::def_args(int p_a, int p_b) {
}
void Example::_notification(int p_what) {
if (p_what == NOTIFICATION_READY) {
Dictionary opts;
opts["rpc_mode"] = MultiplayerAPI::RPC_MODE_AUTHORITY;
opts["transfer_mode"] = MultiplayerPeer::TRANSFER_MODE_RELIABLE;
opts["call_local"] = true;
opts["channel"] = 0;
rpc_config("test_rpc", opts);
}
//UtilityFunctions::print("Notification: ", String::num(p_what));
UtilityFunctions::print("Notification: ", String::num(p_what));
}
bool Example::_set(const StringName &p_name, const Variant &p_value) {
@@ -121,10 +112,6 @@ void Example::_bind_methods() {
// Methods.
ClassDB::bind_method(D_METHOD("simple_func"), &Example::simple_func);
ClassDB::bind_method(D_METHOD("simple_const_func"), &Example::simple_const_func);
ClassDB::bind_method(D_METHOD("custom_ref_func", "ref"), &Example::custom_ref_func);
ClassDB::bind_method(D_METHOD("custom_const_ref_func", "ref"), &Example::custom_const_ref_func);
ClassDB::bind_method(D_METHOD("image_ref_func", "image"), &Example::image_ref_func);
ClassDB::bind_method(D_METHOD("image_const_ref_func", "image"), &Example::image_const_ref_func);
ClassDB::bind_method(D_METHOD("return_something"), &Example::return_something);
ClassDB::bind_method(D_METHOD("return_something_const"), &Example::return_something_const);
ClassDB::bind_method(D_METHOD("return_empty_ref"), &Example::return_empty_ref);
@@ -137,27 +124,10 @@ void Example::_bind_methods() {
ClassDB::bind_method(D_METHOD("test_dictionary"), &Example::test_dictionary);
ClassDB::bind_method(D_METHOD("test_node_argument"), &Example::test_node_argument);
ClassDB::bind_method(D_METHOD("test_string_ops"), &Example::test_string_ops);
ClassDB::bind_method(D_METHOD("test_str_utility"), &Example::test_str_utility);
ClassDB::bind_method(D_METHOD("test_string_is_fourty_two"), &Example::test_string_is_fourty_two);
ClassDB::bind_method(D_METHOD("test_vector_ops"), &Example::test_vector_ops);
ClassDB::bind_method(D_METHOD("test_object_cast_to_node", "object"), &Example::test_object_cast_to_node);
ClassDB::bind_method(D_METHOD("test_object_cast_to_control", "object"), &Example::test_object_cast_to_control);
ClassDB::bind_method(D_METHOD("test_object_cast_to_example", "object"), &Example::test_object_cast_to_example);
ClassDB::bind_method(D_METHOD("test_variant_vector2i_conversion", "variant"), &Example::test_variant_vector2i_conversion);
ClassDB::bind_method(D_METHOD("test_variant_int_conversion", "variant"), &Example::test_variant_int_conversion);
ClassDB::bind_method(D_METHOD("test_variant_float_conversion", "variant"), &Example::test_variant_float_conversion);
ClassDB::bind_method(D_METHOD("test_add_child", "node"), &Example::test_add_child);
ClassDB::bind_method(D_METHOD("test_set_tileset", "tilemap", "tileset"), &Example::test_set_tileset);
ClassDB::bind_method(D_METHOD("test_bitfield", "flags"), &Example::test_bitfield);
ClassDB::bind_method(D_METHOD("test_rpc", "value"), &Example::test_rpc);
ClassDB::bind_method(D_METHOD("test_send_rpc", "value"), &Example::test_send_rpc);
ClassDB::bind_method(D_METHOD("return_last_rpc_arg"), &Example::return_last_rpc_arg);
ClassDB::bind_method(D_METHOD("def_args", "a", "b"), &Example::def_args, DEFVAL(100), DEFVAL(200));
ClassDB::bind_static_method("Example", D_METHOD("test_static", "a", "b"), &Example::test_static);
@@ -209,43 +179,29 @@ void Example::_bind_methods() {
}
Example::Example() {
//UtilityFunctions::print("Constructor.");
UtilityFunctions::print("Constructor.");
}
Example::~Example() {
//UtilityFunctions::print("Destructor.");
UtilityFunctions::print("Destructor.");
}
// Methods.
void Example::simple_func() {
emit_custom_signal("simple_func", 3);
UtilityFunctions::print(" Simple func called.");
}
void Example::simple_const_func() const {
((Example *)this)->emit_custom_signal("simple_const_func", 4);
}
int Example::custom_ref_func(Ref<ExampleRef> p_ref) {
return p_ref.is_valid() ? p_ref->get_id() : -1;
}
int Example::custom_const_ref_func(const Ref<ExampleRef> &p_ref) {
return p_ref.is_valid() ? p_ref->get_id() : -1;
}
String Example::image_ref_func(Ref<Image> p_image) {
return p_image.is_valid() ? String("valid") : String("invalid");
}
String Example::image_const_ref_func(const Ref<Image> &p_image) {
return p_image.is_valid() ? String("valid") : String("invalid");
UtilityFunctions::print(" Simple const func called.");
}
String Example::return_something(const String &base) {
return base + String("42");
UtilityFunctions::print(" Return something called.");
return base;
}
Viewport *Example::return_something_const() const {
UtilityFunctions::print(" Return something const called.");
if (is_inside_tree()) {
Viewport *result = get_viewport();
return result;
@@ -265,23 +221,32 @@ ExampleRef *Example::return_extended_ref() const {
return memnew(ExampleRef());
}
Example *Example::test_node_argument(Example *p_node) const {
UtilityFunctions::print(" Test node argument called with ", p_node ? String::num(p_node->get_instance_id()) : "null");
return p_node;
}
Ref<ExampleRef> Example::extended_ref_checks(Ref<ExampleRef> p_ref) const {
// This is therefor the prefered way of instancing and returning a refcounted object:
Ref<ExampleRef> ref;
ref.instantiate();
UtilityFunctions::print(" Example ref checks called with value: ", p_ref->get_instance_id(), ", returning value: ", ref->get_instance_id());
return ref;
}
Variant Example::varargs_func(const Variant **args, GDExtensionInt arg_count, GDExtensionCallError &error) {
UtilityFunctions::print(" Varargs (Variant return) called with ", String::num((double)arg_count), " arguments");
return arg_count;
}
int Example::varargs_func_nv(const Variant **args, GDExtensionInt arg_count, GDExtensionCallError &error) {
return 42 + arg_count;
UtilityFunctions::print(" Varargs (int return) called with ", String::num((double)arg_count), " arguments");
return 42;
}
void Example::varargs_func_void(const Variant **args, GDExtensionInt arg_count, GDExtensionCallError &error) {
emit_custom_signal("varargs_func_void", arg_count + 1);
UtilityFunctions::print(" Varargs (no return) called with ", String::num((double)arg_count), " arguments");
}
void Example::emit_custom_signal(const String &name, int value) {
@@ -307,14 +272,6 @@ String Example::test_string_ops() const {
return s;
}
String Example::test_str_utility() const {
return UtilityFunctions::str("Hello, ", "World", "! The answer is ", 42);
}
bool Example::test_string_is_fourty_two(const String &p_string) const {
return strcmp(p_string.utf8().ptr(), "fourty two") == 0;
}
int Example::test_vector_ops() const {
PackedInt32Array arr;
arr.push_back(10);
@@ -328,12 +285,10 @@ int Example::test_vector_ops() const {
return ret;
}
int Example::test_tarray_arg(const TypedArray<int64_t> &p_array) {
int sum = 0;
void Example::test_tarray_arg(const TypedArray<int64_t> &p_array) {
for (int i = 0; i < p_array.size(); i++) {
sum += (int)p_array[i];
UtilityFunctions::print(p_array[i]);
}
return sum;
}
TypedArray<Vector2> Example::test_tarray() const {
@@ -355,58 +310,11 @@ Dictionary Example::test_dictionary() const {
return dict;
}
Example *Example::test_node_argument(Example *p_node) const {
return p_node;
}
bool Example::test_object_cast_to_node(Object *p_object) const {
return Object::cast_to<Node>(p_object) != nullptr;
}
bool Example::test_object_cast_to_control(Object *p_object) const {
return Object::cast_to<Control>(p_object) != nullptr;
}
bool Example::test_object_cast_to_example(Object *p_object) const {
return Object::cast_to<Example>(p_object) != nullptr;
}
Vector2i Example::test_variant_vector2i_conversion(const Variant &p_variant) const {
return p_variant;
}
int Example::test_variant_int_conversion(const Variant &p_variant) const {
return p_variant;
}
float Example::test_variant_float_conversion(const Variant &p_variant) const {
return p_variant;
}
void Example::test_add_child(Node *p_node) {
add_child(p_node);
}
void Example::test_set_tileset(TileMap *p_tilemap, const Ref<TileSet> &p_tileset) const {
p_tilemap->set_tileset(p_tileset);
}
BitField<Example::Flags> Example::test_bitfield(BitField<Flags> flags) {
UtilityFunctions::print(" Got BitField: ", String::num_int64(flags));
return flags;
}
void Example::test_rpc(int p_value) {
last_rpc_arg = p_value;
}
void Example::test_send_rpc(int p_value) {
rpc("test_rpc", p_value);
}
int Example::return_last_rpc_arg() {
return last_rpc_arg;
}
// Properties.
void Example::set_custom_position(const Vector2 &pos) {
custom_position = pos;
@@ -427,10 +335,3 @@ bool Example::_has_point(const Vector2 &point) const {
return false;
}
void Example::_input(const Ref<InputEvent> &event) {
const InputEventKey *key_event = Object::cast_to<const InputEventKey>(*event);
if (key_event) {
emit_custom_signal(String("_input: ") + key_event->get_key_label(), key_event->get_unicode());
}
}

View File

@@ -16,10 +16,6 @@
#include <godot_cpp/classes/control.hpp>
#include <godot_cpp/classes/global_constants.hpp>
#include <godot_cpp/classes/image.hpp>
#include <godot_cpp/classes/input_event_key.hpp>
#include <godot_cpp/classes/tile_map.hpp>
#include <godot_cpp/classes/tile_set.hpp>
#include <godot_cpp/classes/viewport.hpp>
#include <godot_cpp/core/binder_common.hpp>
@@ -42,7 +38,6 @@ public:
ExampleRef();
~ExampleRef();
void set_id(int p_id);
int get_id() const;
};
@@ -72,7 +67,6 @@ private:
Vector2 custom_position;
Vector3 property_from_list;
Vector2 dprop[3];
int last_rpc_arg = 0;
public:
// Constants.
@@ -96,13 +90,8 @@ public:
// Functions.
void simple_func();
void simple_const_func() const;
int custom_ref_func(Ref<ExampleRef> p_ref);
int custom_const_ref_func(const Ref<ExampleRef> &p_ref);
String image_ref_func(Ref<Image> p_image);
String image_const_ref_func(const Ref<Image> &p_image);
String return_something(const String &base);
Viewport *return_something_const() const;
Ref<ExampleRef> return_ref() const;
Ref<ExampleRef> return_empty_ref() const;
ExampleRef *return_extended_ref() const;
Ref<ExampleRef> extended_ref_checks(Ref<ExampleRef> p_ref) const;
@@ -113,33 +102,15 @@ public:
int def_args(int p_a = 100, int p_b = 200);
Array test_array() const;
int test_tarray_arg(const TypedArray<int64_t> &p_array);
void test_tarray_arg(const TypedArray<int64_t> &p_array);
TypedArray<Vector2> test_tarray() const;
Dictionary test_dictionary() const;
Example *test_node_argument(Example *p_node) const;
String test_string_ops() const;
String test_str_utility() const;
bool test_string_is_fourty_two(const String &p_str) const;
int test_vector_ops() const;
bool test_object_cast_to_node(Object *p_object) const;
bool test_object_cast_to_control(Object *p_object) const;
bool test_object_cast_to_example(Object *p_object) const;
Vector2i test_variant_vector2i_conversion(const Variant &p_variant) const;
int test_variant_int_conversion(const Variant &p_variant) const;
float test_variant_float_conversion(const Variant &p_variant) const;
void test_add_child(Node *p_node);
void test_set_tileset(TileMap *p_tilemap, const Ref<TileSet> &p_tileset) const;
BitField<Flags> test_bitfield(BitField<Flags> flags);
// RPC
void test_rpc(int p_value);
void test_send_rpc(int p_value);
int return_last_rpc_arg();
// Property.
void set_custom_position(const Vector2 &pos);
Vector2 get_custom_position() const;
@@ -151,7 +122,6 @@ public:
// Virtual function override (no need to bind manually).
virtual bool _has_point(const Vector2 &point) const override;
virtual void _input(const Ref<InputEvent> &event) override;
};
VARIANT_ENUM_CAST(Example::Constants);

View File

@@ -36,8 +36,8 @@ void uninitialize_example_module(ModuleInitializationLevel p_level) {
extern "C" {
// Initialization.
GDExtensionBool GDE_EXPORT example_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
godot::GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization);
GDExtensionBool GDE_EXPORT example_library_init(const GDExtensionInterface *p_interface, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
godot::GDExtensionBinding::InitObject init_obj(p_interface, p_library, r_initialization);
init_obj.register_initializer(initialize_example_module);
init_obj.register_terminator(uninitialize_example_module);

View File

@@ -29,7 +29,7 @@ def generate(env):
if env["arch"] not in ("arm64", "x86_64", "arm32", "x86_32"):
print("Only arm64, x86_64, arm32, and x86_32 are supported on Android. Exiting.")
env.Exit(1)
Exit()
if sys.platform == "win32" or sys.platform == "msys":
my_spawn.configure(env)
@@ -100,5 +100,3 @@ def generate(env):
)
env.Append(CCFLAGS=arch_info["ccflags"])
env.Append(LINKFLAGS=["--target=" + arch_info["target"] + env["android_api_level"], "-march=" + arch_info["march"]])
env.Append(CPPDEFINES=["ANDROID_ENABLED", "UNIX_ENABLED"])

View File

@@ -1,310 +0,0 @@
import os, sys, platform
from SCons.Variables import EnumVariable, PathVariable, BoolVariable
from SCons.Tool import Tool
from SCons.Builder import Builder
from SCons.Errors import UserError
from binding_generator import scons_generate_bindings, scons_emit_files
def add_sources(sources, dir, extension):
for f in os.listdir(dir):
if f.endswith("." + extension):
sources.append(dir + "/" + f)
def normalize_path(val, env):
return val if os.path.isabs(val) else os.path.join(env.Dir("#").abspath, val)
def validate_file(key, val, env):
if not os.path.isfile(normalize_path(val, env)):
raise UserError("'%s' is not a file: %s" % (key, val))
def validate_dir(key, val, env):
if not os.path.isdir(normalize_path(val, env)):
raise UserError("'%s' is not a directory: %s" % (key, val))
def validate_parent_dir(key, val, env):
if not os.path.isdir(normalize_path(os.path.dirname(val), env)):
raise UserError("'%s' is not a directory: %s" % (key, os.path.dirname(val)))
platforms = ("linux", "macos", "windows", "android", "ios", "javascript")
# CPU architecture options.
architecture_array = [
"",
"universal",
"x86_32",
"x86_64",
"arm32",
"arm64",
"rv64",
"ppc32",
"ppc64",
"wasm32",
]
architecture_aliases = {
"x64": "x86_64",
"amd64": "x86_64",
"armv7": "arm32",
"armv8": "arm64",
"arm64v8": "arm64",
"aarch64": "arm64",
"rv": "rv64",
"riscv": "rv64",
"riscv64": "rv64",
"ppcle": "ppc32",
"ppc": "ppc32",
"ppc64le": "ppc64",
}
def exists(env):
return True
def options(opts, env):
# Try to detect the host platform automatically.
# This is used if no `platform` argument is passed
if sys.platform.startswith("linux"):
default_platform = "linux"
elif sys.platform == "darwin":
default_platform = "macos"
elif sys.platform == "win32" or sys.platform == "msys":
default_platform = "windows"
elif ARGUMENTS.get("platform", ""):
default_platform = ARGUMENTS.get("platform")
else:
raise ValueError("Could not detect platform automatically, please specify with platform=<platform>")
opts.Add(
EnumVariable(
key="platform",
help="Target platform",
default=env.get("platform", default_platform),
allowed_values=platforms,
ignorecase=2,
)
)
# Editor and template_debug are compatible (i.e. you can use the same binary for Godot editor builds and Godot debug templates).
# Godot release templates are only compatible with "template_release" builds.
# For this reason, we default to template_debug builds, unlike Godot which defaults to editor builds.
opts.Add(
EnumVariable(
key="target",
help="Compilation target",
default=env.get("target", "template_debug"),
allowed_values=("editor", "template_release", "template_debug"),
)
)
opts.Add(
PathVariable(
key="gdextension_dir",
help="Path to a custom directory containing GDExtension interface header and API JSON file",
default=env.get("gdextension_dir", None),
validator=validate_dir,
)
)
opts.Add(
PathVariable(
key="custom_api_file",
help="Path to a custom GDExtension API JSON file (takes precedence over `gdextension_dir`)",
default=env.get("custom_api_file", None),
validator=validate_file,
)
)
opts.Add(
BoolVariable(
key="generate_bindings",
help="Force GDExtension API bindings generation. Auto-detected by default.",
default=env.get("generate_bindings", False),
)
)
opts.Add(
BoolVariable(
key="generate_template_get_node",
help="Generate a template version of the Node class's get_node.",
default=env.get("generate_template_get_node", True),
)
)
opts.Add(
BoolVariable(
key="build_library",
help="Build the godot-cpp library.",
default=env.get("build_library", True),
)
)
opts.Add(
EnumVariable(
key="precision",
help="Set the floating-point precision level",
default=env.get("precision", "single"),
allowed_values=("single", "double"),
)
)
opts.Add(
EnumVariable(
key="arch",
help="CPU architecture",
default=env.get("arch", ""),
allowed_values=architecture_array,
map=architecture_aliases,
)
)
# compiledb
opts.Add(
BoolVariable(
key="compiledb",
help="Generate compilation DB (`compile_commands.json`) for external tools",
default=env.get("compiledb", False),
)
)
opts.Add(
PathVariable(
key="compiledb_file",
help="Path to a custom `compile_commands.json` file",
default=env.get("compiledb_file", "compile_commands.json"),
validator=validate_parent_dir,
)
)
# Add platform options
for pl in platforms:
tool = Tool(pl, toolpath=["tools"])
if hasattr(tool, "options"):
tool.options(opts)
# Targets flags tool (optimizations, debug symbols)
target_tool = Tool("targets", toolpath=["tools"])
target_tool.options(opts)
def generate(env):
# Default num_jobs to local cpu count if not user specified.
# SCons has a peculiarity where user-specified options won't be overridden
# by SetOption, so we can rely on this to know if we should use our default.
initial_num_jobs = env.GetOption("num_jobs")
altered_num_jobs = initial_num_jobs + 1
env.SetOption("num_jobs", altered_num_jobs)
if env.GetOption("num_jobs") == altered_num_jobs:
cpu_count = os.cpu_count()
if cpu_count is None:
print("Couldn't auto-detect CPU count to configure build parallelism. Specify it with the -j argument.")
else:
safer_cpu_count = cpu_count if cpu_count <= 4 else cpu_count - 1
print(
"Auto-detected %d CPU cores available for build parallelism. Using %d cores by default. You can override it with the -j argument."
% (cpu_count, safer_cpu_count)
)
env.SetOption("num_jobs", safer_cpu_count)
# Process CPU architecture argument.
if env["arch"] == "":
# No architecture specified. Default to arm64 if building for Android,
# universal if building for macOS or iOS, wasm32 if building for web,
# otherwise default to the host architecture.
if env["platform"] in ["macos", "ios"]:
env["arch"] = "universal"
elif env["platform"] == "android":
env["arch"] = "arm64"
elif env["platform"] == "javascript":
env["arch"] = "wasm32"
else:
host_machine = platform.machine().lower()
if host_machine in architecture_array:
env["arch"] = host_machine
elif host_machine in architecture_aliases.keys():
env["arch"] = architecture_aliases[host_machine]
elif "86" in host_machine:
# Catches x86, i386, i486, i586, i686, etc.
env["arch"] = "x86_32"
else:
print("Unsupported CPU architecture: " + host_machine)
env.Exit(1)
print("Building for architecture " + env["arch"] + " on platform " + env["platform"])
tool = Tool(env["platform"], toolpath=["tools"])
if tool is None or not tool.exists(env):
raise ValueError("Required toolchain not found for platform " + env["platform"])
tool.generate(env)
target_tool = Tool("targets", toolpath=["tools"])
target_tool.generate(env)
# Require C++17
if env.get("is_msvc", False):
env.Append(CXXFLAGS=["/std:c++17"])
else:
env.Append(CXXFLAGS=["-std=c++17"])
if env["precision"] == "double":
env.Append(CPPDEFINES=["REAL_T_IS_DOUBLE"])
# Suffix
suffix = ".{}.{}".format(env["platform"], env["target"])
if env.dev_build:
suffix += ".dev"
if env["precision"] == "double":
suffix += ".double"
suffix += "." + env["arch"]
if env["ios_simulator"]:
suffix += ".simulator"
env["suffix"] = suffix # Exposed when included from another project
env["OBJSUFFIX"] = suffix + env["OBJSUFFIX"]
# compile_commands.json
if env.get("compiledb", False):
env.Tool("compilation_db")
env.Alias("compiledb", env.CompilationDatabase(normalize_path(env["compiledb_file"], env)))
# Builders
env.Append(BUILDERS={"GodotCPPBindings": Builder(action=scons_generate_bindings, emitter=scons_emit_files)})
env.AddMethod(_godot_cpp, "GodotCPP")
def _godot_cpp(env):
api_file = normalize_path(env.get("custom_api_file", env.File("gdextension/extension_api.json").abspath), env)
extension_dir = normalize_path(env.get("gdextension_dir", env.Dir("gdextension").abspath), env)
bindings = env.GodotCPPBindings(
env.Dir("."),
[
api_file,
os.path.join(extension_dir, "gdextension_interface.h"),
"binding_generator.py",
],
)
# Forces bindings regeneration.
if env["generate_bindings"]:
env.AlwaysBuild(bindings)
env.NoCache(bindings)
# Sources to compile
sources = []
add_sources(sources, "src", "cpp")
add_sources(sources, "src/classes", "cpp")
add_sources(sources, "src/core", "cpp")
add_sources(sources, "src/variant", "cpp")
sources.extend([f for f in bindings if str(f).endswith(".cpp")])
# Includes
env.AppendUnique(CPPPATH=[env.Dir(d) for d in [extension_dir, "include", "gen/include"]])
library = None
library_name = "libgodot-cpp" + env["suffix"] + env["LIBSUFFIX"]
if env["build_library"]:
library = env.StaticLibrary(target=env.File("bin/%s" % library_name), source=sources)
env.Default(library)
env.AppendUnique(LIBS=[env.File("bin/%s" % library_name)])
return library

View File

@@ -1,6 +1,7 @@
import os
import sys
import subprocess
import ios_osxcross
from SCons.Variables import *
if sys.version_info < (3,):
@@ -15,10 +16,6 @@ else:
return codecs.utf_8_decode(x)[0]
def has_ios_osxcross():
return "OSXCROSS_IOS" in os.environ
def options(opts):
opts.Add(BoolVariable("ios_simulator", "Target iOS Simulator", False))
opts.Add("ios_min_version", "Target minimum iphoneos/iphonesimulator version", "10.0")
@@ -28,18 +25,17 @@ def options(opts):
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain",
)
opts.Add("IOS_SDK_PATH", "Path to the iOS SDK", "")
if has_ios_osxcross():
opts.Add("ios_triple", "Triple for ios toolchain", "")
ios_osxcross.options(opts)
def exists(env):
return sys.platform == "darwin" or has_ios_osxcross()
return sys.platform == "darwin" or ios_osxcross.exists(env)
def generate(env):
if env["arch"] not in ("universal", "arm64", "x86_64"):
raise ValueError("Only universal, arm64, and x86_64 are supported on iOS. Exiting.")
print("Only universal, arm64, and x86_64 are supported on iOS. Exiting.")
Exit()
if env["ios_simulator"]:
sdk_name = "iphonesimulator"
@@ -68,26 +64,7 @@ def generate(env):
env["ENV"]["PATH"] = env["IOS_TOOLCHAIN_PATH"] + "/Developer/usr/bin/:" + env["ENV"]["PATH"]
else:
# OSXCross
compiler_path = "$IOS_TOOLCHAIN_PATH/usr/bin/${ios_triple}"
env["CC"] = compiler_path + "clang"
env["CXX"] = compiler_path + "clang++"
env["AR"] = compiler_path + "ar"
env["RANLIB"] = compiler_path + "ranlib"
env["SHLIBSUFFIX"] = ".dylib"
env.Prepend(
CPPPATH=[
"$IOS_SDK_PATH/usr/include",
"$IOS_SDK_PATH/System/Library/Frameworks/AudioUnit.framework/Headers",
]
)
env.Append(CCFLAGS=["-stdlib=libc++"])
binpath = os.path.join(env["IOS_TOOLCHAIN_PATH"], "usr", "bin")
if binpath not in env["ENV"]["PATH"]:
env.PrependENVPath("PATH", binpath)
ios_osxcross.generate(env)
if env["arch"] == "universal":
if env["ios_simulator"]:
@@ -102,5 +79,3 @@ def generate(env):
env.Append(CCFLAGS=["-isysroot", env["IOS_SDK_PATH"]])
env.Append(LINKFLAGS=["-isysroot", env["IOS_SDK_PATH"], "-F" + env["IOS_SDK_PATH"]])
env.Append(CPPDEFINES=["IOS_ENABLED", "UNIX_ENABLED"])

26
tools/ios_osxcross.py Normal file
View File

@@ -0,0 +1,26 @@
import os
def options(opts):
opts.Add("ios_triple", "Triple for ios toolchain", "")
def exists(env):
return "OSXCROSS_IOS" in os.environ
def generate(env):
compiler_path = "$IOS_TOOLCHAIN_PATH/usr/bin/${ios_triple}"
env["CC"] = compiler_path + "clang"
env["CXX"] = compiler_path + "clang++"
env["AR"] = compiler_path + "ar"
env["RANLIB"] = compiler_path + "ranlib"
env["SHLIBSUFFIX"] = ".dylib"
env.Prepend(
CPPPATH=[
"$IOS_SDK_PATH/usr/include",
"$IOS_SDK_PATH/System/Library/Frameworks/AudioUnit.framework/Headers",
]
)
env.Append(CCFLAGS=["-stdlib=libc++"])

View File

@@ -8,7 +8,7 @@ def exists(env):
def generate(env):
if env["arch"] not in ("wasm32"):
print("Only wasm32 supported on web. Exiting.")
env.Exit(1)
Exit()
if "EM_CONFIG" in os.environ:
env["ENV"] = os.environ
@@ -43,5 +43,3 @@ def generate(env):
env.Append(CCFLAGS=["-O0", "-g"])
elif env["target"] == "release":
env.Append(CCFLAGS=["-O3"])
env.Append(CPPDEFINES=["WEB_ENABLED", "UNIX_ENABLED"])

View File

@@ -32,5 +32,3 @@ def generate(env):
elif env["arch"] == "rv64":
env.Append(CCFLAGS=["-march=rv64gc"])
env.Append(LINKFLAGS=["-march=rv64gc"])
env.Append(CPPDEFINES=["LINUX_ENABLED", "UNIX_ENABLED"])

View File

@@ -1,51 +1,31 @@
import os
import sys
def has_osxcross():
return "OSXCROSS_ROOT" in os.environ
import macos_osxcross
def options(opts):
opts.Add("macos_deployment_target", "macOS deployment target", "default")
opts.Add("macos_sdk_path", "macOS SDK path", "")
if has_osxcross():
opts.Add("osxcross_sdk", "OSXCross SDK version", "darwin16")
macos_osxcross.options(opts)
def exists(env):
return sys.platform == "darwin" or has_osxcross()
return sys.platform == "darwin" or macos_osxcross.exists(env)
def generate(env):
if env["arch"] not in ("universal", "arm64", "x86_64"):
print("Only universal, arm64, and x86_64 are supported on macOS. Exiting.")
env.Exit(1)
Exit()
if sys.platform == "darwin":
# Use clang on macOS by default
env["CXX"] = "clang++"
env["CC"] = "clang"
else:
# OSXCross
root = os.environ.get("OSXCROSS_ROOT", "")
if env["arch"] == "arm64":
basecmd = root + "/target/bin/arm64-apple-" + env["osxcross_sdk"] + "-"
else:
basecmd = root + "/target/bin/x86_64-apple-" + env["osxcross_sdk"] + "-"
# Use osxcross
macos_osxcross.generate(env)
env["CC"] = basecmd + "clang"
env["CXX"] = basecmd + "clang++"
env["AR"] = basecmd + "ar"
env["RANLIB"] = basecmd + "ranlib"
env["AS"] = basecmd + "as"
binpath = os.path.join(root, "target", "bin")
if binpath not in env["ENV"]["PATH"]:
# Add OSXCROSS bin folder to PATH (required for linking).
env.PrependENVPath("PATH", binpath)
# Common flags
if env["arch"] == "universal":
env.Append(LINKFLAGS=["-arch", "x86_64", "-arch", "arm64"])
env.Append(CCFLAGS=["-arch", "x86_64", "-arch", "arm64"])
@@ -68,5 +48,3 @@ def generate(env):
"-Wl,-undefined,dynamic_lookup",
]
)
env.Append(CPPDEFINES=["MACOS_ENABLED", "UNIX_ENABLED"])

28
tools/macos_osxcross.py Normal file
View File

@@ -0,0 +1,28 @@
import os
def options(opts):
opts.Add("osxcross_sdk", "OSXCross SDK version", "darwin16")
def exists(env):
return "OSXCROSS_ROOT" in os.environ
def generate(env):
root = os.environ.get("OSXCROSS_ROOT", "")
if env["arch"] == "arm64":
basecmd = root + "/target/bin/arm64-apple-" + env["osxcross_sdk"] + "-"
else:
basecmd = root + "/target/bin/x86_64-apple-" + env["osxcross_sdk"] + "-"
env["CC"] = basecmd + "clang"
env["CXX"] = basecmd + "clang++"
env["AR"] = basecmd + "ar"
env["RANLIB"] = basecmd + "ranlib"
env["AS"] = basecmd + "as"
binpath = os.path.join(root, "target", "bin")
if binpath not in env["ENV"]["PATH"]:
# Add OSXCROSS bin folder to PATH (required for linking).
env["ENV"]["PATH"] = "%s:%s" % (binpath, env["ENV"]["PATH"])

View File

@@ -1,14 +1,10 @@
import os
import subprocess
import sys
from SCons.Script import ARGUMENTS
from SCons.Variables import *
from SCons.Variables.BoolVariable import _text2bool
# Helper methods
def get_cmdline_bool(option, default):
"""We use `ARGUMENTS.get()` to check if options were manually overridden on the command line,
and SCons' _text2bool helper to convert them to booleans, otherwise they're handled as strings.
@@ -20,24 +16,6 @@ def get_cmdline_bool(option, default):
return default
def using_clang(env):
return "clang" in os.path.basename(env["CC"])
def is_vanilla_clang(env):
if not using_clang(env):
return False
try:
version = subprocess.check_output([env.subst(env["CXX"]), "--version"]).strip().decode("utf-8")
except (subprocess.CalledProcessError, OSError):
print("Couldn't parse CXX environment variable to infer compiler version.")
return False
return not version.startswith("Apple")
# Main tool definition
def options(opts):
opts.Add(
EnumVariable(
@@ -56,21 +34,19 @@ def exists(env):
def generate(env):
# Configuration of build targets:
# - Editor or template
# - Debug features (DEBUG_ENABLED code)
# - Dev only code (DEV_ENABLED code)
# - Optimization level
# - Debug symbols for crash traces / debuggers
# Keep this configuration in sync with SConstruct in upstream Godot.
env.editor_build = env["target"] == "editor"
env.dev_build = env["dev_build"]
env.debug_features = env["target"] in ["editor", "template_debug"]
env.editor_build = env["target"] == "editor"
if env.editor_build:
env.AppendUnique(CPPDEFINES=["TOOLS_ENABLED"])
if env.debug_features:
env.AppendUnique(CPPDEFINES=["DEBUG_ENABLED", "DEBUG_METHODS_ENABLED"])
if env.dev_build:
opt_level = "none"
env.AppendUnique(CPPDEFINES=["DEV_ENABLED"])
elif env.debug_features:
opt_level = "speed_trace"
else: # Release
@@ -79,57 +55,29 @@ def generate(env):
env["optimize"] = ARGUMENTS.get("optimize", opt_level)
env["debug_symbols"] = get_cmdline_bool("debug_symbols", env.dev_build)
if env.editor_build:
env.Append(CPPDEFINES=["TOOLS_ENABLED"])
if env.debug_features:
# DEBUG_ENABLED enables debugging *features* and debug-only code, which is intended
# to give *users* extra debugging information for their game development.
env.Append(CPPDEFINES=["DEBUG_ENABLED"])
# In upstream Godot this is added in typedefs.h when DEBUG_ENABLED is set.
env.Append(CPPDEFINES=["DEBUG_METHODS_ENABLED"])
if env.dev_build:
# DEV_ENABLED enables *engine developer* code which should only be compiled for those
# working on the engine itself.
env.Append(CPPDEFINES=["DEV_ENABLED"])
else:
# Disable assert() for production targets (only used in thirdparty code).
env.Append(CPPDEFINES=["NDEBUG"])
# Set optimize and debug_symbols flags.
# "custom" means do nothing and let users set their own optimization flags.
if env.get("is_msvc", False):
if env["debug_symbols"]:
env.Append(CCFLAGS=["/Zi", "/FS"])
env.Append(LINKFLAGS=["/DEBUG:FULL"])
if env["optimize"] == "speed":
if env["optimize"] == "speed" or env["optimize"] == "speed_trace":
env.Append(CCFLAGS=["/O2"])
env.Append(LINKFLAGS=["/OPT:REF"])
elif env["optimize"] == "speed_trace":
env.Append(CCFLAGS=["/O2"])
env.Append(LINKFLAGS=["/OPT:REF", "/OPT:NOICF"])
elif env["optimize"] == "size":
env.Append(CCFLAGS=["/O1"])
env.Append(LINKFLAGS=["/OPT:REF"])
elif env["optimize"] == "debug" or env["optimize"] == "none":
env.Append(CCFLAGS=["/Od"])
if env["optimize"] == "debug" or env["optimize"] == "none":
env.Append(CCFLAGS=["/MDd", "/Od"])
else:
env.Append(CCFLAGS=["/MD"])
else:
if env["debug_symbols"]:
# Adding dwarf-4 explicitly makes stacktraces work with clang builds,
# otherwise addr2line doesn't understand them.
env.Append(CCFLAGS=["-gdwarf-4"])
if env.dev_build:
env.Append(CCFLAGS=["-g3"])
else:
env.Append(CCFLAGS=["-g2"])
else:
if using_clang(env) and not is_vanilla_clang(env):
# Apple Clang, its linker doesn't like -s.
env.Append(LINKFLAGS=["-Wl,-S", "-Wl,-x", "-Wl,-dead_strip"])
else:
env.Append(LINKFLAGS=["-s"])
if env["optimize"] == "speed":
env.Append(CCFLAGS=["-O3"])

View File

@@ -9,7 +9,6 @@ from SCons.Variables import *
def options(opts):
opts.Add(BoolVariable("use_mingw", "Use the MinGW compiler instead of MSVC - only effective on Windows", False))
opts.Add(BoolVariable("use_clang_cl", "Use the clang driver instead of MSVC - only effective on Windows", False))
opts.Add(BoolVariable("use_static_cpp", "Link MinGW/MSVC C++ runtime libraries statically", True))
def exists(env):
@@ -31,18 +30,13 @@ def generate(env):
env.Tool("mslink")
env.Append(CPPDEFINES=["TYPED_METHOD_BIND", "NOMINMAX"])
env.Append(CCFLAGS=["/EHsc", "/utf-8"])
env.Append(CCFLAGS=["/EHsc"])
env.Append(LINKFLAGS=["/WX"])
if env["use_clang_cl"]:
env["CC"] = "clang-cl"
env["CXX"] = "clang-cl"
if env["use_static_cpp"]:
env.Append(CCFLAGS=["/MT"])
else:
env.Append(CCFLAGS=["/MD"])
elif sys.platform == "win32" or sys.platform == "msys":
env["use_mingw"] = True
mingw.generate(env)
@@ -51,18 +45,6 @@ def generate(env):
env["SHLIBPREFIX"] = ""
# Want dll suffix
env["SHLIBSUFFIX"] = ".dll"
env.Append(CCFLAGS=["-Wwrite-strings"])
env.Append(LINKFLAGS=["-Wl,--no-undefined"])
if env["use_static_cpp"]:
env.Append(
LINKFLAGS=[
"-static",
"-static-libgcc",
"-static-libstdc++",
]
)
# Long line hack. Use custom spawn, quick AR append (to avoid files with the same names to override each other).
my_spawn.configure(env)
@@ -78,15 +60,13 @@ def generate(env):
# Want dll suffix
env["SHLIBSUFFIX"] = ".dll"
env.Append(CCFLAGS=["-Wwrite-strings"])
env.Append(LINKFLAGS=["-Wl,--no-undefined"])
if env["use_static_cpp"]:
env.Append(
LINKFLAGS=[
"-static",
"-static-libgcc",
"-static-libstdc++",
]
)
env.Append(CPPDEFINES=["WINDOWS_ENABLED"])
# These options are for a release build even using target=debug
env.Append(CCFLAGS=["-O3", "-Wwrite-strings"])
env.Append(
LINKFLAGS=[
"--static",
"-Wl,--no-undefined",
"-static-libgcc",
"-static-libstdc++",
]
)